eclipse-paho / eclipse-paho/paho.mqtt.java
Unable to connect via SSL/WSS when no proxy is involved
- Dominant language
- Java
- Stars
- 2.3k
- Forks
- 919
- PR merge metrics
- No merged PRs in 30d
Description
Please fill out the form below before submitting, thank you!
- [X ] Bug exists Release Version 1.2.5 ( Master Branch)
- [X ] Bug exists in MQTTv3 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)
- [X ] Bug exists in MQTTv5 Client on Snapshot Version 1.2.6-SNAPSHOT (Develop Branch)
Hi,
I'm trying to connect via SSL/WSS to some MQTT broker, through **optional** proxy. ~~It works fine behind a proxy~~, but I cannot make it work using direct connection.
The `TCPNetworkModule` class has a `start()` method where we can find the following code:
```
SocketAddress sockaddr = new InetSocketAddress(host, port);
socket = factory.createSocket();
socket.connect(sockaddr, conTimeout*1000);
```
So, I provide a custom `MySSLSocketFactory` class, extending `SSLSocketFactory`, where I override the default `createSocket()` method.
The main idea is to generate some `SSLContext`, then use its `getSocketFactory()` method to retrieve appropriate `SSLSocketFactory` and finally use one of its `createSocket` methods.
Behind a Proxy, there is no problem as we can write something like this:
```
Socket tunnelSocket = new Socket(myProxy);
tunnelSocket.connect(new InetSocketAddress(myProxyHost, myProxyPort), myTimeout);
return mySSLContext.getSocketFactory().createSocket(tunnelSocket, host, port, true);
```
We actually provide an ~~**unconnected**~~ socket (let's call it the "main socket") to the same host and port used by `TCPNetworkModule` when it defines `sockaddr`, but through some kind of a *proxied SSL tunnel*. Notice that the `tunnelSocket` **must** be connected before we call the above `createSocket` method, otherwise we get an "Underlying socket is not connected" `SocketException`.
then `TCPNetworkModule` connects this socket through the line
```
socket.connect(sockaddr, conTimeout*1000);
```
~~and all goes fine~~...
When no proxy is involved, we cannot use the above *tunneling* feature.
Let's try something like that:
```
return mySSLContext.getSocketFactory().createSocket(host, port);
```
Unfortunately, here we actually provide a **connected** main socket, as the above `createSocket(String host, int port)` method creates **and connects** the socket. Then, of course, when `TCPNetworkModule` connects this socket, we have an "already connected" `SocketException`.
We cannot write something like that
```
return mySSLContext.getSocketFactory().createSocket();
```
as creating an **unconnected** `Socket` seems forbidden and we get an "Unconnected sockets not implemented" `SocketException`.
I can see some simple solution, changing `TCPNetworkModule` code a bit, adding a simple condition:
```
if (!socket.isConnected()) {
socket.connect(sockaddr, conTimeout*1000);
}
```
I guess that it should solve the problem.
Best regards
Contributor guide
Research direction
Start in TCPNetworkModule.start(), then trace how its socket.connect call interacts with the SSLSocketFactory createSocket methods described in the issue. Verify that direct SSL/WSS connections work when the factory returns an already-connected socket, while proxied connections continue to work without an already-connected exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100