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