1a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath/* 2a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Copyright (C) 2007 The Android Open Source Project 3a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * 4a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 5a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * you may not use this file except in compliance with the License. 6a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * You may obtain a copy of the License at 7a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * 8a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 9a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * 10a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Unless required by applicable law or agreed to in writing, software 11a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 12a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * See the License for the specific language governing permissions and 14a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * limitations under the License. 15a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 16a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 17a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathpackage android.net.http; 18a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 19a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport android.content.Context; 20a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport android.os.SystemClock; 21a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 22a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.io.IOException; 23a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.net.UnknownHostException; 24a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.util.LinkedList; 25a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 26a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport javax.net.ssl.SSLHandshakeException; 27a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 28a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.ConnectionReuseStrategy; 29a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.HttpEntity; 30a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.HttpException; 31a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.HttpHost; 32a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.HttpVersion; 33a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.ParseException; 34a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.ProtocolVersion; 35a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.protocol.ExecutionContext; 36a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.protocol.HttpContext; 37a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.protocol.BasicHttpContext; 38a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 39a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathabstract class Connection { 40a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 41a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 42a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Allow a TCP connection 60 idle seconds before erroring out 43a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 44a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath static final int SOCKET_TIMEOUT = 60000; 45a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 46a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int SEND = 0; 47a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int READ = 1; 48a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int DRAIN = 2; 49a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int DONE = 3; 50a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final String[] states = {"SEND", "READ", "DRAIN", "DONE"}; 51a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 52a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Context mContext; 53a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 54a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** The low level connection */ 55a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath protected AndroidHttpClientConnection mHttpClientConnection = null; 56a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 57a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 58a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * The server SSL certificate associated with this connection 59a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * (null if the connection is not secure) 60a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * It would be nice to store the whole certificate chain, but 61a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * we want to keep things as light-weight as possible 62a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 63a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath protected SslCertificate mCertificate = null; 64a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 65a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 66a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * The host this connection is connected to. If using proxy, 67a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * this is set to the proxy address 68a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 69a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath HttpHost mHost; 70a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 71a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** true if the connection can be reused for sending more requests */ 72a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private boolean mCanPersist; 73a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 74a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** context required by ConnectionReuseStrategy. */ 75a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private HttpContext mHttpContext; 76a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 77a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** set when cancelled */ 78a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static int STATE_NORMAL = 0; 79a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static int STATE_CANCEL_REQUESTED = 1; 80a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private int mActive = STATE_NORMAL; 81a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 82a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** The number of times to try to re-connect (if connect fails). */ 83a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private final static int RETRY_REQUEST_LIMIT = 2; 84a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 85a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int MIN_PIPE = 2; 86a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final int MAX_PIPE = 3; 87a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 88a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 89a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Doesn't seem to exist anymore in the new HTTP client, so copied here. 90a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 91a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static final String HTTP_CONNECTION = "http.connection"; 92a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 93a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath RequestFeeder mRequestFeeder; 94a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 95a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 96a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Buffer for feeding response blocks to webkit. One block per 97a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * connection reduces memory churn. 98a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 99a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private byte[] mBuf; 100a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 101a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath protected Connection(Context context, HttpHost host, 102a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath RequestFeeder requestFeeder) { 103a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mContext = context; 104a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHost = host; 105a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mRequestFeeder = requestFeeder; 106a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 107a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mCanPersist = false; 108a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpContext = new BasicHttpContext(null); 109a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 110a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 111a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath HttpHost getHost() { 112a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mHost; 113a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 114a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 115a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 116a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * connection factory: returns an HTTP or HTTPS connection as 117a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * necessary 118a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 119a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath static Connection getConnection( 120a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Context context, HttpHost host, HttpHost proxy, 121a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath RequestFeeder requestFeeder) { 122a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 123a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (host.getSchemeName().equals("http")) { 124a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return new HttpConnection(context, host, requestFeeder); 125a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 126a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 127a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // Otherwise, default to https 128a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return new HttpsConnection(context, host, proxy, requestFeeder); 129a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 130a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 131a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 132a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @return The server SSL certificate associated with this 133a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * connection (null if the connection is not secure) 134a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 135a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* package */ SslCertificate getCertificate() { 136a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mCertificate; 137a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 138a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 139a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 140a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Close current network connection 141a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Note: this runs in non-network thread 142a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 143a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath void cancel() { 144a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mActive = STATE_CANCEL_REQUESTED; 145a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath closeConnection(); 146a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 147a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "Connection.cancel(): connection closed " + mHost); 148a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 149a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 150a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 151a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Process requests in queue 152a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * pipelines requests 153a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 154a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath void processRequests(Request firstRequest) { 155a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Request req = null; 156a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath boolean empty; 157a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath int error = EventHandler.OK; 158a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Exception exception = null; 159a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 160a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath LinkedList<Request> pipe = new LinkedList<Request>(); 161a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 162a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath int minPipe = MIN_PIPE, maxPipe = MAX_PIPE; 163a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath int state = SEND; 164a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 165a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath while (state != DONE) { 166a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 167a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath states[state] + " pipe " + pipe.size()); 168a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 169a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* If a request was cancelled, give other cancel requests 170a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath some time to go through so we don't uselessly restart 171a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath connections */ 172a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (mActive == STATE_CANCEL_REQUESTED) { 173a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath try { 174a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Thread.sleep(100); 175a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (InterruptedException x) { /* ignore */ } 176a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mActive = STATE_NORMAL; 177a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 178a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 179a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath switch (state) { 180a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case SEND: { 181a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (pipe.size() == maxPipe) { 182a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = READ; 183a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 184a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 185a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* get a request */ 186a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (firstRequest == null) { 187a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req = mRequestFeeder.getRequest(mHost); 188a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else { 189a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req = firstRequest; 190a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath firstRequest = null; 191a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 192a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (req == null) { 193a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = DRAIN; 194a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 195a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 196a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.setConnection(this); 197a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 198a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* Don't work on cancelled requests. */ 199a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (req.mCancelled) { 200a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 201a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "processRequests(): skipping cancelled request " 202a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath + req); 203a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.complete(); 204a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 205a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 206a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 207a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (mHttpClientConnection == null || 208a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath !mHttpClientConnection.isOpen()) { 209a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* If this call fails, the address is bad or 210a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath the net is down. Punt for now. 211a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 212a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath FIXME: blow out entire queue here on 213a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath connection failure if net up? */ 214a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 215a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (!openHttpConnection(req)) { 216a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = DONE; 217a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 218a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 219a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 220a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 221a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* we have a connection, let the event handler 222a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * know of any associated certificate, 223a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * potentially none. 224a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 225a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mEventHandler.certificate(mCertificate); 226a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 227a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath try { 228a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* FIXME: don't increment failure count if old 229a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath connection? There should not be a penalty for 230a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath attempting to reuse an old connection */ 231a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.sendRequest(mHttpClientConnection); 232a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (HttpException e) { 233a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 234a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR; 235a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IOException e) { 236a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 237a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_IO; 238a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IllegalStateException e) { 239a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 240a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_IO; 241a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 242a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (exception != null) { 243a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (httpFailure(req, error, exception) && 244a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath !req.mCancelled) { 245a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* retry request if not permanent failure 246a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath or cancelled */ 247a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath pipe.addLast(req); 248a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 249a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = null; 250a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = clearPipe(pipe) ? DONE : SEND; 251a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath minPipe = maxPipe = 1; 252a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 253a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 254a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 255a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath pipe.addLast(req); 256a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (!mCanPersist) state = READ; 257a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 258a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 259a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 260a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case DRAIN: 261a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case READ: { 262a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath empty = !mRequestFeeder.haveRequest(mHost); 263a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath int pipeSize = pipe.size(); 264a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (state != DRAIN && pipeSize < minPipe && 265a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath !empty && mCanPersist) { 266a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = SEND; 267a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 268a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else if (pipeSize == 0) { 269a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* Done if no other work to do */ 270a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = empty ? DONE : SEND; 271a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 272a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 273a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 274a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req = (Request)pipe.removeFirst(); 275a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 276a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "processRequests() reading " + req); 277a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 278a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath try { 279a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.readResponse(mHttpClientConnection); 280a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (ParseException e) { 281a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 282a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_IO; 283a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IOException e) { 284a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 285a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_IO; 286a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IllegalStateException e) { 287a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 288a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_IO; 289a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 290a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (exception != null) { 291a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (httpFailure(req, error, exception) && 292a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath !req.mCancelled) { 293a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /* retry request if not permanent failure 294a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath or cancelled */ 295a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.reset(); 296a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath pipe.addFirst(req); 297a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 298a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = null; 299a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mCanPersist = false; 300a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 301a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (!mCanPersist) { 302a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 303a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "processRequests(): no persist, closing " + 304a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHost); 305a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 306a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath closeConnection(); 307a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 308a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpContext.removeAttribute(HTTP_CONNECTION); 309a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath clearPipe(pipe); 310a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath minPipe = maxPipe = 1; 311a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath state = SEND; 312a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 313a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath break; 314a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 315a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 316a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 317a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 318a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 319a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 320a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * After a send/receive failure, any pipelined requests must be 321a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * cleared back to the mRequest queue 322a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @return true if mRequests is empty after pipe cleared 323a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 324a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private boolean clearPipe(LinkedList<Request> pipe) { 325a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath boolean empty = true; 326a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 327a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "Connection.clearPipe(): clearing pipe " + pipe.size()); 328a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath synchronized (mRequestFeeder) { 329a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Request tReq; 330a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath while (!pipe.isEmpty()) { 331a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath tReq = (Request)pipe.removeLast(); 332a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 333a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "clearPipe() adding back " + mHost + " " + tReq); 334a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mRequestFeeder.requeueRequest(tReq); 335a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath empty = false; 336a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 337a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (empty) empty = !mRequestFeeder.haveRequest(mHost); 338a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 339a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return empty; 340a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 341a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 342a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 343a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @return true on success 344a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 345a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private boolean openHttpConnection(Request req) { 346a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 347a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath long now = SystemClock.uptimeMillis(); 348a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath int error = EventHandler.OK; 349a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Exception exception = null; 350a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 351a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath try { 352a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // reset the certificate to null before opening a connection 353a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mCertificate = null; 354a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpClientConnection = openConnection(req); 355a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (mHttpClientConnection != null) { 356a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpClientConnection.setSocketTimeout(SOCKET_TIMEOUT); 357a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpContext.setAttribute(HTTP_CONNECTION, 358a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpClientConnection); 359a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else { 360a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // we tried to do SSL tunneling, failed, 361a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // and need to drop the request; 362a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // we have already informed the handler 363a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mFailCount = RETRY_REQUEST_LIMIT; 364a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return false; 365a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 366a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (UnknownHostException e) { 367a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v("Failed to open connection"); 368a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_LOOKUP; 369a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 370a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IllegalArgumentException e) { 371a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v("Illegal argument exception"); 372a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_CONNECT; 373a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mFailCount = RETRY_REQUEST_LIMIT; 374a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 375a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (SSLConnectionClosedByUserException e) { 376a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // hack: if we have an SSL connection failure, 377a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // we don't want to reconnect 378a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mFailCount = RETRY_REQUEST_LIMIT; 379a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // no error message 380a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return false; 381a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (SSLHandshakeException e) { 382a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // hack: if we have an SSL connection failure, 383a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // we don't want to reconnect 384a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mFailCount = RETRY_REQUEST_LIMIT; 385a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 386a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "SSL exception performing handshake"); 387a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_FAILED_SSL_HANDSHAKE; 388a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 389a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } catch (IOException e) { 390a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = EventHandler.ERROR_CONNECT; 391a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath exception = e; 392a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 393a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 394a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) { 395a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath long now2 = SystemClock.uptimeMillis(); 396a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath HttpLog.v("Connection.openHttpConnection() " + 397a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath (now2 - now) + " " + mHost); 398a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 399a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 400a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (error == EventHandler.OK) { 401a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return true; 402a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else { 403a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (req.mFailCount < RETRY_REQUEST_LIMIT) { 404a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // requeue 405a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mRequestFeeder.requeueRequest(req); 406a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mFailCount++; 407a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else { 408a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath httpFailure(req, error, exception); 409a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 410a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return error == EventHandler.OK; 411a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 412a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 413a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 414a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 415a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Helper. Calls the mEventHandler's error() method only if 416a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * request failed permanently. Increments mFailcount on failure. 417a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * 418a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Increments failcount only if the network is believed to be 419a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * connected 420a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * 421a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @return true if request can be retried (less than 422a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * RETRY_REQUEST_LIMIT failures have occurred). 423a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 424a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private boolean httpFailure(Request req, int errorId, Exception e) { 425a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath boolean ret = true; 426a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 427a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // e.printStackTrace(); 428a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (HttpLog.LOGV) HttpLog.v( 429a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath "httpFailure() ******* " + e + " count " + req.mFailCount + 430a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath " " + mHost + " " + req.getUri()); 431a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 432a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (++req.mFailCount >= RETRY_REQUEST_LIMIT) { 433a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath ret = false; 434a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath String error; 435a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (errorId < 0) { 436a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = getEventHandlerErrorString(errorId); 437a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else { 438a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath Throwable cause = e.getCause(); 439a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath error = cause != null ? cause.toString() : e.getMessage(); 440a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 441a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.mEventHandler.error(errorId, error); 442a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath req.complete(); 443a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 444a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 445a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath closeConnection(); 446a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mHttpContext.removeAttribute(HTTP_CONNECTION); 447a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 448a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return ret; 449a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 450a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 451a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private static String getEventHandlerErrorString(int errorId) { 452a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath switch (errorId) { 453a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.OK: 454a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "OK"; 455a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 456a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR: 457a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR"; 458a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 459a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_LOOKUP: 460a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_LOOKUP"; 461a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 462a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_UNSUPPORTED_AUTH_SCHEME: 463a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_UNSUPPORTED_AUTH_SCHEME"; 464a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 465a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_AUTH: 466a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_AUTH"; 467a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 468a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_PROXYAUTH: 469a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_PROXYAUTH"; 470a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 471a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_CONNECT: 472a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_CONNECT"; 473a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 474a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_IO: 475a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_IO"; 476a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 477a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_TIMEOUT: 478a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_TIMEOUT"; 479a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 480a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_REDIRECT_LOOP: 481a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_REDIRECT_LOOP"; 482a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 483a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_UNSUPPORTED_SCHEME: 484a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_UNSUPPORTED_SCHEME"; 485a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 486a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_FAILED_SSL_HANDSHAKE: 487a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_FAILED_SSL_HANDSHAKE"; 488a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 489a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.ERROR_BAD_URL: 490a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "ERROR_BAD_URL"; 491a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 492a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.FILE_ERROR: 493a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "FILE_ERROR"; 494a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 495a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.FILE_NOT_FOUND_ERROR: 496a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "FILE_NOT_FOUND_ERROR"; 497a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 498a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath case EventHandler.TOO_MANY_REQUESTS_ERROR: 499a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "TOO_MANY_REQUESTS_ERROR"; 500a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 501a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath default: 502a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return "UNKNOWN_ERROR"; 503a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 504a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 505a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 506a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath HttpContext getHttpContext() { 507a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mHttpContext; 508a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 509a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 510a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 511a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Use same logic as ConnectionReuseStrategy 512a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @see ConnectionReuseStrategy 513a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 514a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath private boolean keepAlive(HttpEntity entity, 515a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath ProtocolVersion ver, int connType, final HttpContext context) { 516a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath org.apache.http.HttpConnection conn = (org.apache.http.HttpConnection) 517a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath context.getAttribute(ExecutionContext.HTTP_CONNECTION); 518a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 519a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (conn != null && !conn.isOpen()) 520a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return false; 521a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // do NOT check for stale connection, that is an expensive operation 522a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 523a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (entity != null) { 524a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (entity.getContentLength() < 0) { 525a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (!entity.isChunked() || ver.lessEquals(HttpVersion.HTTP_1_0)) { 526a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // if the content length is not known and is not chunk 527a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // encoded, the connection cannot be reused 528a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return false; 529a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 530a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 531a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 532a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // Check for 'Connection' directive 533a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (connType == Headers.CONN_CLOSE) { 534a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return false; 535a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } else if (connType == Headers.CONN_KEEP_ALIVE) { 536a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return true; 537a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 538a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath // Resorting to protocol version default close connection policy 539a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return !ver.lessEquals(HttpVersion.HTTP_1_0); 540a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 541a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 542a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath void setCanPersist(HttpEntity entity, ProtocolVersion ver, int connType) { 543a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mCanPersist = keepAlive(entity, ver, connType, mHttpContext); 544a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 545a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 546a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath void setCanPersist(boolean canPersist) { 547a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath mCanPersist = canPersist; 548a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 549a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 550a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath boolean getCanPersist() { 551a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mCanPersist; 552a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 553a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 554a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** typically http or https... set by subclass */ 555a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath abstract String getScheme(); 556a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath abstract void closeConnection(); 557a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath abstract AndroidHttpClientConnection openConnection(Request req) throws IOException; 558a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 559a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath /** 560a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Prints request queue to log, for debugging. 561a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * returns request count 562a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */ 563a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath public synchronized String toString() { 564a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mHost.toString(); 565a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 566a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 567a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath byte[] getBuf() { 568a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath if (mBuf == null) mBuf = new byte[8192]; 569a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath return mBuf; 570a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath } 571a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath 572a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath} 573