Пример #1
0
    @Override
    public NextAction handleClose(final FilterChainContext ctx) throws IOException {
      Socket tunnelSocket = tunnelSockets.get(ctx.getConnection());
      if (tunnelSocket != null) {
        tunnelSocket.close();
      }

      return ctx.getStopAction();
    }
Пример #2
0
    @Override
    public NextAction handleRead(FilterChainContext ctx) throws IOException {
      // Take ADD-service response
      final AddResponseMessage addResponseMessage = ctx.getMessage();

      // do output
      LOGGER.log(Level.INFO, "Result={0}", addResponseMessage.getResult());

      return ctx.getStopAction();
    }
Пример #3
0
    @Override
    public NextAction handleRead(FilterChainContext ctx) throws IOException {
      final Buffer content = ctx.getMessage();
      try {
        future.result(content);
      } catch (Exception e) {
        future.failure(e);
        e.printStackTrace();
      }

      return ctx.getStopAction();
    }
Пример #4
0
 /*
  * 接收
  *
  * @param context 上下文
  * @param channel 通道
  * @param buffer 缓存
  * @param readable 缓存可读
  * @param bytes 输入缓存
  * @param offset 指向已读数据的偏移量,off之前的数据都是已用过的
  * @param limit 有效长度,limit之后的长度是空白或无效数据,off到limit之间的数据是准备使用的数据
  * @return 后续动作
  * @throws IOException
  */
 private NextAction receive(
     FilterChainContext context,
     Channel channel,
     Buffer buffer,
     int readable,
     byte[] bytes,
     int offset,
     int limit)
     throws IOException {
   for (; ; ) {
     int read = Math.min(readable, bytes.length - limit); // 取bytes缓存空闲区,和可读取新数据,的最小值,即:此次最多读写数据的大小
     buffer.get(bytes, limit, read); // 从可读取新数据中,读取数据,尽量填满bytes缓存空闲区
     limit += read; // 有效数据变长
     readable -= read; // 可读数据变少
     UnsafeByteArrayInputStream input =
         new UnsafeByteArrayInputStream(
             bytes, offset, limit - offset); // 将bytes缓存转成InputStream,不需要关闭
     Object msg = upstreamCodec.decode(channel, input); // 调用Codec接口,解码数据
     if (msg == Codec.NEED_MORE_INPUT) { // 如果Codec觉得数据不够,不足以解码成一个对象
       if (readable == 0) { // 如果没有更多可读数据
         channel.setAttribute(
             BUFFER_KEY, new Object[] {bytes, offset, limit}); // 放入通道属性中,等待下一个Buffer的到来
         return context.getStopAction();
       } else { // 扩充或挪出空闲区,并循环,直到可读数据都加载到bytes缓存
         if (offset == 0) { // 如果bytes缓存全部没有被使用,如果这时数据还不够
           bytes = Bytes.copyOf(bytes, bytes.length << 1); // 将bytes缓存扩大一倍
         } else { // 如果bytes缓存有一段数据已被使用
           int len = limit - offset; // 计算有效数据长度
           System.arraycopy(
               bytes, offset, bytes, 0, len); // 将数据向前移到,压缩到已使用的部分,这样limit后面就会多出一些空闲,可以放数据
           offset = 0; // 移到后,bytes缓存没有数据被使用
           limit = len; // 移到后,有效数据都在bytes缓存最前面
         }
       }
     } else { // 如果解析出一个结果
       int position = input.position(); // 记录InputStream用了多少
       if (position == offset) { // 如果InputStream没有被读过,就返回了数据,直接报错,否则InputStream永远读不完,会死递归
         throw new IOException("Decode without read data.");
       }
       offset = position; // 记录已读数据
       context.setMessage(msg); // 将消息改为解码后的对象,以便被后面的Filter使用。
       if (limit - offset > 0 || readable > 0) { // 如果有效数据没有被读完,或者Buffer区还有未读数据
         return context.getInvokeAction(
             new Object[] {
               buffer, readable, bytes, offset, limit
             }); // 正常执行完Filter,并重新发起一轮Filter,继续读
       } else { // 否则所有数据读完
         return context.getInvokeAction(); // 正常执行完Filter
       }
     }
   }
 }
  @Override
  public NextAction handleRead(final FilterChainContext ctx) throws IOException {
    final HttpContent httpContent = ctx.getMessage();
    if (httpContent.isLast()) {
      // Perform the cleanup logic if it's the last chunk of the payload
      final HttpResponsePacket response = (HttpResponsePacket) httpContent.getHttpHeader();

      recycleRequestResponsePackets(ctx.getConnection(), response);
      return ctx.getStopAction();
    }

    return ctx.getInvokeAction();
  }
  @Override
  public NextAction handleWrite(final FilterChainContext ctx) throws IOException {

    Object message = ctx.getMessage();
    if (message instanceof RequestInfoHolder) {
      ctx.setMessage(null);
      if (!sendAsGrizzlyRequest((RequestInfoHolder) message, ctx)) {
        return ctx.getSuspendAction();
      }
    } else if (message instanceof Buffer) {
      return ctx.getInvokeAction();
    }

    return ctx.getStopAction();
  }
      @Override
      public NextAction handleRead(FilterChainContext ctx) throws IOException {

        HttpContent c = (HttpContent) ctx.getMessage();
        Buffer b = c.getContent();
        if (b.hasRemaining()) {
          sb.append(b.toStringContent());
        }

        // Last content from the server, set the future result so
        // the client can display the result and gracefully exit.
        if (c.isLast()) {
          future.result(sb.toString());
        }
        return ctx.getStopAction(); // discontinue filter chain execution
      }
 private static boolean checkHandshakeError(
     final FilterChainContext ctx, final HttpTxContext httpCtx) {
   Throwable t = getHandshakeError(ctx.getConnection());
   if (t != null) {
     httpCtx.abort(t);
     return true;
   }
   return false;
 }
 private static boolean checkProxyAuthFailure(
     final FilterChainContext ctx, final HttpTxContext httpCtx) {
   final Boolean failed = PROXY_AUTH_FAILURE.get(ctx.getConnection());
   if (failed != null && failed) {
     httpCtx.abort(new IllegalStateException("Unable to authenticate with proxy"));
     return true;
   }
   return false;
 }
  @Override
  public NextAction handleWrite(FilterChainContext ctx) throws IOException {

    try {
      Thread.sleep(random.nextInt(50) + 10);
    } catch (InterruptedException ignored) {
    }

    return ctx.getInvokeAction();
  }
