Open or-else opened 6 years ago
OK, I figured it out. This is the same bug as https://github.com/TakahikoKawasaki/nv-websocket-client/issues/106
Golang's Letsencrypt implementation requires client to support SNI. Android's socket.getSession() starts handshake implicitly but does not expose exceptions if the handshake fails, just silently closes the socket (https://issuetracker.google.com/issues/37046928). The handshake fails because the server closes the connection because the client sends blank ServerName in ClientHello. And that happens because SNI is not supported as correctly pointed out in the https://github.com/TakahikoKawasaki/nv-websocket-client/issues/106
Any chance to have https://github.com/TakahikoKawasaki/nv-websocket-client/issues/106 fixed any time soon?
Beside the solution in PR #109 , another option is to add another method to WsSocketFactory which would take Socket is one of the parameters, like this:
public abstract Socket createSocket(Socket s,
String host,
int port,
boolean autoClose)
throws IOException
This way I could provide my own properly configured socket.
This issue is a show stopper for me. Please talk to me. Let me know if this can be addressed any time soon.
Or add a method WebSocket.setSocket(Socket s)
like https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/java/org/java_websocket/client/WebSocketClient.java#L487 does.
@or-else have you switched to any other library which can work properly with WSS websockets and Let's Encrypt certificates on back-end?
Yes, I've switched to https://github.com/TooTallNate/Java-WebSocket/
Android SDK version 25 in Android emulator.
I keep getting
HostnameUnverifiedException
thrown fromSocketConnector.verifyHostname(SSLSocket socket, String hostname)
at SocketConnector.java line 171 because OkHostnameVerifier.verify(String host, SSLSession session) returns false in SocketConnector.java line 164. That in turn happens becauseCertificate[] certificates = session.getPeerCertificates();
in OkHostnameVerifier.java line 64 throwsjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate
.The culprit I believe is the call
SSLSession session = socket.getSession();
in SocketConnector.java line 161 Before the call thesocket
is connected:Socket[address=api.tinode.co/104.196.16.37,port=443,localPort=54910]
during the call it gets closed:Socket[unconnected]
and the session is returned ascom.android.org.conscrypt.SSLNullSession
which obviously knows nothing about the host name.The connection is created with the default socketFactory:
See full source here: https://github.com/tinode/android-example/blob/devel/tinodesdk/src/main/java/co/tinode/tinodesdk/Connection.java
The host is secured with a Letsencrypt certificate which seems to be perfectly fine: https://www.ssllabs.com/ssltest/analyze.html?d=api.tinode.co It works fine in the browser in the same Android emulator. The websocket also works fine without the SSL.
What's going on? Is this a known issue?
Btw, because
verifyHostname
throws a customHostnameUnverifiedException
instead of re-throwingjavax.net.ssl.SSLPeerUnverifiedException
, it loses the stack trace and makes it a lot harder to debug the problem. For instance, instead of just posting the stack trace I have to write it up like this. What's the value in replacing SSLPeerUnverifiedException with a custom one?