aboutsummaryrefslogtreecommitdiff
path: root/media/sctp
diff options
context:
space:
mode:
authorFlorent Castelli <orphis@webrtc.org>2021-06-29 14:58:23 +0200
committerWebRTC LUCI CQ <webrtc-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-06-29 14:37:32 +0000
commitdcb9ffc6f22986bf94e1c06b0d642342a9b9cb55 (patch)
treed2deeaceeadb74dc2b18e5f7f2c994a6930e63fa /media/sctp
parentc362eb2d1c5a639bc2a07e514e144cfb3432101a (diff)
downloadwebrtc-dcb9ffc6f22986bf94e1c06b0d642342a9b9cb55.tar.gz
DataChannel: Propagate SCTP transport errors to the channels
When the transport is terminated, if an error has occured, it will be propagated to the channels. When such errors can happen at the SCTP level (e.g. out of resources), RTCError may contain an error code matching the definition at https://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml#sctp-parameters-24 If the m= line is rejected or removed from SDP, an error will again be sent to the data channels, signaling their unexpected transition to closed. Bug: webrtc:12904 Change-Id: Iea3d8aba0a57bbedb5d03f0fb6f7aba292e92fe8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/223541 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Florent Castelli <orphis@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34386}
Diffstat (limited to 'media/sctp')
-rw-r--r--media/sctp/dcsctp_transport.cc32
-rw-r--r--media/sctp/sctp_transport_internal.h22
-rw-r--r--media/sctp/usrsctp_transport.cc51
3 files changed, 98 insertions, 7 deletions
diff --git a/media/sctp/dcsctp_transport.cc b/media/sctp/dcsctp_transport.cc
index 90fb0e8aca..d913f0cc8d 100644
--- a/media/sctp/dcsctp_transport.cc
+++ b/media/sctp/dcsctp_transport.cc
@@ -73,6 +73,28 @@ absl::optional<DataMessageType> ToDataMessageType(dcsctp::PPID ppid) {
return absl::nullopt;
}
+absl::optional<cricket::SctpErrorCauseCode> ToErrorCauseCode(
+ dcsctp::ErrorKind error) {
+ switch (error) {
+ case dcsctp::ErrorKind::kParseFailed:
+ return cricket::SctpErrorCauseCode::kUnrecognizedParameters;
+ case dcsctp::ErrorKind::kPeerReported:
+ return cricket::SctpErrorCauseCode::kUserInitiatedAbort;
+ case dcsctp::ErrorKind::kWrongSequence:
+ case dcsctp::ErrorKind::kProtocolViolation:
+ return cricket::SctpErrorCauseCode::kProtocolViolation;
+ case dcsctp::ErrorKind::kResourceExhaustion:
+ return cricket::SctpErrorCauseCode::kOutOfResource;
+ case dcsctp::ErrorKind::kTooManyRetries:
+ case dcsctp::ErrorKind::kUnsupportedOperation:
+ case dcsctp::ErrorKind::kNoError:
+ case dcsctp::ErrorKind::kNotConnected:
+ // No SCTP error cause code matches those
+ break;
+ }
+ return absl::nullopt;
+}
+
bool IsEmptyPPID(dcsctp::PPID ppid) {
WebrtcPPID webrtc_ppid = static_cast<WebrtcPPID>(ppid.value());
return webrtc_ppid == WebrtcPPID::kStringEmpty ||
@@ -413,6 +435,14 @@ void DcSctpTransport::OnAborted(dcsctp::ErrorKind error,
<< "->OnAborted(error=" << dcsctp::ToString(error)
<< ", message=" << message << ").";
ready_to_send_data_ = false;
+ RTCError rtc_error(RTCErrorType::OPERATION_ERROR_WITH_DATA,
+ std::string(message));
+ rtc_error.set_error_detail(RTCErrorDetailType::SCTP_FAILURE);
+ auto code = ToErrorCauseCode(error);
+ if (code.has_value()) {
+ rtc_error.set_sctp_cause_code(static_cast<uint16_t>(*code));
+ }
+ SignalClosedAbruptly(rtc_error);
}
void DcSctpTransport::OnConnected() {
@@ -520,7 +550,7 @@ void DcSctpTransport::OnTransportReadPacket(
void DcSctpTransport::OnTransportClosed(
rtc::PacketTransportInternal* transport) {
RTC_LOG(LS_VERBOSE) << debug_name_ << "->OnTransportClosed().";
- SignalClosedAbruptly();
+ SignalClosedAbruptly({});
}
void DcSctpTransport::MaybeConnectSocket() {
diff --git a/media/sctp/sctp_transport_internal.h b/media/sctp/sctp_transport_internal.h
index 96c35ffb93..b1327165b6 100644
--- a/media/sctp/sctp_transport_internal.h
+++ b/media/sctp/sctp_transport_internal.h
@@ -53,6 +53,24 @@ constexpr uint16_t kMinSctpSid = 0;
// usrsctp.h)
const int kSctpDefaultPort = 5000;
+// Error cause codes defined at
+// https://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml#sctp-parameters-24
+enum class SctpErrorCauseCode : uint16_t {
+ kInvalidStreamIdentifier = 1,
+ kMissingMandatoryParameter = 2,
+ kStaleCookieError = 3,
+ kOutOfResource = 4,
+ kUnresolvableAddress = 5,
+ kUnrecognizedChunkType = 6,
+ kInvalidMandatoryParameter = 7,
+ kUnrecognizedParameters = 8,
+ kNoUserData = 9,
+ kCookieReceivedWhileShuttingDown = 10,
+ kRestartWithNewAddresses = 11,
+ kUserInitiatedAbort = 12,
+ kProtocolViolation = 13,
+};
+
// Abstract SctpTransport interface for use internally (by PeerConnection etc.).
// Exists to allow mock/fake SctpTransports to be created.
class SctpTransportInternal {
@@ -137,8 +155,8 @@ class SctpTransportInternal {
// and outgoing streams reset).
sigslot::signal1<int> SignalClosingProcedureComplete;
// Fired when the underlying DTLS transport has closed due to an error
- // or an incoming DTLS disconnect.
- sigslot::signal0<> SignalClosedAbruptly;
+ // or an incoming DTLS disconnect or SCTP transport errors.
+ sigslot::signal1<webrtc::RTCError> SignalClosedAbruptly;
// Helper for debugging.
virtual void set_debug_name_for_testing(const char* debug_name) = 0;
diff --git a/media/sctp/usrsctp_transport.cc b/media/sctp/usrsctp_transport.cc
index d43c017207..7824a72934 100644
--- a/media/sctp/usrsctp_transport.cc
+++ b/media/sctp/usrsctp_transport.cc
@@ -53,6 +53,7 @@ constexpr int kSctpErrorReturn = 0;
#include "rtc_base/thread_annotations.h"
#include "rtc_base/trace_event.h"
+namespace cricket {
namespace {
// The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
@@ -236,9 +237,39 @@ sctp_sendv_spa CreateSctpSendParams(int sid,
}
return spa;
}
-} // namespace
-namespace cricket {
+std::string SctpErrorCauseCodeToString(SctpErrorCauseCode code) {
+ switch (code) {
+ case SctpErrorCauseCode::kInvalidStreamIdentifier:
+ return "Invalid Stream Identifier";
+ case SctpErrorCauseCode::kMissingMandatoryParameter:
+ return "Missing Mandatory Parameter";
+ case SctpErrorCauseCode::kStaleCookieError:
+ return "Stale Cookie Error";
+ case SctpErrorCauseCode::kOutOfResource:
+ return "Out of Resource";
+ case SctpErrorCauseCode::kUnresolvableAddress:
+ return "Unresolvable Address";
+ case SctpErrorCauseCode::kUnrecognizedChunkType:
+ return "Unrecognized Chunk Type";
+ case SctpErrorCauseCode::kInvalidMandatoryParameter:
+ return "Invalid Mandatory Parameter";
+ case SctpErrorCauseCode::kUnrecognizedParameters:
+ return "Unrecognized Parameters";
+ case SctpErrorCauseCode::kNoUserData:
+ return "No User Data";
+ case SctpErrorCauseCode::kCookieReceivedWhileShuttingDown:
+ return "Cookie Received Whilte Shutting Down";
+ case SctpErrorCauseCode::kRestartWithNewAddresses:
+ return "Restart With New Addresses";
+ case SctpErrorCauseCode::kUserInitiatedAbort:
+ return "User Initiated Abort";
+ case SctpErrorCauseCode::kProtocolViolation:
+ return "Protocol Violation";
+ }
+ return "Unknown error";
+}
+} // namespace
// Maps SCTP transport ID to UsrsctpTransport object, necessary in send
// threshold callback and outgoing packet callback. It also provides a facility
@@ -1211,7 +1242,11 @@ void UsrsctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
}
void UsrsctpTransport::OnClosed(rtc::PacketTransportInternal* transport) {
- SignalClosedAbruptly();
+ webrtc::RTCError error =
+ webrtc::RTCError(webrtc::RTCErrorType::OPERATION_ERROR_WITH_DATA,
+ "Transport channel closed");
+ error.set_error_detail(webrtc::RTCErrorDetailType::SCTP_FAILURE);
+ SignalClosedAbruptly(error);
}
void UsrsctpTransport::OnSendThresholdCallback() {
@@ -1497,9 +1532,17 @@ void UsrsctpTransport::OnNotificationAssocChange(
// came up, send any queued resets.
SendQueuedStreamResets();
break;
- case SCTP_COMM_LOST:
+ case SCTP_COMM_LOST: {
RTC_LOG(LS_INFO) << "Association change SCTP_COMM_LOST";
+ webrtc::RTCError error = webrtc::RTCError(
+ webrtc::RTCErrorType::OPERATION_ERROR_WITH_DATA,
+ SctpErrorCauseCodeToString(
+ static_cast<SctpErrorCauseCode>(change.sac_error)));
+ error.set_error_detail(webrtc::RTCErrorDetailType::SCTP_FAILURE);
+ error.set_sctp_cause_code(change.sac_error);
+ SignalClosedAbruptly(error);
break;
+ }
case SCTP_RESTART:
RTC_LOG(LS_INFO) << "Association change SCTP_RESTART";
break;