private SpdyHeadersFrame readHeaderBlockFrame(ByteBuf buffer) {
    int streamId;
    switch (type) {
      case SPDY_SYN_STREAM_FRAME:
        if (buffer.readableBytes() < 10) {
          return null;
        }

        int offset = buffer.readerIndex();
        streamId = getUnsignedInt(buffer, offset);
        int associatedToStreamId = getUnsignedInt(buffer, offset + 4);
        byte priority = (byte) (buffer.getByte(offset + 8) >> 5 & 0x07);
        buffer.skipBytes(10);
        length -= 10;

        SpdySynStreamFrame spdySynStreamFrame =
            new DefaultSpdySynStreamFrame(streamId, associatedToStreamId, priority);
        spdySynStreamFrame.setLast((flags & SPDY_FLAG_FIN) != 0);
        spdySynStreamFrame.setUnidirectional((flags & SPDY_FLAG_UNIDIRECTIONAL) != 0);

        return spdySynStreamFrame;

      case SPDY_SYN_REPLY_FRAME:
        if (buffer.readableBytes() < 4) {
          return null;
        }

        streamId = getUnsignedInt(buffer, buffer.readerIndex());
        buffer.skipBytes(4);
        length -= 4;

        SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId);
        spdySynReplyFrame.setLast((flags & SPDY_FLAG_FIN) != 0);

        return spdySynReplyFrame;

      case SPDY_HEADERS_FRAME:
        if (buffer.readableBytes() < 4) {
          return null;
        }

        streamId = getUnsignedInt(buffer, buffer.readerIndex());
        buffer.skipBytes(4);
        length -= 4;

        SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(streamId);
        spdyHeadersFrame.setLast((flags & SPDY_FLAG_FIN) != 0);

        return spdyHeadersFrame;

      default:
        throw new Error("Shouldn't reach here.");
    }
  }
Exemplo n.º 2
0
  private SpdySynStreamFrame createSynStreamFrame(HttpMessage httpMessage) throws Exception {
    boolean chunked = httpMessage.isChunked();

    // Get the Stream-ID, Associated-To-Stream-ID, Priority, URL, and scheme from the headers
    int streamID = SpdyHttpHeaders.getStreamID(httpMessage);
    int associatedToStreamID = SpdyHttpHeaders.getAssociatedToStreamID(httpMessage);
    byte priority = SpdyHttpHeaders.getPriority(httpMessage);
    String URL = SpdyHttpHeaders.getUrl(httpMessage);
    String scheme = SpdyHttpHeaders.getScheme(httpMessage);
    SpdyHttpHeaders.removeStreamID(httpMessage);
    SpdyHttpHeaders.removeAssociatedToStreamID(httpMessage);
    SpdyHttpHeaders.removePriority(httpMessage);
    SpdyHttpHeaders.removeUrl(httpMessage);
    SpdyHttpHeaders.removeScheme(httpMessage);

    // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
    // headers are not valid and MUST not be sent.
    httpMessage.removeHeader(HttpHeaders.Names.CONNECTION);
    httpMessage.removeHeader("Keep-Alive");
    httpMessage.removeHeader("Proxy-Connection");
    httpMessage.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);

    SpdySynStreamFrame spdySynStreamFrame =
        new DefaultSpdySynStreamFrame(streamID, associatedToStreamID, priority);

    // Unfold the first line of the message into name/value pairs
    if (httpMessage instanceof HttpRequest) {
      HttpRequest httpRequest = (HttpRequest) httpMessage;
      SpdyHeaders.setMethod(spdyVersion, spdySynStreamFrame, httpRequest.getMethod());
      SpdyHeaders.setUrl(spdyVersion, spdySynStreamFrame, httpRequest.getUri());
      SpdyHeaders.setVersion(spdyVersion, spdySynStreamFrame, httpMessage.getProtocolVersion());
    }
    if (httpMessage instanceof HttpResponse) {
      HttpResponse httpResponse = (HttpResponse) httpMessage;
      SpdyHeaders.setStatus(spdyVersion, spdySynStreamFrame, httpResponse.getStatus());
      SpdyHeaders.setUrl(spdyVersion, spdySynStreamFrame, URL);
      spdySynStreamFrame.setUnidirectional(true);
    }

    // Replace the HTTP host header with the SPDY host header
    if (spdyVersion >= 3) {
      String host = HttpHeaders.getHost(httpMessage);
      httpMessage.removeHeader(HttpHeaders.Names.HOST);
      SpdyHeaders.setHost(spdySynStreamFrame, host);
    }

    // Set the SPDY scheme header
    if (scheme == null) {
      scheme = "https";
    }
    SpdyHeaders.setScheme(spdyVersion, spdySynStreamFrame, scheme);

    // Transfer the remaining HTTP headers
    for (Map.Entry<String, String> entry : httpMessage.getHeaders()) {
      spdySynStreamFrame.addHeader(entry.getKey(), entry.getValue());
    }

    if (chunked) {
      currentStreamID = streamID;
      spdySynStreamFrame.setLast(false);
    } else {
      spdySynStreamFrame.setLast(httpMessage.getContent().readableBytes() == 0);
    }

    return spdySynStreamFrame;
  }
