c++qtwebsocketqtwebsockets

QWebSocket can't process the handshake


I have a problem with establishing a WebSocket connection using QWebSocket. I'm using Qt 5.6 and its QWebSocket implementation. I'm sure that server works right and uses WS v13 protocol. It works fine with all browsers. When I try to connect to the server, QWebSocket emits error and stateChanged signals with these messages (I get them using errorString() method):

QWebSocketPrivate::processHandshake: Connection closed while reading header.
Invalid statusline in response: Upgrade: websocket
Invalid statusline in response: Connection: Upgrade
Invalid statusline in response: Sec-WebSocket-Accept: HLaITyncgax+CH7OUIXnsCfFDDY=
Invalid statusline in response: // there's a carriage return symbol

Although it says Connection closed while reading header, connection isn't actually closed (because server sends additional packets through websocket after a while). I've tested my application on websocket.org's echo test and it works fine! But I sniffed the packets on both tries and didn't find any significant differences.

Result of packet sniffing on the server which I try to connect to:

GET / HTTP/1.1
Host: <hostname>:6670
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: WcIsYc1AZ6CKikXFwGXgMg==
Origin: http://<hostname>
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
Connection: keep-alive, Upgrade


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 7lfSGmSz/eW1mSzaMnuzOqg00w4=

Result of packet sniffing on connection with echo.websocket.org:

GET / HTTP/1.1
Host: echo.websocket.org:80
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: MUAZoP0Ef4KSWkmtsB5YDw==
Origin: http://<hostname>
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
Connection: keep-alive, Upgrade


HTTP/1.1 101 Web Socket Protocol Handshake
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://<hostname>
Connection: Upgrade
Date: Thu, 31 Mar 2016 12:05:49 GMT
Sec-WebSocket-Accept: c4yAe+A1VRuhF1LSC/TGgPoa8N4=
Server: Kaazing Gateway
Upgrade: websocket

<data exchange goes here normally>

What should I do to investigate and fix the problem? I have no access to the server.

P.S. Yes, I'm aware of QTBUG-40878. It affects Qt 5.3.1 but I use 5.6.0 and it has been obviously fixed in my Qt setup.


Solution

  • This may be QTBUG-51069 (which is not the one you mentioned):

    If there is a delay between status line ("HTTP/1.1 101 Upgrading Protocol") and headers, QWebSocketPrivate::processHandshake erroneously detects server disconnect. The problem is that disconnect condition is checked using QAbstractSocket::atEnd function which just checks if data available and not the actual socket state. This results in multiple error signals:

    websocket error: QWebSocket::processHandshake: Connection closed while reading header.
    websocket error: Invalid statusline in response: Date: Thu, 11 Feb 2016 20:07:37 GMT^M .
    websocket error: Invalid statusline in response: Server: WSGIServer/0.1 Python/2.7.10^M .
    websocket error: Invalid statusline in response: Upgrade: websocket^M .
    websocket error: Invalid statusline in response: Connection: Upgrade^M .
    websocket error: Invalid statusline in response: Sec-WebSocket-Accept: oQ+NK56UdGrsXFisB9chjE3SU+Y=^M .
    websocket error: Invalid statusline in response: Sec-WebSocket-Version: 13^M .
    websocket error: Invalid statusline in response: Content-Length: 0^M .
    websocket error: Invalid statusline in response: ^M .
    

    The fix is in Qt 5.6.2.

    For Qt 5.7, judging from the commit history I think it will be in 5.7.1.