Closed KieranWebber closed 3 years ago
We encounter similar issue as well. We also use SSL and the protocol is never upgraded to websocket.
I managed to get it to upgrade of https on a emulator only after passing it a ssl context that accepted all certs. However when tested on a actual device it still failed to upgrade
I'm not sure, but it seems some preparations are required for Android according to README of Java-WebSocket.
https://github.com/TooTallNate/Java-WebSocket#wss-support http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/
I'll give that another go but my ssl cert is trusted by default by Android. So it would seem odd that I have to provide it to the Trust store
CarbonAssassin, did you have any luck on this issue? We did some experiments and noticed that connection over HTTP works perfectly fine( upgrading to websocket). But once we switched it to SSL, it never upgrades, and stays in xhr polling. FYI, my ssl cert is trusted by default by Android as well
It looks Java-WebSocket has some issues for SSL like https://github.com/TooTallNate/Java-WebSocket/issues/293. Are they applicable to you?
We are currently using Android 4.3, so the above issue is not applicable to our situation. I did some tracing and notice something interesting. For now, we use a commercial ssl certificate, and I have the following setup :
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, null, null);
IO.setDefaultSSLContext(sc);
IO.Options opts = new IO.Options();
opts.secure = true;
opts.sslContext = sc;
socket = IO.socket("https://www.myapp.xxx", opts);
With the above, I do see that Websocket instance gets called (WebSocket.java), and it tries to connect with the following : Line 100 : this.ws.connect();
However, right after it calls connect(), the onClose() method gets called, and the error message is com.android.org.conscrypt.OpenSSLSessionImpl cannot be cast to com.android.org.conscrypt.SSLSessionImpl
With a HTTP connection, the onOpen() method would get called instead, and websocket is upgraded successfully...
Is there anything wrong with my SSLContext setup steps? Again, thanks for your help
@Alex--Kang https://github.com/TooTallNate/Java-WebSocket/issues/141 looks resemble.
ok . good news.
After trying all the possible work-arounds ( btw, http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/ didn't work for me either.. ), i decided to look into the source code and found the following.
In Java-WebSocket-master, it provides a SSLClientExample.java and it shows that we should assign the SSLContext with:
SSLContext sslContext = null;
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
// sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();
chatclient.setSocket( factory.createSocket() );
chatclient.connectBlocking();
So, instead of using Java-websocket-1.3.0.jar, i replaced it with the latest source code( commit # 05d2e2). Also, I modified the WebSocket.java (/engineio/client/transports) with :
if (this.sslContext != null) {
//this.ws.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(this.sslContext));
SSLSocketFactory factory = sslContext.getSocketFactory();
try {
ws.setSocket(factory.createSocket());
}
catch (Exception e)
{
e.printStackTrace();
}
}
And in my android client, I simply use the default setting
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, null, null);
IO.Options opts = new IO.Options();
opts.secure = true;
opts.sslContext = sc;
socket = IO.socket(url, opts);
With these modifications, socketio connects successfully and the websocket would upgrade correctly without giving errors.
I noticed that the latest "release" of Java-websocket is 1.3 as of April, 2013, and the above changes was introduced in Sept, 2013. (https://github.com/TooTallNate/Java-WebSocket/commit/9b0a4b8c182bbe3f384d8ee8ede54eb754900bf5?diff=unified) I wonder what's the best way to tackle this problem. Would you consider fork your own java-websocket and fix from there? or wait for the next release of jws
Thanks
@Alex--Kang good news! I'm waiting update of the lib, thought it would not be released in the near feature :(
@nkzawa I am also wondering why the author doesn't bump up the jar version while actually he's still actively developing it. In this case, is it possible for you to grab the latest source of Java-WebSocket instead of its outdated 1.3 jar file in engine.io? It does fix our SSL issue.
@dytsai I'm not thinking to do that for now since not sure the latest source of master branch is stable enough or not. If you are using a build system like Gradle or Maven, I believe you can override the version of the dependency if you need. Though it would be troublesome :(
That's what we did and how we finally got it working. However, like you said, it's gonna be very troublesome without fully tested. It's not socket.io client, not engine.io but the underlying Java websocket library. Now we are really stuck here sigh.
I have a Wireshark trace of a Java Desktop app attempting an HTTPS connect to a NodeJS SocketIO server, and it shows the websocket-upgrade request is transmitted as plain-text, while XHR polling requests are encrypted.
Sadly, I don't think sharing the trace would be much help without my TLS key for decode.
However, the following ladder diagrams attempts to detail my observation: 1) encrypted XHR poll exchange to port 8080
[----------Client----------] [----------Server:8080-----------]
SYN ->
<- SYN,ACK
ACK ->
TLSv1.2(ClientHello) ->
<- ACK
<- TLSv1.2(ServerHello)
<- TLSv1.2(Certificate)
ACK ->
TLSv1.2(ClientKeyExchange) ->
TLSv1.2(ChangeCipherSpec) ->
TLSv1.2(Finished) ->
<- ACK
<- TLSv1.2(ChangeCipherSpec,Finished)
TLS(GET /socket.io/..etc) ->
<- HTTP(200 OK)
TLSv1.2(Alert,Warning:Close) ->
FIN,ACK ->
<- FIN,ACK
ACK ->
2) plain-text websocket-upgrade to port 8080
[----------Client----------] [----------Server:8080-----------]
SYN ->
<- SYN,ACK
ACK ->
PLAIN(GET /socket.io/..etc) ->
<- ACK
RST,ACK ->
Anybody else think this might be relevant?
Maybe we should replace Java-WebSocket with OkHttp I've tried to use latest API, and it works https://github.com/nkzawa/engine.io-client.java/pull/14
Ambivalence to my earlier post suggests the observation was old news.
Cutting past the socket.io level, my investigation at the engine.io level using a basic NodeJS script has pointed me to Java-WebSocket as the cause of the https upgrade failure, explaining the discussions around JW and a possible switch to OkHttp. Please correct me if I'm wrong.
My interest is in using socket.io-client.java over https from within a Windows desktop Java app, while I see most others interest revolves around Android Java apps, where I have no experience.
Am I right in thinking that websocket upgrade https is not yet working on any Java platform, and if so, does anyone have a view on a likely time-frame.
Thanks in advance.
Apologies to all, the sample at https://github.com/jonathanve/socket-io-android put me on the right track.
As my SSL cert is trusted by default, I wrongly assumed the following would work:
socket = IO.socket("https://<hostname>");
However, https requires opts that explicitly supply the sslContext
IO.Options opts = new IO.Options();
opts.sslContext = SSLContext.getDefault();
socket = IO.socket("https://<hostname>", opts);
It could help new-comers like myself if the IO.socket(uri, opts) method were enhanced to populate the otherwise empty opts = new Options();
with the default SSLContext, such as:
if (source.scheme.equals('https') && opts.sslContext == null) {
opts.sslContext = SSLContext.getDefault();
}
Please try just released v0.5.0 which the websocket transport is replaced with OkHttp.
Had the same issue. Works with v0.5.0.
IO.Options opts = new IO.Options();
opts.secure = true;
opts.sslContext = SSLContext.getDefault();
final String url = ...;
socket = IO.socket(url, opts);
@hekar Could you pls shed some light here? We are using this lib in production with https. For now, we can connect to our server without any issue. Do you still have issues? If yes, could you pls add some log here?
I make it work, see https://github.com/TooTallNate/Java-WebSocket/issues/141#issuecomment-149303289
Hello,
I am unable to connect from android to my socket io (https), the SSL certificate is valid and works well on web browser.
Here's my code,
` IO.Options opts = new IO.Options(); opts.secure = true; opts.sslContext = SSLContext.getDefault(); opts.hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } };
socket = IO.socket("https://domain.com:3700",opts); socket.connect(); `
The socket is never connected without any error log, any suggestion for what's wrong with my code?
@leoganda
I'm also having issues connecting over HTTPS. You can try to log transport error like this:
socket.io().on(Manager.EVENT_TRANSPORT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Transport transport = (Transport) args[0];
transport.on(Transport.EVENT_ERROR, new Emitter.Listener() {
@Override
public void call(Object... args) {
Exception e = (Exception) args[0];
Log.e("TEST", "transport error " + e);
e.printStackTrace();
e.getCause().printStackTrace();
}
});
}
});
@nkzawa
Connecting to localhost Node works fine. But when connecting to the same Node hosted somewhere via HTTPS I keep getting xhr poll error
caused by a 400
status code in the response.
E/TEST: xhr open GET: https://xxx/socket.io/?EIO=3&transport=polling
E/TEST: sending xhr with url https://xxx/socket.io/?EIO=3&transport=polling | data null
E/TEST: transport error io.socket.engineio.client.EngineIOException: xhr poll error
Specifying the SSLContext or the HostnameVerifier didn't help.
EDIT I could finally connect the socket by adding a "Origin" header to the requests!
socket.io().on(Manager.EVENT_TRANSPORT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Transport transport = (Transport) args[0];
transport.on(Transport.EVENT_REQUEST_HEADERS, new Emitter.Listener() {
@Override
public void call(Object... args) {
Map<String, List<String>> headers = (Map<String, List<String>>)args[0];
headers.put("Origin", Arrays.asList("https://domain"));
}
});
}
});
@Lumbi It is not working for me with 0.7.0 version and is giving same errors. Did you have to add anything else in options?
Not Working Transport error coming
Closed due to inactivity, please reopen if needed.
I've been having an issue with this library and https for quite a while now. When attempting to connect to my node.js server over https the connection never upgrades to a Websocket and permanent uses xhr polling. This is with both https termination on HAPROXY and a direct connection to a node server running the https itself. As soon as I remove https and connect via https the connection instantly upgrades to a Web socket. Having had a look at the logs the client probes correctly and creates a Web socket Transport. This transport immediately errors and the client falls back to xhr polling. The only success I had was giving IO an sslcontext which accepted all certs and host names (My Certificate is a valid one and trusted by Android by defualt) and setting the only transport to Web socket. Now the first time this is run it gets into a infinite Web socket loop and starts leaking memory. However on later attempts having been restarted the client does sometimes connect correctly via a Web socket. Having looked at the Engine.io source the Web socket is failing the ping/pong probe when using https. I've personally exhausted all things I can think of and any help would be much appreciated - I can provide any logs if you need them. It just seems odd that it upgrades perfectly on http and adding ssl breaks it immediatlty