Search code examples
javascriptwebsocketwebsockify

Minimal example of "websocket wrapping" for web server using websockify


some webdev basic questions for a noob.

background: I have a javascript client that uses the websocket protocol, and a good old java server, which I'm perfectly able to interact with via telnet. I want them to be able to communicate to each other locally (passing strings would suffice).

For that, I definitely don't want to make deep changes in the client. I tried to adapt the server to websocket following this guide before that, and even passed the handshake but it got pretty messy.

So at this point I believe that the best way to deal with this would be to serve through a TCP->WebSocket proxy like websockify. If I got the explanation right, it would "wrap" the server's process, opening the "upgraded" connection in a new port. And the websocket client should be able to directly speak to the server through that port. But I've been trying to implement this with different approaches without success, therefore my questions:


  • Is there a better way to deal with this problem? (that would explain google's sparseness, I can imagine this happens very often!)
  • If "wrapping" is the best way and I got it right, how to implement it?

Implementation - edited: For the sake of testing, I've tried to build a simple echo server:

  • I'm running the very simple command line echo server suggested in this post: ncat -l 2000 -k -c xargs -n1 echo. Talking to it via telnet localhost 2000 returns the desired echo. So far so good.

  • I installed websockify using apt-get,and run it as follows: websockify 2023: 2000, this should open the same server via a websocket connection on port 2023.

  • At this point I'm still able to comunicate via telnet localhost 2000, but I'm not having that much luck with port 2023. This is what I tried so far:

    • Downloaded the telsocket binary, and called ./telsocket -url ws://127.0.0.1:2023. Response: errrr dial tcp 127.0.0.1:2023: connection refused
    • Cloned wssh (a command line shell for websocket), which seems very promising. I was able to install it, but running wssh -l localhost:2023 returns NameError: name 'PROTOCOL_SSLv3' is not defined. Apparently some problems with gevent (didn't look much further into that).
    • Tested the several examples in websockify's repo, like wstelnet, or the ones in tests. All of them got me a code 400, message Invalid protocol selected.

Follow-up - edited: Diving deeper into the websock.js and wstelnet.js files, I was able to get more specific results by issuing the following into the JS console:

ws = new Websock()
ws.open("ws://127.0.0.1:2023", "binary") // connects, proxy says: connecting to: :2000, Plain non-SSL (ws://) WebSocket connection, Version hybi-13, base64: 'False'
ws.send_string("hello server")           // send and wait for echo 
ws.get_rQ()                              // empty??

So, as you can see, I'm able to establish the connection, but still don't get an echo. The mistake might be as well in the server's side since every tool I tried is failing. Help! D:


Remarks: Since it is intended to work locally, I wouldn't care having either ws or wss. I also don't have a preferred way to do this as long as it is viable and works. In case it is relevant, I'm on Ubuntu15.10 + Firefox47.0


Solution

  • finally, I got the TCP echo server communicating with websockify's websocket telnet emulator through websockify's proxy. This is how:

    1. run the echo server ncat -l 2000 -k -c 'xargs -n1 echo echoServer received'
    2. in a separate process, run the proxy: websockify 2023 :2000
    3. clone the repo: git clone https://github.com/novnc/websockify.git, and make the following changes to wstelnet.js:

      3.1 changing the line ws.open(uri) to ws.open(uri, "binary") allowed to overcome the code 400 problem.

      3.2 in the definition of do_recv (this is a permalink), add the following line after the initial var statement: arr = Array.from(arr); this is a conversion to Array since Uint8Array didn't apparently support the shift method.

    4. open wstelnet.html with firefox, select Host: localhost, Port: 2023, no encryption, press Connect and type into the black field.

    The screen should reply with echoServer received: <YOUR_MESSAGE>. hurray!