Skip to content

Commit

Permalink
merge upstream master
Browse files Browse the repository at this point in the history
  • Loading branch information
jestan committed Feb 19, 2012
2 parents 4b99c4f + 479def2 commit 20d7379
Show file tree
Hide file tree
Showing 54 changed files with 1,509 additions and 314 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,22 @@ public QueryStringDecoder(URI uri, Charset charset, int maxParams) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}

String rawPath = uri.getRawPath();
if (rawPath != null) {
hasPath = true;
} else {
rawPath ="";
hasPath = false;
}
// Also take care of cut of things like "http://localhost"
String newUri = rawPath + "?" + uri.getRawQuery();

// http://en.wikipedia.org/wiki/Query_string
this.uri = uri.toASCIIString().replace(';', '&');
this.uri = newUri.replace(';', '&');
this.charset = charset;
this.maxParams = maxParams;
hasPath = false;

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ static int getSignedInt(ChannelBuffer buf, int offset) {
(buf.getByte(offset + 3) & 0xFF));
}

/**
* Returns {@code true} if ID is for a server initiated stream or ping.
*/
static boolean isServerID(int ID) {
// Server initiated streams and pings have even IDs
return ID % 2 == 0;
}

/**
* Validate a SPDY header name.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,27 @@
public class SpdyFrameCodec implements ChannelUpstreamHandler,
ChannelDownstreamHandler {

private final SpdyFrameDecoder decoder = new SpdyFrameDecoder();
private final SpdyFrameEncoder encoder = new SpdyFrameEncoder();
private final SpdyFrameDecoder decoder;
private final SpdyFrameEncoder encoder;

/**
* Creates a new instance with the default decoder and encoder options
* ({@code maxChunkSize (8192)}, {@code maxFrameSize (65536)},
* {@code maxHeaderSize (16384)}, {@code compressionLevel (6)},
* {@code windowBits (15)}, and {@code memLevel (8)}).
*/
public SpdyFrameCodec() {
this(8192, 65536, 16384, 6, 15, 8);
}

/**
* Creates a new instance with the specified decoder and encoder options.
*/
public SpdyFrameCodec(
int maxChunkSize, int maxFrameSize, int maxHeaderSize,
int compressionLevel, int windowBits, int memLevel) {
decoder = new SpdyFrameDecoder(maxChunkSize, maxFrameSize, maxHeaderSize);
encoder = new SpdyFrameEncoder(compressionLevel, windowBits, memLevel);
}

