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(&params.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, &params,
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(&notification.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