WebSocket finishing messages that aren't final
Joebayld opened this issue · comments
I've been tracing a bug with the WebSocketParser
and I think I've found where it's at. In my app, the client is sending a lot of data quickly to the server, causing some packets to be fragmented. The issue I've found is that telegraph is calling the finishedMessage
method on messages that aren't marked final. This is resulting in broken JSON on my app.
When examining the incoming data I can see the split data frames. The WebSocketParser
should see that a packet is not final and wait till a message is marked final before firing that message to the delegate. It should just append any packets payload that follows the non-final packet.
I've added this small piece of code to the parser for debugging and it results in a crash.
case .payload:
// For now we can only support payloads that can fit into a Data object,
// if the payload is any bigger we should probably offload it to a temporary file
let payloadSafeLength = payloadLength > Int.max ? Int.max : Int(payloadLength)
// Is this the first payload byte?
if payload.isEmpty {
payload.reserveCapacity(payloadSafeLength)
}
// Append the byte we already read
payload.append(byte)
// Append any payload bytes available in the stream
let payloadBytesToRead = payloadSafeLength - payload.count
payload.append(stream.read(count: payloadBytesToRead))
// Is the payload complete?
if payload.count == payloadSafeLength {
// Are we finished with the packet? <---- THIS IS WHERE THE ISSUE IS
if !message.finBit {
fatalError("endOfMessage set when we never recieved the final packet!")
}
nextPart = .endOfMessage
}
Let me know your thoughts and I can take a stab at fixing this.
Ah I just realized this could be intentional as I could check the message.finBit
on the delegate call. But then the weird part is that the .continuationFrame
is sent as binary (when it is a continuation of the original textFrame
)
Nice work on tracking down the issue! The WebSocket implementation of Telegraph is quite basic. You're quite likely to run into a few issues here and there if you use more advanced options.
I'm not quite sure if it should be Telegraph's responsibility to combine the fragmented messages. We could have a look at how other web servers handle that. Maybe the nicest solution would be to have a setting where you can control if Telegraph will automatically handle it for you, and perhaps that should be on by default.