Skip to content

Commit

Permalink
SPDY: fix for mozilla firefox bug 754766
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Pinner authored and trustin committed May 17, 2012
1 parent 0136cba commit ba76d5b
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 8 deletions.
@@ -0,0 +1,76 @@
/*
* 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.
*/
package org.jboss.netty.handler.codec.spdy;

import org.jboss.netty.util.internal.StringUtil;

/**
* The default {@link SpdyWindowUpdateFrame} implementation.
*/
public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame {

private int streamID;
private int deltaWindowSize;

/**
* Creates a new instance.
*
* @param streamID the Stream-ID of this frame
* @param deltaWindowSize the Delta-Window-Size of this frame
*/
public DefaultSpdyWindowUpdateFrame(int streamID, int deltaWindowSize) {
setStreamID(streamID);
setDeltaWindowSize(deltaWindowSize);
}

public int getStreamID() {
return streamID;
}

public void setStreamID(int streamID) {
if (streamID <= 0) {
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamID);
}
this.streamID = streamID;
}

public int getDeltaWindowSize() {
return deltaWindowSize;
}

public void setDeltaWindowSize(int deltaWindowSize) {
if (deltaWindowSize <= 0) {
throw new IllegalArgumentException(
"Delta-Window-Size must be positive: " +
deltaWindowSize);
}
this.deltaWindowSize = deltaWindowSize;
}

@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(getClass().getSimpleName());
buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = ");
buf.append(streamID);
buf.append(StringUtil.NEWLINE);
buf.append("--> Delta-Window-Size = ");
buf.append(deltaWindowSize);
return buf.toString();
}
}
Expand Up @@ -123,6 +123,26 @@ protected Object decode(
fireInvalidControlFrameException(ctx);
}
}

// FrameDecoders must consume data when producing frames
// All length 0 frames must be generated now
if (length == 0) {
if (state == State.READ_DATA_FRAME) {
if (streamID == 0) {
state = State.FRAME_ERROR;
fireProtocolException(ctx, "Received invalid data frame");
return null;
}

SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(streamID);
spdyDataFrame.setLast((flags & SPDY_DATA_FLAG_FIN) != 0);
state = State.READ_COMMON_HEADER;
return spdyDataFrame;
}
// There are no length 0 control frames
state = State.READ_COMMON_HEADER;
}

return null;

case READ_CONTROL_FRAME:
Expand Down Expand Up @@ -351,13 +371,14 @@ private State readCommonHeader(ChannelBuffer buffer) {
}

private Object readControlFrame(ChannelBuffer buffer) {
int streamID;
switch (type) {
case SPDY_RST_STREAM_FRAME:
if (buffer.readableBytes() < 8) {
return null;
}

int streamID = getUnsignedInt(buffer, buffer.readerIndex());
streamID = getUnsignedInt(buffer, buffer.readerIndex());
int statusCode = getSignedInt(buffer, buffer.readerIndex() + 4);
buffer.skipBytes(8);

Expand All @@ -383,6 +404,17 @@ private Object readControlFrame(ChannelBuffer buffer) {

return new DefaultSpdyGoAwayFrame(lastGoodStreamID);

case SPDY_WINDOW_UPDATE_FRAME:
if (buffer.readableBytes() < 8) {
return null;
}

streamID = getUnsignedInt(buffer, buffer.readerIndex());
int deltaWindowSize = getUnsignedInt(buffer, buffer.readerIndex() + 4);
buffer.skipBytes(8);

return new DefaultSpdyWindowUpdateFrame(streamID, deltaWindowSize);

default:
throw new Error("Shouldn't reach here.");
}
Expand Down Expand Up @@ -630,6 +662,8 @@ private boolean isValidControlFrameHeader() {
return length == 4 || length >= 8;

case SPDY_WINDOW_UPDATE_FRAME:
return length == 8;

default:
return true;
}
Expand All @@ -644,10 +678,10 @@ private boolean willGenerateControlFrame() {
case SPDY_PING_FRAME:
case SPDY_GOAWAY_FRAME:
case SPDY_HEADERS_FRAME:
case SPDY_WINDOW_UPDATE_FRAME:
return true;

case SPDY_NOOP_FRAME:
case SPDY_WINDOW_UPDATE_FRAME:
default:
return false;
}
Expand Down
Expand Up @@ -231,6 +231,18 @@ protected Object encode(
frame.writeShort(0);
}
return ChannelBuffers.wrappedBuffer(frame, data);

} else if (msg instanceof SpdyWindowUpdateFrame) {

SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg;
ChannelBuffer frame = ChannelBuffers.buffer(
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + 8);
frame.writeShort(SPDY_VERSION | 0x8000);
frame.writeShort(SPDY_WINDOW_UPDATE_FRAME);
frame.writeInt(8);
frame.writeInt(spdyWindowUpdateFrame.getStreamID());
frame.writeInt(spdyWindowUpdateFrame.getDeltaWindowSize());
return frame;
}

// Unknown message type
Expand Down
@@ -0,0 +1,43 @@
/*
* 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.
*/
package org.jboss.netty.handler.codec.spdy;

/**
* A SPDY Protocol WINDOW_UPDATE Control Frame
*/
public interface SpdyWindowUpdateFrame {

/**
* Returns the Stream-ID of this frame.
*/
int getStreamID();

/**
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
*/
void setStreamID(int streamID);

/**
* Returns the Delta-Window-Size of this frame.
*/
int getDeltaWindowSize();

/**
* Sets the Delta-Window-Size of this frame.
* The Delta-Window-Size must be positive.
*/
void setDeltaWindowSize(int deltaWindowSize);
}
Expand Up @@ -47,7 +47,7 @@
public abstract class AbstractSocketSpdyEchoTest {

private static final Random random = new Random();
static final ChannelBuffer frames = ChannelBuffers.buffer(1160);
static final ChannelBuffer frames = ChannelBuffers.buffer(1176);
static final int ignoredBytes = 20;

private static ExecutorService executor;
Expand All @@ -68,7 +68,7 @@ public abstract class AbstractSocketSpdyEchoTest {
frames.writeInt(0);

// SPDY Data Frame
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
frames.writeByte(0x01);
frames.writeMedium(1024);
for (int i = 0; i < 256; i ++) {
Expand All @@ -81,7 +81,7 @@ public abstract class AbstractSocketSpdyEchoTest {
frames.writeShort(1);
frames.writeByte(0x03);
frames.writeMedium(12);
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeShort(0x8000);
frames.writeShort(0);
Expand All @@ -92,15 +92,15 @@ public abstract class AbstractSocketSpdyEchoTest {
frames.writeShort(2);
frames.writeByte(0x01);
frames.writeMedium(8);
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
frames.writeInt(0);

// SPDY RST_STREAM Frame
frames.writeByte(0x80);
frames.writeByte(2);
frames.writeShort(3);
frames.writeInt(8);
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
frames.writeInt(random.nextInt() | 0x01);

// SPDY SETTINGS Frame
Expand Down Expand Up @@ -133,7 +133,15 @@ public abstract class AbstractSocketSpdyEchoTest {
frames.writeByte(2);
frames.writeShort(8);
frames.writeInt(4);
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);

// SPDY WINDOW_UPDATE Frame
frames.writeByte(0x80);
frames.writeByte(2);
frames.writeShort(9);
frames.writeInt(8);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
}

@BeforeClass
Expand Down

0 comments on commit ba76d5b

Please sign in to comment.