Forum

Understanding Hiawatha's Websocket support

Carsten
6 October 2017, 11:47
Hello Hugo,

thank you for this fantastic, stable, and secure Webserver.

I'm trying to get the Websocket interface of Hiawatha working, but without success now.
Possibly, I do not understand how Hiawatha supports this kind of protocol, and the manual is not very clear on this topic.

Within my virtual host section, I've added "WebSocket = wss://127.0.0.1:5000 /api/websocket 15".
On my Linux embedded machine, I've created and started a server process listening on TCP port 5000.
The client application is an AngularJS application using the Websocket library provided by https://github.com/AngularClass/angular-websocket. My client application and related Ajax requests over HTTPS work properly so far . Furthermore, I can see the HTTPS GET request header to /api/websocket containing some Websocket related header fields, when the websocket connection should be established

Network traffic as seen by Firefox dev-tools:
Request Header:
Host: 192.168.51.33
User-Agent: "Mozilla/5.0 (X11; Ubuntu; Linux...."
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: "de-de,en;q=0.8,pl;q=0.5,en-us;q=0.3"
Accept-Encoding: "gzip,deflate"
Sec-WebSocket-Version: "13"
Origin: "https://192.168.51.33"
Sec-Websocket-Key: "EurnA7QzUTK9AV..."
Connection: "keep-alive,Upgrade"
Pragma: "no-cache"
Cache-Control: "no-cache"
Upgrade: "websocket"


At this time I can see the client connection on my listening port 5000.
Calling socket::accept to accept the client connection on port 5000 is successful, but does not lead Hiawatha to send an appropriate HTTPS response header. The client request is still pending (Firefox dev-tools).

Now, if I send some arbitrary data (e.g. Hello world) through the connected socket on port 5000, the client gets a "500 Internal Server Error" message.

Within the hiawatha-error.gui.log file I see following messages:
192.168.51.32|Fri 06 Oct 2017 07:08:12 +0000|TLS handshake error with websocket
192.168.51.32|Fri 06 Oct 2017 07:08:31 +0000|error connecting to websocket


The TLS connection/handshake works properly with "normal" Ajax requests and JSON payload, but not with websocket?

The server configuration:
ServerId = www-data
ConnectionsTotal = 32
ConnectionsPerIP = 32
MaxUrlLength = 1000
MinTLSversion = TLS1.1
ThreadPoolSize = 10
WorkDirectory = /usr/local/var/ram/hiawatha
SystemLogFile = /var/log/hiawatha.log
ErrorLogFile = /var/log/hiawatha-error.log
AccessLogFile = /dev/null

Hostname = 127.0.0.1
WebsiteRoot = /usr/local/var/www
StartFile = index.html

Binding {
BindingId = SERVICE
Port = 443
Interface = 0.0.0.0
MaxKeepAlive = 60
TimeForRequest = 5,30
TLScertFile = /mnt/config/test.pem
MaxRequestSize = 20480
MaxUploadSize = 25
EnableAlter = yes
}

FastCGIserver {
FastCGIid = fcgi0
ConnectTo = 127.0.0.1:65530
}

UrlToolkit {
ToolkitID = GUI
RequestURI isfile Return
Match ^/api/.* UseFastCGI fcgi0
}

VirtualHost {
RequireBinding = SERVICE
Hostname = *
RequireTLS = yes
PreventXSS = yes
WebsiteRoot = /usr/local/var/www
StartFile = index.html
TimeForCGI = 300
UseToolkit = GUI
AlterList = allow all
AlterMode = 666
FollowSymlinks = yes
WebSocket = wss://127.0.0.1:5000 /api/websocket 15
AccessLogfile = /dev/null
ErrorLogfile = /var/log/hiawatha-error.gui.log
}


Any help and clarification on this topic would be greatly appreciated. Thank you.

Regards,

Carsten
Hugo Leisink
8 October 2017, 16:16
Does your websocket application use an encrypted connection? If not,use ws:// instead of wss://. Using HTTPS does have nothing to do with the websocket connection being encrypted or not.
Carsten
9 October 2017, 11:59
Yes, normal Ajax requests are sent via TCP port 443 (MinTLSversion = TLS1.1, and RequireTLS = yes).
For testing with an unencrypted connection, I switched to port 80, set RequireTLS = no in the virtual host section, and changed schema from wss: to ws: in my frontend application, and hiawatha.conf accordingly.
Using this setup, the message 'TLS handshake error with websocket' goes away, but 'error connecting to websocket' is still present.
Furthermore, I added some code in the backend to read data from TCP port 5000. When the client connects to the websocket URL, I can read the complete HTTP header from the socket. This brought me to the idea to send a complete response header like
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade


instead of 'Hello world'.
Bingo, the Hiawatha error message 'error connecting to websocket' went away, and within the browser's debug window, I can see the GET request to /api/websocket being aknowledged with status code '101 Switching Protocols'.

Now it is clear, that Hiawatha (10.4) does not support Websockets by handling the protocol (RFC 6455) nor generating the related HTTP header for me. Hiawatha only provides a naked TCP socket to communicate with my application. Therefore it is necessary to use a kind of Websocket framework beyond of Hiawatha, handling the Websocket protocol.

Hugo, can you confirm this?

If yes, I may suggest you to clarify the 'Websocket support' of Hiawatha in the manual pages more precisely.

Regards,

Carsten
Hugo Leisink
10 October 2017, 07:59
First, whether the connection from the client to the webserver is encrypted or not, has nothing to do with if the websocket connection needs to be encrypted or not. You can have an encrypted client-server connection (HTTPS) and a plain text websocket connection (ws:). Only use wss: if the websocket connection supports encryption.

Yes, it's up to the websocket application to do the websocket communication. Hiawatha only provides the protocol switch and the connectivity. I used this websocket example (http://www.leisink.net/chat/chat.tar.gz) during testing, and that one works.
Carsten
11 October 2017, 10:24
Hi Hugo,

thank you for your support, background information, and the link to your example code.

Regards

Carsten
This topic has been closed.