On Android L (and probably prior releases) it is necessary to
close a socket explicitly rather than relying on
InputStream/OutputStream to do it for you.
See bug here: https://code.google.com/p/android/issues/detail?id=97564
Follow up to:
https://github.com/square/okhttp/pull/1196.
Combined with an NPN bug (18705877) on Android this is the
reason why fallback connections started failing on Android
after the COMPATIBLE_TLS was changed to be TLSv1.
[The NPN bug means that once enabled on a socket from an
SSLContext then NPN must be configured for every subsequent
socket otherwise some of the NPN state will still be set,
but some will be missing, leading to negotiation issues].
The implication of this change is that the follow up request
after a handshake failure may now be HTTP/2 or SPDY
(or HTTP/1.1). Previous to this change they would always
have been HTTP/1.1.
Previous to pull 1196 they would also have been
HTTP/1.1 because COMPATIBLE_TLS was SSLv3.
On Android getByName(null) returns the first of
[IPv6 loopback, IPv4 loopback], binding the server to ::1.
The IPv6 loopback address returns "localhost". "localhost"
does not resolve to the IPv6 address.
Instead: explicitly select "localhost" ensuring
MockWebServer binds to an IP that can be looked up by name
and should also be a loopback address.
isClosed() now means "has close() been called", after
commit ea565b2e30
it meant "has not been initialized or close() has been
called".
Introduced explicit closed state. Minor tweak to use
initialized state to determine whether cleanup will
do anything. Added a test.
okhttp-android-support contains classes needed for Android embedding and
not for normal OkHttp development. The classes here can be excluded from
okhttp-urlconnection, shrinking that artifact. More classes will be
added to this component to make Android maintenance easier.
This is a binary-compatible change, but code that currently calls
ResponseBody [contentLength()|byteStream()|source()|charStream()]
that doesn't necessarily catch or declare IOException will need
to with this change.
These methods could be performing I/O (opening streams, etc.).
Throwing IOException seems reasonable in this case.
contentType() and charset() have not been changed.
Motivation 1: Cipher selection and TLS protocol version selection
should be performed over "enabled", not "support" values. Otherwise,
ciphers / protocols that are disabled by default are re-enabled.
Android would like to avoid enabling values that are considered unsafe
and are disabled by the platform, apps or GMS core.
Motivation 2: Opinionated cipher suite selection makes sense for
OkHttp when bundled with apps. OkHttp probably has the best/newest
information available when compared with the socket factory it
encounters.
However, with the Android platform usecase the socket factory (i.e.
one from the platform, from GMS core, or installed by the app) might
have better information (or reasons why specific suites should not be
used and so it modifies the "enabled" set). Android would therefore
prefer OkHttp to select from a default set specified by the socket
factory, not a list hard-coded at release time.
Unlike ciphers, for protocols there is no current need to
go with the default enabled set so supporting "null" / "use default"
is not required for protocols.
Other change:
The ConnectionSpec caching (see supportedSpec) has been removed from
ConnectionSpec. This seems like an risky optimization to me in an
environment where different SocketFactory instances could be encountered
and doing it properly seems costly and of limited benefit.
Ultimate goal: to improve the TLS fallback behavior so that
socket connections will not be created if the necessary
TLS protocols will not be supported.
To achieve this RouteSelector will be moved into Connection
and so that it can be passed the Socket or protocol information
during the route selection process.
This is a small first step: Make RouteSelector independent
of Connection so that it can later be moved inside of
Connection. It puts the RouteSelector interface in terms
of Routes, which seems logical.