SPDY: fix for mozilla firefox bug 754766
This commit is contained in:
parent
69d5be4225
commit
f60997686d
@ -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 io.netty.handler.codec.spdy;
|
||||
|
||||
import io.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();
|
||||
}
|
||||
}
|
@ -115,6 +115,26 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
||||
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:
|
||||
@ -343,13 +363,14 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -375,6 +396,17 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
||||
|
||||
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.");
|
||||
}
|
||||
@ -622,6 +654,8 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
||||
return length == 4 || length >= 8;
|
||||
|
||||
case SPDY_WINDOW_UPDATE_FRAME:
|
||||
return length == 8;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@ -636,10 +670,10 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
||||
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;
|
||||
}
|
||||
|
@ -231,6 +231,18 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
||||
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
|
||||
|
@ -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 io.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);
|
||||
}
|
@ -47,7 +47,7 @@ import org.junit.Test;
|
||||
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;
|
||||
@ -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 ++) {
|
||||
@ -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);
|
||||
@ -92,7 +92,7 @@ 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
|
||||
@ -100,7 +100,7 @@ public abstract class AbstractSocketSpdyEchoTest {
|
||||
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
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user