Пример #11
0
 @Override
 public NextAction handleRead(FilterChainContext context) throws IOException {
   Object message = context.getMessage();
   Connection<?> connection = context.getConnection();
   Channel channel = GrizzlyChannel.getOrAddChannel(connection, url, handler);
   try {
     if (message instanceof Buffer) { // 收到新的数据包
       Buffer buffer = (Buffer) message; // 缓存
       int readable = buffer.capacity(); // 本次可读取新数据的大小
       if (readable == 0) {
         return context.getStopAction();
       }
       byte[] bytes; // byte[]缓存区,将Buffer转成byte[],再转成UnsafeByteArrayInputStream
       int offset; // 指向已用数据的偏移量,off之前的数据都是已用过的
       int limit; // 有效长度,limit之后的长度是空白或无效数据,off到limit之间的数据是准备使用的有效数据
       Object[] remainder = (Object[]) channel.getAttribute(BUFFER_KEY); // 上次序列化剩下的数据
       channel.removeAttribute(BUFFER_KEY);
       if (remainder == null) { // 如果没有,创建新的bytes缓存
         bytes = new byte[bufferSize];
         offset = 0;
         limit = 0;
       } else { // 如果有,使用剩下的bytes缓存
         bytes = (byte[]) remainder[0];
         offset = (Integer) remainder[1];
         limit = (Integer) remainder[2];
       }
       return receive(context, channel, buffer, readable, bytes, offset, limit);
     } else if (message instanceof Object[]) { // 同一Buffer多轮Filter,即:一个Buffer里有多个请求
       Object[] remainder = (Object[]) message;
       Buffer buffer = (Buffer) remainder[0];
       int readable = (Integer) remainder[1];
       byte[] bytes = (byte[]) remainder[2];
       int offset = (Integer) remainder[3];
       int limit = (Integer) remainder[4];
       return receive(context, channel, buffer, readable, bytes, offset, limit);
     } else { // 其它事件直接往下传
       return context.getInvokeAction();
     }
   } finally {
     GrizzlyChannel.removeChannelIfDisconnectd(connection);
   }
 }
    @Override
    public NextAction handleRead(final FilterChainContext ctx) throws IOException {

      String message = (String) ctx.getMessage();

      logger.log(Level.INFO, "First chunk come: {0}", message);
      intermResultQueue.add(message);

      Connection connection = ctx.getConnection();
      connection.setBlockingReadTimeout(10, TimeUnit.SECONDS);

      try {
        for (int i = 0; i < clientMsgs - 1; i++) {
          final ReadResult rr = ctx.read();
          final String blckMsg = (String) rr.getMessage();

          rr.recycle();
          logger.log(Level.INFO, "Blocking chunk come: {0}", blckMsg);
          intermResultQueue.add(blckMsg);
          message += blckMsg;
        }
      } catch (Exception e) {
        intermResultQueue.add(e);
        return ctx.getStopAction();
      }

      ctx.setMessage(message);

      return ctx.getInvokeAction();
    }
