@Override
  public Result exchangeTerminating(HttpExchange exchange, Result result) {
    if (result.isFailed()) return result;

    HttpResponse response = exchange.getResponse();

    if ((response.getVersion() == HttpVersion.HTTP_1_1)
        && (response.getStatus() == HttpStatus.SWITCHING_PROTOCOLS_101)) {
      String connection = response.getHeaders().get(HttpHeader.CONNECTION);
      if ((connection == null) || !connection.toLowerCase(Locale.US).contains("upgrade")) {
        return new Result(
            result,
            new HttpResponseException(
                "101 Switching Protocols without Connection: Upgrade not supported", response));
      }

      // Upgrade Response
      HttpRequest request = exchange.getRequest();
      if (request instanceof HttpConnectionUpgrader) {
        HttpConnectionUpgrader listener = (HttpConnectionUpgrader) request;
        try {
          listener.upgrade(response, getHttpConnection());
        } catch (Throwable x) {
          return new Result(result, x);
        }
      }
    }

    return result;
  }
  public void setCredentials(HttpExchange exchange) throws IOException {
    StringBuilder buffer = new StringBuilder().append("Digest");

    buffer
        .append(" ")
        .append("username")
        .append('=')
        .append('"')
        .append(securityRealm.getPrincipal())
        .append('"');

    buffer
        .append(", ")
        .append("realm")
        .append('=')
        .append('"')
        .append(String.valueOf(details.get("realm")))
        .append('"');

    buffer
        .append(", ")
        .append("nonce")
        .append('=')
        .append('"')
        .append(String.valueOf(details.get("nonce")))
        .append('"');

    buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"');

    buffer
        .append(", ")
        .append("algorithm")
        .append('=')
        .append(String.valueOf(details.get("algorithm")));

    String cnonce = newCnonce(exchange, securityRealm, details);

    buffer
        .append(", ")
        .append("response")
        .append('=')
        .append('"')
        .append(newResponse(cnonce, exchange, securityRealm, details))
        .append('"');

    buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop")));

    buffer.append(", ").append("nc").append('=').append(NC);

    buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"');

    exchange.setRequestHeader(
        HttpHeaders.AUTHORIZATION, new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1)));
  }
  @Override
  public void exchangeTerminated(HttpExchange exchange, Result result) {
    super.exchangeTerminated(exchange, result);

    Response response = result.getResponse();
    HttpFields responseHeaders = response.getHeaders();

    String closeReason = null;
    if (result.isFailed()) closeReason = "failure";
    else if (receiver.isShutdown()) closeReason = "server close";

    if (closeReason == null) {
      if (response.getVersion().compareTo(HttpVersion.HTTP_1_1) < 0) {
        // HTTP 1.0 must close the connection unless it has
        // an explicit keep alive or it's a CONNECT method.
        boolean keepAlive =
            responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString());
        boolean connect = HttpMethod.CONNECT.is(exchange.getRequest().getMethod());
        if (!keepAlive && !connect) closeReason = "http/1.0";
      } else {
        // HTTP 1.1 or greater closes only if it has an explicit close.
        if (responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()))
          closeReason = "http/1.1";
      }
    }

    if (closeReason != null) {
      if (LOG.isDebugEnabled()) LOG.debug("Closing, reason: {} - {}", closeReason, connection);
      connection.close();
    } else {
      if (response.getStatus() == HttpStatus.SWITCHING_PROTOCOLS_101) connection.remove();
      else release();
    }
  }
 @Override
 protected void send(HttpExchange exchange) {
   normalizeRequest(exchange.getRequest());
   // One connection maps to N channels, so for each exchange we create a new channel
   HttpChannel channel = new HttpChannelOverSPDY(getHttpDestination(), session);
   channel.associate(exchange);
   channel.send();
 }
Example #5
0
 @Override
 protected void expire(HttpDestination destination) {
   try {
     super.expire(destination);
   } catch (IllegalStateException x) {
     _log.debug("On expire: ", x);
     onException(x);
     cancel();
   }
 }
