1
0
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:
Jake Wharton
2013-08-14 13:38:32 -07:00
9 changed files with 248 additions and 224 deletions

View File

@@ -65,7 +65,6 @@
<property name="max" value="100"/>
</module>
<module name="MethodLength"/>
<module name="ParameterNumber"/>
<!-- Checks for whitespace -->

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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;
}
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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