mirror of
https://github.com/square/okhttp.git
synced 2026-01-25 16:01:38 +03:00
Merge pull request #280 from square/jwilson/push_flags
Push stream flags into Spdy3.
This commit is contained in:
@@ -65,7 +65,6 @@
|
||||
<property name="max" value="100"/>
|
||||
</module>
|
||||
<module name="MethodLength"/>
|
||||
<module name="ParameterNumber"/>
|
||||
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
|
||||
@@ -39,7 +39,21 @@ final class Http20Draft04 implements Variant {
|
||||
}
|
||||
|
||||
@Override public boolean nextFrame(Handler handler) throws IOException {
|
||||
return false;
|
||||
int w1;
|
||||
try {
|
||||
w1 = in.readInt();
|
||||
} catch (IOException e) {
|
||||
return false; // This might be a normal socket close.
|
||||
}
|
||||
int w2 = in.readInt();
|
||||
|
||||
int length = w1 & 0xffff;
|
||||
int type = (w1 & 0xff0000) >> 16;
|
||||
int flags = (w1 & 0xff000000) >> 24;
|
||||
boolean r = (w2 & 0x80000000) != 0;
|
||||
int streamId = (w2 & 0x7fffffff);
|
||||
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override public void close() throws IOException {
|
||||
@@ -54,12 +68,6 @@ final class Http20Draft04 implements Variant {
|
||||
this.out = new DataOutputStream(out);
|
||||
}
|
||||
|
||||
@Override public synchronized void writeFrame(byte[] data, int offset, int length)
|
||||
throws IOException {
|
||||
// TODO: this method no longer makes sense; the raw frame can't support all variants!
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override public synchronized void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
@@ -68,12 +76,13 @@ final class Http20Draft04 implements Variant {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override public synchronized void synStream(int flags, int streamId, int associatedStreamId,
|
||||
int priority, int slot, List<String> nameValueBlock) throws IOException {
|
||||
@Override public synchronized void synStream(boolean outFinished, boolean inFinished,
|
||||
int streamId, int associatedStreamId, int priority, int slot, List<String> nameValueBlock)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override public synchronized void synReply(int flags, int streamId,
|
||||
@Override public synchronized void synReply(boolean outFinished, int streamId,
|
||||
List<String> nameValueBlock) throws IOException {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
@@ -87,8 +96,13 @@ final class Http20Draft04 implements Variant {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
@Override public synchronized void data(int flags, int streamId, byte[] data)
|
||||
@Override public synchronized void data(boolean outFinished, int streamId, byte[] data)
|
||||
throws IOException {
|
||||
data(outFinished, streamId, data, 0, data.length);
|
||||
}
|
||||
|
||||
@Override public void data(boolean outFinished, int streamId, byte[] data, int offset,
|
||||
int byteCount) throws IOException {
|
||||
throw new UnsupportedOperationException("TODO");
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,23 @@ import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
final class Spdy3 implements Variant {
|
||||
static final int TYPE_DATA = 0x0;
|
||||
static final int TYPE_SYN_STREAM = 0x1;
|
||||
static final int TYPE_SYN_REPLY = 0x2;
|
||||
static final int TYPE_RST_STREAM = 0x3;
|
||||
static final int TYPE_SETTINGS = 0x4;
|
||||
static final int TYPE_NOOP = 0x5;
|
||||
static final int TYPE_PING = 0x6;
|
||||
static final int TYPE_GOAWAY = 0x7;
|
||||
static final int TYPE_HEADERS = 0x8;
|
||||
static final int TYPE_WINDOW_UPDATE = 0x9;
|
||||
static final int TYPE_CREDENTIAL = 0x10;
|
||||
|
||||
static final int FLAG_FIN = 0x1;
|
||||
static final int FLAG_UNIDIRECTIONAL = 0x2;
|
||||
|
||||
static final int VERSION = 3;
|
||||
|
||||
static final byte[] DICTIONARY;
|
||||
static {
|
||||
try {
|
||||
@@ -120,44 +137,44 @@ final class Spdy3 implements Variant {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SpdyConnection.TYPE_SYN_STREAM:
|
||||
case TYPE_SYN_STREAM:
|
||||
readSynStream(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_SYN_REPLY:
|
||||
case TYPE_SYN_REPLY:
|
||||
readSynReply(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_RST_STREAM:
|
||||
case TYPE_RST_STREAM:
|
||||
readRstStream(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_SETTINGS:
|
||||
case TYPE_SETTINGS:
|
||||
readSettings(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_NOOP:
|
||||
case TYPE_NOOP:
|
||||
if (length != 0) throw ioException("TYPE_NOOP length: %d != 0", length);
|
||||
handler.noop();
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_PING:
|
||||
case TYPE_PING:
|
||||
readPing(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_GOAWAY:
|
||||
case TYPE_GOAWAY:
|
||||
readGoAway(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_HEADERS:
|
||||
case TYPE_HEADERS:
|
||||
readHeaders(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_WINDOW_UPDATE:
|
||||
case TYPE_WINDOW_UPDATE:
|
||||
readWindowUpdate(handler, flags, length);
|
||||
return true;
|
||||
|
||||
case SpdyConnection.TYPE_CREDENTIAL:
|
||||
case TYPE_CREDENTIAL:
|
||||
Util.skipByReading(in, length);
|
||||
throw new UnsupportedOperationException("TODO"); // TODO: implement
|
||||
|
||||
@@ -166,7 +183,8 @@ final class Spdy3 implements Variant {
|
||||
}
|
||||
} else {
|
||||
int streamId = w1 & 0x7fffffff;
|
||||
handler.data(flags, streamId, in, length);
|
||||
boolean inFinished = (flags & FLAG_FIN) != 0;
|
||||
handler.data(inFinished, streamId, in, length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -180,14 +198,19 @@ final class Spdy3 implements Variant {
|
||||
int priority = (s3 & 0xe000) >>> 13;
|
||||
int slot = s3 & 0xff;
|
||||
List<String> nameValueBlock = readNameValueBlock(length - 10);
|
||||
handler.synStream(flags, streamId, associatedStreamId, priority, slot, nameValueBlock);
|
||||
|
||||
boolean inFinished = (flags & FLAG_FIN) != 0;
|
||||
boolean outFinished = (flags & FLAG_UNIDIRECTIONAL) != 0;
|
||||
handler.synStream(outFinished, inFinished, streamId, associatedStreamId, priority, slot,
|
||||
nameValueBlock);
|
||||
}
|
||||
|
||||
private void readSynReply(Handler handler, int flags, int length) throws IOException {
|
||||
int w1 = in.readInt();
|
||||
int streamId = w1 & 0x7fffffff;
|
||||
List<String> nameValueBlock = readNameValueBlock(length - 4);
|
||||
handler.synReply(flags, streamId, nameValueBlock);
|
||||
boolean inFinished = (flags & FLAG_FIN) != 0;
|
||||
handler.synReply(inFinished, streamId, nameValueBlock);
|
||||
}
|
||||
|
||||
private void readRstStream(Handler handler, int flags, int length) throws IOException {
|
||||
@@ -340,23 +363,20 @@ final class Spdy3 implements Variant {
|
||||
// Do nothing: no connection header for SPDY/3.
|
||||
}
|
||||
|
||||
@Override public synchronized void writeFrame(byte[] data, int offset, int length)
|
||||
throws IOException {
|
||||
out.write(data, offset, length);
|
||||
}
|
||||
|
||||
@Override public synchronized void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override public synchronized void synStream(int flags, int streamId, int associatedStreamId,
|
||||
int priority, int slot, List<String> nameValueBlock) throws IOException {
|
||||
@Override public synchronized void synStream(boolean outFinished, boolean inFinished,
|
||||
int streamId, int associatedStreamId, int priority, int slot, List<String> nameValueBlock)
|
||||
throws IOException {
|
||||
writeNameValueBlockToBuffer(nameValueBlock);
|
||||
int length = 10 + nameValueBlockBuffer.size();
|
||||
int type = SpdyConnection.TYPE_SYN_STREAM;
|
||||
int type = TYPE_SYN_STREAM;
|
||||
int flags = (outFinished ? FLAG_FIN : 0) | (inFinished ? FLAG_UNIDIRECTIONAL : 0);
|
||||
|
||||
int unused = 0;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(streamId & 0x7fffffff);
|
||||
out.writeInt(associatedStreamId & 0x7fffffff);
|
||||
@@ -366,12 +386,13 @@ final class Spdy3 implements Variant {
|
||||
}
|
||||
|
||||
@Override public synchronized void synReply(
|
||||
int flags, int streamId, List<String> nameValueBlock) throws IOException {
|
||||
boolean outFinished, int streamId, List<String> nameValueBlock) throws IOException {
|
||||
writeNameValueBlockToBuffer(nameValueBlock);
|
||||
int type = SpdyConnection.TYPE_SYN_REPLY;
|
||||
int type = TYPE_SYN_REPLY;
|
||||
int flags = (outFinished ? FLAG_FIN : 0);
|
||||
int length = nameValueBlockBuffer.size() + 4;
|
||||
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(streamId & 0x7fffffff);
|
||||
nameValueBlockBuffer.writeTo(out);
|
||||
@@ -381,10 +402,10 @@ final class Spdy3 implements Variant {
|
||||
@Override public synchronized void headers(int flags, int streamId, List<String> nameValueBlock)
|
||||
throws IOException {
|
||||
writeNameValueBlockToBuffer(nameValueBlock);
|
||||
int type = SpdyConnection.TYPE_HEADERS;
|
||||
int type = TYPE_HEADERS;
|
||||
int length = nameValueBlockBuffer.size() + 4;
|
||||
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(streamId & 0x7fffffff);
|
||||
nameValueBlockBuffer.writeTo(out);
|
||||
@@ -393,22 +414,26 @@ final class Spdy3 implements Variant {
|
||||
|
||||
@Override public synchronized void rstStream(int streamId, int statusCode) throws IOException {
|
||||
int flags = 0;
|
||||
int type = SpdyConnection.TYPE_RST_STREAM;
|
||||
int type = TYPE_RST_STREAM;
|
||||
int length = 8;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(streamId & 0x7fffffff);
|
||||
out.writeInt(statusCode);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override public synchronized void data(int flags, int streamId, byte[] data)
|
||||
@Override public synchronized void data(boolean outFinished, int streamId, byte[] data)
|
||||
throws IOException {
|
||||
int length = data.length;
|
||||
data(outFinished, streamId, data, 0, data.length);
|
||||
}
|
||||
|
||||
@Override public synchronized void data(boolean outFinished, int streamId, byte[] data,
|
||||
int offset, int byteCount) throws IOException {
|
||||
int flags = (outFinished ? FLAG_FIN : 0);
|
||||
out.writeInt(streamId & 0x7fffffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.write(data);
|
||||
out.flush();
|
||||
out.writeInt((flags & 0xff) << 24 | byteCount & 0xffffff);
|
||||
out.write(data, offset, byteCount);
|
||||
}
|
||||
|
||||
private void writeNameValueBlockToBuffer(List<String> nameValueBlock) throws IOException {
|
||||
@@ -423,10 +448,10 @@ final class Spdy3 implements Variant {
|
||||
}
|
||||
|
||||
@Override public synchronized void settings(int flags, Settings settings) throws IOException {
|
||||
int type = SpdyConnection.TYPE_SETTINGS;
|
||||
int type = TYPE_SETTINGS;
|
||||
int size = settings.size();
|
||||
int length = 4 + size * 8;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(size);
|
||||
for (int i = 0; i <= Settings.COUNT; i++) {
|
||||
@@ -439,18 +464,18 @@ final class Spdy3 implements Variant {
|
||||
}
|
||||
|
||||
@Override public synchronized void noop() throws IOException {
|
||||
int type = SpdyConnection.TYPE_NOOP;
|
||||
int type = TYPE_NOOP;
|
||||
int length = 0;
|
||||
int flags = 0;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override public synchronized void ping(int flags, int id) throws IOException {
|
||||
int type = SpdyConnection.TYPE_PING;
|
||||
int type = TYPE_PING;
|
||||
int length = 4;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(id);
|
||||
out.flush();
|
||||
@@ -458,9 +483,9 @@ final class Spdy3 implements Variant {
|
||||
|
||||
@Override public synchronized void goAway(int flags, int lastGoodStreamId, int statusCode)
|
||||
throws IOException {
|
||||
int type = SpdyConnection.TYPE_GOAWAY;
|
||||
int type = TYPE_GOAWAY;
|
||||
int length = 8;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(lastGoodStreamId);
|
||||
out.writeInt(statusCode);
|
||||
@@ -469,10 +494,10 @@ final class Spdy3 implements Variant {
|
||||
|
||||
@Override public synchronized void windowUpdate(int streamId, int deltaWindowSize)
|
||||
throws IOException {
|
||||
int type = SpdyConnection.TYPE_WINDOW_UPDATE;
|
||||
int type = TYPE_WINDOW_UPDATE;
|
||||
int flags = 0;
|
||||
int length = 8;
|
||||
out.writeInt(0x80000000 | (SpdyConnection.VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff);
|
||||
out.writeInt((flags & 0xff) << 24 | length & 0xffffff);
|
||||
out.writeInt(streamId);
|
||||
out.writeInt(deltaWindowSize);
|
||||
|
||||
@@ -55,22 +55,6 @@ public final class SpdyConnection implements Closeable {
|
||||
// operations must synchronize on 'this' last. This ensures that we never
|
||||
// wait for a blocking operation while holding 'this'.
|
||||
|
||||
static final int FLAG_FIN = 0x1;
|
||||
static final int FLAG_UNIDIRECTIONAL = 0x2;
|
||||
|
||||
static final int TYPE_DATA = 0x0;
|
||||
static final int TYPE_SYN_STREAM = 0x1;
|
||||
static final int TYPE_SYN_REPLY = 0x2;
|
||||
static final int TYPE_RST_STREAM = 0x3;
|
||||
static final int TYPE_SETTINGS = 0x4;
|
||||
static final int TYPE_NOOP = 0x5;
|
||||
static final int TYPE_PING = 0x6;
|
||||
static final int TYPE_GOAWAY = 0x7;
|
||||
static final int TYPE_HEADERS = 0x8;
|
||||
static final int TYPE_WINDOW_UPDATE = 0x9;
|
||||
static final int TYPE_CREDENTIAL = 0x10;
|
||||
static final int VERSION = 3;
|
||||
|
||||
static final int GOAWAY_OK = 0;
|
||||
static final int GOAWAY_PROTOCOL_ERROR = 1;
|
||||
static final int GOAWAY_INTERNAL_ERROR = 2;
|
||||
@@ -159,13 +143,14 @@ public final class SpdyConnection implements Closeable {
|
||||
* Returns a new locally-initiated stream.
|
||||
*
|
||||
* @param out true to create an output stream that we can use to send data
|
||||
* to the remote peer. Corresponds to {@code FLAG_FIN}.
|
||||
* to the remote peer. Corresponds to {@code FLAG_FIN}.
|
||||
* @param in true to create an input stream that the remote peer can use to
|
||||
* send data to us. Corresponds to {@code FLAG_UNIDIRECTIONAL}.
|
||||
* send data to us. Corresponds to {@code FLAG_UNIDIRECTIONAL}.
|
||||
*/
|
||||
public SpdyStream newStream(List<String> requestHeaders, boolean out, boolean in)
|
||||
throws IOException {
|
||||
int flags = (out ? 0 : FLAG_FIN) | (in ? 0 : FLAG_UNIDIRECTIONAL);
|
||||
boolean outFinished = !out;
|
||||
boolean inFinished = !in;
|
||||
int associatedStreamId = 0; // TODO: permit the caller to specify an associated stream?
|
||||
int priority = 0; // TODO: permit the caller to specify a priority?
|
||||
int slot = 0; // TODO: permit the caller to specify a slot?
|
||||
@@ -179,25 +164,29 @@ public final class SpdyConnection implements Closeable {
|
||||
}
|
||||
streamId = nextStreamId;
|
||||
nextStreamId += 2;
|
||||
stream = new SpdyStream(streamId, this, flags, priority, slot, requestHeaders, settings);
|
||||
stream = new SpdyStream(streamId, this, outFinished, inFinished, priority, slot,
|
||||
requestHeaders, settings);
|
||||
if (stream.isOpen()) {
|
||||
streams.put(streamId, stream);
|
||||
setIdle(false);
|
||||
}
|
||||
}
|
||||
|
||||
spdyWriter.synStream(flags, streamId, associatedStreamId, priority, slot, requestHeaders);
|
||||
spdyWriter.synStream(outFinished, inFinished, streamId, associatedStreamId, priority, slot,
|
||||
requestHeaders);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void writeSynReply(int streamId, int flags, List<String> alternating) throws IOException {
|
||||
spdyWriter.synReply(flags, streamId, alternating);
|
||||
void writeSynReply(int streamId, boolean outFinished, List<String> alternating)
|
||||
throws IOException {
|
||||
spdyWriter.synReply(outFinished, streamId, alternating);
|
||||
}
|
||||
|
||||
void writeFrame(byte[] bytes, int offset, int length) throws IOException {
|
||||
spdyWriter.writeFrame(bytes, offset, length);
|
||||
public void writeData(int streamId, boolean outFinished, byte[] buffer, int offset, int byteCount)
|
||||
throws IOException {
|
||||
spdyWriter.data(outFinished, streamId, buffer, offset, byteCount);
|
||||
}
|
||||
|
||||
void writeSynResetLater(final int streamId, final int statusCode) {
|
||||
@@ -450,7 +439,7 @@ public final class SpdyConnection implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void data(int flags, int streamId, InputStream in, int length)
|
||||
@Override public void data(boolean inFinished, int streamId, InputStream in, int length)
|
||||
throws IOException {
|
||||
SpdyStream dataStream = getStream(streamId);
|
||||
if (dataStream == null) {
|
||||
@@ -459,19 +448,18 @@ public final class SpdyConnection implements Closeable {
|
||||
return;
|
||||
}
|
||||
dataStream.receiveData(in, length);
|
||||
if ((flags & SpdyConnection.FLAG_FIN) != 0) {
|
||||
if (inFinished) {
|
||||
dataStream.receiveFin();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void synStream(int flags, int streamId, int associatedStreamId, int priority,
|
||||
int slot, List<String> nameValueBlock) {
|
||||
@Override public void synStream(boolean outFinished, boolean inFinished, int streamId,
|
||||
int associatedStreamId, int priority, int slot, List<String> nameValueBlock) {
|
||||
final SpdyStream synStream;
|
||||
final SpdyStream previous;
|
||||
synchronized (SpdyConnection.this) {
|
||||
synStream =
|
||||
new SpdyStream(streamId, SpdyConnection.this, flags, priority, slot, nameValueBlock,
|
||||
settings);
|
||||
synStream = new SpdyStream(streamId, SpdyConnection.this, outFinished, inFinished, priority,
|
||||
slot, nameValueBlock, settings);
|
||||
if (shutdown) {
|
||||
return;
|
||||
}
|
||||
@@ -495,7 +483,7 @@ public final class SpdyConnection implements Closeable {
|
||||
});
|
||||
}
|
||||
|
||||
@Override public void synReply(int flags, int streamId, List<String> nameValueBlock)
|
||||
@Override public void synReply(boolean inFinished, int streamId, List<String> nameValueBlock)
|
||||
throws IOException {
|
||||
SpdyStream replyStream = getStream(streamId);
|
||||
if (replyStream == null) {
|
||||
@@ -503,7 +491,7 @@ public final class SpdyConnection implements Closeable {
|
||||
return;
|
||||
}
|
||||
replyStream.receiveReply(nameValueBlock);
|
||||
if ((flags & SpdyConnection.FLAG_FIN) != 0) {
|
||||
if (inFinished) {
|
||||
replyStream.receiveFin();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ public interface SpdyReader extends Closeable {
|
||||
boolean nextFrame(Handler handler) throws IOException;
|
||||
|
||||
public interface Handler {
|
||||
void data(int flags, int streamId, InputStream in, int length) throws IOException;
|
||||
void synStream(int flags, int streamId, int associatedStreamId, int priority, int slot,
|
||||
List<String> nameValueBlock);
|
||||
void synReply(int flags, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void data(boolean inFinished, int streamId, InputStream in, int length)
|
||||
throws IOException;
|
||||
void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
|
||||
int priority, int slot, List<String> nameValueBlock);
|
||||
void synReply(boolean inFinished, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void headers(int flags, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void rstStream(int flags, int streamId, int statusCode);
|
||||
void settings(int flags, Settings settings);
|
||||
|
||||
@@ -26,8 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.checkOffsetAndCount;
|
||||
import static com.squareup.okhttp.internal.Util.pokeInt;
|
||||
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||
|
||||
/** A logical bidirectional stream. */
|
||||
public final class SpdyStream {
|
||||
@@ -35,8 +33,6 @@ public final class SpdyStream {
|
||||
// Internal state is guarded by this. No long-running or potentially
|
||||
// blocking operations are performed while the lock is held.
|
||||
|
||||
private static final int DATA_FRAME_HEADER_LENGTH = 8;
|
||||
|
||||
private static final String[] STATUS_CODE_NAMES = {
|
||||
null,
|
||||
"PROTOCOL_ERROR",
|
||||
@@ -95,26 +91,18 @@ public final class SpdyStream {
|
||||
*/
|
||||
private int rstStatusCode = -1;
|
||||
|
||||
SpdyStream(int id, SpdyConnection connection, int flags, int priority, int slot,
|
||||
List<String> requestHeaders, Settings settings) {
|
||||
SpdyStream(int id, SpdyConnection connection, boolean outFinished, boolean inFinished,
|
||||
int priority, int slot, List<String> requestHeaders, Settings settings) {
|
||||
if (connection == null) throw new NullPointerException("connection == null");
|
||||
if (requestHeaders == null) throw new NullPointerException("requestHeaders == null");
|
||||
this.id = id;
|
||||
this.connection = connection;
|
||||
this.in.finished = inFinished;
|
||||
this.out.finished = outFinished;
|
||||
this.priority = priority;
|
||||
this.slot = slot;
|
||||
this.requestHeaders = requestHeaders;
|
||||
|
||||
if (isLocallyInitiated()) {
|
||||
// I am the sender
|
||||
in.finished = (flags & SpdyConnection.FLAG_UNIDIRECTIONAL) != 0;
|
||||
out.finished = (flags & SpdyConnection.FLAG_FIN) != 0;
|
||||
} else {
|
||||
// I am the receiver
|
||||
in.finished = (flags & SpdyConnection.FLAG_FIN) != 0;
|
||||
out.finished = (flags & SpdyConnection.FLAG_UNIDIRECTIONAL) != 0;
|
||||
}
|
||||
|
||||
setSettings(settings);
|
||||
}
|
||||
|
||||
@@ -192,7 +180,7 @@ public final class SpdyStream {
|
||||
*/
|
||||
public void reply(List<String> responseHeaders, boolean out) throws IOException {
|
||||
assert (!Thread.holdsLock(SpdyStream.this));
|
||||
int flags = 0;
|
||||
boolean outFinished = false;
|
||||
synchronized (this) {
|
||||
if (responseHeaders == null) {
|
||||
throw new NullPointerException("responseHeaders == null");
|
||||
@@ -206,10 +194,10 @@ public final class SpdyStream {
|
||||
this.responseHeaders = responseHeaders;
|
||||
if (!out) {
|
||||
this.out.finished = true;
|
||||
flags |= SpdyConnection.FLAG_FIN;
|
||||
outFinished = true;
|
||||
}
|
||||
}
|
||||
connection.writeSynReply(id, flags, responseHeaders);
|
||||
connection.writeSynReply(id, outFinished, responseHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,9 +336,9 @@ public final class SpdyStream {
|
||||
|
||||
private void setSettings(Settings settings) {
|
||||
assert (Thread.holdsLock(connection)); // Because 'settings' is guarded by 'connection'.
|
||||
this.writeWindowSize =
|
||||
settings != null ? settings.getInitialWindowSize(Settings.DEFAULT_INITIAL_WINDOW_SIZE)
|
||||
: Settings.DEFAULT_INITIAL_WINDOW_SIZE;
|
||||
this.writeWindowSize = settings != null
|
||||
? settings.getInitialWindowSize(Settings.DEFAULT_INITIAL_WINDOW_SIZE)
|
||||
: Settings.DEFAULT_INITIAL_WINDOW_SIZE;
|
||||
}
|
||||
|
||||
void receiveSettings(Settings settings) {
|
||||
@@ -614,7 +602,7 @@ public final class SpdyStream {
|
||||
*/
|
||||
private final class SpdyDataOutputStream extends OutputStream {
|
||||
private final byte[] buffer = new byte[8192];
|
||||
private int pos = DATA_FRAME_HEADER_LENGTH;
|
||||
private int pos = 0;
|
||||
|
||||
/** True if the caller has closed this stream. */
|
||||
private boolean closed;
|
||||
@@ -656,7 +644,7 @@ public final class SpdyStream {
|
||||
@Override public void flush() throws IOException {
|
||||
assert (!Thread.holdsLock(SpdyStream.this));
|
||||
checkNotClosed();
|
||||
if (pos > DATA_FRAME_HEADER_LENGTH) {
|
||||
if (pos > 0) {
|
||||
writeFrame(false);
|
||||
connection.flush();
|
||||
}
|
||||
@@ -677,22 +665,16 @@ public final class SpdyStream {
|
||||
cancelStreamIfNecessary();
|
||||
}
|
||||
|
||||
private void writeFrame(boolean last) throws IOException {
|
||||
private void writeFrame(boolean outFinished) throws IOException {
|
||||
assert (!Thread.holdsLock(SpdyStream.this));
|
||||
|
||||
int length = pos - DATA_FRAME_HEADER_LENGTH;
|
||||
int length = pos;
|
||||
synchronized (SpdyStream.this) {
|
||||
waitUntilWritable(length, last);
|
||||
waitUntilWritable(length, outFinished);
|
||||
unacknowledgedBytes += length;
|
||||
}
|
||||
int flags = 0;
|
||||
if (last) {
|
||||
flags |= SpdyConnection.FLAG_FIN;
|
||||
}
|
||||
pokeInt(buffer, 0, id & 0x7fffffff, BIG_ENDIAN);
|
||||
pokeInt(buffer, 4, (flags & 0xff) << 24 | length & 0xffffff, BIG_ENDIAN);
|
||||
connection.writeFrame(buffer, 0, pos);
|
||||
pos = DATA_FRAME_HEADER_LENGTH;
|
||||
connection.writeData(id, outFinished, buffer, 0, pos);
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,15 +23,15 @@ import java.util.List;
|
||||
/** Writes transport frames for SPDY/3 or HTTP/2.0. */
|
||||
public interface SpdyWriter extends Closeable {
|
||||
void connectionHeader();
|
||||
/** Writes a complete variant-specific frame. */
|
||||
void writeFrame(byte[] data, int offset, int length) throws IOException;
|
||||
void flush() throws IOException;
|
||||
void synStream(int flags, int streamId, int associatedStreamId, int priority, int slot,
|
||||
List<String> nameValueBlock) throws IOException;
|
||||
void synReply(int flags, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
|
||||
int priority, int slot, List<String> nameValueBlock) throws IOException;
|
||||
void synReply(boolean outFinished, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void headers(int flags, int streamId, List<String> nameValueBlock) throws IOException;
|
||||
void rstStream(int streamId, int statusCode) throws IOException;
|
||||
void data(int flags, int streamId, byte[] data) throws IOException;
|
||||
void data(boolean outFinished, int streamId, byte[] data) throws IOException;
|
||||
void data(boolean outFinished, int streamId, byte[] data, int offset, int byteCount)
|
||||
throws IOException;
|
||||
void settings(int flags, Settings settings) throws IOException;
|
||||
void noop() throws IOException;
|
||||
void ping(int flags, int id) throws IOException;
|
||||
|
||||
@@ -37,8 +37,9 @@ import static java.util.concurrent.Executors.defaultThreadFactory;
|
||||
/** Replays prerecorded outgoing frames and records incoming frames. */
|
||||
public final class MockSpdyPeer implements Closeable {
|
||||
private int frameCount = 0;
|
||||
private final boolean client;
|
||||
private final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
|
||||
private final SpdyWriter spdyWriter = Variant.SPDY3.newWriter(bytesOut);
|
||||
private final SpdyWriter spdyWriter;
|
||||
private final List<OutFrame> outFrames = new ArrayList<OutFrame>();
|
||||
private final BlockingQueue<InFrame> inFrames = new LinkedBlockingQueue<InFrame>();
|
||||
private int port;
|
||||
@@ -46,6 +47,11 @@ public final class MockSpdyPeer implements Closeable {
|
||||
private ServerSocket serverSocket;
|
||||
private Socket socket;
|
||||
|
||||
public MockSpdyPeer(boolean client) {
|
||||
this.client = client;
|
||||
this.spdyWriter = Variant.SPDY3.newWriter(bytesOut);
|
||||
}
|
||||
|
||||
public void acceptFrame() {
|
||||
frameCount++;
|
||||
}
|
||||
@@ -162,7 +168,9 @@ public final class MockSpdyPeer implements Closeable {
|
||||
public final int sequence;
|
||||
public final SpdyReader reader;
|
||||
public int type = -1;
|
||||
public int flags;
|
||||
public int flags = -1;
|
||||
public boolean outFinished;
|
||||
public boolean inFinished;
|
||||
public int streamId;
|
||||
public int associatedStreamId;
|
||||
public int priority;
|
||||
@@ -180,16 +188,17 @@ public final class MockSpdyPeer implements Closeable {
|
||||
|
||||
@Override public void settings(int flags, Settings settings) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_SETTINGS;
|
||||
this.type = Spdy3.TYPE_SETTINGS;
|
||||
this.flags = flags;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override public void synStream(int flags, int streamId, int associatedStreamId, int priority,
|
||||
int slot, List<String> nameValueBlock) {
|
||||
@Override public void synStream(boolean outFinished, boolean inFinished, int streamId,
|
||||
int associatedStreamId, int priority, int slot, List<String> nameValueBlock) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_SYN_STREAM;
|
||||
this.flags = flags;
|
||||
this.type = Spdy3.TYPE_SYN_STREAM;
|
||||
this.outFinished = outFinished;
|
||||
this.inFinished = inFinished;
|
||||
this.streamId = streamId;
|
||||
this.associatedStreamId = associatedStreamId;
|
||||
this.priority = priority;
|
||||
@@ -197,27 +206,27 @@ public final class MockSpdyPeer implements Closeable {
|
||||
this.nameValueBlock = nameValueBlock;
|
||||
}
|
||||
|
||||
@Override public void synReply(int flags, int streamId, List<String> nameValueBlock) {
|
||||
@Override public void synReply(boolean inFinished, int streamId, List<String> nameValueBlock) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_SYN_REPLY;
|
||||
this.type = Spdy3.TYPE_SYN_REPLY;
|
||||
this.inFinished = inFinished;
|
||||
this.streamId = streamId;
|
||||
this.flags = flags;
|
||||
this.nameValueBlock = nameValueBlock;
|
||||
}
|
||||
|
||||
@Override public void headers(int flags, int streamId, List<String> nameValueBlock) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_HEADERS;
|
||||
this.type = Spdy3.TYPE_HEADERS;
|
||||
this.streamId = streamId;
|
||||
this.flags = flags;
|
||||
this.nameValueBlock = nameValueBlock;
|
||||
}
|
||||
|
||||
@Override public void data(int flags, int streamId, InputStream in, int length)
|
||||
@Override public void data(boolean inFinished, int streamId, InputStream in, int length)
|
||||
throws IOException {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_DATA;
|
||||
this.flags = flags;
|
||||
this.type = Spdy3.TYPE_DATA;
|
||||
this.inFinished = inFinished;
|
||||
this.streamId = streamId;
|
||||
this.data = new byte[length];
|
||||
Util.readFully(in, this.data);
|
||||
@@ -225,7 +234,7 @@ public final class MockSpdyPeer implements Closeable {
|
||||
|
||||
@Override public void rstStream(int flags, int streamId, int statusCode) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_RST_STREAM;
|
||||
this.type = Spdy3.TYPE_RST_STREAM;
|
||||
this.flags = flags;
|
||||
this.streamId = streamId;
|
||||
this.statusCode = statusCode;
|
||||
@@ -233,19 +242,19 @@ public final class MockSpdyPeer implements Closeable {
|
||||
|
||||
@Override public void ping(int flags, int streamId) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_PING;
|
||||
this.type = Spdy3.TYPE_PING;
|
||||
this.flags = flags;
|
||||
this.streamId = streamId;
|
||||
}
|
||||
|
||||
@Override public void noop() {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_NOOP;
|
||||
this.type = Spdy3.TYPE_NOOP;
|
||||
}
|
||||
|
||||
@Override public void goAway(int flags, int lastGoodStreamId, int statusCode) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_GOAWAY;
|
||||
this.type = Spdy3.TYPE_GOAWAY;
|
||||
this.flags = flags;
|
||||
this.streamId = lastGoodStreamId;
|
||||
this.statusCode = statusCode;
|
||||
@@ -253,7 +262,7 @@ public final class MockSpdyPeer implements Closeable {
|
||||
|
||||
@Override public void windowUpdate(int flags, int streamId, int deltaWindowSize) {
|
||||
if (this.type != -1) throw new IllegalStateException();
|
||||
this.type = SpdyConnection.TYPE_WINDOW_UPDATE;
|
||||
this.type = Spdy3.TYPE_WINDOW_UPDATE;
|
||||
this.flags = flags;
|
||||
this.streamId = streamId;
|
||||
this.deltaWindowSize = deltaWindowSize;
|
||||
|
||||
@@ -30,18 +30,16 @@ import org.junit.Test;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.UTF_8;
|
||||
import static com.squareup.okhttp.internal.spdy.Settings.PERSIST_VALUE;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.FLAG_FIN;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.FLAG_UNIDIRECTIONAL;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_DATA;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_GOAWAY;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_NOOP;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_PING;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_RST_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_SYN_REPLY;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_SYN_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.Spdy3.TYPE_WINDOW_UPDATE;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.GOAWAY_INTERNAL_ERROR;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.GOAWAY_PROTOCOL_ERROR;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_DATA;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_GOAWAY;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_NOOP;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_PING;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_RST_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_SYN_REPLY;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_SYN_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyConnection.TYPE_WINDOW_UPDATE;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyStream.RST_FLOW_CONTROL_ERROR;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyStream.RST_INVALID_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyStream.RST_PROTOCOL_ERROR;
|
||||
@@ -49,6 +47,7 @@ import static com.squareup.okhttp.internal.spdy.SpdyStream.RST_REFUSED_STREAM;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyStream.RST_STREAM_IN_USE;
|
||||
import static com.squareup.okhttp.internal.spdy.SpdyStream.WINDOW_UPDATE_THRESHOLD;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -58,7 +57,7 @@ public final class SpdyConnectionTest {
|
||||
throw new AssertionError();
|
||||
}
|
||||
};
|
||||
private final MockSpdyPeer peer = new MockSpdyPeer();
|
||||
private final MockSpdyPeer peer = new MockSpdyPeer(false);
|
||||
|
||||
@After public void tearDown() throws Exception {
|
||||
peer.close();
|
||||
@@ -67,8 +66,8 @@ public final class SpdyConnectionTest {
|
||||
@Test public void clientCreatesStreamAndServerReplies() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().data(SpdyConnection.FLAG_FIN, 1, "robot".getBytes("UTF-8"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().data(true, 1, "robot".getBytes("UTF-8"));
|
||||
peer.acceptFrame(); // DATA
|
||||
peer.play();
|
||||
|
||||
@@ -83,7 +82,8 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(0, synStream.flags);
|
||||
assertFalse(synStream.inFinished);
|
||||
assertFalse(synStream.outFinished);
|
||||
assertEquals(1, synStream.streamId);
|
||||
assertEquals(0, synStream.associatedStreamId);
|
||||
assertEquals(Arrays.asList("b", "banana"), synStream.nameValueBlock);
|
||||
@@ -93,7 +93,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void headersOnlyStreamIsClosedAfterReplyHeaders() throws Exception {
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("b", "banana"));
|
||||
peer.play();
|
||||
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
@@ -107,7 +107,7 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(FLAG_FIN, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(true, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().ping(0, 1);
|
||||
peer.play();
|
||||
|
||||
@@ -127,7 +127,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void serverCreatesStreamAndClientReplies() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(0, 2, 0, 5, 129, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 5, 129, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.play();
|
||||
|
||||
@@ -148,7 +148,7 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame reply = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_REPLY, reply.type);
|
||||
assertEquals(0, reply.flags);
|
||||
assertFalse(reply.inFinished);
|
||||
assertEquals(2, reply.streamId);
|
||||
assertEquals(Arrays.asList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(1, receiveCount.get());
|
||||
@@ -156,7 +156,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void replyWithNoData() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(0, 2, 0, 0, 0, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.play();
|
||||
|
||||
@@ -173,7 +173,7 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame reply = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_REPLY, reply.type);
|
||||
assertEquals(FLAG_FIN, reply.flags);
|
||||
assertTrue(reply.inFinished);
|
||||
assertEquals(Arrays.asList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(1, receiveCount.get());
|
||||
}
|
||||
@@ -192,7 +192,6 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame ping = peer.takeFrame();
|
||||
assertEquals(TYPE_NOOP, ping.type);
|
||||
assertEquals(0, ping.flags);
|
||||
}
|
||||
|
||||
@Test public void serverPingsClient() throws Exception {
|
||||
@@ -288,9 +287,9 @@ public final class SpdyConnectionTest {
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
|
||||
peer.takeFrame(); // Guarantees that the Settings frame has been processed.
|
||||
synchronized (connection) {
|
||||
@@ -307,7 +306,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void bogusDataFrameDoesNotDisruptConnection() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().data(SpdyConnection.FLAG_FIN, 42, "bogus".getBytes("UTF-8"));
|
||||
peer.sendFrame().data(true, 42, "bogus".getBytes("UTF-8"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(0, 2);
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -328,7 +327,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void bogusReplyFrameDoesNotDisruptConnection() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synReply(0, 42, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 42, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(0, 2);
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -350,7 +349,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void clientClosesClientOutputStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("b", "banana"));
|
||||
peer.acceptFrame(); // TYPE_DATA
|
||||
peer.acceptFrame(); // TYPE_DATA with FLAG_FIN
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -358,9 +357,9 @@ public final class SpdyConnectionTest {
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(Arrays.asList("a", "android"), true, false);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
out.write("square".getBytes(UTF_8));
|
||||
@@ -379,14 +378,15 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(FLAG_UNIDIRECTIONAL, synStream.flags);
|
||||
assertFalse(synStream.inFinished);
|
||||
assertTrue(synStream.outFinished);
|
||||
MockSpdyPeer.InFrame data = peer.takeFrame();
|
||||
assertEquals(TYPE_DATA, data.type);
|
||||
assertEquals(0, data.flags);
|
||||
assertFalse(data.inFinished);
|
||||
assertTrue(Arrays.equals("square".getBytes("UTF-8"), data.data));
|
||||
MockSpdyPeer.InFrame fin = peer.takeFrame();
|
||||
assertEquals(TYPE_DATA, fin.type);
|
||||
assertEquals(FLAG_FIN, fin.flags);
|
||||
assertTrue(fin.inFinished);
|
||||
MockSpdyPeer.InFrame ping = peer.takeFrame();
|
||||
assertEquals(TYPE_PING, ping.type);
|
||||
assertEquals(1, ping.streamId);
|
||||
@@ -402,9 +402,9 @@ public final class SpdyConnectionTest {
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(Arrays.asList("a", "android"), true, true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
connection.ping().roundTripTime(); // Ensure that the RST_CANCEL has been received.
|
||||
@@ -420,14 +420,16 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(0, synStream.flags);
|
||||
assertFalse(synStream.inFinished);
|
||||
assertFalse(synStream.outFinished);
|
||||
MockSpdyPeer.InFrame ping = peer.takeFrame();
|
||||
assertEquals(TYPE_PING, ping.type);
|
||||
assertEquals(1, ping.streamId);
|
||||
MockSpdyPeer.InFrame data = peer.takeFrame();
|
||||
assertEquals(TYPE_DATA, data.type);
|
||||
assertEquals(1, data.streamId);
|
||||
assertEquals(FLAG_FIN, data.flags);
|
||||
assertTrue(data.inFinished);
|
||||
assertFalse(data.outFinished);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,9 +443,9 @@ public final class SpdyConnectionTest {
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(Arrays.asList("a", "android"), false, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
OutputStream out = stream.getOutputStream();
|
||||
@@ -465,7 +467,8 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(SpdyConnection.FLAG_FIN, synStream.flags);
|
||||
assertTrue(synStream.inFinished);
|
||||
assertFalse(synStream.outFinished);
|
||||
MockSpdyPeer.InFrame rstStream = peer.takeFrame();
|
||||
assertEquals(TYPE_RST_STREAM, rstStream.type);
|
||||
assertEquals(SpdyStream.RST_CANCEL, rstStream.statusCode);
|
||||
@@ -484,9 +487,9 @@ public final class SpdyConnectionTest {
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(Arrays.asList("a", "android"), true, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
OutputStream out = stream.getOutputStream();
|
||||
@@ -505,13 +508,15 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(0, synStream.flags);
|
||||
assertFalse(synStream.inFinished);
|
||||
assertFalse(synStream.outFinished);
|
||||
MockSpdyPeer.InFrame data = peer.takeFrame();
|
||||
assertEquals(TYPE_DATA, data.type);
|
||||
assertTrue(Arrays.equals("square".getBytes("UTF-8"), data.data));
|
||||
MockSpdyPeer.InFrame fin = peer.takeFrame();
|
||||
assertEquals(TYPE_DATA, fin.type);
|
||||
assertEquals(FLAG_FIN, fin.flags);
|
||||
assertTrue(fin.inFinished);
|
||||
assertFalse(fin.outFinished);
|
||||
MockSpdyPeer.InFrame rstStream = peer.takeFrame();
|
||||
assertEquals(TYPE_RST_STREAM, rstStream.type);
|
||||
assertEquals(SpdyStream.RST_CANCEL, rstStream.statusCode);
|
||||
@@ -520,14 +525,14 @@ public final class SpdyConnectionTest {
|
||||
@Test public void serverClosesClientInputStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().data(FLAG_FIN, 1, "square".getBytes(UTF_8));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().data(true, 1, "square".getBytes(UTF_8));
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection =
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(Arrays.asList("a", "android"), false, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
assertStreamData("square", in);
|
||||
@@ -536,15 +541,16 @@ public final class SpdyConnectionTest {
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
assertEquals(TYPE_SYN_STREAM, synStream.type);
|
||||
assertEquals(SpdyConnection.FLAG_FIN, synStream.flags);
|
||||
assertTrue(synStream.inFinished);
|
||||
assertFalse(synStream.outFinished);
|
||||
}
|
||||
|
||||
@Test public void remoteDoubleSynReply() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().ping(0, 1);
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.play();
|
||||
@@ -575,9 +581,9 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void remoteDoubleSynStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(0, 2, 0, 0, 0, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.sendFrame().synStream(0, 2, 0, 0, 0, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, Arrays.asList("b", "banana"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.play();
|
||||
|
||||
@@ -607,9 +613,9 @@ public final class SpdyConnectionTest {
|
||||
@Test public void remoteSendsDataAfterInFinished() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().data(SpdyConnection.FLAG_FIN, 1, "robot".getBytes("UTF-8"));
|
||||
peer.sendFrame().data(SpdyConnection.FLAG_FIN, 1, "c3po".getBytes("UTF-8")); // Ignored.
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().data(true, 1, "robot".getBytes("UTF-8"));
|
||||
peer.sendFrame().data(true, 1, "c3po".getBytes("UTF-8")); // Ignored.
|
||||
peer.sendFrame().ping(0, 2); // Ping just to make sure the stream was fastforwarded.
|
||||
peer.acceptFrame(); // PING
|
||||
peer.play();
|
||||
@@ -632,8 +638,8 @@ public final class SpdyConnectionTest {
|
||||
@Test public void remoteSendsTooMuchData() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().data(0, 1, new byte[64 * 1024 + 1]);
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("b", "banana"));
|
||||
peer.sendFrame().data(false, 1, new byte[64 * 1024 + 1]);
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(0, 2); // Ping just to make sure the stream was fastforwarded.
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -735,7 +741,7 @@ public final class SpdyConnectionTest {
|
||||
peer.acceptFrame(); // SYN_STREAM 1
|
||||
peer.acceptFrame(); // GOAWAY
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synStream(0, 2, 0, 0, 0, Arrays.asList("b", "b")); // Should be ignored!
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, Arrays.asList("b", "b")); // Should be ignored!
|
||||
peer.sendFrame().ping(0, 1);
|
||||
peer.play();
|
||||
|
||||
@@ -837,7 +843,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void readTimeoutExpires() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().ping(0, 1);
|
||||
peer.play();
|
||||
@@ -867,7 +873,7 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().headers(0, 1, Arrays.asList("c", "c3po"));
|
||||
peer.sendFrame().ping(0, 1);
|
||||
peer.play();
|
||||
@@ -918,12 +924,12 @@ public final class SpdyConnectionTest {
|
||||
@Test public void readSendsWindowUpdate() throws Exception {
|
||||
// Write the mocking script.
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
peer.sendFrame().data(0, 1, new byte[WINDOW_UPDATE_THRESHOLD]);
|
||||
peer.sendFrame().data(false, 1, new byte[WINDOW_UPDATE_THRESHOLD]);
|
||||
peer.acceptFrame(); // WINDOW UPDATE
|
||||
}
|
||||
peer.sendFrame().data(FLAG_FIN, 1, new byte[0]);
|
||||
peer.sendFrame().data(true, 1, new byte[0]);
|
||||
peer.play();
|
||||
|
||||
// Play it back.
|
||||
@@ -982,8 +988,8 @@ public final class SpdyConnectionTest {
|
||||
@Test public void testTruncatedDataFrame() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(0, 1, Arrays.asList("a", "android"));
|
||||
peer.sendTruncatedFrame(8 + 100).data(0, 1, new byte[1024]);
|
||||
peer.sendFrame().synReply(false, 1, Arrays.asList("a", "android"));
|
||||
peer.sendTruncatedFrame(8 + 100).data(false, 1, new byte[1024]);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
|
||||
Reference in New Issue
Block a user