warmcat / libwebsockets

canonical libwebsockets.org networking library
https://libwebsockets.org
Other
4.74k stars 1.48k forks source link

Failure to connect to a QtWebSockets server #453

Closed tanuva closed 8 years ago

tanuva commented 8 years ago

Hi,

this seems to be a quite specific issue and I'm not at all sure if lws is to blame for anything. Still, I'd really like to hear your opinion on this, maybe you can make an educated guess what is going wrong. Now for the facts:

I'm trying to get an lws 1.7 client and a QWebSocketServer to talk to each other. Using the lws example client and the Qt echoserver example, I observe the following in Wireshark: They manage to set up a TCP connection and the lws client sends its HTTP upgrade request:

GET // HTTP/1.1
Pragma: no-cache
Cache-Control: no-cache
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: AOR1H5Uu118vwdTRWhk2yA==
Origin: http://localhost
Sec-WebSocket-Protocol: fake-nonexistant-protocol,lws-mirror-protocol
Sec-WebSocket-Extensions: 
Sec-WebSocket-Version: 13

But there is exactly nothing coming back. I've inserted debug output into lws and came so far that I saw it failing in client.c:375. (Though I didn't manage to get the lwsl_debug output to show up anywhere. Built with "Debug" and ran with -d 65535.) So it looks like the Qt server is cancelling the connection because... it had a bad day. I don't see any significant difference between a web browser's HTTP handshake and lws' one, so the problem seems to be somewhere less visible. Do you have any idea what might be going wrong?

This is OS X 10.11 (Apple LLVM 7.0.2 / clang-700.1.81) Tried Qt 5.4.2, 5.5.1 and the 5.6.0 RC. Always with the lws 1.7 example client (and my own stripped down one).

JoakimSoderberg commented 8 years ago

Just a quick thing that seems weird GET // HTTP/1.1... should it just be one / ?... Is the server ok with that?

lws-team commented 8 years ago

Unless you taught this other server to support one of the ws protocols you ask for, he'll fail the connection on the basis 'I don't understand any ws protocol he wants'. Nobody supports the protocols of the lws test apps except the test apps.

You can try setting the protocol name to NULL in your test client instead, that means 'use the default ws protocol this server offers', or find how to manage it in your server.

tanuva commented 8 years ago

The double // is indeed only sent by the lws example (I didn't investigate the how and why so far). If I use a minimal client I built myself (gist), the following HTTP request is going out:

GET / HTTP/1.1
Pragma: no-cache
Cache-Control: no-cache
Host: localhost:1234
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: 05IqIwkf1gTfCzRXcrXClw==
Sec-WebSocket-Extensions: 
Sec-WebSocket-Version: 13

This is with the protocol name set to NULL, while default yields the same outcome. Still not even a blink from the Qt server and this output from the client:

➜  Downloads DYLD_LIBRARY_PATH=../libwebsockets-1.7-build/lib ./lwstest
Blah!
Initial logging level 65535
Libwebsockets version: 1.7.3 frosch@eddh.froglogic.com-v1.7.3-1-g3816a05
IPV6 not compiled in
libev support not compiled in
 Threads: 1 each 256 fds
 mem: platform fd map:  2048 bytes
 mem: per-conn:          368 bytes + protocol rx buf
 canonical_hostname = eddh.froglogic.com
client connection error

After this, nothing happens until I Ctrl+C the program. (Which is no surprise...)

lws-team commented 8 years ago

Hm... basically we can't debug qt server process from here.

I think what you're sending is fine now, for example the echo test app uses this to interoperate with echo.websocket.org and to pass Autobahn suite.

Your question is why does the server drop the connection... you need to study the server side to understand that (ie, logging).

If that server is more than a year or two old, it may simply not support the "revision 13" ws protocol from the rfc, there were 80 (!) pre-standard versions. Does that server actually work with a modern web-browser for ws?

tanuva commented 8 years ago

The Qt docs state that it does support revision 13 (and only this one). I expected this outcome but hoped I had overlooked something in my lws usage. Using my test program with echo.websocket.org works fine and connecting to the Qt server from Safari does as well - this is what I find really strange about this. Both components work on their own, but pairing them leads to no good. So I'll start digging in Qt. Thanks for your confirmation though!

tanuva commented 8 years ago

I have news: The HTTP request sent by lws contains the line Sec-WebSocket-Extensions:. The Qt class QWebSocketHandshakeRequest though insists that the header field shall have a value. This seems to be standard compliant - unless RFC 6455 is obsolete in this regard of course.

I do (now) set lws_context_creation_info::extensions = NULL in the aforementioned minimal test client. Still, lws sends the empty extensions header. Am I doing something wrong?

On a side note, most other websocket server implementations seem to be more tolerant, Qt is the only one I'm seeing this with.

lws-team commented 8 years ago

Heee.... okay. The rfc abnf does indeed say we can't send empty arg extensions header. I'll take a look at it.

lws-team commented 8 years ago

That should be solved on both master and v1.7-stable.

lws-team commented 8 years ago

I boldly assume that did the trick, please reopen if not.

tanuva commented 8 years ago

Yes, connecting to a Qt server works now. Thanks for the quick fix!