• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Square, Inc.
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 package com.squareup.okhttp;
17 
18 import com.squareup.okhttp.internal.Internal;
19 import com.squareup.okhttp.internal.InternalCache;
20 import com.squareup.okhttp.internal.RouteDatabase;
21 import com.squareup.okhttp.internal.Util;
22 import com.squareup.okhttp.internal.http.AuthenticatorAdapter;
23 import com.squareup.okhttp.internal.http.StreamAllocation;
24 import com.squareup.okhttp.internal.io.RealConnection;
25 import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
26 import java.net.CookieHandler;
27 import java.net.MalformedURLException;
28 import java.net.Proxy;
29 import java.net.ProxySelector;
30 import java.net.URLConnection;
31 import java.net.UnknownHostException;
32 import java.security.GeneralSecurityException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.concurrent.TimeUnit;
36 import javax.net.SocketFactory;
37 import javax.net.ssl.HostnameVerifier;
38 import javax.net.ssl.SSLContext;
39 import javax.net.ssl.SSLSocket;
40 import javax.net.ssl.SSLSocketFactory;
41 
42 /**
43  * Configures and creates HTTP connections. Most applications can use a single
44  * OkHttpClient for all of their HTTP requests - benefiting from a shared
45  * response cache, thread pool, connection re-use, etc.
46  *
47  * <p>Instances of OkHttpClient are intended to be fully configured before they're
48  * shared - once shared they should be treated as immutable and can safely be used
49  * to concurrently open new connections. If required, threads can call
50  * {@link #clone()} to make a shallow copy of the OkHttpClient that can be
51  * safely modified with further configuration changes.
52  */
53 public class OkHttpClient implements Cloneable {
54   private static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(
55       Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1);
56 
57   private static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
58       ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT);
59 
60   static {
61     Internal.instance = new Internal() {
62       @Override public void addLenient(Headers.Builder builder, String line) {
63         builder.addLenient(line);
64       }
65 
66       @Override public void addLenient(Headers.Builder builder, String name, String value) {
67         builder.addLenient(name, value);
68       }
69 
70       @Override public void setCache(OkHttpClient client, InternalCache internalCache) {
71         client.setInternalCache(internalCache);
72       }
73 
74       @Override public InternalCache internalCache(OkHttpClient client) {
75         return client.internalCache();
76       }
77 
78       @Override public boolean connectionBecameIdle(
79           ConnectionPool pool, RealConnection connection) {
80         return pool.connectionBecameIdle(connection);
81       }
82 
83       @Override public RealConnection get(
84           ConnectionPool pool, Address address, StreamAllocation streamAllocation) {
85         return pool.get(address, streamAllocation);
86       }
87 
88       @Override public void put(ConnectionPool pool, RealConnection connection) {
89         pool.put(connection);
90       }
91 
92       @Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) {
93         return connectionPool.routeDatabase;
94       }
95 
96       @Override
97       public void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket) {
98         call.enqueue(responseCallback, forWebSocket);
99       }
100 
101       @Override public StreamAllocation callEngineGetStreamAllocation(Call call) {
102         return call.engine.streamAllocation;
103       }
104 
105       @Override
106       public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) {
107         tlsConfiguration.apply(sslSocket, isFallback);
108       }
109 
110       @Override public HttpUrl getHttpUrlChecked(String url)
111           throws MalformedURLException, UnknownHostException {
112         return HttpUrl.getChecked(url);
113       }
114     };
115   }
116 
117   /** Lazily-initialized. */
118   private static SSLSocketFactory defaultSslSocketFactory;
119 
120   private final RouteDatabase routeDatabase;
121   private Dispatcher dispatcher;
122   private Proxy proxy;
123   private List<Protocol> protocols;
124   private List<ConnectionSpec> connectionSpecs;
125   private final List<Interceptor> interceptors = new ArrayList<>();
126   private final List<Interceptor> networkInterceptors = new ArrayList<>();
127   private ProxySelector proxySelector;
128   private CookieHandler cookieHandler;
129 
130   /** Non-null if this client is caching; possibly by {@code cache}. */
131   private InternalCache internalCache;
132   private Cache cache;
133 
134   private SocketFactory socketFactory;
135   private SSLSocketFactory sslSocketFactory;
136   private HostnameVerifier hostnameVerifier;
137   private CertificatePinner certificatePinner;
138   private Authenticator authenticator;
139   private ConnectionPool connectionPool;
140   private Dns dns;
141   private boolean followSslRedirects = true;
142   private boolean followRedirects = true;
143   private boolean retryOnConnectionFailure = true;
144   private int connectTimeout = 10_000;
145   private int readTimeout = 10_000;
146   private int writeTimeout = 10_000;
147 
OkHttpClient()148   public OkHttpClient() {
149     routeDatabase = new RouteDatabase();
150     dispatcher = new Dispatcher();
151   }
152 
OkHttpClient(OkHttpClient okHttpClient)153   private OkHttpClient(OkHttpClient okHttpClient) {
154     this.routeDatabase = okHttpClient.routeDatabase;
155     this.dispatcher = okHttpClient.dispatcher;
156     this.proxy = okHttpClient.proxy;
157     this.protocols = okHttpClient.protocols;
158     this.connectionSpecs = okHttpClient.connectionSpecs;
159     this.interceptors.addAll(okHttpClient.interceptors);
160     this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
161     this.proxySelector = okHttpClient.proxySelector;
162     this.cookieHandler = okHttpClient.cookieHandler;
163     this.cache = okHttpClient.cache;
164     this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache;
165     this.socketFactory = okHttpClient.socketFactory;
166     this.sslSocketFactory = okHttpClient.sslSocketFactory;
167     this.hostnameVerifier = okHttpClient.hostnameVerifier;
168     this.certificatePinner = okHttpClient.certificatePinner;
169     this.authenticator = okHttpClient.authenticator;
170     this.connectionPool = okHttpClient.connectionPool;
171     this.dns = okHttpClient.dns;
172     this.followSslRedirects = okHttpClient.followSslRedirects;
173     this.followRedirects = okHttpClient.followRedirects;
174     this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
175     this.connectTimeout = okHttpClient.connectTimeout;
176     this.readTimeout = okHttpClient.readTimeout;
177     this.writeTimeout = okHttpClient.writeTimeout;
178   }
179 
180   /**
181    * Sets the default connect timeout for new connections. A value of 0 means no timeout, otherwise
182    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
183    *
184    * @see URLConnection#setConnectTimeout(int)
185    */
setConnectTimeout(long timeout, TimeUnit unit)186   public void setConnectTimeout(long timeout, TimeUnit unit) {
187     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
188     if (unit == null) throw new IllegalArgumentException("unit == null");
189     long millis = unit.toMillis(timeout);
190     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
191     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
192     connectTimeout = (int) millis;
193   }
194 
195   /** Default connect timeout (in milliseconds). */
getConnectTimeout()196   public int getConnectTimeout() {
197     return connectTimeout;
198   }
199 
200   /**
201    * Sets the default read timeout for new connections. A value of 0 means no timeout, otherwise
202    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
203    *
204    * @see URLConnection#setReadTimeout(int)
205    */
setReadTimeout(long timeout, TimeUnit unit)206   public void setReadTimeout(long timeout, TimeUnit unit) {
207     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
208     if (unit == null) throw new IllegalArgumentException("unit == null");
209     long millis = unit.toMillis(timeout);
210     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
211     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
212     readTimeout = (int) millis;
213   }
214 
215   /** Default read timeout (in milliseconds). */
getReadTimeout()216   public int getReadTimeout() {
217     return readTimeout;
218   }
219 
220   /**
221    * Sets the default write timeout for new connections. A value of 0 means no timeout, otherwise
222    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
223    */
setWriteTimeout(long timeout, TimeUnit unit)224   public void setWriteTimeout(long timeout, TimeUnit unit) {
225     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
226     if (unit == null) throw new IllegalArgumentException("unit == null");
227     long millis = unit.toMillis(timeout);
228     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
229     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
230     writeTimeout = (int) millis;
231   }
232 
233   /** Default write timeout (in milliseconds). */
getWriteTimeout()234   public int getWriteTimeout() {
235     return writeTimeout;
236   }
237 
238   /**
239    * Sets the HTTP proxy that will be used by connections created by this
240    * client. This takes precedence over {@link #setProxySelector}, which is
241    * only honored when this proxy is null (which it is by default). To disable
242    * proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
243    */
setProxy(Proxy proxy)244   public OkHttpClient setProxy(Proxy proxy) {
245     this.proxy = proxy;
246     return this;
247   }
248 
getProxy()249   public Proxy getProxy() {
250     return proxy;
251   }
252 
253   /**
254    * Sets the proxy selection policy to be used if no {@link #setProxy proxy}
255    * is specified explicitly. The proxy selector may return multiple proxies;
256    * in that case they will be tried in sequence until a successful connection
257    * is established.
258    *
259    * <p>If unset, the {@link ProxySelector#getDefault() system-wide default}
260    * proxy selector will be used.
261    */
setProxySelector(ProxySelector proxySelector)262   public OkHttpClient setProxySelector(ProxySelector proxySelector) {
263     this.proxySelector = proxySelector;
264     return this;
265   }
266 
getProxySelector()267   public ProxySelector getProxySelector() {
268     return proxySelector;
269   }
270 
271   /**
272    * Sets the cookie handler to be used to read outgoing cookies and write
273    * incoming cookies.
274    *
275    * <p>If unset, the {@link CookieHandler#getDefault() system-wide default}
276    * cookie handler will be used.
277    */
setCookieHandler(CookieHandler cookieHandler)278   public OkHttpClient setCookieHandler(CookieHandler cookieHandler) {
279     this.cookieHandler = cookieHandler;
280     return this;
281   }
282 
getCookieHandler()283   public CookieHandler getCookieHandler() {
284     return cookieHandler;
285   }
286 
287   /** Sets the response cache to be used to read and write cached responses. */
setInternalCache(InternalCache internalCache)288   void setInternalCache(InternalCache internalCache) {
289     this.internalCache = internalCache;
290     this.cache = null;
291   }
292 
internalCache()293   InternalCache internalCache() {
294     return internalCache;
295   }
296 
setCache(Cache cache)297   public OkHttpClient setCache(Cache cache) {
298     this.cache = cache;
299     this.internalCache = null;
300     return this;
301   }
302 
getCache()303   public Cache getCache() {
304     return cache;
305   }
306 
307   /**
308    * Sets the DNS service used to lookup IP addresses for hostnames.
309    *
310    * <p>If unset, the {@link Dns#SYSTEM system-wide default} DNS will be used.
311    */
setDns(Dns dns)312   public OkHttpClient setDns(Dns dns) {
313     this.dns = dns;
314     return this;
315   }
316 
getDns()317   public Dns getDns() {
318     return dns;
319   }
320 
321   /**
322    * Sets the socket factory used to create connections. OkHttp only uses
323    * the parameterless {@link SocketFactory#createSocket() createSocket()}
324    * method to create unconnected sockets. Overriding this method,
325    * e. g., allows the socket to be bound to a specific local address.
326    *
327    * <p>If unset, the {@link SocketFactory#getDefault() system-wide default}
328    * socket factory will be used.
329    */
setSocketFactory(SocketFactory socketFactory)330   public OkHttpClient setSocketFactory(SocketFactory socketFactory) {
331     this.socketFactory = socketFactory;
332     return this;
333   }
334 
getSocketFactory()335   public SocketFactory getSocketFactory() {
336     return socketFactory;
337   }
338 
339   /**
340    * Sets the socket factory used to secure HTTPS connections.
341    *
342    * <p>If unset, a lazily created SSL socket factory will be used.
343    */
setSslSocketFactory(SSLSocketFactory sslSocketFactory)344   public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
345     this.sslSocketFactory = sslSocketFactory;
346     return this;
347   }
348 
getSslSocketFactory()349   public SSLSocketFactory getSslSocketFactory() {
350     return sslSocketFactory;
351   }
352 
353   /**
354    * Sets the verifier used to confirm that response certificates apply to
355    * requested hostnames for HTTPS connections.
356    *
357    * <p>If unset, a default hostname verifier will be used.
358    */
setHostnameVerifier(HostnameVerifier hostnameVerifier)359   public OkHttpClient setHostnameVerifier(HostnameVerifier hostnameVerifier) {
360     this.hostnameVerifier = hostnameVerifier;
361     return this;
362   }
363 
getHostnameVerifier()364   public HostnameVerifier getHostnameVerifier() {
365     return hostnameVerifier;
366   }
367 
368   /**
369    * Sets the certificate pinner that constrains which certificates are trusted.
370    * By default HTTPS connections rely on only the {@link #setSslSocketFactory
371    * SSL socket factory} to establish trust. Pinning certificates avoids the
372    * need to trust certificate authorities.
373    */
setCertificatePinner(CertificatePinner certificatePinner)374   public OkHttpClient setCertificatePinner(CertificatePinner certificatePinner) {
375     this.certificatePinner = certificatePinner;
376     return this;
377   }
378 
getCertificatePinner()379   public CertificatePinner getCertificatePinner() {
380     return certificatePinner;
381   }
382 
383   /**
384    * Sets the authenticator used to respond to challenges from the remote web
385    * server or proxy server.
386    *
387    * <p>If unset, the {@link java.net.Authenticator#setDefault system-wide default}
388    * authenticator will be used.
389    */
setAuthenticator(Authenticator authenticator)390   public OkHttpClient setAuthenticator(Authenticator authenticator) {
391     this.authenticator = authenticator;
392     return this;
393   }
394 
getAuthenticator()395   public Authenticator getAuthenticator() {
396     return authenticator;
397   }
398 
399   /**
400    * Sets the connection pool used to recycle HTTP and HTTPS connections.
401    *
402    * <p>If unset, the {@link ConnectionPool#getDefault() system-wide
403    * default} connection pool will be used.
404    */
setConnectionPool(ConnectionPool connectionPool)405   public OkHttpClient setConnectionPool(ConnectionPool connectionPool) {
406     this.connectionPool = connectionPool;
407     return this;
408   }
409 
getConnectionPool()410   public ConnectionPool getConnectionPool() {
411     return connectionPool;
412   }
413 
414   /**
415    * Configure this client to follow redirects from HTTPS to HTTP and from HTTP
416    * to HTTPS.
417    *
418    * <p>If unset, protocol redirects will be followed. This is different than
419    * the built-in {@code HttpURLConnection}'s default.
420    */
setFollowSslRedirects(boolean followProtocolRedirects)421   public OkHttpClient setFollowSslRedirects(boolean followProtocolRedirects) {
422     this.followSslRedirects = followProtocolRedirects;
423     return this;
424   }
425 
getFollowSslRedirects()426   public boolean getFollowSslRedirects() {
427     return followSslRedirects;
428   }
429 
430   /** Configure this client to follow redirects. If unset, redirects be followed. */
setFollowRedirects(boolean followRedirects)431   public void setFollowRedirects(boolean followRedirects) {
432     this.followRedirects = followRedirects;
433   }
434 
getFollowRedirects()435   public boolean getFollowRedirects() {
436     return followRedirects;
437   }
438 
439   /**
440    * Configure this client to retry or not when a connectivity problem is encountered. By default,
441    * this client silently recovers from the following problems:
442    *
443    * <ul>
444    *   <li><strong>Unreachable IP addresses.</strong> If the URL's host has multiple IP addresses,
445    *       failure to reach any individual IP address doesn't fail the overall request. This can
446    *       increase availability of multi-homed services.
447    *   <li><strong>Stale pooled connections.</strong> The {@link ConnectionPool} reuses sockets
448    *       to decrease request latency, but these connections will occasionally time out.
449    *   <li><strong>Unreachable proxy servers.</strong> A {@link ProxySelector} can be used to
450    *       attempt multiple proxy servers in sequence, eventually falling back to a direct
451    *       connection.
452    * </ul>
453    *
454    * Set this to false to avoid retrying requests when doing so is destructive. In this case the
455    * calling application should do its own recovery of connectivity failures.
456    */
setRetryOnConnectionFailure(boolean retryOnConnectionFailure)457   public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
458     this.retryOnConnectionFailure = retryOnConnectionFailure;
459   }
460 
getRetryOnConnectionFailure()461   public boolean getRetryOnConnectionFailure() {
462     return retryOnConnectionFailure;
463   }
464 
routeDatabase()465   RouteDatabase routeDatabase() {
466     return routeDatabase;
467   }
468 
469   /**
470    * Sets the dispatcher used to set policy and execute asynchronous requests.
471    * Must not be null.
472    */
setDispatcher(Dispatcher dispatcher)473   public OkHttpClient setDispatcher(Dispatcher dispatcher) {
474     if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null");
475     this.dispatcher = dispatcher;
476     return this;
477   }
478 
getDispatcher()479   public Dispatcher getDispatcher() {
480     return dispatcher;
481   }
482 
483   /**
484    * Configure the protocols used by this client to communicate with remote
485    * servers. By default this client will prefer the most efficient transport
486    * available, falling back to more ubiquitous protocols. Applications should
487    * only call this method to avoid specific compatibility problems, such as web
488    * servers that behave incorrectly when SPDY is enabled.
489    *
490    * <p>The following protocols are currently supported:
491    * <ul>
492    *   <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
493    *   <li><a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">spdy/3.1</a>
494    *   <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-17">h2</a>
495    * </ul>
496    *
497    * <p><strong>This is an evolving set.</strong> Future releases include
498    * support for transitional protocols. The http/1.1 transport will never be
499    * dropped.
500    *
501    * <p>If multiple protocols are specified, <a
502    * href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a>
503    * will be used to negotiate a transport.
504    *
505    * <p>{@link Protocol#HTTP_1_0} is not supported in this set. Requests are
506    * initiated with {@code HTTP/1.1} only. If the server responds with {@code
507    * HTTP/1.0}, that will be exposed by {@link Response#protocol()}.
508    *
509    * @param protocols the protocols to use, in order of preference. The list
510    *     must contain {@link Protocol#HTTP_1_1}. It must not contain null or
511    *     {@link Protocol#HTTP_1_0}.
512    */
setProtocols(List<Protocol> protocols)513   public OkHttpClient setProtocols(List<Protocol> protocols) {
514     protocols = Util.immutableList(protocols);
515     if (!protocols.contains(Protocol.HTTP_1_1)) {
516       throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
517     }
518     if (protocols.contains(Protocol.HTTP_1_0)) {
519       throw new IllegalArgumentException("protocols must not contain http/1.0: " + protocols);
520     }
521     if (protocols.contains(null)) {
522       throw new IllegalArgumentException("protocols must not contain null");
523     }
524     this.protocols = Util.immutableList(protocols);
525     return this;
526   }
527 
getProtocols()528   public List<Protocol> getProtocols() {
529     return protocols;
530   }
531 
setConnectionSpecs(List<ConnectionSpec> connectionSpecs)532   public OkHttpClient setConnectionSpecs(List<ConnectionSpec> connectionSpecs) {
533     this.connectionSpecs = Util.immutableList(connectionSpecs);
534     return this;
535   }
536 
getConnectionSpecs()537   public List<ConnectionSpec> getConnectionSpecs() {
538     return connectionSpecs;
539   }
540 
541   /**
542    * Returns a modifiable list of interceptors that observe the full span of each call: from before
543    * the connection is established (if any) until after the response source is selected (either the
544    * origin server, cache, or both).
545    */
interceptors()546   public List<Interceptor> interceptors() {
547     return interceptors;
548   }
549 
550   /**
551    * Returns a modifiable list of interceptors that observe a single network request and response.
552    * These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error for
553    * a network interceptor to short-circuit or repeat a network request.
554    */
networkInterceptors()555   public List<Interceptor> networkInterceptors() {
556     return networkInterceptors;
557   }
558 
559   /**
560    * Prepares the {@code request} to be executed at some point in the future.
561    */
newCall(Request request)562   public Call newCall(Request request) {
563     return new Call(this, request);
564   }
565 
566   /**
567    * Cancels all scheduled or in-flight calls tagged with {@code tag}. Requests
568    * that are already complete cannot be canceled.
569    */
cancel(Object tag)570   public OkHttpClient cancel(Object tag) {
571     getDispatcher().cancel(tag);
572     return this;
573   }
574 
575   /**
576    * Returns a shallow copy of this OkHttpClient that uses the system-wide
577    * default for each field that hasn't been explicitly configured.
578    */
copyWithDefaults()579   OkHttpClient copyWithDefaults() {
580     OkHttpClient result = new OkHttpClient(this);
581     if (result.proxySelector == null) {
582       result.proxySelector = ProxySelector.getDefault();
583     }
584     if (result.cookieHandler == null) {
585       result.cookieHandler = CookieHandler.getDefault();
586     }
587     if (result.socketFactory == null) {
588       result.socketFactory = SocketFactory.getDefault();
589     }
590     if (result.sslSocketFactory == null) {
591       result.sslSocketFactory = getDefaultSSLSocketFactory();
592     }
593     if (result.hostnameVerifier == null) {
594       result.hostnameVerifier = OkHostnameVerifier.INSTANCE;
595     }
596     if (result.certificatePinner == null) {
597       result.certificatePinner = CertificatePinner.DEFAULT;
598     }
599     if (result.authenticator == null) {
600       result.authenticator = AuthenticatorAdapter.INSTANCE;
601     }
602     if (result.connectionPool == null) {
603       result.connectionPool = ConnectionPool.getDefault();
604     }
605     if (result.protocols == null) {
606       result.protocols = DEFAULT_PROTOCOLS;
607     }
608     if (result.connectionSpecs == null) {
609       result.connectionSpecs = DEFAULT_CONNECTION_SPECS;
610     }
611     if (result.dns == null) {
612       result.dns = Dns.SYSTEM;
613     }
614     return result;
615   }
616 
617   /**
618    * Java and Android programs default to using a single global SSL context,
619    * accessible to HTTP clients as {@link SSLSocketFactory#getDefault()}. If we
620    * used the shared SSL context, when OkHttp enables ALPN for its SPDY-related
621    * stuff, it would also enable ALPN for other usages, which might crash them
622    * because ALPN is enabled when it isn't expected to be.
623    *
624    * <p>This code avoids that by defaulting to an OkHttp-created SSL context.
625    * The drawback of this approach is that apps that customize the global SSL
626    * context will lose these customizations.
627    */
getDefaultSSLSocketFactory()628   private synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
629     if (defaultSslSocketFactory == null) {
630       try {
631         SSLContext sslContext = SSLContext.getInstance("TLS");
632         sslContext.init(null, null, null);
633         defaultSslSocketFactory = sslContext.getSocketFactory();
634       } catch (GeneralSecurityException e) {
635         throw new AssertionError(); // The system has no TLS. Just give up.
636       }
637     }
638     return defaultSslSocketFactory;
639   }
640 
641   /** Returns a shallow copy of this OkHttpClient. */
clone()642   @Override public OkHttpClient clone() {
643     return new OkHttpClient(this);
644   }
645 }
646