• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params.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, &params,
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(&notification.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