aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NOTICE.txt41
-rw-r--r--all/build.gradle4
-rw-r--r--build.gradle1
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--okhttp/build.gradle15
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/AsyncFrameWriter.java9
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/Headers.java3
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java5
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java5
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java21
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java (renamed from okhttp/src/main/java/com/squareup/okhttp/internal/OkHttpProtocolNegotiator.java)9
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpSettingsUtil.java (renamed from okhttp/src/main/java/com/squareup/okhttp/internal/framed/OkHttpSettingsUtil.java)6
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OkHttpTlsUpgrader.java (renamed from okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java)7
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java2
-rw-r--r--okhttp/src/main/java/io/grpc/okhttp/Utils.java25
-rw-r--r--okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java15
-rw-r--r--okhttp/third_party/okhttp/LICENSE202
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/CipherSuite.java379
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/ConnectionSpec.java354
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/OptionalMethod.java182
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java384
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Protocol.java101
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/TlsVersion.java57
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Util.java290
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java95
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java141
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java107
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Header.java60
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java53
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Hpack.java441
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Http2.java776
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Huffman.java229
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java242
-rw-r--r--okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Variant.java41
34 files changed, 4258 insertions, 46 deletions
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 000000000..ee67bad4b
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,41 @@
+Copyright 2014, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-----------------------------------------------------------------------
+
+This product contains a modified portion of 'OkHttp', an open source
+HTTP & SPDY client for Android and Java applications, which can be obtained
+at:
+
+ * LICENSE:
+ * okhttp/third_party/okhttp/LICENSE (Apache License 2.0)
+ * HOMEPAGE:
+ * https://github.com/square/okhttp
+ * LOCATION_IN_GRPC:
+ * okhttp/third_party/okhttp \ No newline at end of file
diff --git a/all/build.gradle b/all/build.gradle
index e67b6b470..e7a235a62 100644
--- a/all/build.gradle
+++ b/all/build.gradle
@@ -75,6 +75,10 @@ jacocoTestReport {
additionalSourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories = files(subprojects.sourceSets.main.output)
+ classDirectories = files(classDirectories.files.collect {
+ fileTree(dir: it,
+ exclude: ['**/io/grpc/okhttp/internal/**'])
+ })
}
coveralls {
diff --git a/build.gradle b/build.gradle
index 717ea3c9e..144e1e975 100644
--- a/build.gradle
+++ b/build.gradle
@@ -131,6 +131,7 @@ subprojects {
jsr305: 'com.google.code.findbugs:jsr305:3.0.0',
oauth_client: 'com.google.auth:google-auth-library-oauth2-http:0.3.0',
okhttp: 'com.squareup.okhttp:okhttp:2.5.0',
+ okio: 'com.squareup.okio:okio:1.6.0',
protobuf: "com.google.protobuf:protobuf-java:${protobufVersion}",
protobuf_nano: "com.google.protobuf.nano:protobuf-javanano:${protobufNanoVersion}",
protobuf_plugin: 'com.google.protobuf:protobuf-gradle-plugin:0.7.0',
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4cbfb745d..3279ebc89 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Mon Sep 21 10:27:21 PDT 2015
+#Tue May 12 09:49:30 PDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/okhttp/build.gradle b/okhttp/build.gradle
index af8ca0e27..62b2f53d7 100644
--- a/okhttp/build.gradle
+++ b/okhttp/build.gradle
@@ -5,16 +5,27 @@ plugins {
description = "gRPC: OkHttp"
dependencies {
compile project(':grpc-core'),
- libraries.okhttp
+ libraries.okhttp,
+ libraries.okio
// Tests depend on base class defined by core module.
testCompile project(':grpc-core').sourceSets.test.output
}
+project.sourceSets {
+ main {
+ java {
+ srcDir "${projectDir}/third_party/okhttp/java"
+ }
+ }
+}
+
+checkstyleMain.exclude '**/io/grpc/okhttp/internal/**'
+
// Configure the animal sniffer plugin
animalsniffer {
signature = "org.codehaus.mojo.signature:java16:+@signature"
}
-javadoc.exclude 'com/squareup/**'
+javadoc.exclude 'io/grpc/okhttp/internal/**'
javadoc.options.links 'http://square.github.io/okhttp/javadoc/'
diff --git a/okhttp/src/main/java/io/grpc/okhttp/AsyncFrameWriter.java b/okhttp/src/main/java/io/grpc/okhttp/AsyncFrameWriter.java
index c2be096d2..57eb77201 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/AsyncFrameWriter.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/AsyncFrameWriter.java
@@ -33,12 +33,11 @@ package io.grpc.okhttp;
import com.google.common.base.Preconditions;
-import com.squareup.okhttp.internal.framed.ErrorCode;
-import com.squareup.okhttp.internal.framed.FrameWriter;
-import com.squareup.okhttp.internal.framed.Header;
-import com.squareup.okhttp.internal.framed.Settings;
-
import io.grpc.internal.SerializingExecutor;
+import io.grpc.okhttp.internal.framed.ErrorCode;
+import io.grpc.okhttp.internal.framed.FrameWriter;
+import io.grpc.okhttp.internal.framed.Header;
+import io.grpc.okhttp.internal.framed.Settings;
import okio.Buffer;
diff --git a/okhttp/src/main/java/io/grpc/okhttp/Headers.java b/okhttp/src/main/java/io/grpc/okhttp/Headers.java
index b90954e68..d413587d2 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/Headers.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/Headers.java
@@ -37,11 +37,10 @@ import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY;
import com.google.common.base.Preconditions;
-import com.squareup.okhttp.internal.framed.Header;
-
import io.grpc.Metadata;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.TransportFrameUtil;
+import io.grpc.okhttp.internal.framed.Header;
import okio.ByteString;
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
index 339285422..02f7176a8 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
@@ -77,6 +77,7 @@ public class OkHttpChannelBuilder extends
.tlsVersions(TlsVersion.TLS_1_2)
.supportsTlsExtensions(true)
.build();
+
private static final Resource<ExecutorService> SHARED_EXECUTOR =
new Resource<ExecutorService>() {
@Override
@@ -172,7 +173,7 @@ public class OkHttpChannelBuilder extends
* For secure connection, provides a ConnectionSpec to specify Cipher suite and
* TLS versions.
*
- * <p>By default DEFAULT_CONNECTION_SPEC will be used.
+ * <p>By default {@link #DEFAULT_CONNECTION_SPEC} will be used.
*/
public final OkHttpChannelBuilder connectionSpec(ConnectionSpec connectionSpec) {
this.connectionSpec = connectionSpec;
@@ -265,7 +266,7 @@ public class OkHttpChannelBuilder extends
@Override
public ClientTransport newClientTransport() {
return new OkHttpClientTransport(host, port, authority, executor, socketFactory,
- connectionSpec, maxMessageSize);
+ Utils.convertSpec(connectionSpec), maxMessageSize);
}
@Override
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java
index 3de99086c..36c487789 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java
@@ -34,15 +34,14 @@ package io.grpc.okhttp;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import com.squareup.okhttp.internal.framed.ErrorCode;
-import com.squareup.okhttp.internal.framed.Header;
-
import io.grpc.Metadata;
import io.grpc.MethodDescriptor.MethodType;
import io.grpc.Status;
import io.grpc.internal.ClientStreamListener;
import io.grpc.internal.Http2ClientStream;
import io.grpc.internal.WritableBuffer;
+import io.grpc.okhttp.internal.framed.ErrorCode;
+import io.grpc.okhttp.internal.framed.Header;
import okio.Buffer;
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java
index 0f52c9b1b..1d73ec9dc 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java
@@ -39,18 +39,6 @@ import com.google.common.base.Stopwatch;
import com.google.common.base.Ticker;
import com.google.common.util.concurrent.SettableFuture;
-import com.squareup.okhttp.ConnectionSpec;
-import com.squareup.okhttp.OkHttpTlsUpgrader;
-import com.squareup.okhttp.internal.framed.ErrorCode;
-import com.squareup.okhttp.internal.framed.FrameReader;
-import com.squareup.okhttp.internal.framed.FrameWriter;
-import com.squareup.okhttp.internal.framed.Header;
-import com.squareup.okhttp.internal.framed.HeadersMode;
-import com.squareup.okhttp.internal.framed.Http2;
-import com.squareup.okhttp.internal.framed.OkHttpSettingsUtil;
-import com.squareup.okhttp.internal.framed.Settings;
-import com.squareup.okhttp.internal.framed.Variant;
-
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.MethodDescriptor.MethodType;
@@ -61,6 +49,15 @@ import io.grpc.internal.ClientTransport;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.Http2Ping;
import io.grpc.internal.SerializingExecutor;
+import io.grpc.okhttp.internal.ConnectionSpec;
+import io.grpc.okhttp.internal.framed.ErrorCode;
+import io.grpc.okhttp.internal.framed.FrameReader;
+import io.grpc.okhttp.internal.framed.FrameWriter;
+import io.grpc.okhttp.internal.framed.Header;
+import io.grpc.okhttp.internal.framed.HeadersMode;
+import io.grpc.okhttp.internal.framed.Http2;
+import io.grpc.okhttp.internal.framed.Settings;
+import io.grpc.okhttp.internal.framed.Variant;
import okio.Buffer;
import okio.BufferedSink;
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/OkHttpProtocolNegotiator.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
index c15080250..f2caedc8a 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/OkHttpProtocolNegotiator.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
@@ -29,9 +29,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package com.squareup.okhttp.internal;
+package io.grpc.okhttp;
-import com.squareup.okhttp.Protocol;
+import io.grpc.okhttp.internal.OptionalMethod;
+import io.grpc.okhttp.internal.Platform;
+import io.grpc.okhttp.internal.Protocol;
+import io.grpc.okhttp.internal.Util;
import java.io.IOException;
import java.net.Socket;
@@ -44,7 +47,7 @@ import javax.net.ssl.SSLSocket;
/**
* A helper class located in package com.squareup.okhttp.internal for TLS negotiation.
*/
-public class OkHttpProtocolNegotiator {
+class OkHttpProtocolNegotiator {
private static final Platform PLATFORM = Platform.get();
private static OkHttpProtocolNegotiator NEGOTIATOR = createNegotiator();
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/framed/OkHttpSettingsUtil.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpSettingsUtil.java
index 264ca4cba..b0862f49f 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/framed/OkHttpSettingsUtil.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpSettingsUtil.java
@@ -29,12 +29,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package com.squareup.okhttp.internal.framed;
+package io.grpc.okhttp;
+
+import io.grpc.okhttp.internal.framed.Settings;
/**
* A utility class help gRPC get/set the necessary fields of OkHttp's Settings.
*/
-public class OkHttpSettingsUtil {
+class OkHttpSettingsUtil {
public static final int MAX_CONCURRENT_STREAMS = Settings.MAX_CONCURRENT_STREAMS;
public static final int INITIAL_WINDOW_SIZE = Settings.INITIAL_WINDOW_SIZE;
diff --git a/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpTlsUpgrader.java
index 039552a34..6fa1f7bd7 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/OkHttpTlsUpgrader.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpTlsUpgrader.java
@@ -29,11 +29,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package com.squareup.okhttp;
+package io.grpc.okhttp;
import com.google.common.base.Preconditions;
-import com.squareup.okhttp.internal.OkHttpProtocolNegotiator;
+import io.grpc.okhttp.internal.ConnectionSpec;
+import io.grpc.okhttp.internal.Protocol;
import java.io.IOException;
import java.net.Socket;
@@ -48,7 +49,7 @@ import javax.net.ssl.SSLSocketFactory;
* A helper class that located in package com.squareup.okhttp, so that we can use OkHttp internals
* to do TLS upgrading.
*/
-public final class OkHttpTlsUpgrader {
+final class OkHttpTlsUpgrader {
private static final String HTTP2_PROTOCOL_NAME = "h2";
private static final List<Protocol> TLS_PROTOCOLS =
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java b/okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java
index 3e68b61a1..628ceeb86 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java
@@ -39,7 +39,7 @@ import static java.lang.Math.min;
import com.google.common.base.Preconditions;
-import com.squareup.okhttp.internal.framed.FrameWriter;
+import io.grpc.okhttp.internal.framed.FrameWriter;
import okio.Buffer;
diff --git a/okhttp/src/main/java/io/grpc/okhttp/Utils.java b/okhttp/src/main/java/io/grpc/okhttp/Utils.java
index c7201aa27..4d3919ef2 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/Utils.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/Utils.java
@@ -31,10 +31,11 @@
package io.grpc.okhttp;
-import com.squareup.okhttp.internal.framed.Header;
-
import io.grpc.Metadata;
import io.grpc.internal.TransportFrameUtil;
+import io.grpc.okhttp.internal.CipherSuite;
+import io.grpc.okhttp.internal.ConnectionSpec;
+import io.grpc.okhttp.internal.framed.Header;
import java.util.List;
@@ -63,6 +64,26 @@ class Utils {
return TransportFrameUtil.toRawSerializedHeaders(headerValues);
}
+ static ConnectionSpec convertSpec(com.squareup.okhttp.ConnectionSpec spec) {
+ List<com.squareup.okhttp.TlsVersion> tlsVersionList = spec.tlsVersions();
+ String[] tlsVersions = new String[tlsVersionList.size()];
+ for (int i = 0; i < tlsVersions.length; i++) {
+ tlsVersions[i] = tlsVersionList.get(i).javaName();
+ }
+
+ List<com.squareup.okhttp.CipherSuite> cipherSuiteList = spec.cipherSuites();
+ CipherSuite[] cipherSuites = new CipherSuite[cipherSuiteList.size()];
+ for (int i = 0; i < cipherSuites.length; i++) {
+ cipherSuites[i] = CipherSuite.valueOf(cipherSuiteList.get(i).name());
+ }
+
+ return new ConnectionSpec.Builder(spec.isTls())
+ .supportsTlsExtensions(spec.supportsTlsExtensions())
+ .tlsVersions(tlsVersions)
+ .cipherSuites(cipherSuites)
+ .build();
+ }
+
private Utils() {
// Prevents instantiation
}
diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java
index 165d7d176..1f9507970 100644
--- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java
+++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpClientTransportTest.java
@@ -63,14 +63,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
-import com.squareup.okhttp.internal.framed.ErrorCode;
-import com.squareup.okhttp.internal.framed.FrameReader;
-import com.squareup.okhttp.internal.framed.FrameWriter;
-import com.squareup.okhttp.internal.framed.Header;
-import com.squareup.okhttp.internal.framed.HeadersMode;
-import com.squareup.okhttp.internal.framed.OkHttpSettingsUtil;
-import com.squareup.okhttp.internal.framed.Settings;
-
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.MethodDescriptor.MethodType;
@@ -81,6 +73,13 @@ import io.grpc.internal.ClientStreamListener;
import io.grpc.internal.ClientTransport;
import io.grpc.internal.GrpcUtil;
import io.grpc.okhttp.OkHttpClientTransport.ClientFrameHandler;
+import io.grpc.okhttp.internal.ConnectionSpec;
+import io.grpc.okhttp.internal.framed.ErrorCode;
+import io.grpc.okhttp.internal.framed.FrameReader;
+import io.grpc.okhttp.internal.framed.FrameWriter;
+import io.grpc.okhttp.internal.framed.Header;
+import io.grpc.okhttp.internal.framed.HeadersMode;
+import io.grpc.okhttp.internal.framed.Settings;
import okio.Buffer;
diff --git a/okhttp/third_party/okhttp/LICENSE b/okhttp/third_party/okhttp/LICENSE
new file mode 100644
index 000000000..7a4a3ea24
--- /dev/null
+++ b/okhttp/third_party/okhttp/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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. \ No newline at end of file
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/CipherSuite.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/CipherSuite.java
new file mode 100644
index 000000000..bc2a9b7f0
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/CipherSuite.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import static java.lang.Integer.MAX_VALUE;
+
+/**
+ * <a href="https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml">TLS cipher
+ * suites</a>.
+ *
+ * <p><strong>Not all cipher suites are supported on all platforms.</strong> As newer cipher suites
+ * are created (for stronger privacy, better performance, etc.) they will be adopted by the platform
+ * and then exposed here. Cipher suites that are not available on either Android (through API level
+ * 20) or Java (through JDK 8) are omitted for brevity.
+ *
+ * <p>See also <a href="https://android.googlesource.com/platform/external/conscrypt/+/master/src/main/java/org/conscrypt/NativeCrypto.java">NativeCrypto.java</a>
+ * from conscrypt, which lists the cipher suites supported by Android.
+ */
+public enum CipherSuite {
+ // Last updated 2014-11-11 using cipher suites from Android 21 and Java 8.
+
+ // TLS_NULL_WITH_NULL_NULL("TLS_NULL_WITH_NULL_NULL", 0x0000, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_RSA_WITH_NULL_MD5("SSL_RSA_WITH_NULL_MD5", 0x0001, 5246, 6, 10),
+ TLS_RSA_WITH_NULL_SHA("SSL_RSA_WITH_NULL_SHA", 0x0002, 5246, 6, 10),
+ TLS_RSA_EXPORT_WITH_RC4_40_MD5("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 0x0003, 4346, 6, 10),
+ TLS_RSA_WITH_RC4_128_MD5("SSL_RSA_WITH_RC4_128_MD5", 0x0004, 5246, 6, 10),
+ TLS_RSA_WITH_RC4_128_SHA("SSL_RSA_WITH_RC4_128_SHA", 0x0005, 5246, 6, 10),
+ // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006, 4346, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_IDEA_CBC_SHA("TLS_RSA_WITH_IDEA_CBC_SHA", 0x0007, 5469, MAX_VALUE, MAX_VALUE),
+ TLS_RSA_EXPORT_WITH_DES40_CBC_SHA("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0008, 4346, 6, 10),
+ TLS_RSA_WITH_DES_CBC_SHA("SSL_RSA_WITH_DES_CBC_SHA", 0x0009, 5469, 6, 10),
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA("SSL_RSA_WITH_3DES_EDE_CBC_SHA", 0x000a, 5246, 6, 10),
+ // TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b, 4346, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_DES_CBC_SHA("TLS_DH_DSS_WITH_DES_CBC_SHA", 0x000c, 5469, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA("TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d, 5246, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e, 4346, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_DES_CBC_SHA("TLS_DH_RSA_WITH_DES_CBC_SHA", 0x000f, 5469, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA("TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0011, 4346, 6, 10),
+ TLS_DHE_DSS_WITH_DES_CBC_SHA("SSL_DHE_DSS_WITH_DES_CBC_SHA", 0x0012, 5469, 6, 10),
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 0x0013, 5246, 6, 10),
+ TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0014, 4346, 6, 10),
+ TLS_DHE_RSA_WITH_DES_CBC_SHA("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0015, 5469, 6, 10),
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 0x0016, 5246, 6, 10),
+ TLS_DH_anon_EXPORT_WITH_RC4_40_MD5("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", 0x0017, 4346, 6, 10),
+ TLS_DH_anon_WITH_RC4_128_MD5("SSL_DH_anon_WITH_RC4_128_MD5", 0x0018, 5246, 6, 10),
+ TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0x0019, 4346, 6, 10),
+ TLS_DH_anon_WITH_DES_CBC_SHA("SSL_DH_anon_WITH_DES_CBC_SHA", 0x001a, 5469, 6, 10),
+ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", 0x001b, 5246, 6, 10),
+ TLS_KRB5_WITH_DES_CBC_SHA("TLS_KRB5_WITH_DES_CBC_SHA", 0x001e, 2712, 6, MAX_VALUE),
+ TLS_KRB5_WITH_3DES_EDE_CBC_SHA("TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 0x001f, 2712, 6, MAX_VALUE),
+ TLS_KRB5_WITH_RC4_128_SHA("TLS_KRB5_WITH_RC4_128_SHA", 0x0020, 2712, 6, MAX_VALUE),
+ // TLS_KRB5_WITH_IDEA_CBC_SHA("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021, 2712, MAX_VALUE, MAX_VALUE),
+ TLS_KRB5_WITH_DES_CBC_MD5("TLS_KRB5_WITH_DES_CBC_MD5", 0x0022, 2712, 6, MAX_VALUE),
+ TLS_KRB5_WITH_3DES_EDE_CBC_MD5("TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 0x0023, 2712, 6, MAX_VALUE),
+ TLS_KRB5_WITH_RC4_128_MD5("TLS_KRB5_WITH_RC4_128_MD5", 0x0024, 2712, 6, MAX_VALUE),
+ // TLS_KRB5_WITH_IDEA_CBC_MD5("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025, 2712, MAX_VALUE, MAX_VALUE),
+ TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0x0026, 2712, 6, MAX_VALUE),
+ // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027, 2712, MAX_VALUE, MAX_VALUE),
+ TLS_KRB5_EXPORT_WITH_RC4_40_SHA("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 0x0028, 2712, 6, MAX_VALUE),
+ TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0029, 2712, 6, MAX_VALUE),
+ // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a, 2712, MAX_VALUE, MAX_VALUE),
+ TLS_KRB5_EXPORT_WITH_RC4_40_MD5("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0x002b, 2712, 6, MAX_VALUE),
+ // TLS_PSK_WITH_NULL_SHA("TLS_PSK_WITH_NULL_SHA", 0x002c, 4785, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_NULL_SHA("TLS_DHE_PSK_WITH_NULL_SHA", 0x002d, 4785, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_NULL_SHA("TLS_RSA_PSK_WITH_NULL_SHA", 0x002e, 4785, MAX_VALUE, MAX_VALUE),
+ TLS_RSA_WITH_AES_128_CBC_SHA("TLS_RSA_WITH_AES_128_CBC_SHA", 0x002f, 5246, 6, 10),
+ // TLS_DH_DSS_WITH_AES_128_CBC_SHA("TLS_DH_DSS_WITH_AES_128_CBC_SHA", 0x0030, 5246, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_AES_128_CBC_SHA("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 0x0032, 5246, 6, 10),
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA("TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 0x0033, 5246, 6, 10),
+ TLS_DH_anon_WITH_AES_128_CBC_SHA("TLS_DH_anon_WITH_AES_128_CBC_SHA", 0x0034, 5246, 6, 10),
+ TLS_RSA_WITH_AES_256_CBC_SHA("TLS_RSA_WITH_AES_256_CBC_SHA", 0x0035, 5246, 6, 10),
+ // TLS_DH_DSS_WITH_AES_256_CBC_SHA("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036, 5246, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_AES_256_CBC_SHA("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 0x0038, 5246, 6, 10),
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA("TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 0x0039, 5246, 6, 10),
+ TLS_DH_anon_WITH_AES_256_CBC_SHA("TLS_DH_anon_WITH_AES_256_CBC_SHA", 0x003a, 5246, 6, 10),
+ TLS_RSA_WITH_NULL_SHA256("TLS_RSA_WITH_NULL_SHA256", 0x003b, 5246, 7, 21),
+ TLS_RSA_WITH_AES_128_CBC_SHA256("TLS_RSA_WITH_AES_128_CBC_SHA256", 0x003c, 5246, 7, 21),
+ TLS_RSA_WITH_AES_256_CBC_SHA256("TLS_RSA_WITH_AES_256_CBC_SHA256", 0x003d, 5246, 7, 21),
+ // TLS_DH_DSS_WITH_AES_128_CBC_SHA256("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e, 5246, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_AES_128_CBC_SHA256("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0x0040, 5246, 7, 21),
+ // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0041, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0042, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0043, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0044, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0045, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 0x0046, 5932, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0x0067, 5246, 7, 21),
+ // TLS_DH_DSS_WITH_AES_256_CBC_SHA256("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068, 5246, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_AES_256_CBC_SHA256("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069, 5246, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0x006a, 5246, 7, 21),
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0x006b, 5246, 7, 21),
+ TLS_DH_anon_WITH_AES_128_CBC_SHA256("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x006c, 5246, 7, 21),
+ TLS_DH_anon_WITH_AES_256_CBC_SHA256("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x006d, 5246, 7, 21),
+ // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0084, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0085, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0086, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0087, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0088, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 0x0089, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_RC4_128_SHA("TLS_PSK_WITH_RC4_128_SHA", 0x008a, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_3DES_EDE_CBC_SHA("TLS_PSK_WITH_3DES_EDE_CBC_SHA", 0x008b, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_128_CBC_SHA("TLS_PSK_WITH_AES_128_CBC_SHA", 0x008c, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_256_CBC_SHA("TLS_PSK_WITH_AES_256_CBC_SHA", 0x008d, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_RC4_128_SHA("TLS_DHE_PSK_WITH_RC4_128_SHA", 0x008e, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 0x008f, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_128_CBC_SHA("TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 0x0090, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_256_CBC_SHA("TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 0x0091, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_RC4_128_SHA("TLS_RSA_PSK_WITH_RC4_128_SHA", 0x0092, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 0x0093, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_128_CBC_SHA("TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 0x0094, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_256_CBC_SHA("TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 0x0095, 4279, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_SEED_CBC_SHA("TLS_RSA_WITH_SEED_CBC_SHA", 0x0096, 4162, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_SEED_CBC_SHA("TLS_DH_DSS_WITH_SEED_CBC_SHA", 0x0097, 4162, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_SEED_CBC_SHA("TLS_DH_RSA_WITH_SEED_CBC_SHA", 0x0098, 4162, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_SEED_CBC_SHA("TLS_DHE_DSS_WITH_SEED_CBC_SHA", 0x0099, 4162, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_SEED_CBC_SHA("TLS_DHE_RSA_WITH_SEED_CBC_SHA", 0x009a, 4162, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_SEED_CBC_SHA("TLS_DH_anon_WITH_SEED_CBC_SHA", 0x009b, 4162, MAX_VALUE, MAX_VALUE),
+ TLS_RSA_WITH_AES_128_GCM_SHA256("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c, 5288, 8, 21),
+ TLS_RSA_WITH_AES_256_GCM_SHA384("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d, 5288, 8, 21),
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e, 5288, 8, 21),
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f, 5288, 8, 21),
+ // TLS_DH_RSA_WITH_AES_128_GCM_SHA256("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0, 5288, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_AES_256_GCM_SHA384("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1, 5288, MAX_VALUE, MAX_VALUE),
+ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2, 5288, 8, 21),
+ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3, 5288, 8, 21),
+ // TLS_DH_DSS_WITH_AES_128_GCM_SHA256("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4, 5288, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_AES_256_GCM_SHA384("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5, 5288, MAX_VALUE, MAX_VALUE),
+ TLS_DH_anon_WITH_AES_128_GCM_SHA256("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6, 5288, 8, 21),
+ TLS_DH_anon_WITH_AES_256_GCM_SHA384("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7, 5288, 8, 21),
+ // TLS_PSK_WITH_AES_128_GCM_SHA256("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_256_GCM_SHA384("TLS_PSK_WITH_AES_256_GCM_SHA384", 0x00a9, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_128_GCM_SHA256("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 0x00aa, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_256_GCM_SHA384("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 0x00ab, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_128_GCM_SHA256("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 0x00ac, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_256_GCM_SHA384("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 0x00ad, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_128_CBC_SHA256("TLS_PSK_WITH_AES_128_CBC_SHA256", 0x00ae, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_256_CBC_SHA384("TLS_PSK_WITH_AES_256_CBC_SHA384", 0x00af, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_NULL_SHA256("TLS_PSK_WITH_NULL_SHA256", 0x00b0, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_NULL_SHA384("TLS_PSK_WITH_NULL_SHA384", 0x00b1, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_128_CBC_SHA256("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 0x00b2, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_256_CBC_SHA384("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 0x00b3, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_NULL_SHA256("TLS_DHE_PSK_WITH_NULL_SHA256", 0x00b4, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_NULL_SHA384("TLS_DHE_PSK_WITH_NULL_SHA384", 0x00b5, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_128_CBC_SHA256("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 0x00b6, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_AES_256_CBC_SHA384("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 0x00b7, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_NULL_SHA256("TLS_RSA_PSK_WITH_NULL_SHA256", 0x00b8, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_NULL_SHA384("TLS_RSA_PSK_WITH_NULL_SHA384", 0x00b9, 5487, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00ba, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bb, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00bc, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bd, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00be, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 0x00bf, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c0, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c1, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c2, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c3, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c4, 5932, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 0x00c5, 5932, MAX_VALUE, MAX_VALUE),
+ TLS_EMPTY_RENEGOTIATION_INFO_SCSV("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", 0x00ff, 5746, 6, 14),
+ TLS_ECDH_ECDSA_WITH_NULL_SHA("TLS_ECDH_ECDSA_WITH_NULL_SHA", 0xc001, 4492, 7, 14),
+ TLS_ECDH_ECDSA_WITH_RC4_128_SHA("TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 0xc002, 4492, 7, 14),
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xc003, 4492, 7, 14),
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 0xc004, 4492, 7, 14),
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 0xc005, 4492, 7, 14),
+ TLS_ECDHE_ECDSA_WITH_NULL_SHA("TLS_ECDHE_ECDSA_WITH_NULL_SHA", 0xc006, 4492, 7, 14),
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0xc007, 4492, 7, 14),
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xc008, 4492, 7, 14),
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 0xc009, 4492, 7, 14),
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 0xc00a, 4492, 7, 14),
+ TLS_ECDH_RSA_WITH_NULL_SHA("TLS_ECDH_RSA_WITH_NULL_SHA", 0xc00b, 4492, 7, 14),
+ TLS_ECDH_RSA_WITH_RC4_128_SHA("TLS_ECDH_RSA_WITH_RC4_128_SHA", 0xc00c, 4492, 7, 14),
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 0xc00d, 4492, 7, 14),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 0xc00e, 4492, 7, 14),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 0xc00f, 4492, 7, 14),
+ TLS_ECDHE_RSA_WITH_NULL_SHA("TLS_ECDHE_RSA_WITH_NULL_SHA", 0xc010, 4492, 7, 14),
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA("TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0xc011, 4492, 7, 14),
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0xc012, 4492, 7, 14),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 0xc013, 4492, 7, 14),
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 0xc014, 4492, 7, 14),
+ TLS_ECDH_anon_WITH_NULL_SHA("TLS_ECDH_anon_WITH_NULL_SHA", 0xc015, 4492, 7, 14),
+ TLS_ECDH_anon_WITH_RC4_128_SHA("TLS_ECDH_anon_WITH_RC4_128_SHA", 0xc016, 4492, 7, 14),
+ TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 0xc017, 4492, 7, 14),
+ TLS_ECDH_anon_WITH_AES_128_CBC_SHA("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 0xc018, 4492, 7, 14),
+ TLS_ECDH_anon_WITH_AES_256_CBC_SHA("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 0xc019, 4492, 7, 14),
+ // TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 0xc01a, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 0xc01b, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 0xc01c, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_WITH_AES_128_CBC_SHA("TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 0xc01d, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 0xc01e, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 0xc01f, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_WITH_AES_256_CBC_SHA("TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 0xc020, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021, 5054, MAX_VALUE, MAX_VALUE),
+ // TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022, 5054, MAX_VALUE, MAX_VALUE),
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0xc023, 5289, 7, 21),
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0xc024, 5289, 7, 21),
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0xc025, 5289, 7, 21),
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0xc026, 5289, 7, 21),
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0xc027, 5289, 7, 21),
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0xc028, 5289, 7, 21),
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0xc029, 5289, 7, 21),
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0xc02a, 5289, 7, 21),
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b, 5289, 8, 21),
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c, 5289, 8, 21),
+ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d, 5289, 8, 21),
+ TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e, 5289, 8, 21),
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f, 5289, 8, 21),
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030, 5289, 8, 21),
+ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031, 5289, 8, 21),
+ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032, 5289, 8, 21),
+ // TLS_ECDHE_PSK_WITH_RC4_128_SHA("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 0xc036, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 0xc037, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 0xc038, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_NULL_SHA("TLS_ECDHE_PSK_WITH_NULL_SHA", 0xc039, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_NULL_SHA256("TLS_ECDHE_PSK_WITH_NULL_SHA256", 0xc03a, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_NULL_SHA384("TLS_ECDHE_PSK_WITH_NULL_SHA384", 0xc03b, 5489, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_ARIA_128_CBC_SHA256("TLS_RSA_WITH_ARIA_128_CBC_SHA256", 0xc03c, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_ARIA_256_CBC_SHA384("TLS_RSA_WITH_ARIA_256_CBC_SHA384", 0xc03d, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256("TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", 0xc03e, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384("TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", 0xc03f, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256("TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", 0xc040, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384("TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", 0xc041, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256("TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", 0xc042, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384("TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", 0xc043, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256("TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", 0xc044, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384("TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", 0xc045, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_ARIA_128_CBC_SHA256("TLS_DH_anon_WITH_ARIA_128_CBC_SHA256", 0xc046, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_ARIA_256_CBC_SHA384("TLS_DH_anon_WITH_ARIA_256_CBC_SHA384", 0xc047, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256("TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", 0xc048, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384("TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", 0xc049, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256("TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", 0xc04a, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384("TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", 0xc04b, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256("TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", 0xc04c, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384("TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", 0xc04d, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256("TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", 0xc04e, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384("TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", 0xc04f, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_ARIA_128_GCM_SHA256("TLS_RSA_WITH_ARIA_128_GCM_SHA256", 0xc050, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_ARIA_256_GCM_SHA384("TLS_RSA_WITH_ARIA_256_GCM_SHA384", 0xc051, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256("TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", 0xc052, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384("TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", 0xc053, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256("TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", 0xc054, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384("TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", 0xc055, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256("TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", 0xc056, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384("TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", 0xc057, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256("TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", 0xc058, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384("TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", 0xc059, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_ARIA_128_GCM_SHA256("TLS_DH_anon_WITH_ARIA_128_GCM_SHA256", 0xc05a, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_ARIA_256_GCM_SHA384("TLS_DH_anon_WITH_ARIA_256_GCM_SHA384", 0xc05b, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256("TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", 0xc05c, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384("TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", 0xc05d, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256("TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", 0xc05e, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384("TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", 0xc05f, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256("TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", 0xc060, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384("TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", 0xc061, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256("TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", 0xc062, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384("TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", 0xc063, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_ARIA_128_CBC_SHA256("TLS_PSK_WITH_ARIA_128_CBC_SHA256", 0xc064, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_ARIA_256_CBC_SHA384("TLS_PSK_WITH_ARIA_256_CBC_SHA384", 0xc065, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256("TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", 0xc066, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384("TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", 0xc067, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256("TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", 0xc068, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384("TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", 0xc069, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_ARIA_128_GCM_SHA256("TLS_PSK_WITH_ARIA_128_GCM_SHA256", 0xc06a, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_ARIA_256_GCM_SHA384("TLS_PSK_WITH_ARIA_256_GCM_SHA384", 0xc06b, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256("TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", 0xc06c, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384("TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", 0xc06d, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256("TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", 0xc06e, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384("TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", 0xc06f, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256("TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", 0xc070, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384("TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", 0xc071, 6209, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 0xc072, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 0xc073, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 0xc074, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 0xc075, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0xc076, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384("TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", 0xc077, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256("TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0xc078, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384("TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", 0xc079, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc07a, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc07b, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc07c, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc07d, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc07e, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc07f, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256("TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", 0xc080, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384("TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", 0xc081, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256("TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", 0xc082, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384("TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", 0xc083, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256("TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", 0xc084, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384("TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384", 0xc085, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc086, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc087, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc088, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc089, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc08a, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc08b, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256("TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0xc08c, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384("TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0xc08d, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256("TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0xc08e, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384("TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0xc08f, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256("TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0xc090, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384("TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0xc091, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256("TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0xc092, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384("TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0xc093, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256("TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0xc094, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384("TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0xc095, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256("TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0xc096, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384("TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0xc097, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256("TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0xc098, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384("TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0xc099, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256("TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0xc09a, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384("TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0xc09b, 6367, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_AES_128_CCM("TLS_RSA_WITH_AES_128_CCM", 0xc09c, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_AES_256_CCM("TLS_RSA_WITH_AES_256_CCM", 0xc09d, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_AES_128_CCM("TLS_DHE_RSA_WITH_AES_128_CCM", 0xc09e, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_AES_256_CCM("TLS_DHE_RSA_WITH_AES_256_CCM", 0xc09f, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_AES_128_CCM_8("TLS_RSA_WITH_AES_128_CCM_8", 0xc0a0, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_RSA_WITH_AES_256_CCM_8("TLS_RSA_WITH_AES_256_CCM_8", 0xc0a1, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_AES_128_CCM_8("TLS_DHE_RSA_WITH_AES_128_CCM_8", 0xc0a2, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_RSA_WITH_AES_256_CCM_8("TLS_DHE_RSA_WITH_AES_256_CCM_8", 0xc0a3, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_128_CCM("TLS_PSK_WITH_AES_128_CCM", 0xc0a4, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_256_CCM("TLS_PSK_WITH_AES_256_CCM", 0xc0a5, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_128_CCM("TLS_DHE_PSK_WITH_AES_128_CCM", 0xc0a6, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_DHE_PSK_WITH_AES_256_CCM("TLS_DHE_PSK_WITH_AES_256_CCM", 0xc0a7, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_128_CCM_8("TLS_PSK_WITH_AES_128_CCM_8", 0xc0a8, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_WITH_AES_256_CCM_8("TLS_PSK_WITH_AES_256_CCM_8", 0xc0a9, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_DHE_WITH_AES_128_CCM_8("TLS_PSK_DHE_WITH_AES_128_CCM_8", 0xc0aa, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_PSK_DHE_WITH_AES_256_CCM_8("TLS_PSK_DHE_WITH_AES_256_CCM_8", 0xc0ab, 6655, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_AES_128_CCM("TLS_ECDHE_ECDSA_WITH_AES_128_CCM", 0xc0ac, 7251, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_AES_256_CCM("TLS_ECDHE_ECDSA_WITH_AES_256_CCM", 0xc0ad, 7251, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", 0xc0ae, 7251, MAX_VALUE, MAX_VALUE),
+ // TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8("TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", 0xc0af, 7251, MAX_VALUE, MAX_VALUE),
+ ;
+
+ final String javaName;
+
+ /**
+ * @param javaName the name used by Java APIs for this cipher suite. Different than the IANA name
+ * for older cipher suites because the prefix is {@code SSL_} instead of {@code TLS_}.
+ * @param value the integer identifier for this cipher suite. (Documentation only.)
+ * @param rfc the RFC describing this cipher suite. (Documentation only.)
+ * @param sinceJavaVersion the first major Java release supporting this cipher suite.
+ * @param sinceAndroidVersion the first Android SDK version supporting this cipher suite.
+ */
+ private CipherSuite(
+ String javaName, int value, int rfc, int sinceJavaVersion, int sinceAndroidVersion) {
+ this.javaName = javaName;
+ }
+
+ public static CipherSuite forJavaName(String javaName) {
+ return javaName.startsWith("SSL_")
+ ? valueOf("TLS_" + javaName.substring(4))
+ : valueOf(javaName);
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/ConnectionSpec.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/ConnectionSpec.java
new file mode 100644
index 000000000..457e9c301
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/ConnectionSpec.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.net.ssl.SSLSocket;
+
+/**
+ * Specifies configuration for the socket connection that HTTP traffic travels through. For {@code
+ * https:} URLs, this includes the TLS version and cipher suites to use when negotiating a secure
+ * connection.
+ */
+public final class ConnectionSpec {
+
+ // This is a subset of the cipher suites supported in Chrome 37, current as of 2014-10-5.
+ // All of these suites are available on Android 5.0; earlier releases support a subset of
+ // these suites. https://github.com/square/okhttp/issues/330
+ private static final CipherSuite[] APPROVED_CIPHER_SUITES = new CipherSuite[] {
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+
+ // Note that the following cipher suites are all on HTTP/2's bad cipher suites list. We'll
+ // continue to include them until better suites are commonly available. For example, none
+ // of the better cipher suites listed above shipped with Android 4.4 or Java 7.
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ };
+
+ /** A modern TLS connection with extensions like SNI and ALPN available. */
+ public static final ConnectionSpec MODERN_TLS = new Builder(true)
+ .cipherSuites(APPROVED_CIPHER_SUITES)
+ .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
+ .supportsTlsExtensions(true)
+ .build();
+
+ /** A backwards-compatible fallback connection for interop with obsolete servers. */
+ public static final ConnectionSpec COMPATIBLE_TLS = new Builder(MODERN_TLS)
+ .tlsVersions(TlsVersion.TLS_1_0)
+ .supportsTlsExtensions(true)
+ .build();
+
+ /** Unencrypted, unauthenticated connections for {@code http:} URLs. */
+ public static final ConnectionSpec CLEARTEXT = new Builder(false).build();
+
+ final boolean tls;
+
+ /**
+ * Used if tls == true. The cipher suites to set on the SSLSocket. {@code null} means "use
+ * default set".
+ */
+ private final String[] cipherSuites;
+
+ /** Used if tls == true. The TLS protocol versions to use. */
+ private final String[] tlsVersions;
+
+ final boolean supportsTlsExtensions;
+
+ private ConnectionSpec(Builder builder) {
+ this.tls = builder.tls;
+ this.cipherSuites = builder.cipherSuites;
+ this.tlsVersions = builder.tlsVersions;
+ this.supportsTlsExtensions = builder.supportsTlsExtensions;
+ }
+
+ public boolean isTls() {
+ return tls;
+ }
+
+ /**
+ * Returns the cipher suites to use for a connection. This method can return {@code null} if the
+ * cipher suites enabled by default should be used.
+ */
+ public List<CipherSuite> cipherSuites() {
+ if (cipherSuites == null) {
+ return null;
+ }
+ CipherSuite[] result = new CipherSuite[cipherSuites.length];
+ for (int i = 0; i < cipherSuites.length; i++) {
+ result[i] = CipherSuite.forJavaName(cipherSuites[i]);
+ }
+ return Util.immutableList(result);
+ }
+
+ public List<TlsVersion> tlsVersions() {
+ TlsVersion[] result = new TlsVersion[tlsVersions.length];
+ for (int i = 0; i < tlsVersions.length; i++) {
+ result[i] = TlsVersion.forJavaName(tlsVersions[i]);
+ }
+ return Util.immutableList(result);
+ }
+
+ public boolean supportsTlsExtensions() {
+ return supportsTlsExtensions;
+ }
+
+ /** Applies this spec to {@code sslSocket}. */
+ public void apply(SSLSocket sslSocket, boolean isFallback) {
+ ConnectionSpec specToApply = supportedSpec(sslSocket, isFallback);
+
+ sslSocket.setEnabledProtocols(specToApply.tlsVersions);
+
+ String[] cipherSuitesToEnable = specToApply.cipherSuites;
+ // null means "use default set".
+ if (cipherSuitesToEnable != null) {
+ sslSocket.setEnabledCipherSuites(cipherSuitesToEnable);
+ }
+ }
+
+ /**
+ * Returns a copy of this that omits cipher suites and TLS versions not enabled by
+ * {@code sslSocket}.
+ */
+ private ConnectionSpec supportedSpec(SSLSocket sslSocket, boolean isFallback) {
+ String[] cipherSuitesToEnable = null;
+ if (cipherSuites != null) {
+ String[] cipherSuitesToSelectFrom = sslSocket.getEnabledCipherSuites();
+ cipherSuitesToEnable =
+ Util.intersect(String.class, cipherSuites, cipherSuitesToSelectFrom);
+ }
+
+ if (isFallback) {
+ // In accordance with https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00
+ // the SCSV cipher is added to signal that a protocol fallback has taken place.
+ final String fallbackScsv = "TLS_FALLBACK_SCSV";
+ boolean socketSupportsFallbackScsv =
+ Arrays.asList(sslSocket.getSupportedCipherSuites()).contains(fallbackScsv);
+
+ if (socketSupportsFallbackScsv) {
+ // Add the SCSV cipher to the set of enabled cipher suites iff it is supported.
+ String[] oldEnabledCipherSuites = cipherSuitesToEnable != null
+ ? cipherSuitesToEnable
+ : sslSocket.getEnabledCipherSuites();
+ String[] newEnabledCipherSuites = new String[oldEnabledCipherSuites.length + 1];
+ System.arraycopy(oldEnabledCipherSuites, 0,
+ newEnabledCipherSuites, 0, oldEnabledCipherSuites.length);
+ newEnabledCipherSuites[newEnabledCipherSuites.length - 1] = fallbackScsv;
+ cipherSuitesToEnable = newEnabledCipherSuites;
+ }
+ }
+
+ String[] protocolsToSelectFrom = sslSocket.getEnabledProtocols();
+ String[] protocolsToEnable = Util.intersect(String.class, tlsVersions, protocolsToSelectFrom);
+ return new Builder(this)
+ .cipherSuites(cipherSuitesToEnable)
+ .tlsVersions(protocolsToEnable)
+ .build();
+ }
+
+ /**
+ * Returns {@code true} if the socket, as currently configured, supports this ConnectionSpec.
+ * In order for a socket to be compatible the enabled cipher suites and protocols must intersect.
+ *
+ * <p>For cipher suites, at least one of the {@link #cipherSuites() required cipher suites} must
+ * match the socket's enabled cipher suites. If there are no required cipher suites the socket
+ * must have at least one cipher suite enabled.
+ *
+ * <p>For protocols, at least one of the {@link #tlsVersions() required protocols} must match the
+ * socket's enabled protocols.
+ */
+ public boolean isCompatible(SSLSocket socket) {
+ if (!tls) {
+ return false;
+ }
+
+ String[] enabledProtocols = socket.getEnabledProtocols();
+ boolean requiredProtocolsEnabled = nonEmptyIntersection(tlsVersions, enabledProtocols);
+ if (!requiredProtocolsEnabled) {
+ return false;
+ }
+
+ boolean requiredCiphersEnabled;
+ if (cipherSuites == null) {
+ requiredCiphersEnabled = socket.getEnabledCipherSuites().length > 0;
+ } else {
+ String[] enabledCipherSuites = socket.getEnabledCipherSuites();
+ requiredCiphersEnabled = nonEmptyIntersection(cipherSuites, enabledCipherSuites);
+ }
+ return requiredCiphersEnabled;
+ }
+
+ /**
+ * An N*M intersection that terminates if any intersection is found. The sizes of both
+ * arguments are assumed to be so small, and the likelihood of an intersection so great, that it
+ * is not worth the CPU cost of sorting or the memory cost of hashing.
+ */
+ private static boolean nonEmptyIntersection(String[] a, String[] b) {
+ if (a == null || b == null || a.length == 0 || b.length == 0) {
+ return false;
+ }
+ for (String toFind : a) {
+ if (contains(b, toFind)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static <T> boolean contains(T[] array, T value) {
+ for (T arrayValue : array) {
+ if (Util.equal(value, arrayValue)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override public boolean equals(Object other) {
+ if (!(other instanceof ConnectionSpec)) return false;
+ if (other == this) return true;
+
+ ConnectionSpec that = (ConnectionSpec) other;
+ if (this.tls != that.tls) return false;
+
+ if (tls) {
+ if (!Arrays.equals(this.cipherSuites, that.cipherSuites)) return false;
+ if (!Arrays.equals(this.tlsVersions, that.tlsVersions)) return false;
+ if (this.supportsTlsExtensions != that.supportsTlsExtensions) return false;
+ }
+
+ return true;
+ }
+
+ @Override public int hashCode() {
+ int result = 17;
+ if (tls) {
+ result = 31 * result + Arrays.hashCode(cipherSuites);
+ result = 31 * result + Arrays.hashCode(tlsVersions);
+ result = 31 * result + (supportsTlsExtensions ? 0 : 1);
+ }
+ return result;
+ }
+
+ @Override public String toString() {
+ if (tls) {
+ List<CipherSuite> cipherSuites = cipherSuites();
+ String cipherSuitesString = cipherSuites == null ? "[use default]" : cipherSuites.toString();
+ return "ConnectionSpec(cipherSuites=" + cipherSuitesString
+ + ", tlsVersions=" + tlsVersions()
+ + ", supportsTlsExtensions=" + supportsTlsExtensions
+ + ")";
+ } else {
+ return "ConnectionSpec()";
+ }
+ }
+
+ public static final class Builder {
+ private boolean tls;
+ private String[] cipherSuites;
+ private String[] tlsVersions;
+ private boolean supportsTlsExtensions;
+
+ public Builder(boolean tls) {
+ this.tls = tls;
+ }
+
+ public Builder(ConnectionSpec connectionSpec) {
+ this.tls = connectionSpec.tls;
+ this.cipherSuites = connectionSpec.cipherSuites;
+ this.tlsVersions = connectionSpec.tlsVersions;
+ this.supportsTlsExtensions = connectionSpec.supportsTlsExtensions;
+ }
+
+ public Builder cipherSuites(CipherSuite... cipherSuites) {
+ if (!tls) throw new IllegalStateException("no cipher suites for cleartext connections");
+
+ // Convert enums to the string names Java wants. This makes a defensive copy!
+ String[] strings = new String[cipherSuites.length];
+ for (int i = 0; i < cipherSuites.length; i++) {
+ strings[i] = cipherSuites[i].javaName;
+ }
+ this.cipherSuites = strings;
+ return this;
+ }
+
+ public Builder cipherSuites(String... cipherSuites) {
+ if (!tls) throw new IllegalStateException("no cipher suites for cleartext connections");
+
+ if (cipherSuites == null) {
+ this.cipherSuites = null;
+ } else {
+ // This makes a defensive copy!
+ this.cipherSuites = cipherSuites.clone();
+ }
+
+ return this;
+ }
+
+ public Builder tlsVersions(TlsVersion... tlsVersions) {
+ if (!tls) throw new IllegalStateException("no TLS versions for cleartext connections");
+ if (tlsVersions.length == 0) {
+ throw new IllegalArgumentException("At least one TlsVersion is required");
+ }
+
+ // Convert enums to the string names Java wants. This makes a defensive copy!
+ String[] strings = new String[tlsVersions.length];
+ for (int i = 0; i < tlsVersions.length; i++) {
+ strings[i] = tlsVersions[i].javaName;
+ }
+ this.tlsVersions = strings;
+ return this;
+ }
+
+ public Builder tlsVersions(String... tlsVersions) {
+ if (!tls) throw new IllegalStateException("no TLS versions for cleartext connections");
+
+ if (tlsVersions == null) {
+ this.tlsVersions = null;
+ } else {
+ // This makes a defensive copy!
+ this.tlsVersions = tlsVersions.clone();
+ }
+
+ return this;
+ }
+
+ public Builder supportsTlsExtensions(boolean supportsTlsExtensions) {
+ if (!tls) throw new IllegalStateException("no TLS extensions for cleartext connections");
+ this.supportsTlsExtensions = supportsTlsExtensions;
+ return this;
+ }
+
+ public ConnectionSpec build() {
+ return new ConnectionSpec(this);
+ }
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/OptionalMethod.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/OptionalMethod.java
new file mode 100644
index 000000000..cb9357fb1
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/OptionalMethod.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Duck-typing for methods: Represents a method that may or may not be present on an object.
+ *
+ * @param <T> the type of the object the method might be on, typically an interface or base class
+ */
+public class OptionalMethod<T> {
+
+ /** The return type of the method. null means "don't care". */
+ private final Class<?> returnType;
+
+ private final String methodName;
+
+ @SuppressWarnings("rawtypes")
+ private final Class[] methodParams;
+
+ /**
+ * Creates an optional method.
+ *
+ * @param returnType the return type to required, null if it does not matter
+ * @param methodName the name of the method
+ * @param methodParams the method parameter types
+ */
+ @SuppressWarnings("rawtypes")
+ public OptionalMethod(Class<?> returnType, String methodName, Class... methodParams) {
+ this.returnType = returnType;
+ this.methodName = methodName;
+ this.methodParams = methodParams;
+ }
+
+ /**
+ * Returns true if the method exists on the supplied {@code target}.
+ */
+ public boolean isSupported(T target) {
+ return getMethod(target.getClass()) != null;
+ }
+
+ /**
+ * Invokes the method on {@code target} with {@code args}. If the method does not exist or is not
+ * public then {@code null} is returned. See also
+ * {@link #invokeOptionalWithoutCheckedException(Object, Object...)}.
+ *
+ * @throws IllegalArgumentException if the arguments are invalid
+ * @throws InvocationTargetException if the invocation throws an exception
+ */
+ public Object invokeOptional(T target, Object... args) throws InvocationTargetException {
+ Method m = getMethod(target.getClass());
+ if (m == null) {
+ return null;
+ }
+ try {
+ return m.invoke(target, args);
+ } catch (IllegalAccessException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Invokes the method on {@code target}. If the method does not exist or is not
+ * public then {@code null} is returned. Any RuntimeException thrown by the method is thrown,
+ * checked exceptions are wrapped in an {@link AssertionError}.
+ *
+ * @throws IllegalArgumentException if the arguments are invalid
+ */
+ public Object invokeOptionalWithoutCheckedException(T target, Object... args) {
+ try {
+ return invokeOptional(target, args);
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ if (targetException instanceof RuntimeException) {
+ throw (RuntimeException) targetException;
+ }
+ AssertionError error = new AssertionError("Unexpected exception");
+ error.initCause(targetException);
+ throw error;
+ }
+ }
+
+ /**
+ * Invokes the method on {@code target} with {@code args}. Throws an error if the method is not
+ * supported. See also {@link #invokeWithoutCheckedException(Object, Object...)}.
+ *
+ * @throws IllegalArgumentException if the arguments are invalid
+ * @throws InvocationTargetException if the invocation throws an exception
+ */
+ public Object invoke(T target, Object... args) throws InvocationTargetException {
+ Method m = getMethod(target.getClass());
+ if (m == null) {
+ throw new AssertionError("Method " + methodName + " not supported for object " + target);
+ }
+ try {
+ return m.invoke(target, args);
+ } catch (IllegalAccessException e) {
+ // Method should be public: we checked.
+ AssertionError error = new AssertionError("Unexpectedly could not call: " + m);
+ error.initCause(e);
+ throw error;
+ }
+ }
+
+ /**
+ * Invokes the method on {@code target}. Throws an error if the method is not supported. Any
+ * RuntimeException thrown by the method is thrown, checked exceptions are wrapped in
+ * an {@link AssertionError}.
+ *
+ * @throws IllegalArgumentException if the arguments are invalid
+ */
+ public Object invokeWithoutCheckedException(T target, Object... args) {
+ try {
+ return invoke(target, args);
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ if (targetException instanceof RuntimeException) {
+ throw (RuntimeException) targetException;
+ }
+ AssertionError error = new AssertionError("Unexpected exception");
+ error.initCause(targetException);
+ throw error;
+ }
+ }
+
+ /**
+ * Perform a lookup for the method. No caching.
+ * In order to return a method the method name and arguments must match those specified when
+ * the {@link OptionalMethod} was created. If the return type is specified (i.e. non-null) it
+ * must also be compatible. The method must also be public.
+ */
+ private Method getMethod(Class<?> clazz) {
+ Method method = null;
+ if (methodName != null) {
+ method = getPublicMethod(clazz, methodName, methodParams);
+ if (method != null
+ && returnType != null
+ && !returnType.isAssignableFrom(method.getReturnType())) {
+
+ // If the return type is non-null it must be compatible.
+ method = null;
+ }
+ }
+ return method;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static Method getPublicMethod(Class<?> clazz, String methodName, Class[] parameterTypes) {
+ Method method = null;
+ try {
+ method = clazz.getMethod(methodName, parameterTypes);
+ if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
+ method = null;
+ }
+ } catch (NoSuchMethodException e) {
+ // None.
+ }
+ return method;
+ }
+}
+
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java
new file mode 100644
index 000000000..5561c654f
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2012 Square, Inc.
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.net.ssl.SSLSocket;
+import okio.Buffer;
+
+/**
+ * Access to platform-specific features.
+ *
+ * <h3>Server name indication (SNI)</h3>
+ * Supported on Android 2.3+.
+ *
+ * <h3>Session Tickets</h3>
+ * Supported on Android 2.3+.
+ *
+ * <h3>Android Traffic Stats (Socket Tagging)</h3>
+ * Supported on Android 4.0+.
+ *
+ * <h3>ALPN (Application Layer Protocol Negotiation)</h3>
+ * Supported on Android 5.0+. The APIs were present in Android 4.4, but that implementation was
+ * unstable.
+ *
+ * Supported on OpenJDK 7 and 8 (via the JettyALPN-boot library).
+ */
+public class Platform {
+ public static final Logger logger = Logger.getLogger(Platform.class.getName());
+
+ private static final Platform PLATFORM = findPlatform();
+
+ public static Platform get() {
+ return PLATFORM;
+ }
+
+ /** Prefix used on custom headers. */
+ public String getPrefix() {
+ return "OkHttp";
+ }
+
+ public void logW(String warning) {
+ System.out.println(warning);
+ }
+
+ public void tagSocket(Socket socket) throws SocketException {
+ }
+
+ public void untagSocket(Socket socket) throws SocketException {
+ }
+
+ /**
+ * Configure TLS extensions on {@code sslSocket} for {@code route}.
+ *
+ * @param hostname non-null for client-side handshakes; null for
+ * server-side handshakes.
+ */
+ public void configureTlsExtensions(SSLSocket sslSocket, String hostname,
+ List<Protocol> protocols) {
+ }
+
+ /**
+ * Called after the TLS handshake to release resources allocated by {@link
+ * #configureTlsExtensions}.
+ */
+ public void afterHandshake(SSLSocket sslSocket) {
+ }
+
+ /** Returns the negotiated protocol, or null if no protocol was negotiated. */
+ public String getSelectedProtocol(SSLSocket socket) {
+ return null;
+ }
+
+ public void connectSocket(Socket socket, InetSocketAddress address,
+ int connectTimeout) throws IOException {
+ socket.connect(address, connectTimeout);
+ }
+
+ /** Attempt to match the host runtime to a capable Platform implementation. */
+ private static Platform findPlatform() {
+ // Attempt to find Android 2.3+ APIs.
+ try {
+ try {
+ Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");
+ } catch (ClassNotFoundException e) {
+ // Older platform before being unbundled.
+ Class.forName("org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl");
+ }
+
+ OptionalMethod<Socket> setUseSessionTickets
+ = new OptionalMethod<Socket>(null, "setUseSessionTickets", boolean.class);
+ OptionalMethod<Socket> setHostname
+ = new OptionalMethod<Socket>(null, "setHostname", String.class);
+ Method trafficStatsTagSocket = null;
+ Method trafficStatsUntagSocket = null;
+ OptionalMethod<Socket> getAlpnSelectedProtocol = null;
+ OptionalMethod<Socket> setAlpnProtocols = null;
+
+ // Attempt to find Android 4.0+ APIs.
+ try {
+ Class<?> trafficStats = Class.forName("android.net.TrafficStats");
+ trafficStatsTagSocket = trafficStats.getMethod("tagSocket", Socket.class);
+ trafficStatsUntagSocket = trafficStats.getMethod("untagSocket", Socket.class);
+
+ // Attempt to find Android 5.0+ APIs.
+ try {
+ Class.forName("android.net.Network"); // Arbitrary class added in Android 5.0.
+ getAlpnSelectedProtocol =
+ new OptionalMethod<Socket>(byte[].class, "getAlpnSelectedProtocol");
+ setAlpnProtocols = new OptionalMethod<Socket>(null, "setAlpnProtocols", byte[].class);
+ } catch (ClassNotFoundException ignored) {
+ }
+ } catch (ClassNotFoundException ignored) {
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ return new Android(setUseSessionTickets, setHostname, trafficStatsTagSocket,
+ trafficStatsUntagSocket, getAlpnSelectedProtocol, setAlpnProtocols);
+ } catch (ClassNotFoundException ignored) {
+ // This isn't an Android runtime.
+ }
+
+ // Find Jetty's ALPN extension for OpenJDK.
+ try {
+ String negoClassName = "org.eclipse.jetty.alpn.ALPN";
+ Class<?> negoClass = Class.forName(negoClassName);
+ Class<?> providerClass = Class.forName(negoClassName + "$Provider");
+ Class<?> clientProviderClass = Class.forName(negoClassName + "$ClientProvider");
+ Class<?> serverProviderClass = Class.forName(negoClassName + "$ServerProvider");
+ Method putMethod = negoClass.getMethod("put", SSLSocket.class, providerClass);
+ Method getMethod = negoClass.getMethod("get", SSLSocket.class);
+ Method removeMethod = negoClass.getMethod("remove", SSLSocket.class);
+ return new JdkWithJettyBootPlatform(
+ putMethod, getMethod, removeMethod, clientProviderClass, serverProviderClass);
+ } catch (ClassNotFoundException ignored) {
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ return new Platform();
+ }
+
+ /** Android 2.3 or better. */
+ private static class Android extends Platform {
+ private final OptionalMethod<Socket> setUseSessionTickets;
+ private final OptionalMethod<Socket> setHostname;
+
+ // Non-null on Android 4.0+.
+ private final Method trafficStatsTagSocket;
+ private final Method trafficStatsUntagSocket;
+
+ // Non-null on Android 5.0+.
+ private final OptionalMethod<Socket> getAlpnSelectedProtocol;
+ private final OptionalMethod<Socket> setAlpnProtocols;
+
+ public Android(OptionalMethod<Socket> setUseSessionTickets, OptionalMethod<Socket> setHostname,
+ Method trafficStatsTagSocket, Method trafficStatsUntagSocket,
+ OptionalMethod<Socket> getAlpnSelectedProtocol, OptionalMethod<Socket> setAlpnProtocols) {
+ this.setUseSessionTickets = setUseSessionTickets;
+ this.setHostname = setHostname;
+ this.trafficStatsTagSocket = trafficStatsTagSocket;
+ this.trafficStatsUntagSocket = trafficStatsUntagSocket;
+ this.getAlpnSelectedProtocol = getAlpnSelectedProtocol;
+ this.setAlpnProtocols = setAlpnProtocols;
+ }
+
+ @Override public void connectSocket(Socket socket, InetSocketAddress address,
+ int connectTimeout) throws IOException {
+ try {
+ socket.connect(address, connectTimeout);
+ } catch (SecurityException se) {
+ // Before android 4.3, socket.connect could throw a SecurityException
+ // if opening a socket resulted in an EACCES error.
+ IOException ioException = new IOException("Exception in connect");
+ ioException.initCause(se);
+ throw ioException;
+ }
+ }
+
+ @Override public void configureTlsExtensions(
+ SSLSocket sslSocket, String hostname, List<Protocol> protocols) {
+ // Enable SNI and session tickets.
+ if (hostname != null) {
+ setUseSessionTickets.invokeOptionalWithoutCheckedException(sslSocket, true);
+ setHostname.invokeOptionalWithoutCheckedException(sslSocket, hostname);
+ }
+
+ // Enable ALPN.
+ if (setAlpnProtocols != null && setAlpnProtocols.isSupported(sslSocket)) {
+ Object[] parameters = { concatLengthPrefixed(protocols) };
+ setAlpnProtocols.invokeWithoutCheckedException(sslSocket, parameters);
+ }
+ }
+
+ @Override public String getSelectedProtocol(SSLSocket socket) {
+ if (getAlpnSelectedProtocol == null) return null;
+ if (!getAlpnSelectedProtocol.isSupported(socket)) return null;
+
+ byte[] alpnResult = (byte[]) getAlpnSelectedProtocol.invokeWithoutCheckedException(socket);
+ return alpnResult != null ? new String(alpnResult, Util.UTF_8) : null;
+ }
+
+ @Override public void tagSocket(Socket socket) throws SocketException {
+ if (trafficStatsTagSocket == null) return;
+
+ try {
+ trafficStatsTagSocket.invoke(null, socket);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+ @Override public void untagSocket(Socket socket) throws SocketException {
+ if (trafficStatsUntagSocket == null) return;
+
+ try {
+ trafficStatsUntagSocket.invoke(null, socket);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+ }
+
+ /**
+ * OpenJDK 7+ with {@code org.mortbay.jetty.alpn/alpn-boot} in the boot class path.
+ */
+ private static class JdkWithJettyBootPlatform extends Platform {
+ private final Method putMethod;
+ private final Method getMethod;
+ private final Method removeMethod;
+ private final Class<?> clientProviderClass;
+ private final Class<?> serverProviderClass;
+
+ public JdkWithJettyBootPlatform(Method putMethod, Method getMethod, Method removeMethod,
+ Class<?> clientProviderClass, Class<?> serverProviderClass) {
+ this.putMethod = putMethod;
+ this.getMethod = getMethod;
+ this.removeMethod = removeMethod;
+ this.clientProviderClass = clientProviderClass;
+ this.serverProviderClass = serverProviderClass;
+ }
+
+ @Override public void configureTlsExtensions(
+ SSLSocket sslSocket, String hostname, List<Protocol> protocols) {
+ List<String> names = new ArrayList<String>(protocols.size());
+ for (int i = 0, size = protocols.size(); i < size; i++) {
+ Protocol protocol = protocols.get(i);
+ if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN.
+ names.add(protocol.toString());
+ }
+ try {
+ Object provider = Proxy.newProxyInstance(Platform.class.getClassLoader(),
+ new Class<?>[] { clientProviderClass, serverProviderClass }, new JettyNegoProvider(names));
+ putMethod.invoke(null, sslSocket, provider);
+ } catch (InvocationTargetException e) {
+ throw new AssertionError(e);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override public void afterHandshake(SSLSocket sslSocket) {
+ try {
+ removeMethod.invoke(null, sslSocket);
+ } catch (IllegalAccessException ignored) {
+ throw new AssertionError();
+ } catch (InvocationTargetException ignored) {
+ }
+ }
+
+ @Override public String getSelectedProtocol(SSLSocket socket) {
+ try {
+ JettyNegoProvider provider =
+ (JettyNegoProvider) Proxy.getInvocationHandler(getMethod.invoke(null, socket));
+ if (!provider.unsupported && provider.selected == null) {
+ logger.log(Level.INFO, "ALPN callback dropped: SPDY and HTTP/2 are disabled. "
+ + "Is alpn-boot on the boot class path?");
+ return null;
+ }
+ return provider.unsupported ? null : provider.selected;
+ } catch (InvocationTargetException e) {
+ throw new AssertionError();
+ } catch (IllegalAccessException e) {
+ throw new AssertionError();
+ }
+ }
+ }
+
+ /**
+ * Handle the methods of ALPN's ClientProvider and ServerProvider
+ * without a compile-time dependency on those interfaces.
+ */
+ private static class JettyNegoProvider implements InvocationHandler {
+ /** This peer's supported protocols. */
+ private final List<String> protocols;
+ /** Set when remote peer notifies ALPN is unsupported. */
+ private boolean unsupported;
+ /** The protocol the server selected. */
+ private String selected;
+
+ public JettyNegoProvider(List<String> protocols) {
+ this.protocols = protocols;
+ }
+
+ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ String methodName = method.getName();
+ Class<?> returnType = method.getReturnType();
+ if (args == null) {
+ args = Util.EMPTY_STRING_ARRAY;
+ }
+ if (methodName.equals("supports") && boolean.class == returnType) {
+ return true; // ALPN is supported.
+ } else if (methodName.equals("unsupported") && void.class == returnType) {
+ this.unsupported = true; // Peer doesn't support ALPN.
+ return null;
+ } else if (methodName.equals("protocols") && args.length == 0) {
+ return protocols; // Client advertises these protocols.
+ } else if ((methodName.equals("selectProtocol") || methodName.equals("select"))
+ && String.class == returnType && args.length == 1 && args[0] instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<String> peerProtocols = (List) args[0];
+ // Pick the first known protocol the peer advertises.
+ for (int i = 0, size = peerProtocols.size(); i < size; i++) {
+ if (protocols.contains(peerProtocols.get(i))) {
+ return selected = peerProtocols.get(i);
+ }
+ }
+ return selected = protocols.get(0); // On no intersection, try peer's first protocol.
+ } else if ((methodName.equals("protocolSelected") || methodName.equals("selected"))
+ && args.length == 1) {
+ this.selected = (String) args[0]; // Server selected this protocol.
+ return null;
+ } else {
+ return method.invoke(this, args);
+ }
+ }
+ }
+
+ /**
+ * Returns the concatenation of 8-bit, length prefixed protocol names.
+ * http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4
+ */
+ public static byte[] concatLengthPrefixed(List<Protocol> protocols) {
+ Buffer result = new Buffer();
+ for (int i = 0, size = protocols.size(); i < size; i++) {
+ Protocol protocol = protocols.get(i);
+ if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN.
+ result.writeByte(protocol.toString().length());
+ result.writeUtf8(protocol.toString());
+ }
+ return result.readByteArray();
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Protocol.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Protocol.java
new file mode 100644
index 000000000..0c9244607
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Protocol.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import java.io.IOException;
+
+/**
+ * Protocols that OkHttp implements for <a
+ * href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a>
+ * selection.
+ *
+ * <h3>Protocol vs Scheme</h3>
+ * Despite its name, {@link java.net.URL#getProtocol()} returns the
+ * {@linkplain java.net.URI#getScheme() scheme} (http, https, etc.) of the URL, not
+ * the protocol (http/1.1, spdy/3.1, etc.). OkHttp uses the word <i>protocol</i>
+ * to identify how HTTP messages are framed.
+ */
+public enum Protocol {
+ /**
+ * An obsolete plaintext framing that does not use persistent sockets by
+ * default.
+ */
+ HTTP_1_0("http/1.0"),
+
+ /**
+ * A plaintext framing that includes persistent connections.
+ *
+ * <p>This version of OkHttp implements <a
+ * href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>, and tracks
+ * revisions to that spec.
+ */
+ HTTP_1_1("http/1.1"),
+
+ /**
+ * Chromium's binary-framed protocol that includes header compression,
+ * multiplexing multiple requests on the same socket, and server-push.
+ * HTTP/1.1 semantics are layered on SPDY/3.
+ *
+ * <p>This version of OkHttp implements SPDY 3 <a
+ * href="http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">draft
+ * 3.1</a>. Future releases of OkHttp may use this identifier for a newer draft
+ * of the SPDY spec.
+ */
+ SPDY_3("spdy/3.1"),
+
+ /**
+ * The IETF's binary-framed protocol that includes header compression,
+ * multiplexing multiple requests on the same socket, and server-push.
+ * HTTP/1.1 semantics are layered on HTTP/2.
+ *
+ * <p>HTTP/2 requires deployments of HTTP/2 that use TLS 1.2 support
+ * {@linkplain CipherSuite#TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
+ * , present in Java 8+ and Android 5+. Servers that enforce this may send an
+ * exception message including the string {@code INADEQUATE_SECURITY}.
+ */
+ HTTP_2("h2");
+
+ private final String protocol;
+
+ Protocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ /**
+ * Returns the protocol identified by {@code protocol}.
+ * @throws IOException if {@code protocol} is unknown.
+ */
+ public static Protocol get(String protocol) throws IOException {
+ // Unroll the loop over values() to save an allocation.
+ if (protocol.equals(HTTP_1_0.protocol)) return HTTP_1_0;
+ if (protocol.equals(HTTP_1_1.protocol)) return HTTP_1_1;
+ if (protocol.equals(HTTP_2.protocol)) return HTTP_2;
+ if (protocol.equals(SPDY_3.protocol)) return SPDY_3;
+ throw new IOException("Unexpected protocol: " + protocol);
+ }
+
+ /**
+ * Returns the string used to identify this protocol for ALPN, like
+ * "http/1.1", "spdy/3.1" or "h2".
+ */
+ @Override public String toString() {
+ return protocol;
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/TlsVersion.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/TlsVersion.java
new file mode 100644
index 000000000..548f4acbc
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/TlsVersion.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import javax.net.ssl.SSLSocket;
+
+/**
+ * Versions of TLS that can be offered when negotiating a secure socket. See
+ * {@link SSLSocket#setEnabledProtocols}.
+ */
+public enum TlsVersion {
+ TLS_1_2("TLSv1.2"), // 2008.
+ TLS_1_1("TLSv1.1"), // 2006.
+ TLS_1_0("TLSv1"), // 1999.
+ SSL_3_0("SSLv3"), // 1996.
+ ;
+
+ final String javaName;
+
+ private TlsVersion(String javaName) {
+ this.javaName = javaName;
+ }
+
+ public static TlsVersion forJavaName(String javaName) {
+ if ("TLSv1.2".equals(javaName)) {
+ return TLS_1_2;
+ } else if ("TLSv1.1".equals(javaName)) {
+ return TLS_1_1;
+ } else if ("TLSv1".equals(javaName)) {
+ return TLS_1_0;
+ } else if ("SSLv3".equals(javaName)) {
+ return SSL_3_0;
+ }
+ throw new IllegalArgumentException("Unexpected TLS version: " + javaName);
+ }
+
+ public String javaName() {
+ return javaName;
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Util.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Util.java
new file mode 100644
index 000000000..7501c441d
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Util.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Array;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import okio.Buffer;
+import okio.ByteString;
+import okio.Source;
+
+/** Junk drawer of utility methods. */
+public final class Util {
+ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ /** A cheap and type-safe constant for the UTF-8 Charset. */
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+ private Util() {
+ }
+
+ public static void checkOffsetAndCount(long arrayLength, long offset, long count) {
+ if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ /** Returns true if two possibly-null objects are equal. */
+ public static boolean equal(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
+ }
+
+ /**
+ * Closes {@code closeable}, ignoring any checked exceptions. Does nothing
+ * if {@code closeable} is null.
+ */
+ public static void closeQuietly(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
+ /**
+ * Closes {@code socket}, ignoring any checked exceptions. Does nothing if
+ * {@code socket} is null.
+ */
+ public static void closeQuietly(Socket socket) {
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (AssertionError e) {
+ if (!isAndroidGetsocknameError(e)) throw e;
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
+ /**
+ * Closes {@code serverSocket}, ignoring any checked exceptions. Does nothing if
+ * {@code serverSocket} is null.
+ */
+ public static void closeQuietly(ServerSocket serverSocket) {
+ if (serverSocket != null) {
+ try {
+ serverSocket.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
+ /**
+ * Closes {@code a} and {@code b}. If either close fails, this completes
+ * the other close and rethrows the first encountered exception.
+ */
+ public static void closeAll(Closeable a, Closeable b) throws IOException {
+ Throwable thrown = null;
+ try {
+ a.close();
+ } catch (Throwable e) {
+ thrown = e;
+ }
+ try {
+ b.close();
+ } catch (Throwable e) {
+ if (thrown == null) thrown = e;
+ }
+ if (thrown == null) return;
+ if (thrown instanceof IOException) throw (IOException) thrown;
+ if (thrown instanceof RuntimeException) throw (RuntimeException) thrown;
+ if (thrown instanceof Error) throw (Error) thrown;
+ throw new AssertionError(thrown);
+ }
+
+ /**
+ * Attempts to exhaust {@code source}, returning true if successful. This is useful when reading
+ * a complete source is helpful, such as when doing so completes a cache body or frees a socket
+ * connection for reuse.
+ */
+ public static boolean discard(Source source, int timeout, TimeUnit timeUnit) {
+ try {
+ return skipAll(source, timeout, timeUnit);
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Reads until {@code in} is exhausted or the deadline has been reached. This is careful to not
+ * extend the deadline if one exists already.
+ */
+ public static boolean skipAll(Source source, int duration, TimeUnit timeUnit) throws IOException {
+ long now = System.nanoTime();
+ long originalDuration = source.timeout().hasDeadline()
+ ? source.timeout().deadlineNanoTime() - now
+ : Long.MAX_VALUE;
+ source.timeout().deadlineNanoTime(now + Math.min(originalDuration, timeUnit.toNanos(duration)));
+ try {
+ Buffer skipBuffer = new Buffer();
+ while (source.read(skipBuffer, 2048) != -1) {
+ skipBuffer.clear();
+ }
+ return true; // Success! The source has been exhausted.
+ } catch (InterruptedIOException e) {
+ return false; // We ran out of time before exhausting the source.
+ } finally {
+ if (originalDuration == Long.MAX_VALUE) {
+ source.timeout().clearDeadline();
+ } else {
+ source.timeout().deadlineNanoTime(now + originalDuration);
+ }
+ }
+ }
+
+ /** Returns a 32 character string containing an MD5 hash of {@code s}. */
+ public static String md5Hex(String s) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+ byte[] md5bytes = messageDigest.digest(s.getBytes("UTF-8"));
+ return ByteString.of(md5bytes).hex();
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Returns a Base 64-encoded string containing a SHA-1 hash of {@code s}. */
+ public static String shaBase64(String s) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+ byte[] sha1Bytes = messageDigest.digest(s.getBytes("UTF-8"));
+ return ByteString.of(sha1Bytes).base64();
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Returns a SHA-1 hash of {@code s}. */
+ public static ByteString sha1(ByteString s) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+ byte[] sha1Bytes = messageDigest.digest(s.toByteArray());
+ return ByteString.of(sha1Bytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Returns an immutable copy of {@code list}. */
+ public static <T> List<T> immutableList(List<T> list) {
+ return Collections.unmodifiableList(new ArrayList<T>(list));
+ }
+
+ /** Returns an immutable list containing {@code elements}. */
+ public static <T> List<T> immutableList(T... elements) {
+ return Collections.unmodifiableList(Arrays.asList(elements.clone()));
+ }
+
+ /** Returns an immutable copy of {@code map}. */
+ public static <K, V> Map<K, V> immutableMap(Map<K, V> map) {
+ return Collections.unmodifiableMap(new LinkedHashMap<K, V>(map));
+ }
+
+ public static ThreadFactory threadFactory(final String name, final boolean daemon) {
+ return new ThreadFactory() {
+ @Override public Thread newThread(Runnable runnable) {
+ Thread result = new Thread(runnable, name);
+ result.setDaemon(daemon);
+ return result;
+ }
+ };
+ }
+
+ /**
+ * Returns an array containing containing only elements found in {@code first} and also in
+ * {@code second}. The returned elements are in the same order as in {@code first}.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T[] intersect(Class<T> arrayType, T[] first, T[] second) {
+ List<T> result = intersect(first, second);
+ return result.toArray((T[]) Array.newInstance(arrayType, result.size()));
+ }
+
+ /**
+ * Returns a list containing containing only elements found in {@code first} and also in
+ * {@code second}. The returned elements are in the same order as in {@code first}.
+ */
+ private static <T> List<T> intersect(T[] first, T[] second) {
+ List<T> result = new ArrayList<T>();
+ for (T a : first) {
+ for (T b : second) {
+ if (a.equals(b)) {
+ result.add(b);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /** Returns {@code s} with control characters and non-ASCII characters replaced with '?'. */
+ public static String toHumanReadableAscii(String s) {
+ for (int i = 0, length = s.length(), c; i < length; i += Character.charCount(c)) {
+ c = s.codePointAt(i);
+ if (c > '\u001f' && c < '\u007f') continue;
+
+ Buffer buffer = new Buffer();
+ buffer.writeUtf8(s, 0, i);
+ for (int j = i; j < length; j += Character.charCount(c)) {
+ c = s.codePointAt(j);
+ buffer.writeUtf8CodePoint(c > '\u001f' && c < '\u007f' ? c : '?');
+ }
+ return buffer.readUtf8();
+ }
+ return s;
+ }
+
+ /**
+ * Returns true if {@code e} is due to a firmware bug fixed after Android 4.2.2.
+ * https://code.google.com/p/android/issues/detail?id=54072
+ */
+ public static boolean isAndroidGetsocknameError(AssertionError e) {
+ return e.getCause() != null && e.getMessage() != null
+ && e.getMessage().contains("getsockname failed");
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java
new file mode 100644
index 000000000..38a545930
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-7
+public enum ErrorCode {
+ /** Not an error! For SPDY stream resets, prefer null over NO_ERROR. */
+ NO_ERROR(0, -1, 0),
+
+ PROTOCOL_ERROR(1, 1, 1),
+
+ /** A subtype of PROTOCOL_ERROR used by SPDY. */
+ INVALID_STREAM(1, 2, -1),
+
+ /** A subtype of PROTOCOL_ERROR used by SPDY. */
+ UNSUPPORTED_VERSION(1, 4, -1),
+
+ /** A subtype of PROTOCOL_ERROR used by SPDY. */
+ STREAM_IN_USE(1, 8, -1),
+
+ /** A subtype of PROTOCOL_ERROR used by SPDY. */
+ STREAM_ALREADY_CLOSED(1, 9, -1),
+
+ INTERNAL_ERROR(2, 6, 2),
+
+ FLOW_CONTROL_ERROR(3, 7, -1),
+
+ STREAM_CLOSED(5, -1, -1),
+
+ FRAME_TOO_LARGE(6, 11, -1),
+
+ REFUSED_STREAM(7, 3, -1),
+
+ CANCEL(8, 5, -1),
+
+ COMPRESSION_ERROR(9, -1, -1),
+
+ CONNECT_ERROR(10, -1, -1),
+
+ ENHANCE_YOUR_CALM(11, -1, -1),
+
+ INADEQUATE_SECURITY(12, -1, -1),
+
+ HTTP_1_1_REQUIRED(13, -1, -1),
+
+ INVALID_CREDENTIALS(-1, 10, -1);
+
+ public final int httpCode;
+ public final int spdyRstCode;
+ public final int spdyGoAwayCode;
+
+ private ErrorCode(int httpCode, int spdyRstCode, int spdyGoAwayCode) {
+ this.httpCode = httpCode;
+ this.spdyRstCode = spdyRstCode;
+ this.spdyGoAwayCode = spdyGoAwayCode;
+ }
+
+ public static ErrorCode fromSpdy3Rst(int code) {
+ for (ErrorCode errorCode : ErrorCode.values()) {
+ if (errorCode.spdyRstCode == code) return errorCode;
+ }
+ return null;
+ }
+
+ public static ErrorCode fromHttp2(int code) {
+ for (ErrorCode errorCode : ErrorCode.values()) {
+ if (errorCode.httpCode == code) return errorCode;
+ }
+ return null;
+ }
+
+ public static ErrorCode fromSpdyGoAway(int code) {
+ for (ErrorCode errorCode : ErrorCode.values()) {
+ if (errorCode.spdyGoAwayCode == code) return errorCode;
+ }
+ return null;
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java
new file mode 100644
index 000000000..20c50f7cc
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+import okio.BufferedSource;
+import okio.ByteString;
+
+/** Reads transport frames for SPDY/3 or HTTP/2. */
+public interface FrameReader extends Closeable {
+ void readConnectionPreface() throws IOException;
+ boolean nextFrame(Handler handler) throws IOException;
+
+ interface Handler {
+ void data(boolean inFinished, int streamId, BufferedSource source, int length)
+ throws IOException;
+
+ /**
+ * Create or update incoming headers, creating the corresponding streams
+ * if necessary. Frames that trigger this are SPDY SYN_STREAM, HEADERS, and
+ * SYN_REPLY, and HTTP/2 HEADERS and PUSH_PROMISE.
+ *
+ * @param outFinished true if the receiver should not send further frames.
+ * @param inFinished true if the sender will not send further frames.
+ * @param streamId the stream owning these headers.
+ * @param associatedStreamId the stream that triggered the sender to create
+ * this stream.
+ */
+ void headers(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
+ List<io.grpc.okhttp.internal.framed.Header> headerBlock, HeadersMode headersMode);
+ void rstStream(int streamId, io.grpc.okhttp.internal.framed.ErrorCode errorCode);
+ void settings(boolean clearPrevious, io.grpc.okhttp.internal.framed.Settings settings);
+
+ /** HTTP/2 only. */
+ void ackSettings();
+
+ /**
+ * Read a connection-level ping from the peer. {@code ack} indicates this
+ * is a reply. Payload parameters are different between SPDY/3 and HTTP/2.
+ * <p>
+ * In SPDY/3, only the first {@code payload1} parameter is set. If the
+ * reader is a client, it is an unsigned even number. Likewise, a server
+ * will receive an odd number.
+ * <p>
+ * In HTTP/2, both {@code payload1} and {@code payload2} parameters are
+ * set. The data is opaque binary, and there are no rules on the content.
+ */
+ void ping(boolean ack, int payload1, int payload2);
+
+ /**
+ * The peer tells us to stop creating streams. It is safe to replay
+ * streams with {@code ID > lastGoodStreamId} on a new connection. In-
+ * flight streams with {@code ID <= lastGoodStreamId} can only be replayed
+ * on a new connection if they are idempotent.
+ *
+ * @param lastGoodStreamId the last stream ID the peer processed before
+ * sending this message. If {@code lastGoodStreamId} is zero, the peer
+ * processed no frames.
+ * @param errorCode reason for closing the connection.
+ * @param debugData only valid for HTTP/2; opaque debug data to send.
+ */
+ void goAway(int lastGoodStreamId, io.grpc.okhttp.internal.framed.ErrorCode errorCode, ByteString debugData);
+
+ /**
+ * Notifies that an additional {@code windowSizeIncrement} bytes can be
+ * sent on {@code streamId}, or the connection if {@code streamId} is zero.
+ */
+ void windowUpdate(int streamId, long windowSizeIncrement);
+
+ /**
+ * Called when reading a headers or priority frame. This may be used to
+ * change the stream's weight from the default (16) to a new value.
+ *
+ * @param streamId stream which has a priority change.
+ * @param streamDependency the stream ID this stream is dependent on.
+ * @param weight relative proportion of priority in [1..256].
+ * @param exclusive inserts this stream ID as the sole child of
+ * {@code streamDependency}.
+ */
+ void priority(int streamId, int streamDependency, int weight, boolean exclusive);
+
+ /**
+ * HTTP/2 only. Receive a push promise header block.
+ * <p>
+ * A push promise contains all the headers that pertain to a server-initiated
+ * request, and a {@code promisedStreamId} to which response frames will be
+ * delivered. Push promise frames are sent as a part of the response to
+ * {@code streamId}.
+ *
+ * @param streamId client-initiated stream ID. Must be an odd number.
+ * @param promisedStreamId server-initiated stream ID. Must be an even
+ * number.
+ * @param requestHeaders minimally includes {@code :method}, {@code :scheme},
+ * {@code :authority}, and (@code :path}.
+ */
+ void pushPromise(int streamId, int promisedStreamId, List<io.grpc.okhttp.internal.framed.Header> requestHeaders)
+ throws IOException;
+
+ /**
+ * HTTP/2 only. Expresses that resources for the connection or a client-
+ * initiated stream are available from a different network location or
+ * protocol configuration.
+ *
+ * <p>See <a href="http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-01">alt-svc</a>
+ *
+ * @param streamId when a client-initiated stream ID (odd number), the
+ * origin of this alternate service is the origin of the stream. When
+ * zero, the origin is specified in the {@code origin} parameter.
+ * @param origin when present, the
+ * <a href="http://tools.ietf.org/html/rfc6454">origin</a> is typically
+ * represented as a combination of scheme, host and port. When empty,
+ * the origin is that of the {@code streamId}.
+ * @param protocol an ALPN protocol, such as {@code h2}.
+ * @param host an IP address or hostname.
+ * @param port the IP port associated with the service.
+ * @param maxAge time in seconds that this alternative is considered fresh.
+ */
+ void alternateService(int streamId, String origin, ByteString protocol, String host, int port,
+ long maxAge);
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java
new file mode 100644
index 000000000..333e06c86
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+import okio.Buffer;
+
+/** Writes transport frames for SPDY/3 or HTTP/2. */
+public interface FrameWriter extends Closeable {
+ /** HTTP/2 only. */
+ void connectionPreface() throws IOException;
+ /** Informs the peer that we've applied its latest settings. */
+ void ackSettings(Settings peerSettings) throws IOException;
+
+ /**
+ * HTTP/2 only. Send a push promise header block.
+ * <p>
+ * A push promise contains all the headers that pertain to a server-initiated
+ * request, and a {@code promisedStreamId} to which response frames will be
+ * delivered. Push promise frames are sent as a part of the response to
+ * {@code streamId}. The {@code promisedStreamId} has a priority of one
+ * greater than {@code streamId}.
+ *
+ * @param streamId client-initiated stream ID. Must be an odd number.
+ * @param promisedStreamId server-initiated stream ID. Must be an even
+ * number.
+ * @param requestHeaders minimally includes {@code :method}, {@code :scheme},
+ * {@code :authority}, and (@code :path}.
+ */
+ void pushPromise(int streamId, int promisedStreamId, List<Header> requestHeaders)
+ throws IOException;
+
+ /** SPDY/3 only. */
+ void flush() throws IOException;
+ void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
+ List<Header> headerBlock) throws IOException;
+ void synReply(boolean outFinished, int streamId, List<Header> headerBlock)
+ throws IOException;
+ void headers(int streamId, List<Header> headerBlock) throws IOException;
+ void rstStream(int streamId, ErrorCode errorCode) throws IOException;
+
+ /** The maximum size of bytes that may be sent in a single call to {@link #data}. */
+ int maxDataLength();
+
+ /**
+ * {@code source.length} may be longer than the max length of the variant's data frame.
+ * Implementations must send multiple frames as necessary.
+ *
+ * @param source the buffer to draw bytes from. May be null if byteCount is 0.
+ * @param byteCount must be between 0 and the minimum of {code source.length}
+ * and {@link #maxDataLength}.
+ */
+ void data(boolean outFinished, int streamId, Buffer source, int byteCount) throws IOException;
+
+ /** Write okhttp's settings to the peer. */
+ void settings(Settings okHttpSettings) throws IOException;
+
+ /**
+ * Send a connection-level ping to the peer. {@code ack} indicates this is
+ * a reply. Payload parameters are different between SPDY/3 and HTTP/2.
+ * <p>
+ * In SPDY/3, only the first {@code payload1} parameter is sent. If the
+ * sender is a client, it is an unsigned odd number. Likewise, a server
+ * will send an even number.
+ * <p>
+ * In HTTP/2, both {@code payload1} and {@code payload2} parameters are
+ * sent. The data is opaque binary, and there are no rules on the content.
+ */
+ void ping(boolean ack, int payload1, int payload2) throws IOException;
+
+ /**
+ * Tell the peer to stop creating streams and that we last processed
+ * {@code lastGoodStreamId}, or zero if no streams were processed.
+ *
+ * @param lastGoodStreamId the last stream ID processed, or zero if no
+ * streams were processed.
+ * @param errorCode reason for closing the connection.
+ * @param debugData only valid for HTTP/2; opaque debug data to send.
+ */
+ void goAway(int lastGoodStreamId, ErrorCode errorCode, byte[] debugData) throws IOException;
+
+ /**
+ * Inform peer that an additional {@code windowSizeIncrement} bytes can be
+ * sent on {@code streamId}, or the connection if {@code streamId} is zero.
+ */
+ void windowUpdate(int streamId, long windowSizeIncrement) throws IOException;
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Header.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Header.java
new file mode 100644
index 000000000..00081d489
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Header.java
@@ -0,0 +1,60 @@
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import okio.ByteString;
+
+/** HTTP header: the name is an ASCII string, but the value can be UTF-8. */
+public final class Header {
+ // Special header names defined in the SPDY and HTTP/2 specs.
+ public static final ByteString RESPONSE_STATUS = ByteString.encodeUtf8(":status");
+ public static final ByteString TARGET_METHOD = ByteString.encodeUtf8(":method");
+ public static final ByteString TARGET_PATH = ByteString.encodeUtf8(":path");
+ public static final ByteString TARGET_SCHEME = ByteString.encodeUtf8(":scheme");
+ public static final ByteString TARGET_AUTHORITY = ByteString.encodeUtf8(":authority"); // HTTP/2
+ public static final ByteString TARGET_HOST = ByteString.encodeUtf8(":host"); // spdy/3
+ public static final ByteString VERSION = ByteString.encodeUtf8(":version"); // spdy/3
+
+ /** Name in case-insensitive ASCII encoding. */
+ public final ByteString name;
+ /** Value in UTF-8 encoding. */
+ public final ByteString value;
+ final int hpackSize;
+
+ // TODO: search for toLowerCase and consider moving logic here.
+ public Header(String name, String value) {
+ this(ByteString.encodeUtf8(name), ByteString.encodeUtf8(value));
+ }
+
+ public Header(ByteString name, String value) {
+ this(name, ByteString.encodeUtf8(value));
+ }
+
+ public Header(ByteString name, ByteString value) {
+ this.name = name;
+ this.value = value;
+ this.hpackSize = 32 + name.size() + value.size();
+ }
+
+ @Override public boolean equals(Object other) {
+ if (other instanceof Header) {
+ Header that = (Header) other;
+ return this.name.equals(that.name)
+ && this.value.equals(that.value);
+ }
+ return false;
+ }
+
+ @Override public int hashCode() {
+ int result = 17;
+ result = 31 * result + name.hashCode();
+ result = 31 * result + value.hashCode();
+ return result;
+ }
+
+ @Override public String toString() {
+ return String.format("%s: %s", name.utf8(), value.utf8());
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java
new file mode 100644
index 000000000..3826252f4
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+public enum HeadersMode {
+ SPDY_SYN_STREAM,
+ SPDY_REPLY,
+ SPDY_HEADERS,
+ HTTP_20_HEADERS;
+
+ /** Returns true if it is an error these headers to create a new stream. */
+ public boolean failIfStreamAbsent() {
+ return this == SPDY_REPLY || this == SPDY_HEADERS;
+ }
+
+ /** Returns true if it is an error these headers to update an existing stream. */
+ public boolean failIfStreamPresent() {
+ return this == SPDY_SYN_STREAM;
+ }
+
+ /**
+ * Returns true if it is an error these headers to be the initial headers of a
+ * response.
+ */
+ public boolean failIfHeadersAbsent() {
+ return this == SPDY_HEADERS;
+ }
+
+ /**
+ * Returns true if it is an error these headers to be update existing headers
+ * of a response.
+ */
+ public boolean failIfHeadersPresent() {
+ return this == SPDY_REPLY;
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Hpack.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Hpack.java
new file mode 100644
index 000000000..940735abe
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Hpack.java
@@ -0,0 +1,441 @@
+/*
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ByteString;
+import okio.Okio;
+import okio.Source;
+
+/**
+ * Read and write HPACK v10.
+ *
+ * http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12
+ *
+ * This implementation uses an array for the dynamic table and a list for
+ * indexed entries. Dynamic entries are added to the array, starting in the
+ * last position moving forward. When the array fills, it is doubled.
+ */
+final class Hpack {
+ private static final int PREFIX_4_BITS = 0x0f;
+ private static final int PREFIX_5_BITS = 0x1f;
+ private static final int PREFIX_6_BITS = 0x3f;
+ private static final int PREFIX_7_BITS = 0x7f;
+
+ private static final io.grpc.okhttp.internal.framed.Header[] STATIC_HEADER_TABLE = new io.grpc.okhttp.internal.framed.Header[] {
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_AUTHORITY, ""),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_METHOD, "GET"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_METHOD, "POST"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_PATH, "/"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_PATH, "/index.html"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_SCHEME, "http"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.TARGET_SCHEME, "https"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "200"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "204"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "206"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "304"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "400"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "404"),
+ new io.grpc.okhttp.internal.framed.Header(io.grpc.okhttp.internal.framed.Header.RESPONSE_STATUS, "500"),
+ new io.grpc.okhttp.internal.framed.Header("accept-charset", ""),
+ new io.grpc.okhttp.internal.framed.Header("accept-encoding", "gzip, deflate"),
+ new io.grpc.okhttp.internal.framed.Header("accept-language", ""),
+ new io.grpc.okhttp.internal.framed.Header("accept-ranges", ""),
+ new io.grpc.okhttp.internal.framed.Header("accept", ""),
+ new io.grpc.okhttp.internal.framed.Header("access-control-allow-origin", ""),
+ new io.grpc.okhttp.internal.framed.Header("age", ""),
+ new io.grpc.okhttp.internal.framed.Header("allow", ""),
+ new io.grpc.okhttp.internal.framed.Header("authorization", ""),
+ new io.grpc.okhttp.internal.framed.Header("cache-control", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-disposition", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-encoding", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-language", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-length", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-location", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-range", ""),
+ new io.grpc.okhttp.internal.framed.Header("content-type", ""),
+ new io.grpc.okhttp.internal.framed.Header("cookie", ""),
+ new io.grpc.okhttp.internal.framed.Header("date", ""),
+ new io.grpc.okhttp.internal.framed.Header("etag", ""),
+ new io.grpc.okhttp.internal.framed.Header("expect", ""),
+ new io.grpc.okhttp.internal.framed.Header("expires", ""),
+ new io.grpc.okhttp.internal.framed.Header("from", ""),
+ new io.grpc.okhttp.internal.framed.Header("host", ""),
+ new io.grpc.okhttp.internal.framed.Header("if-match", ""),
+ new io.grpc.okhttp.internal.framed.Header("if-modified-since", ""),
+ new io.grpc.okhttp.internal.framed.Header("if-none-match", ""),
+ new io.grpc.okhttp.internal.framed.Header("if-range", ""),
+ new io.grpc.okhttp.internal.framed.Header("if-unmodified-since", ""),
+ new io.grpc.okhttp.internal.framed.Header("last-modified", ""),
+ new io.grpc.okhttp.internal.framed.Header("link", ""),
+ new io.grpc.okhttp.internal.framed.Header("location", ""),
+ new io.grpc.okhttp.internal.framed.Header("max-forwards", ""),
+ new io.grpc.okhttp.internal.framed.Header("proxy-authenticate", ""),
+ new io.grpc.okhttp.internal.framed.Header("proxy-authorization", ""),
+ new io.grpc.okhttp.internal.framed.Header("range", ""),
+ new io.grpc.okhttp.internal.framed.Header("referer", ""),
+ new io.grpc.okhttp.internal.framed.Header("refresh", ""),
+ new io.grpc.okhttp.internal.framed.Header("retry-after", ""),
+ new io.grpc.okhttp.internal.framed.Header("server", ""),
+ new io.grpc.okhttp.internal.framed.Header("set-cookie", ""),
+ new io.grpc.okhttp.internal.framed.Header("strict-transport-security", ""),
+ new io.grpc.okhttp.internal.framed.Header("transfer-encoding", ""),
+ new io.grpc.okhttp.internal.framed.Header("user-agent", ""),
+ new io.grpc.okhttp.internal.framed.Header("vary", ""),
+ new io.grpc.okhttp.internal.framed.Header("via", ""),
+ new io.grpc.okhttp.internal.framed.Header("www-authenticate", "")
+ };
+
+ private Hpack() {
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#section-3.1
+ static final class Reader {
+
+ private final List<io.grpc.okhttp.internal.framed.Header> headerList = new ArrayList<io.grpc.okhttp.internal.framed.Header>();
+ private final BufferedSource source;
+
+ private int headerTableSizeSetting;
+ private int maxDynamicTableByteCount;
+ // Visible for testing.
+ io.grpc.okhttp.internal.framed.Header[] dynamicTable = new io.grpc.okhttp.internal.framed.Header[8];
+ // Array is populated back to front, so new entries always have lowest index.
+ int nextHeaderIndex = dynamicTable.length - 1;
+ int headerCount = 0;
+ int dynamicTableByteCount = 0;
+
+ Reader(int headerTableSizeSetting, Source source) {
+ this.headerTableSizeSetting = headerTableSizeSetting;
+ this.maxDynamicTableByteCount = headerTableSizeSetting;
+ this.source = Okio.buffer(source);
+ }
+
+ int maxDynamicTableByteCount() {
+ return maxDynamicTableByteCount;
+ }
+
+ /**
+ * Called by the reader when the peer sent {@link Settings#HEADER_TABLE_SIZE}.
+ * While this establishes the maximum dynamic table size, the
+ * {@link #maxDynamicTableByteCount} set during processing may limit the
+ * table size to a smaller amount.
+ * <p> Evicts entries or clears the table as needed.
+ */
+ void headerTableSizeSetting(int headerTableSizeSetting) {
+ this.headerTableSizeSetting = headerTableSizeSetting;
+ this.maxDynamicTableByteCount = headerTableSizeSetting;
+ adjustDynamicTableByteCount();
+ }
+
+ private void adjustDynamicTableByteCount() {
+ if (maxDynamicTableByteCount < dynamicTableByteCount) {
+ if (maxDynamicTableByteCount == 0) {
+ clearDynamicTable();
+ } else {
+ evictToRecoverBytes(dynamicTableByteCount - maxDynamicTableByteCount);
+ }
+ }
+ }
+
+ private void clearDynamicTable() {
+ headerList.clear();
+ Arrays.fill(dynamicTable, null);
+ nextHeaderIndex = dynamicTable.length - 1;
+ headerCount = 0;
+ dynamicTableByteCount = 0;
+ }
+
+ /** Returns the count of entries evicted. */
+ private int evictToRecoverBytes(int bytesToRecover) {
+ int entriesToEvict = 0;
+ if (bytesToRecover > 0) {
+ // determine how many headers need to be evicted.
+ for (int j = dynamicTable.length - 1; j >= nextHeaderIndex && bytesToRecover > 0; j--) {
+ bytesToRecover -= dynamicTable[j].hpackSize;
+ dynamicTableByteCount -= dynamicTable[j].hpackSize;
+ headerCount--;
+ entriesToEvict++;
+ }
+ System.arraycopy(dynamicTable, nextHeaderIndex + 1, dynamicTable,
+ nextHeaderIndex + 1 + entriesToEvict, headerCount);
+ nextHeaderIndex += entriesToEvict;
+ }
+ return entriesToEvict;
+ }
+
+ /**
+ * Read {@code byteCount} bytes of headers from the source stream. This
+ * implementation does not propagate the never indexed flag of a header.
+ */
+ void readHeaders() throws IOException {
+ while (!source.exhausted()) {
+ int b = source.readByte() & 0xff;
+ if (b == 0x80) { // 10000000
+ throw new IOException("index == 0");
+ } else if ((b & 0x80) == 0x80) { // 1NNNNNNN
+ int index = readInt(b, PREFIX_7_BITS);
+ readIndexedHeader(index - 1);
+ } else if (b == 0x40) { // 01000000
+ readLiteralHeaderWithIncrementalIndexingNewName();
+ } else if ((b & 0x40) == 0x40) { // 01NNNNNN
+ int index = readInt(b, PREFIX_6_BITS);
+ readLiteralHeaderWithIncrementalIndexingIndexedName(index - 1);
+ } else if ((b & 0x20) == 0x20) { // 001NNNNN
+ maxDynamicTableByteCount = readInt(b, PREFIX_5_BITS);
+ if (maxDynamicTableByteCount < 0
+ || maxDynamicTableByteCount > headerTableSizeSetting) {
+ throw new IOException("Invalid dynamic table size update " + maxDynamicTableByteCount);
+ }
+ adjustDynamicTableByteCount();
+ } else if (b == 0x10 || b == 0) { // 000?0000 - Ignore never indexed bit.
+ readLiteralHeaderWithoutIndexingNewName();
+ } else { // 000?NNNN - Ignore never indexed bit.
+ int index = readInt(b, PREFIX_4_BITS);
+ readLiteralHeaderWithoutIndexingIndexedName(index - 1);
+ }
+ }
+ }
+
+ public List<io.grpc.okhttp.internal.framed.Header> getAndResetHeaderList() {
+ List<io.grpc.okhttp.internal.framed.Header> result = new ArrayList<io.grpc.okhttp.internal.framed.Header>(headerList);
+ headerList.clear();
+ return result;
+ }
+
+ private void readIndexedHeader(int index) throws IOException {
+ if (isStaticHeader(index)) {
+ io.grpc.okhttp.internal.framed.Header staticEntry = STATIC_HEADER_TABLE[index];
+ headerList.add(staticEntry);
+ } else {
+ int dynamicTableIndex = dynamicTableIndex(index - STATIC_HEADER_TABLE.length);
+ if (dynamicTableIndex < 0 || dynamicTableIndex > dynamicTable.length - 1) {
+ throw new IOException("Header index too large " + (index + 1));
+ }
+ headerList.add(dynamicTable[dynamicTableIndex]);
+ }
+ }
+
+ // referencedHeaders is relative to nextHeaderIndex + 1.
+ private int dynamicTableIndex(int index) {
+ return nextHeaderIndex + 1 + index;
+ }
+
+ private void readLiteralHeaderWithoutIndexingIndexedName(int index) throws IOException {
+ ByteString name = getName(index);
+ ByteString value = readByteString();
+ headerList.add(new io.grpc.okhttp.internal.framed.Header(name, value));
+ }
+
+ private void readLiteralHeaderWithoutIndexingNewName() throws IOException {
+ ByteString name = checkLowercase(readByteString());
+ ByteString value = readByteString();
+ headerList.add(new io.grpc.okhttp.internal.framed.Header(name, value));
+ }
+
+ private void readLiteralHeaderWithIncrementalIndexingIndexedName(int nameIndex)
+ throws IOException {
+ ByteString name = getName(nameIndex);
+ ByteString value = readByteString();
+ insertIntoDynamicTable(-1, new io.grpc.okhttp.internal.framed.Header(name, value));
+ }
+
+ private void readLiteralHeaderWithIncrementalIndexingNewName() throws IOException {
+ ByteString name = checkLowercase(readByteString());
+ ByteString value = readByteString();
+ insertIntoDynamicTable(-1, new io.grpc.okhttp.internal.framed.Header(name, value));
+ }
+
+ private ByteString getName(int index) {
+ if (isStaticHeader(index)) {
+ return STATIC_HEADER_TABLE[index].name;
+ } else {
+ return dynamicTable[dynamicTableIndex(index - STATIC_HEADER_TABLE.length)].name;
+ }
+ }
+
+ private boolean isStaticHeader(int index) {
+ return index >= 0 && index <= STATIC_HEADER_TABLE.length - 1;
+ }
+
+ /** index == -1 when new. */
+ private void insertIntoDynamicTable(int index, io.grpc.okhttp.internal.framed.Header entry) {
+ headerList.add(entry);
+
+ int delta = entry.hpackSize;
+ if (index != -1) { // Index -1 == new header.
+ delta -= dynamicTable[dynamicTableIndex(index)].hpackSize;
+ }
+
+ // if the new or replacement header is too big, drop all entries.
+ if (delta > maxDynamicTableByteCount) {
+ clearDynamicTable();
+ return;
+ }
+
+ // Evict headers to the required length.
+ int bytesToRecover = (dynamicTableByteCount + delta) - maxDynamicTableByteCount;
+ int entriesEvicted = evictToRecoverBytes(bytesToRecover);
+
+ if (index == -1) { // Adding a value to the dynamic table.
+ if (headerCount + 1 > dynamicTable.length) { // Need to grow the dynamic table.
+ io.grpc.okhttp.internal.framed.Header[] doubled = new io.grpc.okhttp.internal.framed.Header[dynamicTable.length * 2];
+ System.arraycopy(dynamicTable, 0, doubled, dynamicTable.length, dynamicTable.length);
+ nextHeaderIndex = dynamicTable.length - 1;
+ dynamicTable = doubled;
+ }
+ index = nextHeaderIndex--;
+ dynamicTable[index] = entry;
+ headerCount++;
+ } else { // Replace value at same position.
+ index += dynamicTableIndex(index) + entriesEvicted;
+ dynamicTable[index] = entry;
+ }
+ dynamicTableByteCount += delta;
+ }
+
+ private int readByte() throws IOException {
+ return source.readByte() & 0xff;
+ }
+
+ int readInt(int firstByte, int prefixMask) throws IOException {
+ int prefix = firstByte & prefixMask;
+ if (prefix < prefixMask) {
+ return prefix; // This was a single byte value.
+ }
+
+ // This is a multibyte value. Read 7 bits at a time.
+ int result = prefixMask;
+ int shift = 0;
+ while (true) {
+ int b = readByte();
+ if ((b & 0x80) != 0) { // Equivalent to (b >= 128) since b is in [0..255].
+ result += (b & 0x7f) << shift;
+ shift += 7;
+ } else {
+ result += b << shift; // Last byte.
+ break;
+ }
+ }
+ return result;
+ }
+
+ /** Reads a potentially Huffman encoded byte string. */
+ ByteString readByteString() throws IOException {
+ int firstByte = readByte();
+ boolean huffmanDecode = (firstByte & 0x80) == 0x80; // 1NNNNNNN
+ int length = readInt(firstByte, PREFIX_7_BITS);
+
+ if (huffmanDecode) {
+ return ByteString.of(io.grpc.okhttp.internal.framed.Huffman.get().decode(source.readByteArray(length)));
+ } else {
+ return source.readByteString(length);
+ }
+ }
+ }
+
+ private static final Map<ByteString, Integer> NAME_TO_FIRST_INDEX = nameToFirstIndex();
+
+ private static Map<ByteString, Integer> nameToFirstIndex() {
+ Map<ByteString, Integer> result =
+ new LinkedHashMap<ByteString, Integer>(STATIC_HEADER_TABLE.length);
+ for (int i = 0; i < STATIC_HEADER_TABLE.length; i++) {
+ if (!result.containsKey(STATIC_HEADER_TABLE[i].name)) {
+ result.put(STATIC_HEADER_TABLE[i].name, i);
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
+
+ static final class Writer {
+ private final Buffer out;
+
+ Writer(Buffer out) {
+ this.out = out;
+ }
+
+ /** This does not use "never indexed" semantics for sensitive headers. */
+ // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#section-6.2.3
+ void writeHeaders(List<io.grpc.okhttp.internal.framed.Header> headerBlock) throws IOException {
+ // TODO: implement index tracking
+ for (int i = 0, size = headerBlock.size(); i < size; i++) {
+ ByteString name = headerBlock.get(i).name.toAsciiLowercase();
+ Integer staticIndex = NAME_TO_FIRST_INDEX.get(name);
+ if (staticIndex != null) {
+ // Literal Header Field without Indexing - Indexed Name.
+ writeInt(staticIndex + 1, PREFIX_4_BITS, 0);
+ writeByteString(headerBlock.get(i).value);
+ } else {
+ out.writeByte(0x00); // Literal Header without Indexing - New Name.
+ writeByteString(name);
+ writeByteString(headerBlock.get(i).value);
+ }
+ }
+ }
+
+ // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#section-4.1.1
+ void writeInt(int value, int prefixMask, int bits) throws IOException {
+ // Write the raw value for a single byte value.
+ if (value < prefixMask) {
+ out.writeByte(bits | value);
+ return;
+ }
+
+ // Write the mask to start a multibyte value.
+ out.writeByte(bits | prefixMask);
+ value -= prefixMask;
+
+ // Write 7 bits at a time 'til we're done.
+ while (value >= 0x80) {
+ int b = value & 0x7f;
+ out.writeByte(b | 0x80);
+ value >>>= 7;
+ }
+ out.writeByte(value);
+ }
+
+ void writeByteString(ByteString data) throws IOException {
+ writeInt(data.size(), PREFIX_7_BITS, 0);
+ out.write(data);
+ }
+ }
+
+ /**
+ * An HTTP/2 response cannot contain uppercase header characters and must
+ * be treated as malformed.
+ */
+ private static ByteString checkLowercase(ByteString name) throws IOException {
+ for (int i = 0, length = name.size(); i < length; i++) {
+ byte c = name.getByte(i);
+ if (c >= 'A' && c <= 'Z') {
+ throw new IOException("PROTOCOL_ERROR response malformed: mixed case name: " + name.utf8());
+ }
+ }
+ return name;
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Http2.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Http2.java
new file mode 100644
index 000000000..0ad535fab
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Http2.java
@@ -0,0 +1,776 @@
+/*
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import io.grpc.okhttp.internal.Protocol;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Logger;
+
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.BufferedSource;
+import okio.ByteString;
+import okio.Source;
+import okio.Timeout;
+
+import static io.grpc.okhttp.internal.framed.Http2.FrameLogger.formatHeader;
+import static java.lang.String.format;
+import static java.util.logging.Level.FINE;
+import static okio.ByteString.EMPTY;
+
+/**
+ * Read and write HTTP/2 frames.
+ * <p>
+ * This implementation assumes we do not send an increased
+ * {@link io.grpc.okhttp.internal.framed.Settings#getMaxFrameSize frame size setting} to the peer. Hence, we
+ * expect all frames to have a max length of {@link #INITIAL_MAX_FRAME_SIZE}.
+ * <p>http://tools.ietf.org/html/draft-ietf-httpbis-http2-17
+ */
+public final class Http2 implements Variant {
+ private static final Logger logger = Logger.getLogger(FrameLogger.class.getName());
+
+ @Override public Protocol getProtocol() {
+ return Protocol.HTTP_2;
+ }
+
+ private 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.
+
+ /**
+ * Creates a frame reader with max header table size of 4096 and data frame
+ * compression disabled.
+ */
+ @Override public FrameReader newReader(BufferedSource source, boolean client) {
+ return new Reader(source, 4096, client);
+ }
+
+ @Override public io.grpc.okhttp.internal.framed.FrameWriter newWriter(BufferedSink sink, boolean client) {
+ return new Writer(sink, client);
+ }
+
+ static final class Reader implements FrameReader {
+ private final BufferedSource source;
+ private final ContinuationSource continuation;
+ private final boolean client;
+
+ // Visible for testing.
+ final Hpack.Reader hpackReader;
+
+ Reader(BufferedSource source, int headerTableSize, boolean client) {
+ this.source = source;
+ this.client = client;
+ this.continuation = new ContinuationSource(this.source);
+ this.hpackReader = new Hpack.Reader(headerTableSize, continuation);
+ }
+
+ @Override public void readConnectionPreface() throws IOException {
+ if (client) return; // Nothing to read; servers doesn't send a connection preface!
+ ByteString connectionPreface = source.readByteString(CONNECTION_PREFACE.size());
+ if (logger.isLoggable(FINE)) logger.fine(format("<< CONNECTION %s", connectionPreface.hex()));
+ if (!CONNECTION_PREFACE.equals(connectionPreface)) {
+ throw ioException("Expected a connection header but was %s", connectionPreface.utf8());
+ }
+ }
+
+ @Override public boolean nextFrame(Handler handler) throws IOException {
+ try {
+ source.require(9); // Frame header size
+ } catch (IOException e) {
+ return false; // This might be a normal socket close.
+ }
+
+ /* 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Length (24) |
+ * +---------------+---------------+---------------+
+ * | Type (8) | Flags (8) |
+ * +-+-+-----------+---------------+-------------------------------+
+ * |R| Stream Identifier (31) |
+ * +=+=============================================================+
+ * | Frame Payload (0...) ...
+ * +---------------------------------------------------------------+
+ */
+ int length = readMedium(source);
+ if (length < 0 || length > INITIAL_MAX_FRAME_SIZE) {
+ throw ioException("FRAME_SIZE_ERROR: %s", length);
+ }
+ 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));
+
+ switch (type) {
+ case TYPE_DATA:
+ readData(handler, length, flags, streamId);
+ break;
+
+ case TYPE_HEADERS:
+ readHeaders(handler, length, flags, streamId);
+ break;
+
+ case TYPE_PRIORITY:
+ readPriority(handler, length, flags, streamId);
+ break;
+
+ case TYPE_RST_STREAM:
+ readRstStream(handler, length, flags, streamId);
+ break;
+
+ case TYPE_SETTINGS:
+ readSettings(handler, length, flags, streamId);
+ break;
+
+ case TYPE_PUSH_PROMISE:
+ readPushPromise(handler, length, flags, streamId);
+ break;
+
+ case TYPE_PING:
+ readPing(handler, length, flags, streamId);
+ break;
+
+ case TYPE_GOAWAY:
+ readGoAway(handler, length, flags, streamId);
+ break;
+
+ case TYPE_WINDOW_UPDATE:
+ readWindowUpdate(handler, length, flags, streamId);
+ break;
+
+ default:
+ // Implementations MUST discard frames that have unknown or unsupported types.
+ source.skip(length);
+ }
+ return true;
+ }
+
+ private void readHeaders(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (streamId == 0) throw ioException("PROTOCOL_ERROR: TYPE_HEADERS streamId == 0");
+
+ boolean endStream = (flags & FLAG_END_STREAM) != 0;
+
+ short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;
+
+ if ((flags & FLAG_PRIORITY) != 0) {
+ readPriority(handler, streamId);
+ length -= 5; // account for above read.
+ }
+
+ length = lengthWithoutPadding(length, flags, padding);
+
+ List<Header> headerBlock = readHeaderBlock(length, padding, flags, streamId);
+
+ handler.headers(false, endStream, streamId, -1, headerBlock, HeadersMode.HTTP_20_HEADERS);
+ }
+
+ private List<Header> readHeaderBlock(int length, short padding, byte flags, int streamId)
+ throws IOException {
+ continuation.length = continuation.left = length;
+ continuation.padding = padding;
+ continuation.flags = flags;
+ continuation.streamId = streamId;
+
+ // TODO: Concat multi-value headers with 0x0, except COOKIE, which uses 0x3B, 0x20.
+ // http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-8.1.2.5
+ hpackReader.readHeaders();
+ return hpackReader.getAndResetHeaderList();
+ }
+
+ private void readData(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ // TODO: checkState open or half-closed (local) or raise STREAM_CLOSED
+ boolean inFinished = (flags & FLAG_END_STREAM) != 0;
+ boolean gzipped = (flags & FLAG_COMPRESSED) != 0;
+ if (gzipped) {
+ throw ioException("PROTOCOL_ERROR: FLAG_COMPRESSED without SETTINGS_COMPRESS_DATA");
+ }
+
+ short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;
+ length = lengthWithoutPadding(length, flags, padding);
+
+ handler.data(inFinished, streamId, source, length);
+ source.skip(padding);
+ }
+
+ private void readPriority(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (length != 5) throw ioException("TYPE_PRIORITY length: %d != 5", length);
+ if (streamId == 0) throw ioException("TYPE_PRIORITY streamId == 0");
+ readPriority(handler, streamId);
+ }
+
+ private void readPriority(Handler handler, int streamId) throws IOException {
+ int w1 = source.readInt();
+ boolean exclusive = (w1 & 0x80000000) != 0;
+ int streamDependency = (w1 & 0x7fffffff);
+ int weight = (source.readByte() & 0xff) + 1;
+ handler.priority(streamId, streamDependency, weight, exclusive);
+ }
+
+ private void readRstStream(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (length != 4) throw ioException("TYPE_RST_STREAM length: %d != 4", length);
+ if (streamId == 0) throw ioException("TYPE_RST_STREAM streamId == 0");
+ int errorCodeInt = source.readInt();
+ io.grpc.okhttp.internal.framed.ErrorCode errorCode = io.grpc.okhttp.internal.framed.ErrorCode.fromHttp2(errorCodeInt);
+ if (errorCode == null) {
+ throw ioException("TYPE_RST_STREAM unexpected error code: %d", errorCodeInt);
+ }
+ handler.rstStream(streamId, errorCode);
+ }
+
+ private void readSettings(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (streamId != 0) throw ioException("TYPE_SETTINGS streamId != 0");
+ if ((flags & FLAG_ACK) != 0) {
+ if (length != 0) throw ioException("FRAME_SIZE_ERROR ack frame should be empty!");
+ handler.ackSettings();
+ return;
+ }
+
+ if (length % 6 != 0) throw ioException("TYPE_SETTINGS length %% 6 != 0: %s", length);
+ io.grpc.okhttp.internal.framed.Settings settings = new io.grpc.okhttp.internal.framed.Settings();
+ for (int i = 0; i < length; i += 6) {
+ short id = source.readShort();
+ int value = source.readInt();
+
+ switch (id) {
+ case 1: // SETTINGS_HEADER_TABLE_SIZE
+ break;
+ case 2: // SETTINGS_ENABLE_PUSH
+ if (value != 0 && value != 1) {
+ throw ioException("PROTOCOL_ERROR SETTINGS_ENABLE_PUSH != 0 or 1");
+ }
+ break;
+ case 3: // SETTINGS_MAX_CONCURRENT_STREAMS
+ id = 4; // Renumbered in draft 10.
+ break;
+ case 4: // SETTINGS_INITIAL_WINDOW_SIZE
+ id = 7; // Renumbered in draft 10.
+ if (value < 0) {
+ throw ioException("PROTOCOL_ERROR SETTINGS_INITIAL_WINDOW_SIZE > 2^31 - 1");
+ }
+ break;
+ case 5: // SETTINGS_MAX_FRAME_SIZE
+ if (value < INITIAL_MAX_FRAME_SIZE || value > 16777215) {
+ throw ioException("PROTOCOL_ERROR SETTINGS_MAX_FRAME_SIZE: %s", value);
+ }
+ break;
+ case 6: // SETTINGS_MAX_HEADER_LIST_SIZE
+ break; // Advisory only, so ignored.
+ default:
+ throw ioException("PROTOCOL_ERROR invalid settings id: %s", id);
+ }
+ settings.set(id, 0, value);
+ }
+ handler.settings(false, settings);
+ if (settings.getHeaderTableSize() >= 0) {
+ hpackReader.headerTableSizeSetting(settings.getHeaderTableSize());
+ }
+ }
+
+ private void readPushPromise(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (streamId == 0) {
+ throw ioException("PROTOCOL_ERROR: TYPE_PUSH_PROMISE streamId == 0");
+ }
+ short padding = (flags & FLAG_PADDED) != 0 ? (short) (source.readByte() & 0xff) : 0;
+ int promisedStreamId = source.readInt() & 0x7fffffff;
+ length -= 4; // account for above read.
+ length = lengthWithoutPadding(length, flags, padding);
+ List<Header> headerBlock = readHeaderBlock(length, padding, flags, streamId);
+ handler.pushPromise(streamId, promisedStreamId, headerBlock);
+ }
+
+ private void readPing(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (length != 8) throw ioException("TYPE_PING length != 8: %s", length);
+ if (streamId != 0) throw ioException("TYPE_PING streamId != 0");
+ int payload1 = source.readInt();
+ int payload2 = source.readInt();
+ boolean ack = (flags & FLAG_ACK) != 0;
+ handler.ping(ack, payload1, payload2);
+ }
+
+ private void readGoAway(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (length < 8) throw ioException("TYPE_GOAWAY length < 8: %s", length);
+ if (streamId != 0) throw ioException("TYPE_GOAWAY streamId != 0");
+ int lastStreamId = source.readInt();
+ int errorCodeInt = source.readInt();
+ int opaqueDataLength = length - 8;
+ io.grpc.okhttp.internal.framed.ErrorCode errorCode = io.grpc.okhttp.internal.framed.ErrorCode.fromHttp2(errorCodeInt);
+ if (errorCode == null) {
+ throw ioException("TYPE_GOAWAY unexpected error code: %d", errorCodeInt);
+ }
+ ByteString debugData = EMPTY;
+ if (opaqueDataLength > 0) { // Must read debug data in order to not corrupt the connection.
+ debugData = source.readByteString(opaqueDataLength);
+ }
+ handler.goAway(lastStreamId, errorCode, debugData);
+ }
+
+ private void readWindowUpdate(Handler handler, int length, byte flags, int streamId)
+ throws IOException {
+ if (length != 4) throw ioException("TYPE_WINDOW_UPDATE length !=4: %s", length);
+ long increment = (source.readInt() & 0x7fffffffL);
+ if (increment == 0) throw ioException("windowSizeIncrement was 0", increment);
+ handler.windowUpdate(streamId, increment);
+ }
+
+ @Override public void close() throws IOException {
+ source.close();
+ }
+ }
+
+ static final class Writer implements io.grpc.okhttp.internal.framed.FrameWriter {
+ private final BufferedSink sink;
+ private final boolean client;
+ private final Buffer hpackBuffer;
+ private final Hpack.Writer hpackWriter;
+ private int maxFrameSize;
+ private boolean closed;
+
+ Writer(BufferedSink sink, boolean client) {
+ this.sink = sink;
+ this.client = client;
+ this.hpackBuffer = new Buffer();
+ this.hpackWriter = new Hpack.Writer(hpackBuffer);
+ this.maxFrameSize = INITIAL_MAX_FRAME_SIZE;
+ }
+
+ @Override public synchronized void flush() throws IOException {
+ if (closed) throw new IOException("closed");
+ sink.flush();
+ }
+
+ @Override public synchronized void ackSettings(io.grpc.okhttp.internal.framed.Settings peerSettings) throws IOException {
+ if (closed) throw new IOException("closed");
+ this.maxFrameSize = peerSettings.getMaxFrameSize(maxFrameSize);
+ int length = 0;
+ byte type = TYPE_SETTINGS;
+ byte flags = FLAG_ACK;
+ int streamId = 0;
+ frameHeader(streamId, length, type, flags);
+ sink.flush();
+ }
+
+ @Override public synchronized void connectionPreface() throws IOException {
+ if (closed) throw new IOException("closed");
+ if (!client) return; // Nothing to write; servers don't send connection headers!
+ if (logger.isLoggable(FINE)) {
+ logger.fine(format(">> CONNECTION %s", CONNECTION_PREFACE.hex()));
+ }
+ sink.write(CONNECTION_PREFACE.toByteArray());
+ sink.flush();
+ }
+
+ @Override public synchronized void synStream(boolean outFinished, boolean inFinished,
+ int streamId, int associatedStreamId, List<Header> headerBlock)
+ throws IOException {
+ if (inFinished) throw new UnsupportedOperationException();
+ if (closed) throw new IOException("closed");
+ headers(outFinished, streamId, headerBlock);
+ }
+
+ @Override public synchronized void synReply(boolean outFinished, int streamId,
+ List<Header> headerBlock) throws IOException {
+ if (closed) throw new IOException("closed");
+ headers(outFinished, streamId, headerBlock);
+ }
+
+ @Override public synchronized void headers(int streamId, List<Header> headerBlock)
+ throws IOException {
+ if (closed) throw new IOException("closed");
+ headers(false, streamId, headerBlock);
+ }
+
+ @Override public synchronized void pushPromise(int streamId, int promisedStreamId,
+ List<Header> requestHeaders) throws IOException {
+ if (closed) throw new IOException("closed");
+ hpackWriter.writeHeaders(requestHeaders);
+
+ long byteCount = hpackBuffer.size();
+ int length = (int) Math.min(maxFrameSize - 4, byteCount);
+ byte type = TYPE_PUSH_PROMISE;
+ byte flags = byteCount == length ? FLAG_END_HEADERS : 0;
+ frameHeader(streamId, length + 4, type, flags);
+ sink.writeInt(promisedStreamId & 0x7fffffff);
+ sink.write(hpackBuffer, length);
+
+ if (byteCount > length) writeContinuationFrames(streamId, byteCount - length);
+ }
+
+ void headers(boolean outFinished, int streamId, List<Header> headerBlock) throws IOException {
+ if (closed) throw new IOException("closed");
+ hpackWriter.writeHeaders(headerBlock);
+
+ long byteCount = hpackBuffer.size();
+ int length = (int) Math.min(maxFrameSize, byteCount);
+ byte type = TYPE_HEADERS;
+ byte flags = byteCount == length ? FLAG_END_HEADERS : 0;
+ if (outFinished) flags |= FLAG_END_STREAM;
+ frameHeader(streamId, length, type, flags);
+ sink.write(hpackBuffer, length);
+
+ if (byteCount > length) writeContinuationFrames(streamId, byteCount - length);
+ }
+
+ private void writeContinuationFrames(int streamId, long byteCount) throws IOException {
+ while (byteCount > 0) {
+ int length = (int) Math.min(maxFrameSize, byteCount);
+ byteCount -= length;
+ frameHeader(streamId, length, TYPE_CONTINUATION, byteCount == 0 ? FLAG_END_HEADERS : 0);
+ sink.write(hpackBuffer, length);
+ }
+ }
+
+ @Override public synchronized void rstStream(int streamId, io.grpc.okhttp.internal.framed.ErrorCode errorCode)
+ throws IOException {
+ if (closed) throw new IOException("closed");
+ if (errorCode.httpCode == -1) throw new IllegalArgumentException();
+
+ int length = 4;
+ byte type = TYPE_RST_STREAM;
+ byte flags = FLAG_NONE;
+ frameHeader(streamId, length, type, flags);
+ sink.writeInt(errorCode.httpCode);
+ sink.flush();
+ }
+
+ @Override public int maxDataLength() {
+ return maxFrameSize;
+ }
+
+ @Override public synchronized void data(boolean outFinished, int streamId, Buffer source,
+ int byteCount) throws IOException {
+ if (closed) throw new IOException("closed");
+ byte flags = FLAG_NONE;
+ if (outFinished) flags |= FLAG_END_STREAM;
+ dataFrame(streamId, flags, source, byteCount);
+ }
+
+ void dataFrame(int streamId, byte flags, Buffer buffer, int byteCount) throws IOException {
+ byte type = TYPE_DATA;
+ frameHeader(streamId, byteCount, type, flags);
+ if (byteCount > 0) {
+ sink.write(buffer, byteCount);
+ }
+ }
+
+ @Override public synchronized void settings(io.grpc.okhttp.internal.framed.Settings settings) throws IOException {
+ if (closed) throw new IOException("closed");
+ int length = settings.size() * 6;
+ byte type = TYPE_SETTINGS;
+ byte flags = FLAG_NONE;
+ int streamId = 0;
+ frameHeader(streamId, length, type, flags);
+ for (int i = 0; i < io.grpc.okhttp.internal.framed.Settings.COUNT; i++) {
+ if (!settings.isSet(i)) continue;
+ int id = i;
+ if (id == 4) id = 3; // SETTINGS_MAX_CONCURRENT_STREAMS renumbered.
+ else if (id == 7) id = 4; // SETTINGS_INITIAL_WINDOW_SIZE renumbered.
+ sink.writeShort(id);
+ sink.writeInt(settings.get(i));
+ }
+ sink.flush();
+ }
+
+ @Override public synchronized void ping(boolean ack, int payload1, int payload2)
+ throws IOException {
+ if (closed) throw new IOException("closed");
+ int length = 8;
+ byte type = TYPE_PING;
+ byte flags = ack ? FLAG_ACK : FLAG_NONE;
+ int streamId = 0;
+ frameHeader(streamId, length, type, flags);
+ sink.writeInt(payload1);
+ sink.writeInt(payload2);
+ sink.flush();
+ }
+
+ @Override public synchronized void goAway(int lastGoodStreamId, io.grpc.okhttp.internal.framed.ErrorCode errorCode,
+ byte[] debugData) throws IOException {
+ if (closed) throw new IOException("closed");
+ if (errorCode.httpCode == -1) throw illegalArgument("errorCode.httpCode == -1");
+ int length = 8 + debugData.length;
+ byte type = TYPE_GOAWAY;
+ byte flags = FLAG_NONE;
+ int streamId = 0;
+ frameHeader(streamId, length, type, flags);
+ sink.writeInt(lastGoodStreamId);
+ sink.writeInt(errorCode.httpCode);
+ if (debugData.length > 0) {
+ sink.write(debugData);
+ }
+ sink.flush();
+ }
+
+ @Override public synchronized void windowUpdate(int streamId, long windowSizeIncrement)
+ throws IOException {
+ if (closed) throw new IOException("closed");
+ if (windowSizeIncrement == 0 || windowSizeIncrement > 0x7fffffffL) {
+ throw illegalArgument("windowSizeIncrement == 0 || windowSizeIncrement > 0x7fffffffL: %s",
+ windowSizeIncrement);
+ }
+ int length = 4;
+ byte type = TYPE_WINDOW_UPDATE;
+ byte flags = FLAG_NONE;
+ frameHeader(streamId, length, type, flags);
+ sink.writeInt((int) windowSizeIncrement);
+ sink.flush();
+ }
+
+ @Override public synchronized void close() throws IOException {
+ closed = true;
+ sink.close();
+ }
+
+ 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 (length > maxFrameSize) {
+ throw illegalArgument("FRAME_SIZE_ERROR length > %d: %d", maxFrameSize, length);
+ }
+ if ((streamId & 0x80000000) != 0) throw illegalArgument("reserved bit set: %s", streamId);
+ writeMedium(sink, length);
+ sink.writeByte(type & 0xff);
+ sink.writeByte(flags & 0xff);
+ sink.writeInt(streamId & 0x7fffffff);
+ }
+ }
+
+ private static IllegalArgumentException illegalArgument(String message, Object... args) {
+ throw new IllegalArgumentException(format(message, args));
+ }
+
+ private static IOException ioException(String message, Object... args) throws IOException {
+ throw new IOException(format(message, args));
+ }
+
+ /**
+ * Decompression of the header block occurs above the framing layer. This
+ * class lazily reads continuation frames as they are needed by {@link
+ * Hpack.Reader#readHeaders()}.
+ */
+ static final class ContinuationSource implements Source {
+ private final BufferedSource source;
+
+ int length;
+ byte flags;
+ int streamId;
+
+ int left;
+ short padding;
+
+ public ContinuationSource(BufferedSource source) {
+ this.source = source;
+ }
+
+ @Override public long read(Buffer sink, long byteCount) throws IOException {
+ while (left == 0) {
+ source.skip(padding);
+ padding = 0;
+ if ((flags & FLAG_END_HEADERS) != 0) return -1;
+ readContinuationHeader();
+ // TODO: test case for empty continuation header?
+ }
+
+ long read = source.read(sink, Math.min(byteCount, left));
+ if (read == -1) return -1;
+ left -= read;
+ return read;
+ }
+
+ @Override public Timeout timeout() {
+ return source.timeout();
+ }
+
+ @Override public void close() throws IOException {
+ }
+
+ private void readContinuationHeader() throws IOException {
+ int previousStreamId = streamId;
+
+ 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));
+ streamId = (source.readInt() & 0x7fffffff);
+ if (type != TYPE_CONTINUATION) throw ioException("%s != TYPE_CONTINUATION", type);
+ if (streamId != previousStreamId) throw ioException("TYPE_CONTINUATION streamId changed");
+ }
+ }
+
+ private static int lengthWithoutPadding(int length, byte flags, short padding)
+ throws IOException {
+ if ((flags & FLAG_PADDED) != 0) length--; // Account for reading the padding length.
+ if (padding > length) {
+ throw ioException("PROTOCOL_ERROR padding %s > remaining length %s", padding, length);
+ }
+ return (short) (length - padding);
+ }
+
+ /**
+ * 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>
+ */
+ static final class FrameLogger {
+
+ 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);
+ }
+
+ /**
+ * 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;
+ }
+
+ /** Lookup table for valid frame types. */
+ private static final String[] TYPES = new String[] {
+ "DATA",
+ "HEADERS",
+ "PRIORITY",
+ "RST_STREAM",
+ "SETTINGS",
+ "PUSH_PROMISE",
+ "PING",
+ "GOAWAY",
+ "WINDOW_UPDATE",
+ "CONTINUATION"
+ };
+
+ /**
+ * 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 {
+ for (int i = 0; i < BINARY.length; i++) {
+ BINARY[i] = format("%8s", Integer.toBinaryString(i)).replace(' ', '0');
+ }
+
+ FLAGS[FLAG_NONE] = "";
+ FLAGS[FLAG_END_STREAM] = "END_STREAM";
+
+ int[] prefixFlags = new int[] {FLAG_END_STREAM};
+
+ FLAGS[FLAG_PADDED] = "PADDED";
+ for (int prefixFlag : prefixFlags) {
+ FLAGS[prefixFlag | FLAG_PADDED] = FLAGS[prefixFlag] + "|PADDED";
+ }
+
+ FLAGS[FLAG_END_HEADERS] = "END_HEADERS"; // Same as END_PUSH_PROMISE.
+ FLAGS[FLAG_PRIORITY] = "PRIORITY"; // Same as FLAG_COMPRESSED.
+ FLAGS[FLAG_END_HEADERS | FLAG_PRIORITY] = "END_HEADERS|PRIORITY"; // Only valid on HEADERS.
+ int[] frameFlags =
+ new int[] {FLAG_END_HEADERS, FLAG_PRIORITY, FLAG_END_HEADERS | FLAG_PRIORITY};
+
+ for (int frameFlag : frameFlags) {
+ for (int prefixFlag : prefixFlags) {
+ FLAGS[prefixFlag | frameFlag] = FLAGS[prefixFlag] + '|' + FLAGS[frameFlag];
+ FLAGS[prefixFlag | frameFlag | FLAG_PADDED] =
+ FLAGS[prefixFlag] + '|' + FLAGS[frameFlag] + "|PADDED";
+ }
+ }
+
+ for (int i = 0; i < FLAGS.length; i++) { // Fill in holes with binary representation.
+ if (FLAGS[i] == null) FLAGS[i] = BINARY[i];
+ }
+ }
+ }
+
+ private static int readMedium(BufferedSource source) throws IOException {
+ return (source.readByte() & 0xff) << 16
+ | (source.readByte() & 0xff) << 8
+ | (source.readByte() & 0xff);
+ }
+
+ private static void writeMedium(BufferedSink sink, int i) throws IOException {
+ sink.writeByte((i >>> 16) & 0xff);
+ sink.writeByte((i >>> 8) & 0xff);
+ sink.writeByte(i & 0xff);
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Huffman.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Huffman.java
new file mode 100644
index 000000000..11370ddbb
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Huffman.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2013 Twitter, 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This class was originally composed from the following classes in
+ * <a href="https://github.com/twitter/hpack">Twitter Hpack</a>.
+ * <ul>
+ * <li>{@code com.twitter.hpack.HuffmanEncoder}</li>
+ * <li>{@code com.twitter.hpack.HuffmanDecoder}</li>
+ * <li>{@code com.twitter.hpack.HpackUtil}</li>
+ * </ul>
+ */
+class Huffman {
+
+ // Appendix C: Huffman Codes
+ // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-B
+ private static final int[] CODES = {
+ 0x1ff8, 0x7fffd8, 0xfffffe2, 0xfffffe3, 0xfffffe4, 0xfffffe5, 0xfffffe6, 0xfffffe7, 0xfffffe8,
+ 0xffffea, 0x3ffffffc, 0xfffffe9, 0xfffffea, 0x3ffffffd, 0xfffffeb, 0xfffffec, 0xfffffed,
+ 0xfffffee, 0xfffffef, 0xffffff0, 0xffffff1, 0xffffff2, 0x3ffffffe, 0xffffff3, 0xffffff4,
+ 0xffffff5, 0xffffff6, 0xffffff7, 0xffffff8, 0xffffff9, 0xffffffa, 0xffffffb, 0x14, 0x3f8,
+ 0x3f9, 0xffa, 0x1ff9, 0x15, 0xf8, 0x7fa, 0x3fa, 0x3fb, 0xf9, 0x7fb, 0xfa, 0x16, 0x17, 0x18,
+ 0x0, 0x1, 0x2, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x5c, 0xfb, 0x7ffc, 0x20, 0xffb,
+ 0x3fc, 0x1ffa, 0x21, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0xfc, 0x73, 0xfd, 0x1ffb, 0x7fff0,
+ 0x1ffc, 0x3ffc, 0x22, 0x7ffd, 0x3, 0x23, 0x4, 0x24, 0x5, 0x25, 0x26, 0x27, 0x6, 0x74, 0x75,
+ 0x28, 0x29, 0x2a, 0x7, 0x2b, 0x76, 0x2c, 0x8, 0x9, 0x2d, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7ffe,
+ 0x7fc, 0x3ffd, 0x1ffd, 0xffffffc, 0xfffe6, 0x3fffd2, 0xfffe7, 0xfffe8, 0x3fffd3, 0x3fffd4,
+ 0x3fffd5, 0x7fffd9, 0x3fffd6, 0x7fffda, 0x7fffdb, 0x7fffdc, 0x7fffdd, 0x7fffde, 0xffffeb,
+ 0x7fffdf, 0xffffec, 0xffffed, 0x3fffd7, 0x7fffe0, 0xffffee, 0x7fffe1, 0x7fffe2, 0x7fffe3,
+ 0x7fffe4, 0x1fffdc, 0x3fffd8, 0x7fffe5, 0x3fffd9, 0x7fffe6, 0x7fffe7, 0xffffef, 0x3fffda,
+ 0x1fffdd, 0xfffe9, 0x3fffdb, 0x3fffdc, 0x7fffe8, 0x7fffe9, 0x1fffde, 0x7fffea, 0x3fffdd,
+ 0x3fffde, 0xfffff0, 0x1fffdf, 0x3fffdf, 0x7fffeb, 0x7fffec, 0x1fffe0, 0x1fffe1, 0x3fffe0,
+ 0x1fffe2, 0x7fffed, 0x3fffe1, 0x7fffee, 0x7fffef, 0xfffea, 0x3fffe2, 0x3fffe3, 0x3fffe4,
+ 0x7ffff0, 0x3fffe5, 0x3fffe6, 0x7ffff1, 0x3ffffe0, 0x3ffffe1, 0xfffeb, 0x7fff1, 0x3fffe7,
+ 0x7ffff2, 0x3fffe8, 0x1ffffec, 0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x7ffffde, 0x7ffffdf,
+ 0x3ffffe5, 0xfffff1, 0x1ffffed, 0x7fff2, 0x1fffe3, 0x3ffffe6, 0x7ffffe0, 0x7ffffe1, 0x3ffffe7,
+ 0x7ffffe2, 0xfffff2, 0x1fffe4, 0x1fffe5, 0x3ffffe8, 0x3ffffe9, 0xffffffd, 0x7ffffe3,
+ 0x7ffffe4, 0x7ffffe5, 0xfffec, 0xfffff3, 0xfffed, 0x1fffe6, 0x3fffe9, 0x1fffe7, 0x1fffe8,
+ 0x7ffff3, 0x3fffea, 0x3fffeb, 0x1ffffee, 0x1ffffef, 0xfffff4, 0xfffff5, 0x3ffffea, 0x7ffff4,
+ 0x3ffffeb, 0x7ffffe6, 0x3ffffec, 0x3ffffed, 0x7ffffe7, 0x7ffffe8, 0x7ffffe9, 0x7ffffea,
+ 0x7ffffeb, 0xffffffe, 0x7ffffec, 0x7ffffed, 0x7ffffee, 0x7ffffef, 0x7fffff0, 0x3ffffee
+ };
+
+ private static final byte[] CODE_LENGTHS = {
+ 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 30,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, 5,
+ 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6,
+ 6, 6, 5, 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, 20, 22, 20, 20, 22, 22, 22, 23,
+ 22, 23, 23, 23, 23, 23, 24, 23, 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23,
+ 24, 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, 21, 21, 22, 21, 23, 22,
+ 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27,
+ 26, 24, 25, 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, 20, 24, 20, 21,
+ 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27,
+ 27, 27, 27, 27, 26
+ };
+
+ private static final Huffman INSTANCE = new Huffman();
+
+ public static Huffman get() {
+ return INSTANCE;
+ }
+
+ private final Node root = new Node();
+
+ private Huffman() {
+ buildTree();
+ }
+
+ void encode(byte[] data, OutputStream out) throws IOException {
+ long current = 0;
+ int n = 0;
+
+ for (int i = 0; i < data.length; i++) {
+ int b = data[i] & 0xFF;
+ int code = CODES[b];
+ int nbits = CODE_LENGTHS[b];
+
+ current <<= nbits;
+ current |= code;
+ n += nbits;
+
+ while (n >= 8) {
+ n -= 8;
+ out.write(((int) (current >> n)));
+ }
+ }
+
+ if (n > 0) {
+ current <<= (8 - n);
+ current |= (0xFF >>> n);
+ out.write((int) current);
+ }
+ }
+
+ int encodedLength(byte[] bytes) {
+ long len = 0;
+
+ for (int i = 0; i < bytes.length; i++) {
+ int b = bytes[i] & 0xFF;
+ len += CODE_LENGTHS[b];
+ }
+
+ return (int) ((len + 7) >> 3);
+ }
+
+ byte[] decode(byte[] buf) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Node node = root;
+ int current = 0;
+ int nbits = 0;
+ for (int i = 0; i < buf.length; i++) {
+ int b = buf[i] & 0xFF;
+ current = (current << 8) | b;
+ nbits += 8;
+ while (nbits >= 8) {
+ int c = (current >>> (nbits - 8)) & 0xFF;
+ node = node.children[c];
+ if (node.children == null) {
+ // terminal node
+ baos.write(node.symbol);
+ nbits -= node.terminalBits;
+ node = root;
+ } else {
+ // non-terminal node
+ nbits -= 8;
+ }
+ }
+ }
+
+ while (nbits > 0) {
+ int c = (current << (8 - nbits)) & 0xFF;
+ node = node.children[c];
+ if (node.children != null || node.terminalBits > nbits) {
+ break;
+ }
+ baos.write(node.symbol);
+ nbits -= node.terminalBits;
+ node = root;
+ }
+
+ return baos.toByteArray();
+ }
+
+ private void buildTree() {
+ for (int i = 0; i < CODE_LENGTHS.length; i++) {
+ addCode(i, CODES[i], CODE_LENGTHS[i]);
+ }
+ }
+
+ private void addCode(int sym, int code, byte len) {
+ Node terminal = new Node(sym, len);
+
+ Node current = root;
+ while (len > 8) {
+ len -= 8;
+ int i = ((code >>> len) & 0xFF);
+ if (current.children == null) {
+ throw new IllegalStateException("invalid dictionary: prefix not unique");
+ }
+ if (current.children[i] == null) {
+ current.children[i] = new Node();
+ }
+ current = current.children[i];
+ }
+
+ int shift = 8 - len;
+ int start = (code << shift) & 0xFF;
+ int end = 1 << shift;
+ for (int i = start; i < start + end; i++) {
+ current.children[i] = terminal;
+ }
+ }
+
+ private static final class Node {
+
+ // Null if terminal.
+ private final Node[] children;
+
+ // Terminal nodes have a symbol.
+ private final int symbol;
+
+ // Number of bits represented in the terminal node.
+ private final int terminalBits;
+
+ /** Construct an internal node. */
+ Node() {
+ this.children = new Node[256];
+ this.symbol = 0; // Not read.
+ this.terminalBits = 0; // Not read.
+ }
+
+ /**
+ * Construct a terminal node.
+ *
+ * @param symbol symbol the node represents
+ * @param bits length of Huffman code in bits
+ */
+ Node(int symbol, int bits) {
+ this.children = null;
+ this.symbol = symbol;
+ int b = bits & 0x07;
+ this.terminalBits = b == 0 ? 8 : b;
+ }
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java
new file mode 100644
index 000000000..0d0ecce99
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import java.util.Arrays;
+
+/**
+ * Settings describe characteristics of the sending peer, which are used by the receiving peer.
+ */
+public final class Settings {
+ /**
+ * From the SPDY/3 and HTTP/2 specs, the default initial window size for all
+ * streams is 64 KiB. (Chrome 25 uses 10 MiB).
+ */
+ static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024;
+
+ /** Peer request to clear durable settings. */
+ static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1;
+
+ /** Sent by servers only. The peer requests this setting persisted for future connections. */
+ static final int PERSIST_VALUE = 0x1;
+ /** Sent by clients only. The client is reminding the server of a persisted value. */
+ static final int PERSISTED = 0x2;
+
+ /** spdy/3: Sender's estimate of max incoming kbps. */
+ static final int UPLOAD_BANDWIDTH = 1;
+ /** HTTP/2: Size in bytes of the table used to decode the sender's header blocks. */
+ static final int HEADER_TABLE_SIZE = 1;
+ /** spdy/3: Sender's estimate of max outgoing kbps. */
+ static final int DOWNLOAD_BANDWIDTH = 2;
+ /** HTTP/2: The peer must not send a PUSH_PROMISE frame when this is 0. */
+ static final int ENABLE_PUSH = 2;
+ /** spdy/3: Sender's estimate of millis between sending a request and receiving a response. */
+ static final int ROUND_TRIP_TIME = 3;
+ /** Sender's maximum number of concurrent streams. */
+ public static final int MAX_CONCURRENT_STREAMS = 4;
+ /** spdy/3: Current CWND in Packets. */
+ static final int CURRENT_CWND = 5;
+ /** HTTP/2: Size in bytes of the largest frame payload the sender will accept. */
+ static final int MAX_FRAME_SIZE = 5;
+ /** spdy/3: Retransmission rate. Percentage */
+ static final int DOWNLOAD_RETRANS_RATE = 6;
+ /** HTTP/2: Advisory only. Size in bytes of the largest header list the sender will accept. */
+ static final int MAX_HEADER_LIST_SIZE = 6;
+ /** Window size in bytes. */
+ public static final int INITIAL_WINDOW_SIZE = 7;
+ /** spdy/3: Size of the client certificate vector. Unsupported. */
+ static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 8;
+ /** Flow control options. */
+ static final int FLOW_CONTROL_OPTIONS = 10;
+
+ /** Total number of settings. */
+ static final int COUNT = 10;
+
+ /** If set, flow control is disabled for streams directed to the sender of these settings. */
+ static final int FLOW_CONTROL_OPTIONS_DISABLED = 0x1;
+
+ /** Bitfield of which flags that values. */
+ private int set;
+
+ /** Bitfield of flags that have {@link #PERSIST_VALUE}. */
+ private int persistValue;
+
+ /** Bitfield of flags that have {@link #PERSISTED}. */
+ private int persisted;
+
+ /** Flag values. */
+ private final int[] values = new int[COUNT];
+
+ void clear() {
+ set = persistValue = persisted = 0;
+ Arrays.fill(values, 0);
+ }
+
+ public Settings set(int id, int idFlags, int value) {
+ if (id >= values.length) {
+ return this; // Discard unknown settings.
+ }
+
+ int bit = 1 << id;
+ set |= bit;
+ if ((idFlags & PERSIST_VALUE) != 0) {
+ persistValue |= bit;
+ } else {
+ persistValue &= ~bit;
+ }
+ if ((idFlags & PERSISTED) != 0) {
+ persisted |= bit;
+ } else {
+ persisted &= ~bit;
+ }
+
+ values[id] = value;
+ return this;
+ }
+
+ /** Returns true if a value has been assigned for the setting {@code id}. */
+ public boolean isSet(int id) {
+ int bit = 1 << id;
+ return (set & bit) != 0;
+ }
+
+ /** Returns the value for the setting {@code id}, or 0 if unset. */
+ public int get(int id) {
+ return values[id];
+ }
+
+ /** Returns the flags for the setting {@code id}, or 0 if unset. */
+ int flags(int id) {
+ int result = 0;
+ if (isPersisted(id)) result |= Settings.PERSISTED;
+ if (persistValue(id)) result |= Settings.PERSIST_VALUE;
+ return result;
+ }
+
+ /** Returns the number of settings that have values assigned. */
+ int size() {
+ return Integer.bitCount(set);
+ }
+
+ /** spdy/3 only. */
+ int getUploadBandwidth(int defaultValue) {
+ int bit = 1 << UPLOAD_BANDWIDTH;
+ return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue;
+ }
+
+ /** HTTP/2 only. Returns -1 if unset. */
+ int getHeaderTableSize() {
+ int bit = 1 << HEADER_TABLE_SIZE;
+ return (bit & set) != 0 ? values[HEADER_TABLE_SIZE] : -1;
+ }
+
+ /** spdy/3 only. */
+ int getDownloadBandwidth(int defaultValue) {
+ int bit = 1 << DOWNLOAD_BANDWIDTH;
+ return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue;
+ }
+
+ /** HTTP/2 only. */
+ // TODO: honor this setting in HTTP/2.
+ boolean getEnablePush(boolean defaultValue) {
+ int bit = 1 << ENABLE_PUSH;
+ return ((bit & set) != 0 ? values[ENABLE_PUSH] : defaultValue ? 1 : 0) == 1;
+ }
+
+ /** spdy/3 only. */
+ int getRoundTripTime(int defaultValue) {
+ int bit = 1 << ROUND_TRIP_TIME;
+ return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue;
+ }
+
+ // TODO: honor this setting in spdy/3 and HTTP/2.
+ int getMaxConcurrentStreams(int defaultValue) {
+ int bit = 1 << MAX_CONCURRENT_STREAMS;
+ return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue;
+ }
+
+ /** spdy/3 only. */
+ int getCurrentCwnd(int defaultValue) {
+ int bit = 1 << CURRENT_CWND;
+ return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue;
+ }
+
+ /** HTTP/2 only. */
+ int getMaxFrameSize(int defaultValue) {
+ int bit = 1 << MAX_FRAME_SIZE;
+ return (bit & set) != 0 ? values[MAX_FRAME_SIZE] : defaultValue;
+ }
+
+ /** spdy/3 only. */
+ int getDownloadRetransRate(int defaultValue) {
+ int bit = 1 << DOWNLOAD_RETRANS_RATE;
+ return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue;
+ }
+
+ /** HTTP/2 only. */
+ int getMaxHeaderListSize(int defaultValue) {
+ int bit = 1 << MAX_HEADER_LIST_SIZE;
+ return (bit & set) != 0 ? values[MAX_HEADER_LIST_SIZE] : defaultValue;
+ }
+
+ int getInitialWindowSize(int defaultValue) {
+ int bit = 1 << INITIAL_WINDOW_SIZE;
+ return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue;
+ }
+
+ /** spdy/3 only. */
+ int getClientCertificateVectorSize(int defaultValue) {
+ int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE;
+ return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue;
+ }
+
+ // TODO: honor this setting in spdy/3 and HTTP/2.
+ boolean isFlowControlDisabled() {
+ int bit = 1 << FLOW_CONTROL_OPTIONS;
+ int value = (bit & set) != 0 ? values[FLOW_CONTROL_OPTIONS] : 0;
+ return (value & FLOW_CONTROL_OPTIONS_DISABLED) != 0;
+ }
+
+ /**
+ * Returns true if this user agent should use this setting in future spdy/3
+ * connections to the same host.
+ */
+ boolean persistValue(int id) {
+ int bit = 1 << id;
+ return (persistValue & bit) != 0;
+ }
+
+ /** Returns true if this setting was persisted. */
+ boolean isPersisted(int id) {
+ int bit = 1 << id;
+ return (persisted & bit) != 0;
+ }
+
+ /**
+ * Writes {@code other} into this. If any setting is populated by this and
+ * {@code other}, the value and flags from {@code other} will be kept.
+ */
+ void merge(Settings other) {
+ for (int i = 0; i < COUNT; i++) {
+ if (!other.isSet(i)) continue;
+ set(i, other.flags(i), other.get(i));
+ }
+ }
+}
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Variant.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Variant.java
new file mode 100644
index 000000000..2b707081b
--- /dev/null
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Variant.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+/*
+ * Forked from OkHttp 2.5.0
+ */
+
+package io.grpc.okhttp.internal.framed;
+
+import io.grpc.okhttp.internal.Protocol;
+import okio.BufferedSink;
+import okio.BufferedSource;
+
+/** A version and dialect of the framed socket protocol. */
+public interface Variant {
+
+ /** The protocol as selected using ALPN. */
+ Protocol getProtocol();
+
+ /**
+ * @param client true if this is the HTTP client's reader, reading frames from a server.
+ */
+ FrameReader newReader(BufferedSource source, boolean client);
+
+ /**
+ * @param client true if this is the HTTP client's writer, writing frames to a server.
+ */
+ FrameWriter newWriter(BufferedSink sink, boolean client);
+}