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);
|
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;
|
return null;
|
||||||
|
|
||||||
case READ_CONTROL_FRAME:
|
case READ_CONTROL_FRAME:
|
||||||
@ -343,13 +363,14 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object readControlFrame(ChannelBuffer buffer) {
|
private Object readControlFrame(ChannelBuffer buffer) {
|
||||||
|
int streamID;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SPDY_RST_STREAM_FRAME:
|
case SPDY_RST_STREAM_FRAME:
|
||||||
if (buffer.readableBytes() < 8) {
|
if (buffer.readableBytes() < 8) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int streamID = getUnsignedInt(buffer, buffer.readerIndex());
|
streamID = getUnsignedInt(buffer, buffer.readerIndex());
|
||||||
int statusCode = getSignedInt(buffer, buffer.readerIndex() + 4);
|
int statusCode = getSignedInt(buffer, buffer.readerIndex() + 4);
|
||||||
buffer.skipBytes(8);
|
buffer.skipBytes(8);
|
||||||
|
|
||||||
@ -375,6 +396,17 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
|
|
||||||
return new DefaultSpdyGoAwayFrame(lastGoodStreamID);
|
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:
|
default:
|
||||||
throw new Error("Shouldn't reach here.");
|
throw new Error("Shouldn't reach here.");
|
||||||
}
|
}
|
||||||
@ -622,6 +654,8 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
return length == 4 || length >= 8;
|
return length == 4 || length >= 8;
|
||||||
|
|
||||||
case SPDY_WINDOW_UPDATE_FRAME:
|
case SPDY_WINDOW_UPDATE_FRAME:
|
||||||
|
return length == 8;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -636,10 +670,10 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
case SPDY_PING_FRAME:
|
case SPDY_PING_FRAME:
|
||||||
case SPDY_GOAWAY_FRAME:
|
case SPDY_GOAWAY_FRAME:
|
||||||
case SPDY_HEADERS_FRAME:
|
case SPDY_HEADERS_FRAME:
|
||||||
|
case SPDY_WINDOW_UPDATE_FRAME:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SPDY_NOOP_FRAME:
|
case SPDY_NOOP_FRAME:
|
||||||
case SPDY_WINDOW_UPDATE_FRAME:
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,18 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
frame.writeShort(0);
|
frame.writeShort(0);
|
||||||
}
|
}
|
||||||
return ChannelBuffers.wrappedBuffer(frame, data);
|
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
|
// 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 {
|
public abstract class AbstractSocketSpdyEchoTest {
|
||||||
|
|
||||||
private static final Random random = new Random();
|
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;
|
static final int ignoredBytes = 20;
|
||||||
|
|
||||||
private static ExecutorService executor;
|
private static ExecutorService executor;
|
||||||
@ -68,7 +68,7 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeInt(0);
|
frames.writeInt(0);
|
||||||
|
|
||||||
// SPDY Data Frame
|
// SPDY Data Frame
|
||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
|
||||||
frames.writeByte(0x01);
|
frames.writeByte(0x01);
|
||||||
frames.writeMedium(1024);
|
frames.writeMedium(1024);
|
||||||
for (int i = 0; i < 256; i ++) {
|
for (int i = 0; i < 256; i ++) {
|
||||||
@ -81,7 +81,7 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeShort(1);
|
frames.writeShort(1);
|
||||||
frames.writeByte(0x03);
|
frames.writeByte(0x03);
|
||||||
frames.writeMedium(12);
|
frames.writeMedium(12);
|
||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
|
||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
||||||
frames.writeShort(0x8000);
|
frames.writeShort(0x8000);
|
||||||
frames.writeShort(0);
|
frames.writeShort(0);
|
||||||
@ -92,7 +92,7 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeShort(2);
|
frames.writeShort(2);
|
||||||
frames.writeByte(0x01);
|
frames.writeByte(0x01);
|
||||||
frames.writeMedium(8);
|
frames.writeMedium(8);
|
||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
|
||||||
frames.writeInt(0);
|
frames.writeInt(0);
|
||||||
|
|
||||||
// SPDY RST_STREAM Frame
|
// SPDY RST_STREAM Frame
|
||||||
@ -100,7 +100,7 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeByte(2);
|
frames.writeByte(2);
|
||||||
frames.writeShort(3);
|
frames.writeShort(3);
|
||||||
frames.writeInt(8);
|
frames.writeInt(8);
|
||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF | 0x01);
|
||||||
frames.writeInt(random.nextInt() | 0x01);
|
frames.writeInt(random.nextInt() | 0x01);
|
||||||
|
|
||||||
// SPDY SETTINGS Frame
|
// SPDY SETTINGS Frame
|
||||||
@ -133,7 +133,15 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeByte(2);
|
frames.writeByte(2);
|
||||||
frames.writeShort(8);
|
frames.writeShort(8);
|
||||||
frames.writeInt(4);
|
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
|
@BeforeClass
|
||||||
|
Loading…
Reference in New Issue
Block a user