diff options
5 files changed, 75 insertions, 7 deletions
diff --git a/src/org/apache/http/impl/AbstractHttpClientConnection.java b/src/org/apache/http/impl/AbstractHttpClientConnection.java index ebfaabb..ac3f4d1 100644 --- a/src/org/apache/http/impl/AbstractHttpClientConnection.java +++ b/src/org/apache/http/impl/AbstractHttpClientConnection.java @@ -47,6 +47,7 @@ import org.apache.http.impl.entity.LaxContentLengthStrategy; import org.apache.http.impl.entity.StrictContentLengthStrategy; import org.apache.http.impl.io.HttpRequestWriter; import org.apache.http.impl.io.HttpResponseParser; +import org.apache.http.impl.io.SocketInputBuffer; import org.apache.http.io.HttpMessageParser; import org.apache.http.io.HttpMessageWriter; import org.apache.http.io.SessionInputBuffer; @@ -198,6 +199,12 @@ public abstract class AbstractHttpClientConnection implements HttpClientConnecti return true; } try { + // BEGIN android-added + // don't reuse connections when the socket input stream is exhausted + if (inbuffer instanceof SocketInputBuffer) { + return ((SocketInputBuffer) inbuffer).isStale(); + } + // END android-added this.inbuffer.isDataAvailable(1); return false; } catch (IOException ex) { diff --git a/src/org/apache/http/impl/client/DefaultHttpClient.java b/src/org/apache/http/impl/client/DefaultHttpClient.java index 7dcb2a2..7b3a3fa 100644 --- a/src/org/apache/http/impl/client/DefaultHttpClient.java +++ b/src/org/apache/http/impl/client/DefaultHttpClient.java @@ -61,7 +61,7 @@ import org.apache.http.cookie.CookieSpecRegistry; import org.apache.http.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.auth.BasicSchemeFactory; import org.apache.http.impl.auth.DigestSchemeFactory; -import org.apache.http.impl.conn.DefaultHttpRoutePlanner; +import org.apache.http.impl.conn.ProxySelectorRoutePlanner; import org.apache.http.impl.conn.SingleClientConnManager; import org.apache.http.impl.cookie.BestMatchSpecFactory; import org.apache.http.impl.cookie.BrowserCompatSpecFactory; @@ -326,8 +326,10 @@ public class DefaultHttpClient extends AbstractHttpClient { @Override protected HttpRoutePlanner createHttpRoutePlanner() { - return new DefaultHttpRoutePlanner - (getConnectionManager().getSchemeRegistry()); + // BEGIN android-changed + // Use the proxy specified by system properties + return new ProxySelectorRoutePlanner(getConnectionManager().getSchemeRegistry(), null); + // END android-changed } diff --git a/src/org/apache/http/impl/client/DefaultRequestDirector.java b/src/org/apache/http/impl/client/DefaultRequestDirector.java index a95c522..bfdddd6 100644 --- a/src/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/src/org/apache/http/impl/client/DefaultRequestDirector.java @@ -67,6 +67,7 @@ import org.apache.http.client.RedirectHandler; import org.apache.http.client.UserTokenHandler; import org.apache.http.client.methods.AbortableHttpRequest; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.HttpClientParams; import org.apache.http.client.protocol.ClientContext; @@ -357,7 +358,13 @@ public class DefaultRequestDirector implements RequestDirector { // Reopen connection if needed if (!managedConn.isOpen()) { managedConn.open(route, context, params); - } + } + // BEGIN android-added + else { + // b/3241899 set the per request timeout parameter on reused connections + managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params)); + } + // END android-added try { establishRoute(route, context); @@ -569,8 +576,21 @@ public class DefaultRequestDirector implements RequestDirector { ClientPNames.DEFAULT_HOST); } if (target == null) { - throw new IllegalStateException - ("Target host must not be null, or set in parameters."); + // BEGIN android-changed + // If the URI was malformed, make it obvious where there's no host component + String scheme = null; + String host = null; + String path = null; + URI uri; + if (request instanceof HttpUriRequest + && (uri = ((HttpUriRequest) request).getURI()) != null) { + scheme = uri.getScheme(); + host = uri.getHost(); + path = uri.getPath(); + } + throw new IllegalStateException( "Target host must not be null, or set in parameters." + + " scheme=" + scheme + ", host=" + host + ", path=" + path); + // END android-changed } return this.routePlanner.determineRoute(target, request, context); diff --git a/src/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java b/src/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java index 136caf4..daa7227 100644 --- a/src/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java +++ b/src/org/apache/http/impl/conn/ProxySelectorRoutePlanner.java @@ -51,6 +51,7 @@ import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.params.ConnRouteParams; +import org.apache.http.conn.params.ConnRoutePNames; /** @@ -140,7 +141,18 @@ public class ProxySelectorRoutePlanner implements HttpRoutePlanner { final InetAddress local = ConnRouteParams.getLocalAddress(request.getParams()); - final HttpHost proxy = determineProxy(target, request, context); + + // BEGIN android-changed + // If the client or request explicitly specifies a proxy (or no + // proxy), prefer that over the ProxySelector's VM-wide default. + HttpHost proxy = (HttpHost) request.getParams().getParameter(ConnRoutePNames.DEFAULT_PROXY); + if (proxy == null) { + proxy = determineProxy(target, request, context); + } else if (ConnRouteParams.NO_HOST.equals(proxy)) { + // value is explicitly unset + proxy = null; + } + // END android-changed final Scheme schm = this.schemeRegistry.getScheme(target.getSchemeName()); diff --git a/src/org/apache/http/impl/io/SocketInputBuffer.java b/src/org/apache/http/impl/io/SocketInputBuffer.java index 4ca9e5f..7d4323b 100644 --- a/src/org/apache/http/impl/io/SocketInputBuffer.java +++ b/src/org/apache/http/impl/io/SocketInputBuffer.java @@ -36,6 +36,7 @@ import java.io.InterruptedIOException; import java.net.Socket; import java.net.SocketTimeoutException; +import java.net.SocketTimeoutException; import org.apache.http.params.HttpParams; @@ -89,4 +90,30 @@ public class SocketInputBuffer extends AbstractSessionInputBuffer { return result; } + // BEGIN android-added + /** + * Returns true if the connection is probably functional. It's insufficient + * to rely on isDataAvailable() returning normally; that approach cannot + * distinguish between an exhausted stream and a stream with zero bytes + * buffered. + * + * @hide + */ + public boolean isStale() throws IOException { + if (hasBufferedData()) { + return false; + } + int oldTimeout = this.socket.getSoTimeout(); + try { + this.socket.setSoTimeout(1); + return fillBuffer() == -1; + } catch (SocketTimeoutException e) { + return false; // the connection is not stale; hooray + } catch (IOException e) { + return true; // the connection is stale, the read or soTimeout failed. + } finally { + this.socket.setSoTimeout(oldTimeout); + } + } + // END android-added } |