diff --git a/okcurl/src/main/java/com/squareup/okhttp/curl/Main.java b/okcurl/src/main/java/com/squareup/okhttp/curl/Main.java index 4cc8c41da..b3ceb7f0c 100644 --- a/okcurl/src/main/java/com/squareup/okhttp/curl/Main.java +++ b/okcurl/src/main/java/com/squareup/okhttp/curl/Main.java @@ -25,7 +25,8 @@ import com.squareup.okhttp.Request; import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; import com.squareup.okhttp.internal.http.StatusLine; -import com.squareup.okhttp.internal.spdy.Http20Draft12; +import com.squareup.okhttp.internal.spdy.Http20Draft13; + import io.airlift.command.Arguments; import io.airlift.command.Command; import io.airlift.command.HelpOption; @@ -265,7 +266,7 @@ public class Main extends HelpOption implements Runnable { } private static void enableHttp2FrameLogging() { - Logger logger = Logger.getLogger(Http20Draft12.class.getName()); + Logger logger = Logger.getLogger(Http20Draft13.class.getName()); logger.setLevel(Level.FINE); ConsoleHandler handler = new ConsoleHandler(); handler.setLevel(Level.FINE); diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft12Test.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft13Test.java similarity index 96% rename from okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft12Test.java rename to okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft13Test.java index 5ac3b114b..b78fd1042 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft12Test.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverHttp20Draft13Test.java @@ -24,9 +24,9 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; -public class HttpOverHttp20Draft12Test extends HttpOverSpdyTest { +public class HttpOverHttp20Draft13Test extends HttpOverSpdyTest { - public HttpOverHttp20Draft12Test() { + public HttpOverHttp20Draft13Test() { super(Protocol.HTTP_2); this.hostHeader = ":authority"; } diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft07Test.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft08Test.java similarity index 97% rename from okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft07Test.java rename to okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft08Test.java index 6bff540f1..2b74c8df5 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft07Test.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft08Test.java @@ -30,23 +30,23 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class HpackDraft07Test { +public class HpackDraft08Test { private final Buffer bytesIn = new Buffer(); - private HpackDraft07.Reader hpackReader; + private HpackDraft08.Reader hpackReader; private Buffer bytesOut = new Buffer(); - private HpackDraft07.Writer hpackWriter; + private HpackDraft08.Writer hpackWriter; @Before public void reset() { hpackReader = newReader(bytesIn); - hpackWriter = new HpackDraft07.Writer(bytesOut); + hpackWriter = new HpackDraft08.Writer(bytesOut); } /** * Variable-length quantity special cases strings which are longer than 127 * bytes. Values such as cookies can be 4KiB, and should be possible to send. * - *

http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-4.1.1 + *

http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#section-4.1.1 */ @Test public void largeHeaderValue() throws IOException { char[] value = new char[4096]; @@ -157,7 +157,7 @@ public class HpackDraft07Test { // Indexed name (idx = 4) -> :path bytesIn.writeByte(0x8c); // Literal value Huffman encoded 12 bytes // decodes to www.example.com which is length 15 - bytesIn.write(decodeHex("e7cf9bebe89b6fb16fa9b6ff")); + bytesIn.write(decodeHex("f1e3c2e5f23a6ba0ab90f4ff")); hpackReader.readHeaders(); hpackReader.emitReferenceSet(); @@ -171,7 +171,7 @@ public class HpackDraft07Test { } /** - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.1.1 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.1.1 */ @Test public void readLiteralHeaderFieldWithIndexing() throws IOException { bytesIn.writeByte(0x40); // Literal indexed @@ -195,7 +195,7 @@ public class HpackDraft07Test { } /** - * https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.2.2 + * https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.2.2 */ @Test public void literalHeaderFieldWithoutIndexingIndexedName() throws IOException { List

headerBlock = headerEntries(":path", "/sample/path"); @@ -268,7 +268,7 @@ public class HpackDraft07Test { } /** - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.1.3 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.1.3 */ @Test public void readIndexedHeaderField() throws IOException { bytesIn.writeByte(0x82); // == Indexed - Add == @@ -379,7 +379,7 @@ public class HpackDraft07Test { } /** - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.2.1 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#section-3.2.1 */ @Test public void toggleIndex() throws IOException { // Static table entries are copied to the top of the reference set. @@ -444,7 +444,7 @@ public class HpackDraft07Test { } /** - * https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.2.4 + * https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.2.4 */ @Test public void readIndexedHeaderFieldFromStaticTableWithoutBuffering() throws IOException { bytesIn.writeByte(0x82); // == Indexed - Add == @@ -461,7 +461,7 @@ public class HpackDraft07Test { } /** - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.2 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.2 */ @Test public void readRequestExamplesWithoutHuffman() throws IOException { firstRequestWithoutHuffman(); @@ -648,7 +648,7 @@ public class HpackDraft07Test { } /** - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-D.3 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-D.3 */ @Test public void readRequestExamplesWithHuffman() throws IOException { firstRequestWithHuffman(); @@ -676,9 +676,9 @@ public class HpackDraft07Test { // idx = 6 -> :path: / bytesIn.writeByte(0x44); // == Literal indexed == // Indexed name (idx = 4) -> :authority - bytesIn.writeByte(0x8c); // Literal value Huffman encoded 12 bytes + bytesIn.writeByte(0x0f); // Literal value Huffman encoded 12 bytes // decodes to www.example.com which is length 15 - bytesIn.write(decodeHex("e7cf9bebe89b6fb16fa9b6ff")); + bytesIn.write(decodeHex("7777772e6578616d706c652e636f6d")); } private void checkReadFirstRequestWithHuffman() { @@ -720,7 +720,7 @@ public class HpackDraft07Test { // Indexed name (idx = 28) -> cache-control bytesIn.writeByte(0x86); // Literal value Huffman encoded 6 bytes // decodes to no-cache which is length 8 - bytesIn.write(decodeHex("b9b9949556bf")); + bytesIn.write(decodeHex("a8eb10649cbf")); } private void checkReadSecondRequestWithHuffman() { @@ -776,10 +776,10 @@ public class HpackDraft07Test { bytesIn.writeByte(0x40); // Literal indexed bytesIn.writeByte(0x88); // Literal name Huffman encoded 8 bytes // decodes to custom-key which is length 10 - bytesIn.write(decodeHex("571c5cdb737b2faf")); - bytesIn.writeByte(0x89); // Literal value Huffman encoded 6 bytes + bytesIn.write(decodeHex("25a849e95ba97d7f")); + bytesIn.writeByte(0x89); // Literal value Huffman encoded 9 bytes // decodes to custom-value which is length 12 - bytesIn.write(decodeHex("571c5cdb73724d9c57")); + bytesIn.write(decodeHex("25a849e95bb8e8b4bf")); } private void checkReadThirdRequestWithHuffman() { @@ -906,8 +906,8 @@ public class HpackDraft07Test { assertEquals(ByteString.EMPTY, newReader(byteStream(0)).readByteString()); } - private HpackDraft07.Reader newReader(Buffer source) { - return new HpackDraft07.Reader(4096, source); + private HpackDraft08.Reader newReader(Buffer source) { + return new HpackDraft08.Reader(4096, source); } private Buffer byteStream(int... bytes) { diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12FrameLoggerTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13FrameLoggerTest.java similarity index 69% rename from okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12FrameLoggerTest.java rename to okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13FrameLoggerTest.java index d0ebd5340..3ab2ca39c 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12FrameLoggerTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13FrameLoggerTest.java @@ -20,22 +20,22 @@ import java.util.Arrays; import java.util.List; import org.junit.Test; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_ACK; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_END_HEADERS; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_END_STREAM; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_NONE; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FrameLogger.formatFlags; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FrameLogger.formatHeader; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_CONTINUATION; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_DATA; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_GOAWAY; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_HEADERS; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_PING; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_PUSH_PROMISE; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.TYPE_SETTINGS; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_ACK; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_END_HEADERS; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_END_STREAM; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_NONE; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FrameLogger.formatFlags; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FrameLogger.formatHeader; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_CONTINUATION; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_DATA; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_GOAWAY; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_HEADERS; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_PING; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_PUSH_PROMISE; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.TYPE_SETTINGS; import static org.junit.Assert.assertEquals; -public class Http20Draft12FrameLoggerTest { +public class Http20Draft13FrameLoggerTest { /** Real stream traffic applied to the log format. */ @Test public void exampleStream() { @@ -103,14 +103,14 @@ public class Http20Draft12FrameLoggerTest { "END_STREAM|END_HEADERS", "END_SEGMENT|END_HEADERS", "END_STREAM|END_SEGMENT|END_HEADERS", - "PAD_LOW", - "END_STREAM|PAD_LOW", - "END_SEGMENT|PAD_LOW", - "END_STREAM|END_SEGMENT|PAD_LOW", + "PADDED", + "END_STREAM|PADDED", + "END_SEGMENT|PADDED", + "END_STREAM|END_SEGMENT|PADDED", "00001100", - "END_STREAM|END_HEADERS|PAD_LOW", - "END_SEGMENT|END_HEADERS|PAD_LOW", - "END_STREAM|END_SEGMENT|END_HEADERS|PAD_LOW", + "END_STREAM|END_HEADERS|PADDED", + "END_SEGMENT|END_HEADERS|PADDED", + "END_STREAM|END_SEGMENT|END_HEADERS|PADDED", "00010000", "00010001", "00010010", @@ -119,14 +119,14 @@ public class Http20Draft12FrameLoggerTest { "00010101", "00010110", "00010111", - "PAD_LOW|PAD_HIGH", - "END_STREAM|PAD_LOW|PAD_HIGH", - "END_SEGMENT|PAD_LOW|PAD_HIGH", - "END_STREAM|END_SEGMENT|PAD_LOW|PAD_HIGH", + "00011000", + "00011001", + "00011010", + "00011011", "00011100", - "END_STREAM|END_HEADERS|PAD_LOW|PAD_HIGH", - "END_SEGMENT|END_HEADERS|PAD_LOW|PAD_HIGH", - "END_STREAM|END_SEGMENT|END_HEADERS|PAD_LOW|PAD_HIGH", + "00011101", + "00011110", + "00011111", "PRIORITY", "END_STREAM|PRIORITY", "END_SEGMENT|PRIORITY", @@ -136,13 +136,13 @@ public class Http20Draft12FrameLoggerTest { "END_SEGMENT|END_HEADERS|PRIORITY", "END_STREAM|END_SEGMENT|END_HEADERS|PRIORITY", "00101000", - "END_STREAM|PRIORITY|PAD_LOW", - "END_SEGMENT|PRIORITY|PAD_LOW", - "END_STREAM|END_SEGMENT|PRIORITY|PAD_LOW", + "END_STREAM|PRIORITY|PADDED", + "END_SEGMENT|PRIORITY|PADDED", + "END_STREAM|END_SEGMENT|PRIORITY|PADDED", "00101100", - "END_STREAM|END_HEADERS|PRIORITY|PAD_LOW", - "END_SEGMENT|END_HEADERS|PRIORITY|PAD_LOW", - "END_STREAM|END_SEGMENT|END_HEADERS|PRIORITY|PAD_LOW", + "END_STREAM|END_HEADERS|PRIORITY|PADDED", + "END_SEGMENT|END_HEADERS|PRIORITY|PADDED", + "END_STREAM|END_SEGMENT|END_HEADERS|PRIORITY|PADDED", "00110000", "00110001", "00110010", @@ -152,13 +152,13 @@ public class Http20Draft12FrameLoggerTest { "00110110", "00110111", "00111000", - "END_STREAM|PRIORITY|PAD_LOW|PAD_HIGH", - "END_SEGMENT|PRIORITY|PAD_LOW|PAD_HIGH", - "END_STREAM|END_SEGMENT|PRIORITY|PAD_LOW|PAD_HIGH", + "00111001", + "00111010", + "00111011", "00111100", - "END_STREAM|END_HEADERS|PRIORITY|PAD_LOW|PAD_HIGH", - "END_SEGMENT|END_HEADERS|PRIORITY|PAD_LOW|PAD_HIGH", - "END_STREAM|END_SEGMENT|END_HEADERS|PRIORITY|PAD_LOW|PAD_HIGH" + "00111101", + "00111110", + "00111111" ), formattedFlags); } } diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12Test.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13Test.java similarity index 55% rename from okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12Test.java rename to okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13Test.java index bf2b43a8a..4f626fa80 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft12Test.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft13Test.java @@ -15,49 +15,44 @@ */ package com.squareup.okhttp.internal.spdy; -import com.squareup.okhttp.Protocol; -import com.squareup.okhttp.internal.Util; import java.io.IOException; import java.util.Arrays; import java.util.List; + +import com.squareup.okhttp.internal.Util; + +import org.junit.Test; + import okio.Buffer; import okio.BufferedSource; import okio.ByteString; import okio.GzipSink; import okio.Okio; -import org.junit.Test; - import static com.squareup.okhttp.internal.Util.headerEntries; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_COMPRESSED; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_END_HEADERS; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_END_STREAM; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_NONE; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_PAD_HIGH; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_PAD_LOW; -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FLAG_PRIORITY; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_COMPRESSED; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_END_HEADERS; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_END_STREAM; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_NONE; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_PADDED; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FLAG_PRIORITY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class Http20Draft12Test { +public class Http20Draft13Test { final Buffer frame = new Buffer(); - final FrameReader fr = new Http20Draft12.Reader(frame, 4096, false); + final FrameReader fr = new Http20Draft13.Reader(frame, 4096, false); final int expectedStreamId = 15; - @Test public void unknownFrameTypeProtocolError() throws IOException { + @Test public void unknownFrameTypeSkipped() throws IOException { frame.writeShort(4); // has a 4-byte field frame.writeByte(99); // type 99 frame.writeByte(0); // no flags frame.writeInt(expectedStreamId); frame.writeInt(111111111); // custom data - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR: unknown frame type 99", e.getMessage()); - } + fr.nextFrame(new BaseTestHandler()); // Should not callback. } @Test public void onlyOneLiteralHeadersFrame() throws IOException { @@ -65,7 +60,7 @@ public class Http20Draft12Test { Buffer headerBytes = literalHeaders(sentHeaders); frame.writeShort((int) headerBytes.size()); - frame.writeByte(Http20Draft12.TYPE_HEADERS); + frame.writeByte(Http20Draft13.TYPE_HEADERS); frame.writeByte(FLAG_END_HEADERS | FLAG_END_STREAM); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeAll(headerBytes); @@ -91,7 +86,7 @@ public class Http20Draft12Test { Buffer headerBytes = literalHeaders(sentHeaders); frame.writeShort((int) (headerBytes.size() + 5)); - frame.writeByte(Http20Draft12.TYPE_HEADERS); + frame.writeByte(Http20Draft13.TYPE_HEADERS); frame.writeByte(FLAG_END_HEADERS | FLAG_PRIORITY); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeInt(0); // Independent stream. @@ -126,15 +121,15 @@ public class Http20Draft12Test { Buffer headerBlock = literalHeaders(sentHeaders); // Write the first headers frame. - frame.writeShort(Http20Draft12.MAX_FRAME_SIZE); - frame.writeByte(Http20Draft12.TYPE_HEADERS); + frame.writeShort(Http20Draft13.MAX_FRAME_SIZE); + frame.writeByte(Http20Draft13.TYPE_HEADERS); frame.writeByte(0); // no flags frame.writeInt(expectedStreamId & 0x7fffffff); - frame.write(headerBlock, Http20Draft12.MAX_FRAME_SIZE); + frame.write(headerBlock, Http20Draft13.MAX_FRAME_SIZE); // Write the continuation frame, specifying no more frames are expected. frame.writeShort((int) headerBlock.size()); - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); + frame.writeByte(Http20Draft13.TYPE_CONTINUATION); frame.writeByte(FLAG_END_HEADERS); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeAll(headerBlock); @@ -168,8 +163,8 @@ public class Http20Draft12Test { // Write the push promise frame, specifying the associated stream ID. Buffer headerBytes = literalHeaders(pushPromise); frame.writeShort((int) (headerBytes.size() + 4)); - frame.writeByte(Http20Draft12.TYPE_PUSH_PROMISE); - frame.writeByte(Http20Draft12.FLAG_END_PUSH_PROMISE); + frame.writeByte(Http20Draft13.TYPE_PUSH_PROMISE); + frame.writeByte(Http20Draft13.FLAG_END_PUSH_PROMISE); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeInt(expectedPromisedStreamId & 0x7fffffff); frame.writeAll(headerBytes); @@ -195,8 +190,8 @@ public class Http20Draft12Test { Buffer headerBlock = literalHeaders(pushPromise); // Write the first headers frame. - frame.writeShort(Http20Draft12.MAX_FRAME_SIZE); - frame.writeByte(Http20Draft12.TYPE_PUSH_PROMISE); + frame.writeShort(Http20Draft13.MAX_FRAME_SIZE); + frame.writeByte(Http20Draft13.TYPE_PUSH_PROMISE); frame.writeByte(0); // no flags frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeInt(expectedPromisedStreamId & 0x7fffffff); @@ -204,7 +199,7 @@ public class Http20Draft12Test { // Write the continuation frame, specifying no more frames are expected. frame.writeShort((int) headerBlock.size()); - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); + frame.writeByte(Http20Draft13.TYPE_CONTINUATION); frame.writeByte(FLAG_END_HEADERS); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeAll(headerBlock); @@ -224,7 +219,7 @@ public class Http20Draft12Test { @Test public void readRstStreamFrame() throws IOException { frame.writeShort(4); - frame.writeByte(Http20Draft12.TYPE_RST_STREAM); + frame.writeByte(Http20Draft13.TYPE_RST_STREAM); frame.writeByte(0); // No flags frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeInt(ErrorCode.COMPRESSION_ERROR.httpCode); @@ -240,15 +235,13 @@ public class Http20Draft12Test { @Test public void readSettingsFrame() throws IOException { final int reducedTableSizeBytes = 16; - frame.writeShort(15); // 3 settings * 5 bytes (1 for the code and 4 for the value). - frame.writeByte(Http20Draft12.TYPE_SETTINGS); + frame.writeShort(12); // 2 settings * 6 bytes (2 for the code and 4 for the value). + frame.writeByte(Http20Draft13.TYPE_SETTINGS); frame.writeByte(0); // No flags frame.writeInt(0); // Settings are always on the connection stream 0. - frame.writeByte(1); // SETTINGS_HEADER_TABLE_SIZE + frame.writeShort(1); // SETTINGS_HEADER_TABLE_SIZE frame.writeInt(reducedTableSizeBytes); - frame.writeByte(2); // SETTINGS_ENABLE_PUSH - frame.writeInt(0); - frame.writeByte(5); // SETTINGS_COMPRESS_DATA + frame.writeShort(2); // SETTINGS_ENABLE_PUSH frame.writeInt(0); fr.nextFrame(new BaseTestHandler() { @@ -256,17 +249,16 @@ public class Http20Draft12Test { assertFalse(clearPrevious); // No clearPrevious in HTTP/2. assertEquals(reducedTableSizeBytes, settings.getHeaderTableSize()); assertEquals(false, settings.getEnablePush(true)); - assertEquals(false, settings.getCompressData(true)); } }); } @Test public void readSettingsFrameInvalidPushValue() throws IOException { - frame.writeShort(5); // 1 for the code and 4 for the value - frame.writeByte(Http20Draft12.TYPE_SETTINGS); + frame.writeShort(6); // 2 for the code and 4 for the value + frame.writeByte(Http20Draft13.TYPE_SETTINGS); frame.writeByte(0); // No flags frame.writeInt(0); // Settings are always on the connection stream 0. - frame.writeByte(2); + frame.writeShort(2); frame.writeInt(2); try { @@ -278,11 +270,11 @@ public class Http20Draft12Test { } @Test public void readSettingsFrameInvalidSettingId() throws IOException { - frame.writeShort(5); // 1 for the code and 4 for the value - frame.writeByte(Http20Draft12.TYPE_SETTINGS); + frame.writeShort(6); // 2 for the code and 4 for the value + frame.writeByte(Http20Draft13.TYPE_SETTINGS); frame.writeByte(0); // No flags frame.writeInt(0); // Settings are always on the connection stream 0. - frame.writeByte(7); // old number for SETTINGS_INITIAL_WINDOW_SIZE + frame.writeShort(7); // old number for SETTINGS_INITIAL_WINDOW_SIZE frame.writeInt(1); try { @@ -294,11 +286,11 @@ public class Http20Draft12Test { } @Test public void readSettingsFrameNegativeWindowSize() throws IOException { - frame.writeShort(5); // 1 for the code and 4 for the value - frame.writeByte(Http20Draft12.TYPE_SETTINGS); + frame.writeShort(6); // 2 for the code and 4 for the value + frame.writeByte(Http20Draft13.TYPE_SETTINGS); frame.writeByte(0); // No flags frame.writeInt(0); // Settings are always on the connection stream 0. - frame.writeByte(4); // SETTINGS_INITIAL_WINDOW_SIZE + frame.writeShort(4); // SETTINGS_INITIAL_WINDOW_SIZE frame.writeInt(Integer.MIN_VALUE); try { @@ -314,8 +306,8 @@ public class Http20Draft12Test { final int expectedPayload2 = 8; frame.writeShort(8); // length - frame.writeByte(Http20Draft12.TYPE_PING); - frame.writeByte(Http20Draft12.FLAG_ACK); + frame.writeByte(Http20Draft13.TYPE_PING); + frame.writeByte(Http20Draft13.FLAG_ACK); frame.writeInt(0); // connection-level frame.writeInt(expectedPayload1); frame.writeInt(expectedPayload2); @@ -333,11 +325,11 @@ public class Http20Draft12Test { } @Test public void maxLengthDataFrame() throws IOException { - final byte[] expectedData = new byte[Http20Draft12.MAX_FRAME_SIZE]; + final byte[] expectedData = new byte[Http20Draft13.MAX_FRAME_SIZE]; Arrays.fill(expectedData, (byte) 2); frame.writeShort(expectedData.length); - frame.writeByte(Http20Draft12.TYPE_DATA); + frame.writeByte(Http20Draft13.TYPE_DATA); frame.writeByte(0); // no flags frame.writeInt(expectedStreamId & 0x7fffffff); frame.write(expectedData); @@ -350,7 +342,7 @@ public class Http20Draft12Test { int length) throws IOException { assertFalse(inFinished); assertEquals(expectedStreamId, streamId); - assertEquals(Http20Draft12.MAX_FRAME_SIZE, length); + assertEquals(Http20Draft13.MAX_FRAME_SIZE, length); ByteString data = source.readByteString(length); for (byte b : data.toByteArray()) { assertEquals(2, b); @@ -361,13 +353,13 @@ public class Http20Draft12Test { /** We do not send SETTINGS_COMPRESS_DATA = 1, nor want to. Let's make sure we error. */ @Test public void compressedDataFrameWhenSettingDisabled() throws IOException { - byte[] expectedData = new byte[Http20Draft12.MAX_FRAME_SIZE]; + byte[] expectedData = new byte[Http20Draft13.MAX_FRAME_SIZE]; Arrays.fill(expectedData, (byte) 2); Buffer zipped = gzip(expectedData); int zippedSize = (int) zipped.size(); frame.writeShort(zippedSize); - frame.writeByte(Http20Draft12.TYPE_DATA); + frame.writeByte(Http20Draft13.TYPE_DATA); frame.writeByte(FLAG_COMPRESSED); frame.writeInt(expectedStreamId & 0x7fffffff); zipped.readAll(frame); @@ -386,15 +378,15 @@ public class Http20Draft12Test { byte[] expectedData = new byte[dataLength]; Arrays.fill(expectedData, (byte) 2); - int paddingLength = 257; + int paddingLength = 254; byte[] padding = new byte[paddingLength]; Arrays.fill(padding, (byte) 0); - frame.writeShort(dataLength + paddingLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_DATA); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); + frame.writeShort(dataLength + paddingLength + 1); + frame.writeByte(Http20Draft13.TYPE_DATA); + frame.writeByte(FLAG_PADDED); frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); + frame.writeByte(paddingLength); frame.write(expectedData); frame.write(padding); @@ -402,29 +394,14 @@ public class Http20Draft12Test { assertTrue(frame.exhausted()); // Padding was skipped. } - @Test public void readPaddedDataFrameZeroPaddingHigh() throws IOException { - int dataLength = 1123; - byte[] expectedData = new byte[dataLength]; - Arrays.fill(expectedData, (byte) 2); - - frame.writeShort(dataLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_DATA); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0); - frame.write(expectedData); - - fr.nextFrame(assertData()); - } - - @Test public void readPaddedDataFrameZeroPaddingLow() throws IOException { + @Test public void readPaddedDataFrameZeroPadding() throws IOException { int dataLength = 1123; byte[] expectedData = new byte[dataLength]; Arrays.fill(expectedData, (byte) 2); frame.writeShort(dataLength + 1); - frame.writeByte(Http20Draft12.TYPE_DATA); - frame.writeByte(FLAG_PAD_LOW); + frame.writeByte(Http20Draft13.TYPE_DATA); + frame.writeByte(FLAG_PADDED); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeByte(0); frame.write(expectedData); @@ -432,69 +409,17 @@ public class Http20Draft12Test { fr.nextFrame(assertData()); } - @Test public void readPaddedDataFrameMissingLowFlag() throws IOException { - int dataLength = 1123; - byte[] expectedData = new byte[dataLength]; - Arrays.fill(expectedData, (byte) 2); - - int paddingLength = 257; - byte[] padding = new byte[paddingLength]; - Arrays.fill(padding, (byte) 0); - - frame.writeShort(dataLength + paddingLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_DATA); - frame.writeByte(FLAG_PAD_HIGH); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); - frame.write(expectedData); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR FLAG_PAD_HIGH set without FLAG_PAD_LOW", e.getMessage()); - } - } - - /** - * Padding is encoded over 2 bytes, so maximum value is 65535, but maximum frame size is Http20Draft12.MAX_FRAME_SIZE. - */ - @Test public void readPaddedDataFrameWithTooMuchPadding() throws IOException { - int dataLength = 1123; - byte[] expectedData = new byte[dataLength]; - Arrays.fill(expectedData, (byte) 2); - - final byte[] padding = new byte[0xffff]; - Arrays.fill(padding, (byte) 0); - - frame.writeShort(dataLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0xffff); - frame.write(expectedData); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR padding > 16383: 65535", e.getMessage()); - } - } - @Test public void readPaddedHeadersFrame() throws IOException { - int paddingLength = 257; + int paddingLength = 254; byte[] padding = new byte[paddingLength]; Arrays.fill(padding, (byte) 0); Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - frame.writeShort((int) headerBlock.size() + paddingLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_HIGH | FLAG_PAD_LOW); + frame.writeShort((int) headerBlock.size() + paddingLength + 1); + frame.writeByte(Http20Draft13.TYPE_HEADERS); + frame.writeByte(FLAG_END_HEADERS | FLAG_PADDED); frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); + frame.writeByte(paddingLength); frame.writeAll(headerBlock); frame.write(padding); @@ -502,23 +427,11 @@ public class Http20Draft12Test { assertTrue(frame.exhausted()); // Padding was skipped. } - @Test public void readPaddedHeadersFrameZeroPaddingHigh() throws IOException { + @Test public void readPaddedHeadersFrameZeroPadding() throws IOException { Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - frame.writeShort((int) headerBlock.size() + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0); - frame.writeAll(headerBlock); - - fr.nextFrame(assertHeaderBlock()); - } - - @Test public void readPaddedHeadersFrameZeroPaddingLow() throws IOException { - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - frame.writeShort((int) headerBlock.size() + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_LOW); + frame.writeShort((int) headerBlock.size() + 1); + frame.writeByte(Http20Draft13.TYPE_HEADERS); + frame.writeByte(FLAG_END_HEADERS | FLAG_PADDED); frame.writeInt(expectedStreamId & 0x7fffffff); frame.writeByte(0); frame.writeAll(headerBlock); @@ -526,55 +439,9 @@ public class Http20Draft12Test { fr.nextFrame(assertHeaderBlock()); } - @Test public void readPaddedHeadersFrameMissingLowFlag() throws IOException { - int paddingLength = 257; - byte[] padding = new byte[paddingLength]; - Arrays.fill(padding, (byte) 0); - - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - frame.writeShort((int) headerBlock.size() + 1); - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_PAD_HIGH); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); - frame.writeAll(headerBlock); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR FLAG_PAD_HIGH set without FLAG_PAD_LOW", e.getMessage()); - } - } - - /** - * Padding is encoded over 2 bytes, so maximum value is 65535, but maximum frame size is Http20Draft12.MAX_FRAME_SIZE. - */ - @Test public void readPaddedHeadersFrameWithTooMuchPadding() throws IOException { - byte[] padding = new byte[0xffff]; - Arrays.fill(padding, (byte) 0); - - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - frame.writeShort((int) headerBlock.size() + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0xffff); - frame.writeAll(headerBlock); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR padding > 16383: 65535", e.getMessage()); - } - } - /** Headers are compressed, then framed. */ @Test public void readPaddedHeadersFrameThenContinuation() throws IOException { - int paddingLength = 257; + int paddingLength = 254; byte[] padding = new byte[paddingLength]; Arrays.fill(padding, (byte) 0); @@ -582,130 +449,23 @@ public class Http20Draft12Test { Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); // Write the first headers frame. - frame.writeShort((int) (headerBlock.size() / 2) + paddingLength + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); + frame.writeShort((int) (headerBlock.size() / 2) + paddingLength + 1); + frame.writeByte(Http20Draft13.TYPE_HEADERS); + frame.writeByte(FLAG_PADDED); frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); + frame.writeByte(paddingLength); frame.write(headerBlock, headerBlock.size() / 2); frame.write(padding); // Write the continuation frame, specifying no more frames are expected. - frame.writeShort((int) headerBlock.size() + paddingLength + 2); - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); // 2 for PAD_HIGH,LOW. - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_HIGH | FLAG_PAD_LOW); + frame.writeShort((int) headerBlock.size()); + frame.writeByte(Http20Draft13.TYPE_CONTINUATION); + frame.writeByte(FLAG_END_HEADERS); frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); - frame.writeAll(headerBlock); - frame.write(padding); - - fr.nextFrame(assertHeaderBlock()); - assertTrue(frame.exhausted()); // Padding was skipped. - } - - @Test public void readPaddedContinuationFrameZeroPaddingHigh() throws IOException { - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - - // Write the first headers frame. - frame.writeShort((int) (headerBlock.size() / 2)); - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(0); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.write(headerBlock, headerBlock.size() / 2); - - // Write the continuation frame, specifying no more frames are expected. - frame.writeShort((int) headerBlock.size() + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0); frame.writeAll(headerBlock); fr.nextFrame(assertHeaderBlock()); - } - - @Test public void readPaddedContinuationFrameZeroPaddingLow() throws IOException { - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - - // Write the first headers frame. - frame.writeShort((int) (headerBlock.size() / 2)); - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(0); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.write(headerBlock, headerBlock.size() / 2); - - // Write the continuation frame, specifying no more frames are expected. - frame.writeShort((int) headerBlock.size() + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); - frame.writeByte(FLAG_END_HEADERS | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeByte(0); - frame.writeAll(headerBlock); - - fr.nextFrame(assertHeaderBlock()); - } - - @Test public void readPaddedContinuationFrameMissingLowFlag() throws IOException { - int paddingLength = 257; - byte[] padding = new byte[paddingLength]; - Arrays.fill(padding, (byte) 0); - - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - - // Write the first headers frame. - frame.writeShort((int) (headerBlock.size() / 2)); - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(0); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.write(headerBlock, headerBlock.size() / 2); - - // Write the continuation frame, specifying no more frames are expected. - frame.writeShort((int) headerBlock.size() + 1); - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); - frame.writeByte(FLAG_PAD_HIGH); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(paddingLength); - frame.writeAll(headerBlock); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR FLAG_PAD_HIGH set without FLAG_PAD_LOW", e.getMessage()); - } - } - - /** - * Padding is encoded over 2 bytes, so maximum value is 65535, but maximum frame size is Http20Draft12.MAX_FRAME_SIZE. - */ - @Test public void readPaddedContinuationFrameWithTooMuchPadding() throws IOException { - byte[] padding = new byte[0xffff]; - Arrays.fill(padding, (byte) 0); - - Buffer headerBlock = literalHeaders(headerEntries("foo", "barrr", "baz", "qux")); - // Write the first headers frame. - frame.writeShort((int) (headerBlock.size() / 2)); - frame.writeByte(Http20Draft12.TYPE_HEADERS); - frame.writeByte(0); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.write(headerBlock, headerBlock.size() / 2); - - // Write the continuation frame, specifying no more frames are expected. - frame.writeShort((int) (headerBlock.size() / 2) + 2); // 2 for PAD_HIGH,LOW. - frame.writeByte(Http20Draft12.TYPE_CONTINUATION); - frame.writeByte(FLAG_PAD_HIGH | FLAG_PAD_LOW); - frame.writeInt(expectedStreamId & 0x7fffffff); - frame.writeShort(0xffff); - frame.write(headerBlock, (headerBlock.size() / 2)); - frame.write(padding); - - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("PROTOCOL_ERROR padding > 16383: 65535", e.getMessage()); - } + assertTrue(frame.exhausted()); } @Test public void tooLargeDataFrame() throws IOException { @@ -721,7 +481,7 @@ public class Http20Draft12Test { final long expectedWindowSizeIncrement = 0x7fffffff; frame.writeShort(4); // length - frame.writeByte(Http20Draft12.TYPE_WINDOW_UPDATE); + frame.writeByte(Http20Draft13.TYPE_WINDOW_UPDATE); frame.writeByte(0); // No flags. frame.writeInt(expectedStreamId); frame.writeInt((int) expectedWindowSizeIncrement); @@ -758,7 +518,7 @@ public class Http20Draft12Test { final ErrorCode expectedError = ErrorCode.PROTOCOL_ERROR; frame.writeShort(8); // Without debug data there's only 2 32-bit fields. - frame.writeByte(Http20Draft12.TYPE_GOAWAY); + frame.writeByte(Http20Draft13.TYPE_GOAWAY); frame.writeByte(0); // no flags. frame.writeInt(0); // connection-scope frame.writeInt(expectedStreamId); // last good stream. @@ -783,7 +543,7 @@ public class Http20Draft12Test { // Compose the expected GOAWAY frame without debug data. frame.writeShort(8 + expectedData.size()); - frame.writeByte(Http20Draft12.TYPE_GOAWAY); + frame.writeByte(Http20Draft13.TYPE_GOAWAY); frame.writeByte(0); // no flags. frame.writeInt(0); // connection-scope frame.writeInt(0); // never read any stream! @@ -804,10 +564,10 @@ public class Http20Draft12Test { } @Test public void frameSizeError() throws IOException { - Http20Draft12.Writer writer = new Http20Draft12.Writer(new Buffer(), true); + Http20Draft13.Writer writer = new Http20Draft13.Writer(new Buffer(), true); try { - writer.frameHeader(0, 16384, Http20Draft12.TYPE_DATA, FLAG_NONE); + writer.frameHeader(0, 16384, Http20Draft13.TYPE_DATA, FLAG_NONE); fail(); } catch (IllegalArgumentException e) { assertEquals("FRAME_SIZE_ERROR length > 16383: 16384", e.getMessage()); @@ -815,140 +575,59 @@ public class Http20Draft12Test { } @Test public void streamIdHasReservedBit() throws IOException { - Http20Draft12.Writer writer = new Http20Draft12.Writer(new Buffer(), true); + Http20Draft13.Writer writer = new Http20Draft13.Writer(new Buffer(), true); try { int streamId = 3; streamId |= 1L << 31; // set reserved bit - writer.frameHeader(streamId, Http20Draft12.MAX_FRAME_SIZE, Http20Draft12.TYPE_DATA, FLAG_NONE); + writer.frameHeader(streamId, Http20Draft13.MAX_FRAME_SIZE, Http20Draft13.TYPE_DATA, FLAG_NONE); fail(); } catch (IllegalArgumentException e) { assertEquals("reserved bit set: -2147483645", e.getMessage()); } } - @Test public void blockedFrameIgnored() throws IOException { - frame.writeShort(0); - frame.writeByte(Http20Draft12.TYPE_BLOCKED); - frame.writeByte(0); // no flags. - frame.writeInt(0); // connection-scope. - - fr.nextFrame(new BaseTestHandler()); // Should not callback. - } - - @Test public void blockedFrameIOEWithPayload() throws IOException { - frame.writeShort(4); - frame.writeByte(Http20Draft12.TYPE_BLOCKED); - frame.writeByte(0); // no flags. - frame.writeInt(0); // connection-scope. - frame.writeUtf8("abcd"); // Send a payload even though it is illegal. - - // Consume the unknown frame. - try { - fr.nextFrame(new BaseTestHandler()); - fail(); - } catch (IOException e) { - assertEquals("TYPE_BLOCKED length != 0: 4", e.getMessage()); - } - } - - @Test public void readAltSvcStreamOrigin() throws IOException { - frame.writeShort(9 + Protocol.HTTP_2.toString().length() + "www-2.example.com".length()); - frame.writeByte(Http20Draft12.TYPE_ALTSVC); - frame.writeByte(0); // No flags. - frame.writeInt(expectedStreamId); // Use stream origin. - frame.writeInt(0xffffffff); // Max-Age 32bit number. - frame.writeShort(443); // Port. - frame.writeByte(0); // Reserved. - frame.writeByte(Protocol.HTTP_2.toString().length()); // Proto-Len. - frame.writeUtf8(Protocol.HTTP_2.toString()); // Protocol-ID. - frame.writeByte("www-2.example.com".length()); // Host-Len. - frame.writeUtf8("www-2.example.com"); - - fr.nextFrame(new BaseTestHandler() { // Consume the alt-svc frame. - @Override public void alternateService(int streamId, String origin, ByteString protocol, - String host, int port, long maxAge) { - assertEquals(expectedStreamId, streamId); - assertEquals("", origin); - assertEquals(Protocol.HTTP_2.toString(), protocol.utf8()); - assertEquals("www-2.example.com", host); - assertEquals(443, port); - assertEquals(0xffffffffL, maxAge); - } - }); - } - - @Test public void readAltSvcAlternateOrigin() throws IOException { - frame.writeShort(9 - + Protocol.HTTP_2.toString().length() - + "www-2.example.com".length() - + "https://example.com:443".length()); - frame.writeByte(Http20Draft12.TYPE_ALTSVC); - frame.writeByte(0); // No flags. - frame.writeInt(0); // Specify origin. - frame.writeInt(0xffffffff); // Max-Age 32bit number. - frame.writeShort(443); // Port. - frame.writeByte(0); // Reserved. - frame.writeByte(Protocol.HTTP_2.toString().length()); // Proto-Len. - frame.writeUtf8(Protocol.HTTP_2.toString()); // Protocol-ID. - frame.writeByte("www-2.example.com".length()); // Host-Len. - frame.writeUtf8("www-2.example.com"); - frame.writeUtf8("https://example.com:443"); // Remainder is Origin. - - fr.nextFrame(new BaseTestHandler() { // Consume the alt-svc frame. - @Override public void alternateService(int streamId, String origin, ByteString protocol, - String host, int port, long maxAge) { - assertEquals(0, streamId); - assertEquals("https://example.com:443", origin); - assertEquals(Protocol.HTTP_2.toString(), protocol.utf8()); - assertEquals("www-2.example.com", host); - assertEquals(443, port); - assertEquals(0xffffffffL, maxAge); - } - }); - } - private Buffer literalHeaders(List
sentHeaders) throws IOException { Buffer out = new Buffer(); - new HpackDraft07.Writer(out).writeHeaders(sentHeaders); + new HpackDraft08.Writer(out).writeHeaders(sentHeaders); return out; } private Buffer sendHeaderFrames(boolean outFinished, List
headers) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).headers(outFinished, expectedStreamId, headers); + new Http20Draft13.Writer(out, true).headers(outFinished, expectedStreamId, headers); return out; } private Buffer sendPushPromiseFrames(int streamId, List
headers) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).pushPromise(expectedStreamId, streamId, headers); + new Http20Draft13.Writer(out, true).pushPromise(expectedStreamId, streamId, headers); return out; } private Buffer sendPingFrame(boolean ack, int payload1, int payload2) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).ping(ack, payload1, payload2); + new Http20Draft13.Writer(out, true).ping(ack, payload1, payload2); return out; } private Buffer sendGoAway(int lastGoodStreamId, ErrorCode errorCode, byte[] debugData) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).goAway(lastGoodStreamId, errorCode, debugData); + new Http20Draft13.Writer(out, true).goAway(lastGoodStreamId, errorCode, debugData); return out; } private Buffer sendDataFrame(Buffer data) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).dataFrame(expectedStreamId, FLAG_NONE, data, + new Http20Draft13.Writer(out, true).dataFrame(expectedStreamId, FLAG_NONE, data, (int) data.size()); return out; } private Buffer windowUpdate(long windowSizeIncrement) throws IOException { Buffer out = new Buffer(); - new Http20Draft12.Writer(out, true).windowUpdate(expectedStreamId, windowSizeIncrement); + new Http20Draft13.Writer(out, true).windowUpdate(expectedStreamId, windowSizeIncrement); return out; } diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http2ConnectionTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http2ConnectionTest.java index e700dd6c6..5f25e486c 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http2ConnectionTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/Http2ConnectionTest.java @@ -46,7 +46,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public final class Http2ConnectionTest { - private static final Variant HTTP_2 = new Http20Draft12(); + private static final Variant HTTP_2 = new Http20Draft13(); private final MockSpdyPeer peer = new MockSpdyPeer(); @After public void tearDown() throws Exception { @@ -140,7 +140,7 @@ public final class Http2ConnectionTest { // verify the peer's settings were read and applied. assertEquals(0, connection.peerSettings.getHeaderTableSize()); - Http20Draft12.Reader frameReader = (Http20Draft12.Reader) connection.readerRunnable.frameReader; + Http20Draft13.Reader frameReader = (Http20Draft13.Reader) connection.readerRunnable.frameReader; assertEquals(0, frameReader.hpackReader.maxHeaderTableByteCount()); // TODO: when supported, check the frameWriter's compression table is unaffected. } diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/MockSpdyPeer.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/MockSpdyPeer.java index 10025758c..7e1823b73 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/MockSpdyPeer.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/MockSpdyPeer.java @@ -278,7 +278,7 @@ public final class MockSpdyPeer implements Closeable { @Override public void pushPromise(int streamId, int associatedStreamId, List
headerBlock) { - this.type = Http20Draft12.TYPE_PUSH_PROMISE; + this.type = Http20Draft13.TYPE_PUSH_PROMISE; this.streamId = streamId; this.associatedStreamId = associatedStreamId; this.headerBlock = headerBlock; diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/SettingsTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/SettingsTest.java index 330566316..a33b1d52e 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/SettingsTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/SettingsTest.java @@ -62,14 +62,9 @@ public final class SettingsTest { settings.set(MAX_CONCURRENT_STREAMS, 0, 75); assertEquals(75, settings.getMaxConcurrentStreams(-3)); - // WARNING: clash on flags between spdy/3 and HTTP/2! assertEquals(-3, settings.getCurrentCwnd(-3)); settings.set(Settings.CURRENT_CWND, 0, 86); assertEquals(86, settings.getCurrentCwnd(-3)); - settings.clear(); - assertEquals(true, settings.getCompressData(true)); - settings.set(Settings.COMPRESS_DATA, 0, 1); - assertEquals(true, settings.getCompressData(false)); assertEquals(-3, settings.getDownloadRetransRate(-3)); settings.set(DOWNLOAD_RETRANS_RATE, 0, 97); diff --git a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java index 469b1f386..d52c68dca 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java +++ b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java @@ -399,11 +399,11 @@ public final class OkHttpClient implements Cloneable { * * *

This is an evolving set. Future releases may drop - * support for transitional protocols (like h2-12), in favor of their + * support for transitional protocols (like h2-13), in favor of their * successors (h2). The http/1.1 transport will never be dropped. * *

If multiple protocols are specified, This version of OkHttp implements HTTP/2 draft 12 + * href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-13">draft 12 * with HPACK draft + * href="http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08">draft * 6. Future releases of OkHttp may use this identifier for a newer draft * of these specs. */ - HTTP_2("h2-12"); + HTTP_2("h2-13"); private final String protocol; @@ -92,7 +92,7 @@ public enum Protocol { /** * Returns the string used to identify this protocol for ALPN and NPN, like - * "http/1.1", "spdy/3.1" or "h2-12". + * "http/1.1", "spdy/3.1" or "h2-13". */ @Override public String toString() { return protocol; diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/ErrorCode.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/ErrorCode.java index 6d9c784b7..db3028222 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/ErrorCode.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/ErrorCode.java @@ -15,7 +15,7 @@ */ package com.squareup.okhttp.internal.spdy; -// http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-7 +// http://tools.ietf.org/html/draft-ietf-httpbis-http2-13#section-7 public enum ErrorCode { /** Not an error! For SPDY stream resets, prefer null over NO_ERROR. */ NO_ERROR(0, -1, 0), diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft07.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft08.java similarity index 98% rename from okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft07.java rename to okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft08.java index 574e14243..2f7840355 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft07.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft08.java @@ -30,15 +30,15 @@ import okio.Okio; import okio.Source; /** - * Read and write HPACK v07. + * Read and write HPACK v08. * - * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07 + * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08 * * This implementation uses an array for the header table with a bitset for * references. Dynamic entries are added to the array, starting in the last * position moving forward. When the array fills, it is doubled. */ -final class HpackDraft07 { +final class HpackDraft08 { private static final int PREFIX_4_BITS = 0x0f; private static final int PREFIX_6_BITS = 0x3f; private static final int PREFIX_7_BITS = 0x7f; @@ -59,7 +59,7 @@ final class HpackDraft07 { new Header(Header.RESPONSE_STATUS, "404"), new Header(Header.RESPONSE_STATUS, "500"), new Header("accept-charset", ""), - new Header("accept-encoding", ""), + new Header("accept-encoding", "gzip, deflate"), new Header("accept-language", ""), new Header("accept-ranges", ""), new Header("accept", ""), @@ -107,10 +107,10 @@ final class HpackDraft07 { new Header("www-authenticate", "") }; - private HpackDraft07() { + private HpackDraft08() { } - // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.2 + // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#section-3.2 static final class Reader { private final List

emittedHeaders = new ArrayList<>(); @@ -429,7 +429,7 @@ final class HpackDraft07 { } /** This does not use "never indexed" semantics for sensitive headers. */ - // https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-4.3.3 + // https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#section-4.3.3 void writeHeaders(List
headerBlock) throws IOException { // TODO: implement index tracking for (int i = 0, size = headerBlock.size(); i < size; i++) { @@ -447,7 +447,7 @@ final class HpackDraft07 { } } - // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-4.1.1 + // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#section-4.1.1 void writeInt(int value, int prefixMask, int bits) throws IOException { // Write the raw value for a single byte value. if (value < prefixMask) { diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft12.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft13.java similarity index 87% rename from okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft12.java rename to okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft13.java index 887a93a7e..4c40a17a6 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft12.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Http20Draft13.java @@ -15,28 +15,29 @@ */ package com.squareup.okhttp.internal.spdy; -import com.squareup.okhttp.Protocol; import java.io.IOException; import java.util.List; import java.util.logging.Logger; + +import com.squareup.okhttp.Protocol; + import okio.Buffer; import okio.BufferedSink; import okio.BufferedSource; import okio.ByteString; import okio.Source; import okio.Timeout; - -import static com.squareup.okhttp.internal.spdy.Http20Draft12.FrameLogger.formatHeader; +import static com.squareup.okhttp.internal.spdy.Http20Draft13.FrameLogger.formatHeader; import static java.lang.String.format; import static java.util.logging.Level.FINE; import static okio.ByteString.EMPTY; /** - * Read and write HTTP/2 v12 frames. - *

http://tools.ietf.org/html/draft-ietf-httpbis-http2-12 + * Read and write HTTP/2 v13 frames. + *

http://tools.ietf.org/html/draft-ietf-httpbis-http2-13 */ -public final class Http20Draft12 implements Variant { - private static final Logger logger = Logger.getLogger(Http20Draft12.class.getName()); +public final class Http20Draft13 implements Variant { + private static final Logger logger = Logger.getLogger(Http20Draft13.class.getName()); @Override public Protocol getProtocol() { return Protocol.HTTP_2; @@ -57,8 +58,6 @@ public final class Http20Draft12 implements Variant { static final byte TYPE_GOAWAY = 0x7; static final byte TYPE_WINDOW_UPDATE = 0x8; static final byte TYPE_CONTINUATION = 0x9; - static final byte TYPE_ALTSVC = 0xa; - static final byte TYPE_BLOCKED = 0xb; static final byte FLAG_NONE = 0x0; static final byte FLAG_ACK = 0x1; // Used for settings and ping. @@ -66,8 +65,7 @@ public final class Http20Draft12 implements Variant { static final byte FLAG_END_SEGMENT = 0x2; static final byte FLAG_END_HEADERS = 0x4; // Used for headers and continuation. static final byte FLAG_END_PUSH_PROMISE = 0x4; - static final byte FLAG_PAD_LOW = 0x8; // Used for headers, data, and continuation. - static final byte FLAG_PAD_HIGH = 0x10; // Used for headers, data, and continuation. + static final byte FLAG_PADDED = 0x8; // Used for headers and data. static final byte FLAG_PRIORITY = 0x20; // Used for headers. static final byte FLAG_COMPRESSED = 0x20; // Used for data. @@ -93,13 +91,13 @@ public final class Http20Draft12 implements Variant { private final boolean client; // Visible for testing. - final HpackDraft07.Reader hpackReader; + final HpackDraft08.Reader hpackReader; Reader(BufferedSource source, int headerTableSize, boolean client) { this.source = source; this.client = client; this.continuation = new ContinuationSource(this.source); - this.hpackReader = new HpackDraft07.Reader(headerTableSize, continuation); + this.hpackReader = new HpackDraft08.Reader(headerTableSize, continuation); } @Override public void readConnectionPreface() throws IOException { @@ -166,16 +164,9 @@ public final class Http20Draft12 implements Variant { readWindowUpdate(handler, length, flags, streamId); break; - case TYPE_ALTSVC: - readAlternateService(handler, length, flags, streamId); - break; - - case TYPE_BLOCKED: // Ignore as this is experimental. - if (length != 0) throw ioException("TYPE_BLOCKED length != 0: %s", length); - break; - default: - throw ioException("PROTOCOL_ERROR: unknown frame type %s", type); + // Implementations MUST discard frames that have unknown or unsupported types. + source.skip(length); } return true; } @@ -186,7 +177,7 @@ public final class Http20Draft12 implements Variant { boolean endStream = (flags & FLAG_END_STREAM) != 0; - short padding = readPadding(source, flags); + short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0; if ((flags & FLAG_PRIORITY) != 0) { readPriority(handler, streamId); @@ -223,7 +214,7 @@ public final class Http20Draft12 implements Variant { throw ioException("PROTOCOL_ERROR: FLAG_COMPRESSED without SETTINGS_COMPRESS_DATA"); } - short padding = readPadding(source, flags); + short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0; length = lengthWithoutPadding(length, flags, padding); handler.data(inFinished, streamId, source, length); @@ -266,10 +257,10 @@ public final class Http20Draft12 implements Variant { return; } - if (length % 5 != 0) throw ioException("TYPE_SETTINGS length %% 5 != 0: %s", length); + if (length % 6 != 0) throw ioException("TYPE_SETTINGS length %% 6 != 0: %s", length); Settings settings = new Settings(); - for (int i = 0; i < length; i += 5) { - int id = source.readByte(); + for (int i = 0; i < length; i += 6) { + short id = source.readShort(); int value = source.readInt(); switch (id) { @@ -307,9 +298,10 @@ public final class Http20Draft12 implements Variant { if (streamId == 0) { throw ioException("PROTOCOL_ERROR: TYPE_PUSH_PROMISE streamId == 0"); } - short padding = readPadding(source, flags); + short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0; int promisedStreamId = source.readInt() & 0x7fffffff; length -= 4; // account for above read. + length = lengthWithoutPadding(length, flags, padding); List

headerBlock = readHeaderBlock(length, padding, flags, streamId); handler.pushPromise(streamId, promisedStreamId, headerBlock); } @@ -350,20 +342,6 @@ public final class Http20Draft12 implements Variant { handler.windowUpdate(streamId, increment); } - private void readAlternateService(Handler handler, short length, byte flags, int streamId) - throws IOException { - long maxAge = source.readInt() & 0xffffffffL; - int port = source.readShort() & 0xffff; - source.readByte(); // Reserved. - int protocolLength = source.readByte() & 0xff; - ByteString protocol = source.readByteString(protocolLength); - int hostLength = source.readByte() & 0xff; - String host = source.readUtf8(hostLength); - int originLength = length - 9 - protocolLength - hostLength; - String origin = source.readUtf8(originLength); - handler.alternateService(streamId, origin, protocol, host, port, maxAge); - } - @Override public void close() throws IOException { source.close(); } @@ -373,14 +351,14 @@ public final class Http20Draft12 implements Variant { private final BufferedSink sink; private final boolean client; private final Buffer hpackBuffer; - private final HpackDraft07.Writer hpackWriter; + private final HpackDraft08.Writer hpackWriter; private boolean closed; Writer(BufferedSink sink, boolean client) { this.sink = sink; this.client = client; this.hpackBuffer = new Buffer(); - this.hpackWriter = new HpackDraft07.Writer(hpackBuffer); + this.hpackWriter = new HpackDraft08.Writer(hpackBuffer); } @Override public synchronized void flush() throws IOException { @@ -506,7 +484,7 @@ public final class Http20Draft12 implements Variant { @Override public synchronized void settings(Settings settings) throws IOException { if (closed) throw new IOException("closed"); - int length = settings.size() * 5; + int length = settings.size() * 6; byte type = TYPE_SETTINGS; byte flags = FLAG_NONE; int streamId = 0; @@ -516,7 +494,7 @@ public final class Http20Draft12 implements Variant { int id = i; if (id == 4) id = 3; // SETTINGS_MAX_CONCURRENT_STREAMS renumbered. else if (id == 7) id = 4; // SETTINGS_INITIAL_WINDOW_SIZE renumbered. - sink.writeByte(id); + sink.writeShort(id); sink.writeInt(settings.get(i)); } sink.flush(); @@ -594,7 +572,7 @@ public final class Http20Draft12 implements Variant { /** * Decompression of the header block occurs above the framing layer. This * class lazily reads continuation frames as they are needed by {@link - * HpackDraft07.Reader#readHeaders()}. + * HpackDraft08.Reader#readHeaders()}. */ static final class ContinuationSource implements Source { private final BufferedSource source; @@ -636,41 +614,19 @@ public final class Http20Draft12 implements Variant { int previousStreamId = streamId; int w1 = source.readInt(); int w2 = source.readInt(); - length = (short) ((w1 & 0x3fff0000) >> 16); + length = left = (short) ((w1 & 0x3fff0000) >> 16); byte type = (byte) ((w1 & 0xff00) >> 8); flags = (byte) (w1 & 0xff); if (logger.isLoggable(FINE)) logger.fine(formatHeader(true, streamId, length, type, flags)); - padding = readPadding(source, flags); - length = left = lengthWithoutPadding(length, flags, padding); streamId = (w2 & 0x7fffffff); if (type != TYPE_CONTINUATION) throw ioException("%s != TYPE_CONTINUATION", type); if (streamId != previousStreamId) throw ioException("TYPE_CONTINUATION streamId changed"); } } - private static short readPadding(BufferedSource source, byte flags) throws IOException { - if ((flags & FLAG_PAD_HIGH) != 0 && (flags & FLAG_PAD_LOW) == 0) { - throw ioException("PROTOCOL_ERROR FLAG_PAD_HIGH set without FLAG_PAD_LOW"); - } - int padding = 0; - if ((flags & FLAG_PAD_HIGH) != 0) { - padding = source.readShort() & 0xffff; - } else if ((flags & FLAG_PAD_LOW) != 0) { - padding = source.readByte() & 0xff; - } - if (padding > MAX_FRAME_SIZE) { - throw ioException("PROTOCOL_ERROR padding > %d: %d", MAX_FRAME_SIZE, padding); - } - return (short) padding; - } - private static short lengthWithoutPadding(short length, byte flags, short padding) throws IOException { - if ((flags & FLAG_PAD_HIGH) != 0) { // account for reading the padding length. - length -= 2; - } else if ((flags & FLAG_PAD_LOW) != 0) { - length--; - } + if ((flags & FLAG_PADDED) != 0) length--; // Account for reading the padding length. if (padding > length) { throw ioException("PROTOCOL_ERROR padding %s > remaining length %s", padding, length); } @@ -719,8 +675,6 @@ public final class Http20Draft12 implements Variant { case TYPE_RST_STREAM: case TYPE_GOAWAY: case TYPE_WINDOW_UPDATE: - case TYPE_ALTSVC: - case TYPE_BLOCKED: return BINARY[flags]; } String result = flags < FLAGS.length ? FLAGS[flags] : BINARY[flags]; @@ -744,9 +698,7 @@ public final class Http20Draft12 implements Variant { "PING", "GOAWAY", "WINDOW_UPDATE", - "CONTINUATION", - "ALTSVC", - "BLOCKED" + "CONTINUATION" }; /** @@ -768,14 +720,9 @@ public final class Http20Draft12 implements Variant { int[] prefixFlags = new int[] {FLAG_END_STREAM, FLAG_END_SEGMENT, FLAG_END_SEGMENT | FLAG_END_STREAM}; - FLAGS[FLAG_PAD_LOW] = "PAD_LOW"; - FLAGS[FLAG_PAD_LOW | FLAG_PAD_HIGH] = "PAD_LOW|PAD_HIGH"; - int[] suffixFlags = new int[] {FLAG_PAD_LOW, FLAG_PAD_LOW | FLAG_PAD_HIGH}; - + FLAGS[FLAG_PADDED] = "PADDED"; for (int prefixFlag : prefixFlags) { - for (int suffixFlag : suffixFlags) { - FLAGS[prefixFlag | suffixFlag] = FLAGS[prefixFlag] + '|' + FLAGS[suffixFlag]; - } + FLAGS[prefixFlag | FLAG_PADDED] = FLAGS[prefixFlag] + "|PADDED"; } FLAGS[FLAG_END_HEADERS] = "END_HEADERS"; // Same as END_PUSH_PROMISE. @@ -787,10 +734,8 @@ public final class Http20Draft12 implements Variant { for (int frameFlag : frameFlags) { for (int prefixFlag : prefixFlags) { FLAGS[prefixFlag | frameFlag] = FLAGS[prefixFlag] + '|' + FLAGS[frameFlag]; - for (int suffixFlag : suffixFlags) { - FLAGS[prefixFlag | frameFlag | suffixFlag] = - FLAGS[prefixFlag] + '|' + FLAGS[frameFlag] + '|' + FLAGS[suffixFlag]; - } + FLAGS[prefixFlag | frameFlag | FLAG_PADDED] = + FLAGS[prefixFlag] + '|' + FLAGS[frameFlag] + "|PADDED"; } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Huffman.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Huffman.java index 5fd2d5478..ab1501115 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Huffman.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Huffman.java @@ -31,49 +31,47 @@ import java.io.OutputStream; class Huffman { // Appendix C: Huffman Codes - // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-C + // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08#appendix-C private static final int[] CODES = { - 0x3ffffba, 0x3ffffbb, 0x3ffffbc, 0x3ffffbd, 0x3ffffbe, 0x3ffffbf, 0x3ffffc0, 0x3ffffc1, - 0x3ffffc2, 0x3ffffc3, 0x3ffffc4, 0x3ffffc5, 0x3ffffc6, 0x3ffffc7, 0x3ffffc8, 0x3ffffc9, - 0x3ffffca, 0x3ffffcb, 0x3ffffcc, 0x3ffffcd, 0x3ffffce, 0x3ffffcf, 0x3ffffd0, 0x3ffffd1, - 0x3ffffd2, 0x3ffffd3, 0x3ffffd4, 0x3ffffd5, 0x3ffffd6, 0x3ffffd7, 0x3ffffd8, 0x3ffffd9, 0x6, - 0x1ffc, 0x1f0, 0x3ffc, 0x7ffc, 0x1e, 0x64, 0x1ffd, 0x3fa, 0x1f1, 0x3fb, 0x3fc, 0x65, 0x66, - 0x1f, 0x7, 0x0, 0x1, 0x2, 0x8, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0xec, 0x1fffc, 0x27, - 0x7ffd, 0x3fd, 0x7ffe, 0x67, 0xed, 0xee, 0x68, 0xef, 0x69, 0x6a, 0x1f2, 0xf0, 0x1f3, 0x1f4, - 0x1f5, 0x6b, 0x6c, 0xf1, 0xf2, 0x1f6, 0x1f7, 0x6d, 0x28, 0xf3, 0x1f8, 0x1f9, 0xf4, 0x1fa, - 0x1fb, 0x7fc, 0x3ffffda, 0x7fd, 0x3ffd, 0x6e, 0x3fffe, 0x9, 0x6f, 0xa, 0x29, 0xb, 0x70, 0x2a, - 0x2b, 0xc, 0xf5, 0xf6, 0x2c, 0x2d, 0x2e, 0xd, 0x2f, 0x1fc, 0x30, 0x31, 0xe, 0x71, 0x72, 0x73, - 0x74, 0x75, 0xf7, 0x1fffd, 0xffc, 0x1fffe, 0xffd, 0x3ffffdb, 0x3ffffdc, 0x3ffffdd, 0x3ffffde, - 0x3ffffdf, 0x3ffffe0, 0x3ffffe1, 0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x3ffffe5, 0x3ffffe6, - 0x3ffffe7, 0x3ffffe8, 0x3ffffe9, 0x3ffffea, 0x3ffffeb, 0x3ffffec, 0x3ffffed, 0x3ffffee, - 0x3ffffef, 0x3fffff0, 0x3fffff1, 0x3fffff2, 0x3fffff3, 0x3fffff4, 0x3fffff5, 0x3fffff6, - 0x3fffff7, 0x3fffff8, 0x3fffff9, 0x3fffffa, 0x3fffffb, 0x3fffffc, 0x3fffffd, 0x3fffffe, - 0x3ffffff, 0x1ffff80, 0x1ffff81, 0x1ffff82, 0x1ffff83, 0x1ffff84, 0x1ffff85, 0x1ffff86, - 0x1ffff87, 0x1ffff88, 0x1ffff89, 0x1ffff8a, 0x1ffff8b, 0x1ffff8c, 0x1ffff8d, 0x1ffff8e, - 0x1ffff8f, 0x1ffff90, 0x1ffff91, 0x1ffff92, 0x1ffff93, 0x1ffff94, 0x1ffff95, 0x1ffff96, - 0x1ffff97, 0x1ffff98, 0x1ffff99, 0x1ffff9a, 0x1ffff9b, 0x1ffff9c, 0x1ffff9d, 0x1ffff9e, - 0x1ffff9f, 0x1ffffa0, 0x1ffffa1, 0x1ffffa2, 0x1ffffa3, 0x1ffffa4, 0x1ffffa5, 0x1ffffa6, - 0x1ffffa7, 0x1ffffa8, 0x1ffffa9, 0x1ffffaa, 0x1ffffab, 0x1ffffac, 0x1ffffad, 0x1ffffae, - 0x1ffffaf, 0x1ffffb0, 0x1ffffb1, 0x1ffffb2, 0x1ffffb3, 0x1ffffb4, 0x1ffffb5, 0x1ffffb6, - 0x1ffffb7, 0x1ffffb8, 0x1ffffb9, 0x1ffffba, 0x1ffffbb, 0x1ffffbc, 0x1ffffbd, 0x1ffffbe, - 0x1ffffbf, 0x1ffffc0, 0x1ffffc1, 0x1ffffc2, 0x1ffffc3, 0x1ffffc4, 0x1ffffc5, 0x1ffffc6, - 0x1ffffc7, 0x1ffffc8, 0x1ffffc9, 0x1ffffca, 0x1ffffcb, 0x1ffffcc, 0x1ffffcd, 0x1ffffce, - 0x1ffffcf, 0x1ffffd0, 0x1ffffd1, 0x1ffffd2, 0x1ffffd3, 0x1ffffd4, 0x1ffffd5, 0x1ffffd6, - 0x1ffffd7, 0x1ffffd8, 0x1ffffd9, 0x1ffffda, 0x1ffffdb + 0x1ff8, 0x7fffd8, 0xfffffe2, 0xfffffe3, 0xfffffe4, 0xfffffe5, 0xfffffe6, 0xfffffe7, 0xfffffe8, + 0xffffea, 0x3ffffffc, 0xfffffe9, 0xfffffea, 0x3ffffffd, 0xfffffeb, 0xfffffec, 0xfffffed, + 0xfffffee, 0xfffffef, 0xffffff0, 0xffffff1, 0xffffff2, 0x3ffffffe, 0xffffff3, 0xffffff4, + 0xffffff5, 0xffffff6, 0xffffff7, 0xffffff8, 0xffffff9, 0xffffffa, 0xffffffb, 0x14, 0x3f8, + 0x3f9, 0xffa, 0x1ff9, 0x15, 0xf8, 0x7fa, 0x3fa, 0x3fb, 0xf9, 0x7fb, 0xfa, 0x16, 0x17, 0x18, + 0x0, 0x1, 0x2, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x5c, 0xfb, 0x7ffc, 0x20, 0xffb, + 0x3fc, 0x1ffa, 0x21, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0xfc, 0x73, 0xfd, 0x1ffb, 0x7fff0, + 0x1ffc, 0x3ffc, 0x22, 0x7ffd, 0x3, 0x23, 0x4, 0x24, 0x5, 0x25, 0x26, 0x27, 0x6, 0x74, 0x75, + 0x28, 0x29, 0x2a, 0x7, 0x2b, 0x76, 0x2c, 0x8, 0x9, 0x2d, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7ffe, + 0x7fc, 0x3ffd, 0x1ffd, 0xffffffc, 0xfffe6, 0x3fffd2, 0xfffe7, 0xfffe8, 0x3fffd3, 0x3fffd4, + 0x3fffd5, 0x7fffd9, 0x3fffd6, 0x7fffda, 0x7fffdb, 0x7fffdc, 0x7fffdd, 0x7fffde, 0xffffeb, + 0x7fffdf, 0xffffec, 0xffffed, 0x3fffd7, 0x7fffe0, 0xffffee, 0x7fffe1, 0x7fffe2, 0x7fffe3, + 0x7fffe4, 0x1fffdc, 0x3fffd8, 0x7fffe5, 0x3fffd9, 0x7fffe6, 0x7fffe7, 0xffffef, 0x3fffda, + 0x1fffdd, 0xfffe9, 0x3fffdb, 0x3fffdc, 0x7fffe8, 0x7fffe9, 0x1fffde, 0x7fffea, 0x3fffdd, + 0x3fffde, 0xfffff0, 0x1fffdf, 0x3fffdf, 0x7fffeb, 0x7fffec, 0x1fffe0, 0x1fffe1, 0x3fffe0, + 0x1fffe2, 0x7fffed, 0x3fffe1, 0x7fffee, 0x7fffef, 0xfffea, 0x3fffe2, 0x3fffe3, 0x3fffe4, + 0x7ffff0, 0x3fffe5, 0x3fffe6, 0x7ffff1, 0x3ffffe0, 0x3ffffe1, 0xfffeb, 0x7fff1, 0x3fffe7, + 0x7ffff2, 0x3fffe8, 0x1ffffec, 0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x7ffffde, 0x7ffffdf, + 0x3ffffe5, 0xfffff1, 0x1ffffed, 0x7fff2, 0x1fffe3, 0x3ffffe6, 0x7ffffe0, 0x7ffffe1, 0x3ffffe7, + 0x7ffffe2, 0xfffff2, 0x1fffe4, 0x1fffe5, 0x3ffffe8, 0x3ffffe9, 0xffffffd, 0x7ffffe3, + 0x7ffffe4, 0x7ffffe5, 0xfffec, 0xfffff3, 0xfffed, 0x1fffe6, 0x3fffe9, 0x1fffe7, 0x1fffe8, + 0x7ffff3, 0x3fffea, 0x3fffeb, 0x1ffffee, 0x1ffffef, 0xfffff4, 0xfffff5, 0x3ffffea, 0x7ffff4, + 0x3ffffeb, 0x7ffffe6, 0x3ffffec, 0x3ffffed, 0x7ffffe7, 0x7ffffe8, 0x7ffffe9, 0x7ffffea, + 0x7ffffeb, 0xffffffe, 0x7ffffec, 0x7ffffed, 0x7ffffee, 0x7ffffef, 0x7fffff0, 0x3ffffee }; private static final byte[] CODE_LENGTHS = { - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 5, 13, 9, 14, 15, 6, 7, 13, 10, 9, 10, 10, 7, 7, 6, 5, 4, - 4, 4, 5, 6, 6, 6, 6, 6, 6, 6, 8, 17, 6, 15, 10, 15, 7, 8, 8, 7, 8, 7, 7, 9, 8, 9, 9, 9, 7, 7, - 8, 8, 9, 9, 7, 6, 8, 9, 9, 8, 9, 9, 11, 26, 11, 14, 7, 18, 5, 7, 5, 6, 5, 7, 6, 6, 5, 8, 8, 6, - 6, 6, 5, 6, 9, 6, 6, 5, 7, 7, 7, 7, 7, 8, 17, 12, 17, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25 + 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 30, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, + 6, 6, 5, 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, 20, 22, 20, 20, 22, 22, 22, 23, + 22, 23, 23, 23, 23, 23, 24, 23, 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, + 24, 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, 21, 21, 22, 21, 23, 22, + 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, + 26, 24, 25, 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, 20, 24, 20, 21, + 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, + 27, 27, 27, 27, 26 }; private static final Huffman INSTANCE = new Huffman(); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Settings.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Settings.java index 4a034e6cf..9c914db86 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Settings.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/Settings.java @@ -50,8 +50,6 @@ public final class Settings { static final int MAX_CONCURRENT_STREAMS = 4; /** spdy/3: Current CWND in Packets. */ static final int CURRENT_CWND = 5; - /** HTTP/2: The peer must not gzip a DATA frame when this is 0. */ - static final int COMPRESS_DATA = 5; /** spdy/3: Retransmission rate. Percentage */ static final int DOWNLOAD_RETRANS_RATE = 6; /** Window size in bytes. */ @@ -173,13 +171,6 @@ public final class Settings { return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue; } - /** HTTP/2 only. */ - // TODO: honor this setting in HTTP/2. - boolean getCompressData(boolean defaultValue) { - int bit = 1 << COMPRESS_DATA; - return ((bit & set) != 0 ? values[COMPRESS_DATA] : defaultValue ? 1 : 0) == 1; - } - /** spdy/3 only. */ int getDownloadRetransRate(int defaultValue) { int bit = 1 << DOWNLOAD_RETRANS_RATE; diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyConnection.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyConnection.java index 8e22f702c..ed342a2e0 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyConnection.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyConnection.java @@ -133,7 +133,7 @@ public final class SpdyConnection implements Closeable { pushObserver = builder.pushObserver; client = builder.client; handler = builder.handler; - // http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-5.1.1 + // http://tools.ietf.org/html/draft-ietf-httpbis-http2-13#section-5.1.1 nextStreamId = builder.client ? 1 : 2; if (builder.client && protocol == Protocol.HTTP_2) { nextStreamId += 2; // In HTTP/2, 1 on client is reserved for Upgrade. @@ -152,7 +152,7 @@ public final class SpdyConnection implements Closeable { hostName = builder.hostName; if (protocol == Protocol.HTTP_2) { - variant = new Http20Draft12(); + variant = new Http20Draft13(); // Like newSingleThreadExecutor, except lazy creates the thread. pushExecutor = new ThreadPoolExecutor(0, 1, 0L, TimeUnit.MILLISECONDS,