Fix parsing of IPC packets with multiple or partial messages #176
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Observed bug
Sometimes creating subscriptions or sending commands through IPC would result in the promise never resolving, i.e. the message with the expected nonce never getting received.
Reason
The original code to parse the received IPC packets:
RPC/src/transports/ipc.js
Lines 82 to 100 in 9e7de2a
The code assumes that a packet will contain at most one message.
The code will skip the processing of a message if a packet contains:
Practically speaking, we've only seen scenario 1 happen, but theoretically scenario 2 can happen as well.
Scenario 1: A packet contains two complete messages
The packet buffer gets cropped to only contain the message:
RPC/src/transports/ipc.js
Line 85 in 9e7de2a
The rest of the buffer (which contains the second message) gets discarded. The second message never gets decoded.
Scenario 2: A packet contains the tail of one message and the head or entirety of the next message
working.full
already contains a part of the message from the previous packet.This line assumes that the current packet will contain the tail of the message stored in
working.full
:RPC/src/transports/ipc.js
Line 87 in 9e7de2a
However, because it contains the beginning or entirety of the next message, the parsing of the message fails on line 91, resulting in
working.full
containing one full message and at least partially a second message because of the concatenation on line 96:RPC/src/transports/ipc.js
Lines 90 to 97 in 9e7de2a
Because
working.full
is now malformed, it will also affect the decoding of any subsequent messages, causing the packet data to continually be added toworking.full
.Fix
Store the expected length of the current payload (link)
Treat all received packets as a stream of bytes
Concatenate all received packets (link)
Read a number of bytes according to the received message length (link)
Keep the remainder of a packet for decoding of next message (link)
Keep processing the same packet if there's bytes left over after reading the length of the first complete message (link)