Skip to content

Latest commit

 

History

History
 
 

Folders and files

README.md

Stream-based Endpoints over WebSocket

Autobahn|Python provides facilities to wrap existing stream-based Twisted factories and protocols with WebSocket. That means, you can run any stream-based protocol over WebSocket without any modification to the existing protocol and factory.

Why would you want to do that? For example, to create a VNC, SSH, IRC, IMAP, MQTT or other client for some existing protocol that runs on browsers, and connects to an unmodified server.

This example is about running any stream-based Twisted endpoint over WebSocket. Autobahn|Python also supports running WebSocket over any stream-based Twisted endpoint. Please see here.

WebSocket Transport Scheme

Autobahn|Python follows the transport scheme established by websockify: a WebSocket subprotocol is negotiated, either binary or base64. Alternative binary compatible subprotocols may also be specified, such as the MQTT mqttv3.1 protocol, by using the subprotocol endpoint descriptor.

With the binary WebSocket subprotocol, any data is simply sent as payload of WebSocket binary messages. With the base64 WebSocket subprotocol, any data is first Base64 encoded before being sent as the payload of WebSocket text messages.

Since Autobahn|Python implements WebSocket compression, traffic is automatically compressed ("permessage-deflate"). This can be turned off if you want.

Currently the only browser with support for WebSocket compression is Chrome 32+.

Wrapping Factories and Protocols

Here is how you wrap an existing Twisted client protocol HelloClientProtocol:

from autobahn.twisted.websocket import WrappingWebSocketClientFactory

wrappedFactory = Factory.forProtocol(HelloClientProtocol)
factory = WrappingWebSocketClientFactory(wrappedFactory, "ws://localhost:9000")

The only required parameter to WrappingWebSocketClientFactory besides the wrapped factory is the WebSocket URL of the server the wrapping factory will connect to.

There are a couple of optional arguments to WrappingWebSocketClientFactory for controlling it's WebSocket level behavior:

  • enableCompression can be used to enable/disable WebSocket compression ("permessage-deflate")
  • autoFragmentSize can be used to automatically fragment the stream data into WebSocket frames of at most this size
  • debug enables/disables debug log output

You can find a complete example for both client and server in these files:

  1. client.py
  2. server.py

Wrapping Endpoints

Twisted provides a flexible machinery for creating clients and server from Endpoints and Autobahn|Python includes a Twisted Plugin for both client and server stream endpoints.

This allows you to run any stream-based, endpoint-using program over the WebSocket transport Autobahn|Python, without even referencing Autobahn at all:

wrappedFactory = Factory.forProtocol(HelloClientProtocol)

endpoint = clientFromString(reactor, "autobahn:tcp\:localhost\:9000:url=ws\:// localhost\:9000")
endpoint.connect(wrappedFactory)

You can find a complete example for both client and server in these files:

  1. client_endpoint.py
  2. server_endpoint.py

Example Client Endpoint Descriptors

  1. "autobahn:tcp\:localhost\:9000:url=ws\:// localhost\:9000"
  2. "autobahn:tcp\:localhost\:9000:url=ws\:// localhost\:9000:compress=false"
  3. "autobahn:tcp\:localhost\:9000:url=ws\:// localhost\:9000:autofrag=4096:debug=true"

Example Server Endpoint Descriptors

  1. "autobahn:tcp\:9000:url=ws\://localhost\:9000"
  2. "autobahn:tcp\:9000:url=ws\://localhost\:9000:autofrag=4096:debug=true"
  3. "autobahn:tcp\:9000\:interface\=0.0.0.0:url=ws\://localhost\:9000:compress=true"

Twistd

Endpoint Forwarder

Autobahn|Python further includes a twistd (the Twisted Daemon) plugin that provides a generic stream endpoint forwarder.

The forwarder can listen on any stream-based server endpoint and forward traffic to any other stream-based client endpoint.

As an example, here is how you forward WebSocket to Telnet:

twistd -n endpointforward --endpoint "autobahn:tcp\:9000:url=ws\://localhost\:9000" --dest_endpoint="tcp:127.0.0.1:23"

Included in this directory is a Terminal client written in JavaScript (this code is from the websockify project).

Open telnet.html in your browser, provide the server IP and port (the one running twistd) and press connect.

As soon as the Process support for endpoints in Twisted is fully here, the forwarder will allow you to expose any program over WebSocket, by forwarding the program's stdin and stdout.

Another example is to create a WebSocket proxy in front of a MQTT broker. This makes use of the optional subprotocol input that allows the mqttv3.1 binary compatible subprotocol to be accepted along with the default binary and base64 subprotocols.

twistd -n endpointforward --endpoint "autobahn:tcp\:9000:url=ws\://localhost\:9000:subprotocol=mqttv3.1" --dest_endpoint="tcp:127.0.0.1:1883"

Essentially, these features are equivalent of what the following two projects provide:

But since Twisted endpoints are extensible, eg support for serial is coming, this will also allow you to expose serial devices directly over WebSocket!

Manhole

Start manhole

echo "admin:admin" > passwd
twistd -n manhole --telnetPort "autobahn:tcp\:9000:url=ws\://localhost\:9000:compress=false:debug=true" --passwd ./passwd

It seems, login is possible, but then the JS Terminal seems to get confused by Manhole sending fffc01. I don't know what's going on.