[SPDY] Factor out headers into extra class like we did in http and support method chaining where possible
This commit is contained in:
parent
238e03f75b
commit
3843cfd702
@ -62,12 +62,13 @@ public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdyDataFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,8 +77,9 @@ public class DefaultSpdyDataFrame extends DefaultByteBufHolder implements SpdyDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLast(boolean last) {
|
public SpdyDataFrame setLast(boolean last) {
|
||||||
this.last = last;
|
this.last = last;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,12 +61,13 @@ public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLastGoodStreamId(int lastGoodStreamId) {
|
public SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId) {
|
||||||
if (lastGoodStreamId < 0) {
|
if (lastGoodStreamId < 0) {
|
||||||
throw new IllegalArgumentException("Last-good-stream-ID"
|
throw new IllegalArgumentException("Last-good-stream-ID"
|
||||||
+ " cannot be negative: " + lastGoodStreamId);
|
+ " cannot be negative: " + lastGoodStreamId);
|
||||||
}
|
}
|
||||||
this.lastGoodStreamId = lastGoodStreamId;
|
this.lastGoodStreamId = lastGoodStreamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,8 +76,9 @@ public class DefaultSpdyGoAwayFrame implements SpdyGoAwayFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(SpdySessionStatus status) {
|
public SpdyGoAwayFrame setStatus(SpdySessionStatus status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,9 +17,7 @@ package io.netty.handler.codec.spdy;
|
|||||||
|
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default {@link SpdyHeaderBlock} implementation.
|
* The default {@link SpdyHeaderBlock} implementation.
|
||||||
@ -27,7 +25,7 @@ import java.util.Set;
|
|||||||
public class DefaultSpdyHeaderBlock implements SpdyHeaderBlock {
|
public class DefaultSpdyHeaderBlock implements SpdyHeaderBlock {
|
||||||
|
|
||||||
private boolean invalid;
|
private boolean invalid;
|
||||||
private final SpdyHeaders headers = new SpdyHeaders();
|
private final SpdyHeaders headers = new DefaultSpdyHeaders();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
@ -41,62 +39,18 @@ public class DefaultSpdyHeaderBlock implements SpdyHeaderBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInvalid() {
|
public SpdyHeaderBlock setInvalid() {
|
||||||
invalid = true;
|
invalid = true;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addHeader(final String name, final Object value) {
|
public SpdyHeaders headers() {
|
||||||
headers.addHeader(name, value);
|
return headers;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHeader(final String name, final Object value) {
|
|
||||||
headers.setHeader(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHeader(final String name, final Iterable<?> values) {
|
|
||||||
headers.setHeader(name, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeHeader(final String name) {
|
|
||||||
headers.removeHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearHeaders() {
|
|
||||||
headers.clearHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeader(final String name) {
|
|
||||||
return headers.getHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getHeaders(final String name) {
|
|
||||||
return headers.getHeaders(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map.Entry<String, String>> getHeaders() {
|
|
||||||
return headers.getHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsHeader(final String name) {
|
|
||||||
return headers.containsHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getHeaderNames() {
|
|
||||||
return headers.getHeaderNames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void appendHeaders(StringBuilder buf) {
|
protected void appendHeaders(StringBuilder buf) {
|
||||||
for (Map.Entry<String, String> e: getHeaders()) {
|
for (Map.Entry<String, String> e: headers().entries()) {
|
||||||
buf.append(" ");
|
buf.append(" ");
|
||||||
buf.append(e.getKey());
|
buf.append(e.getKey());
|
||||||
buf.append(": ");
|
buf.append(": ");
|
||||||
|
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
* 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.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
|
||||||
|
public class DefaultSpdyHeaders extends SpdyHeaders {
|
||||||
|
|
||||||
|
private static final int BUCKET_SIZE = 17;
|
||||||
|
|
||||||
|
private static int hash(String name) {
|
||||||
|
int h = 0;
|
||||||
|
for (int i = name.length() - 1; i >= 0; i --) {
|
||||||
|
char c = name.charAt(i);
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
c += 32;
|
||||||
|
}
|
||||||
|
h = 31 * h + c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h > 0) {
|
||||||
|
return h;
|
||||||
|
} else if (h == Integer.MIN_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
} else {
|
||||||
|
return -h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean eq(String name1, String name2) {
|
||||||
|
int nameLen = name1.length();
|
||||||
|
if (nameLen != name2.length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = nameLen - 1; i >= 0; i --) {
|
||||||
|
char c1 = name1.charAt(i);
|
||||||
|
char c2 = name2.charAt(i);
|
||||||
|
if (c1 != c2) {
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z') {
|
||||||
|
c1 += 32;
|
||||||
|
}
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z') {
|
||||||
|
c2 += 32;
|
||||||
|
}
|
||||||
|
if (c1 != c2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int index(int hash) {
|
||||||
|
return hash % BUCKET_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final HeaderEntry[] entries = new HeaderEntry[BUCKET_SIZE];
|
||||||
|
private final HeaderEntry head = new HeaderEntry(-1, null, null);
|
||||||
|
|
||||||
|
DefaultSpdyHeaders() {
|
||||||
|
head.before = head.after = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders add(final String name, final Object value) {
|
||||||
|
String lowerCaseName = name.toLowerCase();
|
||||||
|
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
||||||
|
String strVal = toString(value);
|
||||||
|
SpdyCodecUtil.validateHeaderValue(strVal);
|
||||||
|
int h = hash(lowerCaseName);
|
||||||
|
int i = index(h);
|
||||||
|
add0(h, i, lowerCaseName, strVal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add0(int h, int i, final String name, final String value) {
|
||||||
|
// Update the hash table.
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
HeaderEntry newEntry;
|
||||||
|
entries[i] = newEntry = new HeaderEntry(h, name, value);
|
||||||
|
newEntry.next = e;
|
||||||
|
|
||||||
|
// Update the linked list.
|
||||||
|
newEntry.addBefore(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders remove(final String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
String lowerCaseName = name.toLowerCase();
|
||||||
|
int h = hash(lowerCaseName);
|
||||||
|
int i = index(h);
|
||||||
|
remove0(h, i, lowerCaseName);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove0(int h, int i, String name) {
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
if (e == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
e.remove();
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next != null) {
|
||||||
|
entries[i] = next;
|
||||||
|
e = next;
|
||||||
|
} else {
|
||||||
|
entries[i] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.hash == h && eq(name, next.key)) {
|
||||||
|
e.next = next.next;
|
||||||
|
next.remove();
|
||||||
|
} else {
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders set(final String name, final Object value) {
|
||||||
|
String lowerCaseName = name.toLowerCase();
|
||||||
|
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
||||||
|
String strVal = toString(value);
|
||||||
|
SpdyCodecUtil.validateHeaderValue(strVal);
|
||||||
|
int h = hash(lowerCaseName);
|
||||||
|
int i = index(h);
|
||||||
|
remove0(h, i, lowerCaseName);
|
||||||
|
add0(h, i, lowerCaseName, strVal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders set(final String name, final Iterable<?> values) {
|
||||||
|
if (values == null) {
|
||||||
|
throw new NullPointerException("values");
|
||||||
|
}
|
||||||
|
|
||||||
|
String lowerCaseName = name.toLowerCase();
|
||||||
|
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
||||||
|
|
||||||
|
int h = hash(lowerCaseName);
|
||||||
|
int i = index(h);
|
||||||
|
|
||||||
|
remove0(h, i, lowerCaseName);
|
||||||
|
for (Object v: values) {
|
||||||
|
if (v == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String strVal = toString(v);
|
||||||
|
SpdyCodecUtil.validateHeaderValue(strVal);
|
||||||
|
add0(h, i, lowerCaseName, strVal);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders clear() {
|
||||||
|
for (int i = 0; i < entries.length; i ++) {
|
||||||
|
entries[i] = null;
|
||||||
|
}
|
||||||
|
head.before = head.after = head;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(final String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
while (e != null) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
return e.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAll(final String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList<String> values = new LinkedList<String>();
|
||||||
|
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
while (e != null) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
values.addFirst(e.value);
|
||||||
|
}
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map.Entry<String, String>> entries() {
|
||||||
|
List<Map.Entry<String, String>> all =
|
||||||
|
new LinkedList<Map.Entry<String, String>>();
|
||||||
|
|
||||||
|
HeaderEntry e = head.after;
|
||||||
|
while (e != head) {
|
||||||
|
all.add(e);
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(String name) {
|
||||||
|
return get(name) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> names() {
|
||||||
|
Set<String> names = new TreeSet<String>();
|
||||||
|
|
||||||
|
HeaderEntry e = head.after;
|
||||||
|
while (e != head) {
|
||||||
|
names.add(e.key);
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders add(String name, Iterable<?> values) {
|
||||||
|
SpdyCodecUtil.validateHeaderValue(name);
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
for (Object v: values) {
|
||||||
|
String vstr = toString(v);
|
||||||
|
SpdyCodecUtil.validateHeaderValue(vstr);
|
||||||
|
add0(h, i, name, vstr);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return entries().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toString(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class HeaderEntry implements Map.Entry<String, String> {
|
||||||
|
final int hash;
|
||||||
|
final String key;
|
||||||
|
String value;
|
||||||
|
HeaderEntry next;
|
||||||
|
HeaderEntry before, after;
|
||||||
|
|
||||||
|
HeaderEntry(int hash, String key, String value) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove() {
|
||||||
|
before.after = after;
|
||||||
|
after.before = before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBefore(HeaderEntry e) {
|
||||||
|
after = e;
|
||||||
|
before = e.before;
|
||||||
|
before.after = this;
|
||||||
|
after.before = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String setValue(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException("value");
|
||||||
|
}
|
||||||
|
SpdyCodecUtil.validateHeaderValue(value);
|
||||||
|
String oldValue = this.value;
|
||||||
|
this.value = value;
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return key + '=' + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -42,12 +42,13 @@ public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdyHeadersFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,8 +57,15 @@ public class DefaultSpdyHeadersFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLast(boolean last) {
|
public SpdyHeadersFrame setLast(boolean last) {
|
||||||
this.last = last;
|
this.last = last;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeadersFrame setInvalid() {
|
||||||
|
super.setInvalid();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,8 +39,9 @@ public class DefaultSpdyPingFrame implements SpdyPingFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setId(int id) {
|
public SpdyPingFrame setId(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,12 +52,13 @@ public class DefaultSpdyRstStreamFrame implements SpdyRstStreamFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdyRstStreamFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,8 +67,9 @@ public class DefaultSpdyRstStreamFrame implements SpdyRstStreamFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(SpdyStreamStatus status) {
|
public SpdyRstStreamFrame setStatus(SpdyStreamStatus status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -51,12 +51,12 @@ public class DefaultSpdySettingsFrame implements SpdySettingsFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(int id, int value) {
|
public SpdySettingsFrame setValue(int id, int value) {
|
||||||
setValue(id, value, false, false);
|
return setValue(id, value, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(int id, int value, boolean persistValue, boolean persisted) {
|
public SpdySettingsFrame setValue(int id, int value, boolean persistValue, boolean persisted) {
|
||||||
if (id <= 0 || id > SpdyCodecUtil.SPDY_SETTINGS_MAX_ID) {
|
if (id <= 0 || id > SpdyCodecUtil.SPDY_SETTINGS_MAX_ID) {
|
||||||
throw new IllegalArgumentException("Setting ID is not valid: " + id);
|
throw new IllegalArgumentException("Setting ID is not valid: " + id);
|
||||||
}
|
}
|
||||||
@ -69,14 +69,16 @@ public class DefaultSpdySettingsFrame implements SpdySettingsFrame {
|
|||||||
} else {
|
} else {
|
||||||
settingsMap.put(key, new Setting(value, persistValue, persisted));
|
settingsMap.put(key, new Setting(value, persistValue, persisted));
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeValue(int id) {
|
public SpdySettingsFrame removeValue(int id) {
|
||||||
Integer key = Integer.valueOf(id);
|
Integer key = Integer.valueOf(id);
|
||||||
if (settingsMap.containsKey(key)) {
|
if (settingsMap.containsKey(key)) {
|
||||||
settingsMap.remove(key);
|
settingsMap.remove(key);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -90,11 +92,12 @@ public class DefaultSpdySettingsFrame implements SpdySettingsFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPersistValue(int id, boolean persistValue) {
|
public SpdySettingsFrame setPersistValue(int id, boolean persistValue) {
|
||||||
Integer key = Integer.valueOf(id);
|
Integer key = Integer.valueOf(id);
|
||||||
if (settingsMap.containsKey(key)) {
|
if (settingsMap.containsKey(key)) {
|
||||||
settingsMap.get(key).setPersist(persistValue);
|
settingsMap.get(key).setPersist(persistValue);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,11 +111,12 @@ public class DefaultSpdySettingsFrame implements SpdySettingsFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPersisted(int id, boolean persisted) {
|
public SpdySettingsFrame setPersisted(int id, boolean persisted) {
|
||||||
Integer key = Integer.valueOf(id);
|
Integer key = Integer.valueOf(id);
|
||||||
if (settingsMap.containsKey(key)) {
|
if (settingsMap.containsKey(key)) {
|
||||||
settingsMap.get(key).setPersisted(persisted);
|
settingsMap.get(key).setPersisted(persisted);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,8 +125,9 @@ public class DefaultSpdySettingsFrame implements SpdySettingsFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClearPreviouslyPersistedSettings(boolean clear) {
|
public SpdySettingsFrame setClearPreviouslyPersistedSettings(boolean clear) {
|
||||||
this.clear = clear;
|
this.clear = clear;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Map.Entry<Integer, Setting>> getSettings() {
|
private Set<Map.Entry<Integer, Setting>> getSettings() {
|
||||||
|
@ -41,12 +41,13 @@ public class DefaultSpdySynReplyFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdySynReplyFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,8 +56,15 @@ public class DefaultSpdySynReplyFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLast(boolean last) {
|
public SpdySynReplyFrame setLast(boolean last) {
|
||||||
this.last = last;
|
this.last = last;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdySynReplyFrame setInvalid() {
|
||||||
|
super.setInvalid();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,12 +49,13 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdySynStreamFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,13 +64,14 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAssociatedToStreamId(int associatedToStreamId) {
|
public SpdySynStreamFrame setAssociatedToStreamId(int associatedToStreamId) {
|
||||||
if (associatedToStreamId < 0) {
|
if (associatedToStreamId < 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Associated-To-Stream-ID cannot be negative: " +
|
"Associated-To-Stream-ID cannot be negative: " +
|
||||||
associatedToStreamId);
|
associatedToStreamId);
|
||||||
}
|
}
|
||||||
this.associatedToStreamId = associatedToStreamId;
|
this.associatedToStreamId = associatedToStreamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -78,12 +80,13 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPriority(byte priority) {
|
public SpdySynStreamFrame setPriority(byte priority) {
|
||||||
if (priority < 0 || priority > 7) {
|
if (priority < 0 || priority > 7) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Priority must be between 0 and 7 inclusive: " + priority);
|
"Priority must be between 0 and 7 inclusive: " + priority);
|
||||||
}
|
}
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,8 +95,9 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLast(boolean last) {
|
public SpdySynStreamFrame setLast(boolean last) {
|
||||||
this.last = last;
|
this.last = last;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,8 +106,15 @@ public class DefaultSpdySynStreamFrame extends DefaultSpdyHeaderBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUnidirectional(boolean unidirectional) {
|
public SpdySynStreamFrame setUnidirectional(boolean unidirectional) {
|
||||||
this.unidirectional = unidirectional;
|
this.unidirectional = unidirectional;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdySynStreamFrame setInvalid() {
|
||||||
|
super.setInvalid();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,12 +42,13 @@ public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamId(int streamId) {
|
public SpdyWindowUpdateFrame setStreamId(int streamId) {
|
||||||
if (streamId <= 0) {
|
if (streamId <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Stream-ID must be positive: " + streamId);
|
"Stream-ID must be positive: " + streamId);
|
||||||
}
|
}
|
||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,13 +57,14 @@ public class DefaultSpdyWindowUpdateFrame implements SpdyWindowUpdateFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDeltaWindowSize(int deltaWindowSize) {
|
public SpdyWindowUpdateFrame setDeltaWindowSize(int deltaWindowSize) {
|
||||||
if (deltaWindowSize <= 0) {
|
if (deltaWindowSize <= 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Delta-Window-Size must be positive: " +
|
"Delta-Window-Size must be positive: " +
|
||||||
deltaWindowSize);
|
deltaWindowSize);
|
||||||
}
|
}
|
||||||
this.deltaWindowSize = deltaWindowSize;
|
this.deltaWindowSize = deltaWindowSize;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,28 +22,13 @@ import io.netty.buffer.Unpooled;
|
|||||||
/**
|
/**
|
||||||
* A SPDY Protocol Data Frame
|
* A SPDY Protocol Data Frame
|
||||||
*/
|
*/
|
||||||
public interface SpdyDataFrame extends ByteBufHolder {
|
public interface SpdyDataFrame extends ByteBufHolder, SpdyStreamFrame {
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the Stream-ID of this frame.
|
SpdyDataFrame setStreamId(int streamID);
|
||||||
*/
|
|
||||||
int getStreamId();
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
SpdyDataFrame setLast(boolean last);
|
||||||
*/
|
|
||||||
void 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.
|
|
||||||
*/
|
|
||||||
void setLast(boolean last);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data payload of this frame. If there is no data payload
|
* Returns the data payload of this frame. If there is no data payload
|
||||||
|
@ -613,7 +613,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
|
|||||||
String name = new String(nameBytes, "UTF-8");
|
String name = new String(nameBytes, "UTF-8");
|
||||||
|
|
||||||
// Check for identically named headers
|
// Check for identically named headers
|
||||||
if (spdyHeaderBlock.containsHeader(name)) {
|
if (spdyHeaderBlock.headers().contains(name)) {
|
||||||
spdyHeaderBlock.setInvalid();
|
spdyHeaderBlock.setInvalid();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -638,7 +638,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
|
|||||||
spdyHeaderBlock.setInvalid();
|
spdyHeaderBlock.setInvalid();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
spdyHeaderBlock.addHeader(name, "");
|
spdyHeaderBlock.headers().add(name, "");
|
||||||
numHeaders --;
|
numHeaders --;
|
||||||
this.headerSize = headerSize;
|
this.headerSize = headerSize;
|
||||||
continue;
|
continue;
|
||||||
@ -676,7 +676,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder {
|
|||||||
String value = new String(valueBytes, offset, index - offset, "UTF-8");
|
String value = new String(valueBytes, offset, index - offset, "UTF-8");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spdyHeaderBlock.addHeader(name, value);
|
spdyHeaderBlock.headers().add(name, value);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// Name contains NULL or non-ascii characters
|
// Name contains NULL or non-ascii characters
|
||||||
spdyHeaderBlock.setInvalid();
|
spdyHeaderBlock.setInvalid();
|
||||||
|
@ -289,7 +289,7 @@ public class SpdyFrameEncoder extends MessageToByteEncoder<Object> {
|
|||||||
|
|
||||||
private static ByteBuf encodeHeaderBlock(int version, SpdyHeaderBlock headerFrame)
|
private static ByteBuf encodeHeaderBlock(int version, SpdyHeaderBlock headerFrame)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Set<String> names = headerFrame.getHeaderNames();
|
Set<String> names = headerFrame.headers().names();
|
||||||
int numHeaders = names.size();
|
int numHeaders = names.size();
|
||||||
if (numHeaders == 0) {
|
if (numHeaders == 0) {
|
||||||
return Unpooled.EMPTY_BUFFER;
|
return Unpooled.EMPTY_BUFFER;
|
||||||
@ -307,7 +307,7 @@ public class SpdyFrameEncoder extends MessageToByteEncoder<Object> {
|
|||||||
int savedIndex = headerBlock.writerIndex();
|
int savedIndex = headerBlock.writerIndex();
|
||||||
int valueLength = 0;
|
int valueLength = 0;
|
||||||
writeLengthField(version, headerBlock, valueLength);
|
writeLengthField(version, headerBlock, valueLength);
|
||||||
for (String value: headerFrame.getHeaders(name)) {
|
for (String value: headerFrame.headers().getAll(name)) {
|
||||||
byte[] valueBytes = value.getBytes(CharsetUtil.UTF_8);
|
byte[] valueBytes = value.getBytes(CharsetUtil.UTF_8);
|
||||||
if (valueBytes.length > 0) {
|
if (valueBytes.length > 0) {
|
||||||
headerBlock.writeBytes(valueBytes);
|
headerBlock.writeBytes(valueBytes);
|
||||||
|
@ -29,7 +29,7 @@ public interface SpdyGoAwayFrame extends SpdyControlFrame {
|
|||||||
* Sets the Last-good-stream-ID of this frame. The Last-good-stream-ID
|
* Sets the Last-good-stream-ID of this frame. The Last-good-stream-ID
|
||||||
* cannot be negative.
|
* cannot be negative.
|
||||||
*/
|
*/
|
||||||
void setLastGoodStreamId(int lastGoodStreamId);
|
SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the getStatus of this frame.
|
* Returns the getStatus of this frame.
|
||||||
@ -39,5 +39,5 @@ public interface SpdyGoAwayFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets the getStatus of this frame.
|
* Sets the getStatus of this frame.
|
||||||
*/
|
*/
|
||||||
void setStatus(SpdySessionStatus status);
|
SpdyGoAwayFrame setStatus(SpdySessionStatus status);
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SPDY Name/Value Header Block which provides common properties for
|
* A SPDY Name/Value Header Block which provides common properties for
|
||||||
@ -36,68 +33,10 @@ public interface SpdyHeaderBlock {
|
|||||||
/**
|
/**
|
||||||
* Marks this header block as invalid.
|
* Marks this header block as invalid.
|
||||||
*/
|
*/
|
||||||
void setInvalid();
|
SpdyHeaderBlock setInvalid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the header value with the specified header name. If there is
|
* Returns the {@link SpdyHeaders}.
|
||||||
* more than one header value for the specified header name, the first
|
|
||||||
* value is returned.
|
|
||||||
*
|
|
||||||
* @return the header value or {@code null} if there is no such header
|
|
||||||
*/
|
*/
|
||||||
String getHeader(String name);
|
SpdyHeaders headers();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the header values with the specified header name.
|
|
||||||
*
|
|
||||||
* @return the {@link List} of header values. An empty list if there is no
|
|
||||||
* such header.
|
|
||||||
*/
|
|
||||||
List<String> getHeaders(String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all header names and values that this block contains.
|
|
||||||
*
|
|
||||||
* @return the {@link List} of the header name-value pairs. An empty list
|
|
||||||
* if there is no header in this message.
|
|
||||||
*/
|
|
||||||
List<Map.Entry<String, String>> getHeaders();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns {@code true} if and only if there is a header with the specified
|
|
||||||
* header name.
|
|
||||||
*/
|
|
||||||
boolean containsHeader(String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link Set} of all header names that this block contains.
|
|
||||||
*/
|
|
||||||
Set<String> getHeaderNames();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new header with the specified name and value.
|
|
||||||
*/
|
|
||||||
void addHeader(String name, Object value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a new header with the specified name and value. If there is an
|
|
||||||
* existing header with the same name, the existing header is removed.
|
|
||||||
*/
|
|
||||||
void setHeader(String name, Object value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a new header with the specified name and values. If there is an
|
|
||||||
* existing header with the same name, the existing header is removed.
|
|
||||||
*/
|
|
||||||
void setHeader(String name, Iterable<?> values);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the header with the specified name.
|
|
||||||
*/
|
|
||||||
void removeHeader(String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all headers from this block.
|
|
||||||
*/
|
|
||||||
void clearHeaders();
|
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,86 @@ import io.netty.handler.codec.http.HttpMethod;
|
|||||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||||
import io.netty.handler.codec.http.HttpVersion;
|
import io.netty.handler.codec.http.HttpVersion;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the constants for the standard SPDY HTTP header names and commonly
|
* Provides the constants for the standard SPDY HTTP header names and commonly
|
||||||
* used utility methods that access a {@link SpdyHeaderBlock}.
|
* used utility methods that access a {@link SpdyHeaderBlock}.
|
||||||
* @apiviz.stereotype static
|
* @apiviz.stereotype static
|
||||||
*/
|
*/
|
||||||
public class SpdyHeaders {
|
public abstract class SpdyHeaders implements Iterable<Map.Entry<String, String>> {
|
||||||
|
|
||||||
|
public static final SpdyHeaders EMPTY_HEADERS = new SpdyHeaders() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAll(String name) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map.Entry<String, String>> entries() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(String name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> names() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders add(String name, Object value) {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders add(String name, Iterable<?> values) {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders set(String name, Object value) {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders set(String name, Iterable<?> values) {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders remove(String name) {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpdyHeaders clear() {
|
||||||
|
throw new UnsupportedOperationException("read only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String, String>> iterator() {
|
||||||
|
return entries().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SPDY HTTP header names
|
* SPDY HTTP header names
|
||||||
@ -102,7 +170,7 @@ public class SpdyHeaders {
|
|||||||
* @return the header value or {@code null} if there is no such header
|
* @return the header value or {@code null} if there is no such header
|
||||||
*/
|
*/
|
||||||
public static String getHeader(SpdyHeaderBlock block, String name) {
|
public static String getHeader(SpdyHeaderBlock block, String name) {
|
||||||
return block.getHeader(name);
|
return block.headers().get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,7 +182,7 @@ public class SpdyHeaders {
|
|||||||
* header
|
* header
|
||||||
*/
|
*/
|
||||||
public static String getHeader(SpdyHeaderBlock block, String name, String defaultValue) {
|
public static String getHeader(SpdyHeaderBlock block, String name, String defaultValue) {
|
||||||
String value = block.getHeader(name);
|
String value = block.headers().get(name);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
@ -126,7 +194,7 @@ public class SpdyHeaders {
|
|||||||
* existing header with the same name, the existing header is removed.
|
* existing header with the same name, the existing header is removed.
|
||||||
*/
|
*/
|
||||||
public static void setHeader(SpdyHeaderBlock block, String name, Object value) {
|
public static void setHeader(SpdyHeaderBlock block, String name, Object value) {
|
||||||
block.setHeader(name, value);
|
block.headers().set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,35 +202,35 @@ public class SpdyHeaders {
|
|||||||
* existing header with the same name, the existing header is removed.
|
* existing header with the same name, the existing header is removed.
|
||||||
*/
|
*/
|
||||||
public static void setHeader(SpdyHeaderBlock block, String name, Iterable<?> values) {
|
public static void setHeader(SpdyHeaderBlock block, String name, Iterable<?> values) {
|
||||||
block.setHeader(name, values);
|
block.headers().set(name, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new header with the specified name and value.
|
* Adds a new header with the specified name and value.
|
||||||
*/
|
*/
|
||||||
public static void addHeader(SpdyHeaderBlock block, String name, Object value) {
|
public static void addHeader(SpdyHeaderBlock block, String name, Object value) {
|
||||||
block.addHeader(name, value);
|
block.headers().add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the SPDY host header.
|
* Removes the SPDY host header.
|
||||||
*/
|
*/
|
||||||
public static void removeHost(SpdyHeaderBlock block) {
|
public static void removeHost(SpdyHeaderBlock block) {
|
||||||
block.removeHeader(HttpNames.HOST);
|
block.headers().remove(HttpNames.HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SPDY host header.
|
* Returns the SPDY host header.
|
||||||
*/
|
*/
|
||||||
public static String getHost(SpdyHeaderBlock block) {
|
public static String getHost(SpdyHeaderBlock block) {
|
||||||
return block.getHeader(HttpNames.HOST);
|
return block.headers().get(HttpNames.HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the SPDY host header.
|
* Set the SPDY host header.
|
||||||
*/
|
*/
|
||||||
public static void setHost(SpdyHeaderBlock block, String host) {
|
public static void setHost(SpdyHeaderBlock block, String host) {
|
||||||
block.setHeader(HttpNames.HOST, host);
|
block.headers().set(HttpNames.HOST, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,9 +238,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void removeMethod(int spdyVersion, SpdyHeaderBlock block) {
|
public static void removeMethod(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.removeHeader(Spdy2HttpNames.METHOD);
|
block.headers().remove(Spdy2HttpNames.METHOD);
|
||||||
} else {
|
} else {
|
||||||
block.removeHeader(HttpNames.METHOD);
|
block.headers().remove(HttpNames.METHOD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,9 +250,9 @@ public class SpdyHeaders {
|
|||||||
public static HttpMethod getMethod(int spdyVersion, SpdyHeaderBlock block) {
|
public static HttpMethod getMethod(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
try {
|
try {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
return HttpMethod.valueOf(block.getHeader(Spdy2HttpNames.METHOD));
|
return HttpMethod.valueOf(block.headers().get(Spdy2HttpNames.METHOD));
|
||||||
} else {
|
} else {
|
||||||
return HttpMethod.valueOf(block.getHeader(HttpNames.METHOD));
|
return HttpMethod.valueOf(block.headers().get(HttpNames.METHOD));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
@ -196,9 +264,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void setMethod(int spdyVersion, SpdyHeaderBlock block, HttpMethod method) {
|
public static void setMethod(int spdyVersion, SpdyHeaderBlock block, HttpMethod method) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.setHeader(Spdy2HttpNames.METHOD, method.name());
|
block.headers().set(Spdy2HttpNames.METHOD, method.name());
|
||||||
} else {
|
} else {
|
||||||
block.setHeader(HttpNames.METHOD, method.name());
|
block.headers().set(HttpNames.METHOD, method.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,9 +275,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void removeScheme(int spdyVersion, SpdyHeaderBlock block) {
|
public static void removeScheme(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 2) {
|
if (spdyVersion < 2) {
|
||||||
block.removeHeader(Spdy2HttpNames.SCHEME);
|
block.headers().remove(Spdy2HttpNames.SCHEME);
|
||||||
} else {
|
} else {
|
||||||
block.removeHeader(HttpNames.SCHEME);
|
block.headers().remove(HttpNames.SCHEME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,9 +286,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static String getScheme(int spdyVersion, SpdyHeaderBlock block) {
|
public static String getScheme(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
return block.getHeader(Spdy2HttpNames.SCHEME);
|
return block.headers().get(Spdy2HttpNames.SCHEME);
|
||||||
} else {
|
} else {
|
||||||
return block.getHeader(HttpNames.SCHEME);
|
return block.headers().get(HttpNames.SCHEME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,9 +297,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void setScheme(int spdyVersion, SpdyHeaderBlock block, String scheme) {
|
public static void setScheme(int spdyVersion, SpdyHeaderBlock block, String scheme) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.setHeader(Spdy2HttpNames.SCHEME, scheme);
|
block.headers().set(Spdy2HttpNames.SCHEME, scheme);
|
||||||
} else {
|
} else {
|
||||||
block.setHeader(HttpNames.SCHEME, scheme);
|
block.headers().set(HttpNames.SCHEME, scheme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,9 +308,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void removeStatus(int spdyVersion, SpdyHeaderBlock block) {
|
public static void removeStatus(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.removeHeader(Spdy2HttpNames.STATUS);
|
block.headers().remove(Spdy2HttpNames.STATUS);
|
||||||
} else {
|
} else {
|
||||||
block.removeHeader(HttpNames.STATUS);
|
block.headers().remove(HttpNames.STATUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,9 +321,9 @@ public class SpdyHeaders {
|
|||||||
try {
|
try {
|
||||||
String status;
|
String status;
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
status = block.getHeader(Spdy2HttpNames.STATUS);
|
status = block.headers().get(Spdy2HttpNames.STATUS);
|
||||||
} else {
|
} else {
|
||||||
status = block.getHeader(HttpNames.STATUS);
|
status = block.headers().get(HttpNames.STATUS);
|
||||||
}
|
}
|
||||||
int space = status.indexOf(' ');
|
int space = status.indexOf(' ');
|
||||||
if (space == -1) {
|
if (space == -1) {
|
||||||
@ -280,9 +348,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void setStatus(int spdyVersion, SpdyHeaderBlock block, HttpResponseStatus status) {
|
public static void setStatus(int spdyVersion, SpdyHeaderBlock block, HttpResponseStatus status) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.setHeader(Spdy2HttpNames.STATUS, status.toString());
|
block.headers().set(Spdy2HttpNames.STATUS, status.toString());
|
||||||
} else {
|
} else {
|
||||||
block.setHeader(HttpNames.STATUS, status.toString());
|
block.headers().set(HttpNames.STATUS, status.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,9 +359,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void removeUrl(int spdyVersion, SpdyHeaderBlock block) {
|
public static void removeUrl(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.removeHeader(Spdy2HttpNames.URL);
|
block.headers().remove(Spdy2HttpNames.URL);
|
||||||
} else {
|
} else {
|
||||||
block.removeHeader(HttpNames.PATH);
|
block.headers().remove(HttpNames.PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,9 +370,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static String getUrl(int spdyVersion, SpdyHeaderBlock block) {
|
public static String getUrl(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
return block.getHeader(Spdy2HttpNames.URL);
|
return block.headers().get(Spdy2HttpNames.URL);
|
||||||
} else {
|
} else {
|
||||||
return block.getHeader(HttpNames.PATH);
|
return block.headers().get(HttpNames.PATH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,9 +381,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void setUrl(int spdyVersion, SpdyHeaderBlock block, String path) {
|
public static void setUrl(int spdyVersion, SpdyHeaderBlock block, String path) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.setHeader(Spdy2HttpNames.URL, path);
|
block.headers().set(Spdy2HttpNames.URL, path);
|
||||||
} else {
|
} else {
|
||||||
block.setHeader(HttpNames.PATH, path);
|
block.headers().set(HttpNames.PATH, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,9 +392,9 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void removeVersion(int spdyVersion, SpdyHeaderBlock block) {
|
public static void removeVersion(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.removeHeader(Spdy2HttpNames.VERSION);
|
block.headers().remove(Spdy2HttpNames.VERSION);
|
||||||
} else {
|
} else {
|
||||||
block.removeHeader(HttpNames.VERSION);
|
block.headers().remove(HttpNames.VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,9 +404,9 @@ public class SpdyHeaders {
|
|||||||
public static HttpVersion getVersion(int spdyVersion, SpdyHeaderBlock block) {
|
public static HttpVersion getVersion(int spdyVersion, SpdyHeaderBlock block) {
|
||||||
try {
|
try {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
return HttpVersion.valueOf(block.getHeader(Spdy2HttpNames.VERSION));
|
return HttpVersion.valueOf(block.headers().get(Spdy2HttpNames.VERSION));
|
||||||
} else {
|
} else {
|
||||||
return HttpVersion.valueOf(block.getHeader(HttpNames.VERSION));
|
return HttpVersion.valueOf(block.headers().get(HttpNames.VERSION));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
@ -350,295 +418,87 @@ public class SpdyHeaders {
|
|||||||
*/
|
*/
|
||||||
public static void setVersion(int spdyVersion, SpdyHeaderBlock block, HttpVersion httpVersion) {
|
public static void setVersion(int spdyVersion, SpdyHeaderBlock block, HttpVersion httpVersion) {
|
||||||
if (spdyVersion < 3) {
|
if (spdyVersion < 3) {
|
||||||
block.setHeader(Spdy2HttpNames.VERSION, httpVersion.text());
|
block.headers().set(Spdy2HttpNames.VERSION, httpVersion.text());
|
||||||
} else {
|
} else {
|
||||||
block.setHeader(HttpNames.VERSION, httpVersion.text());
|
block.headers().set(HttpNames.VERSION, httpVersion.text());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
private static final int BUCKET_SIZE = 17;
|
public Iterator<Map.Entry<String, String>> iterator() {
|
||||||
|
return entries().iterator();
|
||||||
private static int hash(String name) {
|
|
||||||
int h = 0;
|
|
||||||
for (int i = name.length() - 1; i >= 0; i --) {
|
|
||||||
char c = name.charAt(i);
|
|
||||||
if (c >= 'A' && c <= 'Z') {
|
|
||||||
c += 32;
|
|
||||||
}
|
|
||||||
h = 31 * h + c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h > 0) {
|
|
||||||
return h;
|
|
||||||
} else if (h == Integer.MIN_VALUE) {
|
|
||||||
return Integer.MAX_VALUE;
|
|
||||||
} else {
|
|
||||||
return -h;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean eq(String name1, String name2) {
|
/**
|
||||||
int nameLen = name1.length();
|
* Returns the header value with the specified header name. If there is
|
||||||
if (nameLen != name2.length()) {
|
* more than one header value for the specified header name, the first
|
||||||
return false;
|
* value is returned.
|
||||||
}
|
*
|
||||||
|
* @return the header value or {@code null} if there is no such header
|
||||||
|
*/
|
||||||
|
public abstract String get(String name);
|
||||||
|
|
||||||
for (int i = nameLen - 1; i >= 0; i --) {
|
/**
|
||||||
char c1 = name1.charAt(i);
|
* Returns the header values with the specified header name.
|
||||||
char c2 = name2.charAt(i);
|
*
|
||||||
if (c1 != c2) {
|
* @return the {@link List} of header values. An empty list if there is no
|
||||||
if (c1 >= 'A' && c1 <= 'Z') {
|
* such header.
|
||||||
c1 += 32;
|
*/
|
||||||
}
|
public abstract List<String> getAll(String name);
|
||||||
if (c2 >= 'A' && c2 <= 'Z') {
|
|
||||||
c2 += 32;
|
|
||||||
}
|
|
||||||
if (c1 != c2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int index(int hash) {
|
/**
|
||||||
return hash % BUCKET_SIZE;
|
* Returns all header names and values that this block contains.
|
||||||
}
|
*
|
||||||
|
* @return the {@link List} of the header name-value pairs. An empty list
|
||||||
|
* if there is no header in this message.
|
||||||
|
*/
|
||||||
|
public abstract List<Map.Entry<String, String>> entries();
|
||||||
|
|
||||||
private final HeaderEntry[] entries = new HeaderEntry[BUCKET_SIZE];
|
/**
|
||||||
private final HeaderEntry head = new HeaderEntry(-1, null, null);
|
* Returns {@code true} if and only if there is a header with the specified
|
||||||
|
* header name.
|
||||||
|
*/
|
||||||
|
public abstract boolean contains(String name);
|
||||||
|
|
||||||
SpdyHeaders() {
|
/**
|
||||||
head.before = head.after = head;
|
* Returns the {@link Set} of all header names that this block contains.
|
||||||
}
|
*/
|
||||||
|
public abstract Set<String> names();
|
||||||
|
|
||||||
void addHeader(final String name, final Object value) {
|
/**
|
||||||
String lowerCaseName = name.toLowerCase();
|
* Adds a new header with the specified name and value.
|
||||||
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
*/
|
||||||
String strVal = toString(value);
|
public abstract SpdyHeaders add(String name, Object value);
|
||||||
SpdyCodecUtil.validateHeaderValue(strVal);
|
|
||||||
int h = hash(lowerCaseName);
|
|
||||||
int i = index(h);
|
|
||||||
addHeader0(h, i, lowerCaseName, strVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addHeader0(int h, int i, final String name, final String value) {
|
/**
|
||||||
// Update the hash table.
|
* Adds a new header with the specified name and values. If there is an
|
||||||
HeaderEntry e = entries[i];
|
* existing header with the same name, the existing header is removed.
|
||||||
HeaderEntry newEntry;
|
*/
|
||||||
entries[i] = newEntry = new HeaderEntry(h, name, value);
|
public abstract SpdyHeaders add(String name, Iterable<?> values);
|
||||||
newEntry.next = e;
|
|
||||||
|
|
||||||
// Update the linked list.
|
/**
|
||||||
newEntry.addBefore(head);
|
* Sets a new header with the specified name and value. If there is an
|
||||||
}
|
* existing header with the same name, the existing header is removed.
|
||||||
|
*/
|
||||||
|
public abstract SpdyHeaders set(String name, Object value);
|
||||||
|
|
||||||
void removeHeader(final String name) {
|
/**
|
||||||
if (name == null) {
|
* Sets a new header with the specified name and values. If there is an
|
||||||
throw new NullPointerException("name");
|
* existing header with the same name, the existing header is removed.
|
||||||
}
|
*/
|
||||||
String lowerCaseName = name.toLowerCase();
|
public abstract SpdyHeaders set(String name, Iterable<?> values);
|
||||||
int h = hash(lowerCaseName);
|
|
||||||
int i = index(h);
|
|
||||||
removeHeader0(h, i, lowerCaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeHeader0(int h, int i, String name) {
|
/**
|
||||||
HeaderEntry e = entries[i];
|
* Removes the header with the specified name.
|
||||||
if (e == null) {
|
*/
|
||||||
return;
|
public abstract SpdyHeaders remove(String name);
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
/**
|
||||||
if (e.hash == h && eq(name, e.key)) {
|
* Removes all headers from this block.
|
||||||
e.remove();
|
*/
|
||||||
HeaderEntry next = e.next;
|
public abstract SpdyHeaders clear();
|
||||||
if (next != null) {
|
|
||||||
entries[i] = next;
|
|
||||||
e = next;
|
|
||||||
} else {
|
|
||||||
entries[i] = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
/**
|
||||||
HeaderEntry next = e.next;
|
* Checks if no header exists.
|
||||||
if (next == null) {
|
*/
|
||||||
break;
|
public abstract boolean isEmpty();
|
||||||
}
|
|
||||||
if (next.hash == h && eq(name, next.key)) {
|
|
||||||
e.next = next.next;
|
|
||||||
next.remove();
|
|
||||||
} else {
|
|
||||||
e = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHeader(final String name, final Object value) {
|
|
||||||
String lowerCaseName = name.toLowerCase();
|
|
||||||
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
|
||||||
String strVal = toString(value);
|
|
||||||
SpdyCodecUtil.validateHeaderValue(strVal);
|
|
||||||
int h = hash(lowerCaseName);
|
|
||||||
int i = index(h);
|
|
||||||
removeHeader0(h, i, lowerCaseName);
|
|
||||||
addHeader0(h, i, lowerCaseName, strVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHeader(final String name, final Iterable<?> values) {
|
|
||||||
if (values == null) {
|
|
||||||
throw new NullPointerException("values");
|
|
||||||
}
|
|
||||||
|
|
||||||
String lowerCaseName = name.toLowerCase();
|
|
||||||
SpdyCodecUtil.validateHeaderName(lowerCaseName);
|
|
||||||
|
|
||||||
int h = hash(lowerCaseName);
|
|
||||||
int i = index(h);
|
|
||||||
|
|
||||||
removeHeader0(h, i, lowerCaseName);
|
|
||||||
for (Object v: values) {
|
|
||||||
if (v == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
String strVal = toString(v);
|
|
||||||
SpdyCodecUtil.validateHeaderValue(strVal);
|
|
||||||
addHeader0(h, i, lowerCaseName, strVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearHeaders() {
|
|
||||||
for (int i = 0; i < entries.length; i ++) {
|
|
||||||
entries[i] = null;
|
|
||||||
}
|
|
||||||
head.before = head.after = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getHeader(final String name) {
|
|
||||||
if (name == null) {
|
|
||||||
throw new NullPointerException("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
int h = hash(name);
|
|
||||||
int i = index(h);
|
|
||||||
HeaderEntry e = entries[i];
|
|
||||||
while (e != null) {
|
|
||||||
if (e.hash == h && eq(name, e.key)) {
|
|
||||||
return e.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> getHeaders(final String name) {
|
|
||||||
if (name == null) {
|
|
||||||
throw new NullPointerException("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedList<String> values = new LinkedList<String>();
|
|
||||||
|
|
||||||
int h = hash(name);
|
|
||||||
int i = index(h);
|
|
||||||
HeaderEntry e = entries[i];
|
|
||||||
while (e != null) {
|
|
||||||
if (e.hash == h && eq(name, e.key)) {
|
|
||||||
values.addFirst(e.value);
|
|
||||||
}
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map.Entry<String, String>> getHeaders() {
|
|
||||||
List<Map.Entry<String, String>> all =
|
|
||||||
new LinkedList<Map.Entry<String, String>>();
|
|
||||||
|
|
||||||
HeaderEntry e = head.after;
|
|
||||||
while (e != head) {
|
|
||||||
all.add(e);
|
|
||||||
e = e.after;
|
|
||||||
}
|
|
||||||
return all;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean containsHeader(String name) {
|
|
||||||
return getHeader(name) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> getHeaderNames() {
|
|
||||||
Set<String> names = new TreeSet<String>();
|
|
||||||
|
|
||||||
HeaderEntry e = head.after;
|
|
||||||
while (e != head) {
|
|
||||||
names.add(e.key);
|
|
||||||
e = e.after;
|
|
||||||
}
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toString(Object value) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class HeaderEntry implements Map.Entry<String, String> {
|
|
||||||
final int hash;
|
|
||||||
final String key;
|
|
||||||
String value;
|
|
||||||
HeaderEntry next;
|
|
||||||
HeaderEntry before, after;
|
|
||||||
|
|
||||||
HeaderEntry(int hash, String key, String value) {
|
|
||||||
this.hash = hash;
|
|
||||||
this.key = key;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove() {
|
|
||||||
before.after = after;
|
|
||||||
after.before = before;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addBefore(HeaderEntry e) {
|
|
||||||
after = e;
|
|
||||||
before = e.before;
|
|
||||||
before.after = this;
|
|
||||||
after.before = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String setValue(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
throw new NullPointerException("value");
|
|
||||||
}
|
|
||||||
SpdyCodecUtil.validateHeaderValue(value);
|
|
||||||
String oldValue = this.value;
|
|
||||||
this.value = value;
|
|
||||||
return oldValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return key + '=' + value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,26 +18,15 @@ package io.netty.handler.codec.spdy;
|
|||||||
/**
|
/**
|
||||||
* A SPDY Protocol HEADERS Control Frame
|
* A SPDY Protocol HEADERS Control Frame
|
||||||
*/
|
*/
|
||||||
public interface SpdyHeadersFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
public interface SpdyHeadersFrame extends SpdyHeaderBlock, SpdyControlFrame, SpdyStreamFrame {
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the Stream-ID of this frame.
|
SpdyHeadersFrame setStreamId(int streamID);
|
||||||
*/
|
|
||||||
int getStreamId();
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
SpdyHeadersFrame setLast(boolean last);
|
||||||
*/
|
|
||||||
void setStreamId(int streamID);
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns {@code true} if this frame is the last frame to be transmitted
|
SpdyHeadersFrame setInvalid();
|
||||||
* on the stream.
|
|
||||||
*/
|
|
||||||
boolean isLast();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if this frame is the last frame to be transmitted on the stream.
|
|
||||||
*/
|
|
||||||
void setLast(boolean last);
|
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<Object> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> e: spdyHeadersFrame.getHeaders()) {
|
for (Map.Entry<String, String> e: spdyHeadersFrame.headers().entries()) {
|
||||||
httpMessage.headers().add(e.getKey(), e.getValue());
|
httpMessage.headers().add(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<Object> {
|
|||||||
HttpHeaders.setHost(req, host);
|
HttpHeaders.setHost(req, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> e: requestFrame.getHeaders()) {
|
for (Map.Entry<String, String> e: requestFrame.headers().entries()) {
|
||||||
req.headers().add(e.getKey(), e.getValue());
|
req.headers().add(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<Object> {
|
|||||||
SpdyHeaders.removeVersion(spdyVersion, responseFrame);
|
SpdyHeaders.removeVersion(spdyVersion, responseFrame);
|
||||||
|
|
||||||
FullHttpResponse res = new DefaultFullHttpResponse(version, status);
|
FullHttpResponse res = new DefaultFullHttpResponse(version, status);
|
||||||
for (Map.Entry<String, String> e: responseFrame.getHeaders()) {
|
for (Map.Entry<String, String> e: responseFrame.headers().entries()) {
|
||||||
res.headers().add(e.getKey(), e.getValue());
|
res.headers().add(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<Object> {
|
|||||||
// Create SPDY HEADERS frame out of trailers
|
// Create SPDY HEADERS frame out of trailers
|
||||||
SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(currentStreamId);
|
SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(currentStreamId);
|
||||||
for (Map.Entry<String, String> entry: trailers) {
|
for (Map.Entry<String, String> entry: trailers) {
|
||||||
spdyHeadersFrame.addHeader(entry.getKey(), entry.getValue());
|
spdyHeadersFrame.headers().add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write HEADERS frame and append Data Frame
|
// Write HEADERS frame and append Data Frame
|
||||||
@ -246,7 +246,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<Object> {
|
|||||||
|
|
||||||
// Transfer the remaining HTTP headers
|
// Transfer the remaining HTTP headers
|
||||||
for (Map.Entry<String, String> entry: httpMessage.headers()) {
|
for (Map.Entry<String, String> entry: httpMessage.headers()) {
|
||||||
spdySynStreamFrame.addHeader(entry.getKey(), entry.getValue());
|
spdySynStreamFrame.headers().add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
currentStreamId = spdySynStreamFrame.getStreamId();
|
currentStreamId = spdySynStreamFrame.getStreamId();
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder<Object> {
|
|||||||
|
|
||||||
// Transfer the remaining HTTP headers
|
// Transfer the remaining HTTP headers
|
||||||
for (Map.Entry<String, String> entry: httpResponse.headers()) {
|
for (Map.Entry<String, String> entry: httpResponse.headers()) {
|
||||||
spdySynReplyFrame.addHeader(entry.getKey(), entry.getValue());
|
spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunked) {
|
if (chunked) {
|
||||||
|
@ -28,5 +28,5 @@ public interface SpdyPingFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets the ID of this frame.
|
* Sets the ID of this frame.
|
||||||
*/
|
*/
|
||||||
void setId(int id);
|
SpdyPingFrame setId(int id);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public interface SpdyRstStreamFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
||||||
*/
|
*/
|
||||||
void setStreamId(int streamID);
|
SpdyControlFrame setStreamId(int streamID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the getStatus of this frame.
|
* Returns the getStatus of this frame.
|
||||||
@ -38,5 +38,5 @@ public interface SpdyRstStreamFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets the getStatus of this frame.
|
* Sets the getStatus of this frame.
|
||||||
*/
|
*/
|
||||||
void setStatus(SpdyStreamStatus status);
|
SpdyControlFrame setStatus(SpdyStreamStatus status);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ public interface SpdySettingsFrame extends SpdyControlFrame {
|
|||||||
* Sets the value of the setting ID.
|
* Sets the value of the setting ID.
|
||||||
* The ID must be positive and cannot exceed 16777215.
|
* The ID must be positive and cannot exceed 16777215.
|
||||||
*/
|
*/
|
||||||
void setValue(int id, int value);
|
SpdySettingsFrame setValue(int id, int value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the setting ID.
|
* Sets the value of the setting ID.
|
||||||
@ -60,13 +60,13 @@ public interface SpdySettingsFrame extends SpdyControlFrame {
|
|||||||
* Sets if the setting is persisted (should only be set by the client).
|
* Sets if the setting is persisted (should only be set by the client).
|
||||||
* The ID must be positive and cannot exceed 16777215.
|
* The ID must be positive and cannot exceed 16777215.
|
||||||
*/
|
*/
|
||||||
void setValue(int id, int value, boolean persistVal, boolean persisted);
|
SpdySettingsFrame setValue(int id, int value, boolean persistVal, boolean persisted);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the value of the setting ID.
|
* Removes the value of the setting ID.
|
||||||
* Removes all persistence information for the setting.
|
* Removes all persistence information for the setting.
|
||||||
*/
|
*/
|
||||||
void removeValue(int id);
|
SpdySettingsFrame removeValue(int id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if this setting should be persisted.
|
* Returns {@code true} if this setting should be persisted.
|
||||||
@ -79,7 +79,7 @@ public interface SpdySettingsFrame extends SpdyControlFrame {
|
|||||||
* Sets if this setting should be persisted.
|
* Sets if this setting should be persisted.
|
||||||
* Has no effect if the setting ID has no value.
|
* Has no effect if the setting ID has no value.
|
||||||
*/
|
*/
|
||||||
void setPersistValue(int id, boolean persistValue);
|
SpdySettingsFrame setPersistValue(int id, boolean persistValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if this setting is persisted.
|
* Returns {@code true} if this setting is persisted.
|
||||||
@ -92,7 +92,7 @@ public interface SpdySettingsFrame extends SpdyControlFrame {
|
|||||||
* Sets if this setting is persisted.
|
* Sets if this setting is persisted.
|
||||||
* Has no effect if the setting ID has no value.
|
* Has no effect if the setting ID has no value.
|
||||||
*/
|
*/
|
||||||
void setPersisted(int id, boolean persisted);
|
SpdySettingsFrame setPersisted(int id, boolean persisted);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if previously persisted settings should be cleared.
|
* Returns {@code true} if previously persisted settings should be cleared.
|
||||||
@ -102,5 +102,5 @@ public interface SpdySettingsFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets if previously persisted settings should be cleared.
|
* Sets if previously persisted settings should be cleared.
|
||||||
*/
|
*/
|
||||||
void setClearPreviouslyPersistedSettings(boolean clear);
|
SpdySettingsFrame setClearPreviouslyPersistedSettings(boolean clear);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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 frame which is part of a stream
|
||||||
|
*/
|
||||||
|
public interface SpdyStreamFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Stream-ID of this frame.
|
||||||
|
*/
|
||||||
|
int getStreamId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
@ -18,26 +18,14 @@ package io.netty.handler.codec.spdy;
|
|||||||
/**
|
/**
|
||||||
* A SPDY Protocol SYN_REPLY Control Frame
|
* A SPDY Protocol SYN_REPLY Control Frame
|
||||||
*/
|
*/
|
||||||
public interface SpdySynReplyFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
public interface SpdySynReplyFrame extends SpdyHeaderBlock, SpdyControlFrame, SpdyStreamFrame {
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the Stream-ID of this frame.
|
SpdySynReplyFrame setStreamId(int streamID);
|
||||||
*/
|
|
||||||
int getStreamId();
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
SpdySynReplyFrame setLast(boolean last);
|
||||||
*/
|
|
||||||
void setStreamId(int streamID);
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns {@code true} if this frame is the last frame to be transmitted
|
SpdySynReplyFrame setInvalid();
|
||||||
* on the stream.
|
|
||||||
*/
|
|
||||||
boolean isLast();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if this frame is the last frame to be transmitted on the stream.
|
|
||||||
*/
|
|
||||||
void setLast(boolean last);
|
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,7 @@ package io.netty.handler.codec.spdy;
|
|||||||
/**
|
/**
|
||||||
* A SPDY Protocol SYN_STREAM Control Frame
|
* A SPDY Protocol SYN_STREAM Control Frame
|
||||||
*/
|
*/
|
||||||
public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame , SpdyStreamFrame {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Stream-ID of this frame.
|
|
||||||
*/
|
|
||||||
int getStreamId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
|
||||||
*/
|
|
||||||
void setStreamId(int streamId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Associated-To-Stream-ID of this frame.
|
* Returns the Associated-To-Stream-ID of this frame.
|
||||||
@ -39,7 +29,7 @@ public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
|||||||
* Sets the Associated-To-Stream-ID of this frame.
|
* Sets the Associated-To-Stream-ID of this frame.
|
||||||
* The Associated-To-Stream-ID cannot be negative.
|
* The Associated-To-Stream-ID cannot be negative.
|
||||||
*/
|
*/
|
||||||
void setAssociatedToStreamId(int associatedToStreamId);
|
SpdySynStreamFrame setAssociatedToStreamId(int associatedToStreamId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority of the stream.
|
* Returns the priority of the stream.
|
||||||
@ -50,18 +40,7 @@ public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
|||||||
* Sets the priority of the stream.
|
* Sets the priority of the stream.
|
||||||
* The priority must be between 0 and 7 inclusive.
|
* The priority must be between 0 and 7 inclusive.
|
||||||
*/
|
*/
|
||||||
void setPriority(byte priority);
|
SpdySynStreamFrame setPriority(byte priority);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
void setLast(boolean last);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the stream created with this frame is to be
|
* Returns {@code true} if the stream created with this frame is to be
|
||||||
@ -73,5 +52,14 @@ public interface SpdySynStreamFrame extends SpdyHeaderBlock, SpdyControlFrame {
|
|||||||
* Sets if the stream created with this frame is to be considered
|
* Sets if the stream created with this frame is to be considered
|
||||||
* half-closed to the receiver.
|
* half-closed to the receiver.
|
||||||
*/
|
*/
|
||||||
void setUnidirectional(boolean unidirectional);
|
SpdySynStreamFrame setUnidirectional(boolean unidirectional);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SpdySynStreamFrame setStreamId(int streamID);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SpdySynStreamFrame setLast(boolean last);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SpdySynStreamFrame setInvalid();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public interface SpdyWindowUpdateFrame extends SpdyControlFrame {
|
|||||||
/**
|
/**
|
||||||
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
* Sets the Stream-ID of this frame. The Stream-ID must be positive.
|
||||||
*/
|
*/
|
||||||
void setStreamId(int streamID);
|
SpdyWindowUpdateFrame setStreamId(int streamID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Delta-Window-Size of this frame.
|
* Returns the Delta-Window-Size of this frame.
|
||||||
@ -39,5 +39,5 @@ public interface SpdyWindowUpdateFrame extends SpdyControlFrame {
|
|||||||
* Sets the Delta-Window-Size of this frame.
|
* Sets the Delta-Window-Size of this frame.
|
||||||
* The Delta-Window-Size must be positive.
|
* The Delta-Window-Size must be positive.
|
||||||
*/
|
*/
|
||||||
void setDeltaWindowSize(int deltaWindowSize);
|
SpdyWindowUpdateFrame setDeltaWindowSize(int deltaWindowSize);
|
||||||
}
|
}
|
||||||
|
@ -40,15 +40,15 @@ public class SpdySessionHandlerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void assertHeaderBlock(SpdyHeaderBlock received, SpdyHeaderBlock expected) {
|
private static void assertHeaderBlock(SpdyHeaderBlock received, SpdyHeaderBlock expected) {
|
||||||
for (String name: expected.getHeaderNames()) {
|
for (String name: expected.headers().names()) {
|
||||||
List<String> expectedValues = expected.getHeaders(name);
|
List<String> expectedValues = expected.headers().getAll(name);
|
||||||
List<String> receivedValues = received.getHeaders(name);
|
List<String> receivedValues = received.headers().getAll(name);
|
||||||
assertTrue(receivedValues.containsAll(expectedValues));
|
assertTrue(receivedValues.containsAll(expectedValues));
|
||||||
receivedValues.removeAll(expectedValues);
|
receivedValues.removeAll(expectedValues);
|
||||||
assertTrue(receivedValues.isEmpty());
|
assertTrue(receivedValues.isEmpty());
|
||||||
received.removeHeader(name);
|
received.headers().remove(name);
|
||||||
}
|
}
|
||||||
assertTrue(received.getHeaders().isEmpty());
|
assertTrue(received.headers().entries().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertDataFrame(Object msg, int streamID, boolean last) {
|
private static void assertDataFrame(Object msg, int streamID, boolean last) {
|
||||||
@ -114,7 +114,7 @@ public class SpdySessionHandlerTest {
|
|||||||
|
|
||||||
SpdySynStreamFrame spdySynStreamFrame =
|
SpdySynStreamFrame spdySynStreamFrame =
|
||||||
new DefaultSpdySynStreamFrame(localStreamID, 0, (byte) 0);
|
new DefaultSpdySynStreamFrame(localStreamID, 0, (byte) 0);
|
||||||
spdySynStreamFrame.setHeader("Compression", "test");
|
spdySynStreamFrame.headers().set("Compression", "test");
|
||||||
|
|
||||||
SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamID);
|
SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamID);
|
||||||
spdyDataFrame.setLast(true);
|
spdyDataFrame.setLast(true);
|
||||||
@ -146,8 +146,10 @@ public class SpdySessionHandlerTest {
|
|||||||
assertSynReply(sessionHandler.readOutbound(), localStreamID, false, spdySynStreamFrame);
|
assertSynReply(sessionHandler.readOutbound(), localStreamID, false, spdySynStreamFrame);
|
||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamID);
|
SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(localStreamID);
|
||||||
spdyHeadersFrame.addHeader("HEADER","test1");
|
|
||||||
spdyHeadersFrame.addHeader("HEADER","test2");
|
spdyHeadersFrame.headers().add("HEADER","test1");
|
||||||
|
spdyHeadersFrame.headers().add("HEADER","test2");
|
||||||
|
|
||||||
sessionHandler.writeInbound(spdyHeadersFrame);
|
sessionHandler.writeInbound(spdyHeadersFrame);
|
||||||
assertHeaders(sessionHandler.readOutbound(), localStreamID, spdyHeadersFrame);
|
assertHeaders(sessionHandler.readOutbound(), localStreamID, spdyHeadersFrame);
|
||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
@ -159,6 +161,7 @@ public class SpdySessionHandlerTest {
|
|||||||
spdySynStreamFrame.setStreamId(localStreamID);
|
spdySynStreamFrame.setStreamId(localStreamID);
|
||||||
spdySynStreamFrame.setLast(true);
|
spdySynStreamFrame.setLast(true);
|
||||||
spdySynStreamFrame.setUnidirectional(true);
|
spdySynStreamFrame.setUnidirectional(true);
|
||||||
|
|
||||||
sessionHandler.writeInbound(spdySynStreamFrame);
|
sessionHandler.writeInbound(spdySynStreamFrame);
|
||||||
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.REFUSED_STREAM);
|
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.REFUSED_STREAM);
|
||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
@ -175,6 +178,7 @@ public class SpdySessionHandlerTest {
|
|||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
spdySynStreamFrame.setUnidirectional(false);
|
spdySynStreamFrame.setUnidirectional(false);
|
||||||
|
|
||||||
|
|
||||||
// Check if session handler returns PROTOCOL_ERROR if it receives
|
// Check if session handler returns PROTOCOL_ERROR if it receives
|
||||||
// multiple SYN_STREAM frames for the same active Stream-ID
|
// multiple SYN_STREAM frames for the same active Stream-ID
|
||||||
sessionHandler.writeInbound(spdySynStreamFrame);
|
sessionHandler.writeInbound(spdySynStreamFrame);
|
||||||
@ -190,6 +194,7 @@ public class SpdySessionHandlerTest {
|
|||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
spdySynStreamFrame.setStreamId(localStreamID);
|
spdySynStreamFrame.setStreamId(localStreamID);
|
||||||
|
|
||||||
|
|
||||||
// Check if session handler correctly limits the number of
|
// Check if session handler correctly limits the number of
|
||||||
// concurrent streams in the SETTINGS frame
|
// concurrent streams in the SETTINGS frame
|
||||||
SpdySettingsFrame spdySettingsFrame = new DefaultSpdySettingsFrame();
|
SpdySettingsFrame spdySettingsFrame = new DefaultSpdySettingsFrame();
|
||||||
@ -212,6 +217,7 @@ public class SpdySessionHandlerTest {
|
|||||||
assertDataFrame(sessionHandler.readOutbound(), testStreamID, spdyDataFrame.isLast());
|
assertDataFrame(sessionHandler.readOutbound(), testStreamID, spdyDataFrame.isLast());
|
||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
spdyHeadersFrame.setStreamId(testStreamID);
|
spdyHeadersFrame.setStreamId(testStreamID);
|
||||||
|
|
||||||
sessionHandler.writeInbound(spdyHeadersFrame);
|
sessionHandler.writeInbound(spdyHeadersFrame);
|
||||||
assertRstStream(sessionHandler.readOutbound(), testStreamID, SpdyStreamStatus.INVALID_STREAM);
|
assertRstStream(sessionHandler.readOutbound(), testStreamID, SpdyStreamStatus.INVALID_STREAM);
|
||||||
assertNull(sessionHandler.readOutbound());
|
assertNull(sessionHandler.readOutbound());
|
||||||
@ -219,6 +225,7 @@ public class SpdySessionHandlerTest {
|
|||||||
// Check if session handler returns PROTOCOL_ERROR if it receives
|
// Check if session handler returns PROTOCOL_ERROR if it receives
|
||||||
// an invalid HEADERS frame
|
// an invalid HEADERS frame
|
||||||
spdyHeadersFrame.setStreamId(localStreamID);
|
spdyHeadersFrame.setStreamId(localStreamID);
|
||||||
|
|
||||||
spdyHeadersFrame.setInvalid();
|
spdyHeadersFrame.setInvalid();
|
||||||
sessionHandler.writeInbound(spdyHeadersFrame);
|
sessionHandler.writeInbound(spdyHeadersFrame);
|
||||||
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.PROTOCOL_ERROR);
|
assertRstStream(sessionHandler.readOutbound(), localStreamID, SpdyStreamStatus.PROTOCOL_ERROR);
|
||||||
@ -320,8 +327,8 @@ public class SpdySessionHandlerTest {
|
|||||||
int streamID = spdySynStreamFrame.getStreamId();
|
int streamID = spdySynStreamFrame.getStreamId();
|
||||||
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID);
|
SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID);
|
||||||
spdySynReplyFrame.setLast(spdySynStreamFrame.isLast());
|
spdySynReplyFrame.setLast(spdySynStreamFrame.isLast());
|
||||||
for (Map.Entry<String, String> entry: spdySynStreamFrame.getHeaders()) {
|
for (Map.Entry<String, String> entry: spdySynStreamFrame.headers()) {
|
||||||
spdySynReplyFrame.addHeader(entry.getKey(), entry.getValue());
|
spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.write(spdySynReplyFrame);
|
ctx.write(spdySynReplyFrame);
|
||||||
|
Loading…
Reference in New Issue
Block a user