TCP vs WebSocket isn't actually "translated"
See original GitHub issueThe transit relay doesn’t actually un-frame incoming TCP messages and turn them into properly-sized WebSocket messages. (Related: the only transit-over-websocket client has a “complimentary” bug whereby it turns the WebSocket stream back into a byte-stream).
The transit should act differently when either side is a different transport protocol. If both sides are the same (i.e. TCP<–>TCP or WebSocket<–>WebSocket), messages can be directly transmitted.
If just one side is TCP, the incoming stream must be buffered until at least one message is available (according to the “first 4 bytes are the size” framing). Then this message can be sent to the WebSocket side as a single binary WebSocket message (without the 4 byte size).
In the other case, incoming WebSocket messages should have their length prefixed before being streamed to the TCP side. Thus the maximum size of any incoming WebSocket message can be at most 2**32 - 4
(which we can enforce at the WebSocket layer via Autobahn options).
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:22 (8 by maintainers)
Top GitHub Comments
I think the correct fix here is to split the “relaying” state into two: “translating” or “relaying” (the latter used when both sides are the same, the former used when they’re different).
For “relaying” we continue to just funnel bytes (or messages) back and forth.
In “translating” we must buffer until a complete message is received. When bytes come in on WebSocket connections, this is easy (we have “one message” always). On incoming TCP we must buffer.
Having two states allows the outputs to correspond to the correct behavior.
Yeah … also worth bearing in mind that Twisted itself is our intermediary between the kernel and
dataReceived()
so there may be multiple “on the wire” TCP packet payloads in a singledataReceived()
call, I believe.So, yeah, there could be more than 1 complete message, there could be part of one, the finish of the one we want plus some more, etc. This is why my instincts are that “buffering” (until there’s at least one complete message) is going to be the easiest implementation, not frames.
(I do expect all compliant websocket libraries to deal with incoming websocket frames since they can be arbitrarily split up … but have we confirmed this for the clients we care about?)