示例#1
0
 private void recycleSocket(final AsyncSocket socket, AsyncHttpRequest request) {
   if (socket == null) return;
   URI uri = request.getUri();
   int port = getSchemePort(uri);
   String lookup = computeLookup(uri, port, request);
   // nothing here will block...
   synchronized (this) {
     HashSet<AsyncSocket> sockets = mSockets.get(lookup);
     if (sockets == null) {
       sockets = new HashSet<AsyncSocket>();
       mSockets.put(lookup, sockets);
     }
     final HashSet<AsyncSocket> ss = sockets;
     sockets.add(socket);
     socket.setClosedCallback(
         new CompletedCallback() {
           @Override
           public void onCompleted(Exception ex) {
             synchronized (AsyncSocketMiddleware.this) {
               ss.remove(socket);
             }
             socket.setClosedCallback(null);
           }
         });
   }
 }
示例#2
0
 private void idleSocket(final AsyncSocket socket) {
   // must listen for socket close, otherwise log will get spammed.
   socket.setEndCallback(
       new CompletedCallback() {
         @Override
         public void onCompleted(Exception ex) {
           socket.close();
         }
       });
   socket.setWriteableCallback(null);
   // should not get any data after this point...
   // if so, eat it and disconnect.
   socket.setDataCallback(
       new NullDataCallback() {
         @Override
         public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
           super.onDataAvailable(emitter, bb);
           bb.recycle();
           socket.close();
         }
       });
 }
示例#3
0
  @Override
  public Cancellable getSocket(final AsyncHttpClientMiddleware.GetSocketData data) {
    final URI uri = data.request.getUri();
    final int port = getSchemePort(data.request.getUri());
    if (port == -1) {
      return null;
    }

    ConnectionInfo info = getConnectionInfo(uri.getScheme(), uri.getHost(), port);
    if (info.openCount >= maxConnectionCount) {
      // wait for a connection queue to free up
      SimpleCancellable queueCancel = new SimpleCancellable();
      info.queue.add(data);
      return queueCancel;
    }

    info.openCount++;

    final String lookup = computeLookup(uri, port, data.request);

    data.state.putBoolean(getClass().getCanonicalName() + ".owned", true);

    synchronized (this) {
      final HashSet<AsyncSocket> sockets = mSockets.get(lookup);
      if (sockets != null) {
        for (final AsyncSocket socket : sockets) {
          if (socket.isOpen()) {
            sockets.remove(socket);
            socket.setClosedCallback(null);

            mClient
                .getServer()
                .post(
                    new Runnable() {
                      @Override
                      public void run() {
                        data.request.logd("Reusing keep-alive socket");
                        data.connectCallback.onConnectCompleted(null, socket);
                      }
                    });

            // replace above code with immediate callback?
            //                        data.request.logd("Reusing keep-alive socket");
            //                        data.connectCallback.onConnectCompleted(null, socket);

            // just a noop/dummy, as this can't actually be cancelled.
            return new SimpleCancellable();
          }
        }
      }
    }

    if (!connectAllAddresses || proxyHost != null || data.request.getProxyHost() != null) {
      // just default to connecting to a single address
      data.request.logd("Connecting socket");
      String unresolvedHost;
      int unresolvedPort;
      if (data.request.getProxyHost() != null) {
        unresolvedHost = data.request.getProxyHost();
        unresolvedPort = data.request.getProxyPort();
        // set the host and port explicitly for proxied connections
        data.request
            .getHeaders()
            .getHeaders()
            .setStatusLine(data.request.getProxyRequestLine().toString());
      } else if (proxyHost != null) {
        unresolvedHost = proxyHost;
        unresolvedPort = proxyPort;
        // set the host and port explicitly for proxied connections
        data.request
            .getHeaders()
            .getHeaders()
            .setStatusLine(data.request.getProxyRequestLine().toString());
      } else {
        unresolvedHost = uri.getHost();
        unresolvedPort = port;
      }
      return mClient
          .getServer()
          .connectSocket(
              unresolvedHost, unresolvedPort, wrapCallback(data.connectCallback, uri, port));
    }

    // try to connect to everything...
    data.request.logv("Resolving domain and connecting to all available addresses");
    return mClient
        .getServer()
        .getAllByName(uri.getHost())
        .then(
            new TransformFuture<AsyncSocket, InetAddress[]>() {
              Exception lastException;

              @Override
              protected void error(Exception e) {
                super.error(e);
                data.connectCallback.onConnectCompleted(e, null);
              }

              @Override
              protected void transform(final InetAddress[] result) throws Exception {
                Continuation keepTrying =
                    new Continuation(
                        new CompletedCallback() {
                          @Override
                          public void onCompleted(Exception ex) {
                            // if it completed, that means that the connection failed
                            if (lastException == null)
                              lastException =
                                  new ConnectionFailedException(
                                      "Unable to connect to remote address");
                            setComplete(lastException);
                          }
                        });

                for (final InetAddress address : result) {
                  keepTrying.add(
                      new ContinuationCallback() {
                        @Override
                        public void onContinue(
                            Continuation continuation, final CompletedCallback next)
                            throws Exception {
                          mClient
                              .getServer()
                              .connectSocket(
                                  new InetSocketAddress(address, port),
                                  wrapCallback(
                                      new ConnectCallback() {
                                        @Override
                                        public void onConnectCompleted(
                                            Exception ex, AsyncSocket socket) {
                                          if (isDone()) {
                                            lastException =
                                                new Exception("internal error during connect");
                                            next.onCompleted(null);
                                            return;
                                          }

                                          // try the next address
                                          if (ex != null) {
                                            lastException = ex;
                                            next.onCompleted(null);
                                            return;
                                          }

                                          // if the socket is no longer needed, just hang onto it...
                                          if (isDone() || isCancelled()) {
                                            data.request.logd(
                                                "Recycling extra socket leftover from cancelled operation");
                                            idleSocket(socket);
                                            recycleSocket(socket, data.request);
                                            return;
                                          }

                                          if (setComplete(null, socket)) {
                                            data.connectCallback.onConnectCompleted(ex, socket);
                                          }
                                        }
                                      },
                                      uri,
                                      port));
                        }
                      });
                }

                keepTrying.start();
              }
            });
  }