128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 25f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * libjingle 35f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Copyright 2012 Google Inc. and Robin Seggelmann 428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer. 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * and/or other materials provided with the distribution. 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * derived from this software without specific prior written permission. 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/sctp/sctpdataengine.h" 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <stdarg.h> 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <stdio.h> 32f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org#include <sstream> 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <vector> 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/base/codec.h" 3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/base/constants.h" 3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/base/streamparams.h" 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "usrsctplib/usrsctp.h" 395237aaf243d29732f59557361b7a993c0a18cf0etfarina#include "webrtc/base/arraysize.h" 40a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/buffer.h" 41a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/helpers.h" 42a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h" 43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/safe_conversions.h" 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 45f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgnamespace { 46f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgtypedef cricket::SctpDataMediaChannel::StreamSet StreamSet; 47f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Returns a comma-separated, human-readable list of the stream IDs in 's' 48f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgstd::string ListStreams(const StreamSet& s) { 49f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org std::stringstream result; 50f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org bool first = true; 51e00265ed492c4d61f5ef04f9138739289bac6b98wu@webrtc.org for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) { 52f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (!first) { 53f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org result << ", " << *it; 54f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else { 55f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org result << *it; 56f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org first = false; 57f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 58f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 59f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return result.str(); 60f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 61f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 62f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Returns a pipe-separated, human-readable list of the SCTP_STREAM_RESET 63f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// flags in 'flags' 64f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgstd::string ListFlags(int flags) { 65f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org std::stringstream result; 66f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org bool first = true; 67f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Skip past the first 12 chars (strlen("SCTP_STREAM_")) 68f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org#define MAKEFLAG(X) { X, #X + 12} 69f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org struct flaginfo_t { 70f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org int value; 71f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org const char* name; 72f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } flaginfo[] = { 73f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_INCOMING_SSN), 74f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_OUTGOING_SSN), 75f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_DENIED), 76f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org MAKEFLAG(SCTP_STREAM_RESET_FAILED), 77f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org MAKEFLAG(SCTP_STREAM_CHANGE_DENIED) 78f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org }; 79f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org#undef MAKEFLAG 805237aaf243d29732f59557361b7a993c0a18cf0etfarina for (int i = 0; i < arraysize(flaginfo); ++i) { 81f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (flags & flaginfo[i].value) { 82f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (!first) result << " | "; 83f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org result << flaginfo[i].name; 84f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org first = false; 85f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 86f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 87f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return result.str(); 88f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 89f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 90f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Returns a comma-separated, human-readable list of the integers in 'array'. 91f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// All 'num_elems' of them. 920c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmstd::string ListArray(const uint16_t* array, int num_elems) { 93f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org std::stringstream result; 94f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org for (int i = 0; i < num_elems; ++i) { 95f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (i) { 96f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org result << ", " << array[i]; 97f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else { 98f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org result << array[i]; 99f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 100f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 101f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return result.str(); 102f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 103f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} // namespace 104f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket { 106d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgtypedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; 107d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgtypedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 109624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org// The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280, 110624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org// take off 80 bytes for DTLS/TURN/TCP/IP overhead. 111624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.orgstatic const size_t kSctpMtu = 1200; 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 113e8386d21992b6683b6fadd315ea631875b4256fbLally Singh// The size of the SCTP association send buffer. 256kB, the usrsctp default. 114e8386d21992b6683b6fadd315ea631875b4256fbLally Singhstatic const int kSendBufferSize = 262144; 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgenum { 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket 117d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstruct SctpInboundPacket { 121d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::Buffer buffer; 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ReceiveDataParams params; 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The |flags| parameter is used by SCTP to distinguish notification packets 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // from other types of packets. 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int flags; 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1281112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org// Helper for logging SCTP messages. 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic void debug_sctp_printf(const char *format, ...) { 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char s[255]; 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org va_list ap; 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org va_start(ap, format); 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org vsnprintf(s, sizeof(s), format, ap); 1341112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org LOG(LS_INFO) << "SCTP: " << s; 13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org va_end(ap); 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1381112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org// Get the PPID to use for the terminating fragment of this type. 1391112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.orgstatic SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid( 1401112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org cricket::DataMessageType type) { 1411112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org switch (type) { 1421112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org default: 1431112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case cricket::DMT_NONE: 1441112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return SctpDataMediaChannel::PPID_NONE; 1451112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case cricket::DMT_CONTROL: 1461112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return SctpDataMediaChannel::PPID_CONTROL; 1471112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case cricket::DMT_BINARY: 1481112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return SctpDataMediaChannel::PPID_BINARY_LAST; 1491112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case cricket::DMT_TEXT: 1501112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return SctpDataMediaChannel::PPID_TEXT_LAST; 1511112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org }; 1521112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org} 1531112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 1541112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.orgstatic bool GetDataMediaType( 1551112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org SctpDataMediaChannel::PayloadProtocolIdentifier ppid, 1561112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org cricket::DataMessageType *dest) { 1571112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org ASSERT(dest != NULL); 1581112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org switch (ppid) { 1591112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_BINARY_PARTIAL: 1601112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_BINARY_LAST: 1611112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org *dest = cricket::DMT_BINARY; 1621112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return true; 1631112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 1641112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_TEXT_PARTIAL: 1651112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_TEXT_LAST: 1661112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org *dest = cricket::DMT_TEXT; 1671112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return true; 1681112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 1691112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_CONTROL: 1701112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org *dest = cricket::DMT_CONTROL; 1711112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return true; 1721112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 1731112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org case SctpDataMediaChannel::PPID_NONE: 1741112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org *dest = cricket::DMT_NONE; 1751112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return true; 1761112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 1771112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org default: 1781112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org return false; 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1824c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh// Log the packet in text2pcap format, if log level is at LS_VERBOSE. 183e8386d21992b6683b6fadd315ea631875b4256fbLally Singhstatic void VerboseLogPacket(void *data, size_t length, int direction) { 1844c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { 1854c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh char *dump_buf; 1864c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh if ((dump_buf = usrsctp_dumppacket( 187e8386d21992b6683b6fadd315ea631875b4256fbLally Singh data, length, direction)) != NULL) { 1884c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh LOG(LS_VERBOSE) << dump_buf; 1894c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh usrsctp_freedumpbuffer(dump_buf); 1904c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh } 1914c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh } 1924c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh} 1934c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This is the callback usrsctp uses when there's data to send on the network 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// that has been wrapped appropriatly for the SCTP protocol. 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic int OnSctpOutboundPacket(void* addr, void* data, size_t length, 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org uint8_t tos, uint8_t set_df) { 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "addr: " << addr << "; length: " << length 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "; tos: " << std::hex << static_cast<int>(tos) 2021112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org << "; set_df: " << std::hex << static_cast<int>(set_df); 2034c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh 2044c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND); 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Note: We have to copy the data; the caller will delete it. 2069478437fdea4eb31b92ffe0c10368fe5bc9b9e16Karl Wiberg auto* msg = new OutboundPacketMessage( 2079478437fdea4eb31b92ffe0c10368fe5bc9b9e16Karl Wiberg new rtc::Buffer(reinterpret_cast<uint8_t*>(data), length)); 208f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return 0; 21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This is the callback called from usrsctp when data has been received, after 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// a packet has been interpreted and parsed by usrsctp and found to contain 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// payload data. It is called by a usrsctp thread. It is assumed this function 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// will free the memory used by 'data'. 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void* data, size_t length, 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org struct sctp_rcvinfo rcv, int flags, 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void* ulp_info) { 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info); 22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Post data to the channel's receiver thread (copying it). 22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Unclear if copy is needed as this method is responsible for 22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // memory cleanup. But this does simplify code. 2241112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org const SctpDataMediaChannel::PayloadProtocolIdentifier ppid = 2251112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>( 226d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::HostToNetwork32(rcv.rcv_ppid)); 2271112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org cricket::DataMessageType type = cricket::DMT_NONE; 2281112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) { 2291112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // It's neither a notification nor a recognized data packet. Drop it. 2301112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org LOG(LS_ERROR) << "Received an unknown PPID " << ppid 2311112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org << " on an SCTP packet. Dropping."; 2321112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org } else { 2331112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org SctpInboundPacket* packet = new SctpInboundPacket; 2349478437fdea4eb31b92ffe0c10368fe5bc9b9e16Karl Wiberg packet->buffer.SetData(reinterpret_cast<uint8_t*>(data), length); 2351112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org packet->params.ssrc = rcv.rcv_sid; 2361112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org packet->params.seq_num = rcv.rcv_ssn; 2371112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org packet->params.timestamp = rcv.rcv_tsn; 2381112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org packet->params.type = type; 2391112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org packet->flags = flags; 240f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // The ownership of |packet| transfers to |msg|. 241f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org InboundPacketMessage* msg = new InboundPacketMessage(packet); 242f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); 2431112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org } 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org free(data); 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return 1; 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Set the initial value of the static SCTP Data Engines reference count. 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgint SctpDataEngine::usrsctp_engines_count = 0; 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2510de29504ab7ac923401c8e4e154f3b72038dbcc2wu@webrtc.orgSctpDataEngine::SctpDataEngine() { 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (usrsctp_engines_count == 0) { 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // First argument is udp_encapsulation_port, which is not releveant for our 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // AF_CONN use of sctp. 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf); 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // To turn on/off detailed SCTP debugging. You will also need to have the 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // SCTP_DEBUG cpp defines flag. 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_sysctl_set_sctp_ecn_enable(0); 26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 264e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // This is harmless, but we should find out when the library default 265e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // changes. 266e8386d21992b6683b6fadd315ea631875b4256fbLally Singh int send_size = usrsctp_sysctl_get_sctp_sendspace(); 267e8386d21992b6683b6fadd315ea631875b4256fbLally Singh if (send_size != kSendBufferSize) { 268e8386d21992b6683b6fadd315ea631875b4256fbLally Singh LOG(LS_ERROR) << "Got different send size than expected: " << send_size; 269e8386d21992b6683b6fadd315ea631875b4256fbLally Singh } 270e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // This is not needed right now (we don't do dynamic address changes): 27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // If SCTP Auto-ASCONF is enabled, the peer is informed automatically 27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // when a new address is added or removed. This feature is enabled by 27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // default. 27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // usrsctp_sysctl_set_sctp_auto_asconf(0); 27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Consider turning this on/off. 27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Add a blackhole sysctl. Setting it to 1 results in no ABORTs 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // being sent in response to INITs, setting it to 2 results 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // in no ABORTs being sent for received OOTB packets. 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // This is similar to the TCP sysctl. 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // See: http://svnweb.freebsd.org/base?view=revision&revision=229805 28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // usrsctp_sysctl_set_sctp_blackhole(2); 2871112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 2881112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // Set the number of default outgoing streams. This is the number we'll 2891112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // send in the SCTP INIT message. The 'appropriate default' in the 2901112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // second paragraph of 2911112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2 2921112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // is cricket::kMaxSctpSid. 2931112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org usrsctp_sysctl_set_sctp_nr_outgoing_streams_default( 2941112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org cricket::kMaxSctpSid); 29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_engines_count++; 29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2989c16c39e613ebc5cdfa8ca5818a62ef5c3b18bd7jiayl@webrtc.org cricket::DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, 0); 2999c16c39e613ebc5cdfa8ca5818a62ef5c3b18bd7jiayl@webrtc.org codec.SetParam(kCodecParamPort, kSctpDefaultPort); 3009c16c39e613ebc5cdfa8ca5818a62ef5c3b18bd7jiayl@webrtc.org codecs_.push_back(codec); 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSctpDataEngine::~SctpDataEngine() { 304f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org usrsctp_engines_count--; 305f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org LOG(LS_VERBOSE) << "usrsctp_engines_count:" << usrsctp_engines_count; 306f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org 307f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org if (usrsctp_engines_count == 0) { 308f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org // usrsctp_finish() may fail if it's called too soon after the channels are 309f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org // closed. Wait and try again until it succeeds for up to 3 seconds. 310f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org for (size_t i = 0; i < 300; ++i) { 311f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org if (usrsctp_finish() == 0) 312f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org return; 313f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org 314d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::Thread::SleepMs(10); 315f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org } 316f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org LOG(LS_ERROR) << "Failed to shutdown usrsctp."; 317f8063d34deefb55b4a0e5091fc59d5d5e58e43d8jiayl@webrtc.org } 31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgDataMediaChannel* SctpDataEngine::CreateChannel( 32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DataChannelType data_channel_type) { 32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (data_channel_type != DCT_SCTP) { 32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return NULL; 32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 3257391881f9762ccadeeb0249560b33cf2bcfaf7f9tommi return new SctpDataMediaChannel(rtc::Thread::Current()); 32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 32728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 328e8386d21992b6683b6fadd315ea631875b4256fbLally Singh// static 329e8386d21992b6683b6fadd315ea631875b4256fbLally SinghSctpDataMediaChannel* SctpDataEngine::GetChannelFromSocket( 330e8386d21992b6683b6fadd315ea631875b4256fbLally Singh struct socket* sock) { 331e8386d21992b6683b6fadd315ea631875b4256fbLally Singh struct sockaddr* addrs = nullptr; 332e8386d21992b6683b6fadd315ea631875b4256fbLally Singh int naddrs = usrsctp_getladdrs(sock, 0, &addrs); 333e8386d21992b6683b6fadd315ea631875b4256fbLally Singh if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) { 334e8386d21992b6683b6fadd315ea631875b4256fbLally Singh return nullptr; 335e8386d21992b6683b6fadd315ea631875b4256fbLally Singh } 336e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // usrsctp_getladdrs() returns the addresses bound to this socket, which 337e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // contains the SctpDataMediaChannel* as sconn_addr. Read the pointer, 338e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // then free the list of addresses once we have the pointer. We only open 339e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // AF_CONN sockets, and they should all have the sconn_addr set to the 340e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // pointer that created them, so [0] is as good as any other. 341e8386d21992b6683b6fadd315ea631875b4256fbLally Singh struct sockaddr_conn* sconn = 342e8386d21992b6683b6fadd315ea631875b4256fbLally Singh reinterpret_cast<struct sockaddr_conn*>(&addrs[0]); 343e8386d21992b6683b6fadd315ea631875b4256fbLally Singh SctpDataMediaChannel* channel = 344e8386d21992b6683b6fadd315ea631875b4256fbLally Singh reinterpret_cast<SctpDataMediaChannel*>(sconn->sconn_addr); 345e8386d21992b6683b6fadd315ea631875b4256fbLally Singh usrsctp_freeladdrs(addrs); 346e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 347e8386d21992b6683b6fadd315ea631875b4256fbLally Singh return channel; 348e8386d21992b6683b6fadd315ea631875b4256fbLally Singh} 349e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 350e8386d21992b6683b6fadd315ea631875b4256fbLally Singh// static 351e8386d21992b6683b6fadd315ea631875b4256fbLally Singhint SctpDataEngine::SendThresholdCallback(struct socket* sock, 352e8386d21992b6683b6fadd315ea631875b4256fbLally Singh uint32_t sb_free) { 353e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // Fired on our I/O thread. SctpDataMediaChannel::OnPacketReceived() gets 354e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // a packet containing acknowledgments, which goes into usrsctp_conninput, 355e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // and then back here. 356e8386d21992b6683b6fadd315ea631875b4256fbLally Singh SctpDataMediaChannel* channel = GetChannelFromSocket(sock); 357e8386d21992b6683b6fadd315ea631875b4256fbLally Singh if (!channel) { 358e8386d21992b6683b6fadd315ea631875b4256fbLally Singh LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket " 359e8386d21992b6683b6fadd315ea631875b4256fbLally Singh << sock; 360e8386d21992b6683b6fadd315ea631875b4256fbLally Singh return 0; 361e8386d21992b6683b6fadd315ea631875b4256fbLally Singh } 362e8386d21992b6683b6fadd315ea631875b4256fbLally Singh channel->OnSendThresholdCallback(); 363e8386d21992b6683b6fadd315ea631875b4256fbLally Singh return 0; 364e8386d21992b6683b6fadd315ea631875b4256fbLally Singh} 365e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 366d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgSctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) 36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : worker_thread_(thread), 3689c16c39e613ebc5cdfa8ca5818a62ef5c3b18bd7jiayl@webrtc.org local_port_(kSctpDefaultPort), 3699c16c39e613ebc5cdfa8ca5818a62ef5c3b18bd7jiayl@webrtc.org remote_port_(kSctpDefaultPort), 37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sock_(NULL), 37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sending_(false), 37228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org receiving_(false), 37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org debug_name_("SctpDataMediaChannel") { 37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSctpDataMediaChannel::~SctpDataMediaChannel() { 37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CloseSctpSocket(); 37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 380e8386d21992b6683b6fadd315ea631875b4256fbLally Singhvoid SctpDataMediaChannel::OnSendThresholdCallback() { 38191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(rtc::Thread::Current() == worker_thread_); 382e8386d21992b6683b6fadd315ea631875b4256fbLally Singh SignalReadyToSend(true); 383e8386d21992b6683b6fadd315ea631875b4256fbLally Singh} 384e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 38528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgsockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { 38628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sockaddr_conn sconn = {0}; 38728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sconn.sconn_family = AF_CONN; 38828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_SCONN_LEN 38928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sconn.sconn_len = sizeof(sockaddr_conn); 39028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif 39128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Note: conversion from int to uint16_t happens here. 392d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org sconn.sconn_port = rtc::HostToNetwork16(port); 39328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sconn.sconn_addr = this; 39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return sconn; 39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::OpenSctpSocket() { 39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sock_) { 39928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ 40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "->Ignoring attempt to re-create existing socket."; 40128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 40228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 403e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 404e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // If kSendBufferSize isn't reflective of reality, we log an error, but we 405e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // still have to do something reasonable here. Look up what the buffer's 406e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // real size is and set our threshold to something reasonable. 407e8386d21992b6683b6fadd315ea631875b4256fbLally Singh const static int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 2; 408e8386d21992b6683b6fadd315ea631875b4256fbLally Singh 40928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, 410e8386d21992b6683b6fadd315ea631875b4256fbLally Singh cricket::OnSctpInboundPacket, 411e8386d21992b6683b6fadd315ea631875b4256fbLally Singh &SctpDataEngine::SendThresholdCallback, 412e8386d21992b6683b6fadd315ea631875b4256fbLally Singh kSendThreshold, this); 41328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!sock_) { 41428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; 41528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 41628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 41728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 41828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Make the socket non-blocking. Connect, close, shutdown etc will not block 41928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // the thread waiting for the socket operation to complete. 42028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (usrsctp_set_non_blocking(sock_, 1) < 0) { 42128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; 42228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 42328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 42428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 42528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // This ensures that the usrsctp close call deletes the association. This 42628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // prevents usrsctp from calling OnSctpOutboundPacket with references to 42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // this class as the address. 42828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org linger linger_opt; 42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org linger_opt.l_onoff = 1; 43028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org linger_opt.l_linger = 0; 43128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (usrsctp_setsockopt(sock_, SOL_SOCKET, SO_LINGER, &linger_opt, 43228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sizeof(linger_opt))) { 43328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SO_LINGER."; 43428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 43528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 43628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 437f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Enable stream ID resets. 438f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org struct sctp_assoc_value stream_rst; 439f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org stream_rst.assoc_id = SCTP_ALL_ASSOC; 440f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org stream_rst.assoc_value = 1; 441f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, 442f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org &stream_rst, sizeof(stream_rst))) { 443f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ 444f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "Failed to set SCTP_ENABLE_STREAM_RESET."; 445f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 446f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 447f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 448f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Nagle. 449a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org uint32_t nodelay = 1; 450a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, 451a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org sizeof(nodelay))) { 452a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; 453a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org return false; 454a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org } 455a59696b2a5f0c138d4176249bac223ad6c4316d5sergeyu@chromium.org 456624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org // Disable MTU discovery 457e8386d21992b6683b6fadd315ea631875b4256fbLally Singh sctp_paddrparams params = {{0}}; 458624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org params.spp_assoc_id = 0; 459624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org params.spp_flags = SPP_PMTUD_DISABLE; 460624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org params.spp_pathmtu = kSctpMtu; 461624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, 462624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org sizeof(params))) { 463624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ 464624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org << "Failed to set SCTP_PEER_ADDR_PARAMS."; 465624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org return false; 466624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org } 467624a504f5ba0c2ca2a9a138e6d3ed1c1937b8df4buildbot@webrtc.org 46828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Subscribe to SCTP event notifications. 46928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int event_types[] = {SCTP_ASSOC_CHANGE, 47028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SCTP_PEER_ADDR_CHANGE, 471d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org SCTP_SEND_FAILED_EVENT, 472f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org SCTP_SENDER_DRY_EVENT, 473f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org SCTP_STREAM_RESET_EVENT}; 47428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org struct sctp_event event = {0}; 47528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org event.se_assoc_id = SCTP_ALL_ASSOC; 47628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org event.se_on = 1; 4775237aaf243d29732f59557361b7a993c0a18cf0etfarina for (size_t i = 0; i < arraysize(event_types); i++) { 47828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org event.se_type = event_types[i]; 47928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EVENT, &event, 48028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sizeof(event)) < 0) { 48128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_EVENT type: " 48228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << event.se_type; 48328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 48428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 48528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 48628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 48728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Register this class as an address for usrsctp. This is used by SCTP to 48828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // direct the packets received (by the created socket) to this class. 48928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_register_address(this); 49028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sending_ = true; 49128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 49228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 49328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 49428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::CloseSctpSocket() { 49528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sending_ = false; 49628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sock_) { 49728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We assume that SO_LINGER option is set to close the association when 49828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // close is called. This means that any pending packets in usrsctp will be 49928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // discarded instead of being sent. 50028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_close(sock_); 50128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sock_ = NULL; 50228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org usrsctp_deregister_address(this); 50328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 50428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 50528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 50628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::Connect() { 50728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->Connect()."; 50828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 50928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // If we already have a socket connection, just return. 51028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sock_) { 51128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket " 51228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "is already established."; 51328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 51428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 51528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 51628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // If no socket (it was closed) try to start it again. This can happen when 51728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // the socket we are connecting to closes, does an sctp shutdown handshake, 51828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // or behaves unexpectedly causing us to perform a CloseSctpSocket. 51928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!sock_ && !OpenSctpSocket()) { 52028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 52128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 52228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 52328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Note: conversion from int to uint16_t happens on assignment. 52428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sockaddr_conn local_sconn = GetSctpSockAddr(local_port_); 52528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (usrsctp_bind(sock_, reinterpret_cast<sockaddr *>(&local_sconn), 52628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sizeof(local_sconn)) < 0) { 52728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "->Connect(): " 52828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << ("Failed usrsctp_bind"); 52928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CloseSctpSocket(); 53028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 53128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 53228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 53328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Note: conversion from int to uint16_t happens on assignment. 53428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sockaddr_conn remote_sconn = GetSctpSockAddr(remote_port_); 53528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int connect_result = usrsctp_connect( 53628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sock_, reinterpret_cast<sockaddr *>(&remote_sconn), sizeof(remote_sconn)); 53728654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org if (connect_result < 0 && errno != SCTP_EINPROGRESS) { 53828654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed usrsctp_connect. got errno=" 53928654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org << errno << ", but wanted " << SCTP_EINPROGRESS; 54028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CloseSctpSocket(); 54128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 54228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 54328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 54428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 54528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 54628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::Disconnect() { 54728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Consider calling |usrsctp_shutdown(sock_, ...)| to do a 54828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // shutdown handshake and remove the association. 54928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CloseSctpSocket(); 55028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 55128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 55228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::SetSend(bool send) { 55328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!sending_ && send) { 55428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return Connect(); 55528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 55628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sending_ && !send) { 55728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org Disconnect(); 55828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 55928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 56028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 56128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 56228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::SetReceive(bool receive) { 56328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org receiving_ = receive; 56428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 56528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 56628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 567b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenbergbool SctpDataMediaChannel::SetSendParameters(const DataSendParameters& params) { 568b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg return SetSendCodecs(params.codecs); 569b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg} 570b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg 571b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenbergbool SctpDataMediaChannel::SetRecvParameters(const DataRecvParameters& params) { 572b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg return SetRecvCodecs(params.codecs); 573b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg} 574b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg 57528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::AddSendStream(const StreamParams& stream) { 576f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return AddStream(stream); 57728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 57828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SctpDataMediaChannel::RemoveSendStream(uint32_t ssrc) { 580f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return ResetStream(ssrc); 58128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 58228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 58328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::AddRecvStream(const StreamParams& stream) { 584aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // SCTP DataChannels are always bi-directional and calling AddSendStream will 585aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // enable both sending and receiving on the stream. So AddRecvStream is a 586aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // no-op. 587aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org return true; 58828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 58928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SctpDataMediaChannel::RemoveRecvStream(uint32_t ssrc) { 591aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // SCTP DataChannels are always bi-directional and calling RemoveSendStream 592aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // will disable both sending and receiving on the stream. So RemoveRecvStream 593aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // is a no-op. 594aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org return true; 59528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 59628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 59728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SctpDataMediaChannel::SendData( 59828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const SendDataParams& params, 599d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org const rtc::Buffer& payload, 60028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SendDataResult* result) { 60128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (result) { 6021112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // Preset |result| to assume an error. If SendData succeeds, we'll 6031112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // overwrite |*result| once more at the end. 60428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *result = SDR_ERROR; 60528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 60628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 60728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!sending_) { 60828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 60928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "Not sending packet with ssrc=" << params.ssrc 610eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org << " len=" << payload.size() << " before SetSend(true)."; 61128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 61228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 61328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 61491053e7c5a743f4a92f5079844b0747c927f3bbdwu@webrtc.org if (params.type != cricket::DMT_CONTROL && 615f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org open_streams_.find(params.ssrc) == open_streams_.end()) { 61628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 61728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "Not sending data because ssrc is unknown: " 61828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << params.ssrc; 61928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 62028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 62128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 62228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // 62328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Send data using SCTP. 6241112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org ssize_t send_res = 0; // result from usrsctp_sendv. 6251112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org struct sctp_sendv_spa spa = {0}; 6261112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID; 6271112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_sndinfo.snd_sid = params.ssrc; 628d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org spa.sendv_sndinfo.snd_ppid = rtc::HostToNetwork32( 6291112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org GetPpid(params.type)); 6301112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 6311112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // Ordered implies reliable. 6321112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org if (!params.ordered) { 6331112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED; 6341112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) { 6351112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 6361112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX; 6371112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_prinfo.pr_value = params.max_rtx_count; 6381112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org } else { 6391112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; 6401112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL; 6411112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org spa.sendv_prinfo.pr_value = params.max_rtx_ms; 6421112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org } 6431112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org } 6441112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org 6451112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // We don't fragment. 646eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org send_res = usrsctp_sendv( 647eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org sock_, payload.data(), static_cast<size_t>(payload.size()), NULL, 0, &spa, 648eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org rtc::checked_cast<socklen_t>(sizeof(spa)), SCTP_SENDV_SPA, 0); 6491112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org if (send_res < 0) { 650f7026cd7c84b7c10894972ba03d8d7b9c04a99f0jiayl@webrtc.org if (errno == SCTP_EWOULDBLOCK) { 651d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org *result = SDR_BLOCK; 652d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned"; 653d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org } else { 654d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_ 655d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org << "->SendData(...): " 656d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org << " usrsctp_sendv: "; 657d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org } 65828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 65928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 66028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (result) { 6611112c30e1e5f5c7b4b517c4954ef3f15b989a996mallinath@webrtc.org // Only way out now is success. 66228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *result = SDR_SUCCESS; 66328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 66428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 66528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 66628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 66728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Called by network interface when a packet has been received. 668a9890800e078105f21f0a21358ee59a0b3736af6wu@webrtc.orgvoid SctpDataMediaChannel::OnPacketReceived( 669d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 67091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(rtc::Thread::Current() == worker_thread_); 671eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " 672eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org << " length=" << packet->size() << ", sending: " << sending_; 67328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Only give receiving packets to usrsctp after if connected. This enables two 67428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // peers to each make a connect call, but for them not to receive an INIT 67528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // packet before they have called connect; least the last receiver of the INIT 67628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // packet will have called connect, and a connection will be established. 67728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sending_) { 67828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Pass received packet to SCTP stack. Once processed by usrsctp, the data 67928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // will be will be given to the global OnSctpInboundData, and then, 68028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // marshalled by a Post and handled with OnMessage. 6814c277bb938854a6a174e8bfece0bc9a7928da1abLally Singh VerboseLogPacket(packet->data(), packet->size(), SCTP_DUMP_INBOUND); 682eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org usrsctp_conninput(this, packet->data(), packet->size(), 0); 68328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 68428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Consider caching the packet for very slightly better 68528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // reliability. 68628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 68728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 68828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 68928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::OnInboundPacketFromSctpToChannel( 69028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SctpInboundPacket* packet) { 69128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 69228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "Received SCTP data:" 69328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " ssrc=" << packet->params.ssrc 69428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " notification: " << (packet->flags & MSG_NOTIFICATION) 695eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org << " length=" << packet->buffer.size(); 69628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Sending a packet with data == NULL (no data) is SCTPs "close the 69728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // connection" message. This sets sock_ = NULL; 698eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org if (!packet->buffer.size() || !packet->buffer.data()) { 69928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 70028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org "No data, closing."; 70128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 70228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 70328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (packet->flags & MSG_NOTIFICATION) { 70428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org OnNotificationFromSctp(&packet->buffer); 70528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 70628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org OnDataFromSctpToChannel(packet->params, &packet->buffer); 70728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 70828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 70928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 71028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::OnDataFromSctpToChannel( 711d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org const ReceiveDataParams& params, rtc::Buffer* buffer) { 71228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (receiving_) { 71328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): " 714eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org << "Posting with length: " << buffer->size() 715aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org << " on stream " << params.ssrc; 716aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // Reports all received messages to upper layers, no matter whether the sid 717aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org // is known. 7189478437fdea4eb31b92ffe0c10368fe5bc9b9e16Karl Wiberg SignalDataReceived(params, buffer->data<char>(), buffer->size()); 71928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 72028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): " 72128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << "Not receiving packet with sid=" << params.ssrc 722eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org << " len=" << buffer->size() << " before SetReceive(true)."; 72328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 72428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 72528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 726f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgbool SctpDataMediaChannel::AddStream(const StreamParams& stream) { 727f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (!stream.has_ssrcs()) { 728f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 729f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 730f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 7310c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint32_t ssrc = stream.first_ssrc(); 73227ed3cc28cf950456a0c66d7a10656a96832feddlally if (ssrc >= cricket::kMaxSctpSid) { 73327ed3cc28cf950456a0c66d7a10656a96832feddlally LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 73427ed3cc28cf950456a0c66d7a10656a96832feddlally << "Not adding data stream '" << stream.id 73527ed3cc28cf950456a0c66d7a10656a96832feddlally << "' with ssrc=" << ssrc 73627ed3cc28cf950456a0c66d7a10656a96832feddlally << " because stream ssrc is too high."; 73727ed3cc28cf950456a0c66d7a10656a96832feddlally return false; 73827ed3cc28cf950456a0c66d7a10656a96832feddlally } else if (open_streams_.find(ssrc) != open_streams_.end()) { 739aebb1ade9d760841f243e380fa22b7ecff2d3ecchenrika@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 740f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "Not adding data stream '" << stream.id 741f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "' with ssrc=" << ssrc 742f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << " because stream is already open."; 743f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 744f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else if (queued_reset_streams_.find(ssrc) != queued_reset_streams_.end() 745f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org || sent_reset_streams_.find(ssrc) != sent_reset_streams_.end()) { 746f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): " 747f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "Not adding data stream '" << stream.id 748f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "' with ssrc=" << ssrc 749f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << " because stream is still closing."; 750f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 751f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 752f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 753f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org open_streams_.insert(ssrc); 754f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return true; 755f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 756f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 7570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SctpDataMediaChannel::ResetStream(uint32_t ssrc) { 758f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // We typically get this called twice for the same stream, once each for 759f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Send and Recv. 760f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org StreamSet::iterator found = open_streams_.find(ssrc); 761f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 762f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (found == open_streams_.end()) { 763f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 764f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "stream not found."; 765f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 766f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else { 767f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): " 768f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "Removing and queuing RE-CONFIG chunk."; 769f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org open_streams_.erase(found); 770f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 771f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 772f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // SCTP won't let you have more than one stream reset pending at a time, but 773f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // you can close multiple streams in a single reset. So, we keep an internal 774f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // queue of streams-to-reset, and send them as one reset message in 775f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // SendQueuedStreamResets(). 776f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org queued_reset_streams_.insert(ssrc); 777f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 778f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Signal our stream-reset logic that it should try to send now, if it can. 779f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org SendQueuedStreamResets(); 780f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 781f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // The stream will actually get removed when we get the acknowledgment. 782f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return true; 783f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 784f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 785d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid SctpDataMediaChannel::OnNotificationFromSctp(rtc::Buffer* buffer) { 78628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const sctp_notification& notification = 78728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org reinterpret_cast<const sctp_notification&>(*buffer->data()); 788eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org ASSERT(notification.sn_header.sn_length == buffer->size()); 78928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 79028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): handle notifications appropriately. 79128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org switch (notification.sn_header.sn_type) { 79228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_ASSOC_CHANGE: 79328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE"; 79428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org OnNotificationAssocChange(notification.sn_assoc_change); 79528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 79628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_REMOTE_ERROR: 79728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_REMOTE_ERROR"; 79828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 79928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_SHUTDOWN_EVENT: 80028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_SHUTDOWN_EVENT"; 80128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 80228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_ADAPTATION_INDICATION: 803f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_INFO) << "SCTP_ADAPTATION_INDICATION"; 80428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 80528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_PARTIAL_DELIVERY_EVENT: 80628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_PARTIAL_DELIVERY_EVENT"; 80728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 80828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_AUTHENTICATION_EVENT: 80928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_AUTHENTICATION_EVENT"; 81028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 81128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_SENDER_DRY_EVENT: 812f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_SENDER_DRY_EVENT"; 813d64719d8954262fee94e7615422f3d027dc1ae6bwu@webrtc.org SignalReadyToSend(true); 81428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 81528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ldixon): Unblock after congestion. 81628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_NOTIFICATIONS_STOPPED_EVENT: 81728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_NOTIFICATIONS_STOPPED_EVENT"; 81828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 81928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_SEND_FAILED_EVENT: 82028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_SEND_FAILED_EVENT"; 82128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 82228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_STREAM_RESET_EVENT: 823f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org OnStreamResetEvent(¬ification.sn_strreset_event); 82428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 82528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_ASSOC_RESET_EVENT: 82628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_ASSOC_RESET_EVENT"; 82728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 82828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_STREAM_CHANGE_EVENT: 82928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "SCTP_STREAM_CHANGE_EVENT"; 830f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // An acknowledgment we get after our stream resets have gone through, 831f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // if they've failed. We log the message, but don't react -- we don't 832f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // keep around the last-transmitted set of SSIDs we wanted to close for 833f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // error recovery. It doesn't seem likely to occur, and if so, likely 834f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // harmless within the lifetime of a single SCTP association. 83528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 83628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org default: 83728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Unknown SCTP event: " 83828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << notification.sn_header.sn_type; 83928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 84028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 84128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 84228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 84328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::OnNotificationAssocChange( 84428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const sctp_assoc_change& change) { 84528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org switch (change.sac_state) { 84628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_COMM_UP: 84728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << "Association change SCTP_COMM_UP"; 84828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 84928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_COMM_LOST: 85028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_COMM_LOST"; 85128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 85228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_RESTART: 85328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_RESTART"; 85428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 85528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_SHUTDOWN_COMP: 85628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_SHUTDOWN_COMP"; 85728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 85828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case SCTP_CANT_STR_ASSOC: 85928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Association change SCTP_CANT_STR_ASSOC"; 86028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 86128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org default: 86228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Association change UNKNOWN"; 86328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 86428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 86528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 86628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 867f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgvoid SctpDataMediaChannel::OnStreamResetEvent( 868f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org const struct sctp_stream_reset_event* evt) { 869f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // A stream reset always involves two RE-CONFIG chunks for us -- we always 870f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // simultaneously reset a sid's sequence number in both directions. The 871f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // requesting side transmits a RE-CONFIG chunk and waits for the peer to send 872f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // one back. Both sides get this SCTP_STREAM_RESET_EVENT when they receive 873f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // RE-CONFIGs. 874f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org const int num_ssrcs = (evt->strreset_length - sizeof(*evt)) / 875f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org sizeof(evt->strreset_stream_list[0]); 876f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 877f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "): Flags = 0x" 878f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << std::hex << evt->strreset_flags << " (" 879f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListFlags(evt->strreset_flags) << ")"; 880f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "Assoc = " << evt->strreset_assoc_id << ", Streams = [" 881f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListArray(evt->strreset_stream_list, num_ssrcs) 882f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "], Open: [" 883f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(open_streams_) << "], Q'd: [" 884f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(queued_reset_streams_) << "], Sent: [" 885f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(sent_reset_streams_) << "]"; 886f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 887f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // If both sides try to reset some streams at the same time (even if they're 888f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // disjoint sets), we can get reset failures. 889f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (evt->strreset_flags & SCTP_STREAM_RESET_FAILED) { 890f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // OK, just try again. The stream IDs sent over when the RESET_FAILED flag 891f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // is set seem to be garbage values. Ignore them. 892f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org queued_reset_streams_.insert( 893f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org sent_reset_streams_.begin(), 894f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org sent_reset_streams_.end()); 895f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org sent_reset_streams_.clear(); 896f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 897f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else if (evt->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) { 898f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Each side gets an event for each direction of a stream. That is, 899f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // closing sid k will make each side receive INCOMING and OUTGOING reset 900f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // events for k. As per RFC6525, Section 5, paragraph 2, each side will 901f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // get an INCOMING event first. 902f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org for (int i = 0; i < num_ssrcs; i++) { 903f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org const int stream_id = evt->strreset_stream_list[i]; 904f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 905f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // See if this stream ID was closed by our peer or ourselves. 906f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org StreamSet::iterator it = sent_reset_streams_.find(stream_id); 907f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 908f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // The reset was requested locally. 909f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (it != sent_reset_streams_.end()) { 910f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 911f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "): local sid " << stream_id << " acknowledged."; 912f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org sent_reset_streams_.erase(it); 913f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 914f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else if ((it = open_streams_.find(stream_id)) 915f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org != open_streams_.end()) { 916f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // The peer requested the reset. 917f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 918f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "): closing sid " << stream_id; 919f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org open_streams_.erase(it); 9201d66be22c8f929e1170f288472aac9d4b44b7a05buildbot@webrtc.org SignalStreamClosedRemotely(stream_id); 921f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 922f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else if ((it = queued_reset_streams_.find(stream_id)) 923f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org != queued_reset_streams_.end()) { 924f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // The peer requested the reset, but there was a local reset 925f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // queued. 926f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 927f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "): double-sided close for sid " << stream_id; 928f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Both sides want the stream closed, and the peer got to send the 929f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // RE-CONFIG first. Treat it like the local Remove(Send|Recv)Stream 930f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // finished quickly. 931f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org queued_reset_streams_.erase(it); 932f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 933f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } else { 934f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // This stream is unknown. Sometimes this can be from an 935f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // RESET_FAILED-related retransmit. 936f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_ 937f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "): Unknown sid " << stream_id; 938f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 939f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 940f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 941f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 9421a6c6281ca028e4fbba5c015ed7166ffc34bae9cjiayl@webrtc.org // Always try to send the queued RESET because this call indicates that the 9431a6c6281ca028e4fbba5c015ed7166ffc34bae9cjiayl@webrtc.org // last local RESET or remote RESET has made some progress. 9441a6c6281ca028e4fbba5c015ed7166ffc34bae9cjiayl@webrtc.org SendQueuedStreamResets(); 945f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 946f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 94778187525665490922748d79377bcb351579e03c0wu@webrtc.org// Puts the specified |param| from the codec identified by |id| into |dest| 94878187525665490922748d79377bcb351579e03c0wu@webrtc.org// and returns true. Or returns false if it wasn't there, leaving |dest| 94978187525665490922748d79377bcb351579e03c0wu@webrtc.org// untouched. 95078187525665490922748d79377bcb351579e03c0wu@webrtc.orgstatic bool GetCodecIntParameter(const std::vector<DataCodec>& codecs, 95178187525665490922748d79377bcb351579e03c0wu@webrtc.org int id, const std::string& name, 95278187525665490922748d79377bcb351579e03c0wu@webrtc.org const std::string& param, int* dest) { 95378187525665490922748d79377bcb351579e03c0wu@webrtc.org std::string value; 95478187525665490922748d79377bcb351579e03c0wu@webrtc.org Codec match_pattern; 95578187525665490922748d79377bcb351579e03c0wu@webrtc.org match_pattern.id = id; 95678187525665490922748d79377bcb351579e03c0wu@webrtc.org match_pattern.name = name; 95778187525665490922748d79377bcb351579e03c0wu@webrtc.org for (size_t i = 0; i < codecs.size(); ++i) { 95878187525665490922748d79377bcb351579e03c0wu@webrtc.org if (codecs[i].Matches(match_pattern)) { 95978187525665490922748d79377bcb351579e03c0wu@webrtc.org if (codecs[i].GetParam(param, &value)) { 960d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org *dest = rtc::FromString<int>(value); 96178187525665490922748d79377bcb351579e03c0wu@webrtc.org return true; 96278187525665490922748d79377bcb351579e03c0wu@webrtc.org } 96378187525665490922748d79377bcb351579e03c0wu@webrtc.org } 96478187525665490922748d79377bcb351579e03c0wu@webrtc.org } 96578187525665490922748d79377bcb351579e03c0wu@webrtc.org return false; 96678187525665490922748d79377bcb351579e03c0wu@webrtc.org} 96778187525665490922748d79377bcb351579e03c0wu@webrtc.org 96878187525665490922748d79377bcb351579e03c0wu@webrtc.orgbool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) { 96978187525665490922748d79377bcb351579e03c0wu@webrtc.org return GetCodecIntParameter( 97078187525665490922748d79377bcb351579e03c0wu@webrtc.org codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 97178187525665490922748d79377bcb351579e03c0wu@webrtc.org &remote_port_); 97278187525665490922748d79377bcb351579e03c0wu@webrtc.org} 97378187525665490922748d79377bcb351579e03c0wu@webrtc.org 97478187525665490922748d79377bcb351579e03c0wu@webrtc.orgbool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { 97578187525665490922748d79377bcb351579e03c0wu@webrtc.org return GetCodecIntParameter( 97678187525665490922748d79377bcb351579e03c0wu@webrtc.org codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 97778187525665490922748d79377bcb351579e03c0wu@webrtc.org &local_port_); 97878187525665490922748d79377bcb351579e03c0wu@webrtc.org} 97928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 98028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SctpDataMediaChannel::OnPacketFromSctpToNetwork( 981d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::Buffer* buffer) { 982e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // usrsctp seems to interpret the MTU we give it strangely -- it seems to 983e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // give us back packets bigger than that MTU, if only by a fixed amount. 984e8386d21992b6683b6fadd315ea631875b4256fbLally Singh // This is that amount that we've observed. 985e8386d21992b6683b6fadd315ea631875b4256fbLally Singh const int kSctpOverhead = 76; 986e8386d21992b6683b6fadd315ea631875b4256fbLally Singh if (buffer->size() > (kSctpOverhead + kSctpMtu)) { 98728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " 988f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << "SCTP seems to have made a packet that is bigger " 989e8386d21992b6683b6fadd315ea631875b4256fbLally Singh << "than its official MTU: " << buffer->size() 990e8386d21992b6683b6fadd315ea631875b4256fbLally Singh << " vs max of " << kSctpMtu 991e8386d21992b6683b6fadd315ea631875b4256fbLally Singh << " even after adding " << kSctpOverhead 992e8386d21992b6683b6fadd315ea631875b4256fbLally Singh << " extra SCTP overhead"; 99328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 994c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan MediaChannel::SendPacket(buffer, rtc::PacketOptions()); 99528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 99628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 997f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.orgbool SctpDataMediaChannel::SendQueuedStreamResets() { 998f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) 999f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return true; 1000f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 1001f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" 1002f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(queued_reset_streams_) << "], Open: [" 1003f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(open_streams_) << "], Sent: [" 1004f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << ListStreams(sent_reset_streams_) << "]"; 1005f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 1006f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org const size_t num_streams = queued_reset_streams_.size(); 10070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const size_t num_bytes = 10080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström sizeof(struct sctp_reset_streams) + (num_streams * sizeof(uint16_t)); 1009f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 10100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström std::vector<uint8_t> reset_stream_buf(num_bytes, 0); 1011f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org struct sctp_reset_streams* resetp = reinterpret_cast<sctp_reset_streams*>( 1012f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org &reset_stream_buf[0]); 1013f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org resetp->srs_assoc_id = SCTP_ALL_ASSOC; 1014f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org resetp->srs_flags = SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_OUTGOING; 1015d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org resetp->srs_number_streams = rtc::checked_cast<uint16_t>(num_streams); 1016f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org int result_idx = 0; 1017f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org for (StreamSet::iterator it = queued_reset_streams_.begin(); 1018f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org it != queued_reset_streams_.end(); ++it) { 1019f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org resetp->srs_stream_list[result_idx++] = *it; 1020f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 1021f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 1022a576faf82a692c9422dcdc3278394ed25e6ee4f7jiayl@webrtc.org int ret = usrsctp_setsockopt( 1023a576faf82a692c9422dcdc3278394ed25e6ee4f7jiayl@webrtc.org sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp, 1024d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::checked_cast<socklen_t>(reset_stream_buf.size())); 1025f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (ret < 0) { 1026f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to send a stream reset for " 1027f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org << num_streams << " streams"; 1028f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return false; 1029f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 1030f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 1031f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // sent_reset_streams_ is empty, and all the queued_reset_streams_ go into 1032f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // it now. 1033f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org queued_reset_streams_.swap(sent_reset_streams_); 1034f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return true; 1035f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org} 1036f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org 1037d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid SctpDataMediaChannel::OnMessage(rtc::Message* msg) { 103828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org switch (msg->message_id) { 103928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case MSG_SCTPINBOUNDPACKET: { 1040d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_ptr<InboundPacketMessage> pdata( 1041f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org static_cast<InboundPacketMessage*>(msg->pdata)); 1042f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org OnInboundPacketFromSctpToChannel(pdata->data().get()); 104328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 104428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 104528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case MSG_SCTPOUTBOUNDPACKET: { 1046d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_ptr<OutboundPacketMessage> pdata( 1047f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org static_cast<OutboundPacketMessage*>(msg->pdata)); 1048f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org OnPacketFromSctpToNetwork(pdata->data().get()); 104928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 105028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 105128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 105228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 105328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace cricket 1054