1 /* 2 * libjingle SCTP 3 * Copyright 2012 Google Inc, and Robin Seggelmann 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/media/sctp/sctpdataengine.h" 29 30 #include <stdarg.h> 31 #include <stdio.h> 32 #include <sstream> 33 #include <vector> 34 35 #include "talk/media/base/codec.h" 36 #include "talk/media/base/constants.h" 37 #include "talk/media/base/streamparams.h" 38 #include "usrsctplib/usrsctp.h" 39 #include "webrtc/base/buffer.h" 40 #include "webrtc/base/helpers.h" 41 #include "webrtc/base/logging.h" 42 #include "webrtc/base/safe_conversions.h" 43 44 namespace { 45 typedef cricket::SctpDataMediaChannel::StreamSet StreamSet; 46 // Returns a comma-separated, human-readable list of the stream IDs in 's' 47 std::string ListStreams(const StreamSet& s) { 48 std::stringstream result; 49 bool first = true; 50 for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) { 51 if (!first) { 52 result << ", " << *it; 53 } else { 54 result << *it; 55 first = false; 56 } 57 } 58 return result.str(); 59 } 60 61 // Returns a pipe-separated, human-readable list of the SCTP_STREAM_RESET 62 // flags in 'flags' 63 std::string ListFlags(int flags) { 64 std::stringstream result; 65 bool first = true; 66 // Skip past the first 12 chars (strlen("SCTP_STREAM_")) 67 #define MAKEFLAG(X) { X, #X + 12} 68 struct flaginfo_t { 69 int value; 70 const char* name; 71 } flaginfo[] = { 72 MAKEFLAG(SCTP_STREAM_RESET_INCOMING_SSN), 73 MAKEFLAG(SCTP_STREAM_RESET_OUTGOING_SSN), 74 MAKEFLAG(SCTP_STREAM_RESET_DENIED), 75 MAKEFLAG(SCTP_STREAM_RESET_FAILED), 76 MAKEFLAG(SCTP_STREAM_CHANGE_DENIED) 77 }; 78 #undef MAKEFLAG 79 for (int i = 0; i < ARRAY_SIZE(flaginfo); ++i) { 80 if (flags & flaginfo[i].value) { 81 if (!first) result << " | "; 82 result << flaginfo[i].name; 83 first = false; 84 } 85 } 86 return result.str(); 87 } 88 89 // Returns a comma-separated, human-readable list of the integers in 'array'. 90 // All 'num_elems' of them. 91 std::string ListArray(const uint16* array, int num_elems) { 92 std::stringstream result; 93 for (int i = 0; i < num_elems; ++i) { 94 if (i) { 95 result << ", " << array[i]; 96 } else { 97 result << array[i]; 98 } 99 } 100 return result.str(); 101 } 102 } // namespace 103 104 namespace cricket { 105 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; 106 typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; 107 108 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280, 109 // take off 80 bytes for DTLS/TURN/TCP/IP overhead. 110 static const size_t kSctpMtu = 1200; 111 112 enum { 113 MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket 114 MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer 115 }; 116 117 struct SctpInboundPacket { 118 rtc::Buffer buffer; 119 ReceiveDataParams params; 120 // The |flags| parameter is used by SCTP to distinguish notification packets 121 // from other types of packets. 122 int flags; 123 }; 124 125 // Helper for logging SCTP messages. 126 static void debug_sctp_printf(const char *format, ...) { 127 char s[255]; 128 va_list ap; 129 va_start(ap, format); 130 vsnprintf(s, sizeof(s), format, ap); 131 LOG(LS_INFO) << "SCTP: " << s; 132 va_end(ap); 133 } 134 135 // Get the PPID to use for the terminating fragment of this type. 136 static SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid( 137 cricket::DataMessageType type) { 138 switch (type) { 139 default: 140 case cricket::DMT_NONE: 141 return SctpDataMediaChannel::PPID_NONE; 142 case cricket::DMT_CONTROL: 143 return SctpDataMediaChannel::PPID_CONTROL; 144 case cricket::DMT_BINARY: 145 return SctpDataMediaChannel::PPID_BINARY_LAST; 146 case cricket::DMT_TEXT: 147 return SctpDataMediaChannel::PPID_TEXT_LAST; 148 }; 149 } 150 151 static bool GetDataMediaType( 152 SctpDataMediaChannel::PayloadProtocolIdentifier ppid, 153 cricket::DataMessageType *dest) { 154 ASSERT(dest != NULL); 155 switch (ppid) { 156 case SctpDataMediaChannel::PPID_BINARY_PARTIAL: 157 case SctpDataMediaChannel::PPID_BINARY_LAST: 158 *dest = cricket::DMT_BINARY; 159 return true; 160 161 case SctpDataMediaChannel::PPID_TEXT_PARTIAL: 162 case SctpDataMediaChannel::PPID_TEXT_LAST: 163 *dest = cricket::DMT_TEXT; 164 return true; 165 166 case SctpDataMediaChannel::PPID_CONTROL: 167 *dest = cricket::DMT_CONTROL; 168 return true; 169 170 case SctpDataMediaChannel::PPID_NONE: 171 *dest = cricket::DMT_NONE; 172 return true; 173 174 default: 175 return false; 176 } 177 } 178 179 // This is the callback usrsctp uses when there's data to send on the network 180 // that has been wrapped appropriatly for the SCTP protocol. 181 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, 182 uint8_t tos, uint8_t set_df) { 183 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 184 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 185 << "addr: " << addr << "; length: " << length 186 << "; tos: " << std::hex << static_cast<int>(tos) 187 << "; set_df: " << std::hex << static_cast<int>(set_df); 188 // Note: We have to copy the data; the caller will delete it. 189 OutboundPacketMessage* msg = 190 new OutboundPacketMessage(new rtc::Buffer(data, length)); 191 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 192 return 0; 193 } 194 195 // This is the callback called from usrsctp when data has been received, after 196 // a packet has been interpreted and parsed by usrsctp and found to contain 197 // payload data. It is called by a usrsctp thread. It is assumed this function 198 // will free the memory used by 'data'. 199 static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, 200 void* data, size_t length, 201 struct sctp_rcvinfo rcv, int flags, 202 void* ulp_info) { 203 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info); 204 // Post data to the channel's receiver thread (copying it). 205 // TODO(ldixon): Unclear if copy is needed as this method is responsible for 206 // memory cleanup. But this does simplify code. 207 const SctpDataMediaChannel::PayloadProtocolIdentifier ppid = 208 static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>( 209 rtc::HostToNetwork32(rcv.rcv_ppid)); 210 cricket::DataMessageType type = cricket::DMT_NONE; 211 if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) { 212 // It's neither a notification nor a recognized data packet. Drop it. 213 LOG(LS_ERROR) << "Received an unknown PPID " << ppid 214 << " on an SCTP packet. Dropping."; 215 } else { 216 SctpInboundPacket* packet = new SctpInboundPacket; 217 packet->buffer.SetData(data, length); 218 packet->params.ssrc = rcv.rcv_sid; 219 packet->params.seq_num = rcv.rcv_ssn; 220 packet->params.timestamp = rcv.rcv_tsn; 221 packet->params.type = type; 222 packet->flags = flags; 223 // The ownership of |packet| transfers to |msg|. 224 InboundPacketMessage* msg = new InboundPacketMessage(packet); 225 channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); 226 } 227 free(data); 228 return 1; 229 } 230 231 // Set the initial value of the static SCTP Data Engines reference count. 232 int SctpDataEngine::usrsctp_engines_count = 0; 233 234 SctpDataEngine::SctpDataEngine() { 235 if (usrsctp_engines_count == 0) { 236 // First argument is udp_encapsulation_port, which is not releveant for our 237 // AF_CONN use of sctp. 238 usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf); 239 240 // To turn on/off detailed SCTP debugging. You will also need to have the 241 // SCTP_DEBUG cpp defines flag. 242 // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); 243 244 // TODO(ldixon): Consider turning this on/off. 245 usrsctp_sysctl_set_sctp_ecn_enable(0); 246 247 // TODO(ldixon): Consider turning this on/off. 248 // This is not needed right now (we don't do dynamic address changes): 249 // If SCTP Auto-ASCONF is enabled, the peer is informed automatically 250 // when a new address is added or removed. This feature is enabled by 251 // default. 252 // usrsctp_sysctl_set_sctp_auto_asconf(0); 253 254 // TODO(ldixon): Consider turning this on/off. 255 // Add a blackhole sysctl. Setting it to 1 results in no ABORTs 256 // being sent in response to INITs, setting it to 2 results 257 // in no ABORTs being sent for received OOTB packets. 258 // This is similar to the TCP sysctl. 259 // 260 // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html 261 // See: http://svnweb.freebsd.org/base?view=revision&revision=229805 262 // usrsctp_sysctl_set_sctp_blackhole(2); 263 264 // Set the number of default outgoing streams. This is the number we'll 265 // send in the SCTP INIT message. The 'appropriate default' in the 266 // second paragraph of 267 // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2 268 // is cricket::kMaxSctpSid. 269 usrsctp_sysctl_set_sctp_nr_outgoing_streams_default( 270 cricket::kMaxSctpSid); 271 } 272 usrsctp_engines_count++; 273 274 cricket::DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, 0); 275 codec.SetParam(kCodecParamPort, kSctpDefaultPort); 276 codecs_.push_back(codec); 277 } 278 279 SctpDataEngine::~SctpDataEngine() { 280 usrsctp_engines_count--; 281 LOG(LS_VERBOSE) << "usrsctp_engines_count:" << usrsctp_engines_count; 282 283 if (usrsctp_engines_count == 0) { 284 // usrsctp_finish() may fail if it's called too soon after the channels are 285 // closed. Wait and try again until it succeeds for up to 3 seconds. 286 for (size_t i = 0; i < 300; ++i) { 287 if (usrsctp_finish() == 0) 288 return; 289 290 rtc::Thread::SleepMs(10); 291 } 292 LOG(LS_ERROR) << "Failed to shutdown usrsctp."; 293 } 294 } 295 296 DataMediaChannel* SctpDataEngine::CreateChannel( 297 DataChannelType data_channel_type) { 298 if (data_channel_type != DCT_SCTP) { 299 return NULL; 300 } 301 return new SctpDataMediaChannel(rtc::Thread::Current()); 302 } 303 304 SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) 305 : worker_thread_(thread), 306 local_port_(kSctpDefaultPort), 307 remote_port_(kSctpDefaultPort), 308 sock_(NULL), 309 sending_(false), 310 receiving_(false), 311 debug_name_("SctpDataMediaChannel") { 312 } 313 314 SctpDataMediaChannel::~SctpDataMediaChannel() { 315 CloseSctpSocket(); 316 } 317 318 sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { 319 sockaddr_conn sconn = {0}; 320 sconn.sconn_family = AF_CONN; 321 #ifdef HAVE_SCONN_LEN 322 sconn.sconn_len = sizeof(sockaddr_conn); 323 #endif 324 // Note: conversion from int to uint16_t happens here. 325 sconn.sconn_port = rtc::HostToNetwork16(port); 326 sconn.sconn_addr = this; 327 return sconn; 328 } 329 330 bool SctpDataMediaChannel::OpenSctpSocket() { 331 if (sock_) { 332 LOG(LS_VERBOSE) << debug_name_ 333 << "->Ignoring attempt to re-create existing socket."; 334 return false; 335 } 336 sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, 337 cricket::OnSctpInboundPacket, NULL, 0, this); 338 if (!sock_) { 339 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; 340 return false; 341 } 342 343 // Make the socket non-blocking. Connect, close, shutdown etc will not block 344 // the thread waiting for the socket operation to complete. 345 if (usrsctp_set_non_blocking(sock_, 1) < 0) { 346 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; 347 return false; 348 } 349 350 // This ensures that the usrsctp close call deletes the association. This 351 // prevents usrsctp from calling OnSctpOutboundPacket with references to 352 // this class as the address. 353 linger linger_opt; 354 linger_opt.l_onoff = 1; 355 linger_opt.l_linger = 0; 356 if (usrsctp_setsockopt(sock_, SOL_SOCKET, SO_LINGER, &linger_opt, 357 sizeof(linger_opt))) { 358 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SO_LINGER."; 359 return false; 360 } 361 362 // Enable stream ID resets. 363 struct sctp_assoc_value stream_rst; 364 stream_rst.assoc_id = SCTP_ALL_ASSOC; 365 stream_rst.assoc_value = 1; 366 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, 367 &stream_rst, sizeof(stream_rst))) { 368 LOG_ERRNO(LS_ERROR) << debug_name_ 369 << "Failed to set SCTP_ENABLE_STREAM_RESET."; 370 return false; 371 } 372 373 // Nagle. 374 uint32_t nodelay = 1; 375 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, 376 sizeof(nodelay))) { 377 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; 378 return false; 379 } 380 381 // Disable MTU discovery 382 struct sctp_paddrparams params; 383 params.spp_assoc_id = 0; 384 params.spp_flags = SPP_PMTUD_DISABLE; 385 params.spp_pathmtu = kSctpMtu; 386 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, 387 sizeof(params))) { 388 LOG_ERRNO(LS_ERROR) << debug_name_ 389 << "Failed to set SCTP_PEER_ADDR_PARAMS."; 390 return false; 391 } 392 393 // Subscribe to SCTP event notifications. 394 int event_types[] = {SCTP_ASSOC_CHANGE, 395 SCTP_PEER_ADDR_CHANGE, 396 SCTP_SEND_FAILED_EVENT, 397 SCTP_SENDER_DRY_EVENT, 398 SCTP_STREAM_RESET_EVENT}; 399 struct sctp_event event = {0}; 400 event.se_assoc_id = SCTP_ALL_ASSOC; 401 event.se_on = 1; 402 for (size_t i = 0; i < ARRAY_SIZE(event_types); i++) { 403 event.se_type = event_types[i]; 404 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EVENT, &event, 405 sizeof(event)) < 0) { 406 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_EVENT type: " 407 << event.se_type; 408 return false; 409 } 410 } 411 412 // Register this class as an address for usrsctp. This is used by SCTP to 413 // direct the packets received (by the created socket) to this class. 414 usrsctp_register_address(this); 415 sending_ = true; 416 return true; 417 } 418 419 void SctpDataMediaChannel::CloseSctpSocket() { 420 sending_ = false; 421 if (sock_) { 422 // We assume that SO_LINGER option is set to close the association when 423 // close is called. This means that any pending packets in usrsctp will be 424 // discarded instead of being sent. 425 usrsctp_close(sock_); 426 sock_ = NULL; 427 usrsctp_deregister_address(this); 428 } 429 } 430 431 bool SctpDataMediaChannel::Connect() { 432 LOG(LS_VERBOSE) << debug_name_ << "->Connect()."; 433 434 // If we already have a socket connection, just return. 435 if (sock_) { 436 LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket " 437 "is already established."; 438 return true; 439 } 440 441 // If no socket (it was closed) try to start it again. This can happen when 442 // the socket we are connecting to closes, does an sctp shutdown handshake, 443 // or behaves unexpectedly causing us to perform a CloseSctpSocket. 444 if (!sock_ && !OpenSctpSocket()) { 445 return false; 446 } 447 448 // Note: conversion from int to uint16_t happens on assignment. 449 sockaddr_conn local_sconn = GetSctpSockAddr(local_port_); 450 if (usrsctp_bind(sock_, reinterpret_cast<sockaddr *>(&local_sconn), 451 sizeof(local_sconn)) < 0) { 452 LOG_ERRNO(LS_ERROR) << debug_name_ << "->Connect(): " 453 << ("Failed usrsctp_bind"); 454 CloseSctpSocket(); 455 return false; 456 } 457 458 // Note: conversion from int to uint16_t happens on assignment. 459 sockaddr_conn remote_sconn = GetSctpSockAddr(remote_port_); 460 int connect_result = usrsctp_connect( 461 sock_, reinterpret_cast<sockaddr *>(&remote_sconn), sizeof(remote_sconn)); 462 if (connect_result < 0 && errno != SCTP_EINPROGRESS) { 463 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed usrsctp_connect. got errno=" 464 << errno << ", but wanted " << SCTP_EINPROGRESS; 465 CloseSctpSocket(); 466 return false; 467 } 468 return true; 469 } 470 471 void SctpDataMediaChannel::Disconnect() { 472 // TODO(ldixon): Consider calling |usrsctp_shutdown(sock_, ...)| to do a 473 // shutdown handshake and remove the association. 474 CloseSctpSocket(); 475 } 476 477 bool SctpDataMediaChannel::SetSend(bool send) { 478 if (!sending_ && send) { 479 return Connect(); 480 } 481 if (sending_ && !send) { 482 Disconnect(); 483 } 484 return true; 485 } 486 487 bool SctpDataMediaChannel::SetReceive(bool receive) { 488 receiving_ = receive; 489 return true; 490 } 491 492 bool SctpDataMediaChannel::AddSendStream(const StreamParams& stream) { 493 return AddStream(stream); 494 } 495 496 bool SctpDataMediaChannel::RemoveSendStream(uint32 ssrc) { 497 return ResetStream(ssrc); 498 } 499 500 bool SctpDataMediaChannel::AddRecvStream(const StreamParams& stream) { 501 // SCTP DataChannels are always bi-directional and calling AddSendStream will 502 // enable both sending and receiving on the stream. So AddRecvStream is a 503 // no-op. 504 return true; 505 } 506 507 bool SctpDataMediaChannel::RemoveRecvStream(uint32 ssrc) { 508 // SCTP DataChannels are always bi-directional and calling RemoveSendStream 509 // will disable both sending and receiving on the stream. So RemoveRecvStream 510 // is a no-op. 511 return true; 512 } 513 514 bool SctpDataMediaChannel::SendData( 515 const SendDataParams& params, 516 const rtc::Buffer& payload, 517 SendDataResult* result) { 518 if (result) { 519 // Preset |result| to assume an error. If SendData succeeds, we'll 520 // overwrite |*result| once more at the end. 521 *result = SDR_ERROR; 522 } 523 524 if (!sending_) { 525 LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 526 << "Not sending packet with ssrc=" << params.ssrc 527 << " len=" << payload.length() << " before SetSend(true)."; 528 return false; 529 } 530 531 if (params.type != cricket::DMT_CONTROL && 532 open_streams_.find(params.ssrc) == open_streams_.end()) { 533 LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 534 << "Not sending data because ssrc is unknown: " 535 << params.ssrc; 536 return false; 537 } 538 539 // 540 // Send data using SCTP. 541 ssize_t send_res = 0; // result from usrsctp_sendv. 542 struct sctp_sendv_spa spa = {0}; 543 spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID; 544 spa.sendv_sndinfo.snd_sid = params.ssrc; 545 spa.sendv_sndinfo.snd_ppid = rtc::HostToNetwork32( 546 GetPpid(params.type)); 547 548 // Ordered implies reliable. 549 if (!params.ordered) { 550 spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED; 551 if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) { 552 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 553 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX; 554 spa.sendv_prinfo.pr_value = params.max_rtx_count; 555 } else { 556 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 557 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL; 558 spa.sendv_prinfo.pr_value = params.max_rtx_ms; 559 } 560 } 561 562 // We don't fragment. 563 send_res = usrsctp_sendv(sock_, payload.data(), 564 static_cast<size_t>(payload.length()), 565 NULL, 0, &spa, 566 rtc::checked_cast<socklen_t>(sizeof(spa)), 567 SCTP_SENDV_SPA, 0); 568 if (send_res < 0) { 569 if (errno == SCTP_EWOULDBLOCK) { 570 *result = SDR_BLOCK; 571 LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned"; 572 } else { 573 LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_ 574 << "->SendData(...): " 575 << " usrsctp_sendv: "; 576 } 577 return false; 578 } 579 if (result) { 580 // Only way out now is success. 581 *result = SDR_SUCCESS; 582 } 583 return true; 584 } 585 586 // Called by network interface when a packet has been received. 587 void SctpDataMediaChannel::OnPacketReceived( 588 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 589 LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " << " length=" 590 << packet->length() << ", sending: " << sending_; 591 // Only give receiving packets to usrsctp after if connected. This enables two 592 // peers to each make a connect call, but for them not to receive an INIT 593 // packet before they have called connect; least the last receiver of the INIT 594 // packet will have called connect, and a connection will be established. 595 if (sending_) { 596 // Pass received packet to SCTP stack. Once processed by usrsctp, the data 597 // will be will be given to the global OnSctpInboundData, and then, 598 // marshalled by a Post and handled with OnMessage. 599 usrsctp_conninput(this, packet->data(), packet->length(), 0); 600 } else { 601 // TODO(ldixon): Consider caching the packet for very slightly better 602 // reliability. 603 } 604 } 605 606 void SctpDataMediaChannel::OnInboundPacketFromSctpToChannel( 607 SctpInboundPacket* packet) { 608 LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 609 << "Received SCTP data:" 610 << " ssrc=" << packet->params.ssrc 611 << " notification: " << (packet->flags & MSG_NOTIFICATION) 612 << " length=" << packet->buffer.length(); 613 // Sending a packet with data == NULL (no data) is SCTPs "close the 614 // connection" message. This sets sock_ = NULL; 615 if (!packet->buffer.length() || !packet->buffer.data()) { 616 LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 617 "No data, closing."; 618 return; 619 } 620 if (packet->flags & MSG_NOTIFICATION) { 621 OnNotificationFromSctp(&packet->buffer); 622 } else { 623 OnDataFromSctpToChannel(packet->params, &packet->buffer); 624 } 625 } 626 627 void SctpDataMediaChannel::OnDataFromSctpToChannel( 628 const ReceiveDataParams& params, rtc::Buffer* buffer) { 629 if (receiving_) { 630 LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): " 631 << "Posting with length: " << buffer->length() 632 << " on stream " << params.ssrc; 633 // Reports all received messages to upper layers, no matter whether the sid 634 // is known. 635 SignalDataReceived(params, buffer->data(), buffer->length()); 636 } else { 637 LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): " 638 << "Not receiving packet with sid=" << params.ssrc 639 << " len=" << buffer->length() 640 << " before SetReceive(true)."; 641 } 642 } 643 644 bool SctpDataMediaChannel::AddStream(const StreamParams& stream) { 645 if (!stream.has_ssrcs()) { 646 return false; 647 } 648 649 const uint32 ssrc = stream.first_ssrc(); 650 if (open_streams_.find(ssrc) != open_streams_.end()) { 651 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 652 << "Not adding data stream '" << stream.id 653 << "' with ssrc=" << ssrc 654 << " because stream is already open."; 655 return false; 656 } else if (queued_reset_streams_.find(ssrc) != queued_reset_streams_.end() 657 || sent_reset_streams_.find(ssrc) != sent_reset_streams_.end()) { 658 LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 659 << "Not adding data stream '" << stream.id 660 << "' with ssrc=" << ssrc 661 << " because stream is still closing."; 662 return false; 663 } 664 665 open_streams_.insert(ssrc); 666 return true; 667 } 668 669 bool SctpDataMediaChannel::ResetStream(uint32 ssrc) { 670 // We typically get this called twice for the same stream, once each for 671 // Send and Recv. 672 StreamSet::iterator found = open_streams_.find(ssrc); 673 674 if (found == open_streams_.end()) { 675 LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 676 << "stream not found."; 677 return false; 678 } else { 679 LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 680 << "Removing and queuing RE-CONFIG chunk."; 681 open_streams_.erase(found); 682 } 683 684 // SCTP won't let you have more than one stream reset pending at a time, but 685 // you can close multiple streams in a single reset. So, we keep an internal 686 // queue of streams-to-reset, and send them as one reset message in 687 // SendQueuedStreamResets(). 688 queued_reset_streams_.insert(ssrc); 689 690 // Signal our stream-reset logic that it should try to send now, if it can. 691 SendQueuedStreamResets(); 692 693 // The stream will actually get removed when we get the acknowledgment. 694 return true; 695 } 696 697 void SctpDataMediaChannel::OnNotificationFromSctp(rtc::Buffer* buffer) { 698 const sctp_notification& notification = 699 reinterpret_cast<const sctp_notification&>(*buffer->data()); 700 ASSERT(notification.sn_header.sn_length == buffer->length()); 701 702 // TODO(ldixon): handle notifications appropriately. 703 switch (notification.sn_header.sn_type) { 704 case SCTP_ASSOC_CHANGE: 705 LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE"; 706 OnNotificationAssocChange(notification.sn_assoc_change); 707 break; 708 case SCTP_REMOTE_ERROR: 709 LOG(LS_INFO) << "SCTP_REMOTE_ERROR"; 710 break; 711 case SCTP_SHUTDOWN_EVENT: 712 LOG(LS_INFO) << "SCTP_SHUTDOWN_EVENT"; 713 break; 714 case SCTP_ADAPTATION_INDICATION: 715 LOG(LS_INFO) << "SCTP_ADAPTATION_INDICATION"; 716 break; 717 case SCTP_PARTIAL_DELIVERY_EVENT: 718 LOG(LS_INFO) << "SCTP_PARTIAL_DELIVERY_EVENT"; 719 break; 720 case SCTP_AUTHENTICATION_EVENT: 721 LOG(LS_INFO) << "SCTP_AUTHENTICATION_EVENT"; 722 break; 723 case SCTP_SENDER_DRY_EVENT: 724 LOG(LS_VERBOSE) << "SCTP_SENDER_DRY_EVENT"; 725 SignalReadyToSend(true); 726 break; 727 // TODO(ldixon): Unblock after congestion. 728 case SCTP_NOTIFICATIONS_STOPPED_EVENT: 729 LOG(LS_INFO) << "SCTP_NOTIFICATIONS_STOPPED_EVENT"; 730 break; 731 case SCTP_SEND_FAILED_EVENT: 732 LOG(LS_INFO) << "SCTP_SEND_FAILED_EVENT"; 733 break; 734 case SCTP_STREAM_RESET_EVENT: 735 OnStreamResetEvent(¬ification.sn_strreset_event); 736 break; 737 case SCTP_ASSOC_RESET_EVENT: 738 LOG(LS_INFO) << "SCTP_ASSOC_RESET_EVENT"; 739 break; 740 case SCTP_STREAM_CHANGE_EVENT: 741 LOG(LS_INFO) << "SCTP_STREAM_CHANGE_EVENT"; 742 // An acknowledgment we get after our stream resets have gone through, 743 // if they've failed. We log the message, but don't react -- we don't 744 // keep around the last-transmitted set of SSIDs we wanted to close for 745 // error recovery. It doesn't seem likely to occur, and if so, likely 746 // harmless within the lifetime of a single SCTP association. 747 break; 748 default: 749 LOG(LS_WARNING) << "Unknown SCTP event: " 750 << notification.sn_header.sn_type; 751 break; 752 } 753 } 754 755 void SctpDataMediaChannel::OnNotificationAssocChange( 756 const sctp_assoc_change& change) { 757 switch (change.sac_state) { 758 case SCTP_COMM_UP: 759 LOG(LS_VERBOSE) << "Association change SCTP_COMM_UP"; 760 break; 761 case SCTP_COMM_LOST: 762 LOG(LS_INFO) << "Association change SCTP_COMM_LOST"; 763 break; 764 case SCTP_RESTART: 765 LOG(LS_INFO) << "Association change SCTP_RESTART"; 766 break; 767 case SCTP_SHUTDOWN_COMP: 768 LOG(LS_INFO) << "Association change SCTP_SHUTDOWN_COMP"; 769 break; 770 case SCTP_CANT_STR_ASSOC: 771 LOG(LS_INFO) << "Association change SCTP_CANT_STR_ASSOC"; 772 break; 773 default: 774 LOG(LS_INFO) << "Association change UNKNOWN"; 775 break; 776 } 777 } 778 779 void SctpDataMediaChannel::OnStreamResetEvent( 780 const struct sctp_stream_reset_event* evt) { 781 // A stream reset always involves two RE-CONFIG chunks for us -- we always 782 // simultaneously reset a sid's sequence number in both directions. The 783 // requesting side transmits a RE-CONFIG chunk and waits for the peer to send 784 // one back. Both sides get this SCTP_STREAM_RESET_EVENT when they receive 785 // RE-CONFIGs. 786 const int num_ssrcs = (evt->strreset_length - sizeof(*evt)) / 787 sizeof(evt->strreset_stream_list[0]); 788 LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 789 << "): Flags = 0x" 790 << std::hex << evt->strreset_flags << " (" 791 << ListFlags(evt->strreset_flags) << ")"; 792 LOG(LS_VERBOSE) << "Assoc = " << evt->strreset_assoc_id << ", Streams = [" 793 << ListArray(evt->strreset_stream_list, num_ssrcs) 794 << "], Open: [" 795 << ListStreams(open_streams_) << "], Q'd: [" 796 << ListStreams(queued_reset_streams_) << "], Sent: [" 797 << ListStreams(sent_reset_streams_) << "]"; 798 799 // If both sides try to reset some streams at the same time (even if they're 800 // disjoint sets), we can get reset failures. 801 if (evt->strreset_flags & SCTP_STREAM_RESET_FAILED) { 802 // OK, just try again. The stream IDs sent over when the RESET_FAILED flag 803 // is set seem to be garbage values. Ignore them. 804 queued_reset_streams_.insert( 805 sent_reset_streams_.begin(), 806 sent_reset_streams_.end()); 807 sent_reset_streams_.clear(); 808 809 } else if (evt->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) { 810 // Each side gets an event for each direction of a stream. That is, 811 // closing sid k will make each side receive INCOMING and OUTGOING reset 812 // events for k. As per RFC6525, Section 5, paragraph 2, each side will 813 // get an INCOMING event first. 814 for (int i = 0; i < num_ssrcs; i++) { 815 const int stream_id = evt->strreset_stream_list[i]; 816 817 // See if this stream ID was closed by our peer or ourselves. 818 StreamSet::iterator it = sent_reset_streams_.find(stream_id); 819 820 // The reset was requested locally. 821 if (it != sent_reset_streams_.end()) { 822 LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 823 << "): local sid " << stream_id << " acknowledged."; 824 sent_reset_streams_.erase(it); 825 826 } else if ((it = open_streams_.find(stream_id)) 827 != open_streams_.end()) { 828 // The peer requested the reset. 829 LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 830 << "): closing sid " << stream_id; 831 open_streams_.erase(it); 832 SignalStreamClosedRemotely(stream_id); 833 834 } else if ((it = queued_reset_streams_.find(stream_id)) 835 != queued_reset_streams_.end()) { 836 // The peer requested the reset, but there was a local reset 837 // queued. 838 LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 839 << "): double-sided close for sid " << stream_id; 840 // Both sides want the stream closed, and the peer got to send the 841 // RE-CONFIG first. Treat it like the local Remove(Send|Recv)Stream 842 // finished quickly. 843 queued_reset_streams_.erase(it); 844 845 } else { 846 // This stream is unknown. Sometimes this can be from an 847 // RESET_FAILED-related retransmit. 848 LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 849 << "): Unknown sid " << stream_id; 850 } 851 } 852 } 853 854 // Always try to send the queued RESET because this call indicates that the 855 // last local RESET or remote RESET has made some progress. 856 SendQueuedStreamResets(); 857 } 858 859 // Puts the specified |param| from the codec identified by |id| into |dest| 860 // and returns true. Or returns false if it wasn't there, leaving |dest| 861 // untouched. 862 static bool GetCodecIntParameter(const std::vector<DataCodec>& codecs, 863 int id, const std::string& name, 864 const std::string& param, int* dest) { 865 std::string value; 866 Codec match_pattern; 867 match_pattern.id = id; 868 match_pattern.name = name; 869 for (size_t i = 0; i < codecs.size(); ++i) { 870 if (codecs[i].Matches(match_pattern)) { 871 if (codecs[i].GetParam(param, &value)) { 872 *dest = rtc::FromString<int>(value); 873 return true; 874 } 875 } 876 } 877 return false; 878 } 879 880 bool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) { 881 return GetCodecIntParameter( 882 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 883 &remote_port_); 884 } 885 886 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { 887 return GetCodecIntParameter( 888 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 889 &local_port_); 890 } 891 892 void SctpDataMediaChannel::OnPacketFromSctpToNetwork( 893 rtc::Buffer* buffer) { 894 if (buffer->length() > kSctpMtu) { 895 LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " 896 << "SCTP seems to have made a packet that is bigger " 897 "than its official MTU."; 898 } 899 MediaChannel::SendPacket(buffer); 900 } 901 902 bool SctpDataMediaChannel::SendQueuedStreamResets() { 903 if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) 904 return true; 905 906 LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" 907 << ListStreams(queued_reset_streams_) << "], Open: [" 908 << ListStreams(open_streams_) << "], Sent: [" 909 << ListStreams(sent_reset_streams_) << "]"; 910 911 const size_t num_streams = queued_reset_streams_.size(); 912 const size_t num_bytes = sizeof(struct sctp_reset_streams) 913 + (num_streams * sizeof(uint16)); 914 915 std::vector<uint8> reset_stream_buf(num_bytes, 0); 916 struct sctp_reset_streams* resetp = reinterpret_cast<sctp_reset_streams*>( 917 &reset_stream_buf[0]); 918 resetp->srs_assoc_id = SCTP_ALL_ASSOC; 919 resetp->srs_flags = SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_OUTGOING; 920 resetp->srs_number_streams = rtc::checked_cast<uint16_t>(num_streams); 921 int result_idx = 0; 922 for (StreamSet::iterator it = queued_reset_streams_.begin(); 923 it != queued_reset_streams_.end(); ++it) { 924 resetp->srs_stream_list[result_idx++] = *it; 925 } 926 927 int ret = usrsctp_setsockopt( 928 sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp, 929 rtc::checked_cast<socklen_t>(reset_stream_buf.size())); 930 if (ret < 0) { 931 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to send a stream reset for " 932 << num_streams << " streams"; 933 return false; 934 } 935 936 // sent_reset_streams_ is empty, and all the queued_reset_streams_ go into 937 // it now. 938 queued_reset_streams_.swap(sent_reset_streams_); 939 return true; 940 } 941 942 void SctpDataMediaChannel::OnMessage(rtc::Message* msg) { 943 switch (msg->message_id) { 944 case MSG_SCTPINBOUNDPACKET: { 945 rtc::scoped_ptr<InboundPacketMessage> pdata( 946 static_cast<InboundPacketMessage*>(msg->pdata)); 947 OnInboundPacketFromSctpToChannel(pdata->data().get()); 948 break; 949 } 950 case MSG_SCTPOUTBOUNDPACKET: { 951 rtc::scoped_ptr<OutboundPacketMessage> pdata( 952 static_cast<OutboundPacketMessage*>(msg->pdata)); 953 OnPacketFromSctpToNetwork(pdata->data().get()); 954 break; 955 } 956 } 957 } 958 } // namespace cricket 959