SPDY: update object hierarchy

This commit is contained in:
Jeff Pinner 2013-06-04 14:32:11 -07:00 committed by Norman Maurer
parent 7f7bf304b0
commit c8ca329932
36 changed files with 531 additions and 682 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,17 +16,16 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder; import io.netty.buffer.IllegalBufferAccessException;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
/** /**
* The default {@link SpdyDataFrame} implementation. * The default {@link SpdyDataFrame} implementation.
*/ */
public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDataFrame { public class DefaultSpdyDataFrame extends DefaultSpdyStreamFrame implements SpdyDataFrame {
private int streamId; private final ByteBuf data;
private boolean last;
/** /**
* Creates a new instance. * Creates a new instance.
@ -44,8 +43,11 @@ public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDa
* @param data the payload of the frame. Can not exceed {@link SpdyCodecUtil#SPDY_MAX_LENGTH} * @param data the payload of the frame. Can not exceed {@link SpdyCodecUtil#SPDY_MAX_LENGTH}
*/ */
public DefaultSpdyDataFrame(int streamId, ByteBuf data) { public DefaultSpdyDataFrame(int streamId, ByteBuf data) {
super(validate(data)); super(streamId);
setStreamId(streamId); if (data == null) {
throw new NullPointerException("data");
}
this.data = validate(data);
} }
private static ByteBuf validate(ByteBuf data) { private static ByteBuf validate(ByteBuf data) {
@ -56,51 +58,60 @@ public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDa
return data; return data;
} }
@Override
public int getStreamId() {
return streamId;
}
@Override @Override
public SpdyDataFrame setStreamId(int streamId) { public SpdyDataFrame setStreamId(int streamId) {
if (streamId <= 0) { super.setStreamId(streamId);
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId);
}
this.streamId = streamId;
return this; return this;
} }
@Override
public boolean isLast() {
return last;
}
@Override @Override
public SpdyDataFrame setLast(boolean last) { public SpdyDataFrame setLast(boolean last) {
this.last = last; super.setLast(last);
return this; return this;
} }
@Override @Override
public DefaultSpdyDataFrame copy() { public ByteBuf content() {
DefaultSpdyDataFrame frame = new DefaultSpdyDataFrame(getStreamId(), content().copy()); if (data.refCnt() <= 0) {
throw new IllegalBufferAccessException();
}
return data;
}
@Override
public SpdyDataFrame copy() {
SpdyDataFrame frame = new DefaultSpdyDataFrame(getStreamId(), content().copy());
frame.setLast(isLast()); frame.setLast(isLast());
return frame; return frame;
} }
@Override
public int refCnt() {
return data.refCnt();
}
@Override @Override
public SpdyDataFrame retain() { public SpdyDataFrame retain() {
super.retain(); data.retain();
return this; return this;
} }
@Override @Override
public SpdyDataFrame retain(int increment) { public SpdyDataFrame retain(int increment) {
super.retain(increment); data.retain(increment);
return this; return this;
} }
@Override
public boolean release() {
return data.release();
}
@Override
public boolean release(int decrement) {
return data.release(decrement);
}
@Override @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -110,7 +121,7 @@ public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDa
buf.append(')'); buf.append(')');
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Size = "); buf.append("--> Size = ");
if (refCnt() == 0) { if (refCnt() == 0) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -48,19 +48,17 @@ public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame {
* Creates a new instance. * Creates a new instance.
* *
* @param lastGoodStreamId the Last-good-stream-ID of this frame * @param lastGoodStreamId the Last-good-stream-ID of this frame
* @param status the getStatus of this frame * @param status the status of this frame
*/ */
public DefaultSpdyGoAwayFrame(int lastGoodStreamId, SpdySessionStatus status) { public DefaultSpdyGoAwayFrame(int lastGoodStreamId, SpdySessionStatus status) {
setLastGoodStreamId(lastGoodStreamId); setLastGoodStreamId(lastGoodStreamId);
setStatus(status); setStatus(status);
} }
@Override
public int getLastGoodStreamId() { public int getLastGoodStreamId() {
return lastGoodStreamId; return lastGoodStreamId;
} }
@Override
public SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId) { public SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId) {
if (lastGoodStreamId < 0) { if (lastGoodStreamId < 0) {
throw new IllegalArgumentException("Last-good-stream-ID" throw new IllegalArgumentException("Last-good-stream-ID"
@ -70,12 +68,10 @@ public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame {
return this; return this;
} }
@Override
public SpdySessionStatus getStatus() { public SpdySessionStatus getStatus() {
return status; return status;
} }
@Override
public SpdyGoAwayFrame setStatus(SpdySessionStatus status) { public SpdyGoAwayFrame setStatus(SpdySessionStatus status) {
this.status = status; this.status = status;
return this; return this;
@ -87,10 +83,10 @@ public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame {
buf.append(getClass().getSimpleName()); buf.append(getClass().getSimpleName());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Last-good-stream-ID = "); buf.append("--> Last-good-stream-ID = ");
buf.append(lastGoodStreamId); buf.append(getLastGoodStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Status: "); buf.append("--> Status: ");
buf.append(status.toString()); buf.append(getStatus().toString());
return buf.toString(); return buf.toString();
} }
} }

View File

@ -1,61 +0,0 @@
/*
* 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;
import java.util.Map;
/**
* The default {@link SpdyHeaderBlock} implementation.
*/
public class DefaultSpdyHeaderBlock implements SpdyHeaderBlock {
private boolean invalid;
private final SpdyHeaders headers = new DefaultSpdyHeaders();
/**
* Creates a new instance.
*/
protected DefaultSpdyHeaderBlock() {
}
@Override
public boolean isInvalid() {
return invalid;
}
@Override
public SpdyHeaderBlock setInvalid() {
invalid = true;
return this;
}
@Override
public SpdyHeaders headers() {
return headers;
}
protected void appendHeaders(StringBuilder buf) {
for (Map.Entry<String, String> e: headers().entries()) {
buf.append(" ");
buf.append(e.getKey());
buf.append(": ");
buf.append(e.getValue());
buf.append(StringUtil.NEWLINE);
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -15,17 +15,18 @@
*/ */
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import java.util.Map;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
/** /**
* The default {@link SpdyHeadersFrame} implementation. * The default {@link SpdyHeadersFrame} implementation.
*/ */
public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock public class DefaultSpdyHeadersFrame extends DefaultSpdyStreamFrame
implements SpdyHeadersFrame { implements SpdyHeadersFrame {
private int streamId; private boolean invalid;
private boolean last; private final SpdyHeaders headers = new DefaultSpdyHeaders();
/** /**
* Creates a new instance. * Creates a new instance.
@ -33,41 +34,34 @@ public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock
* @param streamId the Stream-ID of this frame * @param streamId the Stream-ID of this frame
*/ */
public DefaultSpdyHeadersFrame(int streamId) { public DefaultSpdyHeadersFrame(int streamId) {
setStreamId(streamId); super(streamId);
}
@Override
public int getStreamId() {
return streamId;
} }
@Override @Override
public SpdyHeadersFrame setStreamId(int streamId) { public SpdyHeadersFrame setStreamId(int streamId) {
if (streamId <= 0) { super.setStreamId(streamId);
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId);
}
this.streamId = streamId;
return this; return this;
} }
@Override
public boolean isLast() {
return last;
}
@Override @Override
public SpdyHeadersFrame setLast(boolean last) { public SpdyHeadersFrame setLast(boolean last) {
this.last = last; super.setLast(last);
return this; return this;
} }
@Override public boolean isInvalid() {
return invalid;
}
public SpdyHeadersFrame setInvalid() { public SpdyHeadersFrame setInvalid() {
super.setInvalid(); invalid = true;
return this; return this;
} }
public SpdyHeaders headers() {
return headers;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -77,7 +71,7 @@ public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock
buf.append(')'); buf.append(')');
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Headers:"); buf.append("--> Headers:");
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
@ -87,4 +81,14 @@ public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock
buf.setLength(buf.length() - StringUtil.NEWLINE.length()); buf.setLength(buf.length() - StringUtil.NEWLINE.length());
return buf.toString(); return buf.toString();
} }
protected void appendHeaders(StringBuilder buf) {
for (Map.Entry<String, String> e: headers().entries()) {
buf.append(" ");
buf.append(e.getKey());
buf.append(": ");
buf.append(e.getValue());
buf.append(StringUtil.NEWLINE);
}
}
} }

View File

@ -1,27 +0,0 @@
/*
* 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;
/**
* The default {@link SpdyNoOpFrame} implementation.
*/
public class DefaultSpdyNoOpFrame implements SpdyNoOpFrame {
@Override
public String toString() {
return getClass().getSimpleName();
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -33,12 +33,10 @@ public class DefaultSpdyPingFrame implements SpdyPingFrame {
setId(id); setId(id);
} }
@Override
public int getId() { public int getId() {
return id; return id;
} }
@Override
public SpdyPingFrame setId(int id) { public SpdyPingFrame setId(int id) {
this.id = id; this.id = id;
return this; return this;
@ -50,7 +48,7 @@ public class DefaultSpdyPingFrame implements SpdyPingFrame {
buf.append(getClass().getSimpleName()); buf.append(getClass().getSimpleName());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> ID = "); buf.append("--> ID = ");
buf.append(id); buf.append(getId());
return buf.toString(); return buf.toString();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -20,9 +20,9 @@ import io.netty.util.internal.StringUtil;
/** /**
* The default {@link SpdyRstStreamFrame} implementation. * The default {@link SpdyRstStreamFrame} implementation.
*/ */
public class DefaultSpdyRstStreamFrame implements SpdyRstStreamFrame { public class DefaultSpdyRstStreamFrame extends DefaultSpdyStreamFrame
implements SpdyRstStreamFrame {
private int streamId;
private SpdyStreamStatus status; private SpdyStreamStatus status;
/** /**
@ -39,34 +39,29 @@ public class DefaultSpdyRstStreamFrame implements SpdyRstStreamFrame {
* Creates a new instance. * Creates a new instance.
* *
* @param streamId the Stream-ID of this frame * @param streamId the Stream-ID of this frame
* @param status the getStatus of this frame * @param status the status of this frame
*/ */
public DefaultSpdyRstStreamFrame(int streamId, SpdyStreamStatus status) { public DefaultSpdyRstStreamFrame(int streamId, SpdyStreamStatus status) {
setStreamId(streamId); super(streamId);
setStatus(status); setStatus(status);
} }
@Override
public int getStreamId() {
return streamId;
}
@Override @Override
public SpdyRstStreamFrame setStreamId(int streamId) { public SpdyRstStreamFrame setStreamId(int streamId) {
if (streamId <= 0) { super.setStreamId(streamId);
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId);
}
this.streamId = streamId;
return this; return this;
} }
@Override @Override
public SpdyRstStreamFrame setLast(boolean last) {
super.setLast(last);
return this;
}
public SpdyStreamStatus getStatus() { public SpdyStreamStatus getStatus() {
return status; return status;
} }
@Override
public SpdyRstStreamFrame setStatus(SpdyStreamStatus status) { public SpdyRstStreamFrame setStatus(SpdyStreamStatus status) {
this.status = status; this.status = status;
return this; return this;
@ -78,10 +73,10 @@ public class DefaultSpdyRstStreamFrame implements SpdyRstStreamFrame {
buf.append(getClass().getSimpleName()); buf.append(getClass().getSimpleName());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Status: "); buf.append("--> Status: ");
buf.append(status.toString()); buf.append(getStatus().toString());
return buf.toString(); return buf.toString();
} }
} }

View File

@ -0,0 +1,56 @@
/*
* Copyright 2013 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;
/**
* The default {@link SpdyStreamFrame} implementation.
*/
public abstract class DefaultSpdyStreamFrame implements SpdyStreamFrame {
private int streamId;
private boolean last;
/**
* Creates a new instance.
*
* @param streamId the Stream-ID of this frame
*/
protected DefaultSpdyStreamFrame(int streamId) {
setStreamId(streamId);
}
public int getStreamId() {
return streamId;
}
public SpdyStreamFrame setStreamId(int streamId) {
if (streamId <= 0) {
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId);
}
this.streamId = streamId;
return this;
}
public boolean isLast() {
return last;
}
public SpdyStreamFrame setLast(boolean last) {
this.last = last;
return this;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -20,44 +20,27 @@ import io.netty.util.internal.StringUtil;
/** /**
* The default {@link SpdySynReplyFrame} implementation. * The default {@link SpdySynReplyFrame} implementation.
*/ */
public class DefaultSpdySynReplyFrame extends DefaultSpdyHeaderBlock public class DefaultSpdySynReplyFrame extends DefaultSpdyHeadersFrame
implements SpdySynReplyFrame { implements SpdySynReplyFrame {
private int streamId;
private boolean last;
/** /**
* Creates a new instance. * Creates a new instance.
* *
* @param streamId the Stream-ID of this frame * @param streamId the Stream-ID of this frame
*/ */
public DefaultSpdySynReplyFrame(int streamId) { public DefaultSpdySynReplyFrame(int streamId) {
setStreamId(streamId); super(streamId);
}
@Override
public int getStreamId() {
return streamId;
} }
@Override @Override
public SpdySynReplyFrame setStreamId(int streamId) { public SpdySynReplyFrame setStreamId(int streamId) {
if (streamId <= 0) { super.setStreamId(streamId);
throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId);
}
this.streamId = streamId;
return this; return this;
} }
@Override
public boolean isLast() {
return last;
}
@Override @Override
public SpdySynReplyFrame setLast(boolean last) { public SpdySynReplyFrame setLast(boolean last) {
this.last = last; super.setLast(last);
return this; return this;
} }
@ -76,7 +59,7 @@ public class DefaultSpdySynReplyFrame extends DefaultSpdyHeaderBlock
buf.append(')'); buf.append(')');
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Headers:"); buf.append("--> Headers:");
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -20,13 +20,11 @@ import io.netty.util.internal.StringUtil;
/** /**
* The default {@link SpdySynStreamFrame} implementation. * The default {@link SpdySynStreamFrame} implementation.
*/ */
public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock public class DefaultSpdySynStreamFrame extends DefaultSpdyHeadersFrame
implements SpdySynStreamFrame { implements SpdySynStreamFrame {
private int streamId;
private int associatedToStreamId; private int associatedToStreamId;
private byte priority; private byte priority;
private boolean last;
private boolean unidirectional; private boolean unidirectional;
/** /**
@ -38,23 +36,26 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
*/ */
public DefaultSpdySynStreamFrame( public DefaultSpdySynStreamFrame(
int streamId, int associatedToStreamId, byte priority) { int streamId, int associatedToStreamId, byte priority) {
setStreamId(streamId); super(streamId);
setAssociatedToStreamId(associatedToStreamId); setAssociatedToStreamId(associatedToStreamId);
setPriority(priority); setPriority(priority);
} }
@Override @Override
public int getStreamId() { public SpdySynStreamFrame setStreamId(int streamId) {
return streamId; super.setStreamId(streamId);
return this;
} }
@Override @Override
public SpdySynStreamFrame setStreamId(int streamId) { public SpdySynStreamFrame setLast(boolean last) {
if (streamId <= 0) { super.setLast(last);
throw new IllegalArgumentException( return this;
"Stream-ID must be positive: " + streamId); }
}
this.streamId = streamId; @Override
public SpdySynStreamFrame setInvalid() {
super.setInvalid();
return this; return this;
} }
@ -89,17 +90,6 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
return this; return this;
} }
@Override
public boolean isLast() {
return last;
}
@Override
public SpdySynStreamFrame setLast(boolean last) {
this.last = last;
return this;
}
@Override @Override
public boolean isUnidirectional() { public boolean isUnidirectional() {
return unidirectional; return unidirectional;
@ -111,12 +101,6 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
return this; return this;
} }
@Override
public SpdySynStreamFrame setInvalid() {
super.setInvalid();
return this;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
@ -128,15 +112,15 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
buf.append(')'); buf.append(')');
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
if (associatedToStreamId != 0) { if (associatedToStreamId != 0) {
buf.append("--> Associated-To-Stream-ID = "); buf.append("--> Associated-To-Stream-ID = ");
buf.append(associatedToStreamId); buf.append(getAssociatedToStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
} }
buf.append("--> Priority = "); buf.append("--> Priority = ");
buf.append(priority); buf.append(getPriority());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Headers:"); buf.append("--> Headers:");
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -43,9 +43,9 @@ public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame {
@Override @Override
public SpdyWindowUpdateFrame setStreamId(int streamId) { public SpdyWindowUpdateFrame setStreamId(int streamId) {
if (streamId <= 0) { if (streamId < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Stream-ID must be positive: " + streamId); "Stream-ID cannot be negative: " + streamId);
} }
this.streamId = streamId; this.streamId = streamId;
return this; return this;
@ -73,10 +73,10 @@ public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame {
buf.append(getClass().getSimpleName()); buf.append(getClass().getSimpleName());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Stream-ID = "); buf.append("--> Stream-ID = ");
buf.append(streamId); buf.append(getStreamId());
buf.append(StringUtil.NEWLINE); buf.append(StringUtil.NEWLINE);
buf.append("--> Delta-Window-Size = "); buf.append("--> Delta-Window-Size = ");
buf.append(deltaWindowSize); buf.append(getDeltaWindowSize());
return buf.toString(); return buf.toString();
} }
} }

View File

@ -1,23 +0,0 @@
/*
* 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;
/**
* A SPDY Protocol Control Frame
*/
public interface SpdyControlFrame extends SpdyDataOrControlFrame {
// Tag interface
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -20,9 +20,9 @@ import io.netty.buffer.ByteBufHolder;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
/** /**
* A SPDY Protocol Data Frame * A SPDY Protocol DATA Frame
*/ */
public interface SpdyDataFrame extends ByteBufHolder, SpdyStreamFrame, SpdyDataOrControlFrame { public interface SpdyDataFrame extends ByteBufHolder, SpdyStreamFrame {
@Override @Override
SpdyDataFrame setStreamId(int streamID); SpdyDataFrame setStreamId(int streamID);

View File

@ -13,9 +13,11 @@
* License for the specific language governing permissions and limitations * License for the specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
public interface SpdyDataOrControlFrame { /**
* A SPDY Protocol Frame
*/
public interface SpdyFrame {
// Tag interface // Tag interface
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -21,7 +21,6 @@ import io.netty.channel.CombinedChannelDuplexHandler;
* A combination of {@link SpdyFrameDecoder} and {@link SpdyFrameEncoder}. * A combination of {@link SpdyFrameDecoder} and {@link SpdyFrameEncoder}.
*/ */
public final class SpdyFrameCodec extends CombinedChannelDuplexHandler<SpdyFrameDecoder, SpdyFrameEncoder> { public final class SpdyFrameCodec extends CombinedChannelDuplexHandler<SpdyFrameDecoder, SpdyFrameEncoder> {
/** /**
* Creates a new instance with the specified {@code version} and * Creates a new instance with the specified {@code version} and
* the default decoder and encoder options * the default decoder and encoder options

View File

@ -25,7 +25,7 @@ import io.netty.handler.codec.TooLongFrameException;
import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; import static io.netty.handler.codec.spdy.SpdyCodecUtil.*;
/** /**
* Decodes {@link ByteBuf}s into SPDY Data and Control Frames. * Decodes {@link ByteBuf}s into SPDY Frames.
*/ */
public class SpdyFrameDecoder extends ByteToMessageDecoder { public class SpdyFrameDecoder extends ByteToMessageDecoder {
@ -37,7 +37,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
private State state; private State state;
private SpdySettingsFrame spdySettingsFrame; private SpdySettingsFrame spdySettingsFrame;
private SpdyHeaderBlock spdyHeaderBlock; private SpdyHeadersFrame spdyHeadersFrame;
// SPDY common header fields // SPDY common header fields
private byte flags; private byte flags;
@ -221,12 +221,12 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
case READ_HEADER_BLOCK_FRAME: case READ_HEADER_BLOCK_FRAME:
try { try {
spdyHeaderBlock = readHeaderBlockFrame(buffer); spdyHeadersFrame = readHeaderBlockFrame(buffer);
if (spdyHeaderBlock != null) { if (spdyHeadersFrame != null) {
if (length == 0) { if (length == 0) {
state = State.READ_COMMON_HEADER; state = State.READ_COMMON_HEADER;
Object frame = spdyHeaderBlock; Object frame = spdyHeadersFrame;
spdyHeaderBlock = null; spdyHeadersFrame = null;
out.add(frame); out.add(frame);
return; return;
} }
@ -247,15 +247,15 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
decodeHeaderBlock(buffer.readSlice(compressedBytes)); decodeHeaderBlock(buffer.readSlice(compressedBytes));
} catch (Exception e) { } catch (Exception e) {
state = State.FRAME_ERROR; state = State.FRAME_ERROR;
spdyHeaderBlock = null; spdyHeadersFrame = null;
decompressed = null; decompressed = null;
ctx.fireExceptionCaught(e); ctx.fireExceptionCaught(e);
return; return;
} }
if (spdyHeaderBlock != null && spdyHeaderBlock.isInvalid()) { if (spdyHeadersFrame != null && spdyHeadersFrame.isInvalid()) {
Object frame = spdyHeaderBlock; Object frame = spdyHeadersFrame;
spdyHeaderBlock = null; spdyHeadersFrame = null;
decompressed = null; decompressed = null;
if (length == 0) { if (length == 0) {
state = State.READ_COMMON_HEADER; state = State.READ_COMMON_HEADER;
@ -265,8 +265,8 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
} }
if (length == 0) { if (length == 0) {
Object frame = spdyHeaderBlock; Object frame = spdyHeadersFrame;
spdyHeaderBlock = null; spdyHeadersFrame = null;
state = State.READ_COMMON_HEADER; state = State.READ_COMMON_HEADER;
out.add(frame); out.add(frame);
return; return;
@ -436,7 +436,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
} }
} }
private SpdyHeaderBlock readHeaderBlockFrame(ByteBuf buffer) { private SpdyHeadersFrame readHeaderBlockFrame(ByteBuf buffer) {
int minLength; int minLength;
int streamID; int streamID;
switch (type) { switch (type) {
@ -567,7 +567,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
headerBlockDecompressor.setInput(buffer); headerBlockDecompressor.setInput(buffer);
headerBlockDecompressor.decode(decompressed); headerBlockDecompressor.decode(decompressed);
if (spdyHeaderBlock == null) { if (spdyHeadersFrame == null) {
// Only decompressing data to keep decompression context in sync // Only decompressing data to keep decompression context in sync
decompressed = null; decompressed = null;
return; return;
@ -582,7 +582,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
} }
numHeaders = readLengthField(); numHeaders = readLengthField();
if (numHeaders < 0) { if (numHeaders < 0) {
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
} }
@ -601,7 +601,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
// Recipients of a zero-length name must issue a stream error // Recipients of a zero-length name must issue a stream error
if (nameLength <= 0) { if (nameLength <= 0) {
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
headerSize += nameLength; headerSize += nameLength;
@ -621,8 +621,8 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
String name = new String(nameBytes, "UTF-8"); String name = new String(nameBytes, "UTF-8");
// Check for identically named headers // Check for identically named headers
if (spdyHeaderBlock.headers().contains(name)) { if (spdyHeadersFrame.headers().contains(name)) {
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
@ -636,17 +636,17 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
// Recipients of illegal value fields must issue a stream error // Recipients of illegal value fields must issue a stream error
if (valueLength < 0) { if (valueLength < 0) {
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
// SPDY/3 allows zero-length (empty) header values // SPDY/3 allows zero-length (empty) header values
if (valueLength == 0) { if (valueLength == 0) {
if (version < 3) { if (version < 3) {
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} else { } else {
spdyHeaderBlock.headers().add(name, ""); spdyHeadersFrame.headers().add(name, "");
numHeaders --; numHeaders --;
this.headerSize = headerSize; this.headerSize = headerSize;
continue; continue;
@ -678,16 +678,16 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
if (index < valueBytes.length && valueBytes[index + 1] == (byte) 0) { if (index < valueBytes.length && valueBytes[index + 1] == (byte) 0) {
// Received multiple, in-sequence NULL characters // Received multiple, in-sequence NULL characters
// Recipients of illegal value fields must issue a stream error // Recipients of illegal value fields must issue a stream error
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
String value = new String(valueBytes, offset, index - offset, "UTF-8"); String value = new String(valueBytes, offset, index - offset, "UTF-8");
try { try {
spdyHeaderBlock.headers().add(name, value); spdyHeadersFrame.headers().add(name, value);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Name contains NULL or non-ascii characters // Name contains NULL or non-ascii characters
spdyHeaderBlock.setInvalid(); spdyHeadersFrame.setInvalid();
return; return;
} }
index ++; index ++;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -29,9 +29,9 @@ import java.util.Set;
import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; import static io.netty.handler.codec.spdy.SpdyCodecUtil.*;
/** /**
* Encodes a SPDY Data or Control Frame into a {@link ByteBuf}. * Encodes a SPDY Frame into a {@link ByteBuf}.
*/ */
public class SpdyFrameEncoder extends MessageToByteEncoder<SpdyDataOrControlFrame> { public class SpdyFrameEncoder extends MessageToByteEncoder<SpdyFrame> {
private final int version; private final int version;
private volatile boolean finished; private volatile boolean finished;
@ -76,7 +76,7 @@ public class SpdyFrameEncoder extends MessageToByteEncoder<SpdyDataOrControlFram
} }
@Override @Override
protected void encode(ChannelHandlerContext ctx, SpdyDataOrControlFrame msg, ByteBuf out) throws Exception { protected void encode(ChannelHandlerContext ctx, SpdyFrame msg, ByteBuf out) throws Exception {
if (msg instanceof SpdyDataFrame) { if (msg instanceof SpdyDataFrame) {
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
@ -202,13 +202,6 @@ public class SpdyFrameEncoder extends MessageToByteEncoder<SpdyDataOrControlFram
out.writeInt(spdySettingsFrame.getValue(id)); out.writeInt(spdySettingsFrame.getValue(id));
} }
} else if (msg instanceof SpdyNoOpFrame) {
out.ensureWritable(SPDY_HEADER_SIZE);
out.writeShort(version | 0x8000);
out.writeShort(SPDY_NOOP_FRAME);
out.writeInt(0);
} else if (msg instanceof SpdyPingFrame) { } else if (msg instanceof SpdyPingFrame) {
SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
@ -285,7 +278,7 @@ public class SpdyFrameEncoder extends MessageToByteEncoder<SpdyDataOrControlFram
} }
} }
private static ByteBuf encodeHeaderBlock(int version, SpdyHeaderBlock headerFrame) private static ByteBuf encodeHeaderBlock(int version, SpdyHeadersFrame headerFrame)
throws Exception { throws Exception {
Set<String> names = headerFrame.headers().names(); Set<String> names = headerFrame.headers().names();
int numHeaders = names.size(); int numHeaders = names.size();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol GOAWAY Control Frame * A SPDY Protocol GOAWAY Frame
*/ */
public interface SpdyGoAwayFrame extends SpdyControlFrame { public interface SpdyGoAwayFrame extends SpdyFrame {
/** /**
* Returns the Last-good-stream-ID of this frame. * Returns the Last-good-stream-ID of this frame.
@ -32,12 +32,12 @@ public interface SpdyGoAwayFrame extends SpdyControlFrame {
SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId); SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId);
/** /**
* Returns the getStatus of this frame. * Returns the status of this frame.
*/ */
SpdySessionStatus getStatus(); SpdySessionStatus getStatus();
/** /**
* Sets the getStatus of this frame. * Sets the status of this frame.
*/ */
SpdyGoAwayFrame setStatus(SpdySessionStatus status); SpdyGoAwayFrame setStatus(SpdySessionStatus status);
} }

View File

@ -1,42 +0,0 @@
/*
* 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;
/**
* A SPDY Name/Value Header Block which provides common properties for
* {@link SpdySynStreamFrame}, {@link SpdySynReplyFrame}, and
* {@link SpdyHeadersFrame}.
* @see SpdyHeaders
*/
public interface SpdyHeaderBlock {
/**
* Returns {@code true} if this header block is invalid.
* A RST_STREAM frame with code PROTOCOL_ERROR should be sent.
*/
boolean isInvalid();
/**
* Marks this header block as invalid.
*/
SpdyHeaderBlock setInvalid();
/**
* Returns the {@link SpdyHeaders}.
*/
SpdyHeaders headers();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -27,7 +27,7 @@ import java.util.Set;
/** /**
* Provides the constants for the standard SPDY HTTP header names and commonly * Provides the constants for the standard SPDY HTTP header names and commonly
* used utility methods that access a {@link SpdyHeaderBlock}. * used utility methods that access a {@link SpdyHeadersFrame}.
*/ */
public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>> { public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>> {
@ -166,8 +166,8 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
* *
* @return the header value or {@code null} if there is no such header * @return the header value or {@code null} if there is no such header
*/ */
public static String getHeader(SpdyHeaderBlock block, String name) { public static String getHeader(SpdyHeadersFrame frame, String name) {
return block.headers().get(name); return frame.headers().get(name);
} }
/** /**
@ -178,8 +178,8 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
* @return the header value or the {@code defaultValue} if there is no such * @return the header value or the {@code defaultValue} if there is no such
* header * header
*/ */
public static String getHeader(SpdyHeaderBlock block, String name, String defaultValue) { public static String getHeader(SpdyHeadersFrame frame, String name, String defaultValue) {
String value = block.headers().get(name); String value = frame.headers().get(name);
if (value == null) { if (value == null) {
return defaultValue; return defaultValue;
} }
@ -190,66 +190,66 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
* Sets a new header with the specified name and value. If there is an * Sets a new header with the specified name and value. If there is an
* existing header with the same name, the existing header is removed. * existing header with the same name, the existing header is removed.
*/ */
public static void setHeader(SpdyHeaderBlock block, String name, Object value) { public static void setHeader(SpdyHeadersFrame frame, String name, Object value) {
block.headers().set(name, value); frame.headers().set(name, value);
} }
/** /**
* Sets a new header with the specified name and values. If there is an * Sets a new header with the specified name and values. If there is an
* existing header with the same name, the existing header is removed. * existing header with the same name, the existing header is removed.
*/ */
public static void setHeader(SpdyHeaderBlock block, String name, Iterable<?> values) { public static void setHeader(SpdyHeadersFrame frame, String name, Iterable<?> values) {
block.headers().set(name, values); frame.headers().set(name, values);
} }
/** /**
* Adds a new header with the specified name and value. * Adds a new header with the specified name and value.
*/ */
public static void addHeader(SpdyHeaderBlock block, String name, Object value) { public static void addHeader(SpdyHeadersFrame frame, String name, Object value) {
block.headers().add(name, value); frame.headers().add(name, value);
} }
/** /**
* Removes the SPDY host header. * Removes the SPDY host header.
*/ */
public static void removeHost(SpdyHeaderBlock block) { public static void removeHost(SpdyHeadersFrame frame) {
block.headers().remove(HttpNames.HOST); frame.headers().remove(HttpNames.HOST);
} }
/** /**
* Returns the SPDY host header. * Returns the SPDY host header.
*/ */
public static String getHost(SpdyHeaderBlock block) { public static String getHost(SpdyHeadersFrame frame) {
return block.headers().get(HttpNames.HOST); return frame.headers().get(HttpNames.HOST);
} }
/** /**
* Set the SPDY host header. * Set the SPDY host header.
*/ */
public static void setHost(SpdyHeaderBlock block, String host) { public static void setHost(SpdyHeadersFrame frame, String host) {
block.headers().set(HttpNames.HOST, host); frame.headers().set(HttpNames.HOST, host);
} }
/** /**
* Removes the HTTP method header. * Removes the HTTP method header.
*/ */
public static void removeMethod(int spdyVersion, SpdyHeaderBlock block) { public static void removeMethod(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().remove(Spdy2HttpNames.METHOD); frame.headers().remove(Spdy2HttpNames.METHOD);
} else { } else {
block.headers().remove(HttpNames.METHOD); frame.headers().remove(HttpNames.METHOD);
} }
} }
/** /**
* Returns the {@link HttpMethod} represented by the HTTP method header. * Returns the {@link HttpMethod} represented by the HTTP method header.
*/ */
public static HttpMethod getMethod(int spdyVersion, SpdyHeaderBlock block) { public static HttpMethod getMethod(int spdyVersion, SpdyHeadersFrame frame) {
try { try {
if (spdyVersion < 3) { if (spdyVersion < 3) {
return HttpMethod.valueOf(block.headers().get(Spdy2HttpNames.METHOD)); return HttpMethod.valueOf(frame.headers().get(Spdy2HttpNames.METHOD));
} else { } else {
return HttpMethod.valueOf(block.headers().get(HttpNames.METHOD)); return HttpMethod.valueOf(frame.headers().get(HttpNames.METHOD));
} }
} catch (Exception e) { } catch (Exception e) {
return null; return null;
@ -259,68 +259,68 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
/** /**
* Sets the HTTP method header. * Sets the HTTP method header.
*/ */
public static void setMethod(int spdyVersion, SpdyHeaderBlock block, HttpMethod method) { public static void setMethod(int spdyVersion, SpdyHeadersFrame frame, HttpMethod method) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().set(Spdy2HttpNames.METHOD, method.name()); frame.headers().set(Spdy2HttpNames.METHOD, method.name());
} else { } else {
block.headers().set(HttpNames.METHOD, method.name()); frame.headers().set(HttpNames.METHOD, method.name());
} }
} }
/** /**
* Removes the URL scheme header. * Removes the URL scheme header.
*/ */
public static void removeScheme(int spdyVersion, SpdyHeaderBlock block) { public static void removeScheme(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 2) { if (spdyVersion < 2) {
block.headers().remove(Spdy2HttpNames.SCHEME); frame.headers().remove(Spdy2HttpNames.SCHEME);
} else { } else {
block.headers().remove(HttpNames.SCHEME); frame.headers().remove(HttpNames.SCHEME);
} }
} }
/** /**
* Returns the value of the URL scheme header. * Returns the value of the URL scheme header.
*/ */
public static String getScheme(int spdyVersion, SpdyHeaderBlock block) { public static String getScheme(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
return block.headers().get(Spdy2HttpNames.SCHEME); return frame.headers().get(Spdy2HttpNames.SCHEME);
} else { } else {
return block.headers().get(HttpNames.SCHEME); return frame.headers().get(HttpNames.SCHEME);
} }
} }
/** /**
* Sets the URL scheme header. * Sets the URL scheme header.
*/ */
public static void setScheme(int spdyVersion, SpdyHeaderBlock block, String scheme) { public static void setScheme(int spdyVersion, SpdyHeadersFrame frame, String scheme) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().set(Spdy2HttpNames.SCHEME, scheme); frame.headers().set(Spdy2HttpNames.SCHEME, scheme);
} else { } else {
block.headers().set(HttpNames.SCHEME, scheme); frame.headers().set(HttpNames.SCHEME, scheme);
} }
} }
/** /**
* Removes the HTTP response status header. * Removes the HTTP response status header.
*/ */
public static void removeStatus(int spdyVersion, SpdyHeaderBlock block) { public static void removeStatus(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().remove(Spdy2HttpNames.STATUS); frame.headers().remove(Spdy2HttpNames.STATUS);
} else { } else {
block.headers().remove(HttpNames.STATUS); frame.headers().remove(HttpNames.STATUS);
} }
} }
/** /**
* Returns the {@link HttpResponseStatus} represented by the HTTP response status header. * Returns the {@link HttpResponseStatus} represented by the HTTP response status header.
*/ */
public static HttpResponseStatus getStatus(int spdyVersion, SpdyHeaderBlock block) { public static HttpResponseStatus getStatus(int spdyVersion, SpdyHeadersFrame frame) {
try { try {
String status; String status;
if (spdyVersion < 3) { if (spdyVersion < 3) {
status = block.headers().get(Spdy2HttpNames.STATUS); status = frame.headers().get(Spdy2HttpNames.STATUS);
} else { } else {
status = block.headers().get(HttpNames.STATUS); status = frame.headers().get(HttpNames.STATUS);
} }
int space = status.indexOf(' '); int space = status.indexOf(' ');
if (space == -1) { if (space == -1) {
@ -343,67 +343,67 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
/** /**
* Sets the HTTP response status header. * Sets the HTTP response status header.
*/ */
public static void setStatus(int spdyVersion, SpdyHeaderBlock block, HttpResponseStatus status) { public static void setStatus(int spdyVersion, SpdyHeadersFrame frame, HttpResponseStatus status) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().set(Spdy2HttpNames.STATUS, status.toString()); frame.headers().set(Spdy2HttpNames.STATUS, status.toString());
} else { } else {
block.headers().set(HttpNames.STATUS, status.toString()); frame.headers().set(HttpNames.STATUS, status.toString());
} }
} }
/** /**
* Removes the URL path header. * Removes the URL path header.
*/ */
public static void removeUrl(int spdyVersion, SpdyHeaderBlock block) { public static void removeUrl(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().remove(Spdy2HttpNames.URL); frame.headers().remove(Spdy2HttpNames.URL);
} else { } else {
block.headers().remove(HttpNames.PATH); frame.headers().remove(HttpNames.PATH);
} }
} }
/** /**
* Returns the value of the URL path header. * Returns the value of the URL path header.
*/ */
public static String getUrl(int spdyVersion, SpdyHeaderBlock block) { public static String getUrl(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
return block.headers().get(Spdy2HttpNames.URL); return frame.headers().get(Spdy2HttpNames.URL);
} else { } else {
return block.headers().get(HttpNames.PATH); return frame.headers().get(HttpNames.PATH);
} }
} }
/** /**
* Sets the URL path header. * Sets the URL path header.
*/ */
public static void setUrl(int spdyVersion, SpdyHeaderBlock block, String path) { public static void setUrl(int spdyVersion, SpdyHeadersFrame frame, String path) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().set(Spdy2HttpNames.URL, path); frame.headers().set(Spdy2HttpNames.URL, path);
} else { } else {
block.headers().set(HttpNames.PATH, path); frame.headers().set(HttpNames.PATH, path);
} }
} }
/** /**
* Removes the HTTP version header. * Removes the HTTP version header.
*/ */
public static void removeVersion(int spdyVersion, SpdyHeaderBlock block) { public static void removeVersion(int spdyVersion, SpdyHeadersFrame frame) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().remove(Spdy2HttpNames.VERSION); frame.headers().remove(Spdy2HttpNames.VERSION);
} else { } else {
block.headers().remove(HttpNames.VERSION); frame.headers().remove(HttpNames.VERSION);
} }
} }
/** /**
* Returns the {@link HttpVersion} represented by the HTTP version header. * Returns the {@link HttpVersion} represented by the HTTP version header.
*/ */
public static HttpVersion getVersion(int spdyVersion, SpdyHeaderBlock block) { public static HttpVersion getVersion(int spdyVersion, SpdyHeadersFrame frame) {
try { try {
if (spdyVersion < 3) { if (spdyVersion < 3) {
return HttpVersion.valueOf(block.headers().get(Spdy2HttpNames.VERSION)); return HttpVersion.valueOf(frame.headers().get(Spdy2HttpNames.VERSION));
} else { } else {
return HttpVersion.valueOf(block.headers().get(HttpNames.VERSION)); return HttpVersion.valueOf(frame.headers().get(HttpNames.VERSION));
} }
} catch (Exception e) { } catch (Exception e) {
return null; return null;
@ -413,11 +413,11 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
/** /**
* Sets the HTTP version header. * Sets the HTTP version header.
*/ */
public static void setVersion(int spdyVersion, SpdyHeaderBlock block, HttpVersion httpVersion) { public static void setVersion(int spdyVersion, SpdyHeadersFrame frame, HttpVersion httpVersion) {
if (spdyVersion < 3) { if (spdyVersion < 3) {
block.headers().set(Spdy2HttpNames.VERSION, httpVersion.text()); frame.headers().set(Spdy2HttpNames.VERSION, httpVersion.text());
} else { } else {
block.headers().set(HttpNames.VERSION, httpVersion.text()); frame.headers().set(HttpNames.VERSION, httpVersion.text());
} }
} }
@Override @Override
@ -443,7 +443,7 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
public abstract List<String> getAll(String name); public abstract List<String> getAll(String name);
/** /**
* Returns all header names and values that this block contains. * Returns all header names and values that this frame contains.
* *
* @return the {@link List} of the header name-value pairs. An empty list * @return the {@link List} of the header name-value pairs. An empty list
* if there is no header in this message. * if there is no header in this message.
@ -457,7 +457,7 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
public abstract boolean contains(String name); public abstract boolean contains(String name);
/** /**
* Returns the {@link Set} of all header names that this block contains. * Returns the {@link Set} of all header names that this frame contains.
*/ */
public abstract Set<String> names(); public abstract Set<String> names();
@ -490,7 +490,7 @@ public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>>
public abstract SpdyHeaders remove(String name); public abstract SpdyHeaders remove(String name);
/** /**
* Removes all headers from this block. * Removes all headers from this frame.
*/ */
public abstract SpdyHeaders clear(); public abstract SpdyHeaders clear();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,17 +16,29 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol HEADERS Control Frame * A SPDY Protocol HEADERS Frame
*/ */
public interface SpdyHeadersFrame extends SpdyHeaderBlock, SpdyControlFrame, SpdyStreamFrame { public interface SpdyHeadersFrame extends SpdyStreamFrame {
/**
* Returns {@code true} if this header block is invalid.
* A RST_STREAM frame with code PROTOCOL_ERROR should be sent.
*/
boolean isInvalid();
/**
* Marks this header block as invalid.
*/
SpdyHeadersFrame setInvalid();
/**
* Returns the {@link SpdyHeaders}.
*/
SpdyHeaders headers();
@Override @Override
SpdyHeadersFrame setStreamId(int streamID); SpdyHeadersFrame setStreamId(int streamID);
@Override @Override
SpdyHeadersFrame setLast(boolean last); SpdyHeadersFrame setLast(boolean last);
@Override
SpdyHeadersFrame setInvalid();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -22,7 +22,6 @@ import io.netty.channel.CombinedChannelDuplexHandler;
*/ */
public final class SpdyHttpCodec public final class SpdyHttpCodec
extends CombinedChannelDuplexHandler<SpdyHttpDecoder, SpdyHttpEncoder> { extends CombinedChannelDuplexHandler<SpdyHttpDecoder, SpdyHttpEncoder> {
/** /**
* Creates a new instance with the specified decoder options. * Creates a new instance with the specified decoder options.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -37,7 +37,7 @@ import java.util.Map;
* Decodes {@link SpdySynStreamFrame}s, {@link SpdySynReplyFrame}s, * Decodes {@link SpdySynStreamFrame}s, {@link SpdySynReplyFrame}s,
* and {@link SpdyDataFrame}s into {@link FullHttpRequest}s and {@link FullHttpResponse}s. * and {@link SpdyDataFrame}s into {@link FullHttpRequest}s and {@link FullHttpResponse}s.
*/ */
public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyDataOrControlFrame> { public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
private final int spdyVersion; private final int spdyVersion;
private final int maxContentLength; private final int maxContentLength;
@ -91,7 +91,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyDataOrControlFr
} }
@Override @Override
protected void decode(ChannelHandlerContext ctx, SpdyDataOrControlFrame msg, MessageList<Object> out) protected void decode(ChannelHandlerContext ctx, SpdyFrame msg, MessageList<Object> out)
throws Exception { throws Exception {
if (msg instanceof SpdySynStreamFrame) { if (msg instanceof SpdySynStreamFrame) {
@ -252,7 +252,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyDataOrControlFr
} }
} }
private static FullHttpRequest createHttpRequest(int spdyVersion, SpdyHeaderBlock requestFrame) private static FullHttpRequest createHttpRequest(int spdyVersion, SpdyHeadersFrame requestFrame)
throws Exception { throws Exception {
// Create the first line of the request from the name/value pairs // Create the first line of the request from the name/value pairs
HttpMethod method = SpdyHeaders.getMethod(spdyVersion, requestFrame); HttpMethod method = SpdyHeaders.getMethod(spdyVersion, requestFrame);
@ -287,7 +287,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyDataOrControlFr
return req; return req;
} }
private static FullHttpResponse createHttpResponse(int spdyVersion, SpdyHeaderBlock responseFrame) private static FullHttpResponse createHttpResponse(int spdyVersion, SpdyHeadersFrame responseFrame)
throws Exception { throws Exception {
// Create the first line of the response from the name/value pairs // Create the first line of the response from the name/value pairs
HttpResponseStatus status = SpdyHeaders.getStatus(spdyVersion, responseFrame); HttpResponseStatus status = SpdyHeaders.getStatus(spdyVersion, responseFrame);

View File

@ -266,7 +266,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<HttpObject> {
int streamID = SpdyHttpHeaders.getStreamId(httpResponse); int streamID = SpdyHttpHeaders.getStreamId(httpResponse);
SpdyHttpHeaders.removeStreamId(httpResponse); SpdyHttpHeaders.removeStreamId(httpResponse);
// The Connection, Keep-Alive, Proxy-Connection, and Transfer-ENcoding // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding
// headers are not valid and MUST not be sent. // headers are not valid and MUST not be sent.
httpResponse.headers().remove(HttpHeaders.Names.CONNECTION); httpResponse.headers().remove(HttpHeaders.Names.CONNECTION);
httpResponse.headers().remove("Keep-Alive"); httpResponse.headers().remove("Keep-Alive");

View File

@ -1,23 +0,0 @@
/*
* 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;
/**
* A SPDY Protocol NOOP Control Frame
*/
public interface SpdyNoOpFrame extends SpdyControlFrame {
// Tag interface
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol PING Control Frame * A SPDY Protocol PING Frame
*/ */
public interface SpdyPingFrame extends SpdyControlFrame { public interface SpdyPingFrame extends SpdyFrame {
/** /**
* Returns the ID of this frame. * Returns the ID of this frame.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,27 +16,23 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol RST_STREAM Control Frame * A SPDY Protocol RST_STREAM Frame
*/ */
public interface SpdyRstStreamFrame extends SpdyControlFrame { public interface SpdyRstStreamFrame extends SpdyStreamFrame {
/** /**
* Returns the Stream-ID of this frame. * Returns the status of this frame.
*/
int getStreamId();
/**
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
*/
SpdyControlFrame setStreamId(int streamID);
/**
* Returns the getStatus of this frame.
*/ */
SpdyStreamStatus getStatus(); SpdyStreamStatus getStatus();
/** /**
* Sets the getStatus of this frame. * Sets the status of this frame.
*/ */
SpdyControlFrame setStatus(SpdyStreamStatus status); SpdyRstStreamFrame setStatus(SpdyStreamStatus status);
@Override
SpdyRstStreamFrame setStreamId(int streamId);
@Override
SpdyRstStreamFrame setLast(boolean last);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -135,27 +135,29 @@ public class SpdySessionHandler
*/ */
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
int streamID = spdyDataFrame.getStreamId(); int streamId = spdyDataFrame.getStreamId();
// Check if we received a data frame for a Stream-ID which is not open // Check if we received a data frame for a Stream-ID which is not open
if (!spdySession.isActiveStream(streamID)) {
if (streamID <= lastGoodStreamId) { if (!spdySession.isActiveStream(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); if (streamId <= lastGoodStreamId) {
issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR, out);
} else if (!sentGoAwayFrame) { } else if (!sentGoAwayFrame) {
issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM, out);
} }
return; return;
} }
// Check if we received a data frame for a stream which is half-closed // Check if we received a data frame for a stream which is half-closed
if (spdySession.isRemoteSideClosed(streamID)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_ALREADY_CLOSED, out); if (spdySession.isRemoteSideClosed(streamId)) {
issueStreamError(ctx, streamId, SpdyStreamStatus.STREAM_ALREADY_CLOSED, out);
return; return;
} }
// Check if we received a data frame before receiving a SYN_REPLY // Check if we received a data frame before receiving a SYN_REPLY
if (!isRemoteInitiatedID(streamID) && !spdySession.hasReceivedReply(streamID)) { if (!isRemoteInitiatedID(streamId) && !spdySession.hasReceivedReply(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR, out);
return; return;
} }
@ -168,15 +170,15 @@ public class SpdySessionHandler
if (flowControl) { if (flowControl) {
// Update receive window size // Update receive window size
int deltaWindowSize = -1 * spdyDataFrame.content().readableBytes(); int deltaWindowSize = -1 * spdyDataFrame.content().readableBytes();
int newWindowSize = spdySession.updateReceiveWindowSize(streamID, deltaWindowSize); int newWindowSize = spdySession.updateReceiveWindowSize(streamId, deltaWindowSize);
// Window size can become negative if we sent a SETTINGS frame that reduces the // Window size can become negative if we sent a SETTINGS frame that reduces the
// size of the transfer window after the peer has written data frames. // size of the transfer window after the peer has written data frames.
// The value is bounded by the length that SETTINGS frame decrease the window. // The value is bounded by the length that SETTINGS frame decrease the window.
// This difference is stored for the session when writing the SETTINGS frame // This difference is stored for the session when writing the SETTINGS frame
// and is cleared once we send a WINDOW_UPDATE frame. // and is cleared once we send a WINDOW_UPDATE frame.
if (newWindowSize < spdySession.getReceiveWindowSizeLowerBound(streamID)) { if (newWindowSize < spdySession.getReceiveWindowSizeLowerBound(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR, out); issueStreamError(ctx, streamId, SpdyStreamStatus.FLOW_CONTROL_ERROR, out);
return; return;
} }
@ -184,7 +186,7 @@ public class SpdySessionHandler
// Send data frames upstream in initialReceiveWindowSize chunks // Send data frames upstream in initialReceiveWindowSize chunks
if (newWindowSize < 0) { if (newWindowSize < 0) {
while (spdyDataFrame.content().readableBytes() > initialReceiveWindowSize) { while (spdyDataFrame.content().readableBytes() > initialReceiveWindowSize) {
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamID, SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamId,
spdyDataFrame.content().readSlice(initialReceiveWindowSize).retain()); spdyDataFrame.content().readSlice(initialReceiveWindowSize).retain());
ctx.write(partialDataFrame); ctx.write(partialDataFrame);
} }
@ -193,16 +195,16 @@ public class SpdySessionHandler
// Send a WINDOW_UPDATE frame if less than half the window size remains // Send a WINDOW_UPDATE frame if less than half the window size remains
if (newWindowSize <= initialReceiveWindowSize / 2 && !spdyDataFrame.isLast()) { if (newWindowSize <= initialReceiveWindowSize / 2 && !spdyDataFrame.isLast()) {
deltaWindowSize = initialReceiveWindowSize - newWindowSize; deltaWindowSize = initialReceiveWindowSize - newWindowSize;
spdySession.updateReceiveWindowSize(streamID, deltaWindowSize); spdySession.updateReceiveWindowSize(streamId, deltaWindowSize);
SpdyWindowUpdateFrame spdyWindowUpdateFrame = SpdyWindowUpdateFrame spdyWindowUpdateFrame =
new DefaultSpdyWindowUpdateFrame(streamID, deltaWindowSize); new DefaultSpdyWindowUpdateFrame(streamId, deltaWindowSize);
ctx.write(spdyWindowUpdateFrame); ctx.write(spdyWindowUpdateFrame);
} }
} }
// Close the remote side of the stream if this is the last frame // Close the remote side of the stream if this is the last frame
if (spdyDataFrame.isLast()) { if (spdyDataFrame.isLast()) {
halfCloseStream(streamID, true); halfCloseStream(streamId, true);
} }
} else if (msg instanceof SpdySynStreamFrame) { } else if (msg instanceof SpdySynStreamFrame) {
@ -222,18 +224,18 @@ public class SpdySessionHandler
*/ */
SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
int streamID = spdySynStreamFrame.getStreamId(); int streamId = spdySynStreamFrame.getStreamId();
// Check if we received a valid SYN_STREAM frame // Check if we received a valid SYN_STREAM frame
if (spdySynStreamFrame.isInvalid() || if (spdySynStreamFrame.isInvalid() ||
!isRemoteInitiatedID(streamID) || !isRemoteInitiatedID(streamId) ||
spdySession.isActiveStream(streamID)) { spdySession.isActiveStream(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR, out);
return; return;
} }
// Stream-IDs must be monotonically increasing // Stream-IDs must be monotonically increasing
if (streamID <= lastGoodStreamId) { if (streamId <= lastGoodStreamId) {
issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR);
return; return;
} }
@ -242,8 +244,8 @@ public class SpdySessionHandler
byte priority = spdySynStreamFrame.getPriority(); byte priority = spdySynStreamFrame.getPriority();
boolean remoteSideClosed = spdySynStreamFrame.isLast(); boolean remoteSideClosed = spdySynStreamFrame.isLast();
boolean localSideClosed = spdySynStreamFrame.isUnidirectional(); boolean localSideClosed = spdySynStreamFrame.isUnidirectional();
if (!acceptStream(streamID, priority, remoteSideClosed, localSideClosed)) { if (!acceptStream(streamId, priority, remoteSideClosed, localSideClosed)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.REFUSED_STREAM, out); issueStreamError(ctx, streamId, SpdyStreamStatus.REFUSED_STREAM, out);
return; return;
} }
@ -257,27 +259,27 @@ public class SpdySessionHandler
*/ */
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
int streamID = spdySynReplyFrame.getStreamId(); int streamId = spdySynReplyFrame.getStreamId();
// Check if we received a valid SYN_REPLY frame // Check if we received a valid SYN_REPLY frame
if (spdySynReplyFrame.isInvalid() || if (spdySynReplyFrame.isInvalid() ||
isRemoteInitiatedID(streamID) || isRemoteInitiatedID(streamId) ||
spdySession.isRemoteSideClosed(streamID)) { spdySession.isRemoteSideClosed(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM, out);
return; return;
} }
// Check if we have received multiple frames for the same Stream-ID // Check if we have received multiple frames for the same Stream-ID
if (spdySession.hasReceivedReply(streamID)) { if (spdySession.hasReceivedReply(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_IN_USE, out); issueStreamError(ctx, streamId, SpdyStreamStatus.STREAM_IN_USE, out);
return; return;
} }
spdySession.receivedReply(streamID); spdySession.receivedReply(streamId);
// Close the remote side of the stream if this is the last frame // Close the remote side of the stream if this is the last frame
if (spdySynReplyFrame.isLast()) { if (spdySynReplyFrame.isLast()) {
halfCloseStream(streamID, true); halfCloseStream(streamId, true);
} }
} else if (msg instanceof SpdyRstStreamFrame) { } else if (msg instanceof SpdyRstStreamFrame) {
@ -351,22 +353,22 @@ public class SpdySessionHandler
} else if (msg instanceof SpdyHeadersFrame) { } else if (msg instanceof SpdyHeadersFrame) {
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
int streamID = spdyHeadersFrame.getStreamId(); int streamId = spdyHeadersFrame.getStreamId();
// Check if we received a valid HEADERS frame // Check if we received a valid HEADERS frame
if (spdyHeadersFrame.isInvalid()) { if (spdyHeadersFrame.isInvalid()) {
issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR, out);
return; return;
} }
if (spdySession.isRemoteSideClosed(streamID)) { if (spdySession.isRemoteSideClosed(streamId)) {
issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM, out);
return; return;
} }
// Close the remote side of the stream if this is the last frame // Close the remote side of the stream if this is the last frame
if (spdyHeadersFrame.isLast()) { if (spdyHeadersFrame.isLast()) {
halfCloseStream(streamID, true); halfCloseStream(streamId, true);
} }
} else if (msg instanceof SpdyWindowUpdateFrame) { } else if (msg instanceof SpdyWindowUpdateFrame) {
@ -383,21 +385,21 @@ public class SpdySessionHandler
if (flowControl) { if (flowControl) {
SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg; SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg;
int streamID = spdyWindowUpdateFrame.getStreamId(); int streamId = spdyWindowUpdateFrame.getStreamId();
int deltaWindowSize = spdyWindowUpdateFrame.getDeltaWindowSize(); int deltaWindowSize = spdyWindowUpdateFrame.getDeltaWindowSize();
// Ignore frames for half-closed streams // Ignore frames for half-closed streams
if (spdySession.isLocalSideClosed(streamID)) { if (spdySession.isLocalSideClosed(streamId)) {
return; return;
} }
// Check for numerical overflow // Check for numerical overflow
if (spdySession.getSendWindowSize(streamID) > Integer.MAX_VALUE - deltaWindowSize) { if (spdySession.getSendWindowSize(streamId) > Integer.MAX_VALUE - deltaWindowSize) {
issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR, out); issueStreamError(ctx, streamId, SpdyStreamStatus.FLOW_CONTROL_ERROR, out);
return; return;
} }
updateSendWindowSize(streamID, deltaWindowSize, out); updateSendWindowSize(streamId, deltaWindowSize, out);
} }
} }
@ -459,10 +461,10 @@ public class SpdySessionHandler
if (msg instanceof SpdyDataFrame) { if (msg instanceof SpdyDataFrame) {
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
final int streamID = spdyDataFrame.getStreamId(); final int streamId = spdyDataFrame.getStreamId();
// Frames must not be sent on half-closed streams // Frames must not be sent on half-closed streams
if (spdySession.isLocalSideClosed(streamID)) { if (spdySession.isLocalSideClosed(streamId)) {
throw PROTOCOL_EXCEPTION; throw PROTOCOL_EXCEPTION;
} }
@ -482,22 +484,22 @@ public class SpdySessionHandler
if (flowControl) { if (flowControl) {
synchronized (flowControlLock) { synchronized (flowControlLock) {
int dataLength = spdyDataFrame.content().readableBytes(); int dataLength = spdyDataFrame.content().readableBytes();
int sendWindowSize = spdySession.getSendWindowSize(streamID); int sendWindowSize = spdySession.getSendWindowSize(streamId);
if (sendWindowSize <= 0) { if (sendWindowSize <= 0) {
// Stream is stalled -- enqueue Data frame and return // Stream is stalled -- enqueue Data frame and return
spdySession.putPendingWrite(streamID, spdyDataFrame); spdySession.putPendingWrite(streamId, spdyDataFrame);
return; return;
} else if (sendWindowSize < dataLength) { } else if (sendWindowSize < dataLength) {
// Stream is not stalled but we cannot send the entire frame // Stream is not stalled but we cannot send the entire frame
spdySession.updateSendWindowSize(streamID, -1 * sendWindowSize); spdySession.updateSendWindowSize(streamId, -1 * sendWindowSize);
// Create a partial data frame whose length is the current window size // Create a partial data frame whose length is the current window size
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamID, SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamId,
spdyDataFrame.content().readSlice(sendWindowSize).retain()); spdyDataFrame.content().readSlice(sendWindowSize).retain());
// Enqueue the remaining data (will be the first frame queued) // Enqueue the remaining data (will be the first frame queued)
spdySession.putPendingWrite(streamID, spdyDataFrame); spdySession.putPendingWrite(streamId, spdyDataFrame);
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the stream on write failures that leaves the transfer window in a corrupt state. // Close the stream on write failures that leaves the transfer window in a corrupt state.
@ -511,7 +513,7 @@ public class SpdySessionHandler
// @Override // @Override
// public void operationComplete(ChannelFuture future) throws Exception { // public void operationComplete(ChannelFuture future) throws Exception {
// if (!future.isSuccess()) { // if (!future.isSuccess()) {
// issueStreamError(context, streamID, SpdyStreamStatus.INTERNAL_ERROR); // issueStreamError(context, streamId, SpdyStreamStatus.INTERNAL_ERROR);
// } // }
// } // }
//}); //});
@ -520,7 +522,7 @@ public class SpdySessionHandler
return; return;
} else { } else {
// Window size is large enough to send entire data frame // Window size is large enough to send entire data frame
spdySession.updateSendWindowSize(streamID, -1 * dataLength); spdySession.updateSendWindowSize(streamId, -1 * dataLength);
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the stream on write failures that leaves the transfer window in a corrupt state. // Close the stream on write failures that leaves the transfer window in a corrupt state.
@ -533,7 +535,7 @@ public class SpdySessionHandler
// @Override // @Override
// public void operationComplete(ChannelFuture future) throws Exception { // public void operationComplete(ChannelFuture future) throws Exception {
// if (!future.isSuccess()) { // if (!future.isSuccess()) {
// issueStreamError(context, streamID, SpdyStreamStatus.INTERNAL_ERROR); // issueStreamError(context, streamId, SpdyStreamStatus.INTERNAL_ERROR);
// } // }
// } // }
//}); //});
@ -543,38 +545,38 @@ public class SpdySessionHandler
// Close the local side of the stream if this is the last frame // Close the local side of the stream if this is the last frame
if (spdyDataFrame.isLast()) { if (spdyDataFrame.isLast()) {
halfCloseStream(streamID, false); halfCloseStream(streamId, false);
} }
} else if (msg instanceof SpdySynStreamFrame) { } else if (msg instanceof SpdySynStreamFrame) {
SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
int streamID = spdySynStreamFrame.getStreamId(); int streamId = spdySynStreamFrame.getStreamId();
if (isRemoteInitiatedID(streamID)) { if (isRemoteInitiatedID(streamId)) {
throw PROTOCOL_EXCEPTION; throw PROTOCOL_EXCEPTION;
} }
byte priority = spdySynStreamFrame.getPriority(); byte priority = spdySynStreamFrame.getPriority();
boolean remoteSideClosed = spdySynStreamFrame.isUnidirectional(); boolean remoteSideClosed = spdySynStreamFrame.isUnidirectional();
boolean localSideClosed = spdySynStreamFrame.isLast(); boolean localSideClosed = spdySynStreamFrame.isLast();
if (!acceptStream(streamID, priority, remoteSideClosed, localSideClosed)) { if (!acceptStream(streamId, priority, remoteSideClosed, localSideClosed)) {
throw PROTOCOL_EXCEPTION; throw PROTOCOL_EXCEPTION;
} }
} else if (msg instanceof SpdySynReplyFrame) { } else if (msg instanceof SpdySynReplyFrame) {
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
int streamID = spdySynReplyFrame.getStreamId(); int streamId = spdySynReplyFrame.getStreamId();
// Frames must not be sent on half-closed streams // Frames must not be sent on half-closed streams
if (!isRemoteInitiatedID(streamID) || spdySession.isLocalSideClosed(streamID)) { if (!isRemoteInitiatedID(streamId) || spdySession.isLocalSideClosed(streamId)) {
throw PROTOCOL_EXCEPTION; throw PROTOCOL_EXCEPTION;
} }
// Close the local side of the stream if this is the last frame // Close the local side of the stream if this is the last frame
if (spdySynReplyFrame.isLast()) { if (spdySynReplyFrame.isLast()) {
halfCloseStream(streamID, false); halfCloseStream(streamId, false);
} }
} else if (msg instanceof SpdyRstStreamFrame) { } else if (msg instanceof SpdyRstStreamFrame) {
@ -627,16 +629,16 @@ public class SpdySessionHandler
} else if (msg instanceof SpdyHeadersFrame) { } else if (msg instanceof SpdyHeadersFrame) {
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
int streamID = spdyHeadersFrame.getStreamId(); int streamId = spdyHeadersFrame.getStreamId();
// Frames must not be sent on half-closed streams // Frames must not be sent on half-closed streams
if (spdySession.isLocalSideClosed(streamID)) { if (spdySession.isLocalSideClosed(streamId)) {
throw PROTOCOL_EXCEPTION; throw PROTOCOL_EXCEPTION;
} }
// Close the local side of the stream if this is the last frame // Close the local side of the stream if this is the last frame
if (spdyHeadersFrame.isLast()) { if (spdyHeadersFrame.isLast()) {
halfCloseStream(streamID, false); halfCloseStream(streamId, false);
} }
} else if (msg instanceof SpdyWindowUpdateFrame) { } else if (msg instanceof SpdyWindowUpdateFrame) {
@ -675,12 +677,11 @@ public class SpdySessionHandler
* Note: this is only called by the worker thread * Note: this is only called by the worker thread
*/ */
private void issueStreamError( private void issueStreamError(
ChannelHandlerContext ctx, int streamID, SpdyStreamStatus status, MessageList<Object> in) { ChannelHandlerContext ctx, int streamId, SpdyStreamStatus status, MessageList<Object> in) {
boolean fireMessageReceived = !spdySession.isRemoteSideClosed(streamId);
removeStream(ctx, streamId);
boolean fireMessageReceived = !spdySession.isRemoteSideClosed(streamID); SpdyRstStreamFrame spdyRstStreamFrame = new DefaultSpdyRstStreamFrame(streamId, status);
removeStream(ctx, streamID);
SpdyRstStreamFrame spdyRstStreamFrame = new DefaultSpdyRstStreamFrame(streamID, status);
ctx.write(spdyRstStreamFrame); ctx.write(spdyRstStreamFrame);
if (fireMessageReceived) { if (fireMessageReceived) {
in.add(spdyRstStreamFrame); in.add(spdyRstStreamFrame);
@ -694,8 +695,8 @@ public class SpdySessionHandler
*/ */
private boolean isRemoteInitiatedID(int id) { private boolean isRemoteInitiatedID(int id) {
boolean serverID = SpdyCodecUtil.isServerId(id); boolean serverId = SpdyCodecUtil.isServerId(id);
return server && !serverID || !server && serverID; return server && !serverId || !server && serverId;
} }
private void updateConcurrentStreams(int newConcurrentStreams, boolean remote) { private void updateConcurrentStreams(int newConcurrentStreams, boolean remote) {
@ -741,7 +742,7 @@ public class SpdySessionHandler
// need to synchronize accesses to sentGoAwayFrame, lastGoodStreamId, and initial window sizes // need to synchronize accesses to sentGoAwayFrame, lastGoodStreamId, and initial window sizes
private synchronized boolean acceptStream( private synchronized boolean acceptStream(
int streamID, byte priority, boolean remoteSideClosed, boolean localSideClosed) { int streamId, byte priority, boolean remoteSideClosed, boolean localSideClosed) {
// Cannot initiate any new streams after receiving or sending GOAWAY // Cannot initiate any new streams after receiving or sending GOAWAY
if (receivedGoAwayFrame || sentGoAwayFrame) { if (receivedGoAwayFrame || sentGoAwayFrame) {
return false; return false;
@ -753,27 +754,27 @@ public class SpdySessionHandler
return false; return false;
} }
spdySession.acceptStream( spdySession.acceptStream(
streamID, priority, remoteSideClosed, localSideClosed, streamId, priority, remoteSideClosed, localSideClosed,
initialSendWindowSize, initialReceiveWindowSize); initialSendWindowSize, initialReceiveWindowSize);
if (isRemoteInitiatedID(streamID)) { if (isRemoteInitiatedID(streamId)) {
lastGoodStreamId = streamID; lastGoodStreamId = streamId;
} }
return true; return true;
} }
private void halfCloseStream(int streamID, boolean remote) { private void halfCloseStream(int streamId, boolean remote) {
if (remote) { if (remote) {
spdySession.closeRemoteSide(streamID); spdySession.closeRemoteSide(streamId);
} else { } else {
spdySession.closeLocalSide(streamID); spdySession.closeLocalSide(streamId);
} }
if (closeSessionFuture != null && spdySession.noActiveStreams()) { if (closeSessionFuture != null && spdySession.noActiveStreams()) {
closeSessionFuture.trySuccess(); closeSessionFuture.trySuccess();
} }
} }
private void removeStream(ChannelHandlerContext ctx, int streamID) { private void removeStream(ChannelHandlerContext ctx, int streamId) {
if (spdySession.removeStream(streamID)) { if (spdySession.removeStream(streamId)) {
ctx.fireExceptionCaught(STREAM_CLOSED); ctx.fireExceptionCaught(STREAM_CLOSED);
} }
@ -782,13 +783,13 @@ public class SpdySessionHandler
} }
} }
private void updateSendWindowSize(final int streamID, int deltaWindowSize, MessageList<Object> out) { private void updateSendWindowSize(final int streamId, int deltaWindowSize, MessageList<Object> out) {
synchronized (flowControlLock) { synchronized (flowControlLock) {
int newWindowSize = spdySession.updateSendWindowSize(streamID, deltaWindowSize); int newWindowSize = spdySession.updateSendWindowSize(streamId, deltaWindowSize);
while (newWindowSize > 0) { while (newWindowSize > 0) {
// Check if we have unblocked a stalled stream // Check if we have unblocked a stalled stream
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) spdySession.getPendingWrite(streamID); SpdyDataFrame spdyDataFrame = (SpdyDataFrame) spdySession.getPendingWrite(streamId);
if (spdyDataFrame == null) { if (spdyDataFrame == null) {
break; break;
} }
@ -797,8 +798,8 @@ public class SpdySessionHandler
if (newWindowSize >= dataFrameSize) { if (newWindowSize >= dataFrameSize) {
// Window size is large enough to send entire data frame // Window size is large enough to send entire data frame
spdySession.removePendingWrite(streamID); spdySession.removePendingWrite(streamId);
newWindowSize = spdySession.updateSendWindowSize(streamID, -1 * dataFrameSize); newWindowSize = spdySession.updateSendWindowSize(streamId, -1 * dataFrameSize);
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
// Close the stream on write failures that leaves the transfer window in a corrupt state. // Close the stream on write failures that leaves the transfer window in a corrupt state.
@ -811,23 +812,23 @@ public class SpdySessionHandler
// @Override // @Override
// public void operationComplete(ChannelFuture future) throws Exception { // public void operationComplete(ChannelFuture future) throws Exception {
// if (!future.isSuccess()) { // if (!future.isSuccess()) {
// issueStreamError(context, streamID, SpdyStreamStatus.INTERNAL_ERROR); // issueStreamError(context, streamId, SpdyStreamStatus.INTERNAL_ERROR);
// } // }
// } // }
//}); //});
// Close the local side of the stream if this is the last frame // Close the local side of the stream if this is the last frame
if (spdyDataFrame.isLast()) { if (spdyDataFrame.isLast()) {
halfCloseStream(streamID, false); halfCloseStream(streamId, false);
} }
out.add(spdyDataFrame); out.add(spdyDataFrame);
} else { } else {
// We can send a partial frame // We can send a partial frame
spdySession.updateSendWindowSize(streamID, -1 * newWindowSize); spdySession.updateSendWindowSize(streamId, -1 * newWindowSize);
// Create a partial data frame whose length is the current window size // Create a partial data frame whose length is the current window size
SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamID, SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamId,
spdyDataFrame.content().readSlice(newWindowSize).retain()); spdyDataFrame.content().readSlice(newWindowSize).retain());
// The transfer window size is pre-decremented when sending a data frame downstream. // The transfer window size is pre-decremented when sending a data frame downstream.
@ -842,7 +843,7 @@ public class SpdySessionHandler
// @Override // @Override
// public void operationComplete(ChannelFuture future) throws Exception { // public void operationComplete(ChannelFuture future) throws Exception {
// if (!future.isSuccess()) { // if (!future.isSuccess()) {
// issueStreamError(context, streamID, SpdyStreamStatus.INTERNAL_ERROR); // issueStreamError(context, streamId, SpdyStreamStatus.INTERNAL_ERROR);
// } // }
// } // }
//}); //});

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,7 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* The SPDY session getStatus code and its description. * The SPDY session status code and its description.
*/ */
public class SpdySessionStatus implements Comparable<SpdySessionStatus> { public class SpdySessionStatus implements Comparable<SpdySessionStatus> {
@ -40,7 +40,7 @@ public class SpdySessionStatus implements Comparable<SpdySessionStatus> {
/** /**
* Returns the {@link SpdySessionStatus} represented by the specified code. * Returns the {@link SpdySessionStatus} represented by the specified code.
* If the specified code is a defined SPDY getStatus code, a cached instance * If the specified code is a defined SPDY status code, a cached instance
* will be returned. Otherwise, a new instance will be returned. * will be returned. Otherwise, a new instance will be returned.
*/ */
public static SpdySessionStatus valueOf(int code) { public static SpdySessionStatus valueOf(int code) {
@ -74,14 +74,14 @@ public class SpdySessionStatus implements Comparable<SpdySessionStatus> {
} }
/** /**
* Returns the code of this getStatus. * Returns the code of this status.
*/ */
public int getCode() { public int getCode() {
return code; return code;
} }
/** /**
* Returns the getStatus phrase of this getStatus. * Returns the status phrase of this status.
*/ */
public String getStatusPhrase() { public String getStatusPhrase() {
return statusPhrase; return statusPhrase;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -18,9 +18,9 @@ package io.netty.handler.codec.spdy;
import java.util.Set; import java.util.Set;
/** /**
* A SPDY Protocol SETTINGS Control Frame * A SPDY Protocol SETTINGS Frame
*/ */
public interface SpdySettingsFrame extends SpdyControlFrame { public interface SpdySettingsFrame extends SpdyFrame {
int SETTINGS_UPLOAD_BANDWIDTH = 1; int SETTINGS_UPLOAD_BANDWIDTH = 1;
int SETTINGS_DOWNLOAD_BANDWIDTH = 2; int SETTINGS_DOWNLOAD_BANDWIDTH = 2;

View File

@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A frame which is part of a stream * A SPDY Protocol Frame that is associated with an individual SPDY Stream
*/ */
public interface SpdyStreamFrame { public interface SpdyStreamFrame extends SpdyFrame {
/** /**
* Returns the Stream-ID of this frame. * Returns the Stream-ID of this frame.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,7 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* The SPDY stream getStatus code and its description. * The SPDY stream status code and its description.
*/ */
public class SpdyStreamStatus implements Comparable<SpdyStreamStatus> { public class SpdyStreamStatus implements Comparable<SpdyStreamStatus> {
@ -88,13 +88,13 @@ public class SpdyStreamStatus implements Comparable<SpdyStreamStatus> {
/** /**
* Returns the {@link SpdyStreamStatus} represented by the specified code. * Returns the {@link SpdyStreamStatus} represented by the specified code.
* If the specified code is a defined SPDY getStatus code, a cached instance * If the specified code is a defined SPDY status code, a cached instance
* will be returned. Otherwise, a new instance will be returned. * will be returned. Otherwise, a new instance will be returned.
*/ */
public static SpdyStreamStatus valueOf(int code) { public static SpdyStreamStatus valueOf(int code) {
if (code == 0) { if (code == 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"0 is not a valid getStatus code for a RST_STREAM"); "0 is not a valid status code for a RST_STREAM");
} }
switch (code) { switch (code) {
@ -136,7 +136,7 @@ public class SpdyStreamStatus implements Comparable<SpdyStreamStatus> {
public SpdyStreamStatus(int code, String statusPhrase) { public SpdyStreamStatus(int code, String statusPhrase) {
if (code == 0) { if (code == 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"0 is not a valid getStatus code for a RST_STREAM"); "0 is not a valid status code for a RST_STREAM");
} }
if (statusPhrase == null) { if (statusPhrase == null) {
@ -148,14 +148,14 @@ public class SpdyStreamStatus implements Comparable<SpdyStreamStatus> {
} }
/** /**
* Returns the code of this getStatus. * Returns the code of this status.
*/ */
public int getCode() { public int getCode() {
return code; return code;
} }
/** /**
* Returns the getStatus phrase of this getStatus. * Returns the status phrase of this status.
*/ */
public String getStatusPhrase() { public String getStatusPhrase() {
return statusPhrase; return statusPhrase;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol SYN_REPLY Control Frame * A SPDY Protocol SYN_REPLY Frame
*/ */
public interface SpdySynReplyFrame extends SpdyHeaderBlock, SpdyControlFrame, SpdyStreamFrame { public interface SpdySynReplyFrame extends SpdyHeadersFrame {
@Override @Override
SpdySynReplyFrame setStreamId(int streamID); SpdySynReplyFrame setStreamId(int streamID);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol SYN_STREAM Control Frame * A SPDY Protocol SYN_STREAM Frame
*/ */
public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame , SpdyStreamFrame { public interface SpdySynStreamFrame extends SpdyHeadersFrame {
/** /**
* Returns the Associated-To-Stream-ID of this frame. * Returns the Associated-To-Stream-ID of this frame.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -16,9 +16,9 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
/** /**
* A SPDY Protocol WINDOW_UPDATE Control Frame * A SPDY Protocol WINDOW_UPDATE Frame
*/ */
public interface SpdyWindowUpdateFrame extends SpdyControlFrame { public interface SpdyWindowUpdateFrame extends SpdyFrame {
/** /**
* Returns the Stream-ID of this frame. * Returns the Stream-ID of this frame.
@ -26,7 +26,7 @@ public interface SpdyWindowUpdateFrame extends SpdyControlFrame {
int getStreamId(); int getStreamId();
/** /**
* Sets the Stream-ID of this frame. The Stream-ID must be positive. * Sets the Stream-ID of this frame. The Stream-ID cannot be negative.
*/ */
SpdyWindowUpdateFrame setStreamId(int streamID); SpdyWindowUpdateFrame setStreamId(int streamID);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 The Netty Project * Copyright 2013 The Netty Project
* *
* The Netty Project licenses this file to you under the Apache License, * 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 * version 2.0 (the "License"); you may not use this file except in compliance
@ -18,6 +18,7 @@ package io.netty.handler.codec.spdy;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.MessageList; import io.netty.channel.MessageList;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -40,40 +41,25 @@ public class SpdySessionHandlerTest {
closeMessage.setValue(closeSignal, 0); closeMessage.setValue(closeSignal, 0);
} }
private static void assertHeaderBlock(SpdyHeaderBlock received, SpdyHeaderBlock expected) { private static void assertDataFrame(Object msg, int streamId, boolean last) {
for (String name: expected.headers().names()) {
List<String> expectedValues = expected.headers().getAll(name);
List<String> receivedValues = received.headers().getAll(name);
assertTrue(receivedValues.containsAll(expectedValues));
receivedValues.removeAll(expectedValues);
assertTrue(receivedValues.isEmpty());
received.headers().remove(name);
}
assertTrue(received.headers().entries().isEmpty());
}
private static void assertDataFrame(Object msg, int streamID, boolean last) {
assertNotNull(msg); assertNotNull(msg);
assertTrue(msg instanceof SpdyDataFrame); assertTrue(msg instanceof SpdyDataFrame);
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
assertEquals(spdyDataFrame.getStreamId(), streamID); assertEquals(spdyDataFrame.getStreamId(), streamId);
assertEquals(spdyDataFrame.isLast(), last); assertEquals(spdyDataFrame.isLast(), last);
} }
private static void assertSynReply(Object msg, int streamID, boolean last, SpdyHeaderBlock headers) { private static void assertSynReply(Object msg, int streamId, boolean last, SpdyHeaders headers) {
assertNotNull(msg); assertNotNull(msg);
assertTrue(msg instanceof SpdySynReplyFrame); assertTrue(msg instanceof SpdySynReplyFrame);
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; assertHeaders(msg, streamId, last, headers);
assertEquals(spdySynReplyFrame.getStreamId(), streamID);
assertEquals(spdySynReplyFrame.isLast(), last);
assertHeaderBlock(spdySynReplyFrame, headers);
} }
private static void assertRstStream(Object msg, int streamID, SpdyStreamStatus status) { private static void assertRstStream(Object msg, int streamId, SpdyStreamStatus status) {
assertNotNull(msg); assertNotNull(msg);
assertTrue(msg instanceof SpdyRstStreamFrame); assertTrue(msg instanceof SpdyRstStreamFrame);
SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg;
assertEquals(spdyRstStreamFrame.getStreamId(), streamID); assertEquals(spdyRstStreamFrame.getStreamId(), streamId);
assertEquals(spdyRstStreamFrame.getStatus(), status); assertEquals(spdyRstStreamFrame.getStatus(), status);
} }
@ -84,19 +70,28 @@ public class SpdySessionHandlerTest {
assertEquals(spdyPingFrame.getId(), id); assertEquals(spdyPingFrame.getId(), id);
} }
private static void assertGoAway(Object msg, int lastGoodStreamID) { private static void assertGoAway(Object msg, int lastGoodStreamId) {
assertNotNull(msg); assertNotNull(msg);
assertTrue(msg instanceof SpdyGoAwayFrame); assertTrue(msg instanceof SpdyGoAwayFrame);
SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg; SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg;
assertEquals(spdyGoAwayFrame.getLastGoodStreamId(), lastGoodStreamID); assertEquals(spdyGoAwayFrame.getLastGoodStreamId(), lastGoodStreamId);
} }
private static void assertHeaders(Object msg, int streamID, SpdyHeaderBlock headers) { private static void assertHeaders(Object msg, int streamId, boolean last, SpdyHeaders headers) {
assertNotNull(msg); assertNotNull(msg);
assertTrue(msg instanceof SpdyHeadersFrame); assertTrue(msg instanceof SpdyHeadersFrame);
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
assertEquals(spdyHeadersFrame.getStreamId(), streamID); assertEquals(spdyHeadersFrame.getStreamId(), streamId);
assertHeaderBlock(spdyHeadersFrame, headers); assertEquals(spdyHeadersFrame.isLast(), last);
for (String name: headers.names()) {
List<String> expectedValues = headers.getAll(name);
List<String> receivedValues = spdyHeadersFrame.headers().getAll(name);
assertTrue(receivedValues.containsAll(expectedValues));
receivedValues.removeAll(expectedValues);
assertTrue(receivedValues.isEmpty());
spdyHeadersFrame.headers().remove(name);
}
assertTrue(spdyHeadersFrame.headers().entries().isEmpty());
} }
private static void testSpdySessionHandler(int version, boolean server) { private static void testSpdySessionHandler(int version, boolean server) {
@ -107,71 +102,71 @@ public class SpdySessionHandlerTest {
continue; continue;
} }
int localStreamID = server ? 1 : 2; int localStreamId = server ? 1 : 2;
int remoteStreamID = server ? 2 : 1; int remoteStreamId = server ? 2 : 1;
SpdyPingFrame localPingFrame = new DefaultSpdyPingFrame(localStreamID); SpdyPingFrame localPingFrame = new DefaultSpdyPingFrame(localStreamId);
SpdyPingFrame remotePingFrame = new DefaultSpdyPingFrame(remoteStreamID); SpdyPingFrame remotePingFrame = new DefaultSpdyPingFrame(remoteStreamId);
SpdySynStreamFrame spdySynStreamFrame = SpdySynStreamFrame spdySynStreamFrame =
new DefaultSpdySynStreamFrame(localStreamID, 0, (byte) 0); new DefaultSpdySynStreamFrame(localStreamId, 0, (byte) 0);
spdySynStreamFrame.headers().set("Compression", "test"); spdySynStreamFrame.headers().set("Compression", "test");
SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamID); SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamId);
spdyDataFrame.setLast(true); spdyDataFrame.setLast(true);
// Check if session handler returns INVALID_STREAM if it receives // Check if session handler returns INVALID_STREAM if it receives
// a data frame for a Stream-ID that is not open // a data frame for a Stream-ID that is not open
sessionHandler.writeInbound(new DefaultSpdyDataFrame(localStreamID)); sessionHandler.writeInbound(new DefaultSpdyDataFrame(localStreamId));
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.INVALID_STREAM); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.INVALID_STREAM);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler returns PROTOCOL_ERROR if it receives // Check if session handler returns PROTOCOL_ERROR if it receives
// a data frame for a Stream-ID before receiving a SYN_REPLY frame // a data frame for a Stream-ID before receiving a SYN_REPLY frame
sessionHandler.writeInbound(new DefaultSpdyDataFrame(remoteStreamID)); sessionHandler.writeInbound(new DefaultSpdyDataFrame(remoteStreamId));
assertRstStream(sessionHandler.readOutbound(), remoteStreamID, SpdyStreamStatus.PROTOCOL_ERROR); assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
remoteStreamID += 2; remoteStreamId += 2;
// Check if session handler returns PROTOCOL_ERROR if it receives // Check if session handler returns PROTOCOL_ERROR if it receives
// multiple SYN_REPLY frames for the same active Stream-ID // multiple SYN_REPLY frames for the same active Stream-ID
sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamID)); sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId));
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamID)); sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId));
assertRstStream(sessionHandler.readOutbound(), remoteStreamID, SpdyStreamStatus.STREAM_IN_USE); assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.STREAM_IN_USE);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
remoteStreamID += 2; remoteStreamId += 2;
// Check if frame codec correctly compresses/uncompresses headers // Check if frame codec correctly compresses/uncompresses headers
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertSynReply(sessionHandler.readOutbound(), localStreamID, false, spdySynStreamFrame); assertSynReply(sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers());
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamID); SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamId);
spdyHeadersFrame.headers().add("HEADER", "test1"); spdyHeadersFrame.headers().add("HEADER", "test1");
spdyHeadersFrame.headers().add("HEADER", "test2"); spdyHeadersFrame.headers().add("HEADER", "test2");
sessionHandler.writeInbound(spdyHeadersFrame); sessionHandler.writeInbound(spdyHeadersFrame);
assertHeaders(sessionHandler.readOutbound(), localStreamID, spdyHeadersFrame); assertHeaders(sessionHandler.readOutbound(), localStreamId, false, spdyHeadersFrame.headers());
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
localStreamID += 2; localStreamId += 2;
// Check if session handler closed the streams using the number // Check if session handler closed the streams using the number
// of concurrent streams and that it returns REFUSED_STREAM // of concurrent streams and that it returns REFUSED_STREAM
// if it receives a SYN_STREAM frame it does not wish to accept // if it receives a SYN_STREAM frame it does not wish to accept
spdySynStreamFrame.setStreamId(localStreamID); spdySynStreamFrame.setStreamId(localStreamId);
spdySynStreamFrame.setLast(true); spdySynStreamFrame.setLast(true);
spdySynStreamFrame.setUnidirectional(true); spdySynStreamFrame.setUnidirectional(true);
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.REFUSED_STREAM); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler drops active streams if it receives // Check if session handler drops active streams if it receives
// a RST_STREAM frame for that Stream-ID // a RST_STREAM frame for that Stream-ID
sessionHandler.writeInbound(new DefaultSpdyRstStreamFrame(remoteStreamID, 3)); sessionHandler.writeInbound(new DefaultSpdyRstStreamFrame(remoteStreamId, 3));
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
remoteStreamID += 2; remoteStreamId += 2;
// Check if session handler honors UNIDIRECTIONAL streams // Check if session handler honors UNIDIRECTIONAL streams
spdySynStreamFrame.setLast(false); spdySynStreamFrame.setLast(false);
@ -182,17 +177,17 @@ public class SpdySessionHandlerTest {
// Check if session handler returns PROTOCOL_ERROR if it receives // Check if session handler returns PROTOCOL_ERROR if it receives
// multiple SYN_STREAM frames for the same active Stream-ID // multiple SYN_STREAM frames for the same active Stream-ID
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.PROTOCOL_ERROR); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
localStreamID += 2; localStreamId += 2;
// Check if session handler returns PROTOCOL_ERROR if it receives // Check if session handler returns PROTOCOL_ERROR if it receives
// a SYN_STREAM frame with an invalid Stream-ID // a SYN_STREAM frame with an invalid Stream-ID
spdySynStreamFrame.setStreamId(localStreamID - 1); spdySynStreamFrame.setStreamId(localStreamId - 1);
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID - 1, SpdyStreamStatus.PROTOCOL_ERROR); assertRstStream(sessionHandler.readOutbound(), localStreamId - 1, SpdyStreamStatus.PROTOCOL_ERROR);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
spdySynStreamFrame.setStreamId(localStreamID); spdySynStreamFrame.setStreamId(localStreamId);
// Check if session handler correctly limits the number of // Check if session handler correctly limits the number of
// concurrent streams in the SETTINGS frame // concurrent streams in the SETTINGS frame
@ -201,33 +196,33 @@ public class SpdySessionHandlerTest {
sessionHandler.writeInbound(spdySettingsFrame); sessionHandler.writeInbound(spdySettingsFrame);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.REFUSED_STREAM); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
spdySettingsFrame.setValue(SpdySettingsFrame.SETTINGS_MAX_CONCURRENT_STREAMS, 4); spdySettingsFrame.setValue(SpdySettingsFrame.SETTINGS_MAX_CONCURRENT_STREAMS, 4);
sessionHandler.writeInbound(spdySettingsFrame); sessionHandler.writeInbound(spdySettingsFrame);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertSynReply(sessionHandler.readOutbound(), localStreamID, false, spdySynStreamFrame); assertSynReply(sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers());
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler rejects HEADERS for closed streams // Check if session handler rejects HEADERS for closed streams
int testStreamID = spdyDataFrame.getStreamId(); int testStreamId = spdyDataFrame.getStreamId();
sessionHandler.writeInbound(spdyDataFrame); sessionHandler.writeInbound(spdyDataFrame);
assertDataFrame(sessionHandler.readOutbound(), testStreamID, spdyDataFrame.isLast()); assertDataFrame(sessionHandler.readOutbound(), testStreamId, spdyDataFrame.isLast());
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
spdyHeadersFrame.setStreamId(testStreamID); spdyHeadersFrame.setStreamId(testStreamId);
sessionHandler.writeInbound(spdyHeadersFrame); sessionHandler.writeInbound(spdyHeadersFrame);
assertRstStream(sessionHandler.readOutbound(), testStreamID, SpdyStreamStatus.INVALID_STREAM); assertRstStream(sessionHandler.readOutbound(), testStreamId, SpdyStreamStatus.INVALID_STREAM);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler returns PROTOCOL_ERROR if it receives // Check if session handler returns PROTOCOL_ERROR if it receives
// an invalid HEADERS frame // an invalid HEADERS frame
spdyHeadersFrame.setStreamId(localStreamID); spdyHeadersFrame.setStreamId(localStreamId);
spdyHeadersFrame.setInvalid(); spdyHeadersFrame.setInvalid();
sessionHandler.writeInbound(spdyHeadersFrame); sessionHandler.writeInbound(spdyHeadersFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.PROTOCOL_ERROR); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler returns identical local PINGs // Check if session handler returns identical local PINGs
@ -241,20 +236,20 @@ public class SpdySessionHandlerTest {
// Check if session handler sends a GOAWAY frame when closing // Check if session handler sends a GOAWAY frame when closing
sessionHandler.writeInbound(closeMessage); sessionHandler.writeInbound(closeMessage);
assertGoAway(sessionHandler.readOutbound(), localStreamID); assertGoAway(sessionHandler.readOutbound(), localStreamId);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
localStreamID += 2; localStreamId += 2;
// Check if session handler returns REFUSED_STREAM if it receives // Check if session handler returns REFUSED_STREAM if it receives
// SYN_STREAM frames after sending a GOAWAY frame // SYN_STREAM frames after sending a GOAWAY frame
spdySynStreamFrame.setStreamId(localStreamID); spdySynStreamFrame.setStreamId(localStreamId);
sessionHandler.writeInbound(spdySynStreamFrame); sessionHandler.writeInbound(spdySynStreamFrame);
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.REFUSED_STREAM); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
// Check if session handler ignores Data frames after sending // Check if session handler ignores Data frames after sending
// a GOAWAY frame // a GOAWAY frame
spdyDataFrame.setStreamId(localStreamID); spdyDataFrame.setStreamId(localStreamId);
sessionHandler.writeInbound(spdyDataFrame); sessionHandler.writeInbound(spdyDataFrame);
assertNull(sessionHandler.readOutbound()); assertNull(sessionHandler.readOutbound());
@ -279,7 +274,7 @@ public class SpdySessionHandlerTest {
// Echo Handler opens 4 half-closed streams on session connection // Echo Handler opens 4 half-closed streams on session connection
// and then sets the number of concurrent streams to 3 // and then sets the number of concurrent streams to 3
private static class EchoHandler extends ChannelInboundHandlerAdapter { private static class EchoHandler extends SimpleChannelInboundHandler<Object> {
private final int closeSignal; private final int closeSignal;
private final boolean server; private final boolean server;
@ -291,9 +286,9 @@ public class SpdySessionHandlerTest {
@Override @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Initiate 4 new streams // Initiate 4 new streams
int streamID = server ? 2 : 1; int streamId = server ? 2 : 1;
SpdySynStreamFrame spdySynStreamFrame = SpdySynStreamFrame spdySynStreamFrame =
new DefaultSpdySynStreamFrame(streamID, 0, (byte) 0); new DefaultSpdySynStreamFrame(streamId, 0, (byte) 0);
spdySynStreamFrame.setLast(true); spdySynStreamFrame.setLast(true);
ctx.write(spdySynStreamFrame); ctx.write(spdySynStreamFrame);
spdySynStreamFrame.setStreamId(spdySynStreamFrame.getStreamId() + 2); spdySynStreamFrame.setStreamId(spdySynStreamFrame.getStreamId() + 2);
@ -310,38 +305,39 @@ public class SpdySessionHandlerTest {
} }
@Override @Override
public void messageReceived(ChannelHandlerContext ctx, MessageList<Object> messages) throws Exception { public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
for (int i = 0; i < messages.size(); i++) { if (msg instanceof SpdySynStreamFrame) {
Object msg = messages.get(i);
if (msg instanceof SpdyDataFrame ||
msg instanceof SpdyPingFrame ||
msg instanceof SpdyHeadersFrame) {
ctx.write(msg); SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
return; if (!spdySynStreamFrame.isUnidirectional()) {
} int streamId = spdySynStreamFrame.getStreamId();
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId);
if (msg instanceof SpdySynStreamFrame) { spdySynReplyFrame.setLast(spdySynStreamFrame.isLast());
for (Map.Entry<String, String> entry: spdySynStreamFrame.headers()) {
SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
if (!spdySynStreamFrame.isUnidirectional()) {
int streamID = spdySynStreamFrame.getStreamId();
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID);
spdySynReplyFrame.setLast(spdySynStreamFrame.isLast());
for (Map.Entry<String, String> entry: spdySynStreamFrame.headers()) {
spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
}
ctx.write(spdySynReplyFrame);
} }
return;
}
if (msg instanceof SpdySettingsFrame) { ctx.write(spdySynReplyFrame);
SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; }
if (spdySettingsFrame.isSet(closeSignal)) { return;
ctx.close(); }
}
if (msg instanceof SpdySynReplyFrame) {
return;
}
if (msg instanceof SpdyDataFrame ||
msg instanceof SpdyPingFrame ||
msg instanceof SpdyHeadersFrame) {
ctx.write(msg);
return;
}
if (msg instanceof SpdySettingsFrame) {
SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg;
if (spdySettingsFrame.isSet(closeSignal)) {
ctx.close();
} }
} }
} }