Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: webrtc/media/sctp/sctpdataengine.cc

Issue 1995993002: Only initialize usrsctp when it's used and uninitialize when it's not being used. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Change debug_name_ to be const char*, remove unused method and rename the other to for_testing Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/media/sctp/sctpdataengine.h ('k') | webrtc/media/sctp/sctpdataengine_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/media/sctp/sctpdataengine.h" 11 #include "webrtc/media/sctp/sctpdataengine.h"
12 12
13 #include <stdarg.h> 13 #include <stdarg.h>
14 #include <stdio.h> 14 #include <stdio.h>
15 15
16 #include <memory> 16 #include <memory>
17 #include <sstream> 17 #include <sstream>
18 #include <vector> 18 #include <vector>
19 19
20 #include "usrsctplib/usrsctp.h" 20 #include "usrsctplib/usrsctp.h"
21 #include "webrtc/base/arraysize.h" 21 #include "webrtc/base/arraysize.h"
22 #include "webrtc/base/copyonwritebuffer.h" 22 #include "webrtc/base/copyonwritebuffer.h"
23 #include "webrtc/base/criticalsection.h"
23 #include "webrtc/base/helpers.h" 24 #include "webrtc/base/helpers.h"
24 #include "webrtc/base/logging.h" 25 #include "webrtc/base/logging.h"
25 #include "webrtc/base/safe_conversions.h" 26 #include "webrtc/base/safe_conversions.h"
26 #include "webrtc/media/base/codec.h" 27 #include "webrtc/media/base/codec.h"
27 #include "webrtc/media/base/mediaconstants.h" 28 #include "webrtc/media/base/mediaconstants.h"
28 #include "webrtc/media/base/streamparams.h" 29 #include "webrtc/media/base/streamparams.h"
29 30
31 namespace cricket {
32 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
33 // take off 80 bytes for DTLS/TURN/TCP/IP overhead.
34 static const size_t kSctpMtu = 1200;
35
36 // The size of the SCTP association send buffer. 256kB, the usrsctp default.
37 static const int kSendBufferSize = 262144;
38
39 struct SctpInboundPacket {
40 rtc::CopyOnWriteBuffer buffer;
41 ReceiveDataParams params;
42 // The |flags| parameter is used by SCTP to distinguish notification packets
43 // from other types of packets.
44 int flags;
45 };
46
30 namespace { 47 namespace {
31 typedef cricket::SctpDataMediaChannel::StreamSet StreamSet; 48 // Set the initial value of the static SCTP Data Engines reference count.
49 int g_usrsctp_usage_count = 0;
50 rtc::GlobalLockPod g_usrsctp_lock_;
51
52 typedef SctpDataMediaChannel::StreamSet StreamSet;
53
32 // Returns a comma-separated, human-readable list of the stream IDs in 's' 54 // Returns a comma-separated, human-readable list of the stream IDs in 's'
33 std::string ListStreams(const StreamSet& s) { 55 std::string ListStreams(const StreamSet& s) {
34 std::stringstream result; 56 std::stringstream result;
35 bool first = true; 57 bool first = true;
36 for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) { 58 for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) {
37 if (!first) { 59 if (!first) {
38 result << ", " << *it; 60 result << ", " << *it;
39 } else { 61 } else {
40 result << *it; 62 result << *it;
41 first = false; 63 first = false;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 std::stringstream result; 100 std::stringstream result;
79 for (int i = 0; i < num_elems; ++i) { 101 for (int i = 0; i < num_elems; ++i) {
80 if (i) { 102 if (i) {
81 result << ", " << array[i]; 103 result << ", " << array[i];
82 } else { 104 } else {
83 result << array[i]; 105 result << array[i];
84 } 106 }
85 } 107 }
86 return result.str(); 108 return result.str();
87 } 109 }
88 } // namespace
89 110
90 namespace cricket {
91 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; 111 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage;
92 typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage; 112 typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage;
93 113
94 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
95 // take off 80 bytes for DTLS/TURN/TCP/IP overhead.
96 static const size_t kSctpMtu = 1200;
97
98 // The size of the SCTP association send buffer. 256kB, the usrsctp default.
99 static const int kSendBufferSize = 262144;
100 enum { 114 enum {
101 MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket 115 MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket
102 MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer 116 MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer
103 }; 117 };
104 118
105 struct SctpInboundPacket {
106 rtc::CopyOnWriteBuffer buffer;
107 ReceiveDataParams params;
108 // The |flags| parameter is used by SCTP to distinguish notification packets
109 // from other types of packets.
110 int flags;
111 };
112
113 // Helper for logging SCTP messages. 119 // Helper for logging SCTP messages.
114 static void debug_sctp_printf(const char *format, ...) { 120 void DebugSctpPrintf(const char* format, ...) {
121 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
115 char s[255]; 122 char s[255];
116 va_list ap; 123 va_list ap;
117 va_start(ap, format); 124 va_start(ap, format);
118 vsnprintf(s, sizeof(s), format, ap); 125 vsnprintf(s, sizeof(s), format, ap);
119 LOG(LS_INFO) << "SCTP: " << s; 126 LOG(LS_INFO) << "SCTP: " << s;
120 va_end(ap); 127 va_end(ap);
128 #endif
121 } 129 }
122 130
123 // Get the PPID to use for the terminating fragment of this type. 131 // Get the PPID to use for the terminating fragment of this type.
124 static SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid( 132 SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid(DataMessageType type) {
125 cricket::DataMessageType type) {
126 switch (type) { 133 switch (type) {
127 default: 134 default:
128 case cricket::DMT_NONE: 135 case DMT_NONE:
129 return SctpDataMediaChannel::PPID_NONE; 136 return SctpDataMediaChannel::PPID_NONE;
130 case cricket::DMT_CONTROL: 137 case DMT_CONTROL:
131 return SctpDataMediaChannel::PPID_CONTROL; 138 return SctpDataMediaChannel::PPID_CONTROL;
132 case cricket::DMT_BINARY: 139 case DMT_BINARY:
133 return SctpDataMediaChannel::PPID_BINARY_LAST; 140 return SctpDataMediaChannel::PPID_BINARY_LAST;
134 case cricket::DMT_TEXT: 141 case DMT_TEXT:
135 return SctpDataMediaChannel::PPID_TEXT_LAST; 142 return SctpDataMediaChannel::PPID_TEXT_LAST;
136 }; 143 };
137 } 144 }
138 145
139 static bool GetDataMediaType( 146 bool GetDataMediaType(SctpDataMediaChannel::PayloadProtocolIdentifier ppid,
140 SctpDataMediaChannel::PayloadProtocolIdentifier ppid, 147 DataMessageType* dest) {
141 cricket::DataMessageType *dest) {
142 ASSERT(dest != NULL); 148 ASSERT(dest != NULL);
143 switch (ppid) { 149 switch (ppid) {
144 case SctpDataMediaChannel::PPID_BINARY_PARTIAL: 150 case SctpDataMediaChannel::PPID_BINARY_PARTIAL:
145 case SctpDataMediaChannel::PPID_BINARY_LAST: 151 case SctpDataMediaChannel::PPID_BINARY_LAST:
146 *dest = cricket::DMT_BINARY; 152 *dest = DMT_BINARY;
147 return true; 153 return true;
148 154
149 case SctpDataMediaChannel::PPID_TEXT_PARTIAL: 155 case SctpDataMediaChannel::PPID_TEXT_PARTIAL:
150 case SctpDataMediaChannel::PPID_TEXT_LAST: 156 case SctpDataMediaChannel::PPID_TEXT_LAST:
151 *dest = cricket::DMT_TEXT; 157 *dest = DMT_TEXT;
152 return true; 158 return true;
153 159
154 case SctpDataMediaChannel::PPID_CONTROL: 160 case SctpDataMediaChannel::PPID_CONTROL:
155 *dest = cricket::DMT_CONTROL; 161 *dest = DMT_CONTROL;
156 return true; 162 return true;
157 163
158 case SctpDataMediaChannel::PPID_NONE: 164 case SctpDataMediaChannel::PPID_NONE:
159 *dest = cricket::DMT_NONE; 165 *dest = DMT_NONE;
160 return true; 166 return true;
161 167
162 default: 168 default:
163 return false; 169 return false;
164 } 170 }
165 } 171 }
166 172
167 // Log the packet in text2pcap format, if log level is at LS_VERBOSE. 173 // Log the packet in text2pcap format, if log level is at LS_VERBOSE.
168 static void VerboseLogPacket(const void *data, size_t length, int direction) { 174 void VerboseLogPacket(const void* data, size_t length, int direction) {
169 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { 175 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
170 char *dump_buf; 176 char *dump_buf;
171 // Some downstream project uses an older version of usrsctp that expects 177 // Some downstream project uses an older version of usrsctp that expects
172 // a non-const "void*" as first parameter when dumping the packet, so we 178 // a non-const "void*" as first parameter when dumping the packet, so we
173 // need to cast the const away here to avoid a compiler error. 179 // need to cast the const away here to avoid a compiler error.
174 if ((dump_buf = usrsctp_dumppacket( 180 if ((dump_buf = usrsctp_dumppacket(
175 const_cast<void*>(data), length, direction)) != NULL) { 181 const_cast<void*>(data), length, direction)) != NULL) {
176 LOG(LS_VERBOSE) << dump_buf; 182 LOG(LS_VERBOSE) << dump_buf;
177 usrsctp_freedumpbuffer(dump_buf); 183 usrsctp_freedumpbuffer(dump_buf);
178 } 184 }
179 } 185 }
180 } 186 }
181 187
182 // This is the callback usrsctp uses when there's data to send on the network 188 // This is the callback usrsctp uses when there's data to send on the network
183 // that has been wrapped appropriatly for the SCTP protocol. 189 // that has been wrapped appropriatly for the SCTP protocol.
184 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, 190 int OnSctpOutboundPacket(void* addr,
185 uint8_t tos, uint8_t set_df) { 191 void* data,
192 size_t length,
193 uint8_t tos,
194 uint8_t set_df) {
186 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 195 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr);
187 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 196 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
188 << "addr: " << addr << "; length: " << length 197 << "addr: " << addr << "; length: " << length
189 << "; tos: " << std::hex << static_cast<int>(tos) 198 << "; tos: " << std::hex << static_cast<int>(tos)
190 << "; set_df: " << std::hex << static_cast<int>(set_df); 199 << "; set_df: " << std::hex << static_cast<int>(set_df);
191 200
192 VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND); 201 VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND);
193 // Note: We have to copy the data; the caller will delete it. 202 // Note: We have to copy the data; the caller will delete it.
194 auto* msg = new OutboundPacketMessage( 203 auto* msg = new OutboundPacketMessage(
195 new rtc::CopyOnWriteBuffer(reinterpret_cast<uint8_t*>(data), length)); 204 new rtc::CopyOnWriteBuffer(reinterpret_cast<uint8_t*>(data), length));
196 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 205 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg);
197 return 0; 206 return 0;
198 } 207 }
199 208
200 // This is the callback called from usrsctp when data has been received, after 209 // This is the callback called from usrsctp when data has been received, after
201 // a packet has been interpreted and parsed by usrsctp and found to contain 210 // a packet has been interpreted and parsed by usrsctp and found to contain
202 // payload data. It is called by a usrsctp thread. It is assumed this function 211 // payload data. It is called by a usrsctp thread. It is assumed this function
203 // will free the memory used by 'data'. 212 // will free the memory used by 'data'.
204 static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, 213 int OnSctpInboundPacket(struct socket* sock,
205 void* data, size_t length, 214 union sctp_sockstore addr,
206 struct sctp_rcvinfo rcv, int flags, 215 void* data,
207 void* ulp_info) { 216 size_t length,
217 struct sctp_rcvinfo rcv,
218 int flags,
219 void* ulp_info) {
208 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info); 220 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info);
209 // Post data to the channel's receiver thread (copying it). 221 // Post data to the channel's receiver thread (copying it).
210 // TODO(ldixon): Unclear if copy is needed as this method is responsible for 222 // TODO(ldixon): Unclear if copy is needed as this method is responsible for
211 // memory cleanup. But this does simplify code. 223 // memory cleanup. But this does simplify code.
212 const SctpDataMediaChannel::PayloadProtocolIdentifier ppid = 224 const SctpDataMediaChannel::PayloadProtocolIdentifier ppid =
213 static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>( 225 static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>(
214 rtc::HostToNetwork32(rcv.rcv_ppid)); 226 rtc::HostToNetwork32(rcv.rcv_ppid));
215 cricket::DataMessageType type = cricket::DMT_NONE; 227 DataMessageType type = DMT_NONE;
216 if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) { 228 if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) {
217 // It's neither a notification nor a recognized data packet. Drop it. 229 // It's neither a notification nor a recognized data packet. Drop it.
218 LOG(LS_ERROR) << "Received an unknown PPID " << ppid 230 LOG(LS_ERROR) << "Received an unknown PPID " << ppid
219 << " on an SCTP packet. Dropping."; 231 << " on an SCTP packet. Dropping.";
220 } else { 232 } else {
221 SctpInboundPacket* packet = new SctpInboundPacket; 233 SctpInboundPacket* packet = new SctpInboundPacket;
222 packet->buffer.SetData(reinterpret_cast<uint8_t*>(data), length); 234 packet->buffer.SetData(reinterpret_cast<uint8_t*>(data), length);
223 packet->params.ssrc = rcv.rcv_sid; 235 packet->params.ssrc = rcv.rcv_sid;
224 packet->params.seq_num = rcv.rcv_ssn; 236 packet->params.seq_num = rcv.rcv_ssn;
225 packet->params.timestamp = rcv.rcv_tsn; 237 packet->params.timestamp = rcv.rcv_tsn;
226 packet->params.type = type; 238 packet->params.type = type;
227 packet->flags = flags; 239 packet->flags = flags;
228 // The ownership of |packet| transfers to |msg|. 240 // The ownership of |packet| transfers to |msg|.
229 InboundPacketMessage* msg = new InboundPacketMessage(packet); 241 InboundPacketMessage* msg = new InboundPacketMessage(packet);
230 channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); 242 channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg);
231 } 243 }
232 free(data); 244 free(data);
233 return 1; 245 return 1;
234 } 246 }
235 247
236 // Set the initial value of the static SCTP Data Engines reference count. 248 void InitializeUsrSctp() {
237 int SctpDataEngine::usrsctp_engines_count = 0; 249 LOG(LS_INFO) << __FUNCTION__;
250 // First argument is udp_encapsulation_port, which is not releveant for our
251 // AF_CONN use of sctp.
252 usrsctp_init(0, &OnSctpOutboundPacket, &DebugSctpPrintf);
238 253
239 SctpDataEngine::SctpDataEngine() { 254 // To turn on/off detailed SCTP debugging. You will also need to have the
240 if (usrsctp_engines_count == 0) { 255 // SCTP_DEBUG cpp defines flag.
241 // First argument is udp_encapsulation_port, which is not releveant for our 256 // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
242 // AF_CONN use of sctp.
243 usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf);
244 257
245 // To turn on/off detailed SCTP debugging. You will also need to have the 258 // TODO(ldixon): Consider turning this on/off.
246 // SCTP_DEBUG cpp defines flag. 259 usrsctp_sysctl_set_sctp_ecn_enable(0);
247 // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
248 260
249 // TODO(ldixon): Consider turning this on/off. 261 // This is harmless, but we should find out when the library default
250 usrsctp_sysctl_set_sctp_ecn_enable(0); 262 // changes.
263 int send_size = usrsctp_sysctl_get_sctp_sendspace();
264 if (send_size != kSendBufferSize) {
265 LOG(LS_ERROR) << "Got different send size than expected: " << send_size;
266 }
251 267
252 // This is harmless, but we should find out when the library default 268 // TODO(ldixon): Consider turning this on/off.
253 // changes. 269 // This is not needed right now (we don't do dynamic address changes):
254 int send_size = usrsctp_sysctl_get_sctp_sendspace(); 270 // If SCTP Auto-ASCONF is enabled, the peer is informed automatically
255 if (send_size != kSendBufferSize) { 271 // when a new address is added or removed. This feature is enabled by
256 LOG(LS_ERROR) << "Got different send size than expected: " << send_size; 272 // default.
257 } 273 // usrsctp_sysctl_set_sctp_auto_asconf(0);
258 274
259 // TODO(ldixon): Consider turning this on/off. 275 // TODO(ldixon): Consider turning this on/off.
260 // This is not needed right now (we don't do dynamic address changes): 276 // Add a blackhole sysctl. Setting it to 1 results in no ABORTs
261 // If SCTP Auto-ASCONF is enabled, the peer is informed automatically 277 // being sent in response to INITs, setting it to 2 results
262 // when a new address is added or removed. This feature is enabled by 278 // in no ABORTs being sent for received OOTB packets.
263 // default. 279 // This is similar to the TCP sysctl.
264 // usrsctp_sysctl_set_sctp_auto_asconf(0); 280 //
281 // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
282 // See: http://svnweb.freebsd.org/base?view=revision&revision=229805
283 // usrsctp_sysctl_set_sctp_blackhole(2);
265 284
266 // TODO(ldixon): Consider turning this on/off. 285 // Set the number of default outgoing streams. This is the number we'll
267 // Add a blackhole sysctl. Setting it to 1 results in no ABORTs 286 // send in the SCTP INIT message. The 'appropriate default' in the
268 // being sent in response to INITs, setting it to 2 results 287 // second paragraph of
269 // in no ABORTs being sent for received OOTB packets. 288 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2
270 // This is similar to the TCP sysctl. 289 // is kMaxSctpSid.
271 // 290 usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpSid);
272 // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
273 // See: http://svnweb.freebsd.org/base?view=revision&revision=229805
274 // usrsctp_sysctl_set_sctp_blackhole(2);
275
276 // Set the number of default outgoing streams. This is the number we'll
277 // send in the SCTP INIT message. The 'appropriate default' in the
278 // second paragraph of
279 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2
280 // is cricket::kMaxSctpSid.
281 usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(
282 cricket::kMaxSctpSid);
283 }
284 usrsctp_engines_count++;
285
286 cricket::DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName);
287 codec.SetParam(kCodecParamPort, kSctpDefaultPort);
288 codecs_.push_back(codec);
289 } 291 }
290 292
291 SctpDataEngine::~SctpDataEngine() { 293 void UninitializeUsrSctp() {
292 usrsctp_engines_count--; 294 LOG(LS_INFO) << __FUNCTION__;
293 LOG(LS_VERBOSE) << "usrsctp_engines_count:" << usrsctp_engines_count; 295 // usrsctp_finish() may fail if it's called too soon after the channels are
296 // closed. Wait and try again until it succeeds for up to 3 seconds.
297 for (size_t i = 0; i < 300; ++i) {
298 if (usrsctp_finish() == 0)
299 return;
294 300
295 if (usrsctp_engines_count == 0) { 301 rtc::Thread::SleepMs(10);
296 // usrsctp_finish() may fail if it's called too soon after the channels are
297 // closed. Wait and try again until it succeeds for up to 3 seconds.
298 for (size_t i = 0; i < 300; ++i) {
299 if (usrsctp_finish() == 0)
300 return;
301
302 rtc::Thread::SleepMs(10);
303 }
304 LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
305 } 302 }
303 LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
306 } 304 }
307 305
306 void IncrementUsrSctpUsageCount() {
307 rtc::GlobalLockScope lock(&g_usrsctp_lock_);
308 if (!g_usrsctp_usage_count)
Taylor Brandstetter 2016/05/19 15:53:13 nit: We use {}s even for 1-line if statements.
tommi 2016/05/19 16:54:12 Done. (here and in a couple of other places)
309 InitializeUsrSctp();
310 ++g_usrsctp_usage_count;
311 }
312
313 void DecrementUsrSctpUsageCount() {
314 rtc::GlobalLockScope lock(&g_usrsctp_lock_);
315 --g_usrsctp_usage_count;
316 if (!g_usrsctp_usage_count)
317 UninitializeUsrSctp();
318 }
319
320 DataCodec GetSctpDataCodec() {
321 DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName);
322 codec.SetParam(kCodecParamPort, kSctpDefaultPort);
323 return codec;
324 }
325
326 } // namespace
327
328 SctpDataEngine::SctpDataEngine() : codecs_(1, GetSctpDataCodec()) {}
329
330 SctpDataEngine::~SctpDataEngine() {}
331
332 // Called on the worker thread.
308 DataMediaChannel* SctpDataEngine::CreateChannel( 333 DataMediaChannel* SctpDataEngine::CreateChannel(
309 DataChannelType data_channel_type) { 334 DataChannelType data_channel_type) {
310 if (data_channel_type != DCT_SCTP) { 335 if (data_channel_type != DCT_SCTP) {
311 return NULL; 336 return NULL;
312 } 337 }
313 return new SctpDataMediaChannel(rtc::Thread::Current()); 338 return new SctpDataMediaChannel(rtc::Thread::Current());
314 } 339 }
315 340
341 const std::vector<DataCodec>& SctpDataEngine::data_codecs() {
342 RTC_DCHECK(thread_checker_.CalledOnValidThread());
Taylor Brandstetter 2016/05/19 15:53:13 Is this the only place thread_checker_ is used? Co
tommi 2016/05/19 16:54:12 I've removed the thread checker now and moved the
343 return codecs_;
344 }
345
316 // static 346 // static
317 SctpDataMediaChannel* SctpDataEngine::GetChannelFromSocket( 347 SctpDataMediaChannel* SctpDataMediaChannel::GetChannelFromSocket(
318 struct socket* sock) { 348 struct socket* sock) {
319 struct sockaddr* addrs = nullptr; 349 struct sockaddr* addrs = nullptr;
320 int naddrs = usrsctp_getladdrs(sock, 0, &addrs); 350 int naddrs = usrsctp_getladdrs(sock, 0, &addrs);
321 if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) { 351 if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) {
322 return nullptr; 352 return nullptr;
323 } 353 }
324 // usrsctp_getladdrs() returns the addresses bound to this socket, which 354 // usrsctp_getladdrs() returns the addresses bound to this socket, which
325 // contains the SctpDataMediaChannel* as sconn_addr. Read the pointer, 355 // contains the SctpDataMediaChannel* as sconn_addr. Read the pointer,
326 // then free the list of addresses once we have the pointer. We only open 356 // then free the list of addresses once we have the pointer. We only open
327 // AF_CONN sockets, and they should all have the sconn_addr set to the 357 // AF_CONN sockets, and they should all have the sconn_addr set to the
328 // pointer that created them, so [0] is as good as any other. 358 // pointer that created them, so [0] is as good as any other.
329 struct sockaddr_conn* sconn = 359 struct sockaddr_conn* sconn =
330 reinterpret_cast<struct sockaddr_conn*>(&addrs[0]); 360 reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
331 SctpDataMediaChannel* channel = 361 SctpDataMediaChannel* channel =
332 reinterpret_cast<SctpDataMediaChannel*>(sconn->sconn_addr); 362 reinterpret_cast<SctpDataMediaChannel*>(sconn->sconn_addr);
333 usrsctp_freeladdrs(addrs); 363 usrsctp_freeladdrs(addrs);
334 364
335 return channel; 365 return channel;
336 } 366 }
337 367
338 // static 368 // static
339 int SctpDataEngine::SendThresholdCallback(struct socket* sock, 369 int SctpDataMediaChannel::SendThresholdCallback(struct socket* sock,
340 uint32_t sb_free) { 370 uint32_t sb_free) {
341 // Fired on our I/O thread. SctpDataMediaChannel::OnPacketReceived() gets 371 // Fired on our I/O thread. SctpDataMediaChannel::OnPacketReceived() gets
342 // a packet containing acknowledgments, which goes into usrsctp_conninput, 372 // a packet containing acknowledgments, which goes into usrsctp_conninput,
343 // and then back here. 373 // and then back here.
344 SctpDataMediaChannel* channel = GetChannelFromSocket(sock); 374 SctpDataMediaChannel* channel = GetChannelFromSocket(sock);
345 if (!channel) { 375 if (!channel) {
346 LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket " 376 LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket "
347 << sock; 377 << sock;
348 return 0; 378 return 0;
349 } 379 }
350 channel->OnSendThresholdCallback(); 380 channel->OnSendThresholdCallback();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 return sconn; 412 return sconn;
383 } 413 }
384 414
385 bool SctpDataMediaChannel::OpenSctpSocket() { 415 bool SctpDataMediaChannel::OpenSctpSocket() {
386 if (sock_) { 416 if (sock_) {
387 LOG(LS_VERBOSE) << debug_name_ 417 LOG(LS_VERBOSE) << debug_name_
388 << "->Ignoring attempt to re-create existing socket."; 418 << "->Ignoring attempt to re-create existing socket.";
389 return false; 419 return false;
390 } 420 }
391 421
422 IncrementUsrSctpUsageCount();
423
392 // If kSendBufferSize isn't reflective of reality, we log an error, but we 424 // If kSendBufferSize isn't reflective of reality, we log an error, but we
393 // still have to do something reasonable here. Look up what the buffer's 425 // still have to do something reasonable here. Look up what the buffer's
394 // real size is and set our threshold to something reasonable. 426 // real size is and set our threshold to something reasonable.
395 const static int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 2; 427 const static int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 2;
396 428
397 sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, 429 sock_ = usrsctp_socket(
398 cricket::OnSctpInboundPacket, 430 AF_CONN, SOCK_STREAM, IPPROTO_SCTP, OnSctpInboundPacket,
399 &SctpDataEngine::SendThresholdCallback, 431 &SctpDataMediaChannel::SendThresholdCallback, kSendThreshold, this);
400 kSendThreshold, this);
401 if (!sock_) { 432 if (!sock_) {
402 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; 433 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket.";
434 DecrementUsrSctpUsageCount();
403 return false; 435 return false;
404 } 436 }
405 437
406 // Make the socket non-blocking. Connect, close, shutdown etc will not block 438 // Make the socket non-blocking. Connect, close, shutdown etc will not block
407 // the thread waiting for the socket operation to complete. 439 // the thread waiting for the socket operation to complete.
408 if (usrsctp_set_non_blocking(sock_, 1) < 0) { 440 if (usrsctp_set_non_blocking(sock_, 1) < 0) {
409 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; 441 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking.";
410 return false; 442 return false;
411 } 443 }
412 444
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 513
482 void SctpDataMediaChannel::CloseSctpSocket() { 514 void SctpDataMediaChannel::CloseSctpSocket() {
483 sending_ = false; 515 sending_ = false;
484 if (sock_) { 516 if (sock_) {
485 // We assume that SO_LINGER option is set to close the association when 517 // We assume that SO_LINGER option is set to close the association when
486 // close is called. This means that any pending packets in usrsctp will be 518 // close is called. This means that any pending packets in usrsctp will be
487 // discarded instead of being sent. 519 // discarded instead of being sent.
488 usrsctp_close(sock_); 520 usrsctp_close(sock_);
489 sock_ = NULL; 521 sock_ = NULL;
490 usrsctp_deregister_address(this); 522 usrsctp_deregister_address(this);
523
524 DecrementUsrSctpUsageCount();
491 } 525 }
492 } 526 }
493 527
494 bool SctpDataMediaChannel::Connect() { 528 bool SctpDataMediaChannel::Connect() {
495 LOG(LS_VERBOSE) << debug_name_ << "->Connect()."; 529 LOG(LS_VERBOSE) << debug_name_ << "->Connect().";
496 530
497 // If we already have a socket connection, just return. 531 // If we already have a socket connection, just return.
498 if (sock_) { 532 if (sock_) {
499 LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket " 533 LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket "
500 "is already established."; 534 "is already established.";
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 *result = SDR_ERROR; 626 *result = SDR_ERROR;
593 } 627 }
594 628
595 if (!sending_) { 629 if (!sending_) {
596 LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 630 LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
597 << "Not sending packet with ssrc=" << params.ssrc 631 << "Not sending packet with ssrc=" << params.ssrc
598 << " len=" << payload.size() << " before SetSend(true)."; 632 << " len=" << payload.size() << " before SetSend(true).";
599 return false; 633 return false;
600 } 634 }
601 635
602 if (params.type != cricket::DMT_CONTROL && 636 if (params.type != DMT_CONTROL &&
603 open_streams_.find(params.ssrc) == open_streams_.end()) { 637 open_streams_.find(params.ssrc) == open_streams_.end()) {
604 LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 638 LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
605 << "Not sending data because ssrc is unknown: " 639 << "Not sending data because ssrc is unknown: "
606 << params.ssrc; 640 << params.ssrc;
607 return false; 641 return false;
608 } 642 }
609 643
610 // 644 //
611 // Send data using SCTP. 645 // Send data using SCTP.
612 ssize_t send_res = 0; // result from usrsctp_sendv. 646 ssize_t send_res = 0; // result from usrsctp_sendv.
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 << " len=" << buffer.size() << " before SetReceive(true)."; 744 << " len=" << buffer.size() << " before SetReceive(true).";
711 } 745 }
712 } 746 }
713 747
714 bool SctpDataMediaChannel::AddStream(const StreamParams& stream) { 748 bool SctpDataMediaChannel::AddStream(const StreamParams& stream) {
715 if (!stream.has_ssrcs()) { 749 if (!stream.has_ssrcs()) {
716 return false; 750 return false;
717 } 751 }
718 752
719 const uint32_t ssrc = stream.first_ssrc(); 753 const uint32_t ssrc = stream.first_ssrc();
720 if (ssrc >= cricket::kMaxSctpSid) { 754 if (ssrc >= kMaxSctpSid) {
721 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 755 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
722 << "Not adding data stream '" << stream.id 756 << "Not adding data stream '" << stream.id
723 << "' with ssrc=" << ssrc 757 << "' with ssrc=" << ssrc
724 << " because stream ssrc is too high."; 758 << " because stream ssrc is too high.";
725 return false; 759 return false;
726 } else if (open_streams_.find(ssrc) != open_streams_.end()) { 760 } else if (open_streams_.find(ssrc) != open_streams_.end()) {
727 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 761 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
728 << "Not adding data stream '" << stream.id 762 << "Not adding data stream '" << stream.id
729 << "' with ssrc=" << ssrc 763 << "' with ssrc=" << ssrc
730 << " because stream is already open."; 764 << " because stream is already open.";
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 } 1067 }
1034 case MSG_SCTPOUTBOUNDPACKET: { 1068 case MSG_SCTPOUTBOUNDPACKET: {
1035 std::unique_ptr<OutboundPacketMessage> pdata( 1069 std::unique_ptr<OutboundPacketMessage> pdata(
1036 static_cast<OutboundPacketMessage*>(msg->pdata)); 1070 static_cast<OutboundPacketMessage*>(msg->pdata));
1037 OnPacketFromSctpToNetwork(pdata->data().get()); 1071 OnPacketFromSctpToNetwork(pdata->data().get());
1038 break; 1072 break;
1039 } 1073 }
1040 } 1074 }
1041 } 1075 }
1042 } // namespace cricket 1076 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/media/sctp/sctpdataengine.h ('k') | webrtc/media/sctp/sctpdataengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698