public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,42 @@
*/
public class SpdyFrameDecoder extends FrameDecoder {

private final int maxChunkSize;
private final int maxFrameSize;
private final int maxHeaderSize;

private final DecoderEmbedder<ChannelBuffer> headerBlockDecompressor =
new DecoderEmbedder<ChannelBuffer>(new ZlibDecoder(SPDY_DICT));

/**
* Creates a new instance with the default {@code maxChunkSize (8192)},
* {@code maxFrameSize (65536)}, and {@code maxHeaderSize (16384)}.
*/
public SpdyFrameDecoder() {
super();
this(8192, 65536, 16384);
}

/**
* Creates a new instance with the specified parameters.
*/
public SpdyFrameDecoder(
int maxChunkSize, int maxFrameSize, int maxHeaderSize) {
super(true); // Enable unfold for data frames
if (maxChunkSize <= 0) {
throw new IllegalArgumentException(
"maxChunkSize must be a positive integer: " + maxChunkSize);
}
if (maxFrameSize <= 0) {
throw new IllegalArgumentException(
"maxFrameSize must be a positive integer: " + maxFrameSize);
}
if (maxHeaderSize <= 0) {
throw new IllegalArgumentException(
"maxHeaderSize must be a positive integer: " + maxHeaderSize);
}
this.maxChunkSize = maxChunkSize;
this.maxFrameSize = maxFrameSize;
this.maxHeaderSize = maxHeaderSize;
}

@Override
Expand All @@ -67,6 +98,12 @@ protected Object decode(
int dataLength = getUnsignedMedium(buffer, lengthOffset);
int frameLength = SPDY_HEADER_SIZE + dataLength;

// Throw exception if frameLength exceeds maxFrameSize
if (frameLength > maxFrameSize) {
throw new SpdyProtocolException(
"Frame length exceeds " + maxFrameSize + ": " + frameLength);
}

// Wait until entire frame is readable
if (buffer.readableBytes() < frameLength) {
return null;
Expand Down Expand Up @@ -98,12 +135,25 @@ protected Object decode(
int streamID = getUnsignedInt(buffer, frameOffset);
buffer.skipBytes(SPDY_HEADER_SIZE);

SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(streamID);
spdyDataFrame.setLast((flags & SPDY_DATA_FLAG_FIN) != 0);
spdyDataFrame.setCompressed((flags & SPDY_DATA_FLAG_COMPRESS) != 0);
spdyDataFrame.setData(buffer.readBytes(dataLength));
// Generate data frames that do not exceed maxChunkSize
int numFrames = dataLength / maxChunkSize;
if (dataLength % maxChunkSize != 0) {
numFrames ++;
}
SpdyDataFrame[] frames = new SpdyDataFrame[numFrames];
for (int i = 0; i < numFrames; i++) {
int chunkSize = Math.min(maxChunkSize, dataLength);
SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(streamID);
spdyDataFrame.setCompressed((flags & SPDY_DATA_FLAG_COMPRESS) != 0);
spdyDataFrame.setData(buffer.readBytes(chunkSize));
dataLength -= chunkSize;
if (dataLength == 0) {
spdyDataFrame.setLast((flags & SPDY_DATA_FLAG_FIN) != 0);
}
frames[i] = spdyDataFrame;
}

return spdyDataFrame;
return frames;
}
}

Expand Down Expand Up @@ -276,6 +326,7 @@ private void decodeHeaderBlock(SpdyHeaderBlock headerFrame, ChannelBuffer header
throw new SpdyProtocolException(
"Received invalid header block");
}
int headerSize = 0;
int numEntries = getUnsignedShort(headerBlock, headerBlock.readerIndex());
headerBlock.skipBytes(2);
for (int i = 0; i < numEntries; i ++) {
Expand All @@ -289,6 +340,11 @@ private void decodeHeaderBlock(SpdyHeaderBlock headerFrame, ChannelBuffer header
headerFrame.setInvalid();
return;
}
headerSize += nameLength;
if (headerSize > maxHeaderSize) {
throw new SpdyProtocolException(
"Header block exceeds " + maxHeaderSize);
}
if (headerBlock.readableBytes() < nameLength) {
throw new SpdyProtocolException(
"Received invalid header block");
Expand All @@ -310,6 +366,11 @@ private void decodeHeaderBlock(SpdyHeaderBlock headerFrame, ChannelBuffer header
headerFrame.setInvalid();
return;
}
headerSize += valueLength;
if (headerSize > maxHeaderSize) {
throw new SpdyProtocolException(
"Header block exceeds " + maxHeaderSize);
}
if (headerBlock.readableBytes() < valueLength) {
throw new SpdyProtocolException(
"Received invalid header block");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,23 @@
*/
public class SpdyFrameEncoder extends OneToOneEncoder {

private final EncoderEmbedder<ChannelBuffer> headerBlockCompressor =
new EncoderEmbedder<ChannelBuffer>(new ZlibEncoder(9, SPDY_DICT));
private final EncoderEmbedder<ChannelBuffer> headerBlockCompressor;

/**
* Creates a new instance with the default {@code compressionLevel (6)},
* {@code windowBits (15)}, and {@code memLevel (8)}.
*/
public SpdyFrameEncoder() {
this(6, 15, 8);
}

/**
* Creates a new instance with the specified parameters.
*/
public SpdyFrameEncoder(int compressionLevel, int windowBits, int memLevel) {
super();
headerBlockCompressor = new EncoderEmbedder<ChannelBuffer>(
new ZlibEncoder(compressionLevel, windowBits, memLevel, SPDY_DICT));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/*
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.netty.handler.codec.spdy;

import io.netty.channel.ChannelDownstreamHandler;
import io.netty.channel.ChannelEvent;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelUpstreamHandler;

/**
* A combination of {@link SpdyHttpDecoder} and {@link SpdyHttpEncoder}
* @apiviz.has io.netty.handler.codec.sdpy.SpdyHttpDecoder
* @apiviz.has io.netty.handler.codec.spdy.SpdyHttpEncoder
*/
public class SpdyHttpCodec implements ChannelUpstreamHandler, ChannelDownstreamHandler {

private final SpdyHttpDecoder decoder;
private final SpdyHttpEncoder encoder = new SpdyHttpEncoder();

/**
* Creates a new instance with the specified decoder options.
*/
public SpdyHttpCodec(int maxContentLength) {
decoder = new SpdyHttpDecoder(maxContentLength);
}

public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
decoder.handleUpstream(ctx, e);
}

public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
encoder.handleDownstream(ctx, e);
}
}
Loading

0 comments on commit 20d7379

Please sign in to comment.