private void dispatchSomePendingEvents(boolean flag) throws IOException, ParseException, HttpException { if (GoogleAnalyticsTracker.getInstance().getDebug() && flag) { Log.v("GoogleAnalyticsTracker", "dispatching events in dry run mode"); } int i = 0; while (i < events.size() && i < maxEventsPerRequest) { Event event = (Event)events.get(i); String s; BasicHttpRequest basichttprequest; if ("__##GOOGLEPAGEVIEW##__".equals(event.category)) { s = NetworkRequestUtil.constructPageviewRequestPath(event, referrer); } else if ("__##GOOGLETRANSACTION##__".equals(event.category)) { s = NetworkRequestUtil.constructTransactionRequestPath(event, referrer); } else if ("__##GOOGLEITEM##__".equals(event.category)) { s = NetworkRequestUtil.constructItemRequestPath(event, referrer); } else { s = NetworkRequestUtil.constructEventRequestPath(event, referrer); } basichttprequest = new BasicHttpRequest("GET", s); basichttprequest.addHeader("Host", NetworkDispatcher.access$200().getHostName()); basichttprequest.addHeader("User-Agent", userAgent); if (GoogleAnalyticsTracker.getInstance().getDebug()) { Log.i("GoogleAnalyticsTracker", basichttprequest.getRequestLine().toString()); } if (flag) { requesterCallBacks.requestSent(); } else { pipelinedRequester.addRequest(basichttprequest); } i++; } if (!flag) { pipelinedRequester.sendRequests(); } }
/** * Opens the connection to a http server or proxy. * * @return the opened low level connection * @throws IOException if the connection fails for any reason. */ @Override AndroidHttpClientConnection openConnection(Request req) throws IOException { SSLSocket sslSock = null; if (mProxyHost != null) { // If we have a proxy set, we first send a CONNECT request // to the proxy; if the proxy returns 200 OK, we negotiate // a secure connection to the target server via the proxy. // If the request fails, we drop it, but provide the event // handler with the response status and headers. The event // handler is then responsible for cancelling the load or // issueing a new request. AndroidHttpClientConnection proxyConnection = null; Socket proxySock = null; try { proxySock = new Socket(mProxyHost.getHostName(), mProxyHost.getPort()); proxySock.setSoTimeout(60 * 1000); proxyConnection = new AndroidHttpClientConnection(); HttpParams params = new BasicHttpParams(); HttpConnectionParams.setSocketBufferSize(params, 8192); proxyConnection.bind(proxySock, params); } catch (IOException e) { if (proxyConnection != null) { proxyConnection.close(); } String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to establish a connection to the proxy"; } throw new IOException(errorMessage); } StatusLine statusLine = null; int statusCode = 0; Headers headers = new Headers(); try { BasicHttpRequest proxyReq = new BasicHttpRequest("CONNECT", mHost.toHostString()); // add all 'proxy' headers from the original request, we also need // to add 'host' header unless we want proxy to answer us with a // 400 Bad Request for (Header h : req.mHttpRequest.getAllHeaders()) { String headerName = h.getName().toLowerCase(Locale.ROOT); if (headerName.startsWith("proxy") || headerName.equals("keep-alive") || headerName.equals("host")) { proxyReq.addHeader(h); } } proxyConnection.sendRequestHeader(proxyReq); proxyConnection.flush(); // it is possible to receive informational status // codes prior to receiving actual headers; // all those status codes are smaller than OK 200 // a loop is a standard way of dealing with them do { statusLine = proxyConnection.parseResponseHeader(headers); statusCode = statusLine.getStatusCode(); } while (statusCode < HttpStatus.SC_OK); } catch (ParseException e) { String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to send a CONNECT request"; } throw new IOException(errorMessage); } catch (HttpException e) { String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to send a CONNECT request"; } throw new IOException(errorMessage); } catch (IOException e) { String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to send a CONNECT request"; } throw new IOException(errorMessage); } if (statusCode == HttpStatus.SC_OK) { try { sslSock = (SSLSocket) getSocketFactory() .createSocket(proxySock, mHost.getHostName(), mHost.getPort(), true); } catch (IOException e) { if (sslSock != null) { sslSock.close(); } String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to create an SSL socket"; } throw new IOException(errorMessage); } } else { // if the code is not OK, inform the event handler ProtocolVersion version = statusLine.getProtocolVersion(); req.mEventHandler.status( version.getMajor(), version.getMinor(), statusCode, statusLine.getReasonPhrase()); req.mEventHandler.headers(headers); req.mEventHandler.endData(); proxyConnection.close(); // here, we return null to indicate that the original // request needs to be dropped return null; } } else { // if we do not have a proxy, we simply connect to the host try { sslSock = (SSLSocket) getSocketFactory().createSocket(mHost.getHostName(), mHost.getPort()); sslSock.setSoTimeout(SOCKET_TIMEOUT); } catch (IOException e) { if (sslSock != null) { sslSock.close(); } String errorMessage = e.getMessage(); if (errorMessage == null) { errorMessage = "failed to create an SSL socket"; } throw new IOException(errorMessage); } } // do handshake and validate server certificates SslError error = CertificateChainValidator.getInstance() .doHandshakeAndValidateServerCertificates(this, sslSock, mHost.getHostName()); // Inform the user if there is a problem if (error != null) { // handleSslErrorRequest may immediately unsuspend if it wants to // allow the certificate anyway. // So we mark the connection as suspended, call handleSslErrorRequest // then check if we're still suspended and only wait if we actually // need to. synchronized (mSuspendLock) { mSuspended = true; } // don't hold the lock while calling out to the event handler boolean canHandle = req.getEventHandler().handleSslErrorRequest(error); if (!canHandle) { throw new IOException("failed to handle " + error); } synchronized (mSuspendLock) { if (mSuspended) { try { // Put a limit on how long we are waiting; if the timeout // expires (which should never happen unless you choose // to ignore the SSL error dialog for a very long time), // we wake up the thread and abort the request. This is // to prevent us from stalling the network if things go // very bad. mSuspendLock.wait(10 * 60 * 1000); if (mSuspended) { // mSuspended is true if we have not had a chance to // restart the connection yet (ie, the wait timeout // has expired) mSuspended = false; mAborted = true; if (HttpLog.LOGV) { HttpLog.v( "HttpsConnection.openConnection():" + " SSL timeout expired and request was cancelled!!!"); } } } catch (InterruptedException e) { // ignore } } if (mAborted) { // The user decided not to use this unverified connection // so close it immediately. sslSock.close(); throw new SSLConnectionClosedByUserException("connection closed by the user"); } } } // All went well, we have an open, verified connection. AndroidHttpClientConnection conn = new AndroidHttpClientConnection(); BasicHttpParams params = new BasicHttpParams(); params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192); conn.bind(sslSock, params); return conn; }
public void run() { try { Socket socket = new Socket(host.getHostName(), host.getPort()); conn.bind(socket, params); // build request BasicHttpRequest request; if (!this.getRequest().getBody().isEmpty()) { request = new BasicHttpEntityEnclosingRequest( this.getRequest().getMethod(), this.getRequest().getPath()); } else { request = new BasicHttpRequest(this.getRequest().getMethod(), this.getRequest().getPath()); } // add headers Map<String, String> headers = this.getRequest().getHeaders(); Iterator<Map.Entry<String, String>> it = headers.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> pairs = it.next(); request.addHeader(pairs.getKey(), pairs.getValue()); } // set body if (request instanceof BasicHttpEntityEnclosingRequest) { StringEntity body = new StringEntity(this.getRequest().getBody()); ((BasicHttpEntityEnclosingRequest) request).setEntity(body); } logger.info("> " + request.getRequestLine().getUri()); // request request.setParams(params); httpexecutor.preProcess(request, httpproc, context); HttpResponse response = httpexecutor.execute(request, conn, context); response.setParams(params); httpexecutor.postProcess(response, httpproc, context); logger.info("< " + response.getStatusLine()); // set all request headers Header[] allHeaders = request.getAllHeaders(); for (int i = 0; i < allHeaders.length; i++) { this.getRequest().setHeader(allHeaders[i].getName(), allHeaders[i].getValue()); } // create response String content = ""; HttpEntity entity = response.getEntity(); if (entity != null) { content = EntityUtils.toString(entity); } this.response = new Response(response, content); // call callback callback.onResponse(this.request, this.response); } catch (Exception e) { Aletheia.handleException(e); } finally { try { conn.close(); } catch (Exception e) { Aletheia.handleException(e); } } }