Reputation: 819
I was having troubles with https request after update my app to api 21. After a deep code review I found a funny bug.
My app has been compiled with api-21 now, and this api has a new version of okHttp inside the sdk, version 2.2.0. The old version of the app used the version of okHttp 2.0.0.
With the version 2.2.0 I have an exception when I try open a new https request. the exception is:
java.net.SocketException: Unconnected sockets not implemented
at javax.net.SocketFactory.createSocket(SocketFactory.java:64)
at com.squareup.okhttp.Connection.connect(Connection.java:144)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:169)
at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:119)
at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:134)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:314)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:237)
at com.squareup.okhttp.Call.getResponse(Call.java:233)
at com.squareup.okhttp.Call.execute(Call.java:84)
The problem is okHttp changed the way that Connection class works on version 2.1.0. On version 2.0.0 the connection create a new plain Socket directly but know the request this socket to the socket factory this socket will be upgrade to a TLS. The change is:
socket = route.address.socketFactory.createSocket();
My problem is that I have overrited the socketFactory for NotHttpSocketFactory, and this implementation does nothing (it's ok, you want remove http connections) and the method createSocket(), has not been overrited. I dont like allow http requests.
And I override the SocketFactory.
client.setSocketFactory(new BlackphoneStubSocketFactory());
I don't understand why I need a plain socket, with I'm creating a https requests. Is this necessary? I can override the method createSocket() and return an empty socket, but it is necessary or it is a bug on OkHttp.
Upvotes: 4
Views: 3886
Reputation: 2115
Make sure that you define createSocket() on your custom factory.
val httpClient = OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
.socketFactory(object: SocketFactory() {
val factory = SocketFactory.getDefault()
override fun createSocket(): Socket {
return wrap(factory.createSocket())
}
override fun createSocket(p0: String?, p1: Int): Socket {
return wrap(factory.createSocket(p0, p1))
}
override fun createSocket(p0: InetAddress?, p1: Int): Socket {
return wrap(factory.createSocket(p0, p1))
}
override fun createSocket(p0: String?, p1: Int, p2: InetAddress?, p3: Int): Socket {
return wrap(factory.createSocket(p0, p1, p2, p3))
}
override fun createSocket(p0: InetAddress?, p1: Int, p2: InetAddress?, p3: Int): Socket {
return wrap(factory.createSocket(p0, p1, p2, p3))
}
private fun wrap(s: Socket): Socket {
s.receiveBufferSize = 32*1024*1024
return s
}
})
.build()
Upvotes: 2
Reputation: 40623
If you want to do this with OkHttp 2.2, use ConnectionSpec
to disable plaintext connections. For example:
client.setConnectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS));
This will drop support for cleartext connections, and also TLS fallbacks.
Upvotes: 0