Exemplo n.º 3
0
  private static void testSpdySessionHandler(SpdyVersion version, boolean server) {
    EmbeddedChannel sessionHandler =
        new EmbeddedChannel(
            new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server));

    while (sessionHandler.readOutbound() != null) {
      continue;
    }

    int localStreamId = server ? 1 : 2;
    int remoteStreamId = server ? 2 : 1;

    SpdySynStreamFrame spdySynStreamFrame =
        new DefaultSpdySynStreamFrame(localStreamId, 0, (byte) 0);
    spdySynStreamFrame.headers().set("Compression", "test");

    SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamId);
    spdyDataFrame.setLast(true);

    // Check if session handler returns INVALID_STREAM if it receives
    // a data frame for a Stream-ID that is not open
    sessionHandler.writeInbound(new DefaultSpdyDataFrame(localStreamId));
    assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.INVALID_STREAM);
    assertNull(sessionHandler.readOutbound());

    // Check if session handler returns PROTOCOL_ERROR if it receives
    // a data frame for a Stream-ID before receiving a SYN_REPLY frame
    sessionHandler.writeInbound(new DefaultSpdyDataFrame(remoteStreamId));
    assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
    assertNull(sessionHandler.readOutbound());
    remoteStreamId += 2;

    // Check if session handler returns PROTOCOL_ERROR if it receives
    // multiple SYN_REPLY frames for the same active Stream-ID
    sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId));
    assertNull(sessionHandler.readOutbound());
    sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId));
    assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.STREAM_IN_USE);
    assertNull(sessionHandler.readOutbound());
    remoteStreamId += 2;

    // Check if frame codec correctly compresses/uncompresses headers
    sessionHandler.writeInbound(spdySynStreamFrame);
    assertSynReply(
        sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers());
    assertNull(sessionHandler.readOutbound());
    SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamId);

    spdyHeadersFrame.headers().add("HEADER", "test1");
    spdyHeadersFrame.headers().add("HEADER", "test2");

    sessionHandler.writeInbound(spdyHeadersFrame);
    assertHeaders(sessionHandler.readOutbound(), localStreamId, false, spdyHeadersFrame.headers());
    assertNull(sessionHandler.readOutbound());
    localStreamId += 2;

    // Check if session handler closed the streams using the number
    // of concurrent streams and that it returns REFUSED_STREAM
    // if it receives a SYN_STREAM frame it does not wish to accept
    spdySynStreamFrame.setStreamId(localStreamId);
    spdySynStreamFrame.setLast(true);
    spdySynStreamFrame.setUnidirectional(true);

    sessionHandler.writeInbound(spdySynStreamFrame);
    assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM);
    assertNull(sessionHandler.readOutbound());

    // Check if session handler rejects HEADERS for closed streams
    int testStreamId = spdyDataFrame.getStreamId();
    sessionHandler.writeInbound(spdyDataFrame);
    assertDataFrame(sessionHandler.readOutbound(), testStreamId, spdyDataFrame.isLast());
    assertNull(sessionHandler.readOutbound());
    spdyHeadersFrame.setStreamId(testStreamId);

    sessionHandler.writeInbound(spdyHeadersFrame);
    assertRstStream(sessionHandler.readOutbound(), testStreamId, SpdyStreamStatus.INVALID_STREAM);
    assertNull(sessionHandler.readOutbound());

    // Check if session handler drops active streams if it receives
    // a RST_STREAM frame for that Stream-ID
    sessionHandler.writeInbound(new DefaultSpdyRstStreamFrame(remoteStreamId, 3));
    assertNull(sessionHandler.readOutbound());
    remoteStreamId += 2;

    // Check if session handler honors UNIDIRECTIONAL streams
    spdySynStreamFrame.setLast(false);
    sessionHandler.writeInbound(spdySynStreamFrame);
    assertNull(sessionHandler.readOutbound());
    spdySynStreamFrame.setUnidirectional(false);

    // Check if session handler returns PROTOCOL_ERROR if it receives
    // multiple SYN_STREAM frames for the same active Stream-ID
    sessionHandler.writeInbound(spdySynStreamFrame);
    assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
    assertNull(sessionHandler.readOutbound());
    localStreamId += 2;

    // Check if session handler returns PROTOCOL_ERROR if it receives
    // a SYN_STREAM frame with an invalid Stream-ID
    spdySynStreamFrame.setStreamId(localStreamId - 1);
    sessionHandler.writeInbound(spdySynStreamFrame);
    assertRstStream(
        sessionHandler.readOutbound(), localStreamId - 1, SpdyStreamStatus.PROTOCOL_ERROR);
    assertNull(sessionHandler.readOutbound());
    spdySynStreamFrame.setStreamId(localStreamId);

    // Check if session handler returns PROTOCOL_ERROR if it receives
    // an invalid HEADERS frame
    spdyHeadersFrame.setStreamId(localStreamId);

    spdyHeadersFrame.setInvalid();
    sessionHandler.writeInbound(spdyHeadersFrame);
    assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
    assertNull(sessionHandler.readOutbound());

    sessionHandler.finish();
  }
