I created a patch to improve the support of the Socks5 bytestream feature of XMPP for Smack. With this patch comes a new API to establish Socks5 bytestreams. This can be useful for applications that exchange data not only via XMPP messages but also via streams. Socks5 bytestreams can also be a good fallback if Jingle doesn’t work.
Here is a list of changes:
full implementation of XEP-0065 (except the optional UDP Support)
Smack now replies with error message “not_acceptable” if an unexpected Socks5 bytestream request is received
if target fails to connect to all Socks5 proxies it replies with “remote_server_not_found” error (before: “not_acceptable”)
extracted API for Socks5 bytestreams from file transfer API
Socks5 bytestream feature can now be used detached from the file transfer API
file transfer API is now based on that extracted Socks5 bytestream API
use Socks5ByteStreamManager#establishConnection() to initiate a Socks5 bytestream
use Socks5ByteStreamManager#addIncomingByteStreamListener() to listen for incoming Socks5 bytestream requests
use Socks5ByteStreamRequest#accept() to accept incoming Socks5 bytestream
improved timeout behavior for Socks5 bytestreams
response timeout to a Socks5 bytestream request is now configurable through Socks5ByteStreamManager#setTargetResponseTimeout() (was a constant)
timeout for target to connect to Socks5 proxies is now configurable through Socks5ByteStreamRequest#setTotalConnectTimeout() and Socks5ByteStreamRequest#setMinimumConnectTimeout()
every connection attempt to a Socks5 proxy now has a timeout so that connecting to an unreachable Socks5 proxy doesn’t consume the whole timeout for answering the Socks5 bytestream request
improved prioritizing of Socks5 proxies
Socks5 bytestream manager will set the last working Socks5 proxy to the top of the list of Socks5 proxies when establishing a new Socks5 bytestream
Socks5 bytestream feature can now be enabled/disabled
improved local Socks5 proxy server
port of the local Socks5 proxy server can now be configured by editing the smack-config.xml file or by SmackConfiguration#setLocalSocks5ProxyPort()
local Socks5 proxy can now be enabled/disabled by editing the smack-config.xml file or by SmackConfiguration#setLocalSocks5ProxyEnabled()
local Socks5 proxy replies to some bad Socks5 request with appropriate error messages to be more client-friendly
improved documentation of the implementation for maintainability
added about 40 tests with almost 100% code coverage of the changed code
added testing utilities to be able to test the code without using an XMPP server by mocking the XMPPConnection class
The patch is based on the current trunk of the Smack svn repository (rev 11621).
To run the tests the mocking libraries mockito and PowerMock are required.
Copy all files from the archive except the junit-4.7.jar and the *.pom files to Smacks “build” directory.
Note: The support of Socks5 bytestreams depends on the XMPP server (respectively the Socks5 proxy server) implementation. For example Openfire only supports Socks5 bytestreams within the scope of a file transfer by default. You can change this behavior by setting the “xmpp.proxy.transfer.required” flag to false. Additionally not all Socks5 proxy implementations support bidirectional Socks5 bytestream. Openfire only supports a directed Socks5 bytestream from the initiator to the target.
Thanks for your work and sharing it with the community! You should have a look on For Code Contributors Document to include your patch within our official release. Maybe you want continue to work with the community and join the mentorship program to get commit access for the sources?
Do you have already a Jira account? Please ping Daryl Herzmann with your account name, he can grant you the privileges to create an issue for tracking and documenting your patches.
it’s exhausting to review your patch, because it includes many unnecessary formating changes (e.g. indentation changes, line breaks, brace changes). Could you cleanup and maybe split your patch? This would be great and make reviews a lot easier.
With splitting I mean, it would be great if you can create Jira issues, e.g. add local socks 5 proxy configuration, support network address requests from proxy according XEP-0065: Initiator Discovers Network Address of StreamHost,… and assign these issues to me.
I will split it in some smaller patches which should be easier to review.
Also I’m currently working on a document containing some code style guides for creating patches for smack. This could avoid the problem that patches contain unnecessary formating changes.
I couldn’t find anything like that and just choosed one of the codestyles I found in Smack and formatted everything the same way.
Maybe it would be a good idea to have this styleguide and format all the source in Smack the same way to avoid that problem.
here is a new version of the SOCKS5 Bytestream patch. I fixed a few bugs I found and made the changes requested by Guenther Niess review.
The test cases are now separated into the unit tests and smack tests. I’ve also added a shutdown listener for the Socks5BytestreamManager.
Additionally I moved the classes Bytestream and BytestreamsProvider into subpackages of the socks5bytestream package according to our new code guideline.
The patch is now splitted in four parts:
The first adds a convenience class for the ConnectionListener which contains empty implementations for all methods of the ConnectionListener. This is useful if you only want to implement some of the methods and it makes the code look much nicer.
The second patch is the improved implementation of the Socks5 bytestream feature.
The third patch contains Utility classes for unit testing. These require the mockito and powermock libraries.
The last patch contains the test cases for the improved Socks5 bytestream implementation.
I’ve added some improvements to the Socks5 bytestream patch.
You can now add multiple local network addresses to the local Socks5 proxy. This might be useful if your application runs on a machine with multiple network interfaces or is behind a NAT und has a public IP that differs from the local IP.
I also fixed the strange behaviour that so socket returned by Socks5ByteStreamManager#establishConnection() had a fixed timeout of 10 seconds. It is now set to an indefinitely timeout so that calls to InputStream#read() won’t timeout anymore.
The JavaDoc for the adding the IncomingByteStreamListeners is updated and now states that these listeners won’t be informed on incoming Socks5 bytestream requests created in the context of a file transfer.
There are also some new unit tests to check the imrovements.