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:
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
@@ -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(
|
||||
"",
|
||||
@@ -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;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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];
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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(' ');
|
||||
|
||||
@@ -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?");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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 {
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
/**
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user