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;
  }
Exemplo n.º 3
0
  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);
      }
    }
  }