Пример #13
0
  @Override
  public NextAction handleWrite(FilterChainContext context) throws IOException {
    Connection<?> connection = context.getConnection();
    GrizzlyChannel channel = GrizzlyChannel.getOrAddChannel(connection, url, handler);
    try {
      UnsafeByteArrayOutputStream output = new UnsafeByteArrayOutputStream(1024); // 不需要关闭

      if (!(context.getMessage() instanceof Response)) {
        downstreamCodec.encode(channel, output, context.getMessage());
      } else {
        upstreamCodec.encode(channel, output, context.getMessage());
      }

      GrizzlyChannel.removeChannelIfDisconnectd(connection);
      byte[] bytes = output.toByteArray();
      Buffer buffer = connection.getTransport().getMemoryManager().allocate(bytes.length);
      buffer.put(bytes);
      buffer.flip();
      buffer.allowBufferDispose(true);
      context.setMessage(buffer);
    } finally {
      GrizzlyChannel.removeChannelIfDisconnectd(connection);
    }
    return context.getInvokeAction();
  }
      @SuppressWarnings({"unchecked"})
      @Override
      public NextAction handleConnect(FilterChainContext ctx) throws IOException {
        System.out.println("\nClient connected!\n");

        HttpRequestPacket request = createRequest();
        System.out.println("Writing request:\n");
        System.out.println(request.toString());
        ctx.write(request); // write the request

        // for each of the content parts in CONTENT, wrap in a Buffer,
        // create the HttpContent to wrap the buffer and write the
        // content.
        MemoryManager mm = ctx.getMemoryManager();
        for (int i = 0, len = CONTENT.length; i < len; i++) {
          HttpContent.Builder contentBuilder = request.httpContentBuilder();
          Buffer b = Buffers.wrap(mm, CONTENT[i]);
          contentBuilder.content(b);
          HttpContent content = contentBuilder.build();
          System.out.printf("(Client writing: %s)\n", b.toStringContent());
          ctx.write(content);
          try {
            Thread.sleep(2000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

        // since the request created by createRequest() is chunked,
        // we need to write the trailer to signify the end of the
        // POST data
        ctx.write(request.httpTrailerBuilder().build());

        System.out.println("\n");

        return ctx.getStopAction(); // discontinue filter chain execution
      }
  @SuppressWarnings("unchecked")
  public boolean sendRequest(
      final FilterChainContext ctx, final Request request, final HttpRequestPacket requestPacket)
      throws IOException {

    boolean isWriteComplete = true;

    if (Utils.requestHasEntityBody(request)) {
      final HttpTxContext context = HttpTxContext.get(ctx);
      BodyHandler handler = bodyHandlerFactory.getBodyHandler(request);
      if (requestPacket.getHeaders().contains(Header.Expect)
          && requestPacket.getHeaders().getValue(1).equalsIgnoreCase("100-Continue")) {
        // We have to set the content-length now as the headers will be flushed
        // before the FileBodyHandler is invoked.  If we don't do it here, and
        // the user didn't explicitly set the length, then the transfer-encoding
        // will be chunked and zero-copy file transfer will not occur.
        final File f = request.getFile();
        if (f != null) {
          requestPacket.setContentLengthLong(f.length());
        }
        handler = new ExpectHandler(handler);
      }
      context.setBodyHandler(handler);
      if (logger.isDebugEnabled()) {
        logger.debug("REQUEST: {}", requestPacket);
      }
      isWriteComplete = handler.doHandle(ctx, request, requestPacket);
    } else {
      HttpContent content = HttpContent.builder(requestPacket).last(true).build();
      if (logger.isDebugEnabled()) {
        logger.debug("REQUEST: {}", requestPacket);
      }
      ctx.write(content, ctx.getTransportContext().getCompletionHandler());
    }

    return isWriteComplete;
  }
Пример #16
0
  /**
   * Per-request initialization required for the InputBuffer to function properly.
   *
   * @param httpHeader the header from which input will be obtained.
   * @param ctx the FilterChainContext for the chain processing this request
   */
  public void initialize(final HttpHeader httpHeader, final FilterChainContext ctx) {

    if (ctx == null) {
      throw new IllegalArgumentException("ctx cannot be null.");
    }
    this.httpHeader = httpHeader;

    this.ctx = ctx;
    connection = ctx.getConnection();
    final Object message = ctx.getMessage();
    if (message instanceof HttpContent) {
      final HttpContent content = (HttpContent) message;

      // Check if HttpContent is chunked message trailer w/ headers
      checkHttpTrailer(content);
      updateInputContentBuffer(content.getContent());
      contentRead = content.isLast();
      content.recycle();

      if (LOGGER.isLoggable(LOGGER_LEVEL)) {
        log("InputBuffer %s initialize with ready content: %s", this, inputContentBuffer);
      }
    }
  }
Пример #17
0
    @Override
    public NextAction handleRead(FilterChainContext ctx) throws IOException {
      // Get the parsed HttpContent (we assume prev. filter was HTTP)
      HttpContent message = ctx.getMessage();
      Socket tunnelSocket = tunnelSockets.get(ctx.getConnection());

      if (tunnelSocket == null) {
        // handle connection procedure
        return GrizzlyModProxy.this.handleConnect(ctx, message);
      }

      if (message.getContent().hasRemaining()) {
        // relay the content to the tunnel connection

        Buffer buffer = message.getContent();
        message.recycle();

        tunnelSocket
            .getOutputStream()
            .write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
      }

      return ctx.getStopAction();
    }
  public Result find(PUContext puc, FilterChainContext fcc) {
    final Buffer buffer = fcc.getMessage();
    if (buffer.remaining() >= signature.length) {
      final int start = buffer.position();

      for (int i = 0; i < signature.length; i++) {
        if (buffer.get(start + i) != signature[i]) {
          return Result.NOT_FOUND;
        }
      }

      return Result.FOUND;
    }

    return Result.NEED_MORE_DATA;
  }
  private static FilterChainContext checkAndHandleFilterChainUpdate(
      final FilterChainContext ctx, final FilterChainContext sendingCtx) {
    FilterChainContext ctxLocal = sendingCtx;
    SSLConnectionContext sslCtx = SSLUtils.getSslConnectionContext(ctx.getConnection());
    if (sslCtx != null) {
      FilterChain fc = sslCtx.getNewConnectionFilterChain();

      if (fc != null) {
        // Create a new FilterChain context using the new
        // FilterChain.
        // TODO:  We need to mark this connection somehow
        //        as being only suitable for this type of
        //        request.
        ctxLocal = obtainProtocolChainContext(ctx, fc);
      }
    }
    return ctxLocal;
  }
  @SuppressWarnings("unchecked")
  @Override
  public NextAction handleEvent(final FilterChainContext ctx, final FilterChainEvent event)
      throws IOException {

    final Object type = event.type();
    if (type == ContinueEvent.class) {
      final ContinueEvent continueEvent = (ContinueEvent) event;
      ((ExpectHandler) continueEvent.getContext().getBodyHandler()).finish(ctx);
    } else if (type == TunnelRequestEvent.class) {
      // Disable SSL for the time being...
      ctx.notifyDownstream(new SSLSwitchingEvent(false, ctx.getConnection()));
      ctx.suspend();
      TunnelRequestEvent tunnelRequestEvent = (TunnelRequestEvent) event;
      final ProxyServer proxyServer = tunnelRequestEvent.getProxyServer();
      final URI requestUri = tunnelRequestEvent.getUri();

      RequestBuilder builder = new RequestBuilder();
      builder.setMethod(Method.CONNECT.getMethodString());
      builder.setUrl("http://" + getAuthority(requestUri));
      Request request = builder.build();

      AsyncHandler handler =
          new AsyncCompletionHandler() {
            @Override
            public Object onCompleted(Response response) throws Exception {
              if (response.getStatusCode() != 200) {
                PROXY_AUTH_FAILURE.set(ctx.getConnection(), Boolean.TRUE);
              }
              ctx.notifyDownstream(new SSLSwitchingEvent(true, ctx.getConnection()));
              ctx.notifyDownstream(event);
              return response;
            }
          };
      final GrizzlyResponseFuture future =
          new GrizzlyResponseFuture(grizzlyAsyncHttpProvider, request, handler, proxyServer);
      future.setDelegate(SafeFutureImpl.create());

      grizzlyAsyncHttpProvider.execute(
          ctx.getConnection(), request, handler, future, HttpTxContext.get(ctx));
      return ctx.getSuspendAction();
    }

    return ctx.getStopAction();
  }
Пример #21
0
  @Override
  public NextAction handleRead(FilterChainContext ctx) throws IOException {

    final Object message = ctx.getMessage();

    if (_logger.isDebugEnabled()) {
      _logger.debug(String.format("%s: Got [%s] from [%s].", this, message, ctx.getAddress()));
    }

    String responseXML = _coreCommandProcessor.processCommand((String) message);

    if (_logger.isDebugEnabled()) {
      _logger.debug(
          String.format("%s: Returning [%s] to [%s].", this, responseXML, ctx.getAddress()));
    }

    ctx.write(ctx.getAddress(), responseXML, null);

    //  Close the connection
    ctx.getConnection().closeSilently();

    return ctx.getStopAction();
  }
Пример #22
0
  /**
   * Method is called, when new client {@link Connection} was connected to some endpoint
   *
   * @param ctx the filter chain context
   * @return the next action to be executed by chain
   * @throws java.io.IOException
   */
  @Override
  public NextAction handleConnect(FilterChainContext ctx) throws IOException {
    newConnection(ctx.getConnection());

    return ctx.getInvokeAction();
  }
Пример #23
0
 /**
  * Method is called, when the {@link Connection} is getting closed
  *
  * @param ctx the filter chain context
  * @return the next action to be executed by chain
  * @throws java.io.IOException
  */
 @Override
 public NextAction handleClose(FilterChainContext ctx) throws IOException {
   activeConnectionsMap.remove(ctx.getConnection());
   return ctx.getInvokeAction();
 }
  private static FilterChainContext obtainProtocolChainContext(
      final FilterChainContext ctx, final FilterChain completeProtocolFilterChain) {

    final FilterChainContext newFilterChainContext =
        completeProtocolFilterChain.obtainFilterChainContext(
            ctx.getConnection(),
            ctx.getStartIdx() + 1,
            completeProtocolFilterChain.size(),
            ctx.getFilterIdx() + 1);

    newFilterChainContext.setAddressHolder(ctx.getAddressHolder());
    newFilterChainContext.setMessage(ctx.getMessage());
    newFilterChainContext.getInternalContext().setIoEvent(ctx.getInternalContext().getIoEvent());
    ctx.getConnection().setProcessor(completeProtocolFilterChain);
    return newFilterChainContext;
  }
Пример #25
0
 /**
  * Initiates asynchronous data receiving.
  *
  * <p>This is service method, usually users don't have to call it explicitly.
  */
 public void initiateAsyncronousDataReceiving() {
   // fork the FilterChainContext execution
   // keep the current FilterChainContext suspended, but make a copy and resume it
   ctx.fork(ctx.getStopAction());
 }
  private boolean sendAsGrizzlyRequest(
      final RequestInfoHolder requestInfoHolder, final FilterChainContext ctx) throws IOException {

    HttpTxContext httpTxContext = requestInfoHolder.getHttpTxContext();
    if (httpTxContext == null) {
      httpTxContext = HttpTxContext.create(requestInfoHolder);
    }

    if (checkProxyAuthFailure(ctx, httpTxContext)) {
      return true;
    }

    final Request request = httpTxContext.getRequest();
    final URI uri = request.isUseRawUrl() ? request.getRawURI() : request.getURI();
    boolean secure = Utils.isSecure(uri);

    // If the request is secure, check to see if an error occurred during
    // the handshake.  We have to do this here, as the error would occur
    // out of the scope of a HttpTxContext so there would be
    // no good way to communicate the problem to the caller.
    if (secure && checkHandshakeError(ctx, httpTxContext)) {
      return true;
    }

    if (isUpgradeRequest(httpTxContext.getHandler())
        && isWSRequest(httpTxContext.getRequestUrl())) {
      httpTxContext.setWSRequest(true);
      convertToUpgradeRequest(httpTxContext);
    }

    HttpRequestPacket requestPacket = requestCache.poll();
    if (requestPacket == null) {
      requestPacket = new HttpRequestPacketImpl();
    }
    requestPacket.setMethod(request.getMethod());
    requestPacket.setProtocol(Protocol.HTTP_1_1);

    // Special handling for CONNECT.
    if (Method.CONNECT.matchesMethod(request.getMethod())) {
      final int port = uri.getPort();
      requestPacket.setRequestURI(uri.getHost() + ':' + (port == -1 ? 443 : port));
    } else {
      requestPacket.setRequestURI(uri.getPath());
    }

    if (Utils.requestHasEntityBody(request)) {
      final long contentLength = request.getContentLength();
      if (contentLength >= 0) {
        requestPacket.setContentLengthLong(contentLength);
        requestPacket.setChunked(false);
      } else {
        requestPacket.setChunked(true);
      }
    }

    if (httpTxContext.isWSRequest()) {
      try {
        final URI wsURI = new URI(httpTxContext.getWsRequestURI());
        httpTxContext.setProtocolHandler(Version.RFC6455.createHandler(true));
        httpTxContext.setHandshake(httpTxContext.getProtocolHandler().createHandShake(wsURI));
        requestPacket =
            (HttpRequestPacket) httpTxContext.getHandshake().composeHeaders().getHttpHeader();
      } catch (URISyntaxException e) {
        throw new IllegalArgumentException("Invalid WS URI: " + httpTxContext.getWsRequestURI());
      }
    }

    requestPacket.setSecure(secure);
    addQueryString(request, requestPacket);
    addHostHeader(request, uri, requestPacket);
    addGeneralHeaders(request, requestPacket);
    addCookies(request, requestPacket);

    initTransferCompletionHandler(request, httpTxContext.getHandler());

    final HttpRequestPacket requestPacketLocal = requestPacket;
    FilterChainContext sendingCtx = ctx;

    if (secure) {
      // Check to see if the ProtocolNegotiator has given
      // us a different FilterChain to use.  If so, we need
      // use a different FilterChainContext when invoking sendRequest().
      sendingCtx = checkAndHandleFilterChainUpdate(ctx, sendingCtx);
    }
    final Connection c = ctx.getConnection();
    if (!Utils.isSpdyConnection(c)) {
      HttpContext.newInstance(ctx, c, c, c);
    } else {
      SpdySession session = SpdySession.get(c);
      final Lock lock = session.getNewClientStreamLock();
      try {
        lock.lock();
        SpdyStream stream =
            session.openStream(
                requestPacketLocal,
                session.getNextLocalStreamId(),
                0,
                0,
                0,
                false,
                !requestPacketLocal.isExpectContent());
        HttpContext.newInstance(ctx, stream, stream, stream);
      } finally {
        lock.unlock();
      }
    }
    HttpTxContext.set(ctx, httpTxContext);
    return sendRequest(sendingCtx, request, requestPacketLocal);
  }
Пример #27
0
 /**
  * Read next chunk of data in this thread, block if needed.
  *
  * @return {@link HttpContent}
  * @throws IOException
  */
 protected HttpContent blockingRead() throws IOException {
   final ReadResult rr = ctx.read();
   final HttpContent c = (HttpContent) rr.getMessage();
   rr.recycle();
   return c;
 }
Пример #28
0
  /**
   * Method invoked when a first massage (Assumed to be HTTP) is received. Normally this would be
   * HTTP CONNECT and this method processes it and opens a connection to the destination (the server
   * that the client wants to access).
   *
   * <p>This method can be overridden to provide a test-specific handling of the CONNECT method.
   */
  protected NextAction handleConnect(FilterChainContext ctx, HttpContent content) {
    System.out.println("Handle CONNECT start . . .");
    HttpHeader httpHeader = content.getHttpHeader();
    HttpRequestPacket requestPacket = (HttpRequestPacket) httpHeader.getHttpHeader();

    if (!requestPacket.getMethod().matchesMethod("CONNECT")) {
      System.out.println("Received method is not CONNECT");
      writeHttpResponse(ctx, 400);
      return ctx.getStopAction();
    }

    String destinationUri = requestPacket.getRequestURI();

    // We expect URI in form host:port, this is not flexible, but we use it only to test our clients
    int colonIdx = destinationUri.indexOf(':');

    if (colonIdx == -1) {
      System.out.println("Destination URI not in host:port format: " + destinationUri);
      writeHttpResponse(ctx, 400);
      return ctx.getStopAction();
    }

    String hostName = destinationUri.substring(0, colonIdx);
    String portStr = destinationUri.substring(colonIdx + 1);

    int port;
    try {
      port = Integer.parseInt(portStr);
    } catch (Throwable t) {
      System.out.println("Could not parse destination port: " + portStr);
      writeHttpResponse(ctx, 400);
      return ctx.getStopAction();
    }

    try {
      Socket tunnelSocket = new Socket(hostName, port);

      Connection grizzlyConnection = ctx.getConnection();
      tunnelSockets.set(grizzlyConnection, tunnelSocket);

      TunnelSocketReader tunnelSocketReader =
          new TunnelSocketReader(tunnelSocket, grizzlyConnection);
      executorService.submit(tunnelSocketReader::read);
    } catch (IOException e) {
      writeHttpResponse(ctx, 400);
      return ctx.getStopAction();
    }

    // Grizzly does not like CONNECT method and sets "keep alive" to false, if it is present
    // This hacks Grizzly, so it will keep the connection open
    HttpRequestPacket request = getHttpRequest(ctx);
    request.getResponse().getProcessingState().setKeepAlive(true);
    request.getResponse().setContentLength(0);
    request.setMethod("GET");
    // end of hack

    writeHttpResponse(ctx, 200);

    System.out.println("Connection to proxy established.");

    return ctx.getStopAction();
  }
Пример #29
0
 private void writeHttpResponse(FilterChainContext ctx, int status) {
   HttpResponsePacket responsePacket = getHttpRequest(ctx).getResponse();
   responsePacket.setProtocol(Protocol.HTTP_1_1);
   responsePacket.setStatus(status);
   ctx.write(HttpContent.builder(responsePacket).build());
 }
Пример #30
0
 private HttpRequestPacket getHttpRequest(FilterChainContext ctx) {
   return (HttpRequestPacket) ((HttpContent) ctx.getMessage()).getHttpHeader();
 }