Skip to content

Commit

Permalink
TcpClient does not send incomplete packets. (#2721)
Browse files Browse the repository at this point in the history
Before this Pull Request, when the microprocessor runs out of memory while calling `TcpClient::send`, this method could send an incomplete packet. Since `TcpClient::send` does not return the number of bytes actually sent, there's no way to know which part of the message was sent and which part still needs to be sent. Therefore - assuming we keep the interface constant - we should not allow a message to be sent incompletely.

More specifically, when one calls [TcpClient::send](https://github.com/SmingHub/Sming/blob/8939766cb38ef540d8296c3ae4bbc0998f88b91a/Sming/Components/Network/src/Network/TcpClient.cpp#L41), the `data` argument is written to a `MemoryDataStream` (by a call to [MemoryDataStream::write](https://github.com/SmingHub/Sming/blob/8939766cb38ef540d8296c3ae4bbc0998f88b91a/Sming/Core/Data/Stream/MemoryDataStream.cpp#L49C8-L49C31)). According to its [implementation](https://github.com/SmingHub/Sming/blob/8939766cb38ef540d8296c3ae4bbc0998f88b91a/Sming/Core/Data/Stream/MemoryDataStream.cpp#L57), when it is not possible to allocate enough additional memory to hold `data`, `MemoryDataStream` stores "as much as possible" in the space that could be allocated. For a `TcpClient`, this may not be a desirable behavior since this allows incomplete messages to be sent, while there's no way to know how much of the packet was actually sent.

This change ensures there's enough memory to hold `data` before writing it to the `MemoryDataStream`. This makes sure only complete messages are sent.
  • Loading branch information
acburigo authored Mar 7, 2024
1 parent d9d97bd commit 9e4b251
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Sming/Components/Network/src/Network/TcpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ bool TcpClient::send(const char* data, uint16_t len, bool forceCloseAfterSent)
memoryStream = new MemoryDataStream();
}

if(memoryStream->write(data, len) != len) {
if(!memoryStream->ensureCapacity(memoryStream->getSize() + len)) {
debug_e("TcpClient::send ERROR: Unable to store %d bytes in buffer", len);
return false;
}

memoryStream->write(data, len);

return send(memoryStream, forceCloseAfterSent);
}

Expand Down

0 comments on commit 9e4b251

Please sign in to comment.