Deliver partial SCTP messages when the SID is (unexpectedly) changed.
We're receiving SCTP messages one chunk at a time. The sender is supposed to set the MSG_EOR bit on the last chunk of a message. A crash (RTC_CHECK) happened when the sender started a new message without indicating the end of the previous message. This is likely due to an SCTP implementation that doesn't (correctly) support the MSG_EOR bit. This change, rather than calling RTC_CHECK, delivers partial messages when SID is (unexpectedly) changed, which is what happened before we paid attention to the MSG_EOR bit ourselves. TBR=pthatcher@webrtc.org Bug: chromium:884926 Change-Id: I18c773bb60ae724b735a83933eedd030f6360a3c Reviewed-on: https://webrtc-review.googlesource.com/c/103023 Commit-Queue: Jeroen de Borst <jeroendb@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Qingsi Wang <qingsi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24935}
This commit is contained in:
parent
5fb245498c
commit
ad5465b443
@ -295,14 +295,31 @@ class SctpTransport::UsrSctpWrapper {
|
||||
} else {
|
||||
ReceiveDataParams params;
|
||||
|
||||
// Expect only continuation messages belonging to the same sid, usrsctp
|
||||
// ensures this.
|
||||
RTC_CHECK(transport->partial_message_.size() == 0 ||
|
||||
rcv.rcv_sid == transport->partial_message_sid_);
|
||||
params.sid = rcv.rcv_sid;
|
||||
params.seq_num = rcv.rcv_ssn;
|
||||
params.timestamp = rcv.rcv_tsn;
|
||||
params.type = type;
|
||||
|
||||
// Expect only continuation messages belonging to the same sid, the sctp
|
||||
// stack should ensure this.
|
||||
if ((transport->partial_message_.size() != 0) &&
|
||||
(rcv.rcv_sid != transport->partial_params_.sid)) {
|
||||
// A message with a new sid, but haven't seen the EOR for the
|
||||
// previous message. Deliver the previous partial message to avoid
|
||||
// merging messages from different sid's.
|
||||
transport->invoker_.AsyncInvoke<void>(
|
||||
RTC_FROM_HERE, transport->network_thread_,
|
||||
rtc::Bind(&SctpTransport::OnInboundPacketFromSctpToTransport,
|
||||
transport, transport->partial_message_,
|
||||
transport->partial_params_, transport->partial_flags_));
|
||||
|
||||
transport->partial_message_.Clear();
|
||||
}
|
||||
|
||||
transport->partial_message_.AppendData(reinterpret_cast<uint8_t*>(data),
|
||||
length);
|
||||
transport->partial_message_sid_ = rcv.rcv_sid;
|
||||
transport->partial_params_ = params;
|
||||
transport->partial_flags_ = flags;
|
||||
|
||||
free(data);
|
||||
|
||||
@ -315,11 +332,6 @@ class SctpTransport::UsrSctpWrapper {
|
||||
return 1;
|
||||
}
|
||||
|
||||
params.sid = rcv.rcv_sid;
|
||||
params.seq_num = rcv.rcv_ssn;
|
||||
params.timestamp = rcv.rcv_tsn;
|
||||
params.type = type;
|
||||
|
||||
// The ownership of the packet transfers to |invoker_|. Using
|
||||
// CopyOnWriteBuffer is the most convenient way to do this.
|
||||
transport->invoker_.AsyncInvoke<void>(
|
||||
|
||||
@ -146,7 +146,8 @@ class SctpTransport : public SctpTransportInternal,
|
||||
// Track the data received from usrsctp between callbacks until the EOR bit
|
||||
// arrives.
|
||||
rtc::CopyOnWriteBuffer partial_message_;
|
||||
int partial_message_sid_;
|
||||
ReceiveDataParams partial_params_;
|
||||
int partial_flags_;
|
||||
|
||||
bool was_ever_writable_ = false;
|
||||
int local_port_ = kSctpDefaultPort;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user