package com.kitty.poclient.upnp; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.util.thread.ExecutorThreadPool; import org.fourthline.cling.model.message.StreamRequestMessage; import org.fourthline.cling.model.message.StreamResponseMessage; import org.fourthline.cling.model.message.UpnpHeaders; import org.fourthline.cling.model.message.UpnpMessage; import org.fourthline.cling.model.message.UpnpRequest; import org.fourthline.cling.model.message.UpnpResponse; import org.fourthline.cling.model.message.header.ContentTypeHeader; import org.fourthline.cling.model.message.header.UpnpHeader; import org.fourthline.cling.transport.impl.jetty.StreamClientConfigurationImpl; import org.fourthline.cling.transport.spi.InitializationException; import org.fourthline.cling.transport.spi.StreamClient; import org.seamless.util.Exceptions; import org.seamless.util.MimeType; import android.util.Log; import com.kitty.poclient.common.Constant; import com.kitty.poclient.common.UpnpApp; // sendBroadcast public class MyStreamClientImpl extends MyAbstractStreamClient<StreamClientConfigurationImpl, MyStreamClientImpl.HttpContentExchange> { final private static Logger log = Logger.getLogger(StreamClient.class.getName()); private static final String TAG = MyStreamClientImpl.class.getSimpleName() + " "; final protected StreamClientConfigurationImpl configuration; final protected HttpClient client; public MyStreamClientImpl(StreamClientConfigurationImpl configuration) throws InitializationException { this.configuration = configuration; log.info("Starting Jetty HttpClient..."); client = new HttpClient(); // Jetty client needs threads for its internal expiration routines, // which we don't need but // can't disable, so let's abuse the request executor service for this client.setThreadPool(new ExecutorThreadPool(getConfiguration().getRequestExecutorService()) { @Override protected void doStop() throws Exception { // Do nothing, don't shut down the Cling ExecutorService when // Jetty stops! } }); // These are some safety settings, we should never run into these // timeouts as we // do our own expiration checking client.setTimeout((configuration.getTimeoutSeconds() + 5) * 1000); client.setConnectTimeout((configuration.getTimeoutSeconds() + 5) * 1000); client.setMaxRetries(configuration.getRequestRetryCount()); try { client.start(); } catch (Exception ex) { throw new InitializationException("Could not start Jetty HTTP client: " + ex, ex); } } @Override public StreamClientConfigurationImpl getConfiguration() { return configuration; } @Override protected HttpContentExchange createRequest(StreamRequestMessage requestMessage) { return new HttpContentExchange(getConfiguration(), client, requestMessage); } @Override protected Callable<StreamResponseMessage> createCallable(final StreamRequestMessage requestMessage, final HttpContentExchange exchange) { return new Callable<StreamResponseMessage>() { public StreamResponseMessage call() throws Exception { if (log.isLoggable(Level.FINE)) log.fine("Sending HTTP request: " + requestMessage); try { client.send(exchange); } catch (Exception e) { e.printStackTrace(); if(true){// 条件:当前请求的IP端口等于已经选定设备的IP端口 UpnpApp.sendBroadcast(Constant.ACTION_DEAL_STREAMCLIENT_TIMEOUT_OR_FAILURE); Log.e(TAG, "sendBroadcast --> ConnectionFailure"); } } int exchangeState = exchange.waitForDone(); if (exchangeState == HttpExchange.STATUS_COMPLETED) { try { return exchange.createResponse(); } catch (Throwable t) { log.log(Level.WARNING, "Error reading response: " + requestMessage, Exceptions.unwrap(t)); return null; } } else if (exchangeState == HttpExchange.STATUS_CANCELLED) { // That's ok, happens when we abort the exchange after // timeout return null; } else if (exchangeState == HttpExchange.STATUS_EXCEPTED) { // The warnings of the "excepted" condition are logged in // HttpContentExchange return null; } else { log.warning("Unhandled HTTP exchange status: " + exchangeState); return null; } } }; } @Override protected void abort(HttpContentExchange exchange) { exchange.cancel(); } @Override protected boolean logExecutionException(Throwable t) { return false; } @Override public void stop() { try { client.stop(); } catch (Exception ex) { log.info("Error stopping HTTP client: " + ex); } } static public class HttpContentExchange extends ContentExchange { final protected StreamClientConfigurationImpl configuration; final protected HttpClient client; final protected StreamRequestMessage requestMessage; protected Throwable exception; public HttpContentExchange(StreamClientConfigurationImpl configuration, HttpClient client, StreamRequestMessage requestMessage) { super(true); this.configuration = configuration; this.client = client; this.requestMessage = requestMessage; applyRequestURLMethod(); applyRequestHeaders(); applyRequestBody(); } @Override protected void onConnectionFailed(Throwable t) { log.log(Level.WARNING, "HTTP connection failed: " + requestMessage, Exceptions.unwrap(t)); } @Override protected void onException(Throwable t) { log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(t)); } public StreamClientConfigurationImpl getConfiguration() { return configuration; } public StreamRequestMessage getRequestMessage() { return requestMessage; } protected void applyRequestURLMethod() { final UpnpRequest requestOperation = getRequestMessage().getOperation(); if (log.isLoggable(Level.FINE)) log.fine("Preparing HTTP request message with method '" + requestOperation.getHttpMethodName() + "': " + getRequestMessage()); setURL(requestOperation.getURI().toString()); setMethod(requestOperation.getHttpMethodName()); } protected void applyRequestHeaders() { // Headers UpnpHeaders headers = getRequestMessage().getHeaders(); if (log.isLoggable(Level.FINE)) log.fine("Writing headers on HttpContentExchange: " + headers.size()); // TODO Always add the Host header // TODO: ? setRequestHeader(UpnpHeader.Type.HOST.getHttpName(), ); // Add the default user agent if not already set on the message if (!headers.containsKey(UpnpHeader.Type.USER_AGENT)) { setRequestHeader(UpnpHeader.Type.USER_AGENT.getHttpName(), getConfiguration().getUserAgentValue(getRequestMessage().getUdaMajorVersion(), getRequestMessage().getUdaMinorVersion())); } for (Map.Entry<String, List<String>> entry : headers.entrySet()) { for (String v : entry.getValue()) { String headerName = entry.getKey(); if (log.isLoggable(Level.FINE)) log.fine("Setting header '" + headerName + "': " + v); addRequestHeader(headerName, v); } } } protected void applyRequestBody() { // Body if (getRequestMessage().hasBody()) { if (getRequestMessage().getBodyType() == UpnpMessage.BodyType.STRING) { if (log.isLoggable(Level.FINE)) log.fine("Writing textual request body: " + getRequestMessage()); MimeType contentType = getRequestMessage().getContentTypeHeader() != null ? getRequestMessage().getContentTypeHeader().getValue() : ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8; String charset = getRequestMessage().getContentTypeCharset() != null ? getRequestMessage().getContentTypeCharset() : "UTF-8"; setRequestContentType(contentType.toString()); ByteArrayBuffer buffer; try { buffer = new ByteArrayBuffer(getRequestMessage().getBodyString(), charset); } catch (UnsupportedEncodingException ex) { throw new RuntimeException("Unsupported character encoding: " + charset, ex); } setRequestHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buffer.length())); setRequestContent(buffer); } else { if (log.isLoggable(Level.FINE)) log.fine("Writing binary request body: " + getRequestMessage()); if (getRequestMessage().getContentTypeHeader() == null) throw new RuntimeException("Missing content type header in request message: " + requestMessage); MimeType contentType = getRequestMessage().getContentTypeHeader().getValue(); setRequestContentType(contentType.toString()); ByteArrayBuffer buffer; buffer = new ByteArrayBuffer(getRequestMessage().getBodyBytes()); setRequestHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buffer.length())); setRequestContent(buffer); } } } protected StreamResponseMessage createResponse() { // Status UpnpResponse responseOperation = new UpnpResponse(getResponseStatus(), UpnpResponse.Status.getByStatusCode(getResponseStatus()).getStatusMsg()); if (log.isLoggable(Level.FINE)) log.fine("Received response: " + responseOperation); StreamResponseMessage responseMessage = new StreamResponseMessage(responseOperation); // Headers UpnpHeaders headers = new UpnpHeaders(); HttpFields responseFields = getResponseFields(); for (String name : responseFields.getFieldNamesCollection()) { for (String value : responseFields.getValuesCollection(name)) { headers.add(name, value); } } responseMessage.setHeaders(headers); // Body byte[] bytes = getResponseContentBytes(); if (bytes != null && bytes.length > 0 && responseMessage.isContentTypeMissingOrText()) { if (log.isLoggable(Level.FINE)) log.fine("Response contains textual entity body, converting then setting string on message"); try { responseMessage.setBodyCharacters(bytes); } catch (UnsupportedEncodingException ex) { throw new RuntimeException("Unsupported character encoding: " + ex, ex); } } else if (bytes != null && bytes.length > 0) { if (log.isLoggable(Level.FINE)) log.fine("Response contains binary entity body, setting bytes on message"); responseMessage.setBody(UpnpMessage.BodyType.BYTES, bytes); } else { if (log.isLoggable(Level.FINE)) log.fine("Response did not contain entity body"); } if (log.isLoggable(Level.FINE)) log.fine("Response message complete: " + responseMessage); return responseMessage; } } }