mirror of https://github.com/grpc/grpc-java.git
Reduce OkHttp dependency, copy all the needed files into our repository.
This commit is contained in:
parent
6d296e84b6
commit
b121c46b42
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/'
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
@ -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;
|
||||
|
|
@ -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 =
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
95
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java
vendored
Normal file
95
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/ErrorCode.java
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
141
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java
vendored
Normal file
141
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameReader.java
vendored
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
107
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java
vendored
Normal file
107
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/FrameWriter.java
vendored
Normal file
|
@ -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;
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
53
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java
vendored
Normal file
53
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/HeadersMode.java
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
242
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java
vendored
Normal file
242
okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/framed/Settings.java
vendored
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue