@@ -22,6 +22,7 @@ enum PreservedErrno {
22
22
#include < stdio.h>
23
23
24
24
#include < memory>
25
+ #include < unordered_map>
25
26
26
27
#include " absl/algorithm/container.h"
27
28
#include " absl/base/attributes.h"
@@ -39,6 +40,7 @@ enum PreservedErrno {
39
40
#include " rtc_base/logging.h"
40
41
#include " rtc_base/numerics/safe_conversions.h"
41
42
#include " rtc_base/string_utils.h"
43
+ #include " rtc_base/thread_annotations.h"
42
44
#include " rtc_base/thread_checker.h"
43
45
#include " rtc_base/trace_event.h"
44
46
#include " usrsctplib/usrsctp.h"
@@ -72,6 +74,59 @@ enum PayloadProtocolIdentifier {
72
74
PPID_TEXT_LAST = 51
73
75
};
74
76
77
+ // Maps SCTP transport ID to SctpTransport object, necessary in send threshold
78
+ // callback and outgoing packet callback.
79
+ // TODO(crbug.com/1076703): Remove once the underlying problem is fixed or
80
+ // workaround is provided in usrsctp.
81
+ class SctpTransportMap {
82
+ public:
83
+ SctpTransportMap () = default ;
84
+
85
+ // Assigns a new unused ID to the following transport.
86
+ uintptr_t Register (cricket::SctpTransport* transport) {
87
+ rtc::CritScope cs (&lock_);
88
+ // usrsctp_connect fails with a value of 0...
89
+ if (next_id_ == 0 ) {
90
+ ++next_id_;
91
+ }
92
+ // In case we've wrapped around and need to find an empty spot from a
93
+ // removed transport. Assumes we'll never be full.
94
+ while (map_.find (next_id_) != map_.end ()) {
95
+ ++next_id_;
96
+ if (next_id_ == 0 ) {
97
+ ++next_id_;
98
+ }
99
+ };
100
+ map_[next_id_] = transport;
101
+ return next_id_++;
102
+ }
103
+
104
+ // Returns true if found.
105
+ bool Deregister (uintptr_t id) {
106
+ rtc::CritScope cs (&lock_);
107
+ return map_.erase (id) > 0 ;
108
+ }
109
+
110
+ cricket::SctpTransport* Retrieve (uintptr_t id) const {
111
+ rtc::CritScope cs (&lock_);
112
+ auto it = map_.find (id);
113
+ if (it == map_.end ()) {
114
+ return nullptr ;
115
+ }
116
+ return it->second ;
117
+ }
118
+
119
+ private:
120
+ rtc::CriticalSection lock_;
121
+
122
+ uintptr_t next_id_ RTC_GUARDED_BY (lock_) = 0;
123
+ std::unordered_map<uintptr_t , cricket::SctpTransport*> map_
124
+ RTC_GUARDED_BY (lock_);
125
+ };
126
+
127
+ // Should only be modified by UsrSctpWrapper.
128
+ ABSL_CONST_INIT SctpTransportMap* g_transport_map_ = nullptr ;
129
+
75
130
// Helper for logging SCTP messages.
76
131
#if defined(__GNUC__)
77
132
__attribute__ ((__format__(__printf__, 1 , 2 )))
@@ -242,9 +297,12 @@ class SctpTransport::UsrSctpWrapper {
242
297
// Set the number of default outgoing streams. This is the number we'll
243
298
// send in the SCTP INIT message.
244
299
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default (kMaxSctpStreams );
300
+
301
+ g_transport_map_ = new SctpTransportMap ();
245
302
}
246
303
247
304
static void UninitializeUsrSctp () {
305
+ delete g_transport_map_;
248
306
RTC_LOG (LS_INFO) << __FUNCTION__;
249
307
// usrsctp_finish() may fail if it's called too soon after the transports
250
308
// are
@@ -282,7 +340,14 @@ class SctpTransport::UsrSctpWrapper {
282
340
size_t length,
283
341
uint8_t tos,
284
342
uint8_t set_df) {
285
- SctpTransport* transport = static_cast <SctpTransport*>(addr);
343
+ SctpTransport* transport =
344
+ g_transport_map_->Retrieve (reinterpret_cast <uintptr_t >(addr));
345
+ if (!transport) {
346
+ RTC_LOG (LS_ERROR)
347
+ << " OnSctpOutboundPacket: Failed to get transport for socket ID "
348
+ << addr;
349
+ return EINVAL;
350
+ }
286
351
RTC_LOG (LS_VERBOSE) << " global OnSctpOutboundPacket():"
287
352
" addr: "
288
353
<< addr << " ; length: " << length
@@ -392,14 +457,14 @@ class SctpTransport::UsrSctpWrapper {
392
457
return nullptr ;
393
458
}
394
459
// usrsctp_getladdrs() returns the addresses bound to this socket, which
395
- // contains the SctpTransport* as sconn_addr. Read the pointer ,
460
+ // contains the SctpTransport id as sconn_addr. Read the id ,
396
461
// then free the list of addresses once we have the pointer. We only open
397
462
// AF_CONN sockets, and they should all have the sconn_addr set to the
398
- // pointer that created them, so [0] is as good as any other.
463
+ // id of the transport that created them, so [0] is as good as any other.
399
464
struct sockaddr_conn * sconn =
400
465
reinterpret_cast <struct sockaddr_conn *>(&addrs[0 ]);
401
- SctpTransport* transport =
402
- reinterpret_cast <SctpTransport* >(sconn->sconn_addr );
466
+ SctpTransport* transport = g_transport_map_-> Retrieve (
467
+ reinterpret_cast <uintptr_t >(sconn->sconn_addr ) );
403
468
usrsctp_freeladdrs (addrs);
404
469
405
470
return transport;
@@ -779,9 +844,10 @@ bool SctpTransport::OpenSctpSocket() {
779
844
UsrSctpWrapper::DecrementUsrSctpUsageCount ();
780
845
return false ;
781
846
}
782
- // Register this class as an address for usrsctp. This is used by SCTP to
847
+ id_ = g_transport_map_->Register (this );
848
+ // Register our id as an address for usrsctp. This is used by SCTP to
783
849
// direct the packets received (by the created socket) to this class.
784
- usrsctp_register_address (this );
850
+ usrsctp_register_address (reinterpret_cast < void *>(id_) );
785
851
return true ;
786
852
}
787
853
@@ -872,7 +938,8 @@ void SctpTransport::CloseSctpSocket() {
872
938
// discarded instead of being sent.
873
939
usrsctp_close (sock_);
874
940
sock_ = nullptr ;
875
- usrsctp_deregister_address (this );
941
+ usrsctp_deregister_address (reinterpret_cast <void *>(id_));
942
+ RTC_CHECK (g_transport_map_->Deregister (id_));
876
943
UsrSctpWrapper::DecrementUsrSctpUsageCount ();
877
944
ready_to_send_data_ = false ;
878
945
}
@@ -1003,7 +1070,7 @@ void SctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
1003
1070
// will be will be given to the global OnSctpInboundData, and then,
1004
1071
// marshalled by the AsyncInvoker.
1005
1072
VerboseLogPacket (data, len, SCTP_DUMP_INBOUND);
1006
- usrsctp_conninput (this , data, len, 0 );
1073
+ usrsctp_conninput (reinterpret_cast < void *>(id_) , data, len, 0 );
1007
1074
} else {
1008
1075
// TODO(ldixon): Consider caching the packet for very slightly better
1009
1076
// reliability.
@@ -1033,7 +1100,7 @@ sockaddr_conn SctpTransport::GetSctpSockAddr(int port) {
1033
1100
#endif
1034
1101
// Note: conversion from int to uint16_t happens here.
1035
1102
sconn.sconn_port = rtc::HostToNetwork16 (port);
1036
- sconn.sconn_addr = this ;
1103
+ sconn.sconn_addr = reinterpret_cast < void *>(id_) ;
1037
1104
return sconn;
1038
1105
}
1039
1106
0 commit comments