Example #6
0
  @Override
  public void onReply(Stream stream, ReplyInfo replyInfo) {
    HttpExchange exchange = getHttpExchange();
    if (exchange == null) return;

    try {
      HttpResponse response = exchange.getResponse();

      Fields fields = replyInfo.getHeaders();
      short spdy = stream.getSession().getVersion();
      HttpVersion version =
          HttpVersion.fromString(fields.get(HTTPSPDYHeader.VERSION.name(spdy)).getValue());
      response.version(version);
      String[] status = fields.get(HTTPSPDYHeader.STATUS.name(spdy)).getValue().split(" ", 2);

      Integer code = Integer.parseInt(status[0]);
      response.status(code);
      String reason = status.length < 2 ? HttpStatus.getMessage(code) : status[1];
      response.reason(reason);

      if (responseBegin(exchange)) {
        for (Fields.Field field : fields) {
          String name = field.getName();
          if (HTTPSPDYHeader.from(spdy, name) != null) continue;
          // TODO: handle multiple values properly
          HttpField httpField = new HttpField(name, field.getValue());
          responseHeader(exchange, httpField);
        }

        if (responseHeaders(exchange)) {
          if (replyInfo.isClose()) {
            responseSuccess(exchange);
          }
        }
      }
    } catch (Exception x) {
      responseFailure(x);
    }
  }
  @Override
  protected void customizeExchange(HttpExchange exchange, HttpServletRequest request) {
    exchange.addRequestHeader("TB-Tunnel", this.app.getServerIP());
    exchange.addRequestHeader(
        "TB-Credentials", this.app.getClientKey() + "_" + this.app.getClientSecret());
    exchange.addRequestHeader("TB-Tunnel-Version", this.app.getVersion());

    if (this.app.isBypassingSquid()) {
      exchange.addRequestHeader("TB-Tunnel-Port", "2010");
    }

    for (String key : app.getCustomHeaders().keySet()) {
      exchange.addRequestHeader(key, app.getCustomHeaders().get(key));
    }

    Logger.getLogger(ForwarderServlet.class.getName())
        .log(
            Level.INFO,
            " >> [{0}] {1}",
            new Object[] {request.getMethod(), request.getRequestURL()});

    if (app.isDebugMode()) {
      Enumeration<String> headerNames = request.getHeaderNames();
      if (headerNames != null) {
        StringBuilder sb = new StringBuilder();
        String header;

        while (headerNames.hasMoreElements()) {
          header = headerNames.nextElement();
          sb.append(header)
              .append(": ")
              .append(request.getHeader(header))
              .append(System.getProperty("line.separator"));
        }
        Logger.getLogger(ForwarderServlet.class.getName()).log(Level.INFO, sb.toString());
      }
    }
  }
  protected String newResponse(
      String cnonce, HttpExchange exchange, Realm securityRealm, Map details) {
    try {
      MessageDigest md = MessageDigest.getInstance("MD5");

      // calc A1 digest
      md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1));
      byte[] ha1 = md.digest();
      // calc A2 digest
      md.reset();
      md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1));
      byte[] ha2 = md.digest();

      md.update(TypeUtil.toString(ha1, 16).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(NC.getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(TypeUtil.toString(ha2, 16).getBytes(StringUtil.__ISO_8859_1));
      byte[] digest = md.digest();

      // check digest
      return encode(digest);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
    @Override
    protected void send(HttpExchange exchange) {
      Request request = exchange.getRequest();
      normalizeRequest(request);

      // Save the old idle timeout to restore it
      EndPoint endPoint = getEndPoint();
      idleTimeout = endPoint.getIdleTimeout();
      endPoint.setIdleTimeout(request.getIdleTimeout());

      // One channel per connection, just delegate the send
      if (channel.associate(exchange)) channel.send();
      else channel.release();
    }
Example #10
0
 @Override
 protected void onRetry() throws IOException {
   super.onRetry();
 }
  @Override
  protected void sendHeaders(HttpExchange exchange, HttpContent content, Callback callback) {
    Request request = exchange.getRequest();
    ContentProvider requestContent = request.getContent();
    long contentLength = requestContent == null ? -1 : requestContent.getLength();
    String path = request.getPath();
    String query = request.getQuery();
    if (query != null) path += "?" + query;
    HttpGenerator.RequestInfo requestInfo =
        new HttpGenerator.RequestInfo(
            request.getVersion(), request.getHeaders(), contentLength, request.getMethod(), path);

    try {
      HttpClient client = getHttpChannel().getHttpDestination().getHttpClient();
      ByteBufferPool bufferPool = client.getByteBufferPool();
      ByteBuffer header = bufferPool.acquire(client.getRequestBufferSize(), false);
      ByteBuffer chunk = null;

      ByteBuffer contentBuffer = null;
      boolean lastContent = false;
      if (!expects100Continue(request)) {
        content.advance();
        contentBuffer = content.getByteBuffer();
        lastContent = content.isLast();
      }
      while (true) {
        HttpGenerator.Result result =
            generator.generateRequest(requestInfo, header, chunk, contentBuffer, lastContent);
        switch (result) {
          case NEED_CHUNK:
            {
              chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
              break;
            }
          case FLUSH:
            {
              int size = 1;
              boolean hasChunk = chunk != null;
              if (hasChunk) ++size;
              boolean hasContent = contentBuffer != null;
              if (hasContent) ++size;
              ByteBuffer[] toWrite = new ByteBuffer[size];
              ByteBuffer[] toRecycle = new ByteBuffer[hasChunk ? 2 : 1];
              toWrite[0] = header;
              toRecycle[0] = header;
              if (hasChunk) {
                toWrite[1] = chunk;
                toRecycle[1] = chunk;
              }
              if (hasContent) toWrite[toWrite.length - 1] = contentBuffer;
              EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
              endPoint.write(
                  new ByteBufferRecyclerCallback(callback, bufferPool, toRecycle), toWrite);
              return;
            }
          default:
            {
              throw new IllegalStateException();
            }
        }
      }
    } catch (Exception x) {
      LOG.debug(x);
      callback.failed(x);
    }
  }
 protected void setAccessToken(HttpExchange httpExchange) {
   httpExchange.setRequestHeader(TOKEN_HEADER, TOKEN_PREFIX + accessToken);
 }
Example #13
0
 /**
  * BASIC proxy authentication is of the form
  *
  * <p>encoded credentials are of the form: username:password
  */
 public void setCredentials(HttpExchange exchange) throws IOException {
   exchange.setRequestHeader(HttpHeaders.PROXY_AUTHORIZATION_BUFFER, _authorization);
 }
 protected boolean abort(Throwable failure) {
   HttpExchange exchange = channel.getHttpExchange();
   return exchange != null && exchange.getRequest().abort(failure);
 }
Example #15
0
 @Override
 public void onFailure(Stream stream, Throwable x) {
   HttpExchange exchange = getHttpExchange();
   if (exchange == null) return;
   exchange.getRequest().abort(x);
 }