• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.okhttp;
18 
19 import com.google.common.base.Preconditions;
20 import io.grpc.InternalChannelz;
21 import io.grpc.InternalMetadata;
22 import io.grpc.Metadata;
23 import io.grpc.internal.TransportFrameUtil;
24 import io.grpc.okhttp.internal.CipherSuite;
25 import io.grpc.okhttp.internal.ConnectionSpec;
26 import io.grpc.okhttp.internal.framed.Header;
27 import java.net.Socket;
28 import java.net.SocketException;
29 import java.util.List;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32 
33 /**
34  * Common utility methods for OkHttp transport.
35  */
36 class Utils {
37   private static final Logger log = Logger.getLogger(Utils.class.getName());
38 
39   static final int DEFAULT_WINDOW_SIZE = 65535;
40   static final int CONNECTION_STREAM_ID = 0;
41 
convertHeaders(List<Header> http2Headers)42   public static Metadata convertHeaders(List<Header> http2Headers) {
43     return InternalMetadata.newMetadata(convertHeadersToArray(http2Headers));
44   }
45 
convertTrailers(List<Header> http2Headers)46   public static Metadata convertTrailers(List<Header> http2Headers) {
47     return InternalMetadata.newMetadata(convertHeadersToArray(http2Headers));
48   }
49 
convertHeadersToArray(List<Header> http2Headers)50   private static byte[][] convertHeadersToArray(List<Header> http2Headers) {
51     byte[][] headerValues = new byte[http2Headers.size() * 2][];
52     int i = 0;
53     for (Header header : http2Headers) {
54       headerValues[i++] = header.name.toByteArray();
55       headerValues[i++] = header.value.toByteArray();
56     }
57     return TransportFrameUtil.toRawSerializedHeaders(headerValues);
58   }
59 
60   /**
61    * Converts an instance of {@link com.squareup.okhttp.ConnectionSpec} for a secure connection into
62    * that of {@link ConnectionSpec} in the current package.
63    *
64    * @throws IllegalArgumentException
65    *         If {@code spec} is not with TLS
66    */
convertSpec(com.squareup.okhttp.ConnectionSpec spec)67   static ConnectionSpec convertSpec(com.squareup.okhttp.ConnectionSpec spec) {
68     Preconditions.checkArgument(spec.isTls(), "plaintext ConnectionSpec is not accepted");
69 
70     List<com.squareup.okhttp.TlsVersion> tlsVersionList = spec.tlsVersions();
71     String[] tlsVersions = new String[tlsVersionList.size()];
72     for (int i = 0; i < tlsVersions.length; i++) {
73       tlsVersions[i] = tlsVersionList.get(i).javaName();
74     }
75 
76     List<com.squareup.okhttp.CipherSuite> cipherSuiteList = spec.cipherSuites();
77     CipherSuite[] cipherSuites = new CipherSuite[cipherSuiteList.size()];
78     for (int i = 0; i < cipherSuites.length; i++) {
79       cipherSuites[i] = CipherSuite.valueOf(cipherSuiteList.get(i).name());
80     }
81 
82     return new ConnectionSpec.Builder(spec.isTls())
83         .supportsTlsExtensions(spec.supportsTlsExtensions())
84         .tlsVersions(tlsVersions)
85         .cipherSuites(cipherSuites)
86         .build();
87   }
88 
89   /**
90    * Attempts to capture all known socket options and return the results as a
91    * {@link InternalChannelz.SocketOptions}. If getting a socket option threw an exception,
92    * log the error to the logger and report the value as an error in the response.
93    */
getSocketOptions(Socket socket)94   static InternalChannelz.SocketOptions getSocketOptions(Socket socket) {
95     InternalChannelz.SocketOptions.Builder builder = new InternalChannelz.SocketOptions.Builder();
96     try {
97       builder.setSocketOptionLingerSeconds(socket.getSoLinger());
98     } catch (SocketException e) {
99       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
100       builder.addOption("SO_LINGER", "channelz_internal_error");
101     }
102 
103     try {
104       builder.setSocketOptionTimeoutMillis(socket.getSoTimeout());
105     } catch (Exception e) {
106       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
107       builder.addOption("SO_TIMEOUT", "channelz_internal_error");
108     }
109 
110     try {
111       builder.addOption("TCP_NODELAY", socket.getTcpNoDelay());
112     } catch (SocketException e) {
113       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
114       builder.addOption("TCP_NODELAY", "channelz_internal_error");
115     }
116 
117     try {
118       builder.addOption("SO_REUSEADDR", socket.getReuseAddress());
119     } catch (SocketException e) {
120       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
121       builder.addOption("SO_REUSEADDR", "channelz_internal_error");
122     }
123 
124     try {
125       builder.addOption("SO_SNDBUF", socket.getSendBufferSize());
126     } catch (SocketException e) {
127       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
128       builder.addOption("SO_SNDBUF", "channelz_internal_error");
129     }
130 
131     try {
132       builder.addOption("SO_RECVBUF", socket.getReceiveBufferSize());
133     } catch (SocketException e) {
134       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
135       builder.addOption("SO_RECVBUF", "channelz_internal_error");
136     }
137 
138     try {
139       builder.addOption("SO_KEEPALIVE", socket.getKeepAlive());
140     } catch (SocketException e) {
141       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
142       builder.addOption("SO_KEEPALIVE", "channelz_internal_error");
143     }
144 
145     try {
146       builder.addOption("SO_OOBINLINE", socket.getOOBInline());
147     } catch (SocketException e) {
148       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
149       builder.addOption("SO_OOBINLINE", "channelz_internal_error");
150     }
151 
152     try {
153       builder.addOption("IP_TOS", socket.getTrafficClass());
154     } catch (SocketException e) {
155       log.log(Level.SEVERE, "Exception caught while reading socket option", e);
156       builder.addOption("IP_TOS", "channelz_internal_error");
157     }
158     return builder.build();
159   }
160 
Utils()161   private Utils() {
162     // Prevents instantiation
163   }
164 }
165