10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle SCTP 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2012 Google Inc, and Robin Seggelmann 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/sctp/sctpdataengine.h" 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <stdarg.h> 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <stdio.h> 322a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org#include <sstream> 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector> 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/codec.h" 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/constants.h" 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/streamparams.h" 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "usrsctplib/usrsctp.h" 39cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/buffer.h" 40cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/helpers.h" 41cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h" 42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/safe_conversions.h" 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 442a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgnamespace { 452a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgtypedef cricket::SctpDataMediaChannel::StreamSet StreamSet; 462a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org// Returns a comma-separated, human-readable list of the stream IDs in 's' 472a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgstd::string ListStreams(const StreamSet& s) { 482a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org std::stringstream result; 492a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org bool first = true; 506c1232675bde865816bcbba2d2f3935ab04da61fwu@webrtc.org for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) { 512a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (!first) { 522a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org result << ", " << *it; 532a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else { 542a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org result << *it; 552a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org first = false; 562a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 572a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 582a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return result.str(); 592a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 602a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 612a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org// Returns a pipe-separated, human-readable list of the SCTP_STREAM_RESET 622a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org// flags in 'flags' 632a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgstd::string ListFlags(int flags) { 642a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org std::stringstream result; 652a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org bool first = true; 662a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Skip past the first 12 chars (strlen("SCTP_STREAM_")) 672a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org#define MAKEFLAG(X) { X, #X + 12} 682a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org struct flaginfo_t { 692a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org int value; 702a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const char* name; 712a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } flaginfo[] = { 722a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_INCOMING_SSN), 732a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_OUTGOING_SSN), 742a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_DENIED), 752a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_FAILED), 762a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org MAKEFLAG(SCTP_STREAM_CHANGE_DENIED) 772a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org }; 782a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org#undef MAKEFLAG 792a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org for (int i = 0; i < ARRAY_SIZE(flaginfo); ++i) { 802a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (flags & flaginfo[i].value) { 812a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (!first) result << " | "; 822a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org result << flaginfo[i].name; 832a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org first = false; 842a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 852a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 862a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return result.str(); 872a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 882a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 892a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org// Returns a comma-separated, human-readable list of the integers in 'array'. 902a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org// All 'num_elems' of them. 912a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgstd::string ListArray(const uint16* array, int num_elems) { 922a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org std::stringstream result; 932a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org for (int i = 0; i < num_elems; ++i) { 942a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (i) { 952a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org result << ", " << array[i]; 962a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else { 972a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org result << array[i]; 982a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 992a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 1002a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return result.str(); 1012a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 1022a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} // namespace 1032a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 1052a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgtypedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; 1062a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgtypedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1084d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org// The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280, 1094d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org// take off 80 bytes for DTLS/TURN/TCP/IP overhead. 1104d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.orgstatic const size_t kSctpMtu = 1200; 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum { 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket 1142a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct SctpInboundPacket { 1182a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::Buffer buffer; 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ReceiveDataParams params; 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The |flags| parameter is used by SCTP to distinguish notification packets 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // from other types of packets. 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int flags; 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 125391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org// Helper for logging SCTP messages. 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic void debug_sctp_printf(const char *format, ...) { 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char s[255]; 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org va_list ap; 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org va_start(ap, format); 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org vsnprintf(s, sizeof(s), format, ap); 131391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org LOG(LS_INFO) << "SCTP: " << s; 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org va_end(ap); 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 135391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org// Get the PPID to use for the terminating fragment of this type. 136391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.orgstatic SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid( 137391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org cricket::DataMessageType type) { 138391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org switch (type) { 139391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org default: 140391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case cricket::DMT_NONE: 141391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return SctpDataMediaChannel::PPID_NONE; 142391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case cricket::DMT_CONTROL: 143391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return SctpDataMediaChannel::PPID_CONTROL; 144391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case cricket::DMT_BINARY: 145391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return SctpDataMediaChannel::PPID_BINARY_LAST; 146391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case cricket::DMT_TEXT: 147391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return SctpDataMediaChannel::PPID_TEXT_LAST; 148391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org }; 149391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org} 150391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 151391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.orgstatic bool GetDataMediaType( 152391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org SctpDataMediaChannel::PayloadProtocolIdentifier ppid, 153391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org cricket::DataMessageType *dest) { 154391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org ASSERT(dest != NULL); 155391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org switch (ppid) { 156391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_BINARY_PARTIAL: 157391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_BINARY_LAST: 158391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org *dest = cricket::DMT_BINARY; 159391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return true; 160391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 161391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_TEXT_PARTIAL: 162391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_TEXT_LAST: 163391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org *dest = cricket::DMT_TEXT; 164391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return true; 165391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 166391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_CONTROL: 167391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org *dest = cricket::DMT_CONTROL; 168391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return true; 169391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 170391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org case SctpDataMediaChannel::PPID_NONE: 171391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org *dest = cricket::DMT_NONE; 172391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return true; 173391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 174391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org default: 175391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org return false; 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This is the callback usrsctp uses when there's data to send on the network 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// that has been wrapped appropriatly for the SCTP protocol. 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic int OnSctpOutboundPacket(void* addr, void* data, size_t length, 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint8_t tos, uint8_t set_df) { 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "addr: " << addr << "; length: " << length 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "; tos: " << std::hex << static_cast<int>(tos) 187391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org << "; set_df: " << std::hex << static_cast<int>(set_df); 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note: We have to copy the data; the caller will delete it. 1892a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org OutboundPacketMessage* msg = 1902a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org new OutboundPacketMessage(new rtc::Buffer(data, length)); 1912a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return 0; 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This is the callback called from usrsctp when data has been received, after 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// a packet has been interpreted and parsed by usrsctp and found to contain 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// payload data. It is called by a usrsctp thread. It is assumed this function 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// will free the memory used by 'data'. 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void* data, size_t length, 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org struct sctp_rcvinfo rcv, int flags, 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void* ulp_info) { 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info); 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Post data to the channel's receiver thread (copying it). 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Unclear if copy is needed as this method is responsible for 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // memory cleanup. But this does simplify code. 207391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org const SctpDataMediaChannel::PayloadProtocolIdentifier ppid = 208391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>( 2092a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::HostToNetwork32(rcv.rcv_ppid)); 210391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org cricket::DataMessageType type = cricket::DMT_NONE; 211391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) { 212391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // It's neither a notification nor a recognized data packet. Drop it. 213391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org LOG(LS_ERROR) << "Received an unknown PPID " << ppid 214391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org << " on an SCTP packet. Dropping."; 215391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org } else { 216391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org SctpInboundPacket* packet = new SctpInboundPacket; 217391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->buffer.SetData(data, length); 218391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->params.ssrc = rcv.rcv_sid; 219391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->params.seq_num = rcv.rcv_ssn; 220391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->params.timestamp = rcv.rcv_tsn; 221391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->params.type = type; 222391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org packet->flags = flags; 2232a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // The ownership of |packet| transfers to |msg|. 2242a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org InboundPacketMessage* msg = new InboundPacketMessage(packet); 2252a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); 226391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org } 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org free(data); 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return 1; 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Set the initial value of the static SCTP Data Engines reference count. 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint SctpDataEngine::usrsctp_engines_count = 0; 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 234f5b8e7a761959709cf8201685deaf35ed074cb83wu@webrtc.orgSctpDataEngine::SctpDataEngine() { 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (usrsctp_engines_count == 0) { 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // First argument is udp_encapsulation_port, which is not releveant for our 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // AF_CONN use of sctp. 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf); 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // To turn on/off detailed SCTP debugging. You will also need to have the 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // SCTP_DEBUG cpp defines flag. 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_sysctl_set_sctp_ecn_enable(0); 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This is not needed right now (we don't do dynamic address changes): 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If SCTP Auto-ASCONF is enabled, the peer is informed automatically 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // when a new address is added or removed. This feature is enabled by 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // default. 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // usrsctp_sysctl_set_sctp_auto_asconf(0); 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Add a blackhole sysctl. Setting it to 1 results in no ABORTs 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // being sent in response to INITs, setting it to 2 results 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // in no ABORTs being sent for received OOTB packets. 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This is similar to the TCP sysctl. 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // See: http://svnweb.freebsd.org/base?view=revision&revision=229805 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // usrsctp_sysctl_set_sctp_blackhole(2); 263391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 264391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // Set the number of default outgoing streams. This is the number we'll 265391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // send in the SCTP INIT message. The 'appropriate default' in the 266391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // second paragraph of 267391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2 268391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // is cricket::kMaxSctpSid. 269391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org usrsctp_sysctl_set_sctp_nr_outgoing_streams_default( 270391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org cricket::kMaxSctpSid); 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_engines_count++; 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 274e4b3e8d10bdf1e112408887533f57c2667f1f7aejiayl@webrtc.org cricket::DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, 0); 275e4b3e8d10bdf1e112408887533f57c2667f1f7aejiayl@webrtc.org codec.SetParam(kCodecParamPort, kSctpDefaultPort); 276e4b3e8d10bdf1e112408887533f57c2667f1f7aejiayl@webrtc.org codecs_.push_back(codec); 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSctpDataEngine::~SctpDataEngine() { 280d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org usrsctp_engines_count--; 281d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org LOG(LS_VERBOSE) << "usrsctp_engines_count:" << usrsctp_engines_count; 282d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org 283d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org if (usrsctp_engines_count == 0) { 284d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org // usrsctp_finish() may fail if it's called too soon after the channels are 285d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org // closed. Wait and try again until it succeeds for up to 3 seconds. 286d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org for (size_t i = 0; i < 300; ++i) { 287d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org if (usrsctp_finish() == 0) 288d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org return; 289d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org 2902a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::Thread::SleepMs(10); 291d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org } 292d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org LOG(LS_ERROR) << "Failed to shutdown usrsctp."; 293d19ccc188174c1154987ce2512be1bc64905a3bcjiayl@webrtc.org } 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgDataMediaChannel* SctpDataEngine::CreateChannel( 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DataChannelType data_channel_type) { 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (data_channel_type != DCT_SCTP) { 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3012a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org return new SctpDataMediaChannel(rtc::Thread::Current()); 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3042a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgSctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : worker_thread_(thread), 306e4b3e8d10bdf1e112408887533f57c2667f1f7aejiayl@webrtc.org local_port_(kSctpDefaultPort), 307e4b3e8d10bdf1e112408887533f57c2667f1f7aejiayl@webrtc.org remote_port_(kSctpDefaultPort), 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sock_(NULL), 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sending_(false), 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org receiving_(false), 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org debug_name_("SctpDataMediaChannel") { 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSctpDataMediaChannel::~SctpDataMediaChannel() { 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CloseSctpSocket(); 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgsockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sockaddr_conn sconn = {0}; 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sconn.sconn_family = AF_CONN; 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SCONN_LEN 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sconn.sconn_len = sizeof(sockaddr_conn); 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note: conversion from int to uint16_t happens here. 3252a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org sconn.sconn_port = rtc::HostToNetwork16(port); 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sconn.sconn_addr = this; 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return sconn; 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::OpenSctpSocket() { 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sock_) { 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "->Ignoring attempt to re-create existing socket."; 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, 3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::OnSctpInboundPacket, NULL, 0, this); 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!sock_) { 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Make the socket non-blocking. Connect, close, shutdown etc will not block 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the thread waiting for the socket operation to complete. 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (usrsctp_set_non_blocking(sock_, 1) < 0) { 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This ensures that the usrsctp close call deletes the association. This 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // prevents usrsctp from calling OnSctpOutboundPacket with references to 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // this class as the address. 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org linger linger_opt; 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org linger_opt.l_onoff = 1; 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org linger_opt.l_linger = 0; 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (usrsctp_setsockopt(sock_, SOL_SOCKET, SO_LINGER, &linger_opt, 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sizeof(linger_opt))) { 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SO_LINGER."; 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3622a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Enable stream ID resets. 3632a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org struct sctp_assoc_value stream_rst; 3642a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org stream_rst.assoc_id = SCTP_ALL_ASSOC; 3652a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org stream_rst.assoc_value = 1; 3662a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, 3672a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org &stream_rst, sizeof(stream_rst))) { 3682a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ 3692a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "Failed to set SCTP_ENABLE_STREAM_RESET."; 3702a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 3712a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 3722a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 3732a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Nagle. 374ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org uint32_t nodelay = 1; 375ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, 376ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org sizeof(nodelay))) { 377ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; 378ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org return false; 379ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org } 380ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org 3814d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org // Disable MTU discovery 3824d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org struct sctp_paddrparams params; 3834d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org params.spp_assoc_id = 0; 3844d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org params.spp_flags = SPP_PMTUD_DISABLE; 3854d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org params.spp_pathmtu = kSctpMtu; 3864d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, 3874d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org sizeof(params))) { 3884d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ 3894d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org << "Failed to set SCTP_PEER_ADDR_PARAMS."; 3904d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org return false; 3914d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org } 3924d81c99f2b415fdcd115b63df3929dc9a73e95b3buildbot@webrtc.org 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Subscribe to SCTP event notifications. 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int event_types[] = {SCTP_ASSOC_CHANGE, 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SCTP_PEER_ADDR_CHANGE, 396d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org SCTP_SEND_FAILED_EVENT, 3972a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org SCTP_SENDER_DRY_EVENT, 3982a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org SCTP_STREAM_RESET_EVENT}; 3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org struct sctp_event event = {0}; 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org event.se_assoc_id = SCTP_ALL_ASSOC; 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org event.se_on = 1; 4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(event_types); i++) { 4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org event.se_type = event_types[i]; 4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EVENT, &event, 4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sizeof(event)) < 0) { 4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_EVENT type: " 4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << event.se_type; 4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Register this class as an address for usrsctp. This is used by SCTP to 4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // direct the packets received (by the created socket) to this class. 4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_register_address(this); 4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sending_ = true; 4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::CloseSctpSocket() { 4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sending_ = false; 4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sock_) { 4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We assume that SO_LINGER option is set to close the association when 4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // close is called. This means that any pending packets in usrsctp will be 4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // discarded instead of being sent. 4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_close(sock_); 4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sock_ = NULL; 4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_deregister_address(this); 4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::Connect() { 4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->Connect()."; 4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If we already have a socket connection, just return. 4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sock_) { 4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket " 4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "is already established."; 4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If no socket (it was closed) try to start it again. This can happen when 4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the socket we are connecting to closes, does an sctp shutdown handshake, 4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // or behaves unexpectedly causing us to perform a CloseSctpSocket. 4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!sock_ && !OpenSctpSocket()) { 4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note: conversion from int to uint16_t happens on assignment. 4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sockaddr_conn local_sconn = GetSctpSockAddr(local_port_); 4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (usrsctp_bind(sock_, reinterpret_cast<sockaddr *>(&local_sconn), 4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sizeof(local_sconn)) < 0) { 4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "->Connect(): " 4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ("Failed usrsctp_bind"); 4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CloseSctpSocket(); 4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note: conversion from int to uint16_t happens on assignment. 4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sockaddr_conn remote_sconn = GetSctpSockAddr(remote_port_); 4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int connect_result = usrsctp_connect( 4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sock_, reinterpret_cast<sockaddr *>(&remote_sconn), sizeof(remote_sconn)); 4621a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org if (connect_result < 0 && errno != SCTP_EINPROGRESS) { 4631a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed usrsctp_connect. got errno=" 4641a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org << errno << ", but wanted " << SCTP_EINPROGRESS; 4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CloseSctpSocket(); 4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::Disconnect() { 4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Consider calling |usrsctp_shutdown(sock_, ...)| to do a 4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // shutdown handshake and remove the association. 4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CloseSctpSocket(); 4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::SetSend(bool send) { 4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!sending_ && send) { 4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return Connect(); 4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sending_ && !send) { 4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Disconnect(); 4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::SetReceive(bool receive) { 4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org receiving_ = receive; 4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::AddSendStream(const StreamParams& stream) { 4932a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return AddStream(stream); 4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::RemoveSendStream(uint32 ssrc) { 4972a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return ResetStream(ssrc); 4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::AddRecvStream(const StreamParams& stream) { 5018485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // SCTP DataChannels are always bi-directional and calling AddSendStream will 5028485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // enable both sending and receiving on the stream. So AddRecvStream is a 5038485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // no-op. 5048485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org return true; 5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::RemoveRecvStream(uint32 ssrc) { 5088485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // SCTP DataChannels are always bi-directional and calling RemoveSendStream 5098485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // will disable both sending and receiving on the stream. So RemoveRecvStream 5108485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // is a no-op. 5118485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org return true; 5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SctpDataMediaChannel::SendData( 5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const SendDataParams& params, 5162a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org const rtc::Buffer& payload, 5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SendDataResult* result) { 5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (result) { 519391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // Preset |result| to assume an error. If SendData succeeds, we'll 520391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // overwrite |*result| once more at the end. 5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *result = SDR_ERROR; 5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!sending_) { 5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "Not sending packet with ssrc=" << params.ssrc 5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " len=" << payload.length() << " before SetSend(true)."; 5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5315aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org if (params.type != cricket::DMT_CONTROL && 5322a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org open_streams_.find(params.ssrc) == open_streams_.end()) { 5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "Not sending data because ssrc is unknown: " 5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << params.ssrc; 5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // 5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Send data using SCTP. 541391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org ssize_t send_res = 0; // result from usrsctp_sendv. 542391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org struct sctp_sendv_spa spa = {0}; 543391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID; 544391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_sndinfo.snd_sid = params.ssrc; 5452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org spa.sendv_sndinfo.snd_ppid = rtc::HostToNetwork32( 546391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org GetPpid(params.type)); 547391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 548391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // Ordered implies reliable. 549391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org if (!params.ordered) { 550391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED; 551391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) { 552391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 553391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX; 554391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_prinfo.pr_value = params.max_rtx_count; 555391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org } else { 556391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 557391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL; 558391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org spa.sendv_prinfo.pr_value = params.max_rtx_ms; 559391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org } 560391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org } 561391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org 562391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // We don't fragment. 563391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org send_res = usrsctp_sendv(sock_, payload.data(), 564391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org static_cast<size_t>(payload.length()), 565391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org NULL, 0, &spa, 5662a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::checked_cast<socklen_t>(sizeof(spa)), 567391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org SCTP_SENDV_SPA, 0); 568391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org if (send_res < 0) { 569a7f7834eb84ba9551f91eec23dfa26a211bb93c7jiayl@webrtc.org if (errno == SCTP_EWOULDBLOCK) { 570d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org *result = SDR_BLOCK; 571d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned"; 572d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org } else { 573d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_ 574d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org << "->SendData(...): " 575d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org << " usrsctp_sendv: "; 576d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org } 5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (result) { 580391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org // Only way out now is success. 5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *result = SDR_SUCCESS; 5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Called by network interface when a packet has been received. 587f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid SctpDataMediaChannel::OnPacketReceived( 5882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 589391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " << " length=" 590391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org << packet->length() << ", sending: " << sending_; 5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Only give receiving packets to usrsctp after if connected. This enables two 5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // peers to each make a connect call, but for them not to receive an INIT 5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // packet before they have called connect; least the last receiver of the INIT 5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // packet will have called connect, and a connection will be established. 5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sending_) { 5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Pass received packet to SCTP stack. Once processed by usrsctp, the data 5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // will be will be given to the global OnSctpInboundData, and then, 5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // marshalled by a Post and handled with OnMessage. 5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org usrsctp_conninput(this, packet->data(), packet->length(), 0); 6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Consider caching the packet for very slightly better 6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // reliability. 6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::OnInboundPacketFromSctpToChannel( 6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SctpInboundPacket* packet) { 6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "Received SCTP data:" 6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " ssrc=" << packet->params.ssrc 6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " notification: " << (packet->flags & MSG_NOTIFICATION) 612391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org << " length=" << packet->buffer.length(); 6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Sending a packet with data == NULL (no data) is SCTPs "close the 6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // connection" message. This sets sock_ = NULL; 6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!packet->buffer.length() || !packet->buffer.data()) { 6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "No data, closing."; 6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (packet->flags & MSG_NOTIFICATION) { 6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnNotificationFromSctp(&packet->buffer); 6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnDataFromSctpToChannel(packet->params, &packet->buffer); 6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::OnDataFromSctpToChannel( 6282a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org const ReceiveDataParams& params, rtc::Buffer* buffer) { 6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (receiving_) { 6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): " 6318485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org << "Posting with length: " << buffer->length() 6328485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org << " on stream " << params.ssrc; 6338485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // Reports all received messages to upper layers, no matter whether the sid 6348485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org // is known. 6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalDataReceived(params, buffer->data(), buffer->length()); 6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): " 6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "Not receiving packet with sid=" << params.ssrc 6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " len=" << buffer->length() 6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " before SetReceive(true)."; 6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6442a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgbool SctpDataMediaChannel::AddStream(const StreamParams& stream) { 6452a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (!stream.has_ssrcs()) { 6462a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 6472a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 6482a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6492a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const uint32 ssrc = stream.first_ssrc(); 6502a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (open_streams_.find(ssrc) != open_streams_.end()) { 6518485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 6522a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "Not adding data stream '" << stream.id 6532a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "' with ssrc=" << ssrc 6542a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << " because stream is already open."; 6552a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 6562a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else if (queued_reset_streams_.find(ssrc) != queued_reset_streams_.end() 6572a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org || sent_reset_streams_.find(ssrc) != sent_reset_streams_.end()) { 6582a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 6592a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "Not adding data stream '" << stream.id 6602a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "' with ssrc=" << ssrc 6612a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << " because stream is still closing."; 6622a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 6632a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 6642a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6652a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org open_streams_.insert(ssrc); 6662a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return true; 6672a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 6682a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6692a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgbool SctpDataMediaChannel::ResetStream(uint32 ssrc) { 6702a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // We typically get this called twice for the same stream, once each for 6712a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Send and Recv. 6722a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org StreamSet::iterator found = open_streams_.find(ssrc); 6732a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6742a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (found == open_streams_.end()) { 6752a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 6762a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "stream not found."; 6772a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 6782a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else { 6792a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 6802a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "Removing and queuing RE-CONFIG chunk."; 6812a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org open_streams_.erase(found); 6822a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 6832a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6842a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // SCTP won't let you have more than one stream reset pending at a time, but 6852a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // you can close multiple streams in a single reset. So, we keep an internal 6862a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // queue of streams-to-reset, and send them as one reset message in 6872a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // SendQueuedStreamResets(). 6882a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org queued_reset_streams_.insert(ssrc); 6892a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6902a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Signal our stream-reset logic that it should try to send now, if it can. 6912a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org SendQueuedStreamResets(); 6922a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6932a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // The stream will actually get removed when we get the acknowledgment. 6942a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return true; 6952a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 6962a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 6972a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid SctpDataMediaChannel::OnNotificationFromSctp(rtc::Buffer* buffer) { 6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const sctp_notification& notification = 6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org reinterpret_cast<const sctp_notification&>(*buffer->data()); 7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(notification.sn_header.sn_length == buffer->length()); 7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): handle notifications appropriately. 7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (notification.sn_header.sn_type) { 7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_ASSOC_CHANGE: 7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE"; 7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnNotificationAssocChange(notification.sn_assoc_change); 7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_REMOTE_ERROR: 7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_REMOTE_ERROR"; 7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_SHUTDOWN_EVENT: 7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_SHUTDOWN_EVENT"; 7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_ADAPTATION_INDICATION: 7152a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_INFO) << "SCTP_ADAPTATION_INDICATION"; 7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_PARTIAL_DELIVERY_EVENT: 7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_PARTIAL_DELIVERY_EVENT"; 7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_AUTHENTICATION_EVENT: 7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_AUTHENTICATION_EVENT"; 7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_SENDER_DRY_EVENT: 7242a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_SENDER_DRY_EVENT"; 725d156f12e9ee96258b7b79d0e3d8ddab6b4b87fbbwu@webrtc.org SignalReadyToSend(true); 7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ldixon): Unblock after congestion. 7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_NOTIFICATIONS_STOPPED_EVENT: 7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_NOTIFICATIONS_STOPPED_EVENT"; 7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_SEND_FAILED_EVENT: 7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_SEND_FAILED_EVENT"; 7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_STREAM_RESET_EVENT: 7352a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org OnStreamResetEvent(¬ification.sn_strreset_event); 7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_ASSOC_RESET_EVENT: 7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_ASSOC_RESET_EVENT"; 7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_STREAM_CHANGE_EVENT: 7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SCTP_STREAM_CHANGE_EVENT"; 7422a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // An acknowledgment we get after our stream resets have gone through, 7432a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // if they've failed. We log the message, but don't react -- we don't 7442a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // keep around the last-transmitted set of SSIDs we wanted to close for 7452a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // error recovery. It doesn't seem likely to occur, and if so, likely 7462a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // harmless within the lifetime of a single SCTP association. 7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Unknown SCTP event: " 7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << notification.sn_header.sn_type; 7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::OnNotificationAssocChange( 7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const sctp_assoc_change& change) { 7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (change.sac_state) { 7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_COMM_UP: 7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "Association change SCTP_COMM_UP"; 7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_COMM_LOST: 7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_COMM_LOST"; 7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_RESTART: 7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_RESTART"; 7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_SHUTDOWN_COMP: 7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_SHUTDOWN_COMP"; 7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case SCTP_CANT_STR_ASSOC: 7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_CANT_STR_ASSOC"; 7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Association change UNKNOWN"; 7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7792a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgvoid SctpDataMediaChannel::OnStreamResetEvent( 7802a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const struct sctp_stream_reset_event* evt) { 7812a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // A stream reset always involves two RE-CONFIG chunks for us -- we always 7822a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // simultaneously reset a sid's sequence number in both directions. The 7832a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // requesting side transmits a RE-CONFIG chunk and waits for the peer to send 7842a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // one back. Both sides get this SCTP_STREAM_RESET_EVENT when they receive 7852a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // RE-CONFIGs. 7862a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const int num_ssrcs = (evt->strreset_length - sizeof(*evt)) / 7872a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org sizeof(evt->strreset_stream_list[0]); 7882a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 7892a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "): Flags = 0x" 7902a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << std::hex << evt->strreset_flags << " (" 7912a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListFlags(evt->strreset_flags) << ")"; 7922a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "Assoc = " << evt->strreset_assoc_id << ", Streams = [" 7932a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListArray(evt->strreset_stream_list, num_ssrcs) 7942a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "], Open: [" 7952a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(open_streams_) << "], Q'd: [" 7962a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(queued_reset_streams_) << "], Sent: [" 7972a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(sent_reset_streams_) << "]"; 7982a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 7992a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // If both sides try to reset some streams at the same time (even if they're 8002a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // disjoint sets), we can get reset failures. 8012a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (evt->strreset_flags & SCTP_STREAM_RESET_FAILED) { 8022a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // OK, just try again. The stream IDs sent over when the RESET_FAILED flag 8032a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // is set seem to be garbage values. Ignore them. 8042a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org queued_reset_streams_.insert( 8052a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org sent_reset_streams_.begin(), 8062a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org sent_reset_streams_.end()); 8072a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org sent_reset_streams_.clear(); 8082a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8092a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else if (evt->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) { 8102a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Each side gets an event for each direction of a stream. That is, 8112a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // closing sid k will make each side receive INCOMING and OUTGOING reset 8122a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // events for k. As per RFC6525, Section 5, paragraph 2, each side will 8132a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // get an INCOMING event first. 8142a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org for (int i = 0; i < num_ssrcs; i++) { 8152a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const int stream_id = evt->strreset_stream_list[i]; 8162a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8172a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // See if this stream ID was closed by our peer or ourselves. 8182a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org StreamSet::iterator it = sent_reset_streams_.find(stream_id); 8192a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8202a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // The reset was requested locally. 8212a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (it != sent_reset_streams_.end()) { 8222a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 8232a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "): local sid " << stream_id << " acknowledged."; 8242a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org sent_reset_streams_.erase(it); 8252a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8262a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else if ((it = open_streams_.find(stream_id)) 8272a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org != open_streams_.end()) { 8282a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // The peer requested the reset. 8292a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 8302a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "): closing sid " << stream_id; 8312a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org open_streams_.erase(it); 832f365c83eeda1a21af3740b70798f6ca65c7bc182buildbot@webrtc.org SignalStreamClosedRemotely(stream_id); 8332a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8342a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else if ((it = queued_reset_streams_.find(stream_id)) 8352a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org != queued_reset_streams_.end()) { 8362a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // The peer requested the reset, but there was a local reset 8372a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // queued. 8382a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 8392a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "): double-sided close for sid " << stream_id; 8402a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // Both sides want the stream closed, and the peer got to send the 8412a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // RE-CONFIG first. Treat it like the local Remove(Send|Recv)Stream 8422a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // finished quickly. 8432a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org queued_reset_streams_.erase(it); 8442a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8452a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } else { 8462a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // This stream is unknown. Sometimes this can be from an 8472a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // RESET_FAILED-related retransmit. 8482a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 8492a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "): Unknown sid " << stream_id; 8502a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 8512a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 8522a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 8532a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 8542b70e77dba449835b2ebc97bbed56b069af711b1jiayl@webrtc.org // Always try to send the queued RESET because this call indicates that the 8552b70e77dba449835b2ebc97bbed56b069af711b1jiayl@webrtc.org // last local RESET or remote RESET has made some progress. 8562b70e77dba449835b2ebc97bbed56b069af711b1jiayl@webrtc.org SendQueuedStreamResets(); 8572a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 8582a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 859861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org// Puts the specified |param| from the codec identified by |id| into |dest| 860861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org// and returns true. Or returns false if it wasn't there, leaving |dest| 861861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org// untouched. 862861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.orgstatic bool GetCodecIntParameter(const std::vector<DataCodec>& codecs, 863861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org int id, const std::string& name, 864861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org const std::string& param, int* dest) { 865861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org std::string value; 866861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org Codec match_pattern; 867861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org match_pattern.id = id; 868861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org match_pattern.name = name; 869861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org for (size_t i = 0; i < codecs.size(); ++i) { 870861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org if (codecs[i].Matches(match_pattern)) { 871861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org if (codecs[i].GetParam(param, &value)) { 8722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org *dest = rtc::FromString<int>(value); 873861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return true; 874861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org } 875861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org } 876861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org } 877861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return false; 878861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org} 879861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 880861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.orgbool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) { 881861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return GetCodecIntParameter( 882861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 883861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org &remote_port_); 884861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org} 885861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 886861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.orgbool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { 887861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return GetCodecIntParameter( 888861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 889861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org &local_port_); 890861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org} 8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SctpDataMediaChannel::OnPacketFromSctpToNetwork( 8932a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::Buffer* buffer) { 8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (buffer->length() > kSctpMtu) { 8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " 8962a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << "SCTP seems to have made a packet that is bigger " 8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "than its official MTU."; 8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8997162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org MediaChannel::SendPacket(buffer); 9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9022a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.orgbool SctpDataMediaChannel::SendQueuedStreamResets() { 9032a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) 9042a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return true; 9052a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 9062a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" 9072a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(queued_reset_streams_) << "], Open: [" 9082a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(open_streams_) << "], Sent: [" 9092a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << ListStreams(sent_reset_streams_) << "]"; 9102a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 9112a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const size_t num_streams = queued_reset_streams_.size(); 9122a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org const size_t num_bytes = sizeof(struct sctp_reset_streams) 9132a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org + (num_streams * sizeof(uint16)); 9142a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 9152a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org std::vector<uint8> reset_stream_buf(num_bytes, 0); 9162a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org struct sctp_reset_streams* resetp = reinterpret_cast<sctp_reset_streams*>( 9172a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org &reset_stream_buf[0]); 9182a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org resetp->srs_assoc_id = SCTP_ALL_ASSOC; 9192a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org resetp->srs_flags = SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_OUTGOING; 9202a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org resetp->srs_number_streams = rtc::checked_cast<uint16_t>(num_streams); 9212a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org int result_idx = 0; 9222a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org for (StreamSet::iterator it = queued_reset_streams_.begin(); 9232a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org it != queued_reset_streams_.end(); ++it) { 9242a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org resetp->srs_stream_list[result_idx++] = *it; 9252a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 9262a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 92713a42bcb8b909faef285ec36b59740e5696a2295jiayl@webrtc.org int ret = usrsctp_setsockopt( 92813a42bcb8b909faef285ec36b59740e5696a2295jiayl@webrtc.org sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp, 9292a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::checked_cast<socklen_t>(reset_stream_buf.size())); 9302a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org if (ret < 0) { 9312a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to send a stream reset for " 9322a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org << num_streams << " streams"; 9332a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return false; 9342a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org } 9352a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 9362a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // sent_reset_streams_ is empty, and all the queued_reset_streams_ go into 9372a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org // it now. 9382a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org queued_reset_streams_.swap(sent_reset_streams_); 9392a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org return true; 9402a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org} 9412a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org 9422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid SctpDataMediaChannel::OnMessage(rtc::Message* msg) { 9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (msg->message_id) { 9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case MSG_SCTPINBOUNDPACKET: { 9452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<InboundPacketMessage> pdata( 9462a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org static_cast<InboundPacketMessage*>(msg->pdata)); 9472a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org OnInboundPacketFromSctpToChannel(pdata->data().get()); 9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 9490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case MSG_SCTPOUTBOUNDPACKET: { 9512a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<OutboundPacketMessage> pdata( 9522a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org static_cast<OutboundPacketMessage*>(msg->pdata)); 9532a81a3893cea812cfa676ff7553038078c17f56cwu@webrtc.org OnPacketFromSctpToNetwork(pdata->data().get()); 9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket 959