1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <errno.h>
12 namespace {
13 // Some ERRNO values get re-#defined to WSA* equivalents in some talk/
14 // headers. We save the original ones in an enum.
15 enum PreservedErrno {
16 SCTP_EINPROGRESS = EINPROGRESS,
17 SCTP_EWOULDBLOCK = EWOULDBLOCK
18 };
19
20 // Successful return value from usrsctp callbacks. Is not actually used by
21 // usrsctp, but all example programs for usrsctp use 1 as their return value.
22 constexpr int kSctpSuccessReturn = 1;
23
24 } // namespace
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <usrsctp.h>
29
30 #include <memory>
31 #include <unordered_map>
32
33 #include "absl/algorithm/container.h"
34 #include "absl/base/attributes.h"
35 #include "absl/types/optional.h"
36 #include "media/base/codec.h"
37 #include "media/base/media_channel.h"
38 #include "media/base/media_constants.h"
39 #include "media/base/stream_params.h"
40 #include "media/sctp/sctp_transport.h"
41 #include "p2p/base/dtls_transport_internal.h" // For PF_NORMAL
42 #include "rtc_base/arraysize.h"
43 #include "rtc_base/copy_on_write_buffer.h"
44 #include "rtc_base/helpers.h"
45 #include "rtc_base/logging.h"
46 #include "rtc_base/numerics/safe_conversions.h"
47 #include "rtc_base/string_utils.h"
48 #include "rtc_base/synchronization/mutex.h"
49 #include "rtc_base/thread_annotations.h"
50 #include "rtc_base/thread_checker.h"
51 #include "rtc_base/trace_event.h"
52
53 namespace {
54
55 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
56 // take off 80 bytes for DTLS/TURN/TCP/IP overhead.
57 static constexpr size_t kSctpMtu = 1200;
58
59 // Set the initial value of the static SCTP Data Engines reference count.
60 ABSL_CONST_INIT int g_usrsctp_usage_count = 0;
61 ABSL_CONST_INIT bool g_usrsctp_initialized_ = false;
62 ABSL_CONST_INIT webrtc::GlobalMutex g_usrsctp_lock_(absl::kConstInit);
63
64 // DataMessageType is used for the SCTP "Payload Protocol Identifier", as
65 // defined in http://tools.ietf.org/html/rfc4960#section-14.4
66 //
67 // For the list of IANA approved values see:
68 // http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xml
69 // The value is not used by SCTP itself. It indicates the protocol running
70 // on top of SCTP.
71 enum {
72 PPID_NONE = 0, // No protocol is specified.
73 // Matches the PPIDs in mozilla source and
74 // https://datatracker.ietf.org/doc/draft-ietf-rtcweb-data-protocol Sec. 9
75 // They're not yet assigned by IANA.
76 PPID_CONTROL = 50,
77 PPID_BINARY_PARTIAL = 52,
78 PPID_BINARY_LAST = 53,
79 PPID_TEXT_PARTIAL = 54,
80 PPID_TEXT_LAST = 51
81 };
82
83 // Maps SCTP transport ID to SctpTransport object, necessary in send threshold
84 // callback and outgoing packet callback.
85 // TODO(crbug.com/1076703): Remove once the underlying problem is fixed or
86 // workaround is provided in usrsctp.
87 class SctpTransportMap {
88 public:
89 SctpTransportMap() = default;
90
91 // Assigns a new unused ID to the following transport.
Register(cricket::SctpTransport * transport)92 uintptr_t Register(cricket::SctpTransport* transport) {
93 webrtc::MutexLock lock(&lock_);
94 // usrsctp_connect fails with a value of 0...
95 if (next_id_ == 0) {
96 ++next_id_;
97 }
98 // In case we've wrapped around and need to find an empty spot from a
99 // removed transport. Assumes we'll never be full.
100 while (map_.find(next_id_) != map_.end()) {
101 ++next_id_;
102 if (next_id_ == 0) {
103 ++next_id_;
104 }
105 };
106 map_[next_id_] = transport;
107 return next_id_++;
108 }
109
110 // Returns true if found.
Deregister(uintptr_t id)111 bool Deregister(uintptr_t id) {
112 webrtc::MutexLock lock(&lock_);
113 return map_.erase(id) > 0;
114 }
115
Retrieve(uintptr_t id) const116 cricket::SctpTransport* Retrieve(uintptr_t id) const {
117 webrtc::MutexLock lock(&lock_);
118 auto it = map_.find(id);
119 if (it == map_.end()) {
120 return nullptr;
121 }
122 return it->second;
123 }
124
125 private:
126 mutable webrtc::Mutex lock_;
127
128 uintptr_t next_id_ RTC_GUARDED_BY(lock_) = 0;
129 std::unordered_map<uintptr_t, cricket::SctpTransport*> map_
130 RTC_GUARDED_BY(lock_);
131 };
132
133 // Should only be modified by UsrSctpWrapper.
134 ABSL_CONST_INIT SctpTransportMap* g_transport_map_ = nullptr;
135
136 // Helper for logging SCTP messages.
137 #if defined(__GNUC__)
138 __attribute__((__format__(__printf__, 1, 2)))
139 #endif
DebugSctpPrintf(const char * format,...)140 void DebugSctpPrintf(const char* format, ...) {
141 #if RTC_DCHECK_IS_ON
142 char s[255];
143 va_list ap;
144 va_start(ap, format);
145 vsnprintf(s, sizeof(s), format, ap);
146 RTC_LOG(LS_INFO) << "SCTP: " << s;
147 va_end(ap);
148 #endif
149 }
150
151 // Get the PPID to use for the terminating fragment of this type.
GetPpid(cricket::DataMessageType type)152 uint32_t GetPpid(cricket::DataMessageType type) {
153 switch (type) {
154 default:
155 case cricket::DMT_NONE:
156 return PPID_NONE;
157 case cricket::DMT_CONTROL:
158 return PPID_CONTROL;
159 case cricket::DMT_BINARY:
160 return PPID_BINARY_LAST;
161 case cricket::DMT_TEXT:
162 return PPID_TEXT_LAST;
163 }
164 }
165
GetDataMediaType(uint32_t ppid,cricket::DataMessageType * dest)166 bool GetDataMediaType(uint32_t ppid, cricket::DataMessageType* dest) {
167 RTC_DCHECK(dest != NULL);
168 switch (ppid) {
169 case PPID_BINARY_PARTIAL:
170 case PPID_BINARY_LAST:
171 *dest = cricket::DMT_BINARY;
172 return true;
173
174 case PPID_TEXT_PARTIAL:
175 case PPID_TEXT_LAST:
176 *dest = cricket::DMT_TEXT;
177 return true;
178
179 case PPID_CONTROL:
180 *dest = cricket::DMT_CONTROL;
181 return true;
182
183 case PPID_NONE:
184 *dest = cricket::DMT_NONE;
185 return true;
186
187 default:
188 return false;
189 }
190 }
191
192 // Log the packet in text2pcap format, if log level is at LS_VERBOSE.
193 //
194 // In order to turn these logs into a pcap file you can use, first filter the
195 // "SCTP_PACKET" log lines:
196 //
197 // cat chrome_debug.log | grep SCTP_PACKET > filtered.log
198 //
199 // Then run through text2pcap:
200 //
201 // text2pcap -n -l 248 -D -t '%H:%M:%S.' filtered.log filtered.pcapng
202 //
203 // Command flag information:
204 // -n: Outputs to a pcapng file, can specify inbound/outbound packets.
205 // -l: Specifies the link layer header type. 248 means SCTP. See:
206 // http://www.tcpdump.org/linktypes.html
207 // -D: Text before packet specifies if it is inbound or outbound.
208 // -t: Time format.
209 //
210 // Why do all this? Because SCTP goes over DTLS, which is encrypted. So just
211 // getting a normal packet capture won't help you, unless you have the DTLS
212 // keying material.
VerboseLogPacket(const void * data,size_t length,int direction)213 void VerboseLogPacket(const void* data, size_t length, int direction) {
214 if (RTC_LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
215 char* dump_buf;
216 // Some downstream project uses an older version of usrsctp that expects
217 // a non-const "void*" as first parameter when dumping the packet, so we
218 // need to cast the const away here to avoid a compiler error.
219 if ((dump_buf = usrsctp_dumppacket(const_cast<void*>(data), length,
220 direction)) != NULL) {
221 RTC_LOG(LS_VERBOSE) << dump_buf;
222 usrsctp_freedumpbuffer(dump_buf);
223 }
224 }
225 }
226
227 // Creates the sctp_sendv_spa struct used for setting flags in the
228 // sctp_sendv() call.
CreateSctpSendParams(const cricket::SendDataParams & params)229 sctp_sendv_spa CreateSctpSendParams(const cricket::SendDataParams& params) {
230 struct sctp_sendv_spa spa = {0};
231 spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID;
232 spa.sendv_sndinfo.snd_sid = params.sid;
233 spa.sendv_sndinfo.snd_ppid = rtc::HostToNetwork32(GetPpid(params.type));
234 // Explicitly marking the EOR flag turns the usrsctp_sendv call below into a
235 // non atomic operation. This means that the sctp lib might only accept the
236 // message partially. This is done in order to improve throughput, so that we
237 // don't have to wait for an empty buffer to send the max message length, for
238 // example.
239 spa.sendv_sndinfo.snd_flags |= SCTP_EOR;
240
241 // Ordered implies reliable.
242 if (!params.ordered) {
243 spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED;
244 if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) {
245 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
246 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
247 spa.sendv_prinfo.pr_value = params.max_rtx_count;
248 } else {
249 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
250 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
251 spa.sendv_prinfo.pr_value = params.max_rtx_ms;
252 }
253 }
254 return spa;
255 }
256 } // namespace
257
258 namespace cricket {
259
260 // Handles global init/deinit, and mapping from usrsctp callbacks to
261 // SctpTransport calls.
262 class SctpTransport::UsrSctpWrapper {
263 public:
InitializeUsrSctp()264 static void InitializeUsrSctp() {
265 RTC_LOG(LS_INFO) << __FUNCTION__;
266 // UninitializeUsrSctp tries to call usrsctp_finish in a loop for three
267 // seconds; if that failed and we were left in a still-initialized state, we
268 // don't want to call usrsctp_init again as that will result in undefined
269 // behavior.
270 if (g_usrsctp_initialized_) {
271 RTC_LOG(LS_WARNING) << "Not reinitializing usrsctp since last attempt at "
272 "usrsctp_finish failed.";
273 } else {
274 // First argument is udp_encapsulation_port, which is not releveant for
275 // our AF_CONN use of sctp.
276 usrsctp_init(0, &UsrSctpWrapper::OnSctpOutboundPacket, &DebugSctpPrintf);
277 g_usrsctp_initialized_ = true;
278 }
279
280 // To turn on/off detailed SCTP debugging. You will also need to have the
281 // SCTP_DEBUG cpp defines flag, which can be turned on in media/BUILD.gn.
282 // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
283
284 // TODO(ldixon): Consider turning this on/off.
285 usrsctp_sysctl_set_sctp_ecn_enable(0);
286
287 // WebRTC doesn't use these features, so disable them to reduce the
288 // potential attack surface.
289 usrsctp_sysctl_set_sctp_asconf_enable(0);
290 usrsctp_sysctl_set_sctp_auth_enable(0);
291
292 // This is harmless, but we should find out when the library default
293 // changes.
294 int send_size = usrsctp_sysctl_get_sctp_sendspace();
295 if (send_size != kSctpSendBufferSize) {
296 RTC_LOG(LS_ERROR) << "Got different send size than expected: "
297 << send_size;
298 }
299
300 // TODO(ldixon): Consider turning this on/off.
301 // This is not needed right now (we don't do dynamic address changes):
302 // If SCTP Auto-ASCONF is enabled, the peer is informed automatically
303 // when a new address is added or removed. This feature is enabled by
304 // default.
305 // usrsctp_sysctl_set_sctp_auto_asconf(0);
306
307 // TODO(ldixon): Consider turning this on/off.
308 // Add a blackhole sysctl. Setting it to 1 results in no ABORTs
309 // being sent in response to INITs, setting it to 2 results
310 // in no ABORTs being sent for received OOTB packets.
311 // This is similar to the TCP sysctl.
312 //
313 // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
314 // See: http://svnweb.freebsd.org/base?view=revision&revision=229805
315 // usrsctp_sysctl_set_sctp_blackhole(2);
316
317 // Set the number of default outgoing streams. This is the number we'll
318 // send in the SCTP INIT message.
319 usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpStreams);
320
321 g_transport_map_ = new SctpTransportMap();
322 }
323
UninitializeUsrSctp()324 static void UninitializeUsrSctp() {
325 RTC_LOG(LS_INFO) << __FUNCTION__;
326 // usrsctp_finish() may fail if it's called too soon after the transports
327 // are
328 // closed. Wait and try again until it succeeds for up to 3 seconds.
329 for (size_t i = 0; i < 300; ++i) {
330 if (usrsctp_finish() == 0) {
331 g_usrsctp_initialized_ = false;
332 delete g_transport_map_;
333 g_transport_map_ = nullptr;
334 return;
335 }
336
337 rtc::Thread::SleepMs(10);
338 }
339 delete g_transport_map_;
340 g_transport_map_ = nullptr;
341 RTC_LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
342 }
343
IncrementUsrSctpUsageCount()344 static void IncrementUsrSctpUsageCount() {
345 webrtc::GlobalMutexLock lock(&g_usrsctp_lock_);
346 if (!g_usrsctp_usage_count) {
347 InitializeUsrSctp();
348 }
349 ++g_usrsctp_usage_count;
350 }
351
DecrementUsrSctpUsageCount()352 static void DecrementUsrSctpUsageCount() {
353 webrtc::GlobalMutexLock lock(&g_usrsctp_lock_);
354 --g_usrsctp_usage_count;
355 if (!g_usrsctp_usage_count) {
356 UninitializeUsrSctp();
357 }
358 }
359
360 // This is the callback usrsctp uses when there's data to send on the network
361 // that has been wrapped appropriatly for the SCTP protocol.
OnSctpOutboundPacket(void * addr,void * data,size_t length,uint8_t tos,uint8_t set_df)362 static int OnSctpOutboundPacket(void* addr,
363 void* data,
364 size_t length,
365 uint8_t tos,
366 uint8_t set_df) {
367 if (!g_transport_map_) {
368 RTC_LOG(LS_ERROR)
369 << "OnSctpOutboundPacket called after usrsctp uninitialized?";
370 return EINVAL;
371 }
372 SctpTransport* transport =
373 g_transport_map_->Retrieve(reinterpret_cast<uintptr_t>(addr));
374 if (!transport) {
375 RTC_LOG(LS_ERROR)
376 << "OnSctpOutboundPacket: Failed to get transport for socket ID "
377 << addr;
378 return EINVAL;
379 }
380 RTC_LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
381 "addr: "
382 << addr << "; length: " << length
383 << "; tos: " << rtc::ToHex(tos)
384 << "; set_df: " << rtc::ToHex(set_df);
385
386 VerboseLogPacket(data, length, SCTP_DUMP_OUTBOUND);
387 // Note: We have to copy the data; the caller will delete it.
388 rtc::CopyOnWriteBuffer buf(reinterpret_cast<uint8_t*>(data), length);
389 // TODO(deadbeef): Why do we need an AsyncInvoke here? We're already on the
390 // right thread and don't need to unwind the stack.
391 transport->invoker_.AsyncInvoke<void>(
392 RTC_FROM_HERE, transport->network_thread_,
393 rtc::Bind(&SctpTransport::OnPacketFromSctpToNetwork, transport, buf));
394 return 0;
395 }
396
397 // This is the callback called from usrsctp when data has been received, after
398 // a packet has been interpreted and parsed by usrsctp and found to contain
399 // payload data. It is called by a usrsctp thread. It is assumed this function
400 // will free the memory used by 'data'.
OnSctpInboundPacket(struct socket * sock,union sctp_sockstore addr,void * data,size_t length,struct sctp_rcvinfo rcv,int flags,void * ulp_info)401 static int OnSctpInboundPacket(struct socket* sock,
402 union sctp_sockstore addr,
403 void* data,
404 size_t length,
405 struct sctp_rcvinfo rcv,
406 int flags,
407 void* ulp_info) {
408 SctpTransport* transport = GetTransportFromSocket(sock);
409 if (!transport) {
410 RTC_LOG(LS_ERROR)
411 << "OnSctpInboundPacket: Failed to get transport for socket " << sock
412 << "; possibly was already destroyed.";
413 free(data);
414 return 0;
415 }
416 // Sanity check that both methods of getting the SctpTransport pointer
417 // yield the same result.
418 RTC_CHECK_EQ(transport, static_cast<SctpTransport*>(ulp_info));
419 int result =
420 transport->OnDataOrNotificationFromSctp(data, length, rcv, flags);
421 free(data);
422 return result;
423 }
424
GetTransportFromSocket(struct socket * sock)425 static SctpTransport* GetTransportFromSocket(struct socket* sock) {
426 struct sockaddr* addrs = nullptr;
427 int naddrs = usrsctp_getladdrs(sock, 0, &addrs);
428 if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) {
429 return nullptr;
430 }
431 // usrsctp_getladdrs() returns the addresses bound to this socket, which
432 // contains the SctpTransport id as sconn_addr. Read the id,
433 // then free the list of addresses once we have the pointer. We only open
434 // AF_CONN sockets, and they should all have the sconn_addr set to the
435 // id of the transport that created them, so [0] is as good as any other.
436 struct sockaddr_conn* sconn =
437 reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
438 if (!g_transport_map_) {
439 RTC_LOG(LS_ERROR)
440 << "GetTransportFromSocket called after usrsctp uninitialized?";
441 usrsctp_freeladdrs(addrs);
442 return nullptr;
443 }
444 SctpTransport* transport = g_transport_map_->Retrieve(
445 reinterpret_cast<uintptr_t>(sconn->sconn_addr));
446 usrsctp_freeladdrs(addrs);
447
448 return transport;
449 }
450
451 // TODO(crbug.com/webrtc/11899): This is a legacy callback signature, remove
452 // when usrsctp is updated.
SendThresholdCallback(struct socket * sock,uint32_t sb_free)453 static int SendThresholdCallback(struct socket* sock, uint32_t sb_free) {
454 // Fired on our I/O thread. SctpTransport::OnPacketReceived() gets
455 // a packet containing acknowledgments, which goes into usrsctp_conninput,
456 // and then back here.
457 SctpTransport* transport = GetTransportFromSocket(sock);
458 if (!transport) {
459 RTC_LOG(LS_ERROR)
460 << "SendThresholdCallback: Failed to get transport for socket "
461 << sock << "; possibly was already destroyed.";
462 return 0;
463 }
464 transport->OnSendThresholdCallback();
465 return 0;
466 }
467
SendThresholdCallback(struct socket * sock,uint32_t sb_free,void * ulp_info)468 static int SendThresholdCallback(struct socket* sock,
469 uint32_t sb_free,
470 void* ulp_info) {
471 // Fired on our I/O thread. SctpTransport::OnPacketReceived() gets
472 // a packet containing acknowledgments, which goes into usrsctp_conninput,
473 // and then back here.
474 SctpTransport* transport = GetTransportFromSocket(sock);
475 if (!transport) {
476 RTC_LOG(LS_ERROR)
477 << "SendThresholdCallback: Failed to get transport for socket "
478 << sock << "; possibly was already destroyed.";
479 return 0;
480 }
481 // Sanity check that both methods of getting the SctpTransport pointer
482 // yield the same result.
483 RTC_CHECK_EQ(transport, static_cast<SctpTransport*>(ulp_info));
484 transport->OnSendThresholdCallback();
485 return 0;
486 }
487 };
488
SctpTransport(rtc::Thread * network_thread,rtc::PacketTransportInternal * transport)489 SctpTransport::SctpTransport(rtc::Thread* network_thread,
490 rtc::PacketTransportInternal* transport)
491 : network_thread_(network_thread),
492 transport_(transport),
493 was_ever_writable_(transport ? transport->writable() : false) {
494 RTC_DCHECK(network_thread_);
495 RTC_DCHECK_RUN_ON(network_thread_);
496 ConnectTransportSignals();
497 }
498
~SctpTransport()499 SctpTransport::~SctpTransport() {
500 // Close abruptly; no reset procedure.
501 CloseSctpSocket();
502 // It's not strictly necessary to reset these fields to nullptr,
503 // but having these fields set to nullptr is a clear indication that
504 // object was destructed. There was a bug in usrsctp when it
505 // invoked OnSctpOutboundPacket callback for destructed SctpTransport,
506 // which caused obscure SIGSEGV on access to these fields,
507 // having this fields set to nullptr will make it easier to understand
508 // that SctpTransport was destructed and "use-after-free" bug happen.
509 // SIGSEGV error triggered on dereference these pointers will also
510 // be easier to understand due to 0x0 address. All of this assumes
511 // that ASAN is not enabled to detect "use-after-free", which is
512 // currently default configuration.
513 network_thread_ = nullptr;
514 transport_ = nullptr;
515 }
516
SetDtlsTransport(rtc::PacketTransportInternal * transport)517 void SctpTransport::SetDtlsTransport(rtc::PacketTransportInternal* transport) {
518 RTC_DCHECK_RUN_ON(network_thread_);
519 DisconnectTransportSignals();
520 transport_ = transport;
521 ConnectTransportSignals();
522 if (!was_ever_writable_ && transport && transport->writable()) {
523 was_ever_writable_ = true;
524 // New transport is writable, now we can start the SCTP connection if Start
525 // was called already.
526 if (started_) {
527 RTC_DCHECK(!sock_);
528 Connect();
529 }
530 }
531 }
532
Start(int local_sctp_port,int remote_sctp_port,int max_message_size)533 bool SctpTransport::Start(int local_sctp_port,
534 int remote_sctp_port,
535 int max_message_size) {
536 RTC_DCHECK_RUN_ON(network_thread_);
537 if (local_sctp_port == -1) {
538 local_sctp_port = kSctpDefaultPort;
539 }
540 if (remote_sctp_port == -1) {
541 remote_sctp_port = kSctpDefaultPort;
542 }
543 if (max_message_size > kSctpSendBufferSize) {
544 RTC_LOG(LS_ERROR) << "Max message size of " << max_message_size
545 << " is larger than send bufffer size "
546 << kSctpSendBufferSize;
547 return false;
548 }
549 if (max_message_size < 1) {
550 RTC_LOG(LS_ERROR) << "Max message size of " << max_message_size
551 << " is too small";
552 return false;
553 }
554 // We allow changing max_message_size with a second Start() call,
555 // but not changing the port numbers.
556 max_message_size_ = max_message_size;
557 if (started_) {
558 if (local_sctp_port != local_port_ || remote_sctp_port != remote_port_) {
559 RTC_LOG(LS_ERROR)
560 << "Can't change SCTP port after SCTP association formed.";
561 return false;
562 }
563 return true;
564 }
565 local_port_ = local_sctp_port;
566 remote_port_ = remote_sctp_port;
567 started_ = true;
568 RTC_DCHECK(!sock_);
569 // Only try to connect if the DTLS transport has been writable before
570 // (indicating that the DTLS handshake is complete).
571 if (was_ever_writable_) {
572 return Connect();
573 }
574 return true;
575 }
576
OpenStream(int sid)577 bool SctpTransport::OpenStream(int sid) {
578 RTC_DCHECK_RUN_ON(network_thread_);
579 if (sid > kMaxSctpSid) {
580 RTC_LOG(LS_WARNING) << debug_name_
581 << "->OpenStream(...): "
582 "Not adding data stream "
583 "with sid="
584 << sid << " because sid is too high.";
585 return false;
586 }
587 auto it = stream_status_by_sid_.find(sid);
588 if (it == stream_status_by_sid_.end()) {
589 stream_status_by_sid_[sid] = StreamStatus();
590 return true;
591 }
592 if (it->second.is_open()) {
593 RTC_LOG(LS_WARNING) << debug_name_
594 << "->OpenStream(...): "
595 "Not adding data stream "
596 "with sid="
597 << sid << " because stream is already open.";
598 return false;
599 } else {
600 RTC_LOG(LS_WARNING) << debug_name_
601 << "->OpenStream(...): "
602 "Not adding data stream "
603 " with sid="
604 << sid << " because stream is still closing.";
605 return false;
606 }
607 }
608
ResetStream(int sid)609 bool SctpTransport::ResetStream(int sid) {
610 RTC_DCHECK_RUN_ON(network_thread_);
611
612 auto it = stream_status_by_sid_.find(sid);
613 if (it == stream_status_by_sid_.end() || !it->second.is_open()) {
614 RTC_LOG(LS_WARNING) << debug_name_ << "->ResetStream(" << sid
615 << "): stream not open.";
616 return false;
617 }
618
619 RTC_LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << sid
620 << "): "
621 "Queuing RE-CONFIG chunk.";
622 it->second.closure_initiated = true;
623
624 // Signal our stream-reset logic that it should try to send now, if it can.
625 SendQueuedStreamResets();
626
627 // The stream will actually get removed when we get the acknowledgment.
628 return true;
629 }
630
SendData(const SendDataParams & params,const rtc::CopyOnWriteBuffer & payload,SendDataResult * result)631 bool SctpTransport::SendData(const SendDataParams& params,
632 const rtc::CopyOnWriteBuffer& payload,
633 SendDataResult* result) {
634 RTC_DCHECK_RUN_ON(network_thread_);
635
636 if (partial_outgoing_message_.has_value()) {
637 if (result) {
638 *result = SDR_BLOCK;
639 }
640 // Ready to send should get set only when SendData() call gets blocked.
641 ready_to_send_data_ = false;
642 return false;
643 }
644 size_t payload_size = payload.size();
645 OutgoingMessage message(payload, params);
646 SendDataResult send_message_result = SendMessageInternal(&message);
647 if (result) {
648 *result = send_message_result;
649 }
650 if (payload_size == message.size()) {
651 // Nothing was sent.
652 return false;
653 }
654 // If any data is sent, we accept the message. In the case that data was
655 // partially accepted by the sctp library, the remaining is buffered. This
656 // ensures the client does not resend the message.
657 RTC_DCHECK_LT(message.size(), payload_size);
658 if (message.size() > 0) {
659 RTC_DCHECK(!partial_outgoing_message_.has_value());
660 RTC_DLOG(LS_VERBOSE) << "Partially sent message. Buffering the remaining"
661 << message.size() << "/" << payload_size << " bytes.";
662
663 partial_outgoing_message_.emplace(message);
664 }
665 return true;
666 }
667
SendMessageInternal(OutgoingMessage * message)668 SendDataResult SctpTransport::SendMessageInternal(OutgoingMessage* message) {
669 RTC_DCHECK_RUN_ON(network_thread_);
670 if (!sock_) {
671 RTC_LOG(LS_WARNING) << debug_name_
672 << "->SendMessageInternal(...): "
673 "Not sending packet with sid="
674 << message->send_params().sid
675 << " len=" << message->size() << " before Start().";
676 return SDR_ERROR;
677 }
678 if (message->send_params().type != DMT_CONTROL) {
679 auto it = stream_status_by_sid_.find(message->send_params().sid);
680 if (it == stream_status_by_sid_.end() || !it->second.is_open()) {
681 RTC_LOG(LS_WARNING)
682 << debug_name_
683 << "->SendMessageInternal(...): "
684 "Not sending data because sid is unknown or closing: "
685 << message->send_params().sid;
686 return SDR_ERROR;
687 }
688 }
689 if (message->size() > static_cast<size_t>(max_message_size_)) {
690 RTC_LOG(LS_ERROR) << "Attempting to send message of size "
691 << message->size() << " which is larger than limit "
692 << max_message_size_;
693 return SDR_ERROR;
694 }
695
696 // Send data using SCTP.
697 sctp_sendv_spa spa = CreateSctpSendParams(message->send_params());
698 // Note: this send call is not atomic because the EOR bit is set. This means
699 // that usrsctp can partially accept this message and it is our duty to buffer
700 // the rest.
701 ssize_t send_res = usrsctp_sendv(
702 sock_, message->data(), message->size(), NULL, 0, &spa,
703 rtc::checked_cast<socklen_t>(sizeof(spa)), SCTP_SENDV_SPA, 0);
704 if (send_res < 0) {
705 if (errno == SCTP_EWOULDBLOCK) {
706 ready_to_send_data_ = false;
707 RTC_LOG(LS_INFO) << debug_name_
708 << "->SendMessageInternal(...): EWOULDBLOCK returned";
709 return SDR_BLOCK;
710 }
711
712 RTC_LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_
713 << "->SendMessageInternal(...): "
714 " usrsctp_sendv: ";
715 return SDR_ERROR;
716 }
717
718 size_t amount_sent = static_cast<size_t>(send_res);
719 RTC_DCHECK_LE(amount_sent, message->size());
720 message->Advance(amount_sent);
721 // Only way out now is success.
722 return SDR_SUCCESS;
723 }
724
ReadyToSendData()725 bool SctpTransport::ReadyToSendData() {
726 RTC_DCHECK_RUN_ON(network_thread_);
727 return ready_to_send_data_;
728 }
729
ConnectTransportSignals()730 void SctpTransport::ConnectTransportSignals() {
731 RTC_DCHECK_RUN_ON(network_thread_);
732 if (!transport_) {
733 return;
734 }
735 transport_->SignalWritableState.connect(this,
736 &SctpTransport::OnWritableState);
737 transport_->SignalReadPacket.connect(this, &SctpTransport::OnPacketRead);
738 transport_->SignalClosed.connect(this, &SctpTransport::OnClosed);
739 }
740
DisconnectTransportSignals()741 void SctpTransport::DisconnectTransportSignals() {
742 RTC_DCHECK_RUN_ON(network_thread_);
743 if (!transport_) {
744 return;
745 }
746 transport_->SignalWritableState.disconnect(this);
747 transport_->SignalReadPacket.disconnect(this);
748 transport_->SignalClosed.disconnect(this);
749 }
750
Connect()751 bool SctpTransport::Connect() {
752 RTC_DCHECK_RUN_ON(network_thread_);
753 RTC_LOG(LS_VERBOSE) << debug_name_ << "->Connect().";
754
755 // If we already have a socket connection (which shouldn't ever happen), just
756 // return.
757 RTC_DCHECK(!sock_);
758 if (sock_) {
759 RTC_LOG(LS_ERROR) << debug_name_
760 << "->Connect(): Ignored as socket "
761 "is already established.";
762 return true;
763 }
764
765 // If no socket (it was closed) try to start it again. This can happen when
766 // the socket we are connecting to closes, does an sctp shutdown handshake,
767 // or behaves unexpectedly causing us to perform a CloseSctpSocket.
768 if (!OpenSctpSocket()) {
769 return false;
770 }
771
772 // Note: conversion from int to uint16_t happens on assignment.
773 sockaddr_conn local_sconn = GetSctpSockAddr(local_port_);
774 if (usrsctp_bind(sock_, reinterpret_cast<sockaddr*>(&local_sconn),
775 sizeof(local_sconn)) < 0) {
776 RTC_LOG_ERRNO(LS_ERROR)
777 << debug_name_ << "->Connect(): " << ("Failed usrsctp_bind");
778 CloseSctpSocket();
779 return false;
780 }
781
782 // Note: conversion from int to uint16_t happens on assignment.
783 sockaddr_conn remote_sconn = GetSctpSockAddr(remote_port_);
784 int connect_result = usrsctp_connect(
785 sock_, reinterpret_cast<sockaddr*>(&remote_sconn), sizeof(remote_sconn));
786 if (connect_result < 0 && errno != SCTP_EINPROGRESS) {
787 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
788 << "->Connect(): "
789 "Failed usrsctp_connect. got errno="
790 << errno << ", but wanted " << SCTP_EINPROGRESS;
791 CloseSctpSocket();
792 return false;
793 }
794 // Set the MTU and disable MTU discovery.
795 // We can only do this after usrsctp_connect or it has no effect.
796 sctp_paddrparams params = {};
797 memcpy(¶ms.spp_address, &remote_sconn, sizeof(remote_sconn));
798 params.spp_flags = SPP_PMTUD_DISABLE;
799 // The MTU value provided specifies the space available for chunks in the
800 // packet, so we subtract the SCTP header size.
801 params.spp_pathmtu = kSctpMtu - sizeof(struct sctp_common_header);
802 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms,
803 sizeof(params))) {
804 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
805 << "->Connect(): "
806 "Failed to set SCTP_PEER_ADDR_PARAMS.";
807 }
808 // Since this is a fresh SCTP association, we'll always start out with empty
809 // queues, so "ReadyToSendData" should be true.
810 SetReadyToSendData();
811 return true;
812 }
813
OpenSctpSocket()814 bool SctpTransport::OpenSctpSocket() {
815 RTC_DCHECK_RUN_ON(network_thread_);
816 if (sock_) {
817 RTC_LOG(LS_WARNING) << debug_name_
818 << "->OpenSctpSocket(): "
819 "Ignoring attempt to re-create existing socket.";
820 return false;
821 }
822
823 UsrSctpWrapper::IncrementUsrSctpUsageCount();
824
825 // If kSctpSendBufferSize isn't reflective of reality, we log an error, but we
826 // still have to do something reasonable here. Look up what the buffer's real
827 // size is and set our threshold to something reasonable.
828 // TODO(bugs.webrtc.org/11824): That was previously set to 50%, not 25%, but
829 // it was reduced to a recent usrsctp regression. Can return to 50% when the
830 // root cause is fixed.
831 static const int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 4;
832
833 sock_ = usrsctp_socket(
834 AF_CONN, SOCK_STREAM, IPPROTO_SCTP, &UsrSctpWrapper::OnSctpInboundPacket,
835 &UsrSctpWrapper::SendThresholdCallback, kSendThreshold, this);
836 if (!sock_) {
837 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
838 << "->OpenSctpSocket(): "
839 "Failed to create SCTP socket.";
840 UsrSctpWrapper::DecrementUsrSctpUsageCount();
841 return false;
842 }
843
844 if (!ConfigureSctpSocket()) {
845 usrsctp_close(sock_);
846 sock_ = nullptr;
847 UsrSctpWrapper::DecrementUsrSctpUsageCount();
848 return false;
849 }
850 id_ = g_transport_map_->Register(this);
851 // Register our id as an address for usrsctp. This is used by SCTP to
852 // direct the packets received (by the created socket) to this class.
853 usrsctp_register_address(reinterpret_cast<void*>(id_));
854 return true;
855 }
856
ConfigureSctpSocket()857 bool SctpTransport::ConfigureSctpSocket() {
858 RTC_DCHECK_RUN_ON(network_thread_);
859 RTC_DCHECK(sock_);
860 // Make the socket non-blocking. Connect, close, shutdown etc will not block
861 // the thread waiting for the socket operation to complete.
862 if (usrsctp_set_non_blocking(sock_, 1) < 0) {
863 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
864 << "->ConfigureSctpSocket(): "
865 "Failed to set SCTP to non blocking.";
866 return false;
867 }
868
869 // This ensures that the usrsctp close call deletes the association. This
870 // prevents usrsctp from calling OnSctpOutboundPacket with references to
871 // this class as the address.
872 linger linger_opt;
873 linger_opt.l_onoff = 1;
874 linger_opt.l_linger = 0;
875 if (usrsctp_setsockopt(sock_, SOL_SOCKET, SO_LINGER, &linger_opt,
876 sizeof(linger_opt))) {
877 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
878 << "->ConfigureSctpSocket(): "
879 "Failed to set SO_LINGER.";
880 return false;
881 }
882
883 // Enable stream ID resets.
884 struct sctp_assoc_value stream_rst;
885 stream_rst.assoc_id = SCTP_ALL_ASSOC;
886 stream_rst.assoc_value = 1;
887 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET,
888 &stream_rst, sizeof(stream_rst))) {
889 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
890 << "->ConfigureSctpSocket(): "
891 "Failed to set SCTP_ENABLE_STREAM_RESET.";
892 return false;
893 }
894
895 // Nagle.
896 uint32_t nodelay = 1;
897 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay,
898 sizeof(nodelay))) {
899 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
900 << "->ConfigureSctpSocket(): "
901 "Failed to set SCTP_NODELAY.";
902 return false;
903 }
904
905 // Explicit EOR.
906 uint32_t eor = 1;
907 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &eor,
908 sizeof(eor))) {
909 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
910 << "->ConfigureSctpSocket(): "
911 "Failed to set SCTP_EXPLICIT_EOR.";
912 return false;
913 }
914
915 // Subscribe to SCTP event notifications.
916 // TODO(crbug.com/1137936): Subscribe to SCTP_SEND_FAILED_EVENT once deadlock
917 // is fixed upstream, or we switch to the upcall API:
918 // https://github.com/sctplab/usrsctp/issues/537
919 int event_types[] = {SCTP_ASSOC_CHANGE, SCTP_PEER_ADDR_CHANGE,
920 SCTP_SENDER_DRY_EVENT, SCTP_STREAM_RESET_EVENT};
921 struct sctp_event event = {0};
922 event.se_assoc_id = SCTP_ALL_ASSOC;
923 event.se_on = 1;
924 for (size_t i = 0; i < arraysize(event_types); i++) {
925 event.se_type = event_types[i];
926 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EVENT, &event,
927 sizeof(event)) < 0) {
928 RTC_LOG_ERRNO(LS_ERROR) << debug_name_
929 << "->ConfigureSctpSocket(): "
930 "Failed to set SCTP_EVENT type: "
931 << event.se_type;
932 return false;
933 }
934 }
935 return true;
936 }
937
CloseSctpSocket()938 void SctpTransport::CloseSctpSocket() {
939 RTC_DCHECK_RUN_ON(network_thread_);
940 if (sock_) {
941 // We assume that SO_LINGER option is set to close the association when
942 // close is called. This means that any pending packets in usrsctp will be
943 // discarded instead of being sent.
944 usrsctp_close(sock_);
945 sock_ = nullptr;
946 usrsctp_deregister_address(reinterpret_cast<void*>(id_));
947 RTC_CHECK(g_transport_map_->Deregister(id_));
948 UsrSctpWrapper::DecrementUsrSctpUsageCount();
949 ready_to_send_data_ = false;
950 }
951 }
952
SendQueuedStreamResets()953 bool SctpTransport::SendQueuedStreamResets() {
954 RTC_DCHECK_RUN_ON(network_thread_);
955
956 // Figure out how many streams need to be reset. We need to do this so we can
957 // allocate the right amount of memory for the sctp_reset_streams structure.
958 size_t num_streams = absl::c_count_if(
959 stream_status_by_sid_,
960 [](const std::map<uint32_t, StreamStatus>::value_type& stream) {
961 return stream.second.need_outgoing_reset();
962 });
963 if (num_streams == 0) {
964 // Nothing to reset.
965 return true;
966 }
967
968 RTC_LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_
969 << "]: Resetting " << num_streams << " outgoing streams.";
970
971 const size_t num_bytes =
972 sizeof(struct sctp_reset_streams) + (num_streams * sizeof(uint16_t));
973 std::vector<uint8_t> reset_stream_buf(num_bytes, 0);
974 struct sctp_reset_streams* resetp =
975 reinterpret_cast<sctp_reset_streams*>(&reset_stream_buf[0]);
976 resetp->srs_assoc_id = SCTP_ALL_ASSOC;
977 resetp->srs_flags = SCTP_STREAM_RESET_OUTGOING;
978 resetp->srs_number_streams = rtc::checked_cast<uint16_t>(num_streams);
979 int result_idx = 0;
980
981 for (const std::map<uint32_t, StreamStatus>::value_type& stream :
982 stream_status_by_sid_) {
983 if (!stream.second.need_outgoing_reset()) {
984 continue;
985 }
986 resetp->srs_stream_list[result_idx++] = stream.first;
987 }
988
989 int ret =
990 usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp,
991 rtc::checked_cast<socklen_t>(reset_stream_buf.size()));
992 if (ret < 0) {
993 // Note that usrsctp only lets us have one reset in progress at a time
994 // (even though multiple streams can be reset at once). If this happens,
995 // SendQueuedStreamResets will end up called after the current in-progress
996 // reset finishes, in OnStreamResetEvent.
997 RTC_LOG_ERRNO(LS_WARNING) << debug_name_
998 << "->SendQueuedStreamResets(): "
999 "Failed to send a stream reset for "
1000 << num_streams << " streams";
1001 return false;
1002 }
1003
1004 // Since the usrsctp call completed successfully, update our stream status
1005 // map to note that we started the outgoing reset.
1006 for (auto it = stream_status_by_sid_.begin();
1007 it != stream_status_by_sid_.end(); ++it) {
1008 if (it->second.need_outgoing_reset()) {
1009 it->second.outgoing_reset_initiated = true;
1010 }
1011 }
1012 return true;
1013 }
1014
SetReadyToSendData()1015 void SctpTransport::SetReadyToSendData() {
1016 RTC_DCHECK_RUN_ON(network_thread_);
1017 if (!ready_to_send_data_) {
1018 ready_to_send_data_ = true;
1019 SignalReadyToSendData();
1020 }
1021 }
1022
SendBufferedMessage()1023 bool SctpTransport::SendBufferedMessage() {
1024 RTC_DCHECK_RUN_ON(network_thread_);
1025 RTC_DCHECK(partial_outgoing_message_.has_value());
1026 RTC_DLOG(LS_VERBOSE) << "Sending partially buffered message of size "
1027 << partial_outgoing_message_->size() << ".";
1028
1029 SendMessageInternal(&partial_outgoing_message_.value());
1030 if (partial_outgoing_message_->size() > 0) {
1031 // Still need to finish sending the message.
1032 return false;
1033 }
1034 RTC_DCHECK_EQ(0u, partial_outgoing_message_->size());
1035 partial_outgoing_message_.reset();
1036 return true;
1037 }
1038
OnWritableState(rtc::PacketTransportInternal * transport)1039 void SctpTransport::OnWritableState(rtc::PacketTransportInternal* transport) {
1040 RTC_DCHECK_RUN_ON(network_thread_);
1041 RTC_DCHECK_EQ(transport_, transport);
1042 if (!was_ever_writable_ && transport->writable()) {
1043 was_ever_writable_ = true;
1044 if (started_) {
1045 Connect();
1046 }
1047 }
1048 }
1049
1050 // Called by network interface when a packet has been received.
OnPacketRead(rtc::PacketTransportInternal * transport,const char * data,size_t len,const int64_t &,int flags)1051 void SctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
1052 const char* data,
1053 size_t len,
1054 const int64_t& /* packet_time_us */,
1055 int flags) {
1056 RTC_DCHECK_RUN_ON(network_thread_);
1057 RTC_DCHECK_EQ(transport_, transport);
1058 TRACE_EVENT0("webrtc", "SctpTransport::OnPacketRead");
1059
1060 if (flags & PF_SRTP_BYPASS) {
1061 // We are only interested in SCTP packets.
1062 return;
1063 }
1064
1065 RTC_LOG(LS_VERBOSE) << debug_name_
1066 << "->OnPacketRead(...): "
1067 " length="
1068 << len << ", started: " << started_;
1069 // Only give receiving packets to usrsctp after if connected. This enables two
1070 // peers to each make a connect call, but for them not to receive an INIT
1071 // packet before they have called connect; least the last receiver of the INIT
1072 // packet will have called connect, and a connection will be established.
1073 if (sock_) {
1074 // Pass received packet to SCTP stack. Once processed by usrsctp, the data
1075 // will be will be given to the global OnSctpInboundData, and then,
1076 // marshalled by the AsyncInvoker.
1077 VerboseLogPacket(data, len, SCTP_DUMP_INBOUND);
1078 usrsctp_conninput(reinterpret_cast<void*>(id_), data, len, 0);
1079 } else {
1080 // TODO(ldixon): Consider caching the packet for very slightly better
1081 // reliability.
1082 }
1083 }
1084
OnClosed(rtc::PacketTransportInternal * transport)1085 void SctpTransport::OnClosed(rtc::PacketTransportInternal* transport) {
1086 SignalClosedAbruptly();
1087 }
1088
OnSendThresholdCallback()1089 void SctpTransport::OnSendThresholdCallback() {
1090 RTC_DCHECK_RUN_ON(network_thread_);
1091 if (partial_outgoing_message_.has_value()) {
1092 if (!SendBufferedMessage()) {
1093 // Did not finish sending the buffered message.
1094 return;
1095 }
1096 }
1097 SetReadyToSendData();
1098 }
1099
GetSctpSockAddr(int port)1100 sockaddr_conn SctpTransport::GetSctpSockAddr(int port) {
1101 sockaddr_conn sconn = {0};
1102 sconn.sconn_family = AF_CONN;
1103 #ifdef HAVE_SCONN_LEN
1104 sconn.sconn_len = sizeof(sockaddr_conn);
1105 #endif
1106 // Note: conversion from int to uint16_t happens here.
1107 sconn.sconn_port = rtc::HostToNetwork16(port);
1108 sconn.sconn_addr = reinterpret_cast<void*>(id_);
1109 return sconn;
1110 }
1111
OnPacketFromSctpToNetwork(const rtc::CopyOnWriteBuffer & buffer)1112 void SctpTransport::OnPacketFromSctpToNetwork(
1113 const rtc::CopyOnWriteBuffer& buffer) {
1114 RTC_DCHECK_RUN_ON(network_thread_);
1115 if (buffer.size() > (kSctpMtu)) {
1116 RTC_LOG(LS_ERROR) << debug_name_
1117 << "->OnPacketFromSctpToNetwork(...): "
1118 "SCTP seems to have made a packet that is bigger "
1119 "than its official MTU: "
1120 << buffer.size() << " vs max of " << kSctpMtu;
1121 }
1122 TRACE_EVENT0("webrtc", "SctpTransport::OnPacketFromSctpToNetwork");
1123
1124 // Don't create noise by trying to send a packet when the DTLS transport isn't
1125 // even writable.
1126 if (!transport_ || !transport_->writable()) {
1127 return;
1128 }
1129
1130 // Bon voyage.
1131 transport_->SendPacket(buffer.data<char>(), buffer.size(),
1132 rtc::PacketOptions(), PF_NORMAL);
1133 }
1134
InjectDataOrNotificationFromSctpForTesting(void * data,size_t length,struct sctp_rcvinfo rcv,int flags)1135 int SctpTransport::InjectDataOrNotificationFromSctpForTesting(
1136 void* data,
1137 size_t length,
1138 struct sctp_rcvinfo rcv,
1139 int flags) {
1140 return OnDataOrNotificationFromSctp(data, length, rcv, flags);
1141 }
1142
OnDataOrNotificationFromSctp(void * data,size_t length,struct sctp_rcvinfo rcv,int flags)1143 int SctpTransport::OnDataOrNotificationFromSctp(void* data,
1144 size_t length,
1145 struct sctp_rcvinfo rcv,
1146 int flags) {
1147 // If data is NULL, the SCTP association has been closed.
1148 if (!data) {
1149 RTC_LOG(LS_INFO) << debug_name_
1150 << "->OnDataOrNotificationFromSctp(...): "
1151 "No data; association closed.";
1152 return kSctpSuccessReturn;
1153 }
1154
1155 // Handle notifications early.
1156 // Note: Notifications are never split into chunks, so they can and should
1157 // be handled early and entirely separate from the reassembly
1158 // process.
1159 if (flags & MSG_NOTIFICATION) {
1160 RTC_LOG(LS_VERBOSE)
1161 << debug_name_
1162 << "->OnDataOrNotificationFromSctp(...): SCTP notification"
1163 << " length=" << length;
1164
1165 // Copy and dispatch asynchronously
1166 rtc::CopyOnWriteBuffer notification(reinterpret_cast<uint8_t*>(data),
1167 length);
1168 invoker_.AsyncInvoke<void>(
1169 RTC_FROM_HERE, network_thread_,
1170 rtc::Bind(&SctpTransport::OnNotificationFromSctp, this, notification));
1171 return kSctpSuccessReturn;
1172 }
1173
1174 // Log data chunk
1175 const uint32_t ppid = rtc::NetworkToHost32(rcv.rcv_ppid);
1176 RTC_LOG(LS_VERBOSE) << debug_name_
1177 << "->OnDataOrNotificationFromSctp(...): SCTP data chunk"
1178 << " length=" << length << ", sid=" << rcv.rcv_sid
1179 << ", ppid=" << ppid << ", ssn=" << rcv.rcv_ssn
1180 << ", cum-tsn=" << rcv.rcv_cumtsn
1181 << ", eor=" << ((flags & MSG_EOR) ? "y" : "n");
1182
1183 // Validate payload protocol identifier
1184 DataMessageType type = DMT_NONE;
1185 if (!GetDataMediaType(ppid, &type)) {
1186 // Unexpected PPID, dropping
1187 RTC_LOG(LS_ERROR) << "Received an unknown PPID " << ppid
1188 << " on an SCTP packet. Dropping.";
1189 return kSctpSuccessReturn;
1190 }
1191
1192 // Expect only continuation messages belonging to the same SID. The SCTP
1193 // stack is expected to ensure this as long as the User Message
1194 // Interleaving extension (RFC 8260) is not explicitly enabled, so this
1195 // merely acts as a safeguard.
1196 if ((partial_incoming_message_.size() != 0) &&
1197 (rcv.rcv_sid != partial_params_.sid)) {
1198 RTC_LOG(LS_ERROR) << "Received a new SID without EOR in the previous"
1199 << " SCTP packet. Discarding the previous packet.";
1200 partial_incoming_message_.Clear();
1201 }
1202
1203 // Copy metadata of interest
1204 ReceiveDataParams params;
1205 params.type = type;
1206 params.sid = rcv.rcv_sid;
1207 // Note that the SSN is identical for each chunk of the same message.
1208 // Furthermore, it is increased per stream and not on the whole
1209 // association.
1210 params.seq_num = rcv.rcv_ssn;
1211 // There is no timestamp field in the SCTP API
1212 params.timestamp = 0;
1213
1214 // Append the chunk's data to the message buffer
1215 partial_incoming_message_.AppendData(reinterpret_cast<uint8_t*>(data),
1216 length);
1217 partial_params_ = params;
1218 partial_flags_ = flags;
1219
1220 // If the message is not yet complete...
1221 if (!(flags & MSG_EOR)) {
1222 if (partial_incoming_message_.size() < kSctpSendBufferSize) {
1223 // We still have space in the buffer. Continue buffering chunks until
1224 // the message is complete before handing it out.
1225 return kSctpSuccessReturn;
1226 } else {
1227 // The sender is exceeding the maximum message size that we announced.
1228 // Spit out a warning but still hand out the partial message. Note that
1229 // this behaviour is undesirable, see the discussion in issue 7774.
1230 //
1231 // TODO(lgrahl): Once sufficient time has passed and all supported
1232 // browser versions obey the announced maximum message size, we should
1233 // abort the SCTP association instead to prevent message integrity
1234 // violation.
1235 RTC_LOG(LS_ERROR) << "Handing out partial SCTP message.";
1236 }
1237 }
1238
1239 // Dispatch the complete message.
1240 // The ownership of the packet transfers to |invoker_|. Using
1241 // CopyOnWriteBuffer is the most convenient way to do this.
1242 invoker_.AsyncInvoke<void>(
1243 RTC_FROM_HERE, network_thread_,
1244 rtc::Bind(&SctpTransport::OnDataFromSctpToTransport, this, params,
1245 partial_incoming_message_));
1246
1247 // Reset the message buffer
1248 partial_incoming_message_.Clear();
1249 return kSctpSuccessReturn;
1250 }
1251
OnDataFromSctpToTransport(const ReceiveDataParams & params,const rtc::CopyOnWriteBuffer & buffer)1252 void SctpTransport::OnDataFromSctpToTransport(
1253 const ReceiveDataParams& params,
1254 const rtc::CopyOnWriteBuffer& buffer) {
1255 RTC_DCHECK_RUN_ON(network_thread_);
1256 RTC_LOG(LS_VERBOSE) << debug_name_
1257 << "->OnDataFromSctpToTransport(...): "
1258 "Posting with length: "
1259 << buffer.size() << " on stream " << params.sid;
1260 // Reports all received messages to upper layers, no matter whether the sid
1261 // is known.
1262 SignalDataReceived(params, buffer);
1263 }
1264
OnNotificationFromSctp(const rtc::CopyOnWriteBuffer & buffer)1265 void SctpTransport::OnNotificationFromSctp(
1266 const rtc::CopyOnWriteBuffer& buffer) {
1267 RTC_DCHECK_RUN_ON(network_thread_);
1268 if (buffer.size() < sizeof(sctp_notification::sn_header)) {
1269 RTC_LOG(LS_ERROR) << "SCTP notification is shorter than header size: "
1270 << buffer.size();
1271 return;
1272 }
1273
1274 const sctp_notification& notification =
1275 reinterpret_cast<const sctp_notification&>(*buffer.data());
1276 if (buffer.size() != notification.sn_header.sn_length) {
1277 RTC_LOG(LS_ERROR) << "SCTP notification length (" << buffer.size()
1278 << ") does not match sn_length field ("
1279 << notification.sn_header.sn_length << ").";
1280 return;
1281 }
1282
1283 // TODO(ldixon): handle notifications appropriately.
1284 switch (notification.sn_header.sn_type) {
1285 case SCTP_ASSOC_CHANGE:
1286 RTC_LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE";
1287 if (buffer.size() < sizeof(notification.sn_assoc_change)) {
1288 RTC_LOG(LS_ERROR)
1289 << "SCTP_ASSOC_CHANGE notification has less than required length: "
1290 << buffer.size();
1291 return;
1292 }
1293 OnNotificationAssocChange(notification.sn_assoc_change);
1294 break;
1295 case SCTP_REMOTE_ERROR:
1296 RTC_LOG(LS_INFO) << "SCTP_REMOTE_ERROR";
1297 break;
1298 case SCTP_SHUTDOWN_EVENT:
1299 RTC_LOG(LS_INFO) << "SCTP_SHUTDOWN_EVENT";
1300 break;
1301 case SCTP_ADAPTATION_INDICATION:
1302 RTC_LOG(LS_INFO) << "SCTP_ADAPTATION_INDICATION";
1303 break;
1304 case SCTP_PARTIAL_DELIVERY_EVENT:
1305 RTC_LOG(LS_INFO) << "SCTP_PARTIAL_DELIVERY_EVENT";
1306 break;
1307 case SCTP_AUTHENTICATION_EVENT:
1308 RTC_LOG(LS_INFO) << "SCTP_AUTHENTICATION_EVENT";
1309 break;
1310 case SCTP_SENDER_DRY_EVENT:
1311 RTC_LOG(LS_VERBOSE) << "SCTP_SENDER_DRY_EVENT";
1312 SetReadyToSendData();
1313 break;
1314 // TODO(ldixon): Unblock after congestion.
1315 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
1316 RTC_LOG(LS_INFO) << "SCTP_NOTIFICATIONS_STOPPED_EVENT";
1317 break;
1318 case SCTP_SEND_FAILED_EVENT: {
1319 if (buffer.size() < sizeof(notification.sn_send_failed_event)) {
1320 RTC_LOG(LS_ERROR) << "SCTP_SEND_FAILED_EVENT notification has less "
1321 "than required length: "
1322 << buffer.size();
1323 return;
1324 }
1325 const struct sctp_send_failed_event& ssfe =
1326 notification.sn_send_failed_event;
1327 RTC_LOG(LS_WARNING) << "SCTP_SEND_FAILED_EVENT: message with"
1328 " PPID = "
1329 << rtc::NetworkToHost32(ssfe.ssfe_info.snd_ppid)
1330 << " SID = " << ssfe.ssfe_info.snd_sid
1331 << " flags = " << rtc::ToHex(ssfe.ssfe_info.snd_flags)
1332 << " failed to sent due to error = "
1333 << rtc::ToHex(ssfe.ssfe_error);
1334 break;
1335 }
1336 case SCTP_STREAM_RESET_EVENT:
1337 if (buffer.size() < sizeof(notification.sn_strreset_event)) {
1338 RTC_LOG(LS_ERROR) << "SCTP_STREAM_RESET_EVENT notification has less "
1339 "than required length: "
1340 << buffer.size();
1341 return;
1342 }
1343 OnStreamResetEvent(¬ification.sn_strreset_event);
1344 break;
1345 case SCTP_ASSOC_RESET_EVENT:
1346 RTC_LOG(LS_INFO) << "SCTP_ASSOC_RESET_EVENT";
1347 break;
1348 case SCTP_STREAM_CHANGE_EVENT:
1349 RTC_LOG(LS_INFO) << "SCTP_STREAM_CHANGE_EVENT";
1350 // An acknowledgment we get after our stream resets have gone through,
1351 // if they've failed. We log the message, but don't react -- we don't
1352 // keep around the last-transmitted set of SSIDs we wanted to close for
1353 // error recovery. It doesn't seem likely to occur, and if so, likely
1354 // harmless within the lifetime of a single SCTP association.
1355 break;
1356 case SCTP_PEER_ADDR_CHANGE:
1357 RTC_LOG(LS_INFO) << "SCTP_PEER_ADDR_CHANGE";
1358 break;
1359 default:
1360 RTC_LOG(LS_WARNING) << "Unknown SCTP event: "
1361 << notification.sn_header.sn_type;
1362 break;
1363 }
1364 }
1365
OnNotificationAssocChange(const sctp_assoc_change & change)1366 void SctpTransport::OnNotificationAssocChange(const sctp_assoc_change& change) {
1367 RTC_DCHECK_RUN_ON(network_thread_);
1368 switch (change.sac_state) {
1369 case SCTP_COMM_UP:
1370 RTC_LOG(LS_VERBOSE) << "Association change SCTP_COMM_UP, stream # is "
1371 << change.sac_outbound_streams << " outbound, "
1372 << change.sac_inbound_streams << " inbound.";
1373 max_outbound_streams_ = change.sac_outbound_streams;
1374 max_inbound_streams_ = change.sac_inbound_streams;
1375 SignalAssociationChangeCommunicationUp();
1376 // In case someone tried to close a stream before communication
1377 // came up, send any queued resets.
1378 SendQueuedStreamResets();
1379 break;
1380 case SCTP_COMM_LOST:
1381 RTC_LOG(LS_INFO) << "Association change SCTP_COMM_LOST";
1382 break;
1383 case SCTP_RESTART:
1384 RTC_LOG(LS_INFO) << "Association change SCTP_RESTART";
1385 break;
1386 case SCTP_SHUTDOWN_COMP:
1387 RTC_LOG(LS_INFO) << "Association change SCTP_SHUTDOWN_COMP";
1388 break;
1389 case SCTP_CANT_STR_ASSOC:
1390 RTC_LOG(LS_INFO) << "Association change SCTP_CANT_STR_ASSOC";
1391 break;
1392 default:
1393 RTC_LOG(LS_INFO) << "Association change UNKNOWN";
1394 break;
1395 }
1396 }
1397
OnStreamResetEvent(const struct sctp_stream_reset_event * evt)1398 void SctpTransport::OnStreamResetEvent(
1399 const struct sctp_stream_reset_event* evt) {
1400 RTC_DCHECK_RUN_ON(network_thread_);
1401
1402 // This callback indicates that a reset is complete for incoming and/or
1403 // outgoing streams. The reset may have been initiated by us or the remote
1404 // side.
1405 const int num_sids = (evt->strreset_length - sizeof(*evt)) /
1406 sizeof(evt->strreset_stream_list[0]);
1407
1408 if (evt->strreset_flags & SCTP_STREAM_RESET_FAILED) {
1409 // OK, just try sending any previously sent stream resets again. The stream
1410 // IDs sent over when the RESET_FIALED flag is set seem to be garbage
1411 // values. Ignore them.
1412 for (std::map<uint32_t, StreamStatus>::value_type& stream :
1413 stream_status_by_sid_) {
1414 stream.second.outgoing_reset_initiated = false;
1415 }
1416 SendQueuedStreamResets();
1417 // TODO(deadbeef): If this happens, the entire SCTP association is in quite
1418 // crippled state. The SCTP session should be dismantled, and the WebRTC
1419 // connectivity errored because is clear that the distant party is not
1420 // playing ball: malforms the transported data.
1421 return;
1422 }
1423
1424 // Loop over the received events and properly update the StreamStatus map.
1425 for (int i = 0; i < num_sids; i++) {
1426 const uint32_t sid = evt->strreset_stream_list[i];
1427 auto it = stream_status_by_sid_.find(sid);
1428 if (it == stream_status_by_sid_.end()) {
1429 // This stream is unknown. Sometimes this can be from a
1430 // RESET_FAILED-related retransmit.
1431 RTC_LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
1432 << "): Unknown sid " << sid;
1433 continue;
1434 }
1435 StreamStatus& status = it->second;
1436
1437 if (evt->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) {
1438 RTC_LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_INCOMING_SSN(" << debug_name_
1439 << "): sid " << sid;
1440 status.incoming_reset_complete = true;
1441 // If we receive an incoming stream reset and we haven't started the
1442 // closing procedure ourselves, this means the remote side started the
1443 // closing procedure; fire a signal so that the relevant data channel
1444 // can change to "closing" (we still need to reset the outgoing stream
1445 // before it changes to "closed").
1446 if (!status.closure_initiated) {
1447 SignalClosingProcedureStartedRemotely(sid);
1448 }
1449 }
1450 if (evt->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) {
1451 RTC_LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_OUTGOING_SSN(" << debug_name_
1452 << "): sid " << sid;
1453 status.outgoing_reset_complete = true;
1454 }
1455
1456 // If this reset completes the closing procedure, remove the stream from
1457 // our map so we can consider it closed, and fire a signal such that the
1458 // relevant DataChannel will change its state to "closed" and its ID can be
1459 // re-used.
1460 if (status.reset_complete()) {
1461 stream_status_by_sid_.erase(it);
1462 SignalClosingProcedureComplete(sid);
1463 }
1464 }
1465
1466 // Always try to send any queued resets because this call indicates that the
1467 // last outgoing or incoming reset has made some progress.
1468 SendQueuedStreamResets();
1469 }
1470
1471 } // namespace cricket
1472