1
0
mirror of https://github.com/square/okhttp.git synced 2025-11-27 18:21:14 +03:00

Rename FramedConnection to Http2Connection.

Also rename HttpStream to HttpCodec. This is the interface implemented
for both HTTP/1.1 and HTTP/2. The HTTP/2 codec creates a stream when
it is used.
This commit is contained in:
jwilson
2016-07-09 18:08:02 -04:00
parent 33660bf58b
commit 3d43a8dba8
49 changed files with 708 additions and 753 deletions

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.File;
import java.io.IOException;
@@ -38,14 +38,14 @@ import okio.Source;
import static okhttp3.internal.platform.Platform.INFO;
/** A basic HTTP_2 server that serves the contents of a local directory. */
public final class FramedServer extends FramedConnection.Listener {
static final Logger logger = Logger.getLogger(FramedServer.class.getName());
/** A basic HTTP/2 server that serves the contents of a local directory. */
public final class Http2Server extends Http2Connection.Listener {
static final Logger logger = Logger.getLogger(Http2Server.class.getName());
private final File baseDirectory;
private final SSLSocketFactory sslSocketFactory;
public FramedServer(File baseDirectory, SSLSocketFactory sslSocketFactory) {
public Http2Server(File baseDirectory, SSLSocketFactory sslSocketFactory) {
this.baseDirectory = baseDirectory;
this.sslSocketFactory = sslSocketFactory;
}
@@ -65,11 +65,11 @@ public final class FramedServer extends FramedConnection.Listener {
if (protocol != Protocol.HTTP_2) {
throw new ProtocolException("Protocol " + protocol + " unsupported");
}
FramedConnection framedConnection = new FramedConnection.Builder(false)
Http2Connection connection = new Http2Connection.Builder(false)
.socket(sslSocket)
.listener(this)
.build();
framedConnection.start();
connection.start();
} catch (IOException e) {
logger.log(Level.INFO, "FramedServer connection failure: " + e);
Util.closeQuietly(socket);
@@ -90,7 +90,7 @@ public final class FramedServer extends FramedConnection.Listener {
return sslSocket;
}
@Override public void onStream(final FramedStream stream) throws IOException {
@Override public void onStream(final Http2Stream stream) throws IOException {
try {
List<Header> requestHeaders = stream.getRequestHeaders();
String path = null;
@@ -120,7 +120,7 @@ public final class FramedServer extends FramedConnection.Listener {
}
}
private void send404(FramedStream stream, String path) throws IOException {
private void send404(Http2Stream stream, String path) throws IOException {
List<Header> responseHeaders = Arrays.asList(
new Header(":status", "404"),
new Header(":version", "HTTP/1.1"),
@@ -132,7 +132,7 @@ public final class FramedServer extends FramedConnection.Listener {
out.close();
}
private void serveDirectory(FramedStream stream, File[] files) throws IOException {
private void serveDirectory(Http2Stream stream, File[] files) throws IOException {
List<Header> responseHeaders = Arrays.asList(
new Header(":status", "200"),
new Header(":version", "HTTP/1.1"),
@@ -147,7 +147,7 @@ public final class FramedServer extends FramedConnection.Listener {
out.close();
}
private void serveFile(FramedStream stream, File file) throws IOException {
private void serveFile(Http2Stream stream, File file) throws IOException {
List<Header> responseHeaders = Arrays.asList(
new Header(":status", "200"),
new Header(":version", "HTTP/1.1"),
@@ -181,7 +181,7 @@ public final class FramedServer extends FramedConnection.Listener {
return;
}
FramedServer server = new FramedServer(new File(args[0]),
Http2Server server = new Http2Server(new File(args[0]),
SslClient.localhost().sslContext.getSocketFactory());
server.run();
}

View File

@@ -20,7 +20,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Headers;
import okhttp3.internal.Internal;
import okhttp3.internal.framed.Settings;
import okhttp3.internal.http2.Settings;
import okhttp3.ws.WebSocketListener;
import okio.Buffer;

View File

@@ -61,12 +61,12 @@ import okhttp3.Response;
import okhttp3.internal.Internal;
import okhttp3.internal.NamedRunnable;
import okhttp3.internal.Util;
import okhttp3.internal.framed.ErrorCode;
import okhttp3.internal.framed.FramedConnection;
import okhttp3.internal.framed.FramedStream;
import okhttp3.internal.framed.Header;
import okhttp3.internal.framed.Settings;
import okhttp3.internal.http.HttpMethod;
import okhttp3.internal.http2.ErrorCode;
import okhttp3.internal.http2.Header;
import okhttp3.internal.http2.Http2Connection;
import okhttp3.internal.http2.Http2Stream;
import okhttp3.internal.http2.Settings;
import okhttp3.internal.platform.Platform;
import okhttp3.internal.ws.RealWebSocket;
import okhttp3.internal.ws.WebSocketProtocol;
@@ -125,8 +125,8 @@ public final class MockWebServer implements TestRule {
private final Set<Socket> openClientSockets =
Collections.newSetFromMap(new ConcurrentHashMap<Socket, Boolean>());
private final Set<FramedConnection> openFramedConnections =
Collections.newSetFromMap(new ConcurrentHashMap<FramedConnection, Boolean>());
private final Set<Http2Connection> openConnections =
Collections.newSetFromMap(new ConcurrentHashMap<Http2Connection, Boolean>());
private final AtomicInteger requestCount = new AtomicInteger();
private long bodyLimit = Long.MAX_VALUE;
private ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault();
@@ -352,7 +352,7 @@ public final class MockWebServer implements TestRule {
Util.closeQuietly(s.next());
s.remove();
}
for (Iterator<FramedConnection> s = openFramedConnections.iterator(); s.hasNext(); ) {
for (Iterator<Http2Connection> s = openConnections.iterator(); s.hasNext(); ) {
Util.closeQuietly(s.next());
s.remove();
}
@@ -451,12 +451,12 @@ public final class MockWebServer implements TestRule {
if (protocol == Protocol.HTTP_2) {
FramedSocketHandler framedSocketListener = new FramedSocketHandler(socket, protocol);
FramedConnection framedConnection = new FramedConnection.Builder(false)
Http2Connection connection = new Http2Connection.Builder(false)
.socket(socket)
.listener(framedSocketListener)
.build();
framedConnection.start();
openFramedConnections.add(framedConnection);
connection.start();
openConnections.add(connection);
openClientSockets.remove(socket);
return;
} else if (protocol != Protocol.HTTP_1_1) {
@@ -842,7 +842,7 @@ public final class MockWebServer implements TestRule {
}
/** Processes HTTP requests layered over framed protocols. */
private class FramedSocketHandler extends FramedConnection.Listener {
private class FramedSocketHandler extends Http2Connection.Listener {
private final Socket socket;
private final Protocol protocol;
private final AtomicInteger sequenceNumber = new AtomicInteger();
@@ -852,7 +852,7 @@ public final class MockWebServer implements TestRule {
this.protocol = protocol;
}
@Override public void onStream(FramedStream stream) throws IOException {
@Override public void onStream(Http2Stream stream) throws IOException {
MockResponse peekedResponse = dispatcher.peek();
if (peekedResponse.getSocketPolicy() == RESET_STREAM_AT_START) {
try {
@@ -880,7 +880,7 @@ public final class MockWebServer implements TestRule {
}
}
private RecordedRequest readRequest(FramedStream stream) throws IOException {
private RecordedRequest readRequest(Http2Stream stream) throws IOException {
List<Header> streamHeaders = stream.getRequestHeaders();
Headers.Builder httpHeaders = new Headers.Builder();
String method = "<:method omitted>";
@@ -909,7 +909,7 @@ public final class MockWebServer implements TestRule {
sequenceNumber.getAndIncrement(), socket);
}
private void writeResponse(FramedStream stream, MockResponse response) throws IOException {
private void writeResponse(Http2Stream stream, MockResponse response) throws IOException {
Settings settings = response.getSettings();
if (settings != null) {
stream.getConnection().setSettings(settings);
@@ -944,7 +944,7 @@ public final class MockWebServer implements TestRule {
}
}
private void pushPromises(FramedStream stream, List<PushPromise> promises) throws IOException {
private void pushPromises(Http2Stream stream, List<PushPromise> promises) throws IOException {
for (PushPromise pushPromise : promises) {
List<Header> pushedHeaders = new ArrayList<>();
pushedHeaders.add(new Header(Header.TARGET_AUTHORITY, url(pushPromise.path()).host()));
@@ -959,7 +959,7 @@ public final class MockWebServer implements TestRule {
requestQueue.add(new RecordedRequest(requestLine, pushPromise.headers(), chunkSizes, 0,
new Buffer(), sequenceNumber.getAndIncrement(), socket));
boolean hasBody = pushPromise.response().getBody() != null;
FramedStream pushedStream =
Http2Stream pushedStream =
stream.getConnection().pushStream(stream.getId(), pushedHeaders, hasBody);
writeResponse(pushedStream, pushPromise.response());
}

View File

@@ -45,8 +45,8 @@ import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.Util;
import okhttp3.internal.framed.Http2;
import okhttp3.internal.http.StatusLine;
import okhttp3.internal.http2.Http2;
import okio.BufferedSource;
import okio.Okio;
import okio.Sink;
@@ -274,7 +274,7 @@ public class Main extends HelpOption implements Runnable {
}
private static void enableHttp2FrameLogging() {
frameLogger = Logger.getLogger(Http2.class.getName() + "$FrameLogger");
frameLogger = Logger.getLogger(Http2.class.getName());
frameLogger.setLevel(Level.FINE);
ConsoleHandler handler = new ConsoleHandler();
handler.setLevel(Level.FINE);

View File

@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.Collection;
import okhttp3.internal.framed.hpackjson.Story;
import okhttp3.internal.http2.hpackjson.Story;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static okhttp3.internal.framed.hpackjson.HpackJsonUtil.storiesForCurrentDraft;
import static okhttp3.internal.http2.hpackjson.HpackJsonUtil.storiesForCurrentDraft;
@RunWith(Parameterized.class)
public class HpackDecodeInteropTest extends HpackDecodeTestBase {

View File

@@ -13,15 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import okhttp3.internal.framed.hpackjson.Case;
import okhttp3.internal.framed.hpackjson.HpackJsonUtil;
import okhttp3.internal.framed.hpackjson.Story;
import okhttp3.internal.framed.Header;
import okhttp3.internal.framed.Hpack;
import okhttp3.internal.http2.hpackjson.Case;
import okhttp3.internal.http2.hpackjson.HpackJsonUtil;
import okhttp3.internal.http2.hpackjson.Story;
import okio.Buffer;
import static org.junit.Assert.assertEquals;

View File

@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.Collection;
import okhttp3.internal.framed.hpackjson.Case;
import okhttp3.internal.framed.hpackjson.Story;
import okhttp3.internal.framed.Hpack;
import okhttp3.internal.http2.hpackjson.Case;
import okhttp3.internal.http2.hpackjson.Story;
import okio.Buffer;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed.hpackjson;
package okhttp3.internal.http2.hpackjson;
import java.util.ArrayList;
import java.util.LinkedHashMap;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed.hpackjson;
package okhttp3.internal.http2.hpackjson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed.hpackjson;
package okhttp3.internal.http2.hpackjson;
import java.util.ArrayList;
import java.util.List;

View File

@@ -18,9 +18,7 @@ package okhttp3;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.internal.tls.SslClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;

View File

@@ -22,8 +22,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.internal.Internal;
import okhttp3.internal.framed.Header;
import okhttp3.internal.http.Http2xStream;
import okhttp3.internal.http2.Header;
import okhttp3.internal.http2.Http2Codec;
import org.junit.Test;
import static okhttp3.TestUtil.headerEntries;
@@ -43,7 +43,7 @@ public final class HeadersTest {
":version", "HTTP/1.1",
"connection", "close");
Request request = new Request.Builder().url("http://square.com/").build();
Response response = Http2xStream.readHttp2HeadersList(headerBlock).request(request).build();
Response response = Http2Codec.readHttp2HeadersList(headerBlock).request(request).build();
Headers headers = response.headers();
assertEquals(1, headers.size());
assertEquals(":version", headers.name(0));
@@ -61,7 +61,7 @@ public final class HeadersTest {
":path", "/",
":authority", "square.com",
":scheme", "http");
assertEquals(expected, Http2xStream.http2HeadersList(request));
assertEquals(expected, Http2Codec.http2HeadersList(request));
}
@Test public void ofTrims() {

View File

@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.internal.framed.Header;
import okhttp3.internal.http2.Header;
public final class TestUtil {
private TestUtil() {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.util.List;
@@ -22,7 +22,7 @@ import okio.ByteString;
import static org.junit.Assert.fail;
class BaseTestHandler implements FrameReader.Handler {
class BaseTestHandler implements Http2Reader.Handler {
@Override public void data(boolean inFinished, int streamId, BufferedSource source, int length)
throws IOException {
fail();

View File

@@ -13,77 +13,75 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import static okhttp3.internal.framed.Http2.FLAG_ACK;
import static okhttp3.internal.framed.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.framed.Http2.FLAG_END_STREAM;
import static okhttp3.internal.framed.Http2.FLAG_NONE;
import static okhttp3.internal.framed.FrameLogger.formatFlags;
import static okhttp3.internal.framed.FrameLogger.formatHeader;
import static okhttp3.internal.framed.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.framed.Http2.TYPE_DATA;
import static okhttp3.internal.framed.Http2.TYPE_GOAWAY;
import static okhttp3.internal.framed.Http2.TYPE_HEADERS;
import static okhttp3.internal.framed.Http2.TYPE_PING;
import static okhttp3.internal.framed.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.framed.Http2.TYPE_SETTINGS;
import static okhttp3.internal.http2.Http2.FLAG_ACK;
import static okhttp3.internal.http2.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.http2.Http2.FLAG_END_STREAM;
import static okhttp3.internal.http2.Http2.FLAG_NONE;
import static okhttp3.internal.http2.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.http2.Http2.TYPE_DATA;
import static okhttp3.internal.http2.Http2.TYPE_GOAWAY;
import static okhttp3.internal.http2.Http2.TYPE_HEADERS;
import static okhttp3.internal.http2.Http2.TYPE_PING;
import static okhttp3.internal.http2.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.http2.Http2.TYPE_SETTINGS;
import static okhttp3.internal.http2.Http2.frameLog;
import static org.junit.Assert.assertEquals;
public final class Http2FrameLoggerTest {
public final class FrameLogTest {
/** Real stream traffic applied to the log format. */
@Test public void exampleStream() {
assertEquals(">> 0x00000000 5 SETTINGS ",
formatHeader(false, 0, 5, TYPE_SETTINGS, FLAG_NONE));
frameLog(false, 0, 5, TYPE_SETTINGS, FLAG_NONE));
assertEquals(">> 0x00000003 100 HEADERS END_HEADERS",
formatHeader(false, 3, 100, TYPE_HEADERS, FLAG_END_HEADERS));
frameLog(false, 3, 100, TYPE_HEADERS, FLAG_END_HEADERS));
assertEquals(">> 0x00000003 0 DATA END_STREAM",
formatHeader(false, 3, 0, TYPE_DATA, FLAG_END_STREAM));
frameLog(false, 3, 0, TYPE_DATA, FLAG_END_STREAM));
assertEquals("<< 0x00000000 15 SETTINGS ",
formatHeader(true, 0, 15, TYPE_SETTINGS, FLAG_NONE));
frameLog(true, 0, 15, TYPE_SETTINGS, FLAG_NONE));
assertEquals(">> 0x00000000 0 SETTINGS ACK",
formatHeader(false, 0, 0, TYPE_SETTINGS, FLAG_ACK));
frameLog(false, 0, 0, TYPE_SETTINGS, FLAG_ACK));
assertEquals("<< 0x00000000 0 SETTINGS ACK",
formatHeader(true, 0, 0, TYPE_SETTINGS, FLAG_ACK));
frameLog(true, 0, 0, TYPE_SETTINGS, FLAG_ACK));
assertEquals("<< 0x00000003 22 HEADERS END_HEADERS",
formatHeader(true, 3, 22, TYPE_HEADERS, FLAG_END_HEADERS));
frameLog(true, 3, 22, TYPE_HEADERS, FLAG_END_HEADERS));
assertEquals("<< 0x00000003 226 DATA END_STREAM",
formatHeader(true, 3, 226, TYPE_DATA, FLAG_END_STREAM));
frameLog(true, 3, 226, TYPE_DATA, FLAG_END_STREAM));
assertEquals(">> 0x00000000 8 GOAWAY ",
formatHeader(false, 0, 8, TYPE_GOAWAY, FLAG_NONE));
frameLog(false, 0, 8, TYPE_GOAWAY, FLAG_NONE));
}
@Test public void flagOverlapOn0x1() {
assertEquals("<< 0x00000000 0 SETTINGS ACK",
formatHeader(true, 0, 0, TYPE_SETTINGS, (byte) 0x1));
frameLog(true, 0, 0, TYPE_SETTINGS, (byte) 0x1));
assertEquals("<< 0x00000000 8 PING ACK",
formatHeader(true, 0, 8, TYPE_PING, (byte) 0x1));
frameLog(true, 0, 8, TYPE_PING, (byte) 0x1));
assertEquals("<< 0x00000003 0 HEADERS END_STREAM",
formatHeader(true, 3, 0, TYPE_HEADERS, (byte) 0x1));
frameLog(true, 3, 0, TYPE_HEADERS, (byte) 0x1));
assertEquals("<< 0x00000003 0 DATA END_STREAM",
formatHeader(true, 3, 0, TYPE_DATA, (byte) 0x1));
frameLog(true, 3, 0, TYPE_DATA, (byte) 0x1));
}
@Test public void flagOverlapOn0x4() {
assertEquals("<< 0x00000003 10000 HEADERS END_HEADERS",
formatHeader(true, 3, 10000, TYPE_HEADERS, (byte) 0x4));
frameLog(true, 3, 10000, TYPE_HEADERS, (byte) 0x4));
assertEquals("<< 0x00000003 10000 CONTINUATION END_HEADERS",
formatHeader(true, 3, 10000, TYPE_CONTINUATION, (byte) 0x4));
frameLog(true, 3, 10000, TYPE_CONTINUATION, (byte) 0x4));
assertEquals("<< 0x00000004 10000 PUSH_PROMISE END_PUSH_PROMISE",
formatHeader(true, 4, 10000, TYPE_PUSH_PROMISE, (byte) 0x4));
frameLog(true, 4, 10000, TYPE_PUSH_PROMISE, (byte) 0x4));
}
@Test public void flagOverlapOn0x20() {
assertEquals("<< 0x00000003 10000 HEADERS PRIORITY",
formatHeader(true, 3, 10000, TYPE_HEADERS, (byte) 0x20));
frameLog(true, 3, 10000, TYPE_HEADERS, (byte) 0x20));
assertEquals("<< 0x00000003 10000 DATA COMPRESSED",
formatHeader(true, 3, 10000, TYPE_DATA, (byte) 0x20));
frameLog(true, 3, 10000, TYPE_DATA, (byte) 0x20));
}
/**
@@ -92,7 +90,7 @@ public final class Http2FrameLoggerTest {
*/
@Test public void allFormattedFlagsWithValidBits() {
List<String> formattedFlags = new ArrayList<>(0x40); // Highest valid flag is 0x20.
for (byte i = 0; i < 0x40; i++) formattedFlags.add(formatFlags(TYPE_HEADERS, i));
for (byte i = 0; i < 0x40; i++) formattedFlags.add(Http2.formatFlags(TYPE_HEADERS, i));
assertEquals(Arrays.asList(
"",

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.util.Arrays;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.util.Arrays;
@@ -29,20 +29,20 @@ import okio.Okio;
import org.junit.Test;
import static okhttp3.TestUtil.headerEntries;
import static okhttp3.internal.framed.Http2.FLAG_COMPRESSED;
import static okhttp3.internal.framed.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.framed.Http2.FLAG_END_STREAM;
import static okhttp3.internal.framed.Http2.FLAG_NONE;
import static okhttp3.internal.framed.Http2.FLAG_PADDED;
import static okhttp3.internal.framed.Http2.FLAG_PRIORITY;
import static okhttp3.internal.http2.Http2.FLAG_COMPRESSED;
import static okhttp3.internal.http2.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.http2.Http2.FLAG_END_STREAM;
import static okhttp3.internal.http2.Http2.FLAG_NONE;
import static okhttp3.internal.http2.Http2.FLAG_PADDED;
import static okhttp3.internal.http2.Http2.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 Http2Test {
public final class Http2Test {
final Buffer frame = new Buffer();
final FrameReader fr = new FrameReader(frame, false);
final Http2Reader reader = new Http2Reader(frame, false);
final int expectedStreamId = 15;
@Test public void unknownFrameTypeSkipped() throws IOException {
@@ -52,7 +52,7 @@ public class Http2Test {
frame.writeInt(expectedStreamId);
frame.writeInt(111111111); // custom data
fr.nextFrame(new BaseTestHandler()); // Should not callback.
reader.nextFrame(new BaseTestHandler()); // Should not callback.
}
@Test public void onlyOneLiteralHeadersFrame() throws IOException {
@@ -67,7 +67,7 @@ public class Http2Test {
assertEquals(frame, sendHeaderFrames(true, sentHeaders)); // Check writer sends the same bytes.
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void headers(boolean inFinished, int streamId,
int associatedStreamId, List<Header> headerBlock) {
assertTrue(inFinished);
@@ -90,7 +90,7 @@ public class Http2Test {
frame.writeByte(255); // Heaviest weight, zero-indexed.
frame.writeAll(headerBytes);
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void priority(int streamId, int streamDependency, int weight,
boolean exclusive) {
assertEquals(0, streamDependency);
@@ -131,7 +131,7 @@ public class Http2Test {
assertEquals(frame, sendHeaderFrames(false, sentHeaders)); // Check writer sends the same bytes.
// Reading the above frames should result in a concatenated headerBlock.
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void headers(boolean inFinished, int streamId,
int associatedStreamId, List<Header> headerBlock) {
assertFalse(inFinished);
@@ -163,7 +163,7 @@ public class Http2Test {
assertEquals(frame, sendPushPromiseFrames(expectedPromisedStreamId, pushPromise));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override
public void pushPromise(int streamId, int promisedStreamId, List<Header> headerBlock) {
assertEquals(expectedStreamId, streamId);
@@ -199,7 +199,7 @@ public class Http2Test {
assertEquals(frame, sendPushPromiseFrames(expectedPromisedStreamId, pushPromise));
// Reading the above frames should result in a concatenated headerBlock.
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override
public void pushPromise(int streamId, int promisedStreamId, List<Header> headerBlock) {
assertEquals(expectedStreamId, streamId);
@@ -216,7 +216,7 @@ public class Http2Test {
frame.writeInt(expectedStreamId & 0x7fffffff);
frame.writeInt(ErrorCode.PROTOCOL_ERROR.httpCode);
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void rstStream(int streamId, ErrorCode errorCode) {
assertEquals(expectedStreamId, streamId);
assertEquals(ErrorCode.PROTOCOL_ERROR, errorCode);
@@ -236,7 +236,7 @@ public class Http2Test {
frame.writeShort(2); // SETTINGS_ENABLE_PUSH
frame.writeInt(0);
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void settings(boolean clearPrevious, Settings settings) {
assertFalse(clearPrevious); // No clearPrevious in HTTP/2.
assertEquals(reducedTableSizeBytes, settings.getHeaderTableSize());
@@ -254,7 +254,7 @@ public class Http2Test {
frame.writeInt(2);
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR SETTINGS_ENABLE_PUSH != 0 or 1", e.getMessage());
@@ -270,7 +270,7 @@ public class Http2Test {
frame.writeInt(1);
final AtomicInteger settingValue = new AtomicInteger();
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void settings(boolean clearPrevious, Settings settings) {
settingValue.set(settings.get(7));
}
@@ -287,7 +287,7 @@ public class Http2Test {
frame.writeInt(Integer.MIN_VALUE);
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR SETTINGS_INITIAL_WINDOW_SIZE > 2^31 - 1", e.getMessage());
@@ -303,7 +303,7 @@ public class Http2Test {
frame.writeInt(Integer.MIN_VALUE);
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: -2147483648", e.getMessage());
@@ -319,7 +319,7 @@ public class Http2Test {
frame.writeInt((int) Math.pow(2, 14) - 1);
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: 16383", e.getMessage());
@@ -335,7 +335,7 @@ public class Http2Test {
frame.writeInt((int) Math.pow(2, 24));
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: 16777216", e.getMessage());
@@ -356,7 +356,7 @@ public class Http2Test {
// Check writer sends the same bytes.
assertEquals(frame, sendPingFrame(true, expectedPayload1, expectedPayload2));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void ping(boolean ack, int payload1, int payload2) {
assertTrue(ack);
assertEquals(expectedPayload1, payload1);
@@ -378,7 +378,7 @@ public class Http2Test {
// Check writer sends the same bytes.
assertEquals(frame, sendDataFrame(new Buffer().write(expectedData)));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void data(boolean inFinished, int streamId, BufferedSource source,
int length) throws IOException {
assertFalse(inFinished);
@@ -406,7 +406,7 @@ public class Http2Test {
zipped.readAll(frame);
try {
fr.nextFrame(new BaseTestHandler());
reader.nextFrame(new BaseTestHandler());
fail();
} catch (IOException e) {
assertEquals("PROTOCOL_ERROR: FLAG_COMPRESSED without SETTINGS_COMPRESS_DATA",
@@ -431,7 +431,7 @@ public class Http2Test {
frame.write(expectedData);
frame.write(padding);
fr.nextFrame(assertData());
reader.nextFrame(assertData());
assertTrue(frame.exhausted()); // Padding was skipped.
}
@@ -447,7 +447,7 @@ public class Http2Test {
frame.writeByte(0);
frame.write(expectedData);
fr.nextFrame(assertData());
reader.nextFrame(assertData());
}
@Test public void readPaddedHeadersFrame() throws IOException {
@@ -464,7 +464,7 @@ public class Http2Test {
frame.writeAll(headerBlock);
frame.write(padding);
fr.nextFrame(assertHeaderBlock());
reader.nextFrame(assertHeaderBlock());
assertTrue(frame.exhausted()); // Padding was skipped.
}
@@ -477,7 +477,7 @@ public class Http2Test {
frame.writeByte(0);
frame.writeAll(headerBlock);
fr.nextFrame(assertHeaderBlock());
reader.nextFrame(assertHeaderBlock());
}
/** Headers are compressed, then framed. */
@@ -505,7 +505,7 @@ public class Http2Test {
frame.writeInt(expectedStreamId & 0x7fffffff);
frame.writeAll(headerBlock);
fr.nextFrame(assertHeaderBlock());
reader.nextFrame(assertHeaderBlock());
assertTrue(frame.exhausted());
}
@@ -530,7 +530,7 @@ public class Http2Test {
// Check writer sends the same bytes.
assertEquals(frame, windowUpdate(expectedWindowSizeIncrement));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void windowUpdate(int streamId, long windowSizeIncrement) {
assertEquals(expectedStreamId, streamId);
assertEquals(expectedWindowSizeIncrement, windowSizeIncrement);
@@ -568,7 +568,7 @@ public class Http2Test {
// Check writer sends the same bytes.
assertEquals(frame, sendGoAway(expectedStreamId, expectedError, Util.EMPTY_BYTE_ARRAY));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void goAway(
int lastGoodStreamId, ErrorCode errorCode, ByteString debugData) {
assertEquals(expectedStreamId, lastGoodStreamId);
@@ -594,7 +594,7 @@ public class Http2Test {
// Check writer sends the same bytes.
assertEquals(frame, sendGoAway(0, expectedError, expectedData.toByteArray()));
fr.nextFrame(new BaseTestHandler() {
reader.nextFrame(new BaseTestHandler() {
@Override public void goAway(
int lastGoodStreamId, ErrorCode errorCode, ByteString debugData) {
assertEquals(0, lastGoodStreamId);
@@ -605,7 +605,7 @@ public class Http2Test {
}
@Test public void frameSizeError() throws IOException {
FrameWriter writer = new FrameWriter(new Buffer(), true);
Http2Writer writer = new Http2Writer(new Buffer(), true);
try {
writer.frameHeader(0, 16777216, Http2.TYPE_DATA, FLAG_NONE);
@@ -619,7 +619,7 @@ public class Http2Test {
@Test public void ackSettingsAppliesMaxFrameSize() throws IOException {
int newMaxFrameSize = 16777215;
FrameWriter writer = new FrameWriter(new Buffer(), true);
Http2Writer writer = new Http2Writer(new Buffer(), true);
writer.applyAndAckSettings(new Settings().set(Settings.MAX_FRAME_SIZE, newMaxFrameSize));
@@ -628,7 +628,7 @@ public class Http2Test {
}
@Test public void streamIdHasReservedBit() throws IOException {
FrameWriter writer = new FrameWriter(new Buffer(), true);
Http2Writer writer = new Http2Writer(new Buffer(), true);
try {
int streamId = 3;
@@ -648,43 +648,43 @@ public class Http2Test {
private Buffer sendHeaderFrames(boolean outFinished, List<Header> headers) throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).headers(outFinished, expectedStreamId, headers);
new Http2Writer(out, true).headers(outFinished, expectedStreamId, headers);
return out;
}
private Buffer sendPushPromiseFrames(int streamId, List<Header> headers) throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).pushPromise(expectedStreamId, streamId, headers);
new Http2Writer(out, true).pushPromise(expectedStreamId, streamId, headers);
return out;
}
private Buffer sendPingFrame(boolean ack, int payload1, int payload2) throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).ping(ack, payload1, payload2);
new Http2Writer(out, true).ping(ack, payload1, payload2);
return out;
}
private Buffer sendGoAway(int lastGoodStreamId, ErrorCode errorCode, byte[] debugData)
throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).goAway(lastGoodStreamId, errorCode, debugData);
new Http2Writer(out, true).goAway(lastGoodStreamId, errorCode, debugData);
return out;
}
private Buffer sendDataFrame(Buffer data) throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).dataFrame(expectedStreamId, FLAG_NONE, data,
new Http2Writer(out, true).dataFrame(expectedStreamId, FLAG_NONE, data,
(int) data.size());
return out;
}
private Buffer windowUpdate(long windowSizeIncrement) throws IOException {
Buffer out = new Buffer();
new FrameWriter(out, true).windowUpdate(expectedStreamId, windowSizeIncrement);
new Http2Writer(out, true).windowUpdate(expectedStreamId, windowSizeIncrement);
return out;
}
private FrameReader.Handler assertHeaderBlock() {
private Http2Reader.Handler assertHeaderBlock() {
return new BaseTestHandler() {
@Override public void headers(boolean inFinished, int streamId,
int associatedStreamId, List<Header> headerBlock) {
@@ -696,7 +696,7 @@ public class Http2Test {
};
}
private FrameReader.Handler assertData() {
private Http2Reader.Handler assertData() {
return new BaseTestHandler() {
@Override public void data(boolean inFinished, int streamId, BufferedSource source,
int length) throws IOException {
@@ -717,7 +717,7 @@ public class Http2Test {
return buffer;
}
/** Create a sufficiently large header set to overflow Http20Draft12.INITIAL_MAX_FRAME_SIZE bytes. */
/** Create a sufficiently large header set to overflow INITIAL_MAX_FRAME_SIZE bytes. */
private static List<Header> largeHeaders() {
String[] nameValues = new String[32];
char[] chars = new char[512];

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.Closeable;
import java.io.IOException;
@@ -44,7 +44,7 @@ public final class MockHttp2Peer implements Closeable {
private int frameCount = 0;
private boolean client = false;
private final Buffer bytesOut = new Buffer();
private FrameWriter frameWriter = new FrameWriter(bytesOut, client);
private Http2Writer writer = new Http2Writer(bytesOut, client);
private final List<OutFrame> outFrames = new ArrayList<>();
private final BlockingQueue<InFrame> inFrames = new LinkedBlockingQueue<>();
private int port;
@@ -58,7 +58,7 @@ public final class MockHttp2Peer implements Closeable {
return;
}
this.client = client;
this.frameWriter = new FrameWriter(bytesOut, client);
this.writer = new Http2Writer(bytesOut, client);
}
public void acceptFrame() {
@@ -67,7 +67,7 @@ public final class MockHttp2Peer implements Closeable {
/** Maximum length of an outbound data frame. */
public int maxOutboundDataLength() {
return frameWriter.maxDataLength();
return writer.maxDataLength();
}
/** Count of frames sent or received. */
@@ -75,9 +75,9 @@ public final class MockHttp2Peer implements Closeable {
return frameCount;
}
public FrameWriter sendFrame() {
public Http2Writer sendFrame() {
outFrames.add(new OutFrame(frameCount++, bytesOut.size(), false));
return frameWriter;
return writer;
}
/**
@@ -85,7 +85,7 @@ public final class MockHttp2Peer implements Closeable {
* close the socket as soon as this frame has been written; otherwise the peer stays open until
* explicitly closed.
*/
public FrameWriter truncateLastFrame(int length) {
public Http2Writer truncateLastFrame(int length) {
OutFrame lastFrame = outFrames.remove(outFrames.size() - 1);
if (length >= bytesOut.size() - lastFrame.start) throw new IllegalArgumentException();
@@ -97,7 +97,7 @@ public final class MockHttp2Peer implements Closeable {
fullBuffer.read(bytesOut, lastFrame.start + length);
outFrames.add(new OutFrame(lastFrame.sequence, lastFrame.start, true));
return frameWriter;
return writer;
}
public InFrame takeFrame() throws InterruptedException {
@@ -136,7 +136,7 @@ public final class MockHttp2Peer implements Closeable {
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
FrameReader reader = new FrameReader(Okio.buffer(Okio.source(in)), client);
Http2Reader reader = new Http2Reader(Okio.buffer(Okio.source(in)), client);
Iterator<OutFrame> outFramesIterator = outFrames.iterator();
byte[] outBytes = bytesOut.readByteArray();
@@ -203,9 +203,9 @@ public final class MockHttp2Peer implements Closeable {
}
}
public static class InFrame implements FrameReader.Handler {
public static class InFrame implements Http2Reader.Handler {
public final int sequence;
public final FrameReader reader;
public final Http2Reader reader;
public int type = -1;
public boolean clearPrevious;
public boolean outFinished;
@@ -221,7 +221,7 @@ public final class MockHttp2Peer implements Closeable {
public int payload1;
public int payload2;
public InFrame(int sequence, FrameReader reader) {
public InFrame(int sequence, Http2Reader reader) {
this.sequence = sequence;
this.reader = reader;
}

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import org.junit.Test;
import static okhttp3.internal.framed.Settings.DEFAULT_INITIAL_WINDOW_SIZE;
import static okhttp3.internal.framed.Settings.MAX_CONCURRENT_STREAMS;
import static okhttp3.internal.http2.Settings.DEFAULT_INITIAL_WINDOW_SIZE;
import static okhttp3.internal.http2.Settings.MAX_CONCURRENT_STREAMS;
import static org.junit.Assert.assertEquals;
public final class SettingsTest {

View File

@@ -33,7 +33,6 @@ import static okhttp3.internal.platform.PlatformTest.getPlatform;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
public final class CertificatePinnerChainValidationTest {
@Rule public final MockWebServer server = new MockWebServer();

View File

@@ -180,7 +180,7 @@ public final class WebSocketCall {
@Override protected void close() throws IOException {
replyExecutor.shutdown();
streamAllocation.noNewStreams();
streamAllocation.streamFinished(true, streamAllocation.stream());
streamAllocation.streamFinished(true, streamAllocation.codec());
}
}
}

View File

@@ -26,9 +26,9 @@ import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.Internal;
import okhttp3.internal.http.HttpCodec;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.http.HttpMethod;
import okhttp3.internal.http.HttpStream;
import okhttp3.internal.http.RealResponseBody;
import okio.Buffer;
import okio.BufferedSink;
@@ -222,7 +222,7 @@ public final class CacheInterceptor implements Interceptor {
@Override public void close() throws IOException {
if (!cacheRequestClosed
&& !discard(this, HttpStream.DISCARD_STREAM_TIMEOUT_MILLIS, MILLISECONDS)) {
&& !discard(this, HttpCodec.DISCARD_STREAM_TIMEOUT_MILLIS, MILLISECONDS)) {
cacheRequestClosed = true;
cacheRequest.abort();
}

View File

@@ -21,7 +21,7 @@ import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.http.HttpStream;
import okhttp3.internal.http.HttpCodec;
import okhttp3.internal.http.RealInterceptorChain;
/** Opens a connection to the target server and proceeds to the next interceptor. */
@@ -39,9 +39,9 @@ public final class ConnectInterceptor implements Interceptor {
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpStream httpStream = streamAllocation.newStream(client, doExtensiveHealthChecks);
HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpStream, connection);
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}

View File

@@ -43,11 +43,11 @@ import okhttp3.Response;
import okhttp3.Route;
import okhttp3.internal.Util;
import okhttp3.internal.Version;
import okhttp3.internal.framed.ErrorCode;
import okhttp3.internal.framed.FramedConnection;
import okhttp3.internal.framed.FramedStream;
import okhttp3.internal.http.Http1xStream;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.http1.Http1Codec;
import okhttp3.internal.http2.ErrorCode;
import okhttp3.internal.http2.Http2Connection;
import okhttp3.internal.http2.Http2Stream;
import okhttp3.internal.platform.Platform;
import okhttp3.internal.tls.OkHostnameVerifier;
import okio.BufferedSink;
@@ -60,7 +60,7 @@ import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static okhttp3.internal.Util.closeQuietly;
public final class RealConnection extends FramedConnection.Listener implements Connection {
public final class RealConnection extends Http2Connection.Listener implements Connection {
private final Route route;
/** The low-level TCP socket. */
@@ -73,7 +73,7 @@ public final class RealConnection extends FramedConnection.Listener implements C
public Socket socket;
private Handshake handshake;
private Protocol protocol;
public volatile FramedConnection framedConnection;
public volatile Http2Connection http2Connection;
public int successCount;
public BufferedSource source;
public BufferedSink sink;
@@ -204,15 +204,15 @@ public final class RealConnection extends FramedConnection.Listener implements C
if (protocol == Protocol.HTTP_2) {
socket.setSoTimeout(0); // Framed connection timeouts are set per-stream.
FramedConnection framedConnection = new FramedConnection.Builder(true)
Http2Connection http2Connection = new Http2Connection.Builder(true)
.socket(socket, route.address().url().host(), source, sink)
.listener(this)
.build();
framedConnection.start();
http2Connection.start();
// Only assign the framed connection once the preface has been sent successfully.
this.allocationLimit = framedConnection.maxConcurrentStreams();
this.framedConnection = framedConnection;
this.allocationLimit = http2Connection.maxConcurrentStreams();
this.http2Connection = http2Connection;
} else {
this.allocationLimit = 1;
}
@@ -287,7 +287,7 @@ public final class RealConnection extends FramedConnection.Listener implements C
// Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
String requestLine = "CONNECT " + Util.hostHeader(url, true) + " HTTP/1.1";
while (true) {
Http1xStream tunnelConnection = new Http1xStream(null, null, source, sink);
Http1Codec tunnelConnection = new Http1Codec(null, null, source, sink);
source.timeout().timeout(readTimeout, MILLISECONDS);
sink.timeout().timeout(writeTimeout, MILLISECONDS);
tunnelConnection.writeRequest(tunnelRequest.headers(), requestLine);
@@ -363,7 +363,7 @@ public final class RealConnection extends FramedConnection.Listener implements C
return false;
}
if (framedConnection != null) {
if (http2Connection != null) {
return true; // TODO: check framedConnection.shutdown.
}
@@ -390,12 +390,12 @@ public final class RealConnection extends FramedConnection.Listener implements C
}
/** Refuse incoming streams. */
@Override public void onStream(FramedStream stream) throws IOException {
@Override public void onStream(Http2Stream stream) throws IOException {
stream.close(ErrorCode.REFUSED_STREAM);
}
/** When settings are received, adjust the allocation limit. */
@Override public void onSettings(FramedConnection connection) {
@Override public void onSettings(Http2Connection connection) {
allocationLimit = connection.maxConcurrentStreams();
}
@@ -408,11 +408,11 @@ public final class RealConnection extends FramedConnection.Listener implements C
* requests simultaneously.
*/
public boolean isMultiplexed() {
return framedConnection != null;
return http2Connection != null;
}
@Override public Protocol protocol() {
if (framedConnection == null) {
if (http2Connection == null) {
return protocol != null ? protocol : Protocol.HTTP_1_1;
} else {
return Protocol.HTTP_2;

View File

@@ -24,11 +24,11 @@ import okhttp3.OkHttpClient;
import okhttp3.Route;
import okhttp3.internal.Internal;
import okhttp3.internal.Util;
import okhttp3.internal.framed.ErrorCode;
import okhttp3.internal.framed.StreamResetException;
import okhttp3.internal.http.Http1xStream;
import okhttp3.internal.http.Http2xStream;
import okhttp3.internal.http.HttpStream;
import okhttp3.internal.http.HttpCodec;
import okhttp3.internal.http1.Http1Codec;
import okhttp3.internal.http2.ErrorCode;
import okhttp3.internal.http2.Http2Codec;
import okhttp3.internal.http2.StreamResetException;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -80,7 +80,7 @@ public final class StreamAllocation {
private RealConnection connection;
private boolean released;
private boolean canceled;
private HttpStream stream;
private HttpCodec codec;
public StreamAllocation(ConnectionPool connectionPool, Address address) {
this.connectionPool = connectionPool;
@@ -88,7 +88,7 @@ public final class StreamAllocation {
this.routeSelector = new RouteSelector(address, routeDatabase());
}
public HttpStream newStream(OkHttpClient client, boolean doExtensiveHealthChecks) {
public HttpCodec newStream(OkHttpClient client, boolean doExtensiveHealthChecks) {
int connectTimeout = client.connectTimeoutMillis();
int readTimeout = client.readTimeoutMillis();
int writeTimeout = client.writeTimeoutMillis();
@@ -98,20 +98,20 @@ public final class StreamAllocation {
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
HttpStream resultStream;
if (resultConnection.framedConnection != null) {
resultStream = new Http2xStream(client, this, resultConnection.framedConnection);
HttpCodec resultCodec;
if (resultConnection.http2Connection != null) {
resultCodec = new Http2Codec(client, this, resultConnection.http2Connection);
} else {
resultConnection.socket().setSoTimeout(readTimeout);
resultConnection.source.timeout().timeout(readTimeout, MILLISECONDS);
resultConnection.sink.timeout().timeout(writeTimeout, MILLISECONDS);
resultStream = new Http1xStream(
resultCodec = new Http1Codec(
client, this, resultConnection.source, resultConnection.sink);
}
synchronized (connectionPool) {
stream = resultStream;
return resultStream;
codec = resultCodec;
return resultCodec;
}
} catch (IOException e) {
throw new RouteException(e);
@@ -156,7 +156,7 @@ public final class StreamAllocation {
Route selectedRoute;
synchronized (connectionPool) {
if (released) throw new IllegalStateException("released");
if (stream != null) throw new IllegalStateException("stream != null");
if (codec != null) throw new IllegalStateException("codec != null");
if (canceled) throw new IOException("Canceled");
RealConnection allocatedConnection = this.connection;
@@ -197,10 +197,10 @@ public final class StreamAllocation {
return newConnection;
}
public void streamFinished(boolean noNewStreams, HttpStream stream) {
public void streamFinished(boolean noNewStreams, HttpCodec codec) {
synchronized (connectionPool) {
if (stream == null || stream != this.stream) {
throw new IllegalStateException("expected " + this.stream + " but was " + stream);
if (codec == null || codec != this.codec) {
throw new IllegalStateException("expected " + this.codec + " but was " + codec);
}
if (!noNewStreams) {
connection.successCount++;
@@ -209,9 +209,9 @@ public final class StreamAllocation {
deallocate(noNewStreams, false, true);
}
public HttpStream stream() {
public HttpCodec codec() {
synchronized (connectionPool) {
return stream;
return codec;
}
}
@@ -240,7 +240,7 @@ public final class StreamAllocation {
RealConnection connectionToClose = null;
synchronized (connectionPool) {
if (streamFinished) {
this.stream = null;
this.codec = null;
}
if (released) {
this.released = true;
@@ -249,7 +249,7 @@ public final class StreamAllocation {
if (noNewStreams) {
connection.noNewStreams = true;
}
if (this.stream == null && (this.released || connection.noNewStreams)) {
if (this.codec == null && (this.released || connection.noNewStreams)) {
release(connection);
if (connection.allocations.isEmpty()) {
connection.idleAtNanos = System.nanoTime();
@@ -267,15 +267,15 @@ public final class StreamAllocation {
}
public void cancel() {
HttpStream streamToCancel;
HttpCodec codecToCancel;
RealConnection connectionToCancel;
synchronized (connectionPool) {
canceled = true;
streamToCancel = stream;
codecToCancel = codec;
connectionToCancel = connection;
}
if (streamToCancel != null) {
streamToCancel.cancel();
if (codecToCancel != null) {
codecToCancel.cancel();
} else if (connectionToCancel != null) {
connectionToCancel.cancel();
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
import java.io.IOException;
import okio.ByteString;
import static okhttp3.internal.Util.format;
public final class Http2 {
static final ByteString CONNECTION_PREFACE
= ByteString.encodeUtf8("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
/** The initial max frame size, applied independently writing to, or reading from the peer. */
static final int INITIAL_MAX_FRAME_SIZE = 0x4000; // 16384
static final byte TYPE_DATA = 0x0;
static final byte TYPE_HEADERS = 0x1;
static final byte TYPE_PRIORITY = 0x2;
static final byte TYPE_RST_STREAM = 0x3;
static final byte TYPE_SETTINGS = 0x4;
static final byte TYPE_PUSH_PROMISE = 0x5;
static final byte TYPE_PING = 0x6;
static final byte TYPE_GOAWAY = 0x7;
static final byte TYPE_WINDOW_UPDATE = 0x8;
static final byte TYPE_CONTINUATION = 0x9;
static final byte FLAG_NONE = 0x0;
static final byte FLAG_ACK = 0x1; // Used for settings and ping.
static final byte FLAG_END_STREAM = 0x1; // Used for headers and data.
static final byte FLAG_END_HEADERS = 0x4; // Used for headers and continuation.
static final byte FLAG_END_PUSH_PROMISE = 0x4;
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.
private Http2() {
}
static IllegalArgumentException illegalArgument(String message, Object... args) {
throw new IllegalArgumentException(format(message, args));
}
static IOException ioException(String message, Object... args) throws IOException {
throw new IOException(format(message, args));
}
}

View File

@@ -34,23 +34,23 @@ public final class CallServerInterceptor implements Interceptor {
}
@Override public Response intercept(Chain chain) throws IOException {
HttpStream httpStream = ((RealInterceptorChain) chain).httpStream();
HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
Request request = chain.request();
long sentRequestMillis = System.currentTimeMillis();
httpStream.writeRequestHeaders(request);
httpCodec.writeRequestHeaders(request);
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
Sink requestBodyOut = httpStream.createRequestBody(request, request.body().contentLength());
Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}
httpStream.finishRequest();
httpCodec.finishRequest();
Response response = httpStream.readResponseHeaders()
Response response = httpCodec.readResponseHeaders()
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
@@ -59,7 +59,7 @@ public final class CallServerInterceptor implements Interceptor {
if (!forWebSocket || response.code() != 101) {
response = response.newBuilder()
.body(httpStream.openResponseBody(response))
.body(httpCodec.openResponseBody(response))
.build();
}

View File

@@ -21,7 +21,8 @@ import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Sink;
public interface HttpStream {
/** Encodes HTTP requests and decodes HTTP responses. */
public interface HttpCodec {
/**
* The timeout to use while discarding a stream of input data. Since this is used for connection
* reuse, this timeout should be significantly less than the time it takes to establish a new

View File

@@ -31,18 +31,18 @@ import okhttp3.internal.connection.StreamAllocation;
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final StreamAllocation streamAllocation;
private final HttpStream httpStream;
private final HttpCodec httpCodec;
private final Connection connection;
private final int index;
private final Request request;
private int calls;
public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,
HttpStream httpStream, Connection connection, int index, Request request) {
HttpCodec httpCodec, Connection connection, int index, Request request) {
this.interceptors = interceptors;
this.connection = connection;
this.streamAllocation = streamAllocation;
this.httpStream = httpStream;
this.httpCodec = httpCodec;
this.index = index;
this.request = request;
}
@@ -55,8 +55,8 @@ public final class RealInterceptorChain implements Interceptor.Chain {
return streamAllocation;
}
public HttpStream httpStream() {
return httpStream;
public HttpCodec httpStream() {
return httpCodec;
}
@Override public Request request() {
@@ -64,35 +64,35 @@ public final class RealInterceptorChain implements Interceptor.Chain {
}
@Override public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpStream, connection);
return proceed(request, streamAllocation, httpCodec, connection);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
Connection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.httpStream != null && !sameConnection(request.url())) {
if (this.httpCodec != null && !sameConnection(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.httpStream != null && calls > 1) {
if (this.httpCodec != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpStream, connection, index + 1, request);
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpStream != null && index + 1 < interceptors.size() && next.calls != 1) {
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}

View File

@@ -29,7 +29,7 @@ public final class RequestLine {
* {@link HttpURLConnection#getHeaderFields}, so it needs to be set even if the transport is
* HTTP/2.
*/
static String get(Request request, Proxy.Type proxyType) {
public static String get(Request request, Proxy.Type proxyType) {
StringBuilder result = new StringBuilder();
result.append(request.method());
result.append(' ');

View File

@@ -174,7 +174,7 @@ public final class RetryAndFollowUpInterceptor implements Interceptor {
streamAllocation.release();
streamAllocation = new StreamAllocation(
client.connectionPool(), createAddress(followUp.url()));
} else if (streamAllocation.stream() != null) {
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.http;
package okhttp3.internal.http1;
import java.io.EOFException;
import java.io.IOException;
@@ -28,6 +28,11 @@ import okhttp3.internal.Internal;
import okhttp3.internal.Util;
import okhttp3.internal.connection.RealConnection;
import okhttp3.internal.connection.StreamAllocation;
import okhttp3.internal.http.HttpCodec;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.http.RealResponseBody;
import okhttp3.internal.http.RequestLine;
import okhttp3.internal.http.StatusLine;
import okio.Buffer;
import okio.BufferedSink;
import okio.BufferedSource;
@@ -61,7 +66,7 @@ import static okhttp3.internal.http.StatusLine.HTTP_CONTINUE;
* Exchanges that do not have a response body can call {@link #newFixedLengthSource(long)
* newFixedLengthSource(0)} and may skip reading and closing that source.
*/
public final class Http1xStream implements HttpStream {
public final class Http1Codec implements HttpCodec {
private static final int STATE_IDLE = 0; // Idle connections are ready to write request headers.
private static final int STATE_OPEN_REQUEST_BODY = 1;
private static final int STATE_WRITING_REQUEST_BODY = 2;
@@ -79,7 +84,7 @@ public final class Http1xStream implements HttpStream {
private final BufferedSink sink;
private int state = STATE_IDLE;
public Http1xStream(OkHttpClient client, StreamAllocation streamAllocation, BufferedSource source,
public Http1Codec(OkHttpClient client, StreamAllocation streamAllocation, BufferedSource source,
BufferedSink sink) {
this.client = client;
this.streamAllocation = streamAllocation;
@@ -353,7 +358,7 @@ public final class Http1xStream implements HttpStream {
state = STATE_CLOSED;
if (streamAllocation != null) {
streamAllocation.streamFinished(!reuseConnection, Http1xStream.this);
streamAllocation.streamFinished(!reuseConnection, Http1Codec.this);
}
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
// http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-7
public enum ErrorCode {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import okhttp3.internal.Util;
import okio.ByteString;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.util.ArrayList;

View File

@@ -13,83 +13,42 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import okio.ByteString;
import static okhttp3.internal.Util.format;
import static okhttp3.internal.framed.Http2.FLAG_ACK;
import static okhttp3.internal.framed.Http2.FLAG_COMPRESSED;
import static okhttp3.internal.framed.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.framed.Http2.FLAG_END_PUSH_PROMISE;
import static okhttp3.internal.framed.Http2.FLAG_END_STREAM;
import static okhttp3.internal.framed.Http2.FLAG_NONE;
import static okhttp3.internal.framed.Http2.FLAG_PADDED;
import static okhttp3.internal.framed.Http2.FLAG_PRIORITY;
import static okhttp3.internal.framed.Http2.TYPE_DATA;
import static okhttp3.internal.framed.Http2.TYPE_GOAWAY;
import static okhttp3.internal.framed.Http2.TYPE_PING;
import static okhttp3.internal.framed.Http2.TYPE_PRIORITY;
import static okhttp3.internal.framed.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.framed.Http2.TYPE_RST_STREAM;
import static okhttp3.internal.framed.Http2.TYPE_SETTINGS;
import static okhttp3.internal.framed.Http2.TYPE_WINDOW_UPDATE;
/**
* Logs a human-readable representation of HTTP/2 frame headers.
*
* <p>The format is:
*
* <pre>
* direction streamID length type flags
* </pre>
* Where direction is {@code <<} for inbound and {@code >>} for outbound.
*
* <p>For example, the following would indicate a HEAD request sent from the client.
* <pre>
* {@code
* << 0x0000000f 12 HEADERS END_HEADERS|END_STREAM
* }
* </pre>
*/
final class FrameLogger {
private FrameLogger() {
}
public final class Http2 {
static final ByteString CONNECTION_PREFACE
= ByteString.encodeUtf8("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
static String formatHeader(boolean inbound, int streamId, int length, byte type, byte flags) {
String formattedType = type < TYPES.length ? TYPES[type] : format("0x%02x", type);
String formattedFlags = formatFlags(type, flags);
return format("%s 0x%08x %5d %-13s %s", inbound ? "<<" : ">>", streamId, length,
formattedType, formattedFlags);
}
/** The initial max frame size, applied independently writing to, or reading from the peer. */
static final int INITIAL_MAX_FRAME_SIZE = 0x4000; // 16384
/**
* Looks up valid string representing flags from the table. Invalid combinations are represented
* in binary.
*/
// Visible for testing.
static String formatFlags(byte type, byte flags) {
if (flags == 0) return "";
switch (type) { // Special case types that have 0 or 1 flag.
case TYPE_SETTINGS:
case TYPE_PING:
return flags == FLAG_ACK ? "ACK" : BINARY[flags];
case TYPE_PRIORITY:
case TYPE_RST_STREAM:
case TYPE_GOAWAY:
case TYPE_WINDOW_UPDATE:
return BINARY[flags];
}
String result = flags < FLAGS.length ? FLAGS[flags] : BINARY[flags];
// Special case types that have overlap flag values.
if (type == TYPE_PUSH_PROMISE && (flags & FLAG_END_PUSH_PROMISE) != 0) {
return result.replace("HEADERS", "PUSH_PROMISE"); // TODO: Avoid allocation.
} else if (type == TYPE_DATA && (flags & FLAG_COMPRESSED) != 0) {
return result.replace("PRIORITY", "COMPRESSED"); // TODO: Avoid allocation.
}
return result;
}
static final byte TYPE_DATA = 0x0;
static final byte TYPE_HEADERS = 0x1;
static final byte TYPE_PRIORITY = 0x2;
static final byte TYPE_RST_STREAM = 0x3;
static final byte TYPE_SETTINGS = 0x4;
static final byte TYPE_PUSH_PROMISE = 0x5;
static final byte TYPE_PING = 0x6;
static final byte TYPE_GOAWAY = 0x7;
static final byte TYPE_WINDOW_UPDATE = 0x8;
static final byte TYPE_CONTINUATION = 0x9;
static final byte FLAG_NONE = 0x0;
static final byte FLAG_ACK = 0x1; // Used for settings and ping.
static final byte FLAG_END_STREAM = 0x1; // Used for headers and data.
static final byte FLAG_END_HEADERS = 0x4; // Used for headers and continuation.
static final byte FLAG_END_PUSH_PROMISE = 0x4;
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.
/** Lookup table for valid frame types. */
private static final String[] TYPES = new String[] {
private static final String[] FRAME_NAMES = new String[] {
"DATA",
"HEADERS",
"PRIORITY",
@@ -106,9 +65,8 @@ final class FrameLogger {
* Lookup table for valid flags for DATA, HEADERS, CONTINUATION. Invalid combinations are
* represented in binary.
*/
private static final String[] FLAGS = new String[0x40]; // Highest bit flag is 0x20.
private static final String[] BINARY = new String[256];
static final String[] FLAGS = new String[0x40]; // Highest bit flag is 0x20.
static final String[] BINARY = new String[256];
static {
for (int i = 0; i < BINARY.length; i++) {
BINARY[i] = format("%8s", Integer.toBinaryString(i)).replace(' ', '0');
@@ -143,4 +101,67 @@ final class FrameLogger {
if (FLAGS[i] == null) FLAGS[i] = BINARY[i];
}
}
private Http2() {
}
static IllegalArgumentException illegalArgument(String message, Object... args) {
throw new IllegalArgumentException(format(message, args));
}
static IOException ioException(String message, Object... args) throws IOException {
throw new IOException(format(message, args));
}
/**
* Returns human-readable representation of HTTP/2 frame headers.
*
* <p>The format is:
*
* <pre>
* direction streamID length type flags
* </pre>
*
* Where direction is {@code <<} for inbound and {@code >>} for outbound.
*
* <p>For example, the following would indicate a HEAD request sent from the client.
* <pre>
* {@code
* << 0x0000000f 12 HEADERS END_HEADERS|END_STREAM
* }
* </pre>
*/
static String frameLog(boolean inbound, int streamId, int length, byte type, byte flags) {
String formattedType = type < FRAME_NAMES.length ? FRAME_NAMES[type] : format("0x%02x", type);
String formattedFlags = formatFlags(type, flags);
return format("%s 0x%08x %5d %-13s %s", inbound ? "<<" : ">>", streamId, length,
formattedType, formattedFlags);
}
/**
* Looks up valid string representing flags from the table. Invalid combinations are represented
* in binary.
*/
// Visible for testing.
static String formatFlags(byte type, byte flags) {
if (flags == 0) return "";
switch (type) { // Special case types that have 0 or 1 flag.
case TYPE_SETTINGS:
case TYPE_PING:
return flags == FLAG_ACK ? "ACK" : BINARY[flags];
case TYPE_PRIORITY:
case TYPE_RST_STREAM:
case TYPE_GOAWAY:
case TYPE_WINDOW_UPDATE:
return BINARY[flags];
}
String result = flags < FLAGS.length ? FLAGS[flags] : BINARY[flags];
// Special case types that have overlap flag values.
if (type == TYPE_PUSH_PROMISE && (flags & FLAG_END_PUSH_PROMISE) != 0) {
return result.replace("HEADERS", "PUSH_PROMISE"); // TODO: Avoid allocation.
} else if (type == TYPE_DATA && (flags & FLAG_COMPRESSED) != 0) {
return result.replace("PRIORITY", "COMPRESSED"); // TODO: Avoid allocation.
}
return result;
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.http;
package okhttp3.internal.http2;
import java.io.IOException;
import java.net.ProtocolException;
@@ -30,24 +30,25 @@ import okhttp3.ResponseBody;
import okhttp3.internal.Internal;
import okhttp3.internal.Util;
import okhttp3.internal.connection.StreamAllocation;
import okhttp3.internal.framed.ErrorCode;
import okhttp3.internal.framed.FramedConnection;
import okhttp3.internal.framed.FramedStream;
import okhttp3.internal.framed.Header;
import okhttp3.internal.http.HttpCodec;
import okhttp3.internal.http.HttpMethod;
import okhttp3.internal.http.RealResponseBody;
import okhttp3.internal.http.RequestLine;
import okhttp3.internal.http.StatusLine;
import okio.ByteString;
import okio.ForwardingSource;
import okio.Okio;
import okio.Sink;
import okio.Source;
import static okhttp3.internal.framed.Header.RESPONSE_STATUS;
import static okhttp3.internal.framed.Header.TARGET_AUTHORITY;
import static okhttp3.internal.framed.Header.TARGET_METHOD;
import static okhttp3.internal.framed.Header.TARGET_PATH;
import static okhttp3.internal.framed.Header.TARGET_SCHEME;
import static okhttp3.internal.http2.Header.RESPONSE_STATUS;
import static okhttp3.internal.http2.Header.TARGET_AUTHORITY;
import static okhttp3.internal.http2.Header.TARGET_METHOD;
import static okhttp3.internal.http2.Header.TARGET_PATH;
import static okhttp3.internal.http2.Header.TARGET_SCHEME;
/** An HTTP stream for HTTP/2. */
public final class Http2xStream implements HttpStream {
/** Encode requests and responses using HTTP/2 frames. */
public final class Http2Codec implements HttpCodec {
private static final ByteString CONNECTION = ByteString.encodeUtf8("connection");
private static final ByteString HOST = ByteString.encodeUtf8("host");
private static final ByteString KEEP_ALIVE = ByteString.encodeUtf8("keep-alive");
@@ -83,14 +84,14 @@ public final class Http2xStream implements HttpStream {
private final OkHttpClient client;
private final StreamAllocation streamAllocation;
private final FramedConnection framedConnection;
private FramedStream stream;
private final Http2Connection connection;
private Http2Stream stream;
public Http2xStream(
OkHttpClient client, StreamAllocation streamAllocation, FramedConnection framedConnection) {
public Http2Codec(
OkHttpClient client, StreamAllocation streamAllocation, Http2Connection connection) {
this.client = client;
this.streamAllocation = streamAllocation;
this.framedConnection = framedConnection;
this.connection = connection;
}
@Override public Sink createRequestBody(Request request, long contentLength) {
@@ -102,7 +103,7 @@ public final class Http2xStream implements HttpStream {
boolean permitsRequestBody = HttpMethod.permitsRequestBody(request.method());
List<Header> requestHeaders = http2HeadersList(request);
stream = framedConnection.newStream(requestHeaders, permitsRequestBody);
stream = connection.newStream(requestHeaders, permitsRequestBody);
stream.readTimeout().timeout(client.readTimeoutMillis(), TimeUnit.MILLISECONDS);
stream.writeTimeout().timeout(client.writeTimeoutMillis(), TimeUnit.MILLISECONDS);
}
@@ -173,7 +174,7 @@ public final class Http2xStream implements HttpStream {
}
@Override public void close() throws IOException {
streamAllocation.streamFinished(false, Http2xStream.this);
streamAllocation.streamFinished(false, Http2Codec.this);
super.close();
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.Closeable;
import java.io.IOException;
@@ -40,7 +40,7 @@ import okio.BufferedSource;
import okio.ByteString;
import okio.Okio;
import static okhttp3.internal.framed.Settings.DEFAULT_INITIAL_WINDOW_SIZE;
import static okhttp3.internal.http2.Settings.DEFAULT_INITIAL_WINDOW_SIZE;
import static okhttp3.internal.platform.Platform.INFO;
/**
@@ -52,7 +52,7 @@ import static okhttp3.internal.platform.Platform.INFO;
* transparency: an IOException that was triggered by a certain caller can be caught and handled by
* that caller.
*/
public final class FramedConnection implements Closeable {
public final class Http2Connection implements Closeable {
// Internal state of this connection is guarded by 'this'. No blocking
// operations may be performed while holding this lock!
@@ -78,7 +78,7 @@ public final class FramedConnection implements Closeable {
* on {@link #executor}.
*/
private final Listener listener;
private final Map<Integer, FramedStream> streams = new HashMap<>();
private final Map<Integer, Http2Stream> streams = new HashMap<>();
private final String hostname;
private int lastGoodStreamId;
private int nextStreamId;
@@ -117,12 +117,12 @@ public final class FramedConnection implements Closeable {
private boolean receivedInitialPeerSettings = false;
final Socket socket;
final FrameWriter frameWriter;
final Http2Writer writer;
// Visible for testing
final Reader readerRunnable;
final ReaderRunnable readerRunnable;
private FramedConnection(Builder builder) {
private Http2Connection(Builder builder) {
pushObserver = builder.pushObserver;
client = builder.client;
listener = builder.listener;
@@ -152,9 +152,9 @@ public final class FramedConnection implements Closeable {
peerSettings.set(Settings.MAX_FRAME_SIZE, Http2.INITIAL_MAX_FRAME_SIZE);
bytesLeftInWriteWindow = peerSettings.getInitialWindowSize();
socket = builder.socket;
frameWriter = new FrameWriter(builder.sink, client);
writer = new Http2Writer(builder.sink, client);
readerRunnable = new Reader(new FrameReader(builder.source, client));
readerRunnable = new ReaderRunnable(new Http2Reader(builder.source, client));
}
/** The protocol as selected using ALPN. */
@@ -163,18 +163,18 @@ public final class FramedConnection implements Closeable {
}
/**
* Returns the number of {@link FramedStream#isOpen() open streams} on this connection.
* Returns the number of {@link Http2Stream#isOpen() open streams} on this connection.
*/
public synchronized int openStreamCount() {
return streams.size();
}
synchronized FramedStream getStream(int id) {
synchronized Http2Stream getStream(int id) {
return streams.get(id);
}
synchronized FramedStream removeStream(int streamId) {
FramedStream stream = streams.remove(streamId);
synchronized Http2Stream removeStream(int streamId) {
Http2Stream stream = streams.remove(streamId);
notifyAll(); // The removed stream may be blocked on a connection-wide window update.
return stream;
}
@@ -190,7 +190,7 @@ public final class FramedConnection implements Closeable {
* @param out true to create an output stream that we can use to send data to the remote peer.
* Corresponds to {@code FLAG_FIN}.
*/
public FramedStream pushStream(int associatedStreamId, List<Header> requestHeaders, boolean out)
public Http2Stream pushStream(int associatedStreamId, List<Header> requestHeaders, boolean out)
throws IOException {
if (client) throw new IllegalStateException("Client cannot push requests.");
return newStream(associatedStreamId, requestHeaders, out);
@@ -201,42 +201,42 @@ public final class FramedConnection implements Closeable {
* @param out true to create an output stream that we can use to send data to the remote peer.
* Corresponds to {@code FLAG_FIN}.
*/
public FramedStream newStream(List<Header> requestHeaders, boolean out) throws IOException {
public Http2Stream newStream(List<Header> requestHeaders, boolean out) throws IOException {
return newStream(0, requestHeaders, out);
}
private FramedStream newStream(
private Http2Stream newStream(
int associatedStreamId, List<Header> requestHeaders, boolean out) throws IOException {
boolean outFinished = !out;
boolean inFinished = false;
boolean flushHeaders;
FramedStream stream;
Http2Stream stream;
int streamId;
synchronized (frameWriter) {
synchronized (writer) {
synchronized (this) {
if (shutdown) {
throw new IOException("shutdown");
}
streamId = nextStreamId;
nextStreamId += 2;
stream = new FramedStream(streamId, this, outFinished, inFinished, requestHeaders);
stream = new Http2Stream(streamId, this, outFinished, inFinished, requestHeaders);
flushHeaders = !out || bytesLeftInWriteWindow == 0L || stream.bytesLeftInWriteWindow == 0L;
if (stream.isOpen()) {
streams.put(streamId, stream);
}
}
if (associatedStreamId == 0) {
frameWriter.synStream(outFinished, streamId, associatedStreamId, requestHeaders);
writer.synStream(outFinished, streamId, associatedStreamId, requestHeaders);
} else if (client) {
throw new IllegalArgumentException("client streams shouldn't have associated stream IDs");
} else { // HTTP/2 has a PUSH_PROMISE frame.
frameWriter.pushPromise(associatedStreamId, streamId, requestHeaders);
writer.pushPromise(associatedStreamId, streamId, requestHeaders);
}
}
if (flushHeaders) {
frameWriter.flush();
writer.flush();
}
return stream;
@@ -244,7 +244,7 @@ public final class FramedConnection implements Closeable {
void writeSynReply(int streamId, boolean outFinished, List<Header> alternating)
throws IOException {
frameWriter.synReply(outFinished, streamId, alternating);
writer.synReply(outFinished, streamId, alternating);
}
/**
@@ -262,13 +262,13 @@ public final class FramedConnection implements Closeable {
public void writeData(int streamId, boolean outFinished, Buffer buffer, long byteCount)
throws IOException {
if (byteCount == 0) { // Empty data frames are not flow-controlled.
frameWriter.data(outFinished, streamId, buffer, 0);
writer.data(outFinished, streamId, buffer, 0);
return;
}
while (byteCount > 0) {
int toWrite;
synchronized (FramedConnection.this) {
synchronized (Http2Connection.this) {
try {
while (bytesLeftInWriteWindow <= 0) {
// Before blocking, confirm that the stream we're writing is still open. It's possible
@@ -276,19 +276,19 @@ public final class FramedConnection implements Closeable {
if (!streams.containsKey(streamId)) {
throw new IOException("stream closed");
}
FramedConnection.this.wait(); // Wait until we receive a WINDOW_UPDATE.
Http2Connection.this.wait(); // Wait until we receive a WINDOW_UPDATE.
}
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
toWrite = (int) Math.min(byteCount, bytesLeftInWriteWindow);
toWrite = Math.min(toWrite, frameWriter.maxDataLength());
toWrite = Math.min(toWrite, writer.maxDataLength());
bytesLeftInWriteWindow -= toWrite;
}
byteCount -= toWrite;
frameWriter.data(outFinished && byteCount == 0, streamId, buffer, toWrite);
writer.data(outFinished && byteCount == 0, streamId, buffer, toWrite);
}
}
@@ -297,7 +297,7 @@ public final class FramedConnection implements Closeable {
*/
void addBytesToWriteWindow(long delta) {
bytesLeftInWriteWindow += delta;
if (delta > 0) FramedConnection.this.notifyAll();
if (delta > 0) Http2Connection.this.notifyAll();
}
void writeSynResetLater(final int streamId, final ErrorCode errorCode) {
@@ -312,14 +312,14 @@ public final class FramedConnection implements Closeable {
}
void writeSynReset(int streamId, ErrorCode statusCode) throws IOException {
frameWriter.rstStream(streamId, statusCode);
writer.rstStream(streamId, statusCode);
}
void writeWindowUpdateLater(final int streamId, final long unacknowledgedBytesRead) {
executor.execute(new NamedRunnable("OkHttp Window Update %s stream %d", hostname, streamId) {
@Override public void execute() {
try {
frameWriter.windowUpdate(streamId, unacknowledgedBytesRead);
writer.windowUpdate(streamId, unacknowledgedBytesRead);
} catch (IOException ignored) {
}
}
@@ -360,10 +360,10 @@ public final class FramedConnection implements Closeable {
}
private void writePing(boolean reply, int payload1, int payload2, Ping ping) throws IOException {
synchronized (frameWriter) {
synchronized (writer) {
// Observe the sent time immediately before performing I/O.
if (ping != null) ping.send();
frameWriter.ping(reply, payload1, payload2);
writer.ping(reply, payload1, payload2);
}
}
@@ -372,7 +372,7 @@ public final class FramedConnection implements Closeable {
}
public void flush() throws IOException {
frameWriter.flush();
writer.flush();
}
/**
@@ -381,7 +381,7 @@ public final class FramedConnection implements Closeable {
* to gracefully stop accepting new requests without harming previously established streams.
*/
public void shutdown(ErrorCode statusCode) throws IOException {
synchronized (frameWriter) {
synchronized (writer) {
int lastGoodStreamId;
synchronized (this) {
if (shutdown) {
@@ -391,7 +391,7 @@ public final class FramedConnection implements Closeable {
lastGoodStreamId = this.lastGoodStreamId;
}
// TODO: propagate exception message into debugData
frameWriter.goAway(lastGoodStreamId, statusCode, Util.EMPTY_BYTE_ARRAY);
writer.goAway(lastGoodStreamId, statusCode, Util.EMPTY_BYTE_ARRAY);
}
}
@@ -412,11 +412,11 @@ public final class FramedConnection implements Closeable {
thrown = e;
}
FramedStream[] streamsToClose = null;
Http2Stream[] streamsToClose = null;
Ping[] pingsToCancel = null;
synchronized (this) {
if (!streams.isEmpty()) {
streamsToClose = streams.values().toArray(new FramedStream[streams.size()]);
streamsToClose = streams.values().toArray(new Http2Stream[streams.size()]);
streams.clear();
}
if (pings != null) {
@@ -426,7 +426,7 @@ public final class FramedConnection implements Closeable {
}
if (streamsToClose != null) {
for (FramedStream stream : streamsToClose) {
for (Http2Stream stream : streamsToClose) {
try {
stream.close(streamCode);
} catch (IOException e) {
@@ -443,7 +443,7 @@ public final class FramedConnection implements Closeable {
// Close the writer to release its resources (such as deflaters).
try {
frameWriter.close();
writer.close();
} catch (IOException e) {
if (thrown == null) thrown = e;
}
@@ -472,11 +472,11 @@ public final class FramedConnection implements Closeable {
*/
void start(boolean sendConnectionPreface) throws IOException {
if (sendConnectionPreface) {
frameWriter.connectionPreface();
frameWriter.settings(okHttpSettings);
writer.connectionPreface();
writer.settings(okHttpSettings);
int windowSize = okHttpSettings.getInitialWindowSize();
if (windowSize != Settings.DEFAULT_INITIAL_WINDOW_SIZE) {
frameWriter.windowUpdate(0, windowSize - Settings.DEFAULT_INITIAL_WINDOW_SIZE);
writer.windowUpdate(0, windowSize - Settings.DEFAULT_INITIAL_WINDOW_SIZE);
}
}
new Thread(readerRunnable).start(); // Not a daemon thread.
@@ -484,13 +484,13 @@ public final class FramedConnection implements Closeable {
/** Merges {@code settings} into this peer's settings and sends them to the remote peer. */
public void setSettings(Settings settings) throws IOException {
synchronized (frameWriter) {
synchronized (writer) {
synchronized (this) {
if (shutdown) {
throw new IOException("shutdown");
}
okHttpSettings.merge(settings);
frameWriter.settings(settings);
writer.settings(settings);
}
}
}
@@ -536,8 +536,8 @@ public final class FramedConnection implements Closeable {
return this;
}
public FramedConnection build() throws IOException {
return new FramedConnection(this);
public Http2Connection build() throws IOException {
return new Http2Connection(this);
}
}
@@ -545,12 +545,12 @@ public final class FramedConnection implements Closeable {
* Methods in this class must not lock FrameWriter. If a method needs to write a frame, create an
* async task to do so.
*/
class Reader extends NamedRunnable implements FrameReader.Handler {
final FrameReader frameReader;
class ReaderRunnable extends NamedRunnable implements Http2Reader.Handler {
final Http2Reader reader;
private Reader(FrameReader frameReader) {
private ReaderRunnable(Http2Reader reader) {
super("OkHttp %s", hostname);
this.frameReader = frameReader;
this.reader = reader;
}
@Override protected void execute() {
@@ -558,9 +558,9 @@ public final class FramedConnection implements Closeable {
ErrorCode streamErrorCode = ErrorCode.INTERNAL_ERROR;
try {
if (!client) {
frameReader.readConnectionPreface();
reader.readConnectionPreface();
}
while (frameReader.nextFrame(this)) {
while (reader.nextFrame(this)) {
}
connectionErrorCode = ErrorCode.NO_ERROR;
streamErrorCode = ErrorCode.CANCEL;
@@ -572,7 +572,7 @@ public final class FramedConnection implements Closeable {
close(connectionErrorCode, streamErrorCode);
} catch (IOException ignored) {
}
Util.closeQuietly(frameReader);
Util.closeQuietly(reader);
}
}
@@ -582,7 +582,7 @@ public final class FramedConnection implements Closeable {
pushDataLater(streamId, source, length, inFinished);
return;
}
FramedStream dataStream = getStream(streamId);
Http2Stream dataStream = getStream(streamId);
if (dataStream == null) {
writeSynResetLater(streamId, ErrorCode.PROTOCOL_ERROR);
source.skip(length);
@@ -600,8 +600,8 @@ public final class FramedConnection implements Closeable {
pushHeadersLater(streamId, headerBlock, inFinished);
return;
}
FramedStream stream;
synchronized (FramedConnection.this) {
Http2Stream stream;
synchronized (Http2Connection.this) {
// If we're shutdown, don't bother with this stream.
if (shutdown) return;
@@ -615,7 +615,7 @@ public final class FramedConnection implements Closeable {
if (streamId % 2 == nextStreamId % 2) return;
// Create a stream.
final FramedStream newStream = new FramedStream(streamId, FramedConnection.this,
final Http2Stream newStream = new Http2Stream(streamId, Http2Connection.this,
false, inFinished, headerBlock);
lastGoodStreamId = streamId;
streams.put(streamId, newStream);
@@ -646,7 +646,7 @@ public final class FramedConnection implements Closeable {
pushResetLater(streamId, errorCode);
return;
}
FramedStream rstStream = removeStream(streamId);
Http2Stream rstStream = removeStream(streamId);
if (rstStream != null) {
rstStream.receiveRstStream(errorCode);
}
@@ -654,8 +654,8 @@ public final class FramedConnection implements Closeable {
@Override public void settings(boolean clearPrevious, Settings newSettings) {
long delta = 0;
FramedStream[] streamsToNotify = null;
synchronized (FramedConnection.this) {
Http2Stream[] streamsToNotify = null;
synchronized (Http2Connection.this) {
int priorWriteWindowSize = peerSettings.getInitialWindowSize();
if (clearPrevious) peerSettings.clear();
peerSettings.merge(newSettings);
@@ -668,17 +668,17 @@ public final class FramedConnection implements Closeable {
receivedInitialPeerSettings = true;
}
if (!streams.isEmpty()) {
streamsToNotify = streams.values().toArray(new FramedStream[streams.size()]);
streamsToNotify = streams.values().toArray(new Http2Stream[streams.size()]);
}
}
executor.execute(new NamedRunnable("OkHttp %s settings", hostname) {
@Override public void execute() {
listener.onSettings(FramedConnection.this);
listener.onSettings(Http2Connection.this);
}
});
}
if (streamsToNotify != null && delta != 0) {
for (FramedStream stream : streamsToNotify) {
for (Http2Stream stream : streamsToNotify) {
synchronized (stream) {
stream.addBytesToWriteWindow(delta);
}
@@ -690,7 +690,7 @@ public final class FramedConnection implements Closeable {
executor.execute(new NamedRunnable("OkHttp %s ACK Settings", hostname) {
@Override public void execute() {
try {
frameWriter.applyAndAckSettings(peerSettings);
writer.applyAndAckSettings(peerSettings);
} catch (IOException ignored) {
}
}
@@ -718,29 +718,29 @@ public final class FramedConnection implements Closeable {
}
// Copy the streams first. We don't want to hold a lock when we call receiveRstStream().
FramedStream[] streamsCopy;
synchronized (FramedConnection.this) {
streamsCopy = streams.values().toArray(new FramedStream[streams.size()]);
Http2Stream[] streamsCopy;
synchronized (Http2Connection.this) {
streamsCopy = streams.values().toArray(new Http2Stream[streams.size()]);
shutdown = true;
}
// Fail all streams created after the last good stream ID.
for (FramedStream framedStream : streamsCopy) {
if (framedStream.getId() > lastGoodStreamId && framedStream.isLocallyInitiated()) {
framedStream.receiveRstStream(ErrorCode.REFUSED_STREAM);
removeStream(framedStream.getId());
for (Http2Stream http2Stream : streamsCopy) {
if (http2Stream.getId() > lastGoodStreamId && http2Stream.isLocallyInitiated()) {
http2Stream.receiveRstStream(ErrorCode.REFUSED_STREAM);
removeStream(http2Stream.getId());
}
}
}
@Override public void windowUpdate(int streamId, long windowSizeIncrement) {
if (streamId == 0) {
synchronized (FramedConnection.this) {
synchronized (Http2Connection.this) {
bytesLeftInWriteWindow += windowSizeIncrement;
FramedConnection.this.notifyAll();
Http2Connection.this.notifyAll();
}
} else {
FramedStream stream = getStream(streamId);
Http2Stream stream = getStream(streamId);
if (stream != null) {
synchronized (stream) {
stream.addBytesToWriteWindow(windowSizeIncrement);
@@ -786,8 +786,8 @@ public final class FramedConnection implements Closeable {
boolean cancel = pushObserver.onRequest(streamId, requestHeaders);
try {
if (cancel) {
frameWriter.rstStream(streamId, ErrorCode.CANCEL);
synchronized (FramedConnection.this) {
writer.rstStream(streamId, ErrorCode.CANCEL);
synchronized (Http2Connection.this) {
currentPushRequests.remove(streamId);
}
}
@@ -803,9 +803,9 @@ public final class FramedConnection implements Closeable {
@Override public void execute() {
boolean cancel = pushObserver.onHeaders(streamId, requestHeaders, inFinished);
try {
if (cancel) frameWriter.rstStream(streamId, ErrorCode.CANCEL);
if (cancel) writer.rstStream(streamId, ErrorCode.CANCEL);
if (cancel || inFinished) {
synchronized (FramedConnection.this) {
synchronized (Http2Connection.this) {
currentPushRequests.remove(streamId);
}
}
@@ -829,9 +829,9 @@ public final class FramedConnection implements Closeable {
@Override public void execute() {
try {
boolean cancel = pushObserver.onData(streamId, buffer, byteCount, inFinished);
if (cancel) frameWriter.rstStream(streamId, ErrorCode.CANCEL);
if (cancel) writer.rstStream(streamId, ErrorCode.CANCEL);
if (cancel || inFinished) {
synchronized (FramedConnection.this) {
synchronized (Http2Connection.this) {
currentPushRequests.remove(streamId);
}
}
@@ -845,7 +845,7 @@ public final class FramedConnection implements Closeable {
pushExecutor.execute(new NamedRunnable("OkHttp %s Push Reset[%s]", hostname, streamId) {
@Override public void execute() {
pushObserver.onReset(streamId, errorCode);
synchronized (FramedConnection.this) {
synchronized (Http2Connection.this) {
currentPushRequests.remove(streamId);
}
}
@@ -855,17 +855,17 @@ public final class FramedConnection implements Closeable {
/** Listener of streams and settings initiated by the peer. */
public abstract static class Listener {
public static final Listener REFUSE_INCOMING_STREAMS = new Listener() {
@Override public void onStream(FramedStream stream) throws IOException {
@Override public void onStream(Http2Stream stream) throws IOException {
stream.close(ErrorCode.REFUSED_STREAM);
}
};
/**
* Handle a new stream from this connection's peer. Implementations should respond by either
* {@linkplain FramedStream#reply replying to the stream} or {@linkplain FramedStream#close
* {@linkplain Http2Stream#reply replying to the stream} or {@linkplain Http2Stream#close
* closing it}. This response does not need to be synchronous.
*/
public abstract void onStream(FramedStream stream) throws IOException;
public abstract void onStream(Http2Stream stream) throws IOException;
/**
* Notification that the connection's peer's settings may have changed. Implementations should
@@ -875,7 +875,7 @@ public final class FramedConnection implements Closeable {
* remote peer that sends multiple settings frames will trigger multiple calls to this method,
* and those calls are not necessarily serialized.
*/
public void onSettings(FramedConnection connection) {
public void onSettings(Http2Connection connection) {
}
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.Closeable;
import java.io.IOException;
@@ -27,37 +27,37 @@ import okio.Timeout;
import static java.util.logging.Level.FINE;
import static okhttp3.internal.Util.format;
import static okhttp3.internal.framed.FrameLogger.formatHeader;
import static okhttp3.internal.framed.Http2.CONNECTION_PREFACE;
import static okhttp3.internal.framed.Http2.FLAG_ACK;
import static okhttp3.internal.framed.Http2.FLAG_COMPRESSED;
import static okhttp3.internal.framed.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.framed.Http2.FLAG_END_STREAM;
import static okhttp3.internal.framed.Http2.FLAG_PADDED;
import static okhttp3.internal.framed.Http2.FLAG_PRIORITY;
import static okhttp3.internal.framed.Http2.INITIAL_MAX_FRAME_SIZE;
import static okhttp3.internal.framed.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.framed.Http2.TYPE_DATA;
import static okhttp3.internal.framed.Http2.TYPE_GOAWAY;
import static okhttp3.internal.framed.Http2.TYPE_HEADERS;
import static okhttp3.internal.framed.Http2.TYPE_PING;
import static okhttp3.internal.framed.Http2.TYPE_PRIORITY;
import static okhttp3.internal.framed.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.framed.Http2.TYPE_RST_STREAM;
import static okhttp3.internal.framed.Http2.TYPE_SETTINGS;
import static okhttp3.internal.framed.Http2.TYPE_WINDOW_UPDATE;
import static okhttp3.internal.framed.Http2.ioException;
import static okhttp3.internal.http2.Http2.CONNECTION_PREFACE;
import static okhttp3.internal.http2.Http2.FLAG_ACK;
import static okhttp3.internal.http2.Http2.FLAG_COMPRESSED;
import static okhttp3.internal.http2.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.http2.Http2.FLAG_END_STREAM;
import static okhttp3.internal.http2.Http2.FLAG_PADDED;
import static okhttp3.internal.http2.Http2.FLAG_PRIORITY;
import static okhttp3.internal.http2.Http2.INITIAL_MAX_FRAME_SIZE;
import static okhttp3.internal.http2.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.http2.Http2.TYPE_DATA;
import static okhttp3.internal.http2.Http2.TYPE_GOAWAY;
import static okhttp3.internal.http2.Http2.TYPE_HEADERS;
import static okhttp3.internal.http2.Http2.TYPE_PING;
import static okhttp3.internal.http2.Http2.TYPE_PRIORITY;
import static okhttp3.internal.http2.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.http2.Http2.TYPE_RST_STREAM;
import static okhttp3.internal.http2.Http2.TYPE_SETTINGS;
import static okhttp3.internal.http2.Http2.TYPE_WINDOW_UPDATE;
import static okhttp3.internal.http2.Http2.frameLog;
import static okhttp3.internal.http2.Http2.ioException;
import static okio.ByteString.EMPTY;
/**
* Reads transport frames for HTTP/2.
* Reads HTTP/2 transport frames.
*
* <p>This implementation assumes we do not send an increased {@link Settings#getMaxFrameSize frame
* size setting} to the peer. Hence, we expect all frames to have a max length of {@link
* Http2#INITIAL_MAX_FRAME_SIZE}.
*/
final class FrameReader implements Closeable {
private static final Logger logger = Logger.getLogger(FrameLogger.class.getName());
final class Http2Reader implements Closeable {
private static final Logger logger = Logger.getLogger(Http2.class.getName());
private final BufferedSource source;
private final ContinuationSource continuation;
@@ -67,7 +67,7 @@ final class FrameReader implements Closeable {
final Hpack.Reader hpackReader;
/** Creates a frame reader with max header table size of 4096. */
public FrameReader(BufferedSource source, boolean client) {
public Http2Reader(BufferedSource source, boolean client) {
this.source = source;
this.client = client;
this.continuation = new ContinuationSource(this.source);
@@ -109,7 +109,7 @@ final class FrameReader implements Closeable {
byte type = (byte) (source.readByte() & 0xff);
byte flags = (byte) (source.readByte() & 0xff);
int streamId = (source.readInt() & 0x7fffffff); // Ignore reserved bit.
if (logger.isLoggable(FINE)) logger.fine(formatHeader(true, streamId, length, type, flags));
if (logger.isLoggable(FINE)) logger.fine(frameLog(true, streamId, length, type, flags));
switch (type) {
case TYPE_DATA:
@@ -377,7 +377,7 @@ final class FrameReader implements Closeable {
length = left = readMedium(source);
byte type = (byte) (source.readByte() & 0xff);
flags = (byte) (source.readByte() & 0xff);
if (logger.isLoggable(FINE)) logger.fine(formatHeader(true, streamId, length, type, flags));
if (logger.isLoggable(FINE)) logger.fine(frameLog(true, streamId, length, type, flags));
streamId = (source.readInt() & 0x7fffffff);
if (type != TYPE_CONTINUATION) throw ioException("%s != TYPE_CONTINUATION", type);
if (streamId != previousStreamId) throw ioException("TYPE_CONTINUATION streamId changed");

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.EOFException;
import java.io.IOException;
@@ -29,7 +29,7 @@ import okio.Source;
import okio.Timeout;
/** A logical bidirectional stream. */
public final class FramedStream {
public final class Http2Stream {
// Internal state is guarded by this. No long-running or potentially
// blocking operations are performed while the lock is held.
@@ -49,7 +49,7 @@ public final class FramedStream {
long bytesLeftInWriteWindow;
private final int id;
private final FramedConnection connection;
private final Http2Connection connection;
/** Headers sent by the stream initiator. Immutable and non null. */
private final List<Header> requestHeaders;
@@ -69,7 +69,7 @@ public final class FramedStream {
*/
private ErrorCode errorCode = null;
FramedStream(int id, FramedConnection connection, boolean outFinished, boolean inFinished,
Http2Stream(int id, Http2Connection connection, boolean outFinished, boolean inFinished,
List<Header> requestHeaders) {
if (connection == null) throw new NullPointerException("connection == null");
if (requestHeaders == null) throw new NullPointerException("requestHeaders == null");
@@ -118,7 +118,7 @@ public final class FramedStream {
return connection.client == streamIsClient;
}
public FramedConnection getConnection() {
public Http2Connection getConnection() {
return connection;
}
@@ -158,7 +158,7 @@ public final class FramedStream {
* Corresponds to {@code FLAG_FIN}.
*/
public void reply(List<Header> responseHeaders, boolean out) throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
boolean outFinished = false;
synchronized (this) {
if (responseHeaders == null) {
@@ -248,7 +248,7 @@ public final class FramedStream {
}
void receiveHeaders(List<Header> headers) {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
boolean open = true;
synchronized (this) {
if (responseHeaders == null) {
@@ -268,12 +268,12 @@ public final class FramedStream {
}
void receiveData(BufferedSource in, int length) throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
this.source.receive(in, length);
}
void receiveFin() {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
boolean open;
synchronized (this) {
this.source.finished = true;
@@ -325,7 +325,7 @@ public final class FramedStream {
if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
long read;
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
waitUntilReadable();
checkNotClosed();
if (readBuffer.size() == 0) return -1; // This source is exhausted.
@@ -368,12 +368,12 @@ public final class FramedStream {
}
void receive(BufferedSource in, long byteCount) throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
while (byteCount > 0) {
boolean finished;
boolean flowControlError;
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
finished = this.finished;
flowControlError = byteCount + readBuffer.size() > maxByteCount;
}
@@ -397,11 +397,11 @@ public final class FramedStream {
byteCount -= read;
// Move the received data to the read buffer to the reader can read it.
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
boolean wasEmpty = readBuffer.size() == 0;
readBuffer.writeAll(receiveBuffer);
if (wasEmpty) {
FramedStream.this.notifyAll();
Http2Stream.this.notifyAll();
}
}
}
@@ -412,10 +412,10 @@ public final class FramedStream {
}
@Override public void close() throws IOException {
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
closed = true;
readBuffer.clear();
FramedStream.this.notifyAll();
Http2Stream.this.notifyAll();
}
cancelStreamIfNecessary();
}
@@ -431,7 +431,7 @@ public final class FramedStream {
}
private void cancelStreamIfNecessary() throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
boolean open;
boolean cancel;
synchronized (this) {
@@ -443,7 +443,7 @@ public final class FramedStream {
// is safe because the input stream is closed (we won't use any
// further bytes) and the output stream is either finished or closed
// (so RSTing both streams doesn't cause harm).
FramedStream.this.close(ErrorCode.CANCEL);
Http2Stream.this.close(ErrorCode.CANCEL);
} else if (!open) {
connection.removeStream(id);
}
@@ -469,7 +469,7 @@ public final class FramedStream {
private boolean finished;
@Override public void write(Buffer source, long byteCount) throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
assert (!Thread.holdsLock(Http2Stream.this));
sendBuffer.write(source, byteCount);
while (sendBuffer.size() >= EMIT_BUFFER_SIZE) {
emitDataFrame(false);
@@ -482,7 +482,7 @@ public final class FramedStream {
*/
private void emitDataFrame(boolean outFinished) throws IOException {
long toWrite;
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
writeTimeout.enter();
try {
while (bytesLeftInWriteWindow <= 0 && !finished && !closed && errorCode == null) {
@@ -506,8 +506,8 @@ public final class FramedStream {
}
@Override public void flush() throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
synchronized (FramedStream.this) {
assert (!Thread.holdsLock(Http2Stream.this));
synchronized (Http2Stream.this) {
checkOutNotClosed();
}
while (sendBuffer.size() > 0) {
@@ -521,8 +521,8 @@ public final class FramedStream {
}
@Override public void close() throws IOException {
assert (!Thread.holdsLock(FramedStream.this));
synchronized (FramedStream.this) {
assert (!Thread.holdsLock(Http2Stream.this));
synchronized (Http2Stream.this) {
if (closed) return;
}
if (!sink.finished) {
@@ -536,7 +536,7 @@ public final class FramedStream {
connection.writeData(id, true, null, 0);
}
}
synchronized (FramedStream.this) {
synchronized (Http2Stream.this) {
closed = true;
}
connection.flush();
@@ -549,7 +549,7 @@ public final class FramedStream {
*/
void addBytesToWriteWindow(long delta) {
bytesLeftInWriteWindow += delta;
if (delta > 0) FramedStream.this.notifyAll();
if (delta > 0) Http2Stream.this.notifyAll();
}
private void checkOutNotClosed() throws IOException {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.Closeable;
import java.io.IOException;
@@ -24,27 +24,27 @@ import okio.BufferedSink;
import static java.util.logging.Level.FINE;
import static okhttp3.internal.Util.format;
import static okhttp3.internal.framed.FrameLogger.formatHeader;
import static okhttp3.internal.framed.Http2.CONNECTION_PREFACE;
import static okhttp3.internal.framed.Http2.FLAG_ACK;
import static okhttp3.internal.framed.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.framed.Http2.FLAG_END_STREAM;
import static okhttp3.internal.framed.Http2.FLAG_NONE;
import static okhttp3.internal.framed.Http2.INITIAL_MAX_FRAME_SIZE;
import static okhttp3.internal.framed.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.framed.Http2.TYPE_DATA;
import static okhttp3.internal.framed.Http2.TYPE_GOAWAY;
import static okhttp3.internal.framed.Http2.TYPE_HEADERS;
import static okhttp3.internal.framed.Http2.TYPE_PING;
import static okhttp3.internal.framed.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.framed.Http2.TYPE_RST_STREAM;
import static okhttp3.internal.framed.Http2.TYPE_SETTINGS;
import static okhttp3.internal.framed.Http2.TYPE_WINDOW_UPDATE;
import static okhttp3.internal.framed.Http2.illegalArgument;
import static okhttp3.internal.http2.Http2.CONNECTION_PREFACE;
import static okhttp3.internal.http2.Http2.FLAG_ACK;
import static okhttp3.internal.http2.Http2.FLAG_END_HEADERS;
import static okhttp3.internal.http2.Http2.FLAG_END_STREAM;
import static okhttp3.internal.http2.Http2.FLAG_NONE;
import static okhttp3.internal.http2.Http2.INITIAL_MAX_FRAME_SIZE;
import static okhttp3.internal.http2.Http2.TYPE_CONTINUATION;
import static okhttp3.internal.http2.Http2.TYPE_DATA;
import static okhttp3.internal.http2.Http2.TYPE_GOAWAY;
import static okhttp3.internal.http2.Http2.TYPE_HEADERS;
import static okhttp3.internal.http2.Http2.TYPE_PING;
import static okhttp3.internal.http2.Http2.TYPE_PUSH_PROMISE;
import static okhttp3.internal.http2.Http2.TYPE_RST_STREAM;
import static okhttp3.internal.http2.Http2.TYPE_SETTINGS;
import static okhttp3.internal.http2.Http2.TYPE_WINDOW_UPDATE;
import static okhttp3.internal.http2.Http2.frameLog;
import static okhttp3.internal.http2.Http2.illegalArgument;
/** Writes transport frames for HTTP/2. */
public final class FrameWriter implements Closeable {
private static final Logger logger = Logger.getLogger(FrameLogger.class.getName());
/** Writes HTTP/2 transport frames. */
final class Http2Writer implements Closeable {
private static final Logger logger = Logger.getLogger(Http2.class.getName());
private final BufferedSink sink;
private final boolean client;
@@ -54,7 +54,7 @@ public final class FrameWriter implements Closeable {
final Hpack.Writer hpackWriter;
public FrameWriter(BufferedSink sink, boolean client) {
public Http2Writer(BufferedSink sink, boolean client) {
this.sink = sink;
this.client = client;
this.hpackBuffer = new Buffer();
@@ -263,7 +263,7 @@ public final class FrameWriter implements Closeable {
}
public void frameHeader(int streamId, int length, byte type, byte flags) throws IOException {
if (logger.isLoggable(FINE)) logger.fine(formatHeader(false, streamId, length, type, flags));
if (logger.isLoggable(FINE)) logger.fine(frameLog(false, streamId, length, type, flags));
if (length > maxFrameSize) {
throw illegalArgument("FRAME_SIZE_ERROR length > %d: %d", maxFrameSize, length);
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit;
/**
* A locally-originated ping.
*/
public final class Ping {
final class Ping {
private final CountDownLatch latch = new CountDownLatch(1);
private long sent = -1;
private long received = -1;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;
import java.util.List;

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.util.Arrays;
/**
* Settings describe characteristics of the sending peer, which are used by the receiving peer.
* Settings are {@link FramedConnection connection} scoped.
* Settings are {@link Http2Connection connection} scoped.
*/
public final class Settings {
/**

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.internal.framed;
package okhttp3.internal.http2;
import java.io.IOException;