-
-
Notifications
You must be signed in to change notification settings - Fork 386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sctp: allow partial reads #304
Conversation
removes `ErrShortBuffer` Refs #273
Codecov ReportBase: 56.52% // Head: 56.58% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #304 +/- ##
==========================================
+ Coverage 56.52% 56.58% +0.06%
==========================================
Files 500 500
Lines 47434 47534 +100
Branches 12840 12859 +19
==========================================
+ Hits 26811 26898 +87
- Misses 9948 9956 +8
- Partials 10675 10680 +5
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
where first chunk is processed more than one time
✅ tested with webrtc libp2p transport (all tests are passing) |
@melekes did you review the callsites where data channels use SCTP? |
Yes |
Maybe I am missing something, but this seems like a silently breaking change?
From what I can tell, WebRTC data channels are meant to be message based, not stream based, and so it seems like this like a single logical message will now trigger multiple Am I missing something? |
It is a breaking change (if the given buffer is not long enough to fit the message). However, the size of the buffer is capped at
So if you're using the default (i.e. If you're calling
It won't (because of u16::max).
Does this mean we can't make this change? |
After giving it a little bit of thought (and reading https://lgrahl.de/articles/demystifying-webrtc-dc-size-limit.html), I think from the Rust perspective it would still be correct to fill the buffer in case of |
It feels a bit dubious to mess with the message based nature of Data Channels. As it would be a departure from the specification. Is there a different way to work around the problem you have @melekes? If you control both sides‚ message size can be known and buffers always appropriately sized |
not always!
can you point me to the exact place?
yes. create a very big buffer, which is not ideal to say the least. |
I see two problems here:
With this PR, you'll never face both problems. |
I could be mistaken, but while this PR as written fixes those two problems it creates new problems. Specifically, we send protobuf messages across data channels from the browser. We had an issue where the message we were trying to send ended up being significantly large in some circumstances which caused the If your PR was in at the time, unless I'm missing something this would have been significantly harder to figure out what was going wrong, because partial reads would have triggered multiple data channel messages, which mean all code that expects a single data channel message to be a single deserializable self contained message would have failed. We would have gotten no errors or warnings and just random circumstances of deserialization failures. Maybe I'm wrong and I'm just missing the code which would assemble partial reads into a single For what it's worth, the data channels spec itself in section 6.6 recommends a message size limit of 16K. Specifically:
|
Maybe this is better solved by utilizing the
Specifically, this gets around the issue because while it may allocate a 200MB size buffer to store the one large message, the buffer should be efficiently re-used by |
What if do this? Would it be strictly better than throwing an error if msg is too big? |
huh? in the current implementation you'll just get |
100% yes. As long as a single
Which seems like it leaves two options that I can see (though there are probably others) The first option is to have The downside of this that I see is that some devs may not like the unpredictability of allocations. The second option I see is the reassembly queue and enum SctpReadStatus {
Complete(usize),
Incomplete(usize)
} If the buffer is to short, it still has the partial read in the buffer but returns In let mut immediate_buffer = vec![0u8; DATA_CHANNEL_BUFFER_SIZE as usize];
let mut message_buffer = BytesMut::new(); When IF an incomplete message was passed in, instead of returning the data channel message we just continue the loop until we receive a complete status response. This is actually more efficient than the code is now with a quick look. Right now in |
This PR modifies
read
behaviour to permit partial reads and no longer returnErrShortBuffer
if the buffer is too small to fit a whole message. The buffer will be filled up to its size and the rest of the msg will be returned upon the next call toread
.Closes #273