diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyDataFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyDataFrame.java deleted file mode 100644 index a1e9d73d1f..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyDataFrame.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.IllegalReferenceCountException; -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdyDataFrame} implementation. - */ -public class DefaultSpdyDataFrame extends DefaultSpdyStreamFrame implements SpdyDataFrame { - - private final ByteBuf data; - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - */ - public DefaultSpdyDataFrame(int streamId) { - this(streamId, Unpooled.buffer(0)); - } - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param data the payload of the frame. Can not exceed {@link SpdyCodecUtil#SPDY_MAX_LENGTH} - */ - public DefaultSpdyDataFrame(int streamId, ByteBuf data) { - super(streamId); - if (data == null) { - throw new NullPointerException("data"); - } - this.data = validate(data); - } - - private static ByteBuf validate(ByteBuf data) { - if (data.readableBytes() > SpdyCodecUtil.SPDY_MAX_LENGTH) { - throw new IllegalArgumentException("data payload cannot exceed " - + SpdyCodecUtil.SPDY_MAX_LENGTH + " bytes"); - } - return data; - } - - @Override - public SpdyDataFrame setStreamId(int streamId) { - super.setStreamId(streamId); - return this; - } - - @Override - public SpdyDataFrame setLast(boolean last) { - super.setLast(last); - return this; - } - - @Override - public ByteBuf content() { - if (data.refCnt() <= 0) { - throw new IllegalReferenceCountException(data.refCnt()); - } - return data; - } - - @Override - public SpdyDataFrame copy() { - return replace(content().copy()); - } - - @Override - public SpdyDataFrame duplicate() { - return replace(content().duplicate()); - } - - @Override - public SpdyDataFrame retainedDuplicate() { - return replace(content().retainedDuplicate()); - } - - @Override - public SpdyDataFrame replace(ByteBuf content) { - SpdyDataFrame frame = new DefaultSpdyDataFrame(streamId(), content); - frame.setLast(isLast()); - return frame; - } - - @Override - public int refCnt() { - return data.refCnt(); - } - - @Override - public SpdyDataFrame retain() { - data.retain(); - return this; - } - - @Override - public SpdyDataFrame retain(int increment) { - data.retain(increment); - return this; - } - - @Override - public SpdyDataFrame touch() { - data.touch(); - return this; - } - - @Override - public SpdyDataFrame touch(Object hint) { - data.touch(hint); - return this; - } - - @Override - public boolean release() { - return data.release(); - } - - @Override - public boolean release(int decrement) { - return data.release(decrement); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append("(last: ") - .append(isLast()) - .append(')') - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE) - .append("--> Size = "); - if (refCnt() == 0) { - buf.append("(freed)"); - } else { - buf.append(content().readableBytes()); - } - return buf.toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java deleted file mode 100644 index 4d88875a6e..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdyGoAwayFrame} implementation. - */ -public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame { - - private int lastGoodStreamId; - private SpdySessionStatus status; - - /** - * Creates a new instance. - * - * @param lastGoodStreamId the Last-good-stream-ID of this frame - */ - public DefaultSpdyGoAwayFrame(int lastGoodStreamId) { - this(lastGoodStreamId, 0); - } - - /** - * Creates a new instance. - * - * @param lastGoodStreamId the Last-good-stream-ID of this frame - * @param statusCode the Status code of this frame - */ - public DefaultSpdyGoAwayFrame(int lastGoodStreamId, int statusCode) { - this(lastGoodStreamId, SpdySessionStatus.valueOf(statusCode)); - } - - /** - * Creates a new instance. - * - * @param lastGoodStreamId the Last-good-stream-ID of this frame - * @param status the status of this frame - */ - public DefaultSpdyGoAwayFrame(int lastGoodStreamId, SpdySessionStatus status) { - setLastGoodStreamId(lastGoodStreamId); - setStatus(status); - } - - @Override - public int lastGoodStreamId() { - return lastGoodStreamId; - } - - @Override - public SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId) { - if (lastGoodStreamId < 0) { - throw new IllegalArgumentException("Last-good-stream-ID" - + " cannot be negative: " + lastGoodStreamId); - } - this.lastGoodStreamId = lastGoodStreamId; - return this; - } - - @Override - public SpdySessionStatus status() { - return status; - } - - @Override - public SpdyGoAwayFrame setStatus(SpdySessionStatus status) { - this.status = status; - return this; - } - - @Override - public String toString() { - return new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append(StringUtil.NEWLINE) - .append("--> Last-good-stream-ID = ") - .append(lastGoodStreamId()) - .append(StringUtil.NEWLINE) - .append("--> Status: ") - .append(status()) - .toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java deleted file mode 100644 index 6b2b96a777..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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; - -import io.netty.handler.codec.CharSequenceValueConverter; -import io.netty.handler.codec.DefaultHeaders; -import io.netty.handler.codec.HeadersUtils; - -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER; -import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER; - -public class DefaultSpdyHeaders extends DefaultHeaders implements SpdyHeaders { - private static final NameValidator SpdyNameValidator = SpdyCodecUtil::validateHeaderName; - - public DefaultSpdyHeaders() { - this(true); - } - - @SuppressWarnings("unchecked") - public DefaultSpdyHeaders(boolean validate) { - super(CASE_INSENSITIVE_HASHER, - validate ? HeaderValueConverterAndValidator.INSTANCE : CharSequenceValueConverter.INSTANCE, - validate ? SpdyNameValidator : NameValidator.NOT_NULL); - } - - @Override - public String getAsString(CharSequence name) { - return HeadersUtils.getAsString(this, name); - } - - @Override - public List getAllAsString(CharSequence name) { - return HeadersUtils.getAllAsString(this, name); - } - - @Override - public Iterator> iteratorAsString() { - return HeadersUtils.iteratorAsString(this); - } - - @Override - public boolean contains(CharSequence name, CharSequence value) { - return contains(name, value, false); - } - - @Override - public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) { - return contains(name, value, - ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER); - } - - private static final class HeaderValueConverterAndValidator extends CharSequenceValueConverter { - public static final HeaderValueConverterAndValidator INSTANCE = new HeaderValueConverterAndValidator(); - - @Override - public CharSequence convertObject(Object value) { - final CharSequence seq = super.convertObject(value); - SpdyCodecUtil.validateHeaderValue(seq); - return seq; - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersFrame.java deleted file mode 100644 index f177144393..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersFrame.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -import java.util.Map; - -/** - * The default {@link SpdyHeadersFrame} implementation. - */ -public class DefaultSpdyHeadersFrame extends DefaultSpdyStreamFrame - implements SpdyHeadersFrame { - - private boolean invalid; - private boolean truncated; - private final SpdyHeaders headers; - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - */ - public DefaultSpdyHeadersFrame(int streamId) { - this(streamId, true); - } - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param validate validate the header names and values when adding them to the {@link SpdyHeaders} - */ - public DefaultSpdyHeadersFrame(int streamId, boolean validate) { - super(streamId); - headers = new DefaultSpdyHeaders(validate); - } - - @Override - public SpdyHeadersFrame setStreamId(int streamId) { - super.setStreamId(streamId); - return this; - } - - @Override - public SpdyHeadersFrame setLast(boolean last) { - super.setLast(last); - return this; - } - - @Override - public boolean isInvalid() { - return invalid; - } - - @Override - public SpdyHeadersFrame setInvalid() { - invalid = true; - return this; - } - - @Override - public boolean isTruncated() { - return truncated; - } - - @Override - public SpdyHeadersFrame setTruncated() { - truncated = true; - return this; - } - - @Override - public SpdyHeaders headers() { - return headers; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append("(last: ") - .append(isLast()) - .append(')') - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE) - .append("--> Headers:") - .append(StringUtil.NEWLINE); - appendHeaders(buf); - - // Remove the last newline. - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - return buf.toString(); - } - - protected void appendHeaders(StringBuilder buf) { - for (Map.Entry e: headers()) { - buf.append(" "); - buf.append(e.getKey()); - buf.append(": "); - buf.append(e.getValue()); - buf.append(StringUtil.NEWLINE); - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyPingFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyPingFrame.java deleted file mode 100644 index 37c8a41398..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyPingFrame.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdyPingFrame} implementation. - */ -public class DefaultSpdyPingFrame implements SpdyPingFrame { - - private int id; - - /** - * Creates a new instance. - * - * @param id the unique ID of this frame - */ - public DefaultSpdyPingFrame(int id) { - setId(id); - } - - @Override - public int id() { - return id; - } - - @Override - public SpdyPingFrame setId(int id) { - this.id = id; - return this; - } - - @Override - public String toString() { - return new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append(StringUtil.NEWLINE) - .append("--> ID = ") - .append(id()) - .toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyRstStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyRstStreamFrame.java deleted file mode 100644 index a884295bdf..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyRstStreamFrame.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdyRstStreamFrame} implementation. - */ -public class DefaultSpdyRstStreamFrame extends DefaultSpdyStreamFrame - implements SpdyRstStreamFrame { - - private SpdyStreamStatus status; - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param statusCode the Status code of this frame - */ - public DefaultSpdyRstStreamFrame(int streamId, int statusCode) { - this(streamId, SpdyStreamStatus.valueOf(statusCode)); - } - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param status the status of this frame - */ - public DefaultSpdyRstStreamFrame(int streamId, SpdyStreamStatus status) { - super(streamId); - setStatus(status); - } - - @Override - public SpdyRstStreamFrame setStreamId(int streamId) { - super.setStreamId(streamId); - return this; - } - - @Override - public SpdyRstStreamFrame setLast(boolean last) { - super.setLast(last); - return this; - } - - @Override - public SpdyStreamStatus status() { - return status; - } - - @Override - public SpdyRstStreamFrame setStatus(SpdyStreamStatus status) { - this.status = status; - return this; - } - - @Override - public String toString() { - return new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE) - .append("--> Status: ") - .append(status()) - .toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySettingsFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySettingsFrame.java deleted file mode 100644 index cbebb4a0b0..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySettingsFrame.java +++ /dev/null @@ -1,184 +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; -import java.util.Set; -import java.util.TreeMap; - -/** - * The default {@link SpdySettingsFrame} implementation. - */ -public class DefaultSpdySettingsFrame implements SpdySettingsFrame { - - private boolean clear; - private final Map settingsMap = new TreeMap<>(); - - @Override - public Set ids() { - return settingsMap.keySet(); - } - - @Override - public boolean isSet(int id) { - return settingsMap.containsKey(id); - } - - @Override - public int getValue(int id) { - final Setting setting = settingsMap.get(id); - return setting != null ? setting.getValue() : -1; - } - - @Override - public SpdySettingsFrame setValue(int id, int value) { - return setValue(id, value, false, false); - } - - @Override - public SpdySettingsFrame setValue(int id, int value, boolean persistValue, boolean persisted) { - if (id < 0 || id > SpdyCodecUtil.SPDY_SETTINGS_MAX_ID) { - throw new IllegalArgumentException("Setting ID is not valid: " + id); - } - final Integer key = Integer.valueOf(id); - final Setting setting = settingsMap.get(key); - if (setting != null) { - setting.setValue(value); - setting.setPersist(persistValue); - setting.setPersisted(persisted); - } else { - settingsMap.put(key, new Setting(value, persistValue, persisted)); - } - return this; - } - - @Override - public SpdySettingsFrame removeValue(int id) { - settingsMap.remove(id); - return this; - } - - @Override - public boolean isPersistValue(int id) { - final Setting setting = settingsMap.get(id); - return setting != null && setting.isPersist(); - } - - @Override - public SpdySettingsFrame setPersistValue(int id, boolean persistValue) { - final Setting setting = settingsMap.get(id); - if (setting != null) { - setting.setPersist(persistValue); - } - return this; - } - - @Override - public boolean isPersisted(int id) { - final Setting setting = settingsMap.get(id); - return setting != null && setting.isPersisted(); - } - - @Override - public SpdySettingsFrame setPersisted(int id, boolean persisted) { - final Setting setting = settingsMap.get(id); - if (setting != null) { - setting.setPersisted(persisted); - } - return this; - } - - @Override - public boolean clearPreviouslyPersistedSettings() { - return clear; - } - - @Override - public SpdySettingsFrame setClearPreviouslyPersistedSettings(boolean clear) { - this.clear = clear; - return this; - } - - private Set> getSettings() { - return settingsMap.entrySet(); - } - - private void appendSettings(StringBuilder buf) { - for (Map.Entry e: getSettings()) { - Setting setting = e.getValue(); - buf.append("--> "); - buf.append(e.getKey()); - buf.append(':'); - buf.append(setting.getValue()); - buf.append(" (persist value: "); - buf.append(setting.isPersist()); - buf.append("; persisted: "); - buf.append(setting.isPersisted()); - buf.append(')'); - buf.append(StringUtil.NEWLINE); - } - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append(StringUtil.NEWLINE); - appendSettings(buf); - - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - return buf.toString(); - } - - private static final class Setting { - - private int value; - private boolean persist; - private boolean persisted; - - Setting(int value, boolean persist, boolean persisted) { - this.value = value; - this.persist = persist; - this.persisted = persisted; - } - - int getValue() { - return value; - } - - void setValue(int value) { - this.value = value; - } - - boolean isPersist() { - return persist; - } - - void setPersist(boolean persist) { - this.persist = persist; - } - - boolean isPersisted() { - return persisted; - } - - void setPersisted(boolean persisted) { - this.persisted = persisted; - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java deleted file mode 100644 index 4618d4d4a9..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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); - } - - @Override - public int streamId() { - return streamId; - } - - @Override - public SpdyStreamFrame setStreamId(int streamId) { - if (streamId <= 0) { - throw new IllegalArgumentException( - "Stream-ID must be positive: " + streamId); - } - this.streamId = streamId; - return this; - } - - @Override - public boolean isLast() { - return last; - } - - @Override - public SpdyStreamFrame setLast(boolean last) { - this.last = last; - return this; - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java deleted file mode 100644 index 7efc905641..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdySynReplyFrame} implementation. - */ -public class DefaultSpdySynReplyFrame extends DefaultSpdyHeadersFrame - implements SpdySynReplyFrame { - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - */ - public DefaultSpdySynReplyFrame(int streamId) { - super(streamId); - } - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param validateHeaders validate the header names and values when adding them to the {@link SpdyHeaders} - */ - public DefaultSpdySynReplyFrame(int streamId, boolean validateHeaders) { - super(streamId, validateHeaders); - } - - @Override - public SpdySynReplyFrame setStreamId(int streamId) { - super.setStreamId(streamId); - return this; - } - - @Override - public SpdySynReplyFrame setLast(boolean last) { - super.setLast(last); - return this; - } - - @Override - public SpdySynReplyFrame setInvalid() { - super.setInvalid(); - return this; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append("(last: ") - .append(isLast()) - .append(')') - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE) - .append("--> Headers:") - .append(StringUtil.NEWLINE); - appendHeaders(buf); - - // Remove the last newline. - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - return buf.toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java deleted file mode 100644 index f8adc1c5f1..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdySynStreamFrame} implementation. - */ -public class DefaultSpdySynStreamFrame extends DefaultSpdyHeadersFrame - implements SpdySynStreamFrame { - - private int associatedStreamId; - private byte priority; - private boolean unidirectional; - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param associatedStreamId the Associated-To-Stream-ID of this frame - * @param priority the priority of the stream - */ - public DefaultSpdySynStreamFrame(int streamId, int associatedStreamId, byte priority) { - this(streamId, associatedStreamId, priority, true); - } - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param associatedStreamId the Associated-To-Stream-ID of this frame - * @param priority the priority of the stream - * @param validateHeaders validate the header names and values when adding them to the {@link SpdyHeaders} - */ - public DefaultSpdySynStreamFrame(int streamId, int associatedStreamId, byte priority, boolean validateHeaders) { - super(streamId, validateHeaders); - setAssociatedStreamId(associatedStreamId); - setPriority(priority); - } - - @Override - public SpdySynStreamFrame setStreamId(int streamId) { - super.setStreamId(streamId); - return this; - } - - @Override - public SpdySynStreamFrame setLast(boolean last) { - super.setLast(last); - return this; - } - - @Override - public SpdySynStreamFrame setInvalid() { - super.setInvalid(); - return this; - } - - @Override - public int associatedStreamId() { - return associatedStreamId; - } - - @Override - public SpdySynStreamFrame setAssociatedStreamId(int associatedStreamId) { - if (associatedStreamId < 0) { - throw new IllegalArgumentException( - "Associated-To-Stream-ID cannot be negative: " + - associatedStreamId); - } - this.associatedStreamId = associatedStreamId; - return this; - } - - @Override - public byte priority() { - return priority; - } - - @Override - public SpdySynStreamFrame setPriority(byte priority) { - if (priority < 0 || priority > 7) { - throw new IllegalArgumentException( - "Priority must be between 0 and 7 inclusive: " + priority); - } - this.priority = priority; - return this; - } - - @Override - public boolean isUnidirectional() { - return unidirectional; - } - - @Override - public SpdySynStreamFrame setUnidirectional(boolean unidirectional) { - this.unidirectional = unidirectional; - return this; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append("(last: ") - .append(isLast()) - .append("; unidirectional: ") - .append(isUnidirectional()) - .append(')') - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE); - if (associatedStreamId != 0) { - buf.append("--> Associated-To-Stream-ID = ") - .append(associatedStreamId()) - .append(StringUtil.NEWLINE); - } - buf.append("--> Priority = ") - .append(priority()) - .append(StringUtil.NEWLINE) - .append("--> Headers:") - .append(StringUtil.NEWLINE); - appendHeaders(buf); - - // Remove the last newline. - buf.setLength(buf.length() - StringUtil.NEWLINE.length()); - return buf.toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java deleted file mode 100644 index f14611bac6..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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; - -import io.netty.util.internal.StringUtil; - -/** - * The default {@link SpdyWindowUpdateFrame} implementation. - */ -public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame { - - private int streamId; - private int deltaWindowSize; - - /** - * Creates a new instance. - * - * @param streamId the Stream-ID of this frame - * @param deltaWindowSize the Delta-Window-Size of this frame - */ - public DefaultSpdyWindowUpdateFrame(int streamId, int deltaWindowSize) { - setStreamId(streamId); - setDeltaWindowSize(deltaWindowSize); - } - - @Override - public int streamId() { - return streamId; - } - - @Override - public SpdyWindowUpdateFrame setStreamId(int streamId) { - if (streamId < 0) { - throw new IllegalArgumentException( - "Stream-ID cannot be negative: " + streamId); - } - this.streamId = streamId; - return this; - } - - @Override - public int deltaWindowSize() { - return deltaWindowSize; - } - - @Override - public SpdyWindowUpdateFrame setDeltaWindowSize(int deltaWindowSize) { - if (deltaWindowSize <= 0) { - throw new IllegalArgumentException( - "Delta-Window-Size must be positive: " + - deltaWindowSize); - } - this.deltaWindowSize = deltaWindowSize; - return this; - } - - @Override - public String toString() { - return new StringBuilder() - .append(StringUtil.simpleClassName(this)) - .append(StringUtil.NEWLINE) - .append("--> Stream-ID = ") - .append(streamId()) - .append(StringUtil.NEWLINE) - .append("--> Delta-Window-Size = ") - .append(deltaWindowSize()) - .toString(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyCodecUtil.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyCodecUtil.java deleted file mode 100644 index b25167c3a9..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyCodecUtil.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; - -final class SpdyCodecUtil { - - static final int SPDY_SESSION_STREAM_ID = 0; - - static final int SPDY_HEADER_TYPE_OFFSET = 2; - static final int SPDY_HEADER_FLAGS_OFFSET = 4; - static final int SPDY_HEADER_LENGTH_OFFSET = 5; - static final int SPDY_HEADER_SIZE = 8; - - static final int SPDY_MAX_LENGTH = 0xFFFFFF; // Length is a 24-bit field - - static final byte SPDY_DATA_FLAG_FIN = 0x01; - - static final int SPDY_DATA_FRAME = 0; - static final int SPDY_SYN_STREAM_FRAME = 1; - static final int SPDY_SYN_REPLY_FRAME = 2; - static final int SPDY_RST_STREAM_FRAME = 3; - static final int SPDY_SETTINGS_FRAME = 4; - static final int SPDY_PUSH_PROMISE_FRAME = 5; - static final int SPDY_PING_FRAME = 6; - static final int SPDY_GOAWAY_FRAME = 7; - static final int SPDY_HEADERS_FRAME = 8; - static final int SPDY_WINDOW_UPDATE_FRAME = 9; - - static final byte SPDY_FLAG_FIN = 0x01; - static final byte SPDY_FLAG_UNIDIRECTIONAL = 0x02; - - static final byte SPDY_SETTINGS_CLEAR = 0x01; - static final byte SPDY_SETTINGS_PERSIST_VALUE = 0x01; - static final byte SPDY_SETTINGS_PERSISTED = 0x02; - - static final int SPDY_SETTINGS_MAX_ID = 0xFFFFFF; // ID is a 24-bit field - - static final int SPDY_MAX_NV_LENGTH = 0xFFFF; // Length is a 16-bit field - - // Zlib Dictionary - static final byte[] SPDY_DICT = { - 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // - - - - o p t i - 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // o n s - - - - h - 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // e a d - - - - p - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // o s t - - - - p - 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // u t - - - - d e - 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // l e t e - - - - - 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // t r a c e - - - - 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // - a c c e p t - - 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p - 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t - c h a r s e - 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t - - - - a c c - 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e p t - e n c o - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // d i n g - - - - - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // a c c e p t - l - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // a n g u a g e - - 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p - 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t - r a n g e s - 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // - - - - a g e - - 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // - - - a l l o w - 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // - - - - a u t h - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // o r i z a t i o - 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n - - - - c a c - 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // h e - c o n t r - 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // o l - - - - c o - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // n n e c t i o n - 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t - 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // e n t - b a s e - 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t - 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e n t - e n c o - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // d i n g - - - - - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // c o n t e n t - - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // l a n g u a g e - 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t - 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // e n t - l e n g - 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // t h - - - - c o - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // n t e n t - l o - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // c a t i o n - - - 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n - 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t - m d 5 - - - - 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // - c o n t e n t - 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // - r a n g e - - - 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n - 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t - t y p e - - - 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // - - d a t e - - - 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // - - e t a g - - - 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // - - e x p e c t - 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // - - - - e x p i - 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // r e s - - - - f - 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // r o m - - - - h - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // o s t - - - - i - 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f - m a t c h - - 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // - - - i f - m o - 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // d i f i e d - s - 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // i n c e - - - - - 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // i f - n o n e - - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // m a t c h - - - - 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // - i f - r a n g - 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e - - - - i f - - 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // u n m o d i f i - 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // e d - s i n c e - 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // - - - - l a s t - 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // - m o d i f i e - 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d - - - - l o c - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // a t i o n - - - - 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // - m a x - f o r - 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // w a r d s - - - - 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // - p r a g m a - - 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // - - - p r o x y - 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // - a u t h e n t - 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // i c a t e - - - - 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // - p r o x y - a - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // u t h o r i z a - 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // t i o n - - - - - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // r a n g e - - - - 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // - r e f e r e r - 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // - - - - r e t r - 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y - a f t e r - - 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // - - - s e r v e - 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r - - - - t e - - 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // - - - t r a i l - 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // e r - - - - t r - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // a n s f e r - e - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // n c o d i n g - - 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // - - - u p g r a - 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // d e - - - - u s - 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // e r - a g e n t - 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // - - - - v a r y - 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // - - - - v i a - - 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // - - - w a r n i - 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // n g - - - - w w - 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w - a u t h e n - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // t i c a t e - - - 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // - - m e t h o d - 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // - - - - g e t - - 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // - - - s t a t u - 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s - - - - 2 0 0 - 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // - O K - - - - v - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // e r s i o n - - - 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // - - H T T P - 1 - 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // - 1 - - - - u r - 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l - - - - p u b - 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // l i c - - - - s - 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // e t - c o o k i - 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e - - - - k e e - 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p - a l i v e - - 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // - - - o r i g i - 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n 1 0 0 1 0 1 2 - 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 0 1 2 0 2 2 0 5 - 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 2 0 6 3 0 0 3 0 - 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 2 3 0 3 3 0 4 3 - 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 0 5 3 0 6 3 0 7 - 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 4 0 2 4 0 5 4 0 - 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 6 4 0 7 4 0 8 4 - 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 0 9 4 1 0 4 1 1 - 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 4 1 2 4 1 3 4 1 - 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 4 4 1 5 4 1 6 4 - 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 1 7 5 0 2 5 0 4 - 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 5 0 5 2 0 3 - N - 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // o n - A u t h o - 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // r i t a t i v e - 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // - I n f o r m a - 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // t i o n 2 0 4 - - 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // N o - C o n t e - 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // n t 3 0 1 - M o - 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // v e d - P e r m - 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // a n e n t l y 4 - 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 0 0 - B a d - R - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // e q u e s t 4 0 - 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1 - U n a u t h - 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // o r i z e d 4 0 - 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3 - F o r b i d - 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // d e n 4 0 4 - N - 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // o t - F o u n d - 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 5 0 0 - I n t e - 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // r n a l - S e r - 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // v e r - E r r o - 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r 5 0 1 - N o t - 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // - I m p l e m e - 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // n t e d 5 0 3 - - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // S e r v i c e - - 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // U n a v a i l a - 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // b l e J a n - F - 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // e b - M a r - A - 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // p r - M a y - J - 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // u n - J u l - A - 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // u g - S e p t - - 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // O c t - N o v - - 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // D e c - 0 0 - 0 - 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0 - 0 0 - M o n - 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // - - T u e - - W - 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // e d - - T h u - - 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // - F r i - - S a - 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t - - S u n - - - 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // G M T c h u n k - 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // e d - t e x t - - 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // h t m l - i m a - 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // g e - p n g - i - 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // m a g e - j p g - 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // - i m a g e - g - 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // i f - a p p l i - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x - 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // m l - a p p l i - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x - 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // h t m l - x m l - 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // - t e x t - p l - 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // a i n - t e x t - 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // - j a v a s c r - 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // i p t - p u b l - 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // i c p r i v a t - 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // e m a x - a g e - 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // - g z i p - d e - 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // f l a t e - s d - 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // c h c h a r s e - 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t - u t f - 8 c - 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // h a r s e t - i - 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // s o - 8 8 5 9 - - 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1 - u t f - - - - 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // - e n q - 0 - - }; - - private SpdyCodecUtil() { - } - - /** - * Reads a big-endian unsigned short integer from the buffer. - */ - static int getUnsignedShort(ByteBuf buf, int offset) { - return (buf.getByte(offset) & 0xFF) << 8 | - buf.getByte(offset + 1) & 0xFF; - } - - /** - * Reads a big-endian unsigned medium integer from the buffer. - */ - static int getUnsignedMedium(ByteBuf buf, int offset) { - return (buf.getByte(offset) & 0xFF) << 16 | - (buf.getByte(offset + 1) & 0xFF) << 8 | - buf.getByte(offset + 2) & 0xFF; - } - - /** - * Reads a big-endian (31-bit) integer from the buffer. - */ - static int getUnsignedInt(ByteBuf buf, int offset) { - return (buf.getByte(offset) & 0x7F) << 24 | - (buf.getByte(offset + 1) & 0xFF) << 16 | - (buf.getByte(offset + 2) & 0xFF) << 8 | - buf.getByte(offset + 3) & 0xFF; - } - - /** - * Reads a big-endian signed integer from the buffer. - */ - static int getSignedInt(ByteBuf buf, int offset) { - return (buf.getByte(offset) & 0xFF) << 24 | - (buf.getByte(offset + 1) & 0xFF) << 16 | - (buf.getByte(offset + 2) & 0xFF) << 8 | - buf.getByte(offset + 3) & 0xFF; - } - - /** - * Returns {@code true} if ID is for a server initiated stream or ping. - */ - static boolean isServerId(int id) { - // Server initiated streams and pings have even IDs - return id % 2 == 0; - } - - /** - * Validate a SPDY header name. - */ - static void validateHeaderName(CharSequence name) { - if (name == null) { - throw new NullPointerException("name"); - } - if (name.length() == 0) { - throw new IllegalArgumentException( - "name cannot be length zero"); - } - // Since name may only contain ascii characters, for valid names - // name.length() returns the number of bytes when UTF-8 encoded. - if (name.length() > SPDY_MAX_NV_LENGTH) { - throw new IllegalArgumentException( - "name exceeds allowable length: " + name); - } - for (int i = 0; i < name.length(); i ++) { - char c = name.charAt(i); - if (c == 0) { - throw new IllegalArgumentException( - "name contains null character: " + name); - } - if (c >= 'A' && c <= 'Z') { - throw new IllegalArgumentException("name must be all lower case."); - } - if (c > 127) { - throw new IllegalArgumentException( - "name contains non-ascii character: " + name); - } - } - } - - /** - * Validate a SPDY header value. Does not validate max length. - */ - static void validateHeaderValue(CharSequence value) { - if (value == null) { - throw new NullPointerException("value"); - } - for (int i = 0; i < value.length(); i ++) { - char c = value.charAt(i); - if (c == 0) { - throw new IllegalArgumentException( - "value contains null character: " + value); - } - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyDataFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyDataFrame.java deleted file mode 100644 index b112c5ea66..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyDataFrame.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufHolder; -import io.netty.buffer.Unpooled; - -/** - * A SPDY Protocol DATA Frame - */ -public interface SpdyDataFrame extends ByteBufHolder, SpdyStreamFrame { - - @Override - SpdyDataFrame setStreamId(int streamID); - - @Override - SpdyDataFrame setLast(boolean last); - - /** - * Returns the data payload of this frame. If there is no data payload - * {@link Unpooled#EMPTY_BUFFER} is returned. - * - * The data payload cannot exceed 16777215 bytes. - */ - @Override - ByteBuf content(); - - @Override - SpdyDataFrame copy(); - - @Override - SpdyDataFrame duplicate(); - - @Override - SpdyDataFrame retainedDuplicate(); - - @Override - SpdyDataFrame replace(ByteBuf content); - - @Override - SpdyDataFrame retain(); - - @Override - SpdyDataFrame retain(int increment); - - @Override - SpdyDataFrame touch(); - - @Override - SpdyDataFrame touch(Object hint); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrame.java deleted file mode 100644 index df0b72f7eb..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrame.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol Frame - */ -public interface SpdyFrame { - // Tag interface -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java deleted file mode 100644 index 5937d9a56f..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandler; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.UnsupportedMessageTypeException; - -import java.net.SocketAddress; -import java.util.List; - -/** - * A {@link ChannelHandler} that encodes and decodes SPDY Frames. - */ -public class SpdyFrameCodec extends ByteToMessageDecoder - implements SpdyFrameDecoderDelegate, ChannelOutboundHandler { - - private static final SpdyProtocolException INVALID_FRAME = - new SpdyProtocolException("Received invalid frame"); - - private final SpdyFrameDecoder spdyFrameDecoder; - private final SpdyFrameEncoder spdyFrameEncoder; - private final SpdyHeaderBlockDecoder spdyHeaderBlockDecoder; - private final SpdyHeaderBlockEncoder spdyHeaderBlockEncoder; - - private SpdyHeadersFrame spdyHeadersFrame; - private SpdySettingsFrame spdySettingsFrame; - - private ChannelHandlerContext ctx; - private boolean read; - private final boolean validateHeaders; - - /** - * Creates a new instance with the specified {@code version}, - * {@code validateHeaders (true)}, and - * the default decoder and encoder options - * ({@code maxChunkSize (8192)}, {@code maxHeaderSize (16384)}, - * {@code compressionLevel (6)}, {@code windowBits (15)}, - * and {@code memLevel (8)}). - */ - public SpdyFrameCodec(SpdyVersion version) { - this(version, true); - } - - /** - * Creates a new instance with the specified {@code version}, - * {@code validateHeaders}, and - * the default decoder and encoder options - * ({@code maxChunkSize (8192)}, {@code maxHeaderSize (16384)}, - * {@code compressionLevel (6)}, {@code windowBits (15)}, - * and {@code memLevel (8)}). - */ - public SpdyFrameCodec(SpdyVersion version, boolean validateHeaders) { - this(version, 8192, 16384, 6, 15, 8, validateHeaders); - } - - /** - * Creates a new instance with the specified {@code version}, {@code validateHeaders (true)}, - * decoder and encoder options. - */ - public SpdyFrameCodec( - SpdyVersion version, int maxChunkSize, int maxHeaderSize, - int compressionLevel, int windowBits, int memLevel) { - this(version, maxChunkSize, maxHeaderSize, compressionLevel, windowBits, memLevel, true); - } - - /** - * Creates a new instance with the specified {@code version}, {@code validateHeaders}, - * decoder and encoder options. - */ - public SpdyFrameCodec( - SpdyVersion version, int maxChunkSize, int maxHeaderSize, - int compressionLevel, int windowBits, int memLevel, boolean validateHeaders) { - this(version, maxChunkSize, - SpdyHeaderBlockDecoder.newInstance(version, maxHeaderSize), - SpdyHeaderBlockEncoder.newInstance(version, compressionLevel, windowBits, memLevel), validateHeaders); - } - - protected SpdyFrameCodec(SpdyVersion version, int maxChunkSize, - SpdyHeaderBlockDecoder spdyHeaderBlockDecoder, SpdyHeaderBlockEncoder spdyHeaderBlockEncoder, - boolean validateHeaders) { - spdyFrameDecoder = new SpdyFrameDecoder(version, this, maxChunkSize); - spdyFrameEncoder = new SpdyFrameEncoder(version); - this.spdyHeaderBlockDecoder = spdyHeaderBlockDecoder; - this.spdyHeaderBlockEncoder = spdyHeaderBlockEncoder; - this.validateHeaders = validateHeaders; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - super.handlerAdded(ctx); - this.ctx = ctx; - ctx.channel().closeFuture().addListener((ChannelFutureListener) future -> { - spdyHeaderBlockDecoder.end(); - spdyHeaderBlockEncoder.end(); - }); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - spdyFrameDecoder.decode(in); - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - if (!read) { - if (!ctx.channel().config().isAutoRead()) { - ctx.read(); - } - } - read = false; - super.channelReadComplete(ctx); - } - - @Override - public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception { - ctx.bind(localAddress, promise); - } - - @Override - public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, - ChannelPromise promise) throws Exception { - ctx.connect(remoteAddress, localAddress, promise); - } - - @Override - public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.disconnect(promise); - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.close(promise); - } - - @Override - public void register(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.register(promise); - } - - @Override - public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - ctx.deregister(promise); - } - - @Override - public void read(ChannelHandlerContext ctx) throws Exception { - ctx.read(); - } - - @Override - public void flush(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ByteBuf frame; - - if (msg instanceof SpdyDataFrame) { - - SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; - frame = spdyFrameEncoder.encodeDataFrame( - ctx.alloc(), - spdyDataFrame.streamId(), - spdyDataFrame.isLast(), - spdyDataFrame.content() - ); - spdyDataFrame.release(); - ctx.write(frame, promise); - - } else if (msg instanceof SpdySynStreamFrame) { - - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdySynStreamFrame); - try { - frame = spdyFrameEncoder.encodeSynStreamFrame( - ctx.alloc(), - spdySynStreamFrame.streamId(), - spdySynStreamFrame.associatedStreamId(), - spdySynStreamFrame.priority(), - spdySynStreamFrame.isLast(), - spdySynStreamFrame.isUnidirectional(), - headerBlock - ); - } finally { - headerBlock.release(); - } - ctx.write(frame, promise); - - } else if (msg instanceof SpdySynReplyFrame) { - - SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; - ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdySynReplyFrame); - try { - frame = spdyFrameEncoder.encodeSynReplyFrame( - ctx.alloc(), - spdySynReplyFrame.streamId(), - spdySynReplyFrame.isLast(), - headerBlock - ); - } finally { - headerBlock.release(); - } - ctx.write(frame, promise); - - } else if (msg instanceof SpdyRstStreamFrame) { - - SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; - frame = spdyFrameEncoder.encodeRstStreamFrame( - ctx.alloc(), - spdyRstStreamFrame.streamId(), - spdyRstStreamFrame.status().code() - ); - ctx.write(frame, promise); - - } else if (msg instanceof SpdySettingsFrame) { - - SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; - frame = spdyFrameEncoder.encodeSettingsFrame( - ctx.alloc(), - spdySettingsFrame - ); - ctx.write(frame, promise); - - } else if (msg instanceof SpdyPingFrame) { - - SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; - frame = spdyFrameEncoder.encodePingFrame( - ctx.alloc(), - spdyPingFrame.id() - ); - ctx.write(frame, promise); - - } else if (msg instanceof SpdyGoAwayFrame) { - - SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg; - frame = spdyFrameEncoder.encodeGoAwayFrame( - ctx.alloc(), - spdyGoAwayFrame.lastGoodStreamId(), - spdyGoAwayFrame.status().code() - ); - ctx.write(frame, promise); - - } else if (msg instanceof SpdyHeadersFrame) { - - SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; - ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdyHeadersFrame); - try { - frame = spdyFrameEncoder.encodeHeadersFrame( - ctx.alloc(), - spdyHeadersFrame.streamId(), - spdyHeadersFrame.isLast(), - headerBlock - ); - } finally { - headerBlock.release(); - } - ctx.write(frame, promise); - - } else if (msg instanceof SpdyWindowUpdateFrame) { - - SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg; - frame = spdyFrameEncoder.encodeWindowUpdateFrame( - ctx.alloc(), - spdyWindowUpdateFrame.streamId(), - spdyWindowUpdateFrame.deltaWindowSize() - ); - ctx.write(frame, promise); - } else { - throw new UnsupportedMessageTypeException(msg); - } - } - - @Override - public void readDataFrame(int streamId, boolean last, ByteBuf data) { - read = true; - - SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(streamId, data); - spdyDataFrame.setLast(last); - ctx.fireChannelRead(spdyDataFrame); - } - - @Override - public void readSynStreamFrame( - int streamId, int associatedToStreamId, byte priority, boolean last, boolean unidirectional) { - SpdySynStreamFrame spdySynStreamFrame = - new DefaultSpdySynStreamFrame(streamId, associatedToStreamId, priority, validateHeaders); - spdySynStreamFrame.setLast(last); - spdySynStreamFrame.setUnidirectional(unidirectional); - spdyHeadersFrame = spdySynStreamFrame; - } - - @Override - public void readSynReplyFrame(int streamId, boolean last) { - SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId, validateHeaders); - spdySynReplyFrame.setLast(last); - spdyHeadersFrame = spdySynReplyFrame; - } - - @Override - public void readRstStreamFrame(int streamId, int statusCode) { - read = true; - - SpdyRstStreamFrame spdyRstStreamFrame = new DefaultSpdyRstStreamFrame(streamId, statusCode); - ctx.fireChannelRead(spdyRstStreamFrame); - } - - @Override - public void readSettingsFrame(boolean clearPersisted) { - read = true; - - spdySettingsFrame = new DefaultSpdySettingsFrame(); - spdySettingsFrame.setClearPreviouslyPersistedSettings(clearPersisted); - } - - @Override - public void readSetting(int id, int value, boolean persistValue, boolean persisted) { - spdySettingsFrame.setValue(id, value, persistValue, persisted); - } - - @Override - public void readSettingsEnd() { - read = true; - - Object frame = spdySettingsFrame; - spdySettingsFrame = null; - ctx.fireChannelRead(frame); - } - - @Override - public void readPingFrame(int id) { - read = true; - - SpdyPingFrame spdyPingFrame = new DefaultSpdyPingFrame(id); - ctx.fireChannelRead(spdyPingFrame); - } - - @Override - public void readGoAwayFrame(int lastGoodStreamId, int statusCode) { - read = true; - - SpdyGoAwayFrame spdyGoAwayFrame = new DefaultSpdyGoAwayFrame(lastGoodStreamId, statusCode); - ctx.fireChannelRead(spdyGoAwayFrame); - } - - @Override - public void readHeadersFrame(int streamId, boolean last) { - spdyHeadersFrame = new DefaultSpdyHeadersFrame(streamId, validateHeaders); - spdyHeadersFrame.setLast(last); - } - - @Override - public void readWindowUpdateFrame(int streamId, int deltaWindowSize) { - read = true; - - SpdyWindowUpdateFrame spdyWindowUpdateFrame = new DefaultSpdyWindowUpdateFrame(streamId, deltaWindowSize); - ctx.fireChannelRead(spdyWindowUpdateFrame); - } - - @Override - public void readHeaderBlock(ByteBuf headerBlock) { - try { - spdyHeaderBlockDecoder.decode(ctx.alloc(), headerBlock, spdyHeadersFrame); - } catch (Exception e) { - ctx.fireExceptionCaught(e); - } finally { - headerBlock.release(); - } - } - - @Override - public void readHeaderBlockEnd() { - Object frame = null; - try { - spdyHeaderBlockDecoder.endHeaderBlock(spdyHeadersFrame); - frame = spdyHeadersFrame; - spdyHeadersFrame = null; - } catch (Exception e) { - ctx.fireExceptionCaught(e); - } - if (frame != null) { - read = true; - - ctx.fireChannelRead(frame); - } - } - - @Override - public void readFrameError(String message) { - ctx.fireExceptionCaught(INVALID_FRAME); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java deleted file mode 100644 index e0d1112813..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright 2014 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 static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_DATA_FLAG_FIN; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_DATA_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_FLAG_FIN; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_FLAG_UNIDIRECTIONAL; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_GOAWAY_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADERS_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_FLAGS_OFFSET; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_LENGTH_OFFSET; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_SIZE; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_TYPE_OFFSET; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_PING_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_RST_STREAM_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_CLEAR; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_PERSISTED; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_PERSIST_VALUE; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SYN_REPLY_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SYN_STREAM_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_WINDOW_UPDATE_FRAME; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.getSignedInt; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedInt; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedMedium; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedShort; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -/** - * Decodes {@link ByteBuf}s into SPDY Frames. - */ -public class SpdyFrameDecoder { - - private final int spdyVersion; - private final int maxChunkSize; - - private final SpdyFrameDecoderDelegate delegate; - - private State state; - - // SPDY common header fields - private byte flags; - private int length; - private int streamId; - - private int numSettings; - - private enum State { - READ_COMMON_HEADER, - READ_DATA_FRAME, - READ_SYN_STREAM_FRAME, - READ_SYN_REPLY_FRAME, - READ_RST_STREAM_FRAME, - READ_SETTINGS_FRAME, - READ_SETTING, - READ_PING_FRAME, - READ_GOAWAY_FRAME, - READ_HEADERS_FRAME, - READ_WINDOW_UPDATE_FRAME, - READ_HEADER_BLOCK, - DISCARD_FRAME, - FRAME_ERROR - } - - /** - * Creates a new instance with the specified {@code version} - * and the default {@code maxChunkSize (8192)}. - */ - public SpdyFrameDecoder(SpdyVersion spdyVersion, SpdyFrameDecoderDelegate delegate) { - this(spdyVersion, delegate, 8192); - } - - /** - * Creates a new instance with the specified parameters. - */ - public SpdyFrameDecoder(SpdyVersion spdyVersion, SpdyFrameDecoderDelegate delegate, int maxChunkSize) { - if (spdyVersion == null) { - throw new NullPointerException("spdyVersion"); - } - if (delegate == null) { - throw new NullPointerException("delegate"); - } - if (maxChunkSize <= 0) { - throw new IllegalArgumentException( - "maxChunkSize must be a positive integer: " + maxChunkSize); - } - this.spdyVersion = spdyVersion.getVersion(); - this.delegate = delegate; - this.maxChunkSize = maxChunkSize; - state = State.READ_COMMON_HEADER; - } - - public void decode(ByteBuf buffer) { - boolean last; - int statusCode; - - while (true) { - switch(state) { - case READ_COMMON_HEADER: - if (buffer.readableBytes() < SPDY_HEADER_SIZE) { - return; - } - - int frameOffset = buffer.readerIndex(); - int flagsOffset = frameOffset + SPDY_HEADER_FLAGS_OFFSET; - int lengthOffset = frameOffset + SPDY_HEADER_LENGTH_OFFSET; - buffer.skipBytes(SPDY_HEADER_SIZE); - - boolean control = (buffer.getByte(frameOffset) & 0x80) != 0; - - int version; - int type; - if (control) { - // Decode control frame common header - version = getUnsignedShort(buffer, frameOffset) & 0x7FFF; - type = getUnsignedShort(buffer, frameOffset + SPDY_HEADER_TYPE_OFFSET); - streamId = 0; // Default to session Stream-ID - } else { - // Decode data frame common header - version = spdyVersion; // Default to expected version - type = SPDY_DATA_FRAME; - streamId = getUnsignedInt(buffer, frameOffset); - } - - flags = buffer.getByte(flagsOffset); - length = getUnsignedMedium(buffer, lengthOffset); - - // Check version first then validity - if (version != spdyVersion) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid SPDY Version"); - } else if (!isValidFrameHeader(streamId, type, flags, length)) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid Frame Error"); - } else { - state = getNextState(type, length); - } - break; - - case READ_DATA_FRAME: - if (length == 0) { - state = State.READ_COMMON_HEADER; - delegate.readDataFrame(streamId, hasFlag(flags, SPDY_DATA_FLAG_FIN), Unpooled.buffer(0)); - break; - } - - // Generate data frames that do not exceed maxChunkSize - int dataLength = Math.min(maxChunkSize, length); - - // Wait until entire frame is readable - if (buffer.readableBytes() < dataLength) { - return; - } - - ByteBuf data = buffer.alloc().buffer(dataLength); - data.writeBytes(buffer, dataLength); - length -= dataLength; - - if (length == 0) { - state = State.READ_COMMON_HEADER; - } - - last = length == 0 && hasFlag(flags, SPDY_DATA_FLAG_FIN); - - delegate.readDataFrame(streamId, last, data); - break; - - case READ_SYN_STREAM_FRAME: - if (buffer.readableBytes() < 10) { - return; - } - - int offset = buffer.readerIndex(); - streamId = getUnsignedInt(buffer, offset); - int associatedToStreamId = getUnsignedInt(buffer, offset + 4); - byte priority = (byte) (buffer.getByte(offset + 8) >> 5 & 0x07); - last = hasFlag(flags, SPDY_FLAG_FIN); - boolean unidirectional = hasFlag(flags, SPDY_FLAG_UNIDIRECTIONAL); - buffer.skipBytes(10); - length -= 10; - - if (streamId == 0) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid SYN_STREAM Frame"); - } else { - state = State.READ_HEADER_BLOCK; - delegate.readSynStreamFrame(streamId, associatedToStreamId, priority, last, unidirectional); - } - break; - - case READ_SYN_REPLY_FRAME: - if (buffer.readableBytes() < 4) { - return; - } - - streamId = getUnsignedInt(buffer, buffer.readerIndex()); - last = hasFlag(flags, SPDY_FLAG_FIN); - - buffer.skipBytes(4); - length -= 4; - - if (streamId == 0) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid SYN_REPLY Frame"); - } else { - state = State.READ_HEADER_BLOCK; - delegate.readSynReplyFrame(streamId, last); - } - break; - - case READ_RST_STREAM_FRAME: - if (buffer.readableBytes() < 8) { - return; - } - - streamId = getUnsignedInt(buffer, buffer.readerIndex()); - statusCode = getSignedInt(buffer, buffer.readerIndex() + 4); - buffer.skipBytes(8); - - if (streamId == 0 || statusCode == 0) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid RST_STREAM Frame"); - } else { - state = State.READ_COMMON_HEADER; - delegate.readRstStreamFrame(streamId, statusCode); - } - break; - - case READ_SETTINGS_FRAME: - if (buffer.readableBytes() < 4) { - return; - } - - boolean clear = hasFlag(flags, SPDY_SETTINGS_CLEAR); - - numSettings = getUnsignedInt(buffer, buffer.readerIndex()); - buffer.skipBytes(4); - length -= 4; - - // Validate frame length against number of entries. Each ID/Value entry is 8 bytes. - if ((length & 0x07) != 0 || length >> 3 != numSettings) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid SETTINGS Frame"); - } else { - state = State.READ_SETTING; - delegate.readSettingsFrame(clear); - } - break; - - case READ_SETTING: - if (numSettings == 0) { - state = State.READ_COMMON_HEADER; - delegate.readSettingsEnd(); - break; - } - - if (buffer.readableBytes() < 8) { - return; - } - - byte settingsFlags = buffer.getByte(buffer.readerIndex()); - int id = getUnsignedMedium(buffer, buffer.readerIndex() + 1); - int value = getSignedInt(buffer, buffer.readerIndex() + 4); - boolean persistValue = hasFlag(settingsFlags, SPDY_SETTINGS_PERSIST_VALUE); - boolean persisted = hasFlag(settingsFlags, SPDY_SETTINGS_PERSISTED); - buffer.skipBytes(8); - - --numSettings; - - delegate.readSetting(id, value, persistValue, persisted); - break; - - case READ_PING_FRAME: - if (buffer.readableBytes() < 4) { - return; - } - - int pingId = getSignedInt(buffer, buffer.readerIndex()); - buffer.skipBytes(4); - - state = State.READ_COMMON_HEADER; - delegate.readPingFrame(pingId); - break; - - case READ_GOAWAY_FRAME: - if (buffer.readableBytes() < 8) { - return; - } - - int lastGoodStreamId = getUnsignedInt(buffer, buffer.readerIndex()); - statusCode = getSignedInt(buffer, buffer.readerIndex() + 4); - buffer.skipBytes(8); - - state = State.READ_COMMON_HEADER; - delegate.readGoAwayFrame(lastGoodStreamId, statusCode); - break; - - case READ_HEADERS_FRAME: - if (buffer.readableBytes() < 4) { - return; - } - - streamId = getUnsignedInt(buffer, buffer.readerIndex()); - last = hasFlag(flags, SPDY_FLAG_FIN); - - buffer.skipBytes(4); - length -= 4; - - if (streamId == 0) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid HEADERS Frame"); - } else { - state = State.READ_HEADER_BLOCK; - delegate.readHeadersFrame(streamId, last); - } - break; - - case READ_WINDOW_UPDATE_FRAME: - if (buffer.readableBytes() < 8) { - return; - } - - streamId = getUnsignedInt(buffer, buffer.readerIndex()); - int deltaWindowSize = getUnsignedInt(buffer, buffer.readerIndex() + 4); - buffer.skipBytes(8); - - if (deltaWindowSize == 0) { - state = State.FRAME_ERROR; - delegate.readFrameError("Invalid WINDOW_UPDATE Frame"); - } else { - state = State.READ_COMMON_HEADER; - delegate.readWindowUpdateFrame(streamId, deltaWindowSize); - } - break; - - case READ_HEADER_BLOCK: - if (length == 0) { - state = State.READ_COMMON_HEADER; - delegate.readHeaderBlockEnd(); - break; - } - - if (!buffer.isReadable()) { - return; - } - - int compressedBytes = Math.min(buffer.readableBytes(), length); - ByteBuf headerBlock = buffer.alloc().buffer(compressedBytes); - headerBlock.writeBytes(buffer, compressedBytes); - length -= compressedBytes; - - delegate.readHeaderBlock(headerBlock); - break; - - case DISCARD_FRAME: - int numBytes = Math.min(buffer.readableBytes(), length); - buffer.skipBytes(numBytes); - length -= numBytes; - if (length == 0) { - state = State.READ_COMMON_HEADER; - break; - } - return; - - case FRAME_ERROR: - buffer.skipBytes(buffer.readableBytes()); - return; - - default: - throw new Error("Shouldn't reach here."); - } - } - } - - private static boolean hasFlag(byte flags, byte flag) { - return (flags & flag) != 0; - } - - private static State getNextState(int type, int length) { - switch (type) { - case SPDY_DATA_FRAME: - return State.READ_DATA_FRAME; - - case SPDY_SYN_STREAM_FRAME: - return State.READ_SYN_STREAM_FRAME; - - case SPDY_SYN_REPLY_FRAME: - return State.READ_SYN_REPLY_FRAME; - - case SPDY_RST_STREAM_FRAME: - return State.READ_RST_STREAM_FRAME; - - case SPDY_SETTINGS_FRAME: - return State.READ_SETTINGS_FRAME; - - case SPDY_PING_FRAME: - return State.READ_PING_FRAME; - - case SPDY_GOAWAY_FRAME: - return State.READ_GOAWAY_FRAME; - - case SPDY_HEADERS_FRAME: - return State.READ_HEADERS_FRAME; - - case SPDY_WINDOW_UPDATE_FRAME: - return State.READ_WINDOW_UPDATE_FRAME; - - default: - if (length != 0) { - return State.DISCARD_FRAME; - } else { - return State.READ_COMMON_HEADER; - } - } - } - - private static boolean isValidFrameHeader(int streamId, int type, byte flags, int length) { - switch (type) { - case SPDY_DATA_FRAME: - return streamId != 0; - - case SPDY_SYN_STREAM_FRAME: - return length >= 10; - - case SPDY_SYN_REPLY_FRAME: - return length >= 4; - - case SPDY_RST_STREAM_FRAME: - return flags == 0 && length == 8; - - case SPDY_SETTINGS_FRAME: - return length >= 4; - - case SPDY_PING_FRAME: - return length == 4; - - case SPDY_GOAWAY_FRAME: - return length == 8; - - case SPDY_HEADERS_FRAME: - return length >= 4; - - case SPDY_WINDOW_UPDATE_FRAME: - return length == 8; - - default: - return true; - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoderDelegate.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoderDelegate.java deleted file mode 100644 index 52815c787c..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoderDelegate.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; - -/** - * Callback interface for {@link SpdyFrameDecoder}. - */ -public interface SpdyFrameDecoderDelegate { - - /** - * Called when a DATA frame is received. - */ - void readDataFrame(int streamId, boolean last, ByteBuf data); - - /** - * Called when a SYN_STREAM frame is received. - * The Name/Value Header Block is not included. See readHeaderBlock(). - */ - void readSynStreamFrame( - int streamId, int associatedToStreamId, byte priority, boolean last, boolean unidirectional); - - /** - * Called when a SYN_REPLY frame is received. - * The Name/Value Header Block is not included. See readHeaderBlock(). - */ - void readSynReplyFrame(int streamId, boolean last); - - /** - * Called when a RST_STREAM frame is received. - */ - void readRstStreamFrame(int streamId, int statusCode); - - /** - * Called when a SETTINGS frame is received. - * Settings are not included. See readSetting(). - */ - void readSettingsFrame(boolean clearPersisted); - - /** - * Called when an individual setting within a SETTINGS frame is received. - */ - void readSetting(int id, int value, boolean persistValue, boolean persisted); - - /** - * Called when the entire SETTINGS frame has been received. - */ - void readSettingsEnd(); - - /** - * Called when a PING frame is received. - */ - void readPingFrame(int id); - - /** - * Called when a GOAWAY frame is received. - */ - void readGoAwayFrame(int lastGoodStreamId, int statusCode); - - /** - * Called when a HEADERS frame is received. - * The Name/Value Header Block is not included. See readHeaderBlock(). - */ - void readHeadersFrame(int streamId, boolean last); - - /** - * Called when a WINDOW_UPDATE frame is received. - */ - void readWindowUpdateFrame(int streamId, int deltaWindowSize); - - /** - * Called when the header block within a SYN_STREAM, SYN_REPLY, or HEADERS frame is received. - */ - void readHeaderBlock(ByteBuf headerBlock); - - /** - * Called when an entire header block has been received. - */ - void readHeaderBlockEnd(); - - /** - * Called when an unrecoverable session error has occurred. - */ - void readFrameError(String message); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java deleted file mode 100644 index 1524f95234..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -import java.nio.ByteOrder; -import java.util.Set; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - -/** - * Encodes a SPDY Frame into a {@link ByteBuf}. - */ -public class SpdyFrameEncoder { - - private final int version; - - /** - * Creates a new instance with the specified {@code spdyVersion}. - */ - public SpdyFrameEncoder(SpdyVersion spdyVersion) { - if (spdyVersion == null) { - throw new NullPointerException("spdyVersion"); - } - version = spdyVersion.getVersion(); - } - - private void writeControlFrameHeader(ByteBuf buffer, int type, byte flags, int length) { - buffer.writeShort(version | 0x8000); - buffer.writeShort(type); - buffer.writeByte(flags); - buffer.writeMedium(length); - } - - public ByteBuf encodeDataFrame(ByteBufAllocator allocator, int streamId, boolean last, ByteBuf data) { - byte flags = last ? SPDY_DATA_FLAG_FIN : 0; - int length = data.readableBytes(); - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - frame.writeInt(streamId & 0x7FFFFFFF); - frame.writeByte(flags); - frame.writeMedium(length); - frame.writeBytes(data, data.readerIndex(), length); - return frame; - } - - public ByteBuf encodeSynStreamFrame(ByteBufAllocator allocator, int streamId, int associatedToStreamId, - byte priority, boolean last, boolean unidirectional, ByteBuf headerBlock) { - int headerBlockLength = headerBlock.readableBytes(); - byte flags = last ? SPDY_FLAG_FIN : 0; - if (unidirectional) { - flags |= SPDY_FLAG_UNIDIRECTIONAL; - } - int length = 10 + headerBlockLength; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_SYN_STREAM_FRAME, flags, length); - frame.writeInt(streamId); - frame.writeInt(associatedToStreamId); - frame.writeShort((priority & 0xFF) << 13); - frame.writeBytes(headerBlock, headerBlock.readerIndex(), headerBlockLength); - return frame; - } - - public ByteBuf encodeSynReplyFrame(ByteBufAllocator allocator, int streamId, boolean last, ByteBuf headerBlock) { - int headerBlockLength = headerBlock.readableBytes(); - byte flags = last ? SPDY_FLAG_FIN : 0; - int length = 4 + headerBlockLength; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_SYN_REPLY_FRAME, flags, length); - frame.writeInt(streamId); - frame.writeBytes(headerBlock, headerBlock.readerIndex(), headerBlockLength); - return frame; - } - - public ByteBuf encodeRstStreamFrame(ByteBufAllocator allocator, int streamId, int statusCode) { - byte flags = 0; - int length = 8; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_RST_STREAM_FRAME, flags, length); - frame.writeInt(streamId); - frame.writeInt(statusCode); - return frame; - } - - public ByteBuf encodeSettingsFrame(ByteBufAllocator allocator, SpdySettingsFrame spdySettingsFrame) { - Set ids = spdySettingsFrame.ids(); - int numSettings = ids.size(); - - byte flags = spdySettingsFrame.clearPreviouslyPersistedSettings() ? - SPDY_SETTINGS_CLEAR : 0; - int length = 4 + 8 * numSettings; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_SETTINGS_FRAME, flags, length); - frame.writeInt(numSettings); - for (Integer id : ids) { - flags = 0; - if (spdySettingsFrame.isPersistValue(id)) { - flags |= SPDY_SETTINGS_PERSIST_VALUE; - } - if (spdySettingsFrame.isPersisted(id)) { - flags |= SPDY_SETTINGS_PERSISTED; - } - frame.writeByte(flags); - frame.writeMedium(id); - frame.writeInt(spdySettingsFrame.getValue(id)); - } - return frame; - } - - public ByteBuf encodePingFrame(ByteBufAllocator allocator, int id) { - byte flags = 0; - int length = 4; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_PING_FRAME, flags, length); - frame.writeInt(id); - return frame; - } - - public ByteBuf encodeGoAwayFrame(ByteBufAllocator allocator, int lastGoodStreamId, int statusCode) { - byte flags = 0; - int length = 8; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_GOAWAY_FRAME, flags, length); - frame.writeInt(lastGoodStreamId); - frame.writeInt(statusCode); - return frame; - } - - public ByteBuf encodeHeadersFrame(ByteBufAllocator allocator, int streamId, boolean last, ByteBuf headerBlock) { - int headerBlockLength = headerBlock.readableBytes(); - byte flags = last ? SPDY_FLAG_FIN : 0; - int length = 4 + headerBlockLength; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_HEADERS_FRAME, flags, length); - frame.writeInt(streamId); - frame.writeBytes(headerBlock, headerBlock.readerIndex(), headerBlockLength); - return frame; - } - - public ByteBuf encodeWindowUpdateFrame(ByteBufAllocator allocator, int streamId, int deltaWindowSize) { - byte flags = 0; - int length = 8; - ByteBuf frame = allocator.ioBuffer(SPDY_HEADER_SIZE + length).order(ByteOrder.BIG_ENDIAN); - writeControlFrameHeader(frame, SPDY_WINDOW_UPDATE_FRAME, flags, length); - frame.writeInt(streamId); - frame.writeInt(deltaWindowSize); - return frame; - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyGoAwayFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyGoAwayFrame.java deleted file mode 100644 index d2abb19b37..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyGoAwayFrame.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol GOAWAY Frame - */ -public interface SpdyGoAwayFrame extends SpdyFrame { - - /** - * Returns the Last-good-stream-ID of this frame. - */ - int lastGoodStreamId(); - - /** - * Sets the Last-good-stream-ID of this frame. The Last-good-stream-ID - * cannot be negative. - */ - SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId); - - /** - * Returns the status of this frame. - */ - SpdySessionStatus status(); - - /** - * Sets the status of this frame. - */ - SpdyGoAwayFrame setStatus(SpdySessionStatus status); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecoder.java deleted file mode 100644 index dd2d8684c7..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecoder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -abstract class SpdyHeaderBlockDecoder { - - static SpdyHeaderBlockDecoder newInstance(SpdyVersion spdyVersion, int maxHeaderSize) { - return new SpdyHeaderBlockZlibDecoder(spdyVersion, maxHeaderSize); - } - - /** - * Decodes a SPDY Header Block, adding the Name/Value pairs to the given Headers frame. - * If the header block is malformed, the Headers frame will be marked as invalid. - * A stream error with status code PROTOCOL_ERROR must be issued in response to an invalid frame. - * - * @param alloc the {@link ByteBufAllocator} which can be used to allocate new {@link ByteBuf}s - * @param headerBlock the HeaderBlock to decode - * @param frame the Headers frame that receives the Name/Value pairs - * @throws Exception If the header block is malformed in a way that prevents any future - * decoding of any other header blocks, an exception will be thrown. - * A session error with status code PROTOCOL_ERROR must be issued. - */ - abstract void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception; - - abstract void endHeaderBlock(SpdyHeadersFrame frame) throws Exception; - - abstract void end(); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockEncoder.java deleted file mode 100644 index eab5f4c6c6..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockEncoder.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -abstract class SpdyHeaderBlockEncoder { - - static SpdyHeaderBlockEncoder newInstance( - SpdyVersion version, int compressionLevel, int windowBits, int memLevel) { - return new SpdyHeaderBlockZlibEncoder(version, compressionLevel); - } - - abstract ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception; - abstract void end(); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockJZlibEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockJZlibEncoder.java deleted file mode 100644 index add9d765ae..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockJZlibEncoder.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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; - -import com.jcraft.jzlib.Deflater; -import com.jcraft.jzlib.JZlib; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.compression.CompressionException; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - -class SpdyHeaderBlockJZlibEncoder extends SpdyHeaderBlockRawEncoder { - - private final Deflater z = new Deflater(); - - private boolean finished; - - SpdyHeaderBlockJZlibEncoder( - SpdyVersion version, int compressionLevel, int windowBits, int memLevel) { - super(version); - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - if (windowBits < 9 || windowBits > 15) { - throw new IllegalArgumentException( - "windowBits: " + windowBits + " (expected: 9-15)"); - } - if (memLevel < 1 || memLevel > 9) { - throw new IllegalArgumentException( - "memLevel: " + memLevel + " (expected: 1-9)"); - } - - int resultCode = z.deflateInit( - compressionLevel, windowBits, memLevel, JZlib.W_ZLIB); - if (resultCode != JZlib.Z_OK) { - throw new CompressionException( - "failed to initialize an SPDY header block deflater: " + resultCode); - } else { - resultCode = z.deflateSetDictionary(SPDY_DICT, SPDY_DICT.length); - if (resultCode != JZlib.Z_OK) { - throw new CompressionException( - "failed to set the SPDY dictionary: " + resultCode); - } - } - } - - private void setInput(ByteBuf decompressed) { - int len = decompressed.readableBytes(); - - byte[] in; - int offset; - if (decompressed.hasArray()) { - in = decompressed.array(); - offset = decompressed.arrayOffset() + decompressed.readerIndex(); - } else { - in = new byte[len]; - decompressed.getBytes(decompressed.readerIndex(), in); - offset = 0; - } - z.next_in = in; - z.next_in_index = offset; - z.avail_in = len; - } - - private ByteBuf encode(ByteBufAllocator alloc) { - boolean release = true; - ByteBuf out = null; - try { - int oldNextInIndex = z.next_in_index; - int oldNextOutIndex = z.next_out_index; - - int maxOutputLength = (int) Math.ceil(z.next_in.length * 1.001) + 12; - out = alloc.heapBuffer(maxOutputLength); - z.next_out = out.array(); - z.next_out_index = out.arrayOffset() + out.writerIndex(); - z.avail_out = maxOutputLength; - - int resultCode; - try { - resultCode = z.deflate(JZlib.Z_SYNC_FLUSH); - } finally { - out.skipBytes(z.next_in_index - oldNextInIndex); - } - if (resultCode != JZlib.Z_OK) { - throw new CompressionException("compression failure: " + resultCode); - } - - int outputLength = z.next_out_index - oldNextOutIndex; - if (outputLength > 0) { - out.writerIndex(out.writerIndex() + outputLength); - } - release = false; - return out; - } finally { - // Deference the external references explicitly to tell the VM that - // the allocated byte arrays are temporary so that the call stack - // can be utilized. - // I'm not sure if the modern VMs do this optimization though. - z.next_in = null; - z.next_out = null; - if (release && out != null) { - out.release(); - } - } - } - - @Override - public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception { - if (frame == null) { - throw new IllegalArgumentException("frame"); - } - - if (finished) { - return Unpooled.EMPTY_BUFFER; - } - - ByteBuf decompressed = super.encode(alloc, frame); - try { - if (!decompressed.isReadable()) { - return Unpooled.EMPTY_BUFFER; - } - - setInput(decompressed); - return encode(alloc); - } finally { - decompressed.release(); - } - } - - @Override - public void end() { - if (finished) { - return; - } - finished = true; - z.deflateEnd(); - z.next_in = null; - z.next_out = null; - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java deleted file mode 100644 index 4aede81d3a..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.util.CharsetUtil; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.getSignedInt; - -public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { - - private static final int LENGTH_FIELD_SIZE = 4; - - private final int maxHeaderSize; - - private State state; - - private ByteBuf cumulation; - - private int headerSize; - private int numHeaders; - private int length; - private String name; - - private enum State { - READ_NUM_HEADERS, - READ_NAME_LENGTH, - READ_NAME, - SKIP_NAME, - READ_VALUE_LENGTH, - READ_VALUE, - SKIP_VALUE, - END_HEADER_BLOCK, - ERROR - } - - public SpdyHeaderBlockRawDecoder(SpdyVersion spdyVersion, int maxHeaderSize) { - if (spdyVersion == null) { - throw new NullPointerException("spdyVersion"); - } - this.maxHeaderSize = maxHeaderSize; - state = State.READ_NUM_HEADERS; - } - - private static int readLengthField(ByteBuf buffer) { - int length = getSignedInt(buffer, buffer.readerIndex()); - buffer.skipBytes(LENGTH_FIELD_SIZE); - return length; - } - - @Override - void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { - if (headerBlock == null) { - throw new NullPointerException("headerBlock"); - } - if (frame == null) { - throw new NullPointerException("frame"); - } - - if (cumulation == null) { - decodeHeaderBlock(headerBlock, frame); - if (headerBlock.isReadable()) { - cumulation = alloc.buffer(headerBlock.readableBytes()); - cumulation.writeBytes(headerBlock); - } - } else { - cumulation.writeBytes(headerBlock); - decodeHeaderBlock(cumulation, frame); - if (cumulation.isReadable()) { - cumulation.discardReadBytes(); - } else { - releaseBuffer(); - } - } - } - - protected void decodeHeaderBlock(ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { - int skipLength; - while (headerBlock.isReadable()) { - switch(state) { - case READ_NUM_HEADERS: - if (headerBlock.readableBytes() < LENGTH_FIELD_SIZE) { - return; - } - - numHeaders = readLengthField(headerBlock); - - if (numHeaders < 0) { - state = State.ERROR; - frame.setInvalid(); - } else if (numHeaders == 0) { - state = State.END_HEADER_BLOCK; - } else { - state = State.READ_NAME_LENGTH; - } - break; - - case READ_NAME_LENGTH: - if (headerBlock.readableBytes() < LENGTH_FIELD_SIZE) { - return; - } - - length = readLengthField(headerBlock); - - // Recipients of a zero-length name must issue a stream error - if (length <= 0) { - state = State.ERROR; - frame.setInvalid(); - } else if (length > maxHeaderSize || headerSize > maxHeaderSize - length) { - headerSize = maxHeaderSize + 1; - state = State.SKIP_NAME; - frame.setTruncated(); - } else { - headerSize += length; - state = State.READ_NAME; - } - break; - - case READ_NAME: - if (headerBlock.readableBytes() < length) { - return; - } - - byte[] nameBytes = new byte[length]; - headerBlock.readBytes(nameBytes); - name = new String(nameBytes, CharsetUtil.UTF_8); - - // Check for identically named headers - if (frame.headers().contains(name)) { - state = State.ERROR; - frame.setInvalid(); - } else { - state = State.READ_VALUE_LENGTH; - } - break; - - case SKIP_NAME: - skipLength = Math.min(headerBlock.readableBytes(), length); - headerBlock.skipBytes(skipLength); - length -= skipLength; - - if (length == 0) { - state = State.READ_VALUE_LENGTH; - } - break; - - case READ_VALUE_LENGTH: - if (headerBlock.readableBytes() < LENGTH_FIELD_SIZE) { - return; - } - - length = readLengthField(headerBlock); - - // Recipients of illegal value fields must issue a stream error - if (length < 0) { - state = State.ERROR; - frame.setInvalid(); - } else if (length == 0) { - if (!frame.isTruncated()) { - // SPDY/3 allows zero-length (empty) header values - frame.headers().add(name, ""); - } - - name = null; - if (--numHeaders == 0) { - state = State.END_HEADER_BLOCK; - } else { - state = State.READ_NAME_LENGTH; - } - - } else if (length > maxHeaderSize || headerSize > maxHeaderSize - length) { - headerSize = maxHeaderSize + 1; - name = null; - state = State.SKIP_VALUE; - frame.setTruncated(); - } else { - headerSize += length; - state = State.READ_VALUE; - } - break; - - case READ_VALUE: - if (headerBlock.readableBytes() < length) { - return; - } - - byte[] valueBytes = new byte[length]; - headerBlock.readBytes(valueBytes); - - // Add Name/Value pair to headers - int index = 0; - int offset = 0; - - // Value must not start with a NULL character - if (valueBytes[0] == (byte) 0) { - state = State.ERROR; - frame.setInvalid(); - break; - } - - while (index < length) { - while (index < valueBytes.length && valueBytes[index] != (byte) 0) { - index ++; - } - if (index < valueBytes.length) { - // Received NULL character - if (index + 1 == valueBytes.length || valueBytes[index + 1] == (byte) 0) { - // Value field ended with a NULL character or - // received multiple, in-sequence NULL characters. - // Recipients of illegal value fields must issue a stream error - state = State.ERROR; - frame.setInvalid(); - break; - } - } - String value = new String(valueBytes, offset, index - offset, CharsetUtil.UTF_8); - - try { - frame.headers().add(name, value); - } catch (IllegalArgumentException e) { - // Name contains NULL or non-ascii characters - state = State.ERROR; - frame.setInvalid(); - break; - } - index ++; - offset = index; - } - - name = null; - - // If we broke out of the add header loop, break here - if (state == State.ERROR) { - break; - } - - if (--numHeaders == 0) { - state = State.END_HEADER_BLOCK; - } else { - state = State.READ_NAME_LENGTH; - } - break; - - case SKIP_VALUE: - skipLength = Math.min(headerBlock.readableBytes(), length); - headerBlock.skipBytes(skipLength); - length -= skipLength; - - if (length == 0) { - if (--numHeaders == 0) { - state = State.END_HEADER_BLOCK; - } else { - state = State.READ_NAME_LENGTH; - } - } - break; - - case END_HEADER_BLOCK: - state = State.ERROR; - frame.setInvalid(); - break; - - case ERROR: - headerBlock.skipBytes(headerBlock.readableBytes()); - return; - - default: - throw new Error("Shouldn't reach here."); - } - } - } - - @Override - void endHeaderBlock(SpdyHeadersFrame frame) throws Exception { - if (state != State.END_HEADER_BLOCK) { - frame.setInvalid(); - } - - releaseBuffer(); - - // Initialize header block decoding fields - headerSize = 0; - name = null; - state = State.READ_NUM_HEADERS; - } - - @Override - void end() { - releaseBuffer(); - } - - private void releaseBuffer() { - if (cumulation != null) { - cumulation.release(); - cumulation = null; - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java deleted file mode 100644 index afd547966a..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; - -import java.util.Set; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_MAX_NV_LENGTH; - -public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder { - - private final int version; - - public SpdyHeaderBlockRawEncoder(SpdyVersion version) { - if (version == null) { - throw new NullPointerException("version"); - } - this.version = version.getVersion(); - } - - private static void setLengthField(ByteBuf buffer, int writerIndex, int length) { - buffer.setInt(writerIndex, length); - } - - private static void writeLengthField(ByteBuf buffer, int length) { - buffer.writeInt(length); - } - - @Override - public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception { - Set names = frame.headers().names(); - int numHeaders = names.size(); - if (numHeaders == 0) { - return Unpooled.EMPTY_BUFFER; - } - if (numHeaders > SPDY_MAX_NV_LENGTH) { - throw new IllegalArgumentException( - "header block contains too many headers"); - } - ByteBuf headerBlock = alloc.heapBuffer(); - writeLengthField(headerBlock, numHeaders); - for (CharSequence name: names) { - writeLengthField(headerBlock, name.length()); - ByteBufUtil.writeAscii(headerBlock, name); - int savedIndex = headerBlock.writerIndex(); - int valueLength = 0; - writeLengthField(headerBlock, valueLength); - for (CharSequence value: frame.headers().getAll(name)) { - int length = value.length(); - if (length > 0) { - ByteBufUtil.writeAscii(headerBlock, value); - headerBlock.writeByte(0); - valueLength += length + 1; - } - } - if (valueLength != 0) { - valueLength --; - } - if (valueLength > SPDY_MAX_NV_LENGTH) { - throw new IllegalArgumentException( - "header exceeds allowable length: " + name); - } - if (valueLength > 0) { - setLengthField(headerBlock, savedIndex, valueLength); - headerBlock.writerIndex(headerBlock.writerIndex() - 1); - } - } - return headerBlock; - } - - @Override - void end() { - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java deleted file mode 100644 index 3fb11ffde8..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - -final class SpdyHeaderBlockZlibDecoder extends SpdyHeaderBlockRawDecoder { - - private static final int DEFAULT_BUFFER_CAPACITY = 4096; - private static final SpdyProtocolException INVALID_HEADER_BLOCK = - new SpdyProtocolException("Invalid Header Block"); - - private final Inflater decompressor = new Inflater(); - - private ByteBuf decompressed; - - SpdyHeaderBlockZlibDecoder(SpdyVersion spdyVersion, int maxHeaderSize) { - super(spdyVersion, maxHeaderSize); - } - - @Override - void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { - int len = setInput(headerBlock); - - int numBytes; - do { - numBytes = decompress(alloc, frame); - } while (numBytes > 0); - - // z_stream has an internal 64-bit hold buffer - // it is always capable of consuming the entire input - if (decompressor.getRemaining() != 0) { - // we reached the end of the deflate stream - throw INVALID_HEADER_BLOCK; - } - - headerBlock.skipBytes(len); - } - - private int setInput(ByteBuf compressed) { - int len = compressed.readableBytes(); - - if (compressed.hasArray()) { - decompressor.setInput(compressed.array(), compressed.arrayOffset() + compressed.readerIndex(), len); - } else { - byte[] in = new byte[len]; - compressed.getBytes(compressed.readerIndex(), in); - decompressor.setInput(in, 0, in.length); - } - - return len; - } - - private int decompress(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception { - ensureBuffer(alloc); - byte[] out = decompressed.array(); - int off = decompressed.arrayOffset() + decompressed.writerIndex(); - try { - int numBytes = decompressor.inflate(out, off, decompressed.writableBytes()); - if (numBytes == 0 && decompressor.needsDictionary()) { - try { - decompressor.setDictionary(SPDY_DICT); - } catch (IllegalArgumentException ignored) { - throw INVALID_HEADER_BLOCK; - } - numBytes = decompressor.inflate(out, off, decompressed.writableBytes()); - } - if (frame != null) { - decompressed.writerIndex(decompressed.writerIndex() + numBytes); - decodeHeaderBlock(decompressed, frame); - decompressed.discardReadBytes(); - } - - return numBytes; - } catch (DataFormatException e) { - throw new SpdyProtocolException("Received invalid header block", e); - } - } - - private void ensureBuffer(ByteBufAllocator alloc) { - if (decompressed == null) { - decompressed = alloc.heapBuffer(DEFAULT_BUFFER_CAPACITY); - } - decompressed.ensureWritable(1); - } - - @Override - void endHeaderBlock(SpdyHeadersFrame frame) throws Exception { - super.endHeaderBlock(frame); - releaseBuffer(); - } - - @Override - public void end() { - super.end(); - releaseBuffer(); - decompressor.end(); - } - - private void releaseBuffer() { - if (decompressed != null) { - decompressed.release(); - decompressed = null; - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibEncoder.java deleted file mode 100644 index 9e4cf31aea..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibEncoder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; - -import java.util.zip.Deflater; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - -class SpdyHeaderBlockZlibEncoder extends SpdyHeaderBlockRawEncoder { - - private final Deflater compressor; - - private boolean finished; - - SpdyHeaderBlockZlibEncoder(SpdyVersion spdyVersion, int compressionLevel) { - super(spdyVersion); - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - compressor = new Deflater(compressionLevel); - compressor.setDictionary(SPDY_DICT); - } - - private int setInput(ByteBuf decompressed) { - int len = decompressed.readableBytes(); - - if (decompressed.hasArray()) { - compressor.setInput(decompressed.array(), decompressed.arrayOffset() + decompressed.readerIndex(), len); - } else { - byte[] in = new byte[len]; - decompressed.getBytes(decompressed.readerIndex(), in); - compressor.setInput(in, 0, in.length); - } - - return len; - } - - private ByteBuf encode(ByteBufAllocator alloc, int len) { - ByteBuf compressed = alloc.heapBuffer(len); - boolean release = true; - try { - while (compressInto(compressed)) { - // Although unlikely, it's possible that the compressed size is larger than the decompressed size - compressed.ensureWritable(compressed.capacity() << 1); - } - release = false; - return compressed; - } finally { - if (release) { - compressed.release(); - } - } - } - - private boolean compressInto(ByteBuf compressed) { - byte[] out = compressed.array(); - int off = compressed.arrayOffset() + compressed.writerIndex(); - int toWrite = compressed.writableBytes(); - int numBytes = compressor.deflate(out, off, toWrite, Deflater.SYNC_FLUSH); - compressed.writerIndex(compressed.writerIndex() + numBytes); - return numBytes == toWrite; - } - - @Override - public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception { - if (frame == null) { - throw new IllegalArgumentException("frame"); - } - - if (finished) { - return Unpooled.EMPTY_BUFFER; - } - - ByteBuf decompressed = super.encode(alloc, frame); - try { - if (!decompressed.isReadable()) { - return Unpooled.EMPTY_BUFFER; - } - - int len = setInput(decompressed); - return encode(alloc, len); - } finally { - decompressed.release(); - } - } - - @Override - public void end() { - if (finished) { - return; - } - finished = true; - compressor.end(); - super.end(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java deleted file mode 100644 index f20fde5911..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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; - -import io.netty.handler.codec.Headers; -import io.netty.util.AsciiString; - -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -/** - * Provides the constants for the standard SPDY HTTP header names and commonly - * used utility methods that access a {@link SpdyHeadersFrame}. - */ -public interface SpdyHeaders extends Headers { - - /** - * SPDY HTTP header names - */ - final class HttpNames { - /** - * {@code ":host"} - */ - public static final AsciiString HOST = AsciiString.cached(":host"); - /** - * {@code ":method"} - */ - public static final AsciiString METHOD = AsciiString.cached(":method"); - /** - * {@code ":path"} - */ - public static final AsciiString PATH = AsciiString.cached(":path"); - /** - * {@code ":scheme"} - */ - public static final AsciiString SCHEME = AsciiString.cached(":scheme"); - /** - * {@code ":status"} - */ - public static final AsciiString STATUS = AsciiString.cached(":status"); - /** - * {@code ":version"} - */ - public static final AsciiString VERSION = AsciiString.cached(":version"); - - private HttpNames() { } - } - - /** - * {@link Headers#get(Object)} and convert the result to a {@link String}. - * @param name the name of the header to retrieve - * @return the first header value if the header is found. {@code null} if there's no such header. - */ - String getAsString(CharSequence name); - - /** - * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}. - * @param name the name of the header to retrieve - * @return a {@link List} of header values or an empty {@link List} if no values are found. - */ - List getAllAsString(CharSequence name); - - /** - * {@link #iterator()} that converts each {@link Entry}'s key and value to a {@link String}. - */ - Iterator> iteratorAsString(); - - /** - * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise. - *

- * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value. - * @param name the name of the header to find - * @param value the value of the header to find - * @param ignoreCase {@code true} then a case insensitive compare is run to compare values. - * otherwise a case sensitive compare is run to compare values. - */ - boolean contains(CharSequence name, CharSequence value, boolean ignoreCase); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeadersFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeadersFrame.java deleted file mode 100644 index b1f1303446..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeadersFrame.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol HEADERS Frame - */ -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 {@code true} if this header block has been truncated due to - * length restrictions. - */ - boolean isTruncated(); - - /** - * Mark this header block as truncated. - */ - SpdyHeadersFrame setTruncated(); - - /** - * Returns the {@link SpdyHeaders}. - */ - SpdyHeaders headers(); - - @Override - SpdyHeadersFrame setStreamId(int streamID); - - @Override - SpdyHeadersFrame setLast(boolean last); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java deleted file mode 100644 index 1575b0ddde..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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; - -import io.netty.channel.CombinedChannelDuplexHandler; - -/** - * A combination of {@link SpdyHttpDecoder} and {@link SpdyHttpEncoder} - */ -public final class SpdyHttpCodec extends CombinedChannelDuplexHandler { - /** - * Creates a new instance with the specified decoder options. - */ - public SpdyHttpCodec(SpdyVersion version, int maxContentLength) { - super(new SpdyHttpDecoder(version, maxContentLength), new SpdyHttpEncoder(version)); - } - - /** - * Creates a new instance with the specified decoder options. - */ - public SpdyHttpCodec(SpdyVersion version, int maxContentLength, boolean validateHttpHeaders) { - super(new SpdyHttpDecoder(version, maxContentLength, validateHttpHeaders), new SpdyHttpEncoder(version)); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java deleted file mode 100644 index 221201958b..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * 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; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; -import io.netty.handler.codec.TooLongFrameException; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpMessage; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpUtil; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names; -import io.netty.util.ReferenceCountUtil; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static io.netty.handler.codec.spdy.SpdyHeaders.HttpNames.*; - -/** - * Decodes {@link SpdySynStreamFrame}s, {@link SpdySynReplyFrame}s, - * and {@link SpdyDataFrame}s into {@link FullHttpRequest}s and {@link FullHttpResponse}s. - */ -public class SpdyHttpDecoder extends MessageToMessageDecoder { - - private final boolean validateHeaders; - private final int spdyVersion; - private final int maxContentLength; - private final Map messageMap; - - /** - * Creates a new instance. - * - * @param version the protocol version - * @param maxContentLength the maximum length of the message content. - * If the length of the message content exceeds this value, - * a {@link TooLongFrameException} will be raised. - */ - public SpdyHttpDecoder(SpdyVersion version, int maxContentLength) { - this(version, maxContentLength, new HashMap<>(), true); - } - - /** - * Creates a new instance. - * - * @param version the protocol version - * @param maxContentLength the maximum length of the message content. - * If the length of the message content exceeds this value, - * a {@link TooLongFrameException} will be raised. - * @param validateHeaders {@code true} if http headers should be validated - */ - public SpdyHttpDecoder(SpdyVersion version, int maxContentLength, boolean validateHeaders) { - this(version, maxContentLength, new HashMap<>(), validateHeaders); - } - - /** - * Creates a new instance with the specified parameters. - * - * @param version the protocol version - * @param maxContentLength the maximum length of the message content. - * If the length of the message content exceeds this value, - * a {@link TooLongFrameException} will be raised. - * @param messageMap the {@link Map} used to hold partially received messages. - */ - protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map messageMap) { - this(version, maxContentLength, messageMap, true); - } - - /** - * Creates a new instance with the specified parameters. - * - * @param version the protocol version - * @param maxContentLength the maximum length of the message content. - * If the length of the message content exceeds this value, - * a {@link TooLongFrameException} will be raised. - * @param messageMap the {@link Map} used to hold partially received messages. - * @param validateHeaders {@code true} if http headers should be validated - */ - protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map messageMap, boolean validateHeaders) { - if (version == null) { - throw new NullPointerException("version"); - } - if (maxContentLength <= 0) { - throw new IllegalArgumentException( - "maxContentLength must be a positive integer: " + maxContentLength); - } - spdyVersion = version.getVersion(); - this.maxContentLength = maxContentLength; - this.messageMap = messageMap; - this.validateHeaders = validateHeaders; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - // Release any outstanding messages from the map - for (Map.Entry entry : messageMap.entrySet()) { - ReferenceCountUtil.safeRelease(entry.getValue()); - } - messageMap.clear(); - super.channelInactive(ctx); - } - - protected FullHttpMessage putMessage(int streamId, FullHttpMessage message) { - return messageMap.put(streamId, message); - } - - protected FullHttpMessage getMessage(int streamId) { - return messageMap.get(streamId); - } - - protected FullHttpMessage removeMessage(int streamId) { - return messageMap.remove(streamId); - } - - @Override - protected void decode(ChannelHandlerContext ctx, SpdyFrame msg, List out) - throws Exception { - if (msg instanceof SpdySynStreamFrame) { - - // HTTP requests/responses are mapped one-to-one to SPDY streams. - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - int streamId = spdySynStreamFrame.streamId(); - - if (SpdyCodecUtil.isServerId(streamId)) { - // SYN_STREAM frames initiated by the server are pushed resources - int associatedToStreamId = spdySynStreamFrame.associatedStreamId(); - - // If a client receives a SYN_STREAM with an Associated-To-Stream-ID of 0 - // it must reply with a RST_STREAM with error code INVALID_STREAM. - if (associatedToStreamId == 0) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.INVALID_STREAM); - ctx.writeAndFlush(spdyRstStreamFrame); - return; - } - - // If a client receives a SYN_STREAM with isLast set, - // reply with a RST_STREAM with error code PROTOCOL_ERROR - // (we only support pushed resources divided into two header blocks). - if (spdySynStreamFrame.isLast()) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - return; - } - - // If a client receives a response with a truncated header block, - // reply with a RST_STREAM with error code INTERNAL_ERROR. - if (spdySynStreamFrame.isTruncated()) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.INTERNAL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - return; - } - - try { - FullHttpRequest httpRequestWithEntity = createHttpRequest(spdySynStreamFrame, ctx.alloc()); - - // Set the Stream-ID, Associated-To-Stream-ID, and Priority as headers - httpRequestWithEntity.headers().setInt(Names.STREAM_ID, streamId); - httpRequestWithEntity.headers().setInt(Names.ASSOCIATED_TO_STREAM_ID, associatedToStreamId); - httpRequestWithEntity.headers().setInt(Names.PRIORITY, spdySynStreamFrame.priority()); - - out.add(httpRequestWithEntity); - - } catch (Throwable ignored) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - } - } else { - // SYN_STREAM frames initiated by the client are HTTP requests - - // If a client sends a request with a truncated header block, the server must - // reply with a HTTP 431 REQUEST HEADER FIELDS TOO LARGE reply. - if (spdySynStreamFrame.isTruncated()) { - SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId); - spdySynReplyFrame.setLast(true); - SpdyHeaders frameHeaders = spdySynReplyFrame.headers(); - frameHeaders.setInt(STATUS, HttpResponseStatus.REQUEST_HEADER_FIELDS_TOO_LARGE.code()); - frameHeaders.setObject(VERSION, HttpVersion.HTTP_1_0); - ctx.writeAndFlush(spdySynReplyFrame); - return; - } - - try { - FullHttpRequest httpRequestWithEntity = createHttpRequest(spdySynStreamFrame, ctx.alloc()); - - // Set the Stream-ID as a header - httpRequestWithEntity.headers().setInt(Names.STREAM_ID, streamId); - - if (spdySynStreamFrame.isLast()) { - out.add(httpRequestWithEntity); - } else { - // Request body will follow in a series of Data Frames - putMessage(streamId, httpRequestWithEntity); - } - } catch (Throwable t) { - // If a client sends a SYN_STREAM without all of the getMethod, url (host and path), - // scheme, and version headers the server must reply with a HTTP 400 BAD REQUEST reply. - // Also sends HTTP 400 BAD REQUEST reply if header name/value pairs are invalid - SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId); - spdySynReplyFrame.setLast(true); - SpdyHeaders frameHeaders = spdySynReplyFrame.headers(); - frameHeaders.setInt(STATUS, HttpResponseStatus.BAD_REQUEST.code()); - frameHeaders.setObject(VERSION, HttpVersion.HTTP_1_0); - ctx.writeAndFlush(spdySynReplyFrame); - } - } - - } else if (msg instanceof SpdySynReplyFrame) { - - SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; - int streamId = spdySynReplyFrame.streamId(); - - // If a client receives a SYN_REPLY with a truncated header block, - // reply with a RST_STREAM frame with error code INTERNAL_ERROR. - if (spdySynReplyFrame.isTruncated()) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.INTERNAL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - return; - } - - try { - FullHttpResponse httpResponseWithEntity = - createHttpResponse(spdySynReplyFrame, ctx.alloc(), validateHeaders); - - // Set the Stream-ID as a header - httpResponseWithEntity.headers().setInt(Names.STREAM_ID, streamId); - - if (spdySynReplyFrame.isLast()) { - HttpUtil.setContentLength(httpResponseWithEntity, 0); - out.add(httpResponseWithEntity); - } else { - // Response body will follow in a series of Data Frames - putMessage(streamId, httpResponseWithEntity); - } - } catch (Throwable t) { - // If a client receives a SYN_REPLY without valid getStatus and version headers - // the client must reply with a RST_STREAM frame indicating a PROTOCOL_ERROR - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - } - - } else if (msg instanceof SpdyHeadersFrame) { - - SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; - int streamId = spdyHeadersFrame.streamId(); - FullHttpMessage fullHttpMessage = getMessage(streamId); - - if (fullHttpMessage == null) { - // HEADERS frames may initiate a pushed response - if (SpdyCodecUtil.isServerId(streamId)) { - - // If a client receives a HEADERS with a truncated header block, - // reply with a RST_STREAM frame with error code INTERNAL_ERROR. - if (spdyHeadersFrame.isTruncated()) { - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.INTERNAL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - return; - } - - try { - fullHttpMessage = createHttpResponse(spdyHeadersFrame, ctx.alloc(), validateHeaders); - - // Set the Stream-ID as a header - fullHttpMessage.headers().setInt(Names.STREAM_ID, streamId); - - if (spdyHeadersFrame.isLast()) { - HttpUtil.setContentLength(fullHttpMessage, 0); - out.add(fullHttpMessage); - } else { - // Response body will follow in a series of Data Frames - putMessage(streamId, fullHttpMessage); - } - } catch (Throwable t) { - // If a client receives a SYN_REPLY without valid getStatus and version headers - // the client must reply with a RST_STREAM frame indicating a PROTOCOL_ERROR - SpdyRstStreamFrame spdyRstStreamFrame = - new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR); - ctx.writeAndFlush(spdyRstStreamFrame); - } - } - return; - } - - // Ignore trailers in a truncated HEADERS frame. - if (!spdyHeadersFrame.isTruncated()) { - for (Map.Entry e: spdyHeadersFrame.headers()) { - fullHttpMessage.headers().add(e.getKey(), e.getValue()); - } - } - - if (spdyHeadersFrame.isLast()) { - HttpUtil.setContentLength(fullHttpMessage, fullHttpMessage.content().readableBytes()); - removeMessage(streamId); - out.add(fullHttpMessage); - } - - } else if (msg instanceof SpdyDataFrame) { - - SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; - int streamId = spdyDataFrame.streamId(); - FullHttpMessage fullHttpMessage = getMessage(streamId); - - // If message is not in map discard Data Frame. - if (fullHttpMessage == null) { - return; - } - - ByteBuf content = fullHttpMessage.content(); - if (content.readableBytes() > maxContentLength - spdyDataFrame.content().readableBytes()) { - removeMessage(streamId); - throw new TooLongFrameException( - "HTTP content length exceeded " + maxContentLength + " bytes."); - } - - ByteBuf spdyDataFrameData = spdyDataFrame.content(); - int spdyDataFrameDataLen = spdyDataFrameData.readableBytes(); - content.writeBytes(spdyDataFrameData, spdyDataFrameData.readerIndex(), spdyDataFrameDataLen); - - if (spdyDataFrame.isLast()) { - HttpUtil.setContentLength(fullHttpMessage, content.readableBytes()); - removeMessage(streamId); - out.add(fullHttpMessage); - } - - } else if (msg instanceof SpdyRstStreamFrame) { - - SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; - int streamId = spdyRstStreamFrame.streamId(); - removeMessage(streamId); - } - } - - private static FullHttpRequest createHttpRequest(SpdyHeadersFrame requestFrame, ByteBufAllocator alloc) - throws Exception { - // Create the first line of the request from the name/value pairs - SpdyHeaders headers = requestFrame.headers(); - HttpMethod method = HttpMethod.valueOf(headers.getAsString(METHOD)); - String url = headers.getAsString(PATH); - HttpVersion httpVersion = HttpVersion.valueOf(headers.getAsString(VERSION)); - headers.remove(METHOD); - headers.remove(PATH); - headers.remove(VERSION); - - boolean release = true; - ByteBuf buffer = alloc.buffer(); - try { - FullHttpRequest req = new DefaultFullHttpRequest(httpVersion, method, url, buffer); - - // Remove the scheme header - headers.remove(SCHEME); - - // Replace the SPDY host header with the HTTP host header - CharSequence host = headers.get(HOST); - headers.remove(HOST); - req.headers().set(HttpHeaderNames.HOST, host); - - for (Map.Entry e : requestFrame.headers()) { - req.headers().add(e.getKey(), e.getValue()); - } - - // The Connection and Keep-Alive headers are no longer valid - HttpUtil.setKeepAlive(req, true); - - // Transfer-Encoding header is not valid - req.headers().remove(HttpHeaderNames.TRANSFER_ENCODING); - release = false; - return req; - } finally { - if (release) { - buffer.release(); - } - } - } - - private static FullHttpResponse createHttpResponse(SpdyHeadersFrame responseFrame, ByteBufAllocator alloc, - boolean validateHeaders) throws Exception { - - // Create the first line of the response from the name/value pairs - SpdyHeaders headers = responseFrame.headers(); - HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS)); - HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION)); - headers.remove(STATUS); - headers.remove(VERSION); - - boolean release = true; - ByteBuf buffer = alloc.buffer(); - try { - FullHttpResponse res = new DefaultFullHttpResponse(version, status, buffer, validateHeaders); - for (Map.Entry e: responseFrame.headers()) { - res.headers().add(e.getKey(), e.getValue()); - } - - // The Connection and Keep-Alive headers are no longer valid - HttpUtil.setKeepAlive(res, true); - - // Transfer-Encoding header is not valid - res.headers().remove(HttpHeaderNames.TRANSFER_ENCODING); - res.headers().remove(HttpHeaderNames.TRAILER); - - release = false; - return res; - } finally { - if (release) { - buffer.release(); - } - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java deleted file mode 100644 index d3c5d58247..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java +++ /dev/null @@ -1,332 +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.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.UnsupportedMessageTypeException; -import io.netty.handler.codec.http.FullHttpMessage; -import io.netty.handler.codec.http.HttpContent; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.http.HttpObject; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.LastHttpContent; -import io.netty.util.AsciiString; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Encodes {@link HttpRequest}s, {@link HttpResponse}s, and {@link HttpContent}s - * into {@link SpdySynStreamFrame}s and {@link SpdySynReplyFrame}s. - * - *

Request Annotations

- * - * SPDY specific headers must be added to {@link HttpRequest}s: - * - * - * - * - * - * - * - * - * - * - * - * - *
Header NameHeader Value
{@code "X-SPDY-Stream-ID"}The Stream-ID for this request. - * Stream-IDs must be odd, positive integers, and must increase monotonically.
{@code "X-SPDY-Priority"}The priority value for this request. - * The priority should be between 0 and 7 inclusive. - * 0 represents the highest priority and 7 represents the lowest. - * This header is optional and defaults to 0.
- * - *

Response Annotations

- * - * SPDY specific headers must be added to {@link HttpResponse}s: - * - * - * - * - * - * - * - * - *
Header NameHeader Value
{@code "X-SPDY-Stream-ID"}The Stream-ID of the request corresponding to this response.
- * - *

Pushed Resource Annotations

- * - * SPDY specific headers must be added to pushed {@link HttpRequest}s: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Header NameHeader Value
{@code "X-SPDY-Stream-ID"}The Stream-ID for this resource. - * Stream-IDs must be even, positive integers, and must increase monotonically.
{@code "X-SPDY-Associated-To-Stream-ID"}The Stream-ID of the request that initiated this pushed resource.
{@code "X-SPDY-Priority"}The priority value for this resource. - * The priority should be between 0 and 7 inclusive. - * 0 represents the highest priority and 7 represents the lowest. - * This header is optional and defaults to 0.
- * - *

Required Annotations

- * - * SPDY requires that all Requests and Pushed Resources contain - * an HTTP "Host" header. - * - *

Optional Annotations

- * - * Requests and Pushed Resources must contain a SPDY scheme header. - * This can be set via the {@code "X-SPDY-Scheme"} header but otherwise - * defaults to "https" as that is the most common SPDY deployment. - * - *

Chunked Content

- * - * This encoder associates all {@link HttpContent}s that it receives - * with the most recently received 'chunked' {@link HttpRequest} - * or {@link HttpResponse}. - * - *

Pushed Resources

- * - * All pushed resources should be sent before sending the response - * that corresponds to the initial request. - */ -public class SpdyHttpEncoder extends MessageToMessageEncoder { - - private int currentStreamId; - - private final boolean validateHeaders; - private final boolean headersToLowerCase; - - /** - * Creates a new instance. - * - * @param version the protocol version - */ - public SpdyHttpEncoder(SpdyVersion version) { - this(version, true, true); - } - - /** - * Creates a new instance. - * - * @param version the protocol version - * @param headersToLowerCase convert header names to lowercase. In a controlled environment, - * one can disable the conversion. - * @param validateHeaders validate the header names and values when adding them to the {@link SpdyHeaders} - */ - public SpdyHttpEncoder(SpdyVersion version, boolean headersToLowerCase, boolean validateHeaders) { - if (version == null) { - throw new NullPointerException("version"); - } - this.headersToLowerCase = headersToLowerCase; - this.validateHeaders = validateHeaders; - } - - @Override - protected void encode(ChannelHandlerContext ctx, HttpObject msg, List out) throws Exception { - - boolean valid = false; - boolean last = false; - - if (msg instanceof HttpRequest) { - - HttpRequest httpRequest = (HttpRequest) msg; - SpdySynStreamFrame spdySynStreamFrame = createSynStreamFrame(httpRequest); - out.add(spdySynStreamFrame); - - last = spdySynStreamFrame.isLast() || spdySynStreamFrame.isUnidirectional(); - valid = true; - } - if (msg instanceof HttpResponse) { - - HttpResponse httpResponse = (HttpResponse) msg; - SpdyHeadersFrame spdyHeadersFrame = createHeadersFrame(httpResponse); - out.add(spdyHeadersFrame); - - last = spdyHeadersFrame.isLast(); - valid = true; - } - if (msg instanceof HttpContent && !last) { - - HttpContent chunk = (HttpContent) msg; - - chunk.content().retain(); - SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(currentStreamId, chunk.content()); - if (chunk instanceof LastHttpContent) { - LastHttpContent trailer = (LastHttpContent) chunk; - HttpHeaders trailers = trailer.trailingHeaders(); - if (trailers.isEmpty()) { - spdyDataFrame.setLast(true); - out.add(spdyDataFrame); - } else { - // Create SPDY HEADERS frame out of trailers - SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(currentStreamId, validateHeaders); - spdyHeadersFrame.setLast(true); - Iterator> itr = trailers.iteratorCharSequence(); - while (itr.hasNext()) { - Map.Entry entry = itr.next(); - final CharSequence headerName = - headersToLowerCase ? AsciiString.of(entry.getKey()).toLowerCase() : entry.getKey(); - spdyHeadersFrame.headers().add(headerName, entry.getValue()); - } - - // Write DATA frame and append HEADERS frame - out.add(spdyDataFrame); - out.add(spdyHeadersFrame); - } - } else { - out.add(spdyDataFrame); - } - - valid = true; - } - - if (!valid) { - throw new UnsupportedMessageTypeException(msg); - } - } - - @SuppressWarnings("deprecation") - private SpdySynStreamFrame createSynStreamFrame(HttpRequest httpRequest) throws Exception { - // Get the Stream-ID, Associated-To-Stream-ID, Priority, and scheme from the headers - final HttpHeaders httpHeaders = httpRequest.headers(); - int streamId = httpHeaders.getInt(SpdyHttpHeaders.Names.STREAM_ID); - int associatedToStreamId = httpHeaders.getInt(SpdyHttpHeaders.Names.ASSOCIATED_TO_STREAM_ID, 0); - byte priority = (byte) httpHeaders.getInt(SpdyHttpHeaders.Names.PRIORITY, 0); - CharSequence scheme = httpHeaders.get(SpdyHttpHeaders.Names.SCHEME); - httpHeaders.remove(SpdyHttpHeaders.Names.STREAM_ID); - httpHeaders.remove(SpdyHttpHeaders.Names.ASSOCIATED_TO_STREAM_ID); - httpHeaders.remove(SpdyHttpHeaders.Names.PRIORITY); - httpHeaders.remove(SpdyHttpHeaders.Names.SCHEME); - - // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding - // headers are not valid and MUST not be sent. - httpHeaders.remove(HttpHeaderNames.CONNECTION); - httpHeaders.remove("Keep-Alive"); - httpHeaders.remove("Proxy-Connection"); - httpHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING); - - SpdySynStreamFrame spdySynStreamFrame = - new DefaultSpdySynStreamFrame(streamId, associatedToStreamId, priority, validateHeaders); - - // Unfold the first line of the message into name/value pairs - SpdyHeaders frameHeaders = spdySynStreamFrame.headers(); - frameHeaders.set(SpdyHeaders.HttpNames.METHOD, httpRequest.method().name()); - frameHeaders.set(SpdyHeaders.HttpNames.PATH, httpRequest.uri()); - frameHeaders.set(SpdyHeaders.HttpNames.VERSION, httpRequest.protocolVersion().text()); - - // Replace the HTTP host header with the SPDY host header - CharSequence host = httpHeaders.get(HttpHeaderNames.HOST); - httpHeaders.remove(HttpHeaderNames.HOST); - frameHeaders.set(SpdyHeaders.HttpNames.HOST, host); - - // Set the SPDY scheme header - if (scheme == null) { - scheme = "https"; - } - frameHeaders.set(SpdyHeaders.HttpNames.SCHEME, scheme); - - // Transfer the remaining HTTP headers - Iterator> itr = httpHeaders.iteratorCharSequence(); - while (itr.hasNext()) { - Map.Entry entry = itr.next(); - final CharSequence headerName = - headersToLowerCase ? AsciiString.of(entry.getKey()).toLowerCase() : entry.getKey(); - frameHeaders.add(headerName, entry.getValue()); - } - currentStreamId = spdySynStreamFrame.streamId(); - if (associatedToStreamId == 0) { - spdySynStreamFrame.setLast(isLast(httpRequest)); - } else { - spdySynStreamFrame.setUnidirectional(true); - } - - return spdySynStreamFrame; - } - - @SuppressWarnings("deprecation") - private SpdyHeadersFrame createHeadersFrame(HttpResponse httpResponse) throws Exception { - // Get the Stream-ID from the headers - final HttpHeaders httpHeaders = httpResponse.headers(); - int streamId = httpHeaders.getInt(SpdyHttpHeaders.Names.STREAM_ID); - httpHeaders.remove(SpdyHttpHeaders.Names.STREAM_ID); - - // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding - // headers are not valid and MUST not be sent. - httpHeaders.remove(HttpHeaderNames.CONNECTION); - httpHeaders.remove("Keep-Alive"); - httpHeaders.remove("Proxy-Connection"); - httpHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING); - - SpdyHeadersFrame spdyHeadersFrame; - if (SpdyCodecUtil.isServerId(streamId)) { - spdyHeadersFrame = new DefaultSpdyHeadersFrame(streamId, validateHeaders); - } else { - spdyHeadersFrame = new DefaultSpdySynReplyFrame(streamId, validateHeaders); - } - SpdyHeaders frameHeaders = spdyHeadersFrame.headers(); - // Unfold the first line of the response into name/value pairs - frameHeaders.set(SpdyHeaders.HttpNames.STATUS, httpResponse.status().codeAsText()); - frameHeaders.set(SpdyHeaders.HttpNames.VERSION, httpResponse.protocolVersion().text()); - - // Transfer the remaining HTTP headers - Iterator> itr = httpHeaders.iteratorCharSequence(); - while (itr.hasNext()) { - Map.Entry entry = itr.next(); - final CharSequence headerName = - headersToLowerCase ? AsciiString.of(entry.getKey()).toLowerCase() : entry.getKey(); - spdyHeadersFrame.headers().add(headerName, entry.getValue()); - } - - currentStreamId = streamId; - spdyHeadersFrame.setLast(isLast(httpResponse)); - - return spdyHeadersFrame; - } - - /** - * Checks if the given HTTP message should be considered as a last SPDY frame. - * - * @param httpMessage check this HTTP message - * @return whether the given HTTP message should generate a last SPDY frame. - */ - private static boolean isLast(HttpMessage httpMessage) { - if (httpMessage instanceof FullHttpMessage) { - FullHttpMessage fullMessage = (FullHttpMessage) httpMessage; - if (fullMessage.trailingHeaders().isEmpty() && !fullMessage.content().isReadable()) { - return true; - } - } - - return false; - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java deleted file mode 100644 index 92d5fa835b..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java +++ /dev/null @@ -1,51 +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.AsciiString; - -/** - * Provides the constants for the header names and the utility methods - * used by the {@link SpdyHttpDecoder} and {@link SpdyHttpEncoder}. - */ -public final class SpdyHttpHeaders { - - /** - * SPDY HTTP header names - */ - public static final class Names { - /** - * {@code "x-spdy-stream-id"} - */ - public static final AsciiString STREAM_ID = AsciiString.cached("x-spdy-stream-id"); - /** - * {@code "x-spdy-associated-to-stream-id"} - */ - public static final AsciiString ASSOCIATED_TO_STREAM_ID = AsciiString.cached("x-spdy-associated-to-stream-id"); - /** - * {@code "x-spdy-priority"} - */ - public static final AsciiString PRIORITY = AsciiString.cached("x-spdy-priority"); - /** - * {@code "x-spdy-scheme"} - */ - public static final AsciiString SCHEME = AsciiString.cached("x-spdy-scheme"); - - private Names() { } - } - - private SpdyHttpHeaders() { } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java deleted file mode 100644 index e57c167a77..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java +++ /dev/null @@ -1,68 +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.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageCodec; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names; -import io.netty.util.ReferenceCountUtil; - -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -/** - * {@link MessageToMessageCodec} that takes care of adding the right {@link SpdyHttpHeaders.Names#STREAM_ID} to the - * {@link HttpMessage} if one is not present. This makes it possible to just re-use plan handlers current used - * for HTTP. - */ -public class SpdyHttpResponseStreamIdHandler extends - MessageToMessageCodec { - private static final Integer NO_ID = -1; - private final Queue ids = new LinkedList<>(); - - @Override - public boolean acceptInboundMessage(Object msg) throws Exception { - return msg instanceof HttpMessage || msg instanceof SpdyRstStreamFrame; - } - - @Override - protected void encode(ChannelHandlerContext ctx, HttpMessage msg, List out) throws Exception { - Integer id = ids.poll(); - if (id != null && id.intValue() != NO_ID && !msg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) { - msg.headers().setInt(Names.STREAM_ID, id); - } - - out.add(ReferenceCountUtil.retain(msg)); - } - - @Override - protected void decode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { - if (msg instanceof HttpMessage) { - boolean contains = ((HttpMessage) msg).headers().contains(SpdyHttpHeaders.Names.STREAM_ID); - if (!contains) { - ids.add(NO_ID); - } else { - ids.add(((HttpMessage) msg).headers().getInt(Names.STREAM_ID)); - } - } else if (msg instanceof SpdyRstStreamFrame) { - ids.remove(((SpdyRstStreamFrame) msg).streamId()); - } - - out.add(ReferenceCountUtil.retain(msg)); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyPingFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyPingFrame.java deleted file mode 100644 index fc124f8d31..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyPingFrame.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol PING Frame - */ -public interface SpdyPingFrame extends SpdyFrame { - - /** - * Returns the ID of this frame. - */ - int id(); - - /** - * Sets the ID of this frame. - */ - SpdyPingFrame setId(int id); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyProtocolException.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyProtocolException.java deleted file mode 100644 index 2b5bcbcec2..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyProtocolException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 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; - -public class SpdyProtocolException extends Exception { - - private static final long serialVersionUID = 7870000537743847264L; - - /** - * Creates a new instance. - */ - public SpdyProtocolException() { } - - /** - * Creates a new instance. - */ - public SpdyProtocolException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a new instance. - */ - public SpdyProtocolException(String message) { - super(message); - } - - /** - * Creates a new instance. - */ - public SpdyProtocolException(Throwable cause) { - super(cause); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyRstStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyRstStreamFrame.java deleted file mode 100644 index 44cadb2c60..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyRstStreamFrame.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol RST_STREAM Frame - */ -public interface SpdyRstStreamFrame extends SpdyStreamFrame { - - /** - * Returns the status of this frame. - */ - SpdyStreamStatus status(); - - /** - * Sets the status of this frame. - */ - SpdyRstStreamFrame setStatus(SpdyStreamStatus status); - - @Override - SpdyRstStreamFrame setStreamId(int streamId); - - @Override - SpdyRstStreamFrame setLast(boolean last); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySession.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySession.java deleted file mode 100644 index 954b2c5851..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySession.java +++ /dev/null @@ -1,357 +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.channel.ChannelPromise; - -import java.util.Comparator; -import java.util.Map; -import java.util.Queue; -import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - -final class SpdySession { - - private final AtomicInteger activeLocalStreams = new AtomicInteger(); - private final AtomicInteger activeRemoteStreams = new AtomicInteger(); - private final Map activeStreams = new ConcurrentHashMap<>(); - private final StreamComparator streamComparator = new StreamComparator(); - private final AtomicInteger sendWindowSize; - private final AtomicInteger receiveWindowSize; - - SpdySession(int sendWindowSize, int receiveWindowSize) { - this.sendWindowSize = new AtomicInteger(sendWindowSize); - this.receiveWindowSize = new AtomicInteger(receiveWindowSize); - } - - int numActiveStreams(boolean remote) { - if (remote) { - return activeRemoteStreams.get(); - } else { - return activeLocalStreams.get(); - } - } - - boolean noActiveStreams() { - return activeStreams.isEmpty(); - } - - boolean isActiveStream(int streamId) { - return activeStreams.containsKey(streamId); - } - - // Stream-IDs should be iterated in priority order - Map activeStreams() { - Map streams = new TreeMap<>(streamComparator); - streams.putAll(activeStreams); - return streams; - } - - void acceptStream( - int streamId, byte priority, boolean remoteSideClosed, boolean localSideClosed, - int sendWindowSize, int receiveWindowSize, boolean remote) { - if (!remoteSideClosed || !localSideClosed) { - StreamState state = activeStreams.put(streamId, new StreamState( - priority, remoteSideClosed, localSideClosed, sendWindowSize, receiveWindowSize)); - if (state == null) { - if (remote) { - activeRemoteStreams.incrementAndGet(); - } else { - activeLocalStreams.incrementAndGet(); - } - } - } - } - - private StreamState removeActiveStream(int streamId, boolean remote) { - StreamState state = activeStreams.remove(streamId); - if (state != null) { - if (remote) { - activeRemoteStreams.decrementAndGet(); - } else { - activeLocalStreams.decrementAndGet(); - } - } - return state; - } - - void removeStream(int streamId, Throwable cause, boolean remote) { - StreamState state = removeActiveStream(streamId, remote); - if (state != null) { - state.clearPendingWrites(cause); - } - } - - boolean isRemoteSideClosed(int streamId) { - StreamState state = activeStreams.get(streamId); - return state == null || state.isRemoteSideClosed(); - } - - void closeRemoteSide(int streamId, boolean remote) { - StreamState state = activeStreams.get(streamId); - if (state != null) { - state.closeRemoteSide(); - if (state.isLocalSideClosed()) { - removeActiveStream(streamId, remote); - } - } - } - - boolean isLocalSideClosed(int streamId) { - StreamState state = activeStreams.get(streamId); - return state == null || state.isLocalSideClosed(); - } - - void closeLocalSide(int streamId, boolean remote) { - StreamState state = activeStreams.get(streamId); - if (state != null) { - state.closeLocalSide(); - if (state.isRemoteSideClosed()) { - removeActiveStream(streamId, remote); - } - } - } - - /* - * hasReceivedReply and receivedReply are only called from channelRead() - * no need to synchronize access to the StreamState - */ - boolean hasReceivedReply(int streamId) { - StreamState state = activeStreams.get(streamId); - return state != null && state.hasReceivedReply(); - } - - void receivedReply(int streamId) { - StreamState state = activeStreams.get(streamId); - if (state != null) { - state.receivedReply(); - } - } - - int getSendWindowSize(int streamId) { - if (streamId == SPDY_SESSION_STREAM_ID) { - return sendWindowSize.get(); - } - - StreamState state = activeStreams.get(streamId); - return state != null ? state.getSendWindowSize() : -1; - } - - int updateSendWindowSize(int streamId, int deltaWindowSize) { - if (streamId == SPDY_SESSION_STREAM_ID) { - return sendWindowSize.addAndGet(deltaWindowSize); - } - - StreamState state = activeStreams.get(streamId); - return state != null ? state.updateSendWindowSize(deltaWindowSize) : -1; - } - - int updateReceiveWindowSize(int streamId, int deltaWindowSize) { - if (streamId == SPDY_SESSION_STREAM_ID) { - return receiveWindowSize.addAndGet(deltaWindowSize); - } - - StreamState state = activeStreams.get(streamId); - if (state == null) { - return -1; - } - if (deltaWindowSize > 0) { - state.setReceiveWindowSizeLowerBound(0); - } - return state.updateReceiveWindowSize(deltaWindowSize); - } - - int getReceiveWindowSizeLowerBound(int streamId) { - if (streamId == SPDY_SESSION_STREAM_ID) { - return 0; - } - - StreamState state = activeStreams.get(streamId); - return state != null ? state.getReceiveWindowSizeLowerBound() : 0; - } - - void updateAllSendWindowSizes(int deltaWindowSize) { - for (StreamState state: activeStreams.values()) { - state.updateSendWindowSize(deltaWindowSize); - } - } - - void updateAllReceiveWindowSizes(int deltaWindowSize) { - for (StreamState state: activeStreams.values()) { - state.updateReceiveWindowSize(deltaWindowSize); - if (deltaWindowSize < 0) { - state.setReceiveWindowSizeLowerBound(deltaWindowSize); - } - } - } - - boolean putPendingWrite(int streamId, PendingWrite pendingWrite) { - StreamState state = activeStreams.get(streamId); - return state != null && state.putPendingWrite(pendingWrite); - } - - PendingWrite getPendingWrite(int streamId) { - if (streamId == SPDY_SESSION_STREAM_ID) { - for (Map.Entry e: activeStreams().entrySet()) { - StreamState state = e.getValue(); - if (state.getSendWindowSize() > 0) { - PendingWrite pendingWrite = state.getPendingWrite(); - if (pendingWrite != null) { - return pendingWrite; - } - } - } - return null; - } - - StreamState state = activeStreams.get(streamId); - return state != null ? state.getPendingWrite() : null; - } - - PendingWrite removePendingWrite(int streamId) { - StreamState state = activeStreams.get(streamId); - return state != null ? state.removePendingWrite() : null; - } - - private static final class StreamState { - - private final byte priority; - private boolean remoteSideClosed; - private boolean localSideClosed; - private boolean receivedReply; - private final AtomicInteger sendWindowSize; - private final AtomicInteger receiveWindowSize; - private int receiveWindowSizeLowerBound; - private final Queue pendingWriteQueue = new ConcurrentLinkedQueue<>(); - - StreamState( - byte priority, boolean remoteSideClosed, boolean localSideClosed, - int sendWindowSize, int receiveWindowSize) { - this.priority = priority; - this.remoteSideClosed = remoteSideClosed; - this.localSideClosed = localSideClosed; - this.sendWindowSize = new AtomicInteger(sendWindowSize); - this.receiveWindowSize = new AtomicInteger(receiveWindowSize); - } - - byte getPriority() { - return priority; - } - - boolean isRemoteSideClosed() { - return remoteSideClosed; - } - - void closeRemoteSide() { - remoteSideClosed = true; - } - - boolean isLocalSideClosed() { - return localSideClosed; - } - - void closeLocalSide() { - localSideClosed = true; - } - - boolean hasReceivedReply() { - return receivedReply; - } - - void receivedReply() { - receivedReply = true; - } - - int getSendWindowSize() { - return sendWindowSize.get(); - } - - int updateSendWindowSize(int deltaWindowSize) { - return sendWindowSize.addAndGet(deltaWindowSize); - } - - int updateReceiveWindowSize(int deltaWindowSize) { - return receiveWindowSize.addAndGet(deltaWindowSize); - } - - int getReceiveWindowSizeLowerBound() { - return receiveWindowSizeLowerBound; - } - - void setReceiveWindowSizeLowerBound(int receiveWindowSizeLowerBound) { - this.receiveWindowSizeLowerBound = receiveWindowSizeLowerBound; - } - - boolean putPendingWrite(PendingWrite msg) { - return pendingWriteQueue.offer(msg); - } - - PendingWrite getPendingWrite() { - return pendingWriteQueue.peek(); - } - - PendingWrite removePendingWrite() { - return pendingWriteQueue.poll(); - } - - void clearPendingWrites(Throwable cause) { - for (;;) { - PendingWrite pendingWrite = pendingWriteQueue.poll(); - if (pendingWrite == null) { - break; - } - pendingWrite.fail(cause); - } - } - } - - private final class StreamComparator implements Comparator { - - StreamComparator() { } - - @Override - public int compare(Integer id1, Integer id2) { - StreamState state1 = activeStreams.get(id1); - StreamState state2 = activeStreams.get(id2); - - int result = state1.getPriority() - state2.getPriority(); - if (result != 0) { - return result; - } - - return id1 - id2; - } - } - - public static final class PendingWrite { - final SpdyDataFrame spdyDataFrame; - final ChannelPromise promise; - - PendingWrite(SpdyDataFrame spdyDataFrame, ChannelPromise promise) { - this.spdyDataFrame = spdyDataFrame; - this.promise = promise; - } - - void fail(Throwable cause) { - spdyDataFrame.release(); - promise.setFailure(cause); - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java deleted file mode 100644 index 6ef19b0cf3..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java +++ /dev/null @@ -1,846 +0,0 @@ -/* - * 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; - -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.util.internal.ThrowableUtil; - -import java.util.concurrent.atomic.AtomicInteger; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SESSION_STREAM_ID; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.isServerId; - -/** - * Manages streams within a SPDY session. - */ -public class SpdySessionHandler extends ChannelDuplexHandler { - - private static final SpdyProtocolException PROTOCOL_EXCEPTION = ThrowableUtil.unknownStackTrace( - new SpdyProtocolException(), SpdySessionHandler.class, "handleOutboundMessage(...)"); - private static final SpdyProtocolException STREAM_CLOSED = ThrowableUtil.unknownStackTrace( - new SpdyProtocolException("Stream closed"), SpdySessionHandler.class, "removeStream(...)"); - - private static final int DEFAULT_WINDOW_SIZE = 64 * 1024; // 64 KB default initial window size - private int initialSendWindowSize = DEFAULT_WINDOW_SIZE; - private int initialReceiveWindowSize = DEFAULT_WINDOW_SIZE; - private volatile int initialSessionReceiveWindowSize = DEFAULT_WINDOW_SIZE; - - private final SpdySession spdySession = new SpdySession(initialSendWindowSize, initialReceiveWindowSize); - private int lastGoodStreamId; - - private static final int DEFAULT_MAX_CONCURRENT_STREAMS = Integer.MAX_VALUE; - private int remoteConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS; - private int localConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS; - - private final AtomicInteger pings = new AtomicInteger(); - - private boolean sentGoAwayFrame; - private boolean receivedGoAwayFrame; - - private ChannelFutureListener closeSessionFutureListener; - - private final boolean server; - private final int minorVersion; - - /** - * Creates a new session handler. - * - * @param version the protocol version - * @param server {@code true} if and only if this session handler should - * handle the server endpoint of the connection. - * {@code false} if and only if this session handler should - * handle the client endpoint of the connection. - */ - public SpdySessionHandler(SpdyVersion version, boolean server) { - if (version == null) { - throw new NullPointerException("version"); - } - this.server = server; - minorVersion = version.getMinorVersion(); - } - - public void setSessionReceiveWindowSize(int sessionReceiveWindowSize) { - if (sessionReceiveWindowSize < 0) { - throw new IllegalArgumentException("sessionReceiveWindowSize"); - } - // This will not send a window update frame immediately. - // If this value increases the allowed receive window size, - // a WINDOW_UPDATE frame will be sent when only half of the - // session window size remains during data frame processing. - // If this value decreases the allowed receive window size, - // the window will be reduced as data frames are processed. - initialSessionReceiveWindowSize = sessionReceiveWindowSize; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof SpdyDataFrame) { - - /* - * SPDY Data frame processing requirements: - * - * If an endpoint receives a data frame for a Stream-ID which is not open - * and the endpoint has not sent a GOAWAY frame, it must issue a stream error - * with the error code INVALID_STREAM for the Stream-ID. - * - * If an endpoint which created the stream receives a data frame before receiving - * a SYN_REPLY on that stream, it is a protocol error, and the recipient must - * issue a stream error with the getStatus code PROTOCOL_ERROR for the Stream-ID. - * - * If an endpoint receives multiple data frames for invalid Stream-IDs, - * it may close the session. - * - * If an endpoint refuses a stream it must ignore any data frames for that stream. - * - * If an endpoint receives a data frame after the stream is half-closed from the - * sender, it must send a RST_STREAM frame with the getStatus STREAM_ALREADY_CLOSED. - * - * If an endpoint receives a data frame after the stream is closed, it must send - * a RST_STREAM frame with the getStatus PROTOCOL_ERROR. - */ - SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; - int streamId = spdyDataFrame.streamId(); - - int deltaWindowSize = -1 * spdyDataFrame.content().readableBytes(); - int newSessionWindowSize = - spdySession.updateReceiveWindowSize(SPDY_SESSION_STREAM_ID, deltaWindowSize); - - // Check if session window size is reduced beyond allowable lower bound - if (newSessionWindowSize < 0) { - issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); - return; - } - - // Send a WINDOW_UPDATE frame if less than half the session window size remains - if (newSessionWindowSize <= initialSessionReceiveWindowSize / 2) { - int sessionDeltaWindowSize = initialSessionReceiveWindowSize - newSessionWindowSize; - spdySession.updateReceiveWindowSize(SPDY_SESSION_STREAM_ID, sessionDeltaWindowSize); - SpdyWindowUpdateFrame spdyWindowUpdateFrame = - new DefaultSpdyWindowUpdateFrame(SPDY_SESSION_STREAM_ID, sessionDeltaWindowSize); - ctx.writeAndFlush(spdyWindowUpdateFrame); - } - - // Check if we received a data frame for a Stream-ID which is not open - - if (!spdySession.isActiveStream(streamId)) { - spdyDataFrame.release(); - if (streamId <= lastGoodStreamId) { - issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR); - } else if (!sentGoAwayFrame) { - issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM); - } - return; - } - - // Check if we received a data frame for a stream which is half-closed - - if (spdySession.isRemoteSideClosed(streamId)) { - spdyDataFrame.release(); - issueStreamError(ctx, streamId, SpdyStreamStatus.STREAM_ALREADY_CLOSED); - return; - } - - // Check if we received a data frame before receiving a SYN_REPLY - if (!isRemoteInitiatedId(streamId) && !spdySession.hasReceivedReply(streamId)) { - spdyDataFrame.release(); - issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR); - return; - } - - /* - * SPDY Data frame flow control processing requirements: - * - * Recipient should not send a WINDOW_UPDATE frame as it consumes the last data frame. - */ - - // Update receive window size - int newWindowSize = spdySession.updateReceiveWindowSize(streamId, deltaWindowSize); - - // 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. - // 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 - // and is cleared once we send a WINDOW_UPDATE frame. - if (newWindowSize < spdySession.getReceiveWindowSizeLowerBound(streamId)) { - spdyDataFrame.release(); - issueStreamError(ctx, streamId, SpdyStreamStatus.FLOW_CONTROL_ERROR); - return; - } - - // Window size became negative due to sender writing frame before receiving SETTINGS - // Send data frames upstream in initialReceiveWindowSize chunks - if (newWindowSize < 0) { - while (spdyDataFrame.content().readableBytes() > initialReceiveWindowSize) { - SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame( - streamId, spdyDataFrame.content().readRetainedSlice(initialReceiveWindowSize)); - ctx.writeAndFlush(partialDataFrame); - } - } - - // Send a WINDOW_UPDATE frame if less than half the stream window size remains - if (newWindowSize <= initialReceiveWindowSize / 2 && !spdyDataFrame.isLast()) { - int streamDeltaWindowSize = initialReceiveWindowSize - newWindowSize; - spdySession.updateReceiveWindowSize(streamId, streamDeltaWindowSize); - SpdyWindowUpdateFrame spdyWindowUpdateFrame = - new DefaultSpdyWindowUpdateFrame(streamId, streamDeltaWindowSize); - ctx.writeAndFlush(spdyWindowUpdateFrame); - } - - // Close the remote side of the stream if this is the last frame - if (spdyDataFrame.isLast()) { - halfCloseStream(streamId, true, ctx.newSucceededFuture()); - } - - } else if (msg instanceof SpdySynStreamFrame) { - - /* - * SPDY SYN_STREAM frame processing requirements: - * - * If an endpoint receives a SYN_STREAM with a Stream-ID that is less than - * any previously received SYN_STREAM, it must issue a session error with - * the getStatus PROTOCOL_ERROR. - * - * If an endpoint receives multiple SYN_STREAM frames with the same active - * Stream-ID, it must issue a stream error with the getStatus code PROTOCOL_ERROR. - * - * The recipient can reject a stream by sending a stream error with the - * getStatus code REFUSED_STREAM. - */ - - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - int streamId = spdySynStreamFrame.streamId(); - - // Check if we received a valid SYN_STREAM frame - if (spdySynStreamFrame.isInvalid() || - !isRemoteInitiatedId(streamId) || - spdySession.isActiveStream(streamId)) { - issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR); - return; - } - - // Stream-IDs must be monotonically increasing - if (streamId <= lastGoodStreamId) { - issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); - return; - } - - // Try to accept the stream - byte priority = spdySynStreamFrame.priority(); - boolean remoteSideClosed = spdySynStreamFrame.isLast(); - boolean localSideClosed = spdySynStreamFrame.isUnidirectional(); - if (!acceptStream(streamId, priority, remoteSideClosed, localSideClosed)) { - issueStreamError(ctx, streamId, SpdyStreamStatus.REFUSED_STREAM); - return; - } - - } else if (msg instanceof SpdySynReplyFrame) { - - /* - * SPDY SYN_REPLY frame processing requirements: - * - * If an endpoint receives multiple SYN_REPLY frames for the same active Stream-ID - * it must issue a stream error with the getStatus code STREAM_IN_USE. - */ - - SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; - int streamId = spdySynReplyFrame.streamId(); - - // Check if we received a valid SYN_REPLY frame - if (spdySynReplyFrame.isInvalid() || - isRemoteInitiatedId(streamId) || - spdySession.isRemoteSideClosed(streamId)) { - issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM); - return; - } - - // Check if we have received multiple frames for the same Stream-ID - if (spdySession.hasReceivedReply(streamId)) { - issueStreamError(ctx, streamId, SpdyStreamStatus.STREAM_IN_USE); - return; - } - - spdySession.receivedReply(streamId); - - // Close the remote side of the stream if this is the last frame - if (spdySynReplyFrame.isLast()) { - halfCloseStream(streamId, true, ctx.newSucceededFuture()); - } - - } else if (msg instanceof SpdyRstStreamFrame) { - - /* - * SPDY RST_STREAM frame processing requirements: - * - * After receiving a RST_STREAM on a stream, the receiver must not send - * additional frames on that stream. - * - * An endpoint must not send a RST_STREAM in response to a RST_STREAM. - */ - - SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; - removeStream(spdyRstStreamFrame.streamId(), ctx.newSucceededFuture()); - - } else if (msg instanceof SpdySettingsFrame) { - - SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; - - int settingsMinorVersion = spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_MINOR_VERSION); - if (settingsMinorVersion >= 0 && settingsMinorVersion != minorVersion) { - // Settings frame had the wrong minor version - issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); - return; - } - - int newConcurrentStreams = - spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_MAX_CONCURRENT_STREAMS); - if (newConcurrentStreams >= 0) { - remoteConcurrentStreams = newConcurrentStreams; - } - - // Persistence flag are inconsistent with the use of SETTINGS to communicate - // the initial window size. Remove flags from the sender requesting that the - // value be persisted. Remove values that the sender indicates are persisted. - if (spdySettingsFrame.isPersisted(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE)) { - spdySettingsFrame.removeValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE); - } - spdySettingsFrame.setPersistValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE, false); - - int newInitialWindowSize = - spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE); - if (newInitialWindowSize >= 0) { - updateInitialSendWindowSize(newInitialWindowSize); - } - - } else if (msg instanceof SpdyPingFrame) { - - /* - * SPDY PING frame processing requirements: - * - * Receivers of a PING frame should send an identical frame to the sender - * as soon as possible. - * - * Receivers of a PING frame must ignore frames that it did not initiate - */ - - SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; - - if (isRemoteInitiatedId(spdyPingFrame.id())) { - ctx.writeAndFlush(spdyPingFrame); - return; - } - - // Note: only checks that there are outstanding pings since uniqueness is not enforced - if (pings.get() == 0) { - return; - } - pings.getAndDecrement(); - - } else if (msg instanceof SpdyGoAwayFrame) { - - receivedGoAwayFrame = true; - - } else if (msg instanceof SpdyHeadersFrame) { - - SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; - int streamId = spdyHeadersFrame.streamId(); - - // Check if we received a valid HEADERS frame - if (spdyHeadersFrame.isInvalid()) { - issueStreamError(ctx, streamId, SpdyStreamStatus.PROTOCOL_ERROR); - return; - } - - if (spdySession.isRemoteSideClosed(streamId)) { - issueStreamError(ctx, streamId, SpdyStreamStatus.INVALID_STREAM); - return; - } - - // Close the remote side of the stream if this is the last frame - if (spdyHeadersFrame.isLast()) { - halfCloseStream(streamId, true, ctx.newSucceededFuture()); - } - - } else if (msg instanceof SpdyWindowUpdateFrame) { - - /* - * SPDY WINDOW_UPDATE frame processing requirements: - * - * Receivers of a WINDOW_UPDATE that cause the window size to exceed 2^31 - * must send a RST_STREAM with the getStatus code FLOW_CONTROL_ERROR. - * - * Sender should ignore all WINDOW_UPDATE frames associated with a stream - * after sending the last frame for the stream. - */ - - SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg; - int streamId = spdyWindowUpdateFrame.streamId(); - int deltaWindowSize = spdyWindowUpdateFrame.deltaWindowSize(); - - // Ignore frames for half-closed streams - if (streamId != SPDY_SESSION_STREAM_ID && spdySession.isLocalSideClosed(streamId)) { - return; - } - - // Check for numerical overflow - if (spdySession.getSendWindowSize(streamId) > Integer.MAX_VALUE - deltaWindowSize) { - if (streamId == SPDY_SESSION_STREAM_ID) { - issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); - } else { - issueStreamError(ctx, streamId, SpdyStreamStatus.FLOW_CONTROL_ERROR); - } - return; - } - - updateSendWindowSize(ctx, streamId, deltaWindowSize); - } - - ctx.fireChannelRead(msg); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - for (Integer streamId: spdySession.activeStreams().keySet()) { - removeStream(streamId, ctx.newSucceededFuture()); - } - ctx.fireChannelInactive(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (cause instanceof SpdyProtocolException) { - issueSessionError(ctx, SpdySessionStatus.PROTOCOL_ERROR); - } - - ctx.fireExceptionCaught(cause); - } - - @Override - public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - sendGoAwayFrame(ctx, promise); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - if (msg instanceof SpdyDataFrame || - msg instanceof SpdySynStreamFrame || - msg instanceof SpdySynReplyFrame || - msg instanceof SpdyRstStreamFrame || - msg instanceof SpdySettingsFrame || - msg instanceof SpdyPingFrame || - msg instanceof SpdyGoAwayFrame || - msg instanceof SpdyHeadersFrame || - msg instanceof SpdyWindowUpdateFrame) { - - handleOutboundMessage(ctx, msg, promise); - } else { - ctx.write(msg, promise); - } - } - - private void handleOutboundMessage(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - if (msg instanceof SpdyDataFrame) { - - SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; - int streamId = spdyDataFrame.streamId(); - - // Frames must not be sent on half-closed streams - if (spdySession.isLocalSideClosed(streamId)) { - spdyDataFrame.release(); - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - /* - * SPDY Data frame flow control processing requirements: - * - * Sender must not send a data frame with data length greater - * than the transfer window size. - * - * After sending each data frame, the sender decrements its - * transfer window size by the amount of data transmitted. - * - * When the window size becomes less than or equal to 0, the - * sender must pause transmitting data frames. - */ - - int dataLength = spdyDataFrame.content().readableBytes(); - int sendWindowSize = spdySession.getSendWindowSize(streamId); - int sessionSendWindowSize = spdySession.getSendWindowSize(SPDY_SESSION_STREAM_ID); - sendWindowSize = Math.min(sendWindowSize, sessionSendWindowSize); - - if (sendWindowSize <= 0) { - // Stream is stalled -- enqueue Data frame and return - spdySession.putPendingWrite(streamId, new SpdySession.PendingWrite(spdyDataFrame, promise)); - return; - } else if (sendWindowSize < dataLength) { - // Stream is not stalled but we cannot send the entire frame - spdySession.updateSendWindowSize(streamId, -1 * sendWindowSize); - spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * sendWindowSize); - - // Create a partial data frame whose length is the current window size - SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame( - streamId, spdyDataFrame.content().readRetainedSlice(sendWindowSize)); - - // Enqueue the remaining data (will be the first frame queued) - spdySession.putPendingWrite(streamId, new SpdySession.PendingWrite(spdyDataFrame, promise)); - - // The transfer window size is pre-decremented when sending a data frame downstream. - // Close the session on write failures that leave the transfer window in a corrupt state. - final ChannelHandlerContext context = ctx; - ctx.write(partialDataFrame).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR); - } - }); - return; - } else { - // Window size is large enough to send entire data frame - spdySession.updateSendWindowSize(streamId, -1 * dataLength); - spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * dataLength); - - // The transfer window size is pre-decremented when sending a data frame downstream. - // Close the session on write failures that leave the transfer window in a corrupt state. - final ChannelHandlerContext context = ctx; - promise.addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - issueSessionError(context, SpdySessionStatus.INTERNAL_ERROR); - } - }); - } - - // Close the local side of the stream if this is the last frame - if (spdyDataFrame.isLast()) { - halfCloseStream(streamId, false, promise); - } - - } else if (msg instanceof SpdySynStreamFrame) { - - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - int streamId = spdySynStreamFrame.streamId(); - - if (isRemoteInitiatedId(streamId)) { - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - byte priority = spdySynStreamFrame.priority(); - boolean remoteSideClosed = spdySynStreamFrame.isUnidirectional(); - boolean localSideClosed = spdySynStreamFrame.isLast(); - if (!acceptStream(streamId, priority, remoteSideClosed, localSideClosed)) { - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - } else if (msg instanceof SpdySynReplyFrame) { - - SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; - int streamId = spdySynReplyFrame.streamId(); - - // Frames must not be sent on half-closed streams - if (!isRemoteInitiatedId(streamId) || spdySession.isLocalSideClosed(streamId)) { - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - // Close the local side of the stream if this is the last frame - if (spdySynReplyFrame.isLast()) { - halfCloseStream(streamId, false, promise); - } - - } else if (msg instanceof SpdyRstStreamFrame) { - - SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; - removeStream(spdyRstStreamFrame.streamId(), promise); - - } else if (msg instanceof SpdySettingsFrame) { - - SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; - - int settingsMinorVersion = spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_MINOR_VERSION); - if (settingsMinorVersion >= 0 && settingsMinorVersion != minorVersion) { - // Settings frame had the wrong minor version - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - int newConcurrentStreams = - spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_MAX_CONCURRENT_STREAMS); - if (newConcurrentStreams >= 0) { - localConcurrentStreams = newConcurrentStreams; - } - - // Persistence flag are inconsistent with the use of SETTINGS to communicate - // the initial window size. Remove flags from the sender requesting that the - // value be persisted. Remove values that the sender indicates are persisted. - if (spdySettingsFrame.isPersisted(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE)) { - spdySettingsFrame.removeValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE); - } - spdySettingsFrame.setPersistValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE, false); - - int newInitialWindowSize = - spdySettingsFrame.getValue(SpdySettingsFrame.SETTINGS_INITIAL_WINDOW_SIZE); - if (newInitialWindowSize >= 0) { - updateInitialReceiveWindowSize(newInitialWindowSize); - } - - } else if (msg instanceof SpdyPingFrame) { - - SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; - if (isRemoteInitiatedId(spdyPingFrame.id())) { - ctx.fireExceptionCaught(new IllegalArgumentException( - "invalid PING ID: " + spdyPingFrame.id())); - return; - } - pings.getAndIncrement(); - - } else if (msg instanceof SpdyGoAwayFrame) { - - // Why is this being sent? Intercept it and fail the write. - // Should have sent a CLOSE ChannelStateEvent - promise.setFailure(PROTOCOL_EXCEPTION); - return; - - } else if (msg instanceof SpdyHeadersFrame) { - - SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; - int streamId = spdyHeadersFrame.streamId(); - - // Frames must not be sent on half-closed streams - if (spdySession.isLocalSideClosed(streamId)) { - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - // Close the local side of the stream if this is the last frame - if (spdyHeadersFrame.isLast()) { - halfCloseStream(streamId, false, promise); - } - - } else if (msg instanceof SpdyWindowUpdateFrame) { - - // Why is this being sent? Intercept it and fail the write. - promise.setFailure(PROTOCOL_EXCEPTION); - return; - } - - ctx.write(msg, promise); - } - - /* - * SPDY Session Error Handling: - * - * When a session error occurs, the endpoint encountering the error must first - * send a GOAWAY frame with the Stream-ID of the most recently received stream - * from the remote endpoint, and the error code for why the session is terminating. - * - * After sending the GOAWAY frame, the endpoint must close the TCP connection. - */ - private void issueSessionError( - ChannelHandlerContext ctx, SpdySessionStatus status) { - - sendGoAwayFrame(ctx, status).addListener(new ClosingChannelFutureListener(ctx, ctx.newPromise())); - } - - /* - * SPDY Stream Error Handling: - * - * Upon a stream error, the endpoint must send a RST_STREAM frame which contains - * the Stream-ID for the stream where the error occurred and the error getStatus which - * caused the error. - * - * After sending the RST_STREAM, the stream is closed to the sending endpoint. - * - * Note: this is only called by the worker thread - */ - private void issueStreamError(ChannelHandlerContext ctx, int streamId, SpdyStreamStatus status) { - boolean fireChannelRead = !spdySession.isRemoteSideClosed(streamId); - ChannelPromise promise = ctx.newPromise(); - removeStream(streamId, promise); - - SpdyRstStreamFrame spdyRstStreamFrame = new DefaultSpdyRstStreamFrame(streamId, status); - ctx.writeAndFlush(spdyRstStreamFrame, promise); - if (fireChannelRead) { - ctx.fireChannelRead(spdyRstStreamFrame); - } - } - - /* - * Helper functions - */ - - private boolean isRemoteInitiatedId(int id) { - boolean serverId = isServerId(id); - return server && !serverId || !server && serverId; - } - - // need to synchronize to prevent new streams from being created while updating active streams - private void updateInitialSendWindowSize(int newInitialWindowSize) { - int deltaWindowSize = newInitialWindowSize - initialSendWindowSize; - initialSendWindowSize = newInitialWindowSize; - spdySession.updateAllSendWindowSizes(deltaWindowSize); - } - - // need to synchronize to prevent new streams from being created while updating active streams - private void updateInitialReceiveWindowSize(int newInitialWindowSize) { - int deltaWindowSize = newInitialWindowSize - initialReceiveWindowSize; - initialReceiveWindowSize = newInitialWindowSize; - spdySession.updateAllReceiveWindowSizes(deltaWindowSize); - } - - // need to synchronize accesses to sentGoAwayFrame, lastGoodStreamId, and initial window sizes - private boolean acceptStream( - int streamId, byte priority, boolean remoteSideClosed, boolean localSideClosed) { - // Cannot initiate any new streams after receiving or sending GOAWAY - if (receivedGoAwayFrame || sentGoAwayFrame) { - return false; - } - - boolean remote = isRemoteInitiatedId(streamId); - int maxConcurrentStreams = remote ? localConcurrentStreams : remoteConcurrentStreams; - if (spdySession.numActiveStreams(remote) >= maxConcurrentStreams) { - return false; - } - spdySession.acceptStream( - streamId, priority, remoteSideClosed, localSideClosed, - initialSendWindowSize, initialReceiveWindowSize, remote); - if (remote) { - lastGoodStreamId = streamId; - } - return true; - } - - private void halfCloseStream(int streamId, boolean remote, ChannelFuture future) { - if (remote) { - spdySession.closeRemoteSide(streamId, isRemoteInitiatedId(streamId)); - } else { - spdySession.closeLocalSide(streamId, isRemoteInitiatedId(streamId)); - } - if (closeSessionFutureListener != null && spdySession.noActiveStreams()) { - future.addListener(closeSessionFutureListener); - } - } - - private void removeStream(int streamId, ChannelFuture future) { - spdySession.removeStream(streamId, STREAM_CLOSED, isRemoteInitiatedId(streamId)); - - if (closeSessionFutureListener != null && spdySession.noActiveStreams()) { - future.addListener(closeSessionFutureListener); - } - } - - private void updateSendWindowSize(final ChannelHandlerContext ctx, int streamId, int deltaWindowSize) { - spdySession.updateSendWindowSize(streamId, deltaWindowSize); - - while (true) { - // Check if we have unblocked a stalled stream - SpdySession.PendingWrite pendingWrite = spdySession.getPendingWrite(streamId); - if (pendingWrite == null) { - return; - } - - SpdyDataFrame spdyDataFrame = pendingWrite.spdyDataFrame; - int dataFrameSize = spdyDataFrame.content().readableBytes(); - int writeStreamId = spdyDataFrame.streamId(); - int sendWindowSize = spdySession.getSendWindowSize(writeStreamId); - int sessionSendWindowSize = spdySession.getSendWindowSize(SPDY_SESSION_STREAM_ID); - sendWindowSize = Math.min(sendWindowSize, sessionSendWindowSize); - - if (sendWindowSize <= 0) { - return; - } else if (sendWindowSize < dataFrameSize) { - // We can send a partial frame - spdySession.updateSendWindowSize(writeStreamId, -1 * sendWindowSize); - spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * sendWindowSize); - - // Create a partial data frame whose length is the current window size - SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame( - writeStreamId, spdyDataFrame.content().readRetainedSlice(sendWindowSize)); - - // The transfer window size is pre-decremented when sending a data frame downstream. - // Close the session on write failures that leave the transfer window in a corrupt state. - ctx.writeAndFlush(partialDataFrame).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR); - } - }); - } else { - // Window size is large enough to send entire data frame - spdySession.removePendingWrite(writeStreamId); - spdySession.updateSendWindowSize(writeStreamId, -1 * dataFrameSize); - spdySession.updateSendWindowSize(SPDY_SESSION_STREAM_ID, -1 * dataFrameSize); - - // Close the local side of the stream if this is the last frame - if (spdyDataFrame.isLast()) { - halfCloseStream(writeStreamId, false, pendingWrite.promise); - } - - // The transfer window size is pre-decremented when sending a data frame downstream. - // Close the session on write failures that leave the transfer window in a corrupt state. - ctx.writeAndFlush(spdyDataFrame, pendingWrite.promise).addListener((ChannelFutureListener) future -> { - if (!future.isSuccess()) { - issueSessionError(ctx, SpdySessionStatus.INTERNAL_ERROR); - } - }); - } - } - } - - private void sendGoAwayFrame(ChannelHandlerContext ctx, ChannelPromise future) { - // Avoid NotYetConnectedException - if (!ctx.channel().isActive()) { - ctx.close(future); - return; - } - - ChannelFuture f = sendGoAwayFrame(ctx, SpdySessionStatus.OK); - if (spdySession.noActiveStreams()) { - f.addListener(new ClosingChannelFutureListener(ctx, future)); - } else { - closeSessionFutureListener = new ClosingChannelFutureListener(ctx, future); - } - // FIXME: Close the connection forcibly after timeout. - } - - private ChannelFuture sendGoAwayFrame( - ChannelHandlerContext ctx, SpdySessionStatus status) { - if (!sentGoAwayFrame) { - sentGoAwayFrame = true; - SpdyGoAwayFrame spdyGoAwayFrame = new DefaultSpdyGoAwayFrame(lastGoodStreamId, status); - return ctx.writeAndFlush(spdyGoAwayFrame); - } else { - return ctx.newSucceededFuture(); - } - } - - private static final class ClosingChannelFutureListener implements ChannelFutureListener { - private final ChannelHandlerContext ctx; - private final ChannelPromise promise; - - ClosingChannelFutureListener(ChannelHandlerContext ctx, ChannelPromise promise) { - this.ctx = ctx; - this.promise = promise; - } - - @Override - public void operationComplete(ChannelFuture sentGoAwayFuture) throws Exception { - ctx.close(promise); - } - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionStatus.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionStatus.java deleted file mode 100644 index fd79d1ed12..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionStatus.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 SPDY session status code and its description. - */ -public class SpdySessionStatus implements Comparable { - - /** - * 0 OK - */ - public static final SpdySessionStatus OK = - new SpdySessionStatus(0, "OK"); - - /** - * 1 Protocol Error - */ - public static final SpdySessionStatus PROTOCOL_ERROR = - new SpdySessionStatus(1, "PROTOCOL_ERROR"); - - /** - * 2 Internal Error - */ - public static final SpdySessionStatus INTERNAL_ERROR = - new SpdySessionStatus(2, "INTERNAL_ERROR"); - - /** - * Returns the {@link SpdySessionStatus} represented by the specified code. - * If the specified code is a defined SPDY status code, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static SpdySessionStatus valueOf(int code) { - switch (code) { - case 0: - return OK; - case 1: - return PROTOCOL_ERROR; - case 2: - return INTERNAL_ERROR; - } - - return new SpdySessionStatus(code, "UNKNOWN (" + code + ')'); - } - - private final int code; - - private final String statusPhrase; - - /** - * Creates a new instance with the specified {@code code} and its - * {@code statusPhrase}. - */ - public SpdySessionStatus(int code, String statusPhrase) { - if (statusPhrase == null) { - throw new NullPointerException("statusPhrase"); - } - - this.code = code; - this.statusPhrase = statusPhrase; - } - - /** - * Returns the code of this status. - */ - public int code() { - return code; - } - - /** - * Returns the status phrase of this status. - */ - public String statusPhrase() { - return statusPhrase; - } - - @Override - public int hashCode() { - return code(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SpdySessionStatus)) { - return false; - } - - return code() == ((SpdySessionStatus) o).code(); - } - - @Override - public String toString() { - return statusPhrase(); - } - - @Override - public int compareTo(SpdySessionStatus o) { - return code() - o.code(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySettingsFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySettingsFrame.java deleted file mode 100644 index e24f41a020..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySettingsFrame.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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; - -import java.util.Set; - -/** - * A SPDY Protocol SETTINGS Frame - */ -public interface SpdySettingsFrame extends SpdyFrame { - - int SETTINGS_MINOR_VERSION = 0; - int SETTINGS_UPLOAD_BANDWIDTH = 1; - int SETTINGS_DOWNLOAD_BANDWIDTH = 2; - int SETTINGS_ROUND_TRIP_TIME = 3; - int SETTINGS_MAX_CONCURRENT_STREAMS = 4; - int SETTINGS_CURRENT_CWND = 5; - int SETTINGS_DOWNLOAD_RETRANS_RATE = 6; - int SETTINGS_INITIAL_WINDOW_SIZE = 7; - int SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8; - - /** - * Returns a {@code Set} of the setting IDs. - * The set's iterator will return the IDs in ascending order. - */ - Set ids(); - - /** - * Returns {@code true} if the setting ID has a value. - */ - boolean isSet(int id); - - /** - * Returns the value of the setting ID. - * Returns -1 if the setting ID is not set. - */ - int getValue(int id); - - /** - * Sets the value of the setting ID. - * The ID cannot be negative and cannot exceed 16777215. - */ - SpdySettingsFrame setValue(int id, int value); - - /** - * Sets the value of the setting ID. - * Sets if the setting should be persisted (should only be set by the server). - * Sets if the setting is persisted (should only be set by the client). - * The ID cannot be negative and cannot exceed 16777215. - */ - SpdySettingsFrame setValue(int id, int value, boolean persistVal, boolean persisted); - - /** - * Removes the value of the setting ID. - * Removes all persistence information for the setting. - */ - SpdySettingsFrame removeValue(int id); - - /** - * Returns {@code true} if this setting should be persisted. - * Returns {@code false} if this setting should not be persisted - * or if the setting ID has no value. - */ - boolean isPersistValue(int id); - - /** - * Sets if this setting should be persisted. - * Has no effect if the setting ID has no value. - */ - SpdySettingsFrame setPersistValue(int id, boolean persistValue); - - /** - * Returns {@code true} if this setting is persisted. - * Returns {@code false} if this setting should not be persisted - * or if the setting ID has no value. - */ - boolean isPersisted(int id); - - /** - * Sets if this setting is persisted. - * Has no effect if the setting ID has no value. - */ - SpdySettingsFrame setPersisted(int id, boolean persisted); - - /** - * Returns {@code true} if previously persisted settings should be cleared. - */ - boolean clearPreviouslyPersistedSettings(); - - /** - * Sets if previously persisted settings should be cleared. - */ - SpdySettingsFrame setClearPreviouslyPersistedSettings(boolean clear); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamFrame.java deleted file mode 100644 index 09c9f2a179..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamFrame.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol Frame that is associated with an individual SPDY Stream - */ -public interface SpdyStreamFrame extends SpdyFrame { - - /** - * Returns the Stream-ID of this frame. - */ - int streamId(); - - /** - * Sets the Stream-ID of this frame. The Stream-ID must be positive. - */ - SpdyStreamFrame setStreamId(int streamID); - - /** - * Returns {@code true} if this frame is the last frame to be transmitted - * on the stream. - */ - boolean isLast(); - - /** - * Sets if this frame is the last frame to be transmitted on the stream. - */ - SpdyStreamFrame setLast(boolean last); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamStatus.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamStatus.java deleted file mode 100644 index 75ed740a2a..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyStreamStatus.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 SPDY stream status code and its description. - */ -public class SpdyStreamStatus implements Comparable { - - /** - * 1 Protocol Error - */ - public static final SpdyStreamStatus PROTOCOL_ERROR = - new SpdyStreamStatus(1, "PROTOCOL_ERROR"); - - /** - * 2 Invalid Stream - */ - public static final SpdyStreamStatus INVALID_STREAM = - new SpdyStreamStatus(2, "INVALID_STREAM"); - - /** - * 3 Refused Stream - */ - public static final SpdyStreamStatus REFUSED_STREAM = - new SpdyStreamStatus(3, "REFUSED_STREAM"); - - /** - * 4 Unsupported Version - */ - public static final SpdyStreamStatus UNSUPPORTED_VERSION = - new SpdyStreamStatus(4, "UNSUPPORTED_VERSION"); - - /** - * 5 Cancel - */ - public static final SpdyStreamStatus CANCEL = - new SpdyStreamStatus(5, "CANCEL"); - - /** - * 6 Internal Error - */ - public static final SpdyStreamStatus INTERNAL_ERROR = - new SpdyStreamStatus(6, "INTERNAL_ERROR"); - - /** - * 7 Flow Control Error - */ - public static final SpdyStreamStatus FLOW_CONTROL_ERROR = - new SpdyStreamStatus(7, "FLOW_CONTROL_ERROR"); - - /** - * 8 Stream In Use - */ - public static final SpdyStreamStatus STREAM_IN_USE = - new SpdyStreamStatus(8, "STREAM_IN_USE"); - - /** - * 9 Stream Already Closed - */ - public static final SpdyStreamStatus STREAM_ALREADY_CLOSED = - new SpdyStreamStatus(9, "STREAM_ALREADY_CLOSED"); - - /** - * 10 Invalid Credentials - */ - public static final SpdyStreamStatus INVALID_CREDENTIALS = - new SpdyStreamStatus(10, "INVALID_CREDENTIALS"); - - /** - * 11 Frame Too Large - */ - public static final SpdyStreamStatus FRAME_TOO_LARGE = - new SpdyStreamStatus(11, "FRAME_TOO_LARGE"); - - /** - * Returns the {@link SpdyStreamStatus} represented by the specified code. - * If the specified code is a defined SPDY status code, a cached instance - * will be returned. Otherwise, a new instance will be returned. - */ - public static SpdyStreamStatus valueOf(int code) { - if (code == 0) { - throw new IllegalArgumentException( - "0 is not a valid status code for a RST_STREAM"); - } - - switch (code) { - case 1: - return PROTOCOL_ERROR; - case 2: - return INVALID_STREAM; - case 3: - return REFUSED_STREAM; - case 4: - return UNSUPPORTED_VERSION; - case 5: - return CANCEL; - case 6: - return INTERNAL_ERROR; - case 7: - return FLOW_CONTROL_ERROR; - case 8: - return STREAM_IN_USE; - case 9: - return STREAM_ALREADY_CLOSED; - case 10: - return INVALID_CREDENTIALS; - case 11: - return FRAME_TOO_LARGE; - } - - return new SpdyStreamStatus(code, "UNKNOWN (" + code + ')'); - } - - private final int code; - - private final String statusPhrase; - - /** - * Creates a new instance with the specified {@code code} and its - * {@code statusPhrase}. - */ - public SpdyStreamStatus(int code, String statusPhrase) { - if (code == 0) { - throw new IllegalArgumentException( - "0 is not a valid status code for a RST_STREAM"); - } - - if (statusPhrase == null) { - throw new NullPointerException("statusPhrase"); - } - - this.code = code; - this.statusPhrase = statusPhrase; - } - - /** - * Returns the code of this status. - */ - public int code() { - return code; - } - - /** - * Returns the status phrase of this status. - */ - public String statusPhrase() { - return statusPhrase; - } - - @Override - public int hashCode() { - return code(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SpdyStreamStatus)) { - return false; - } - - return code() == ((SpdyStreamStatus) o).code(); - } - - @Override - public String toString() { - return statusPhrase(); - } - - @Override - public int compareTo(SpdyStreamStatus o) { - return code() - o.code(); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynReplyFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynReplyFrame.java deleted file mode 100644 index 4bce003620..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynReplyFrame.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol SYN_REPLY Frame - */ -public interface SpdySynReplyFrame extends SpdyHeadersFrame { - - @Override - SpdySynReplyFrame setStreamId(int streamID); - - @Override - SpdySynReplyFrame setLast(boolean last); - - @Override - SpdySynReplyFrame setInvalid(); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynStreamFrame.java deleted file mode 100644 index f2efb8cabe..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySynStreamFrame.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol SYN_STREAM Frame - */ -public interface SpdySynStreamFrame extends SpdyHeadersFrame { - - /** - * Returns the Associated-To-Stream-ID of this frame. - */ - int associatedStreamId(); - - /** - * Sets the Associated-To-Stream-ID of this frame. - * The Associated-To-Stream-ID cannot be negative. - */ - SpdySynStreamFrame setAssociatedStreamId(int associatedStreamId); - - /** - * Returns the priority of the stream. - */ - byte priority(); - - /** - * Sets the priority of the stream. - * The priority must be between 0 and 7 inclusive. - */ - SpdySynStreamFrame setPriority(byte priority); - - /** - * Returns {@code true} if the stream created with this frame is to be - * considered half-closed to the receiver. - */ - boolean isUnidirectional(); - - /** - * Sets if the stream created with this frame is to be considered - * half-closed to the receiver. - */ - SpdySynStreamFrame setUnidirectional(boolean unidirectional); - - @Override - SpdySynStreamFrame setStreamId(int streamID); - - @Override - SpdySynStreamFrame setLast(boolean last); - - @Override - SpdySynStreamFrame setInvalid(); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyVersion.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyVersion.java deleted file mode 100644 index 030ee94ec1..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyVersion.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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; - -public enum SpdyVersion { - SPDY_3_1 (3, 1); - - private final int version; - private final int minorVersion; - - SpdyVersion(int version, int minorVersion) { - this.version = version; - this.minorVersion = minorVersion; - } - - int getVersion() { - return version; - } - - int getMinorVersion() { - return minorVersion; - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyWindowUpdateFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyWindowUpdateFrame.java deleted file mode 100644 index bbd8730bd0..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyWindowUpdateFrame.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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; - -/** - * A SPDY Protocol WINDOW_UPDATE Frame - */ -public interface SpdyWindowUpdateFrame extends SpdyFrame { - - /** - * Returns the Stream-ID of this frame. - */ - int streamId(); - - /** - * Sets the Stream-ID of this frame. The Stream-ID cannot be negative. - */ - SpdyWindowUpdateFrame setStreamId(int streamID); - - /** - * Returns the Delta-Window-Size of this frame. - */ - int deltaWindowSize(); - - /** - * Sets the Delta-Window-Size of this frame. - * The Delta-Window-Size must be positive. - */ - SpdyWindowUpdateFrame setDeltaWindowSize(int deltaWindowSize); -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/package-info.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/package-info.java deleted file mode 100644 index 30b4299d5d..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/package-info.java +++ /dev/null @@ -1,19 +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. - */ -/** - * Encoder, decoder, session handler and their related message types for the SPDY protocol. - */ -package io.netty.handler.codec.spdy; diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersTest.java deleted file mode 100644 index c78fe5b8f9..0000000000 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/DefaultSpdyHeadersTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015 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 org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class DefaultSpdyHeadersTest { - - @Test - public void testStringKeyRetrievedAsAsciiString() { - final SpdyHeaders headers = new DefaultSpdyHeaders(); - - // Test adding String key and retrieving it using a AsciiString key - final String method = "GET"; - headers.add(":method", method); - - final String value = headers.getAsString(SpdyHeaders.HttpNames.METHOD.toString()); - assertNotNull(value); - assertEquals(method, value); - - final String value2 = headers.getAsString(SpdyHeaders.HttpNames.METHOD); - assertNotNull(value2); - assertEquals(method, value2); - } - - @Test - public void testAsciiStringKeyRetrievedAsString() { - final SpdyHeaders headers = new DefaultSpdyHeaders(); - - // Test adding AsciiString key and retrieving it using a String key - final String path = "/"; - headers.add(SpdyHeaders.HttpNames.PATH, path); - - final String value = headers.getAsString(SpdyHeaders.HttpNames.PATH); - assertNotNull(value); - assertEquals(path, value); - - final String value2 = headers.getAsString(SpdyHeaders.HttpNames.PATH.toString()); - assertNotNull(value2); - assertEquals(path, value2); - } -} diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyFrameDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyFrameDecoderTest.java deleted file mode 100644 index 964ec15254..0000000000 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyFrameDecoderTest.java +++ /dev/null @@ -1,1324 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.Random; - -import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_SIZE; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -public class SpdyFrameDecoderTest { - - private static final Random RANDOM = new Random(); - - private final SpdyFrameDecoderDelegate delegate = mock(SpdyFrameDecoderDelegate.class); - private final TestSpdyFrameDecoderDelegate testDelegate = new TestSpdyFrameDecoderDelegate(); - private SpdyFrameDecoder decoder; - - @Before - public void createDecoder() { - decoder = new SpdyFrameDecoder(SpdyVersion.SPDY_3_1, testDelegate); - } - - @After - public void releaseBuffers() { - testDelegate.releaseAll(); - } - - private final class TestSpdyFrameDecoderDelegate implements SpdyFrameDecoderDelegate { - private final Queue buffers = new ArrayDeque<>(); - - @Override - public void readDataFrame(int streamId, boolean last, ByteBuf data) { - delegate.readDataFrame(streamId, last, data); - buffers.add(data); - } - - @Override - public void readSynStreamFrame(int streamId, int associatedToStreamId, - byte priority, boolean last, boolean unidirectional) { - delegate.readSynStreamFrame(streamId, associatedToStreamId, priority, last, unidirectional); - } - - @Override - public void readSynReplyFrame(int streamId, boolean last) { - delegate.readSynReplyFrame(streamId, last); - } - - @Override - public void readRstStreamFrame(int streamId, int statusCode) { - delegate.readRstStreamFrame(streamId, statusCode); - } - - @Override - public void readSettingsFrame(boolean clearPersisted) { - delegate.readSettingsFrame(clearPersisted); - } - - @Override - public void readSetting(int id, int value, boolean persistValue, boolean persisted) { - delegate.readSetting(id, value, persistValue, persisted); - } - - @Override - public void readSettingsEnd() { - delegate.readSettingsEnd(); - } - - @Override - public void readPingFrame(int id) { - delegate.readPingFrame(id); - } - - @Override - public void readGoAwayFrame(int lastGoodStreamId, int statusCode) { - delegate.readGoAwayFrame(lastGoodStreamId, statusCode); - } - - @Override - public void readHeadersFrame(int streamId, boolean last) { - delegate.readHeadersFrame(streamId, last); - } - - @Override - public void readWindowUpdateFrame(int streamId, int deltaWindowSize) { - delegate.readWindowUpdateFrame(streamId, deltaWindowSize); - } - - @Override - public void readHeaderBlock(ByteBuf headerBlock) { - delegate.readHeaderBlock(headerBlock); - buffers.add(headerBlock); - } - - @Override - public void readHeaderBlockEnd() { - delegate.readHeaderBlockEnd(); - } - - @Override - public void readFrameError(String message) { - delegate.readFrameError(message); - } - - void releaseAll() { - for (;;) { - ByteBuf buf = buffers.poll(); - if (buf == null) { - return; - } - buf.release(); - } - } - } - - private static void encodeDataFrameHeader(ByteBuf buffer, int streamId, byte flags, int length) { - buffer.writeInt(streamId & 0x7FFFFFFF); - buffer.writeByte(flags); - buffer.writeMedium(length); - } - - private static void encodeControlFrameHeader(ByteBuf buffer, short type, byte flags, int length) { - buffer.writeShort(0x8000 | SpdyVersion.SPDY_3_1.getVersion()); - buffer.writeShort(type); - buffer.writeByte(flags); - buffer.writeMedium(length); - } - - @Test - public void testSpdyDataFrame() throws Exception { - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - byte flags = 0; - int length = 1024; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeDataFrameHeader(buf, streamId, flags, length); - for (int i = 0; i < 256; i ++) { - buf.writeInt(RANDOM.nextInt()); - } - decoder.decode(buf); - verify(delegate).readDataFrame(streamId, false, buf.slice(SPDY_HEADER_SIZE, length)); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testEmptySpdyDataFrame() throws Exception { - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - byte flags = 0; - int length = 0; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeDataFrameHeader(buf, streamId, flags, length); - - decoder.decode(buf); - verify(delegate).readDataFrame(streamId, false, Unpooled.EMPTY_BUFFER); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testLastSpdyDataFrame() throws Exception { - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - byte flags = 0x01; // FLAG_FIN - int length = 0; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeDataFrameHeader(buf, streamId, flags, length); - - decoder.decode(buf); - verify(delegate).readDataFrame(streamId, true, Unpooled.EMPTY_BUFFER); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdyDataFrameFlags() throws Exception { - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - byte flags = (byte) 0xFE; // should ignore any unknown flags - int length = 0; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeDataFrameHeader(buf, streamId, flags, length); - - decoder.decode(buf); - verify(delegate).readDataFrame(streamId, false, Unpooled.EMPTY_BUFFER); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdyDataFrameStreamId() throws Exception { - int streamId = 0; // illegal stream identifier - byte flags = 0; - int length = 0; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeDataFrameHeader(buf, streamId, flags, length); - - decoder.decode(buf); - verify(delegate).readFrameError((String) any()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testPipelinedSpdyDataFrames() throws Exception { - int streamId1 = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int streamId2 = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - byte flags = 0; - int length = 0; - - ByteBuf buf = Unpooled.buffer(2 * (SPDY_HEADER_SIZE + length)); - encodeDataFrameHeader(buf, streamId1, flags, length); - encodeDataFrameHeader(buf, streamId2, flags, length); - - decoder.decode(buf); - verify(delegate).readDataFrame(streamId1, false, Unpooled.EMPTY_BUFFER); - verify(delegate).readDataFrame(streamId2, false, Unpooled.EMPTY_BUFFER); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySynStreamFrame() throws Exception { - short type = 1; - byte flags = 0; - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testLastSpdySynStreamFrame() throws Exception { - short type = 1; - byte flags = 0x01; // FLAG_FIN - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, true, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnidirectionalSpdySynStreamFrame() throws Exception { - short type = 1; - byte flags = 0x02; // FLAG_UNIDIRECTIONAL - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, true); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIndependentSpdySynStreamFrame() throws Exception { - short type = 1; - byte flags = 0; - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = 0; // independent of all other streams - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdySynStreamFrameFlags() throws Exception { - short type = 1; - byte flags = (byte) 0xFC; // undefined flags - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdySynStreamFrameBits() throws Exception { - short type = 1; - byte flags = 0; - int length = 10; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId | 0x80000000); // should ignore reserved bit - buf.writeInt(associatedToStreamId | 0x80000000); // should ignore reserved bit - buf.writeByte(priority << 5 | 0x1F); // should ignore reserved bits - buf.writeByte(0xFF); // should ignore reserved bits - - decoder.decode(buf); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdySynStreamFrameLength() throws Exception { - short type = 1; - byte flags = 0; - int length = 8; // invalid length - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdySynStreamFrameStreamId() throws Exception { - short type = 1; - byte flags = 0; - int length = 10; - int streamId = 0; // invalid stream identifier - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySynStreamFrameHeaderBlock() throws Exception { - short type = 1; - byte flags = 0; - int length = 10; - int headerBlockLength = 1024; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int associatedToStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - byte priority = (byte) (RANDOM.nextInt() & 0x07); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length + headerBlockLength); - encodeControlFrameHeader(buf, type, flags, length + headerBlockLength); - buf.writeInt(streamId); - buf.writeInt(associatedToStreamId); - buf.writeByte(priority << 5); - buf.writeByte(0); - - ByteBuf headerBlock = Unpooled.buffer(headerBlockLength); - for (int i = 0; i < 256; i ++) { - headerBlock.writeInt(RANDOM.nextInt()); - } - - decoder.decode(buf); - decoder.decode(headerBlock); - verify(delegate).readSynStreamFrame(streamId, associatedToStreamId, priority, false, false); - verify(delegate).readHeaderBlock(headerBlock.slice(0, headerBlock.writerIndex())); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - assertFalse(headerBlock.isReadable()); - buf.release(); - headerBlock.release(); - } - - @Test - public void testSpdySynReplyFrame() throws Exception { - short type = 2; - byte flags = 0; - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readSynReplyFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testLastSpdySynReplyFrame() throws Exception { - short type = 2; - byte flags = 0x01; // FLAG_FIN - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readSynReplyFrame(streamId, true); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdySynReplyFrameFlags() throws Exception { - short type = 2; - byte flags = (byte) 0xFE; // undefined flags - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readSynReplyFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdySynReplyFrameBits() throws Exception { - short type = 2; - byte flags = 0; - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId | 0x80000000); // should ignore reserved bit - - decoder.decode(buf); - verify(delegate).readSynReplyFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdySynReplyFrameLength() throws Exception { - short type = 2; - byte flags = 0; - int length = 0; // invalid length - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdySynReplyFrameStreamId() throws Exception { - short type = 2; - byte flags = 0; - int length = 4; - int streamId = 0; // invalid stream identifier - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySynReplyFrameHeaderBlock() throws Exception { - short type = 2; - byte flags = 0; - int length = 4; - int headerBlockLength = 1024; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length + headerBlockLength); - encodeControlFrameHeader(buf, type, flags, length + headerBlockLength); - buf.writeInt(streamId); - - ByteBuf headerBlock = Unpooled.buffer(headerBlockLength); - for (int i = 0; i < 256; i ++) { - headerBlock.writeInt(RANDOM.nextInt()); - } - - decoder.decode(buf); - decoder.decode(headerBlock); - verify(delegate).readSynReplyFrame(streamId, false); - verify(delegate).readHeaderBlock(headerBlock.slice(0, headerBlock.writerIndex())); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - assertFalse(headerBlock.isReadable()); - buf.release(); - headerBlock.release(); - } - - @Test - public void testSpdyRstStreamFrame() throws Exception { - short type = 3; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readRstStreamFrame(streamId, statusCode); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdyRstStreamFrameBits() throws Exception { - short type = 3; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId | 0x80000000); // should ignore reserved bit - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readRstStreamFrame(streamId, statusCode); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyRstStreamFrameFlags() throws Exception { - short type = 3; - byte flags = (byte) 0xFF; // invalid flags - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyRstStreamFrameLength() throws Exception { - short type = 3; - byte flags = 0; - int length = 12; // invalid length - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdyRstStreamFrameStreamId() throws Exception { - short type = 3; - byte flags = 0; - int length = 8; - int streamId = 0; // invalid stream identifier - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdyRstStreamFrameStatusCode() throws Exception { - short type = 3; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - int statusCode = 0; // invalid status code - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySettingsFrame() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 2; - int length = 8 * numSettings + 4; - byte idFlags = 0; - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - delegate.readSettingsEnd(); - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate, times(numSettings)).readSetting(id, value, false, false); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testEmptySpdySettingsFrame() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 0; - int length = 8 * numSettings + 4; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate).readSettingsEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySettingsFrameClearFlag() throws Exception { - short type = 4; - byte flags = 0x01; // FLAG_SETTINGS_CLEAR_SETTINGS - int numSettings = 0; - int length = 8 * numSettings + 4; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - - decoder.decode(buf); - verify(delegate).readSettingsFrame(true); - verify(delegate).readSettingsEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySettingsPersistValues() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 1; - int length = 8 * numSettings + 4; - byte idFlags = 0x01; // FLAG_SETTINGS_PERSIST_VALUE - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - delegate.readSettingsEnd(); - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate, times(numSettings)).readSetting(id, value, true, false); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdySettingsPersistedValues() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 1; - int length = 8 * numSettings + 4; - byte idFlags = 0x02; // FLAG_SETTINGS_PERSISTED - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - delegate.readSettingsEnd(); - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate, times(numSettings)).readSetting(id, value, false, true); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdySettingsFrameFlags() throws Exception { - short type = 4; - byte flags = (byte) 0xFE; // undefined flags - int numSettings = 0; - int length = 8 * numSettings + 4; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate).readSettingsEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdySettingsFlags() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 1; - int length = 8 * numSettings + 4; - byte idFlags = (byte) 0xFC; // undefined flags - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - delegate.readSettingsEnd(); - decoder.decode(buf); - verify(delegate).readSettingsFrame(false); - verify(delegate, times(numSettings)).readSetting(id, value, false, false); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdySettingsFrameLength() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 2; - int length = 8 * numSettings + 8; // invalid length - byte idFlags = 0; - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(numSettings); - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdySettingsFrameNumSettings() throws Exception { - short type = 4; - byte flags = 0; - int numSettings = 2; - int length = 8 * numSettings + 4; - byte idFlags = 0; - int id = RANDOM.nextInt() & 0x00FFFFFF; - int value = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(0); // invalid num_settings - for (int i = 0; i < numSettings; i++) { - buf.writeByte(idFlags); - buf.writeMedium(id); - buf.writeInt(value); - } - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testDiscardUnknownFrame() throws Exception { - short type = 5; - byte flags = (byte) 0xFF; - int length = 8; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeLong(RANDOM.nextLong()); - - decoder.decode(buf); - verifyZeroInteractions(delegate); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testDiscardUnknownEmptyFrame() throws Exception { - short type = 5; - byte flags = (byte) 0xFF; - int length = 0; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - - decoder.decode(buf); - verifyZeroInteractions(delegate); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testProgressivelyDiscardUnknownEmptyFrame() throws Exception { - short type = 5; - byte flags = (byte) 0xFF; - int segment = 4; - int length = 2 * segment; - - ByteBuf header = Unpooled.buffer(SPDY_HEADER_SIZE); - ByteBuf segment1 = Unpooled.buffer(segment); - ByteBuf segment2 = Unpooled.buffer(segment); - encodeControlFrameHeader(header, type, flags, length); - segment1.writeInt(RANDOM.nextInt()); - segment2.writeInt(RANDOM.nextInt()); - - decoder.decode(header); - decoder.decode(segment1); - decoder.decode(segment2); - verifyZeroInteractions(delegate); - assertFalse(header.isReadable()); - assertFalse(segment1.isReadable()); - assertFalse(segment2.isReadable()); - header.release(); - segment1.release(); - segment2.release(); - } - - @Test - public void testSpdyPingFrame() throws Exception { - short type = 6; - byte flags = 0; - int length = 4; - int id = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(id); - - decoder.decode(buf); - verify(delegate).readPingFrame(id); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdyPingFrameFlags() throws Exception { - short type = 6; - byte flags = (byte) 0xFF; // undefined flags - int length = 4; - int id = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(id); - - decoder.decode(buf); - verify(delegate).readPingFrame(id); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyPingFrameLength() throws Exception { - short type = 6; - byte flags = 0; - int length = 8; // invalid length - int id = RANDOM.nextInt(); - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(id); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdyGoAwayFrame() throws Exception { - short type = 7; - byte flags = 0; - int length = 8; - int lastGoodStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(lastGoodStreamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readGoAwayFrame(lastGoodStreamId, statusCode); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdyGoAwayFrameFlags() throws Exception { - short type = 7; - byte flags = (byte) 0xFF; // undefined flags - int length = 8; - int lastGoodStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(lastGoodStreamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readGoAwayFrame(lastGoodStreamId, statusCode); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdyGoAwayFrameBits() throws Exception { - short type = 7; - byte flags = 0; - int length = 8; - int lastGoodStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(lastGoodStreamId | 0x80000000); // should ignore reserved bit - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readGoAwayFrame(lastGoodStreamId, statusCode); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyGoAwayFrameLength() throws Exception { - short type = 7; - byte flags = 0; - int length = 12; // invalid length - int lastGoodStreamId = RANDOM.nextInt() & 0x7FFFFFFF; - int statusCode = RANDOM.nextInt() | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(lastGoodStreamId); - buf.writeInt(statusCode); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdyHeadersFrame() throws Exception { - short type = 8; - byte flags = 0; - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readHeadersFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testLastSpdyHeadersFrame() throws Exception { - short type = 8; - byte flags = 0x01; // FLAG_FIN - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readHeadersFrame(streamId, true); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testUnknownSpdyHeadersFrameFlags() throws Exception { - short type = 8; - byte flags = (byte) 0xFE; // undefined flags - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readHeadersFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdyHeadersFrameBits() throws Exception { - short type = 8; - byte flags = 0; - int length = 4; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId | 0x80000000); // should ignore reserved bit - - decoder.decode(buf); - verify(delegate).readHeadersFrame(streamId, false); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyHeadersFrameLength() throws Exception { - short type = 8; - byte flags = 0; - int length = 0; // invalid length - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyHeadersFrameStreamId() throws Exception { - short type = 8; - byte flags = 0; - int length = 4; - int streamId = 0; // invalid stream identifier - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testSpdyHeadersFrameHeaderBlock() throws Exception { - short type = 8; - byte flags = 0; - int length = 4; - int headerBlockLength = 1024; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length + headerBlockLength); - buf.writeInt(streamId); - - ByteBuf headerBlock = Unpooled.buffer(headerBlockLength); - for (int i = 0; i < 256; i ++) { - headerBlock.writeInt(RANDOM.nextInt()); - } - decoder.decode(buf); - decoder.decode(headerBlock); - verify(delegate).readHeadersFrame(streamId, false); - verify(delegate).readHeaderBlock(headerBlock.slice(0, headerBlock.writerIndex())); - verify(delegate).readHeaderBlockEnd(); - assertFalse(buf.isReadable()); - assertFalse(headerBlock.isReadable()); - buf.release(); - headerBlock.release(); - } - - @Test - public void testSpdyWindowUpdateFrame() throws Exception { - short type = 9; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF; - int deltaWindowSize = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(deltaWindowSize); - - decoder.decode(buf); - verify(delegate).readWindowUpdateFrame(streamId, deltaWindowSize); - assertFalse(buf.isReadable()); - } - - @Test - public void testUnknownSpdyWindowUpdateFrameFlags() throws Exception { - short type = 9; - byte flags = (byte) 0xFF; // undefined flags - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF; - int deltaWindowSize = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(deltaWindowSize); - - decoder.decode(buf); - verify(delegate).readWindowUpdateFrame(streamId, deltaWindowSize); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testReservedSpdyWindowUpdateFrameBits() throws Exception { - short type = 9; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF; - int deltaWindowSize = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId | 0x80000000); // should ignore reserved bit - buf.writeInt(deltaWindowSize | 0x80000000); // should ignore reserved bit - - decoder.decode(buf); - verify(delegate).readWindowUpdateFrame(streamId, deltaWindowSize); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testInvalidSpdyWindowUpdateFrameLength() throws Exception { - short type = 9; - byte flags = 0; - int length = 12; // invalid length - int streamId = RANDOM.nextInt() & 0x7FFFFFFF; - int deltaWindowSize = RANDOM.nextInt() & 0x7FFFFFFF | 0x01; - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(deltaWindowSize); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } - - @Test - public void testIllegalSpdyWindowUpdateFrameDeltaWindowSize() throws Exception { - short type = 9; - byte flags = 0; - int length = 8; - int streamId = RANDOM.nextInt() & 0x7FFFFFFF; - int deltaWindowSize = 0; // invalid delta window size - - ByteBuf buf = Unpooled.buffer(SPDY_HEADER_SIZE + length); - encodeControlFrameHeader(buf, type, flags, length); - buf.writeInt(streamId); - buf.writeInt(deltaWindowSize); - - decoder.decode(buf); - verify(delegate).readFrameError(anyString()); - assertFalse(buf.isReadable()); - buf.release(); - } -} diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java deleted file mode 100644 index bc828397c6..0000000000 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class SpdyHeaderBlockRawDecoderTest { - - private static final int maxHeaderSize = 16; - - private static final String name = "name"; - private static final String value = "value"; - private static final byte[] nameBytes = name.getBytes(); - private static final byte[] valueBytes = value.getBytes(); - - private SpdyHeaderBlockRawDecoder decoder; - private SpdyHeadersFrame frame; - - @Before - public void setUp() { - decoder = new SpdyHeaderBlockRawDecoder(SpdyVersion.SPDY_3_1, maxHeaderSize); - frame = new DefaultSpdyHeadersFrame(1); - } - - @After - public void tearDown() { - decoder.end(); - } - - @Test - public void testEmptyHeaderBlock() throws Exception { - ByteBuf headerBlock = Unpooled.EMPTY_BUFFER; - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testZeroNameValuePairs() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(4); - headerBlock.writeInt(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testNegativeNameValuePairs() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(4); - headerBlock.writeInt(-1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testOneNameValuePair() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(21); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testMissingNameLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(4); - headerBlock.writeInt(1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testZeroNameLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(8); - headerBlock.writeInt(1); - headerBlock.writeInt(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testNegativeNameLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(8); - headerBlock.writeInt(1); - headerBlock.writeInt(-1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testMissingName() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(8); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testIllegalNameOnlyNull() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(18); - headerBlock.writeInt(1); - headerBlock.writeInt(1); - headerBlock.writeByte(0); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testMissingValueLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(12); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testZeroValueLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(16); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals("", frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testNegativeValueLength() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(16); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(-1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testMissingValue() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(16); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testIllegalValueOnlyNull() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(17); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(1); - headerBlock.writeByte(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testIllegalValueStartsWithNull() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(22); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(6); - headerBlock.writeByte(0); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testIllegalValueEndsWithNull() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(22); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(6); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testMultipleValues() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(27); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(11); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(2, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().getAll(name).get(0)); - assertEquals(value, frame.headers().getAll(name).get(1)); - headerBlock.release(); - } - - @Test - public void testMultipleValuesEndsWithNull() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(28); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(12); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testIllegalValueMultipleNulls() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(28); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(12); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - headerBlock.writeByte(0); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testMissingNextNameValuePair() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(21); - headerBlock.writeInt(2); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testMultipleNames() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(38); - headerBlock.writeInt(2); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testExtraData() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(22); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testMultipleDecodes() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(21); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - - int readableBytes = headerBlock.readableBytes(); - for (int i = 0; i < readableBytes; i++) { - ByteBuf headerBlockSegment = headerBlock.slice(i, 1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlockSegment, frame); - assertFalse(headerBlockSegment.isReadable()); - } - decoder.endHeaderBlock(frame); - - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - headerBlock.release(); - } - - @Test - public void testContinueAfterInvalidHeaders() throws Exception { - ByteBuf numHeaders = Unpooled.buffer(4); - numHeaders.writeInt(1); - - ByteBuf nameBlock = Unpooled.buffer(8); - nameBlock.writeInt(4); - nameBlock.writeBytes(nameBytes); - - ByteBuf valueBlock = Unpooled.buffer(9); - valueBlock.writeInt(5); - valueBlock.writeBytes(valueBytes); - - decoder.decode(ByteBufAllocator.DEFAULT, numHeaders, frame); - decoder.decode(ByteBufAllocator.DEFAULT, nameBlock, frame); - frame.setInvalid(); - decoder.decode(ByteBufAllocator.DEFAULT, valueBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(numHeaders.isReadable()); - assertFalse(nameBlock.isReadable()); - assertFalse(valueBlock.isReadable()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - numHeaders.release(); - nameBlock.release(); - valueBlock.release(); - } - - @Test - public void testTruncatedHeaderName() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(maxHeaderSize + 18); - headerBlock.writeInt(1); - headerBlock.writeInt(maxHeaderSize + 1); - for (int i = 0; i < maxHeaderSize + 1; i++) { - headerBlock.writeByte('a'); - } - headerBlock.writeInt(5); - headerBlock.writeBytes(valueBytes); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isTruncated()); - assertFalse(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } - - @Test - public void testTruncatedHeaderValue() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(maxHeaderSize + 13); - headerBlock.writeInt(1); - headerBlock.writeInt(4); - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(13); - for (int i = 0; i < maxHeaderSize - 3; i++) { - headerBlock.writeByte('a'); - } - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertTrue(frame.isTruncated()); - assertFalse(frame.isInvalid()); - assertEquals(0, frame.headers().names().size()); - headerBlock.release(); - } -} diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java deleted file mode 100644 index 404bbd9ec5..0000000000 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2014 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.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class SpdyHeaderBlockZlibDecoderTest { - - // zlib header indicating 32K window size fastest deflate algorithm with SPDY dictionary - private static final byte[] zlibHeader = {0x78, 0x3f, (byte) 0xe3, (byte) 0xc6, (byte) 0xa7, (byte) 0xc2}; - private static final byte[] zlibSyncFlush = {0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff}; - - private static final int maxHeaderSize = 8192; - - private static final String name = "name"; - private static final String value = "value"; - private static final byte[] nameBytes = name.getBytes(); - private static final byte[] valueBytes = value.getBytes(); - - private SpdyHeaderBlockZlibDecoder decoder; - private SpdyHeadersFrame frame; - - @Before - public void setUp() { - decoder = new SpdyHeaderBlockZlibDecoder(SpdyVersion.SPDY_3_1, maxHeaderSize); - frame = new DefaultSpdyHeadersFrame(1); - } - - @After - public void tearDown() { - decoder.end(); - } - - @Test - public void testHeaderBlock() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(37); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x15); // little-endian length (21) - headerBlock.writeByte(0x00); // little-endian length (21) - headerBlock.writeByte(0xea); // one's compliment of length - headerBlock.writeByte(0xff); // one's compliment of length - headerBlock.writeInt(1); // number of Name/Value pairs - headerBlock.writeInt(4); // length of name - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); // length of value - headerBlock.writeBytes(valueBytes); - headerBlock.writeBytes(zlibSyncFlush); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - - headerBlock.release(); - } - - @Test - public void testHeaderBlockMultipleDecodes() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(37); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x15); // little-endian length (21) - headerBlock.writeByte(0x00); // little-endian length (21) - headerBlock.writeByte(0xea); // one's compliment of length - headerBlock.writeByte(0xff); // one's compliment of length - headerBlock.writeInt(1); // number of Name/Value pairs - headerBlock.writeInt(4); // length of name - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); // length of value - headerBlock.writeBytes(valueBytes); - headerBlock.writeBytes(zlibSyncFlush); - - int readableBytes = headerBlock.readableBytes(); - for (int i = 0; i < readableBytes; i++) { - ByteBuf headerBlockSegment = headerBlock.slice(i, 1); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlockSegment, frame); - assertFalse(headerBlockSegment.isReadable()); - } - decoder.endHeaderBlock(frame); - - assertFalse(frame.isInvalid()); - assertEquals(1, frame.headers().names().size()); - assertTrue(frame.headers().contains(name)); - assertEquals(1, frame.headers().getAll(name).size()); - assertEquals(value, frame.headers().get(name)); - - headerBlock.release(); - } - - @Test - public void testLargeHeaderName() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(8220); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x0c); // little-endian length (8204) - headerBlock.writeByte(0x20); // little-endian length (8204) - headerBlock.writeByte(0xf3); // one's compliment of length - headerBlock.writeByte(0xdf); // one's compliment of length - headerBlock.writeInt(1); // number of Name/Value pairs - headerBlock.writeInt(8192); // length of name - for (int i = 0; i < 8192; i++) { - headerBlock.writeByte('n'); - } - headerBlock.writeInt(0); // length of value - headerBlock.writeBytes(zlibSyncFlush); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertFalse(frame.isTruncated()); - assertEquals(1, frame.headers().names().size()); - - headerBlock.release(); - } - - @Test - public void testLargeHeaderValue() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(8220); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x0c); // little-endian length (8204) - headerBlock.writeByte(0x20); // little-endian length (8204) - headerBlock.writeByte(0xf3); // one's compliment of length - headerBlock.writeByte(0xdf); // one's compliment of length - headerBlock.writeInt(1); // number of Name/Value pairs - headerBlock.writeInt(1); // length of name - headerBlock.writeByte('n'); - headerBlock.writeInt(8191); // length of value - for (int i = 0; i < 8191; i++) { - headerBlock.writeByte('v'); - } - headerBlock.writeBytes(zlibSyncFlush); - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - decoder.endHeaderBlock(frame); - - assertFalse(headerBlock.isReadable()); - assertFalse(frame.isInvalid()); - assertFalse(frame.isTruncated()); - assertEquals(1, frame.headers().names().size()); - assertEquals(8191, frame.headers().get("n").length()); - - headerBlock.release(); - } - - @Test(expected = SpdyProtocolException.class) - public void testHeaderBlockExtraData() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(37); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x15); // little-endian length (21) - headerBlock.writeByte(0x00); // little-endian length (21) - headerBlock.writeByte(0xea); // one's compliment of length - headerBlock.writeByte(0xff); // one's compliment of length - headerBlock.writeInt(1); // number of Name/Value pairs - headerBlock.writeInt(4); // length of name - headerBlock.writeBytes(nameBytes); - headerBlock.writeInt(5); // length of value - headerBlock.writeBytes(valueBytes); - headerBlock.writeByte(0x19); // adler-32 checksum - headerBlock.writeByte(0xa5); // adler-32 checksum - headerBlock.writeByte(0x03); // adler-32 checksum - headerBlock.writeByte(0xc9); // adler-32 checksum - headerBlock.writeByte(0); // Data following zlib stream - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - headerBlock.release(); - } - - @Test(expected = SpdyProtocolException.class) - public void testHeaderBlockInvalidDictionary() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(7); - headerBlock.writeByte(0x78); - headerBlock.writeByte(0x3f); - headerBlock.writeByte(0x01); // Unknown dictionary - headerBlock.writeByte(0x02); // Unknown dictionary - headerBlock.writeByte(0x03); // Unknown dictionary - headerBlock.writeByte(0x04); // Unknown dictionary - headerBlock.writeByte(0); // Non-compressed block - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - headerBlock.release(); - } - - @Test(expected = SpdyProtocolException.class) - public void testHeaderBlockInvalidDeflateBlock() throws Exception { - ByteBuf headerBlock = Unpooled.buffer(11); - headerBlock.writeBytes(zlibHeader); - headerBlock.writeByte(0); // Non-compressed block - headerBlock.writeByte(0x00); // little-endian length (0) - headerBlock.writeByte(0x00); // little-endian length (0) - headerBlock.writeByte(0x00); // invalid one's compliment - headerBlock.writeByte(0x00); // invalid one's compliment - decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame); - - headerBlock.release(); - } -} diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java deleted file mode 100644 index 362628aa86..0000000000 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * 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; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.util.internal.logging.InternalLogger; -import io.netty.util.internal.logging.InternalLoggerFactory; -import org.junit.Test; - -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.*; - -public class SpdySessionHandlerTest { - - private static final InternalLogger logger = - InternalLoggerFactory.getInstance(SpdySessionHandlerTest.class); - - private static final int closeSignal = SpdyCodecUtil.SPDY_SETTINGS_MAX_ID; - private static final SpdySettingsFrame closeMessage = new DefaultSpdySettingsFrame(); - - static { - closeMessage.setValue(closeSignal, 0); - } - - private static void assertDataFrame(Object msg, int streamId, boolean last) { - assertNotNull(msg); - assertTrue(msg instanceof SpdyDataFrame); - SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; - assertEquals(streamId, spdyDataFrame.streamId()); - assertEquals(last, spdyDataFrame.isLast()); - } - - private static void assertSynReply(Object msg, int streamId, boolean last, SpdyHeaders headers) { - assertNotNull(msg); - assertTrue(msg instanceof SpdySynReplyFrame); - assertHeaders(msg, streamId, last, headers); - } - - private static void assertRstStream(Object msg, int streamId, SpdyStreamStatus status) { - assertNotNull(msg); - assertTrue(msg instanceof SpdyRstStreamFrame); - SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; - assertEquals(streamId, spdyRstStreamFrame.streamId()); - assertEquals(status, spdyRstStreamFrame.status()); - } - - private static void assertPing(Object msg, int id) { - assertNotNull(msg); - assertTrue(msg instanceof SpdyPingFrame); - SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; - assertEquals(id, spdyPingFrame.id()); - } - - private static void assertGoAway(Object msg, int lastGoodStreamId) { - assertNotNull(msg); - assertTrue(msg instanceof SpdyGoAwayFrame); - SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg; - assertEquals(lastGoodStreamId, spdyGoAwayFrame.lastGoodStreamId()); - } - - private static void assertHeaders(Object msg, int streamId, boolean last, SpdyHeaders headers) { - assertNotNull(msg); - assertTrue(msg instanceof SpdyHeadersFrame); - SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; - assertEquals(streamId, spdyHeadersFrame.streamId()); - assertEquals(last, spdyHeadersFrame.isLast()); - for (CharSequence name: headers.names()) { - List expectedValues = headers.getAll(name); - List receivedValues = spdyHeadersFrame.headers().getAll(name); - assertTrue(receivedValues.containsAll(expectedValues)); - receivedValues.removeAll(expectedValues); - assertTrue(receivedValues.isEmpty()); - spdyHeadersFrame.headers().remove(name); - } - assertTrue(spdyHeadersFrame.headers().isEmpty()); - } - - private static void testSpdySessionHandler(SpdyVersion version, boolean server) { - EmbeddedChannel sessionHandler = new EmbeddedChannel( - new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); - - while (sessionHandler.readOutbound() != null) { - continue; - } - - int localStreamId = server ? 1 : 2; - int remoteStreamId = server ? 2 : 1; - - SpdySynStreamFrame spdySynStreamFrame = - new DefaultSpdySynStreamFrame(localStreamId, 0, (byte) 0); - spdySynStreamFrame.headers().set("compression", "test"); - - SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamId); - spdyDataFrame.setLast(true); - - // Check if session handler returns INVALID_STREAM if it receives - // a data frame for a Stream-ID that is not open - sessionHandler.writeInbound(new DefaultSpdyDataFrame(localStreamId)); - assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.INVALID_STREAM); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler returns PROTOCOL_ERROR if it receives - // a data frame for a Stream-ID before receiving a SYN_REPLY frame - sessionHandler.writeInbound(new DefaultSpdyDataFrame(remoteStreamId)); - assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.PROTOCOL_ERROR); - assertNull(sessionHandler.readOutbound()); - remoteStreamId += 2; - - // Check if session handler returns PROTOCOL_ERROR if it receives - // multiple SYN_REPLY frames for the same active Stream-ID - sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId)); - assertNull(sessionHandler.readOutbound()); - sessionHandler.writeInbound(new DefaultSpdySynReplyFrame(remoteStreamId)); - assertRstStream(sessionHandler.readOutbound(), remoteStreamId, SpdyStreamStatus.STREAM_IN_USE); - assertNull(sessionHandler.readOutbound()); - remoteStreamId += 2; - - // Check if frame codec correctly compresses/uncompresses headers - sessionHandler.writeInbound(spdySynStreamFrame); - assertSynReply(sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers()); - assertNull(sessionHandler.readOutbound()); - SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamId); - - spdyHeadersFrame.headers().add("header", "test1"); - spdyHeadersFrame.headers().add("header", "test2"); - - sessionHandler.writeInbound(spdyHeadersFrame); - assertHeaders(sessionHandler.readOutbound(), localStreamId, false, spdyHeadersFrame.headers()); - assertNull(sessionHandler.readOutbound()); - localStreamId += 2; - - // Check if session handler closed the streams using the number - // of concurrent streams and that it returns REFUSED_STREAM - // if it receives a SYN_STREAM frame it does not wish to accept - spdySynStreamFrame.setStreamId(localStreamId); - spdySynStreamFrame.setLast(true); - spdySynStreamFrame.setUnidirectional(true); - - sessionHandler.writeInbound(spdySynStreamFrame); - assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler rejects HEADERS for closed streams - int testStreamId = spdyDataFrame.streamId(); - sessionHandler.writeInbound(spdyDataFrame); - assertDataFrame(sessionHandler.readOutbound(), testStreamId, spdyDataFrame.isLast()); - assertNull(sessionHandler.readOutbound()); - spdyHeadersFrame.setStreamId(testStreamId); - - sessionHandler.writeInbound(spdyHeadersFrame); - assertRstStream(sessionHandler.readOutbound(), testStreamId, SpdyStreamStatus.INVALID_STREAM); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler drops active streams if it receives - // a RST_STREAM frame for that Stream-ID - sessionHandler.writeInbound(new DefaultSpdyRstStreamFrame(remoteStreamId, 3)); - assertNull(sessionHandler.readOutbound()); - //remoteStreamId += 2; - - // Check if session handler honors UNIDIRECTIONAL streams - spdySynStreamFrame.setLast(false); - sessionHandler.writeInbound(spdySynStreamFrame); - assertNull(sessionHandler.readOutbound()); - spdySynStreamFrame.setUnidirectional(false); - - // Check if session handler returns PROTOCOL_ERROR if it receives - // multiple SYN_STREAM frames for the same active Stream-ID - sessionHandler.writeInbound(spdySynStreamFrame); - assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR); - assertNull(sessionHandler.readOutbound()); - localStreamId += 2; - - // Check if session handler returns PROTOCOL_ERROR if it receives - // a SYN_STREAM frame with an invalid Stream-ID - spdySynStreamFrame.setStreamId(localStreamId - 1); - sessionHandler.writeInbound(spdySynStreamFrame); - assertRstStream(sessionHandler.readOutbound(), localStreamId - 1, SpdyStreamStatus.PROTOCOL_ERROR); - assertNull(sessionHandler.readOutbound()); - spdySynStreamFrame.setStreamId(localStreamId); - - // Check if session handler returns PROTOCOL_ERROR if it receives - // an invalid HEADERS frame - spdyHeadersFrame.setStreamId(localStreamId); - - spdyHeadersFrame.setInvalid(); - sessionHandler.writeInbound(spdyHeadersFrame); - assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.PROTOCOL_ERROR); - assertNull(sessionHandler.readOutbound()); - - sessionHandler.finish(); - } - - private static void testSpdySessionHandlerPing(SpdyVersion version, boolean server) { - EmbeddedChannel sessionHandler = new EmbeddedChannel( - new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); - - while (sessionHandler.readOutbound() != null) { - continue; - } - - int localStreamId = server ? 1 : 2; - int remoteStreamId = server ? 2 : 1; - - SpdyPingFrame localPingFrame = new DefaultSpdyPingFrame(localStreamId); - SpdyPingFrame remotePingFrame = new DefaultSpdyPingFrame(remoteStreamId); - - // Check if session handler returns identical local PINGs - sessionHandler.writeInbound(localPingFrame); - assertPing(sessionHandler.readOutbound(), localPingFrame.id()); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler ignores un-initiated remote PINGs - sessionHandler.writeInbound(remotePingFrame); - assertNull(sessionHandler.readOutbound()); - - sessionHandler.finish(); - } - - private static void testSpdySessionHandlerGoAway(SpdyVersion version, boolean server) { - EmbeddedChannel sessionHandler = new EmbeddedChannel( - new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); - - while (sessionHandler.readOutbound() != null) { - continue; - } - - int localStreamId = server ? 1 : 2; - - SpdySynStreamFrame spdySynStreamFrame = - new DefaultSpdySynStreamFrame(localStreamId, 0, (byte) 0); - spdySynStreamFrame.headers().set("compression", "test"); - - SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamId); - spdyDataFrame.setLast(true); - - // Send an initial request - sessionHandler.writeInbound(spdySynStreamFrame); - assertSynReply(sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers()); - assertNull(sessionHandler.readOutbound()); - sessionHandler.writeInbound(spdyDataFrame); - assertDataFrame(sessionHandler.readOutbound(), localStreamId, true); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler sends a GOAWAY frame when closing - sessionHandler.writeInbound(closeMessage); - assertGoAway(sessionHandler.readOutbound(), localStreamId); - assertNull(sessionHandler.readOutbound()); - localStreamId += 2; - - // Check if session handler returns REFUSED_STREAM if it receives - // SYN_STREAM frames after sending a GOAWAY frame - spdySynStreamFrame.setStreamId(localStreamId); - sessionHandler.writeInbound(spdySynStreamFrame); - assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM); - assertNull(sessionHandler.readOutbound()); - - // Check if session handler ignores Data frames after sending - // a GOAWAY frame - spdyDataFrame.setStreamId(localStreamId); - sessionHandler.writeInbound(spdyDataFrame); - assertNull(sessionHandler.readOutbound()); - - sessionHandler.finish(); - } - - @Test - public void testSpdyClientSessionHandler() { - logger.info("Running: testSpdyClientSessionHandler v3.1"); - testSpdySessionHandler(SpdyVersion.SPDY_3_1, false); - } - - @Test - public void testSpdyClientSessionHandlerPing() { - logger.info("Running: testSpdyClientSessionHandlerPing v3.1"); - testSpdySessionHandlerPing(SpdyVersion.SPDY_3_1, false); - } - - @Test - public void testSpdyClientSessionHandlerGoAway() { - logger.info("Running: testSpdyClientSessionHandlerGoAway v3.1"); - testSpdySessionHandlerGoAway(SpdyVersion.SPDY_3_1, false); - } - - @Test - public void testSpdyServerSessionHandler() { - logger.info("Running: testSpdyServerSessionHandler v3.1"); - testSpdySessionHandler(SpdyVersion.SPDY_3_1, true); - } - - @Test - public void testSpdyServerSessionHandlerPing() { - logger.info("Running: testSpdyServerSessionHandlerPing v3.1"); - testSpdySessionHandlerPing(SpdyVersion.SPDY_3_1, true); - } - - @Test - public void testSpdyServerSessionHandlerGoAway() { - logger.info("Running: testSpdyServerSessionHandlerGoAway v3.1"); - testSpdySessionHandlerGoAway(SpdyVersion.SPDY_3_1, true); - } - - // Echo Handler opens 4 half-closed streams on session connection - // and then sets the number of concurrent streams to 1 - private static class EchoHandler extends ChannelInboundHandlerAdapter { - private final int closeSignal; - private final boolean server; - - EchoHandler(int closeSignal, boolean server) { - this.closeSignal = closeSignal; - this.server = server; - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - // Initiate 4 new streams - int streamId = server ? 2 : 1; - SpdySynStreamFrame spdySynStreamFrame = - new DefaultSpdySynStreamFrame(streamId, 0, (byte) 0); - spdySynStreamFrame.setLast(true); - ctx.writeAndFlush(spdySynStreamFrame); - spdySynStreamFrame.setStreamId(spdySynStreamFrame.streamId() + 2); - ctx.writeAndFlush(spdySynStreamFrame); - spdySynStreamFrame.setStreamId(spdySynStreamFrame.streamId() + 2); - ctx.writeAndFlush(spdySynStreamFrame); - spdySynStreamFrame.setStreamId(spdySynStreamFrame.streamId() + 2); - ctx.writeAndFlush(spdySynStreamFrame); - - // Limit the number of concurrent streams to 1 - SpdySettingsFrame spdySettingsFrame = new DefaultSpdySettingsFrame(); - spdySettingsFrame.setValue(SpdySettingsFrame.SETTINGS_MAX_CONCURRENT_STREAMS, 1); - ctx.writeAndFlush(spdySettingsFrame); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof SpdySynStreamFrame) { - - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - if (!spdySynStreamFrame.isUnidirectional()) { - int streamId = spdySynStreamFrame.streamId(); - SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId); - spdySynReplyFrame.setLast(spdySynStreamFrame.isLast()); - for (Map.Entry entry: spdySynStreamFrame.headers()) { - spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue()); - } - - ctx.writeAndFlush(spdySynReplyFrame); - } - return; - } - - if (msg instanceof SpdySynReplyFrame) { - return; - } - - if (msg instanceof SpdyDataFrame || - msg instanceof SpdyPingFrame || - msg instanceof SpdyHeadersFrame) { - - ctx.writeAndFlush(msg); - return; - } - - if (msg instanceof SpdySettingsFrame) { - SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; - if (spdySettingsFrame.isSet(closeSignal)) { - ctx.close(); - } - } - } - } -} diff --git a/example/pom.xml b/example/pom.xml index d3c4757625..1f3707c4ea 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -110,10 +110,6 @@ ${conscrypt.artifactId} ${conscrypt.classifier} - - org.eclipse.jetty.npn - npn-api - com.jcraft jzlib diff --git a/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java b/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java deleted file mode 100644 index ac01cb1cd2..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.client; - -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.example.http.snoop.HttpSnoopClientHandler; -import io.netty.handler.codec.http.HttpContent; -import io.netty.handler.codec.http.HttpUtil; -import io.netty.handler.codec.http.HttpObject; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.LastHttpContent; -import io.netty.util.CharsetUtil; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * This is a modified version of {@link HttpSnoopClientHandler} that uses a {@link BlockingQueue} to wait until an - * HTTPResponse is received. - */ -public class HttpResponseClientHandler extends SimpleChannelInboundHandler { - - private final BlockingQueue queue = new LinkedBlockingQueue<>(); - - @Override - public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { - if (msg instanceof HttpResponse) { - HttpResponse response = (HttpResponse) msg; - - System.out.println("STATUS: " + response.status()); - System.out.println("VERSION: " + response.protocolVersion()); - System.out.println(); - - if (!response.headers().isEmpty()) { - for (CharSequence name : response.headers().names()) { - for (CharSequence value : response.headers().getAll(name)) { - System.out.println("HEADER: " + name + " = " + value); - } - } - System.out.println(); - } - - if (HttpUtil.isTransferEncodingChunked(response)) { - System.out.println("CHUNKED CONTENT {"); - } else { - System.out.println("CONTENT {"); - } - } - if (msg instanceof HttpContent) { - HttpContent content = (HttpContent) msg; - - System.out.print(content.content().toString(CharsetUtil.UTF_8)); - System.out.flush(); - - if (content instanceof LastHttpContent) { - System.out.println("} END OF CONTENT"); - queue.add(ctx.channel().newSucceededFuture()); - } - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - queue.add(ctx.channel().newFailedFuture(cause)); - cause.printStackTrace(); - ctx.close(); - } - - public BlockingQueue queue() { - return queue; - } -} diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java deleted file mode 100644 index 5e7913a2c2..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.client; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.MultithreadEventLoopGroup; -import io.netty.channel.nio.NioHandler; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaderValues; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.ssl.ApplicationProtocolConfig; -import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolNames; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; - -/** - * An SPDY client that allows you to send HTTP GET to a SPDY server. - *

- * This class must be run with the JVM parameter: {@code java -Xbootclasspath/p: ...}. The - * "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from Maven at - * coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions. See - * Jetty docs for more information. - *

- * You may also use the {@code run-example.sh} script to start the client from the command line: - *

- *     ./run-example.sh spdy-client
- * 
- */ -public final class SpdyClient { - - static final String HOST = System.getProperty("host", "127.0.0.1"); - static final int PORT = Integer.parseInt(System.getProperty("port", "8443")); - - public static void main(String[] args) throws Exception { - // Configure SSL. - final SslContext sslCtx = SslContextBuilder.forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .applicationProtocolConfig(new ApplicationProtocolConfig( - Protocol.NPN, - // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. - SelectorFailureBehavior.NO_ADVERTISE, - // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. - SelectedListenerFailureBehavior.ACCEPT, - ApplicationProtocolNames.SPDY_3_1, - ApplicationProtocolNames.HTTP_1_1)) - .build(); - - HttpResponseClientHandler httpResponseHandler = new HttpResponseClientHandler(); - EventLoopGroup workerGroup = new MultithreadEventLoopGroup(NioHandler.newFactory()); - - try { - Bootstrap b = new Bootstrap(); - b.group(workerGroup); - b.channel(NioSocketChannel.class); - b.option(ChannelOption.SO_KEEPALIVE, true); - b.remoteAddress(HOST, PORT); - b.handler(new SpdyClientInitializer(sslCtx, httpResponseHandler)); - - // Start the client. - Channel channel = b.connect().syncUninterruptibly().channel(); - System.out.println("Connected to " + HOST + ':' + PORT); - - // Create a GET request. - HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - request.headers().set(HttpHeaderNames.HOST, HOST); - request.headers().set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP); - - // Send the GET request. - channel.writeAndFlush(request).sync(); - - // Waits for the complete HTTP response - httpResponseHandler.queue().take().sync(); - System.out.println("Finished SPDY HTTP GET"); - - // Wait until the connection is closed. - channel.close().syncUninterruptibly(); - } finally { - workerGroup.shutdownGracefully(); - } - } -} diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java deleted file mode 100644 index 931f415531..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.client; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.spdy.SpdyFrameCodec; -import io.netty.handler.codec.spdy.SpdyHttpDecoder; -import io.netty.handler.codec.spdy.SpdyHttpEncoder; -import io.netty.handler.codec.spdy.SpdySessionHandler; -import io.netty.handler.ssl.SslContext; - -import static io.netty.handler.codec.spdy.SpdyVersion.*; -import static io.netty.util.internal.logging.InternalLogLevel.*; - -public class SpdyClientInitializer extends ChannelInitializer { - - private static final int MAX_SPDY_CONTENT_LENGTH = 1024 * 1024; // 1 MB - - private final SslContext sslCtx; - private final HttpResponseClientHandler httpResponseHandler; - - public SpdyClientInitializer(SslContext sslCtx, HttpResponseClientHandler httpResponseHandler) { - this.sslCtx = sslCtx; - this.httpResponseHandler = httpResponseHandler; - } - - @Override - public void initChannel(SocketChannel ch) { - ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("ssl", sslCtx.newHandler(ch.alloc())); - pipeline.addLast("spdyFrameCodec", new SpdyFrameCodec(SPDY_3_1)); - pipeline.addLast("spdyFrameLogger", new SpdyFrameLogger(INFO)); - pipeline.addLast("spdySessionHandler", new SpdySessionHandler(SPDY_3_1, false)); - pipeline.addLast("spdyHttpEncoder", new SpdyHttpEncoder(SPDY_3_1)); - pipeline.addLast("spdyHttpDecoder", new SpdyHttpDecoder(SPDY_3_1, MAX_SPDY_CONTENT_LENGTH)); - pipeline.addLast("spdyStreamIdHandler", new SpdyClientStreamIdHandler()); - pipeline.addLast("httpHandler", httpResponseHandler); - } -} diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java deleted file mode 100644 index 8a2fe2d003..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.client; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpMessage; -import io.netty.handler.codec.spdy.SpdyHttpHeaders; -import io.netty.handler.codec.spdy.SpdyHttpHeaders.Names; - -/** - * Adds a unique client stream ID to the SPDY header. Client stream IDs MUST be odd. - */ -public class SpdyClientStreamIdHandler extends ChannelOutboundHandlerAdapter { - - private int currentStreamId = 1; - - public boolean acceptOutboundMessage(Object msg) { - return msg instanceof HttpMessage; - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - if (acceptOutboundMessage(msg)) { - HttpMessage httpMsg = (HttpMessage) msg; - if (!httpMsg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) { - httpMsg.headers().setInt(Names.STREAM_ID, currentStreamId); - // Client stream IDs are always odd - currentStreamId += 2; - } - } - ctx.write(msg, promise); - } -} diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java b/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java deleted file mode 100644 index ab136d76f9..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.client; - -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.spdy.SpdyFrame; -import io.netty.util.internal.logging.InternalLogLevel; -import io.netty.util.internal.logging.InternalLogger; -import io.netty.util.internal.logging.InternalLoggerFactory; - -/** - * Logs SPDY frames for debugging purposes. - */ -public class SpdyFrameLogger extends ChannelDuplexHandler { - - private enum Direction { - INBOUND, OUTBOUND - } - - protected final InternalLogger logger; - private final InternalLogLevel level; - - public SpdyFrameLogger(InternalLogLevel level) { - if (level == null) { - throw new NullPointerException("level"); - } - - logger = InternalLoggerFactory.getInstance(getClass()); - this.level = level; - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - if (acceptMessage(msg)) { - log((SpdyFrame) msg, Direction.INBOUND); - } - ctx.fireChannelRead(msg); - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { - if (acceptMessage(msg)) { - log((SpdyFrame) msg, Direction.OUTBOUND); - } - ctx.write(msg, promise); - } - - private static boolean acceptMessage(Object msg) { - return msg instanceof SpdyFrame; - } - - private void log(SpdyFrame msg, Direction d) { - if (logger.isEnabled(level)) { - StringBuilder b = new StringBuilder(200) - .append("\n----------------") - .append(d.name()) - .append("--------------------\n") - .append(msg) - .append("\n------------------------------------"); - - logger.log(level, b.toString()); - } - } -} diff --git a/example/src/main/java/io/netty/example/spdy/client/package-info.java b/example/src/main/java/io/netty/example/spdy/client/package-info.java deleted file mode 100644 index de3f6d40ed..0000000000 --- a/example/src/main/java/io/netty/example/spdy/client/package-info.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014 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. - */ - -/** - * This package contains an example SPDY HTTP client. It will behave like a SPDY-enabled browser and you can see the - * SPDY frames flowing in and out using the {@link io.netty.example.spdy.client.SpdyFrameLogger}. - * - *

- * This package relies on the Jetty project's implementation of the Transport Layer Security (TLS) extension for Next - * Protocol Negotiation (NPN) for OpenJDK 7 is required. NPN allows the application layer to negotiate which - * protocol, SPDY or HTTP, to use. - *

- * To start, run {@link io.netty.example.spdy.server.SpdyServer} with the JVM parameter: - * {@code java -Xbootclasspath/p: ...}. - * The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from - * Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions. - * See Jetty docs for more - * information. - *

- * After that, you can run {@link io.netty.example.spdy.client.SpdyClient}, also settings the JVM parameter - * mentioned above. - *

- * You may also use the {@code run-example.sh} script to start the server and the client from the command line: - *

- *     ./run-example spdy-server
- * 
- * Then start the client in a different terminal window: - *
- *     ./run-example spdy-client
- * 
- */ -package io.netty.example.spdy.client; diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java b/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java deleted file mode 100644 index bed9bd24da..0000000000 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.server; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.handler.codec.spdy.SpdyFrameCodec; -import io.netty.handler.codec.spdy.SpdyHttpDecoder; -import io.netty.handler.codec.spdy.SpdyHttpEncoder; -import io.netty.handler.codec.spdy.SpdyHttpResponseStreamIdHandler; -import io.netty.handler.codec.spdy.SpdySessionHandler; -import io.netty.handler.codec.spdy.SpdyVersion; -import io.netty.handler.ssl.ApplicationProtocolNames; -import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler; - -/** - * Negotiates with the browser if SPDY or HTTP is going to be used. Once decided, the Netty pipeline is setup with - * the correct handlers for the selected protocol. - */ -public class SpdyOrHttpHandler extends ApplicationProtocolNegotiationHandler { - - private static final int MAX_CONTENT_LENGTH = 1024 * 100; - - protected SpdyOrHttpHandler() { - super(ApplicationProtocolNames.HTTP_1_1); - } - - @Override - protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception { - if (ApplicationProtocolNames.SPDY_3_1.equals(protocol)) { - configureSpdy(ctx, SpdyVersion.SPDY_3_1); - return; - } - - if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) { - configureHttp1(ctx); - return; - } - - throw new IllegalStateException("unknown protocol: " + protocol); - } - - private static void configureSpdy(ChannelHandlerContext ctx, SpdyVersion version) throws Exception { - ChannelPipeline p = ctx.pipeline(); - p.addLast(new SpdyFrameCodec(version)); - p.addLast(new SpdySessionHandler(version, true)); - p.addLast(new SpdyHttpEncoder(version)); - p.addLast(new SpdyHttpDecoder(version, MAX_CONTENT_LENGTH)); - p.addLast(new SpdyHttpResponseStreamIdHandler()); - p.addLast(new SpdyServerHandler()); - } - - private static void configureHttp1(ChannelHandlerContext ctx) throws Exception { - ChannelPipeline p = ctx.pipeline(); - p.addLast(new HttpServerCodec()); - p.addLast(new HttpObjectAggregator(MAX_CONTENT_LENGTH)); - p.addLast(new SpdyServerHandler()); - } -} diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java deleted file mode 100644 index 339f9ddbbc..0000000000 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.server; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.MultithreadEventLoopGroup; -import io.netty.channel.nio.NioHandler; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import io.netty.handler.ssl.ApplicationProtocolConfig; -import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolNames; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.SelfSignedCertificate; - -/** - * A SPDY Server that responds to a GET request with a Hello World. - *

- * This class must be run with the JVM parameter: {@code java -Xbootclasspath/p: ...}. - * The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from - * Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions. - * See Jetty docs for more - * information. - *

- * You may also use the {@code run-example.sh} script to start the server from the command line: - *

- *     ./run-example.sh spdy-server
- * 
- *

- * Once started, you can test the server with your - * SPDY enabled web browser by navigating - * to https://localhost:8443/ - */ -public final class SpdyServer { - - static final int PORT = Integer.parseInt(System.getProperty("port", "8443")); - - public static void main(String[] args) throws Exception { - // Configure SSL. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) - .applicationProtocolConfig(new ApplicationProtocolConfig( - Protocol.NPN, - // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. - SelectorFailureBehavior.NO_ADVERTISE, - // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. - SelectedListenerFailureBehavior.ACCEPT, - ApplicationProtocolNames.SPDY_3_1, - ApplicationProtocolNames.HTTP_1_1)) - .build(); - - // Configure the server. - EventLoopGroup bossGroup = new MultithreadEventLoopGroup(1, NioHandler.newFactory()); - EventLoopGroup workerGroup = new MultithreadEventLoopGroup(NioHandler.newFactory()); - try { - ServerBootstrap b = new ServerBootstrap(); - b.option(ChannelOption.SO_BACKLOG, 1024); - b.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .handler(new LoggingHandler(LogLevel.INFO)) - .childHandler(new SpdyServerInitializer(sslCtx)); - - Channel ch = b.bind(PORT).sync().channel(); - - System.err.println("Open your SPDY-enabled web browser and navigate to https://127.0.0.1:" + PORT + '/'); - System.err.println("If using Chrome browser, check your SPDY sessions at chrome://net-internals/#spdy"); - - ch.closeFuture().sync(); - } finally { - bossGroup.shutdownGracefully(); - workerGroup.shutdownGracefully(); - } - } -} diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java deleted file mode 100644 index 93db15dcbf..0000000000 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.server; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaderValues; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.util.CharsetUtil; - -import java.util.Date; - -import static io.netty.handler.codec.http.HttpUtil.*; -import static io.netty.handler.codec.http.HttpResponseStatus.*; -import static io.netty.handler.codec.http.HttpVersion.*; - -/** - * HTTP handler that responds with a "Hello World" - */ -public class SpdyServerHandler extends SimpleChannelInboundHandler { - - @Override - public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof HttpRequest) { - HttpRequest req = (HttpRequest) msg; - - if (is100ContinueExpected(req)) { - ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); - } - boolean keepAlive = isKeepAlive(req); - - ByteBuf content = Unpooled.copiedBuffer("Hello World " + new Date(), CharsetUtil.UTF_8); - - FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content); - response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8"); - response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); - - if (!keepAlive) { - ctx.write(response).addListener(ChannelFutureListener.CLOSE); - } else { - response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); - ctx.write(response); - } - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) { - ctx.flush(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - cause.printStackTrace(); - ctx.close(); - } -} diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java deleted file mode 100644 index eb63027bcb..0000000000 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 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.example.spdy.server; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.ssl.SslContext; - -/** - * Sets up the Netty pipeline - */ -public class SpdyServerInitializer extends ChannelInitializer { - - private final SslContext sslCtx; - - public SpdyServerInitializer(SslContext sslCtx) { - this.sslCtx = sslCtx; - } - - @Override - public void initChannel(SocketChannel ch) { - ChannelPipeline p = ch.pipeline(); - p.addLast(sslCtx.newHandler(ch.alloc())); - // Negotiates with the browser if SPDY or HTTP is going to be used - p.addLast(new SpdyOrHttpHandler()); - } -} diff --git a/example/src/main/java/io/netty/example/spdy/server/package-info.java b/example/src/main/java/io/netty/example/spdy/server/package-info.java deleted file mode 100644 index 1a61e7a58b..0000000000 --- a/example/src/main/java/io/netty/example/spdy/server/package-info.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 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. - */ - -/** - * This package contains an example SPDY HTTP web server. - *

- * This package relies on the Jetty project's implementation of the Transport Layer Security (TLS) extension for Next - * Protocol Negotiation (NPN) for OpenJDK 7 is required. NPN allows the application layer to negotiate which - * protocol, SPDY or HTTP, to use. - *

- * To start, run {@link io.netty.example.spdy.server.SpdyServer} with the JVM parameter: - * {@code java -Xbootclasspath/p: ...}. - * The "path_to_npn_boot_jar" is the path on the file system for the NPN Boot Jar file which can be downloaded from - * Maven at coordinates org.mortbay.jetty.npn:npn-boot. Different versions applies to different OpenJDK versions. - * See Jetty docs for more - * information. - *

- * You may also use the {@code run-example.sh} script to start the server from the command line: - *

- *     ./run-example spdy-server
- * 
- *

- * Once started, you can test the server with your - * SPDY enabled web browser by navigating - * to https://localhost:8443/ - */ -package io.netty.example.spdy.server; diff --git a/handler/pom.xml b/handler/pom.xml index 7a17fdff1e..47158c73b8 100644 --- a/handler/pom.xml +++ b/handler/pom.xml @@ -66,11 +66,6 @@ bcpkix-jdk15on true - - org.eclipse.jetty.npn - npn-api - true - org.eclipse.jetty.alpn alpn-api diff --git a/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolConfig.java b/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolConfig.java index 82160e37cf..7f9d4fff4b 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolConfig.java +++ b/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolConfig.java @@ -99,7 +99,7 @@ public final class ApplicationProtocolConfig { * Defines which application level protocol negotiation to use. */ public enum Protocol { - NONE, NPN, ALPN, NPN_AND_ALPN + NONE, ALPN } /** diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java b/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java deleted file mode 100644 index 3c2863b66c..0000000000 --- a/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014 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.ssl; - -import javax.net.ssl.SSLEngine; - -/** - * The {@link JdkApplicationProtocolNegotiator} to use if you need NPN and are using {@link SslProvider#JDK}. - * - * @deprecated use {@link ApplicationProtocolConfig}. - */ -@Deprecated -public final class JdkNpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator { - private static final SslEngineWrapperFactory NPN_WRAPPER = new SslEngineWrapperFactory() { - { - if (!JettyNpnSslEngine.isAvailable()) { - throw new RuntimeException("NPN unsupported. Is your classpath configured correctly?" - + " See https://wiki.eclipse.org/Jetty/Feature/NPN"); - } - } - - @Override - public SSLEngine wrapSslEngine(SSLEngine engine, - JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) { - return new JettyNpnSslEngine(engine, applicationNegotiator, isServer); - } - }; - - /** - * Create a new instance. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(Iterable protocols) { - this(false, protocols); - } - - /** - * Create a new instance. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(String... protocols) { - this(false, protocols); - } - - /** - * Create a new instance. - * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, Iterable protocols) { - this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); - } - - /** - * Create a new instance. - * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, String... protocols) { - this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); - } - - /** - * Create a new instance. - * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. - * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, - boolean serverFailIfNoCommonProtocols, Iterable protocols) { - this(clientFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, - serverFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, - protocols); - } - - /** - * Create a new instance. - * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. - * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, - boolean serverFailIfNoCommonProtocols, String... protocols) { - this(clientFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, - serverFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, - protocols); - } - - /** - * Create a new instance. - * @param selectorFactory The factory which provides classes responsible for selecting the protocol. - * @param listenerFactory The factory which provides to be notified of which protocol was selected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, - ProtocolSelectionListenerFactory listenerFactory, Iterable protocols) { - super(NPN_WRAPPER, selectorFactory, listenerFactory, protocols); - } - - /** - * Create a new instance. - * @param selectorFactory The factory which provides classes responsible for selecting the protocol. - * @param listenerFactory The factory which provides to be notified of which protocol was selected. - * @param protocols The order of iteration determines the preference of support for protocols. - */ - public JdkNpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, - ProtocolSelectionListenerFactory listenerFactory, String... protocols) { - super(NPN_WRAPPER, selectorFactory, listenerFactory, protocols); - } -} diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java index 5c36cb93eb..98bfd532b5 100644 --- a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java @@ -403,28 +403,6 @@ public class JdkSslContext extends SslContext { .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString()); } } - case NPN: - if (isServer) { - switch(config.selectedListenerFailureBehavior()) { - case ACCEPT: - return new JdkNpnApplicationProtocolNegotiator(false, config.supportedProtocols()); - case FATAL_ALERT: - return new JdkNpnApplicationProtocolNegotiator(true, config.supportedProtocols()); - default: - throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") - .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString()); - } - } else { - switch(config.selectorFailureBehavior()) { - case FATAL_ALERT: - return new JdkNpnApplicationProtocolNegotiator(true, config.supportedProtocols()); - case NO_ADVERTISE: - return new JdkNpnApplicationProtocolNegotiator(false, config.supportedProtocols()); - default: - throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") - .append(config.selectorFailureBehavior()).append(" failure behavior").toString()); - } - } default: throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") .append(config.protocol()).append(" protocol").toString()); diff --git a/handler/src/main/java/io/netty/handler/ssl/JettyNpnSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/JettyNpnSslEngine.java deleted file mode 100644 index 9e10465817..0000000000 --- a/handler/src/main/java/io/netty/handler/ssl/JettyNpnSslEngine.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2014 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.ssl; - -import static io.netty.util.internal.ObjectUtil.checkNotNull; -import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener; -import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; -import io.netty.util.internal.PlatformDependent; - -import java.util.LinkedHashSet; -import java.util.List; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; - -import org.eclipse.jetty.npn.NextProtoNego; -import org.eclipse.jetty.npn.NextProtoNego.ClientProvider; -import org.eclipse.jetty.npn.NextProtoNego.ServerProvider; - -final class JettyNpnSslEngine extends JdkSslEngine { - private static boolean available; - - static boolean isAvailable() { - updateAvailability(); - return available; - } - - private static void updateAvailability() { - if (available) { - return; - } - try { - // Always use bootstrap class loader. - Class.forName("sun.security.ssl.NextProtoNegoExtension", true, null); - available = true; - } catch (Exception ignore) { - // npn-boot was not loaded. - } - } - - JettyNpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) { - super(engine); - checkNotNull(applicationNegotiator, "applicationNegotiator"); - - if (server) { - final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator - .protocolListenerFactory().newListener(this, applicationNegotiator.protocols()), - "protocolListener"); - NextProtoNego.put(engine, new ServerProvider() { - @Override - public void unsupported() { - protocolListener.unsupported(); - } - - @Override - public List protocols() { - return applicationNegotiator.protocols(); - } - - @Override - public void protocolSelected(String protocol) { - try { - protocolListener.selected(protocol); - } catch (Throwable t) { - PlatformDependent.throwException(t); - } - } - }); - } else { - final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory() - .newSelector(this, new LinkedHashSet<>(applicationNegotiator.protocols())), - "protocolSelector"); - NextProtoNego.put(engine, new ClientProvider() { - @Override - public boolean supports() { - return true; - } - - @Override - public void unsupported() { - protocolSelector.unsupported(); - } - - @Override - public String selectProtocol(List protocols) { - try { - return protocolSelector.select(protocols); - } catch (Throwable t) { - PlatformDependent.throwException(t); - return null; - } - } - }); - } - } - - @Override - public void closeInbound() throws SSLException { - NextProtoNego.remove(getWrappedEngine()); - super.closeInbound(); - } - - @Override - public void closeOutbound() { - NextProtoNego.remove(getWrappedEngine()); - super.closeOutbound(); - } -} diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslNpnApplicationProtocolNegotiator.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslNpnApplicationProtocolNegotiator.java deleted file mode 100644 index 309c07bf53..0000000000 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslNpnApplicationProtocolNegotiator.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014 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.ssl; - -import static io.netty.handler.ssl.ApplicationProtocolUtil.toList; -import static io.netty.util.internal.ObjectUtil.checkNotNull; - -import java.util.List; - -/** - * OpenSSL {@link ApplicationProtocolNegotiator} for NPN. - * - * @deprecated use {@link ApplicationProtocolConfig} - */ -@Deprecated -public final class OpenSslNpnApplicationProtocolNegotiator implements OpenSslApplicationProtocolNegotiator { - private final List protocols; - - public OpenSslNpnApplicationProtocolNegotiator(Iterable protocols) { - this.protocols = checkNotNull(toList(protocols), "protocols"); - } - - public OpenSslNpnApplicationProtocolNegotiator(String... protocols) { - this.protocols = checkNotNull(toList(protocols), "protocols"); - } - - @Override - public ApplicationProtocolConfig.Protocol protocol() { - return ApplicationProtocolConfig.Protocol.NPN; - } - - @Override - public List protocols() { - return protocols; - } - - @Override - public ApplicationProtocolConfig.SelectorFailureBehavior selectorFailureBehavior() { - return ApplicationProtocolConfig.SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL; - } - - @Override - public ApplicationProtocolConfig.SelectedListenerFailureBehavior selectedListenerFailureBehavior() { - return ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT; - } -} diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java index 2bc714c81a..f5716d92b4 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java @@ -298,16 +298,9 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen int selectorBehavior = opensslSelectorFailureBehavior(apn.selectorFailureBehavior()); switch (apn.protocol()) { - case NPN: - SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior); - break; case ALPN: SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior); break; - case NPN_AND_ALPN: - SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior); - SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior); - break; default: throw new Error(); } @@ -561,8 +554,6 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen case NONE: return NONE_PROTOCOL_NEGOTIATOR; case ALPN: - case NPN: - case NPN_AND_ALPN: switch (config.selectedListenerFailureBehavior()) { case CHOOSE_MY_LAST_PROTOCOL: case ACCEPT: diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java index e54c3d93ac..7a0f40c9cd 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java @@ -2177,23 +2177,6 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc protocols, behavior, applicationProtocol); } break; - case NPN: - applicationProtocol = SSL.getNextProtoNegotiated(ssl); - if (applicationProtocol != null) { - ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol( - protocols, behavior, applicationProtocol); - } - break; - case NPN_AND_ALPN: - applicationProtocol = SSL.getAlpnSelected(ssl); - if (applicationProtocol == null) { - applicationProtocol = SSL.getNextProtoNegotiated(ssl); - } - if (applicationProtocol != null) { - ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol( - protocols, behavior, applicationProtocol); - } - break; default: throw new Error(); } diff --git a/handler/src/main/java/io/netty/handler/ssl/SslContext.java b/handler/src/main/java/io/netty/handler/ssl/SslContext.java index 6c5a6c6109..2b64307d6e 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslContext.java @@ -794,7 +794,7 @@ public abstract class SslContext { apn = ApplicationProtocolConfig.DISABLED; } else { apn = new ApplicationProtocolConfig( - Protocol.NPN_AND_ALPN, SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, + Protocol.ALPN, SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, SelectedListenerFailureBehavior.ACCEPT, nextProtocols); } return apn; diff --git a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java index ad2ca68b35..6d82b13e71 100644 --- a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java @@ -46,22 +46,6 @@ import static org.junit.Assume.assumeNoException; @RunWith(Parameterized.class) public class JdkSslEngineTest extends SSLEngineTest { public enum ProviderType { - NPN_JETTY { - @Override - boolean isAvailable() { - return JettyNpnSslEngine.isAvailable(); - } - - @Override - Protocol protocol() { - return Protocol.NPN; - } - - @Override - Provider provider() { - return null; - } - }, ALPN_JETTY { @Override boolean isAvailable() { @@ -201,6 +185,7 @@ public class JdkSslEngineTest extends SSLEngineTest { public void testTlsExtensionNoCompatibleProtocolsClientHandshakeFailure() throws Exception { try { providerType.activate(this); +<<<<<<< HEAD if (providerType == ProviderType.NPN_JETTY) { ApplicationProtocolConfig clientApn = failingNegotiator(providerType.protocol(), PREFERRED_APPLICATION_LEVEL_PROTOCOL); @@ -216,6 +201,17 @@ public class JdkSslEngineTest extends SSLEngineTest { PREFERRED_APPLICATION_LEVEL_PROTOCOL); JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator( (engine, supportedProtocols) -> new ProtocolSelector() { +======= + // ALPN + SelfSignedCertificate ssc = new SelfSignedCertificate(); + JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true, + PREFERRED_APPLICATION_LEVEL_PROTOCOL); + JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator( + new ProtocolSelectorFactory() { + @Override + public ProtocolSelector newSelector(SSLEngine engine, Set supportedProtocols) { + return new ProtocolSelector() { +>>>>>>> a3b937c1a... Drop NPN and SPDY support @Override public void unsupported() { } @@ -224,6 +220,7 @@ public class JdkSslEngineTest extends SSLEngineTest { public String select(List protocols) { return APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE; } +<<<<<<< HEAD }, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); @@ -240,6 +237,25 @@ public class JdkSslEngineTest extends SSLEngineTest { // no exception reported in this case but just the channel will be closed. assertTrue(clientException instanceof SSLHandshakeException || clientException == null); } +======= + }; + } + }, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY, + APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); + + SslContext serverSslCtx = new JdkSslServerContext(providerType.provider(), + ssc.certificate(), ssc.privateKey(), null, null, + IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0); + SslContext clientSslCtx = new JdkSslClientContext(providerType.provider(), null, + InsecureTrustManagerFactory.INSTANCE, null, + IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0); + + setupHandlers(new TestDelegatingSslContext(serverSslCtx), new TestDelegatingSslContext(clientSslCtx)); + assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); + // When using TLSv1.3 the handshake is NOT sent in an extra round trip which means there will be + // no exception reported in this case but just the channel will be closed. + assertTrue(clientException instanceof SSLHandshakeException || clientException == null); +>>>>>>> a3b937c1a... Drop NPN and SPDY support } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test @@ -269,10 +285,6 @@ public class JdkSslEngineTest extends SSLEngineTest { public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception { try { providerType.activate(this); - if (providerType == ProviderType.NPN_JETTY) { - // This test only applies to ALPN. - throw tlsExtensionNotFound(providerType.protocol()); - } // Even the preferred application protocol appears second in the client's list, it will be picked // because it's the first one on server's list. ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN, diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java index 3a6e1358c6..edd8f73c14 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java @@ -186,15 +186,6 @@ public class OpenSslEngineTest extends SSLEngineTest { } return true; } - @Test - public void testNpn() throws Exception { - String versionString = OpenSsl.versionString(); - assumeTrue("LibreSSL 2.6.1 removed NPN support, detected " + versionString, isNpnSupported(versionString)); - ApplicationProtocolConfig apn = acceptingNegotiator(Protocol.NPN, - PREFERRED_APPLICATION_LEVEL_PROTOCOL); - setupHandlers(apn); - runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); - } @Test public void testAlpn() throws Exception { diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java index e17f3e30df..74cfa169bf 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -1550,12 +1550,6 @@ public abstract class SSLEngineTest { .applicationProtocolConfig(serverApn) .sessionCacheSize(0) .sessionTimeout(0); - if (serverApn.protocol() == Protocol.NPN || serverApn.protocol() == Protocol.NPN_AND_ALPN) { - // NPN is not really well supported with TLSv1.3 so force to use TLSv1.2 - // See https://github.com/openssl/openssl/issues/3665 - serverCtxBuilder.protocols(PROTOCOL_TLS_V1_2); - } - SslContextBuilder clientCtxBuilder = SslContextBuilder.forClient() .sslProvider(sslClientProvider()) .sslContextProvider(clientSslContextProvider()) @@ -1565,12 +1559,6 @@ public abstract class SSLEngineTest { .sessionCacheSize(0) .sessionTimeout(0); - if (clientApn.protocol() == Protocol.NPN || clientApn.protocol() == Protocol.NPN_AND_ALPN) { - // NPN is not really well supported with TLSv1.3 so force to use TLSv1.2 - // See https://github.com/openssl/openssl/issues/3665 - clientCtxBuilder.protocols(PROTOCOL_TLS_V1_2); - } - setupHandlers(serverCtxBuilder.build(), clientCtxBuilder.build()); } finally { ssc.delete(); diff --git a/pom.xml b/pom.xml index b7c4a4e6d4..759e498171 100644 --- a/pom.xml +++ b/pom.xml @@ -357,12 +357,6 @@ - - org.eclipse.jetty.npn - npn-api - 1.1.1.v20141010 - provided - org.eclipse.jetty.alpn alpn-api