sta / websocket-sharp

A C# implementation of the WebSocket protocol client and server
http://sta.github.io/websocket-sharp
MIT License
5.72k stars 1.66k forks source link

The header part of a frame....again #140

Open daef opened 9 years ago

daef commented 9 years ago

I'm connecting to a simple server from firefox 40.0a2 and send something.

At first I was using an old version of websocket-sharp.dll binary (it was bundled w/ the WebSockets.unitypackage here http://forum.unity3d.com/threads/unity5-beta-webgl-unity-websockets-plug-in.277567/ )

Then I had to see that sometimes some bytes in the payload are zeroed.

It seems deterministic, the same file always gets corrupted the same way.

So I thought maybe it works on master, cloned into it, compiled, ran my server, connected from js, sent something and bang - WebSocketException ( "The header part of a frame cannot be read from the data source."); was thrown.

After some fiddling I found out that removing the server_no_context_takeover and client_no_context_takeover extensions fixes this problem for me. (They were not sent with the old binary)

When I use master w/o patching out this extensions the ReadBytesAsync-callback in the WebSocketFrame.cs receives an byte[0], checks header.Length and fails.

After patching out those context_takeovers (whatever they're supposed to do) in my clone from master I can receive data again, but the data is corrupted in the same way as in the old version, so now I'm back to investigating why this is happening to me (maybe my code in the browser already f**ed up before websocket-sharp received the bytes, maybe it's another issue w/ websocket-sharp, maybe mozilla .... hope I'll find out soon)

UPDATE: I managed to capture the bytes from the browser to my server via RawCap, wireshark reads the .pcap, already does the unmasking, after deflating the bytes with 5 lines of C# I see the \0 bytes there too - so this is probably not a problem w/ the library, it happens before that

UPDATE 2: I tried the same thing with chrome, there I get the "The header part of the frame" exception always. it doesnt matter if I compile websocket-sharp with or without the _no_context_takeovers

UPDATE 3: it seems to be firefox..: it works if i set network.websocket.extensions.permessage-deflate to false in the about:config

if I set it to true things get really strange... here is what i send and what comes out at the other end:

test                    \0\0\0\0
tes test                \0\0\0 \0\0\0\0
te tes test             te \0\0\0 \0\0\0t
tte tes test            tte \0\0\0 \0\0\0t
this is another test!   this is another \0\0\0\0!
t te tes test           t te tes test
tes tes te              \0\0\0 \0\0\0 \0\0
testyucrap              \0\0\0\0yucrap

UPDATE 4: about the null-bytes, it really seems like this is a firefox-problem, i filed a bug over there...: https://bugzilla.mozilla.org/show_bug.cgi?id=1176176

UPDATE 5: chome seems to do the same thing as firefox

UPDATE 6: I just found issue #120, setting IgnoreExtensions now fixes the null-bytes without me having to change the browser default settings, chrome still tails with the header part...

daef commented 9 years ago

UPDATE 7: mozilla guys say .Net gets the deflatestream wrong...: https://bugzilla.mozilla.org/show_bug.cgi?id=1176176

Quote

The deflated messages are correct. Let's take a zlib header (0x78 0x9C) then append all messages from the pcap file (with added 0x00 0x00 0xFF 0xFF) and pipe it e.g. to "openssl zlib -d". It returns "WRITEFILEtest.txttestyucrap".

The server is buggy. It is obvious from what's missing in the third decoded message that the server doesn't keep LZ77 sliding window between messages but it doesn't announce it by sending client_no_context_takeover parameter in the handshake.

Also, although it isn't required by the specification, I would expect that the server fails the connection when it receives a compressed message that fails to inflate correctly.

igloo15 commented 9 years ago

Seems the mozilla guy responded back saying that the problem was not with deflate stream but your example code.

He said the problem was constructing a new deflate stream for every message. He also said that this library does that same but should work with 'client_no_context_takeover' in response. Which as far as I can tell is in the response.

daef commented 9 years ago

oops, igloo might be right :)