1 /* 2 * libjingle SCTP 3 * Copyright 2012 Google Inc, and Robin Seggelmann 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_MEDIA_SCTP_SCTPDATAENGINE_H_ 29 #define TALK_MEDIA_SCTP_SCTPDATAENGINE_H_ 30 31 #include <errno.h> 32 #include <string> 33 #include <vector> 34 35 namespace cricket { 36 // Some ERRNO values get re-#defined to WSA* equivalents in some talk/ 37 // headers. We save the original ones in an enum. 38 enum PreservedErrno { 39 SCTP_EINPROGRESS = EINPROGRESS, 40 SCTP_EWOULDBLOCK = EWOULDBLOCK 41 }; 42 } // namespace cricket 43 44 #include "talk/base/buffer.h" 45 #include "talk/base/scoped_ptr.h" 46 #include "talk/media/base/codec.h" 47 #include "talk/media/base/mediachannel.h" 48 #include "talk/media/base/mediaengine.h" 49 50 // Defined by "usrsctplib/usrsctp.h" 51 struct sockaddr_conn; 52 struct sctp_assoc_change; 53 // Defined by <sys/socket.h> 54 struct socket; 55 56 namespace cricket { 57 // The highest stream ID (Sid) that SCTP allows, and the number of streams we 58 // tell SCTP we're going to use. 59 const uint32 kMaxSctpSid = 1023; 60 61 // A DataEngine that interacts with usrsctp. 62 // 63 // From channel calls, data flows like this: 64 // [worker thread (although it can in princple be another thread)] 65 // 1. SctpDataMediaChannel::SendData(data) 66 // 2. usrsctp_sendv(data) 67 // [worker thread returns; sctp thread then calls the following] 68 // 3. OnSctpOutboundPacket(wrapped_data) 69 // [sctp thread returns having posted a message for the worker thread] 70 // 4. SctpDataMediaChannel::OnMessage(wrapped_data) 71 // 5. SctpDataMediaChannel::OnPacketFromSctpToNetwork(wrapped_data) 72 // 6. NetworkInterface::SendPacket(wrapped_data) 73 // 7. ... across network ... a packet is sent back ... 74 // 8. SctpDataMediaChannel::OnPacketReceived(wrapped_data) 75 // 9. usrsctp_conninput(wrapped_data) 76 // [worker thread returns; sctp thread then calls the following] 77 // 10. OnSctpInboundData(data) 78 // [sctp thread returns having posted a message fot the worker thread] 79 // 11. SctpDataMediaChannel::OnMessage(inboundpacket) 80 // 12. SctpDataMediaChannel::OnInboundPacketFromSctpToChannel(inboundpacket) 81 // 13. SctpDataMediaChannel::OnDataFromSctpToChannel(data) 82 // 14. SctpDataMediaChannel::SignalDataReceived(data) 83 // [from the same thread, methods registered/connected to 84 // SctpDataMediaChannel are called with the recieved data] 85 class SctpDataEngine : public DataEngineInterface { 86 public: 87 SctpDataEngine(); 88 virtual ~SctpDataEngine(); 89 90 virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type); 91 data_codecs()92 virtual const std::vector<DataCodec>& data_codecs() { return codecs_; } 93 94 private: 95 static int usrsctp_engines_count; 96 std::vector<DataCodec> codecs_; 97 }; 98 99 // TODO(ldixon): Make into a special type of TypedMessageData. 100 // Holds data to be passed on to a channel. 101 struct SctpInboundPacket; 102 103 class SctpDataMediaChannel : public DataMediaChannel, 104 public talk_base::MessageHandler { 105 public: 106 // DataMessageType is used for the SCTP "Payload Protocol Identifier", as 107 // defined in http://tools.ietf.org/html/rfc4960#section-14.4 108 // 109 // For the list of IANA approved values see: 110 // http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xml 111 // The value is not used by SCTP itself. It indicates the protocol running 112 // on top of SCTP. 113 enum PayloadProtocolIdentifier { 114 PPID_NONE = 0, // No protocol is specified. 115 // Matches the PPIDs in mozilla source and 116 // https://datatracker.ietf.org/doc/draft-ietf-rtcweb-data-protocol Sec. 9 117 // They're not yet assigned by IANA. 118 PPID_CONTROL = 50, 119 PPID_BINARY_PARTIAL = 52, 120 PPID_BINARY_LAST = 53, 121 PPID_TEXT_PARTIAL = 54, 122 PPID_TEXT_LAST = 51 123 }; 124 125 // Given a thread which will be used to post messages (received data) to this 126 // SctpDataMediaChannel instance. 127 explicit SctpDataMediaChannel(talk_base::Thread* thread); 128 virtual ~SctpDataMediaChannel(); 129 130 // When SetSend is set to true, connects. When set to false, disconnects. 131 // Calling: "SetSend(true); SetSend(false); SetSend(true);" will connect, 132 // disconnect, and reconnect. 133 virtual bool SetSend(bool send); 134 // Unless SetReceive(true) is called, received packets will be discarded. 135 virtual bool SetReceive(bool receive); 136 137 virtual bool AddSendStream(const StreamParams& sp); 138 virtual bool RemoveSendStream(uint32 ssrc); 139 virtual bool AddRecvStream(const StreamParams& sp); 140 virtual bool RemoveRecvStream(uint32 ssrc); 141 142 // Called when Sctp gets data. The data may be a notification or data for 143 // OnSctpInboundData. Called from the worker thread. 144 virtual void OnMessage(talk_base::Message* msg); 145 // Send data down this channel (will be wrapped as SCTP packets then given to 146 // sctp that will then post the network interface by OnMessage). 147 // Returns true iff successful data somewhere on the send-queue/network. 148 virtual bool SendData(const SendDataParams& params, 149 const talk_base::Buffer& payload, 150 SendDataResult* result = NULL); 151 // A packet is received from the network interface. Posted to OnMessage. 152 virtual void OnPacketReceived(talk_base::Buffer* packet, 153 const talk_base::PacketTime& packet_time); 154 155 // Exposed to allow Post call from c-callbacks. worker_thread()156 talk_base::Thread* worker_thread() const { return worker_thread_; } 157 158 // TODO(ldixon): add a DataOptions class to mediachannel.h SetOptions(int options)159 virtual bool SetOptions(int options) { return false; } GetOptions()160 virtual int GetOptions() const { return 0; } 161 162 // Many of these things are unused by SCTP, but are needed to fulfill 163 // the MediaChannel interface. 164 // TODO(pthatcher): Cleanup MediaChannel interface, or at least 165 // don't try calling these and return false. Right now, things 166 // don't work if we return false. SetSendBandwidth(bool autobw,int bps)167 virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } SetRecvRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)168 virtual bool SetRecvRtpHeaderExtensions( 169 const std::vector<RtpHeaderExtension>& extensions) { return true; } SetSendRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)170 virtual bool SetSendRtpHeaderExtensions( 171 const std::vector<RtpHeaderExtension>& extensions) { return true; } 172 virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs); 173 virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs); OnRtcpReceived(talk_base::Buffer * packet,const talk_base::PacketTime & packet_time)174 virtual void OnRtcpReceived(talk_base::Buffer* packet, 175 const talk_base::PacketTime& packet_time) {} OnReadyToSend(bool ready)176 virtual void OnReadyToSend(bool ready) {} 177 178 // Helper for debugging. set_debug_name(const std::string & debug_name)179 void set_debug_name(const std::string& debug_name) { 180 debug_name_ = debug_name; 181 } debug_name()182 const std::string& debug_name() const { return debug_name_; } 183 184 private: 185 sockaddr_conn GetSctpSockAddr(int port); 186 187 // Creates the socket and connects. Sets sending_ to true. 188 bool Connect(); 189 // Closes the socket. Sets sending_ to false. 190 void Disconnect(); 191 192 // Returns false when openning the socket failed; when successfull sets 193 // sending_ to true 194 bool OpenSctpSocket(); 195 // Sets sending_ to false and sock_ to NULL. 196 void CloseSctpSocket(); 197 198 // Called by OnMessage to send packet on the network. 199 void OnPacketFromSctpToNetwork(talk_base::Buffer* buffer); 200 // Called by OnMessage to decide what to do with the packet. 201 void OnInboundPacketFromSctpToChannel(SctpInboundPacket* packet); 202 void OnDataFromSctpToChannel(const ReceiveDataParams& params, 203 talk_base::Buffer* buffer); 204 void OnNotificationFromSctp(talk_base::Buffer* buffer); 205 void OnNotificationAssocChange(const sctp_assoc_change& change); 206 207 // Responsible for marshalling incoming data to the channels listeners, and 208 // outgoing data to the network interface. 209 talk_base::Thread* worker_thread_; 210 // The local and remote SCTP port to use. These are passed along the wire 211 // and the listener and connector must be using the same port. It is not 212 // related to the ports at the IP level. If set to -1, we default to 213 // kSctpDefaultPort. 214 int local_port_; 215 int remote_port_; 216 struct socket* sock_; // The socket created by usrsctp_socket(...). 217 218 // sending_ is true iff there is a connected socket. 219 bool sending_; 220 // receiving_ controls whether inbound packets are thrown away. 221 bool receiving_; 222 // Unified send/receive streams, as each is bidirectional. 223 std::vector<StreamParams> streams_; 224 225 // A human-readable name for debugging messages. 226 std::string debug_name_; 227 }; 228 229 } // namespace cricket 230 231 #endif // TALK_MEDIA_SCTP_SCTPDATAENGINE_H_ 232