koush / AndroidAsync

Asynchronous socket, http(s) (client+server) and websocket library for android. Based on nio, not threads.
Other
7.52k stars 1.56k forks source link

WebSocket: Support multi-framing sends #683

Open jhihn opened 4 years ago

jhihn commented 4 years ago

Per RFC 6455 10.4. Implementation-Specific Limits client can choose a maximum frame size. It seems that in private byte[] frame(int opcode, byte [] data, int errorCode, int dataOffset, int dataLength) that there is no maximum frame size applied. The data is shoved into a single frame and delivered this cause problems with clients who do implement a maximum frame size.

I suggest there be a setMaxFrameSize() function added and the data to be fragmented into multiple frames when it exceeds the maximum frame size.

jhihn commented 4 years ago

Note, that after further analysis, I have an application sending messages of size 2_536_240 +/- bytes. These messages never arrive at the other side when sent with this library. I am suspecting that framing would help. I have tried both python websockets library and a C++ library and they both report timeouts when receiving data from this library. The python and C++ code have no problem with each other.

The issue only exists when the message size > 300kB. Somewhere beyond that, they silently disappear into the ether. 348951 works, 348997 does not work. Once a frame does not work the server won't send anymore.

 File "pyws.py", line 26, in <module>
    asyncio.get_event_loop().run_until_complete(hello())
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
    return future.result()
  File "pyws.py", line 20, in hello
    greeting = await websocket.recv()
  File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 509, in recv
    await self.ensure_open()
  File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 803, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

If this could work with a single frame, I would accept that, but there's something very not right, and I think multi-framing would help? But if frames over 348k are broken, that implies a max frame size, or there's a bug.

koush commented 4 years ago

Ok thanks, I'll take a look.

koush commented 4 years ago

300k is a strange delimiter. d

https://github.com/koush/AndroidAsync/blob/master/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java#L361

jhihn commented 4 years ago

I created a push request that fixes the issue for me but it is suboptimal. Check the push requests for the project. Based on that pull request I think there's something else going on maybe at the operating system level that's making that specific length and issue.

Edit https://github.com/koush/AndroidAsync/pull/684#issue-497038619

jhihn commented 4 years ago

300k is a strange delimiter. dhttps://github.com/koush/AndroidAsync/blob/master/AndroidAsync/src/com/koushikdutta/async/http/HybiParser.java#L361

Yes I looked all over it and I did come across that but I wasn't sure what was going on there I compared it to other websocket code and it almost agreed but not enough for me to say that I understood it

koush commented 4 years ago

is this a http or https websocket? are you using this library as a server or client websocket?

jhihn commented 4 years ago

Unencrypted websocket server. Client connects, sends text, server replies with a large text reply.