Exemplo n.º 4
0
  @SuppressWarnings("deprecation")
  private SpdySynStreamFrame createSynStreamFrame(HttpMessage httpMessage) throws Exception {
    // Get the Stream-ID, Associated-To-Stream-ID, Priority, URL, and scheme from the headers
    final HttpHeaders httpHeaders = httpMessage.headers();
    int streamID = httpHeaders.getInt(Names.STREAM_ID);
    int associatedToStreamId = httpHeaders.getInt(Names.ASSOCIATED_TO_STREAM_ID, 0);
    byte priority = (byte) httpHeaders.getInt(Names.PRIORITY, 0);
    String URL = httpHeaders.get(Names.URL);
    String scheme = httpHeaders.get(Names.SCHEME);
    httpHeaders.remove(Names.STREAM_ID);
    httpHeaders.remove(Names.ASSOCIATED_TO_STREAM_ID);
    httpHeaders.remove(Names.PRIORITY);
    httpHeaders.remove(Names.URL);
    httpHeaders.remove(Names.SCHEME);

    // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
    // headers are not valid and MUST not be sent.
    httpHeaders.remove(HttpHeaders.Names.CONNECTION);
    httpHeaders.remove(HttpHeaders.Names.KEEP_ALIVE);
    httpHeaders.remove(HttpHeaders.Names.PROXY_CONNECTION);
    httpHeaders.remove(HttpHeaders.Names.TRANSFER_ENCODING);

    SpdySynStreamFrame spdySynStreamFrame =
        new DefaultSpdySynStreamFrame(streamID, associatedToStreamId, priority);

    // Unfold the first line of the message into name/value pairs
    SpdyHeaders frameHeaders = spdySynStreamFrame.headers();
    if (httpMessage instanceof FullHttpRequest) {
      HttpRequest httpRequest = (HttpRequest) httpMessage;
      frameHeaders.set(METHOD, httpRequest.method());
      frameHeaders.set(PATH, httpRequest.uri());
      frameHeaders.set(VERSION, httpMessage.protocolVersion());
    }
    if (httpMessage instanceof HttpResponse) {
      HttpResponse httpResponse = (HttpResponse) httpMessage;
      frameHeaders.set(STATUS, httpResponse.status());
      frameHeaders.set(PATH, URL);
      frameHeaders.set(VERSION, httpMessage.protocolVersion());
      spdySynStreamFrame.setUnidirectional(true);
    }

    // Replace the HTTP host header with the SPDY host header
    if (spdyVersion >= 3) {
      CharSequence host = httpHeaders.getUnconverted(HttpHeaders.Names.HOST);
      httpHeaders.remove(HttpHeaders.Names.HOST);
      frameHeaders.set(HOST, host);
    }

    // Set the SPDY scheme header
    if (scheme == null) {
      scheme = "https";
    }
    frameHeaders.set(SCHEME, scheme);

    // Transfer the remaining HTTP headers
    for (Map.Entry<String, String> entry : httpHeaders) {
      frameHeaders.add(entry.getKey(), entry.getValue());
    }
    currentStreamId = spdySynStreamFrame.streamId();
    spdySynStreamFrame.setLast(isLast(httpMessage));

    return spdySynStreamFrame;
  }