blob: 90011c4f466ead12302068d94a725fc0ab5704f0 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kjellandera96e2d72016-02-04 23:52:28 -080011#ifndef WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_
12#define WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000014#include <errno.h>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000015#include <string>
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000016#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000017
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000018namespace cricket {
19// Some ERRNO values get re-#defined to WSA* equivalents in some talk/
20// headers. We save the original ones in an enum.
21enum PreservedErrno {
22 SCTP_EINPROGRESS = EINPROGRESS,
23 SCTP_EWOULDBLOCK = EWOULDBLOCK
24};
25} // namespace cricket
26
jbaucheec21bd2016-03-20 06:15:43 -070027#include "webrtc/base/copyonwritebuffer.h"
Tommi7d013312016-05-19 19:58:38 +020028#include "webrtc/base/gtest_prod_util.h"
kjellandera96e2d72016-02-04 23:52:28 -080029#include "webrtc/media/base/codec.h"
30#include "webrtc/media/base/mediachannel.h"
31#include "webrtc/media/base/mediaengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032
33// Defined by "usrsctplib/usrsctp.h"
34struct sockaddr_conn;
35struct sctp_assoc_change;
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +000036struct sctp_stream_reset_event;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037// Defined by <sys/socket.h>
38struct socket;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039namespace cricket {
Taylor Brandstetter1d7a6372016-08-24 13:15:27 -070040// The number of outgoing streams that we'll negotiate. Since stream IDs (SIDs)
41// are 0-based, the highest usable SID is 1023.
42//
43// It's recommended to use the maximum of 65535 in:
44// https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.2
45// However, we use 1024 in order to save memory. usrsctp allocates 104 bytes
46// for each pair of incoming/outgoing streams (on a 64-bit system), so 65535
47// streams would waste ~6MB.
48//
49// Note: "max" and "min" here are inclusive.
50constexpr uint16_t kMaxSctpStreams = 1024;
51constexpr uint16_t kMaxSctpSid = kMaxSctpStreams - 1;
52constexpr uint16_t kMinSctpSid = 0;
mallinath@webrtc.org1112c302013-09-23 20:34:45 +000053
jiayl@webrtc.org9c16c392014-05-01 18:30:30 +000054// This is the default SCTP port to use. It is passed along the wire and the
55// connectee and connector must be using the same port. It is not related to the
56// ports at the IP level. (Corresponds to: sockaddr_conn.sconn_port in
57// usrsctp.h)
58const int kSctpDefaultPort = 5000;
59
Lally Singhe8386d22015-08-28 14:54:37 -040060class SctpDataMediaChannel;
61
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062// A DataEngine that interacts with usrsctp.
63//
64// From channel calls, data flows like this:
65// [worker thread (although it can in princple be another thread)]
66// 1. SctpDataMediaChannel::SendData(data)
67// 2. usrsctp_sendv(data)
68// [worker thread returns; sctp thread then calls the following]
69// 3. OnSctpOutboundPacket(wrapped_data)
70// [sctp thread returns having posted a message for the worker thread]
71// 4. SctpDataMediaChannel::OnMessage(wrapped_data)
72// 5. SctpDataMediaChannel::OnPacketFromSctpToNetwork(wrapped_data)
73// 6. NetworkInterface::SendPacket(wrapped_data)
74// 7. ... across network ... a packet is sent back ...
75// 8. SctpDataMediaChannel::OnPacketReceived(wrapped_data)
76// 9. usrsctp_conninput(wrapped_data)
77// [worker thread returns; sctp thread then calls the following]
78// 10. OnSctpInboundData(data)
79// [sctp thread returns having posted a message fot the worker thread]
80// 11. SctpDataMediaChannel::OnMessage(inboundpacket)
81// 12. SctpDataMediaChannel::OnInboundPacketFromSctpToChannel(inboundpacket)
82// 13. SctpDataMediaChannel::OnDataFromSctpToChannel(data)
83// 14. SctpDataMediaChannel::SignalDataReceived(data)
84// [from the same thread, methods registered/connected to
85// SctpDataMediaChannel are called with the recieved data]
Lally Singhe8386d22015-08-28 14:54:37 -040086class SctpDataEngine : public DataEngineInterface, public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 public:
88 SctpDataEngine();
Tommi7d013312016-05-19 19:58:38 +020089 ~SctpDataEngine() override;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090
Tommi7d013312016-05-19 19:58:38 +020091 DataMediaChannel* CreateChannel(DataChannelType data_channel_type) override;
92 const std::vector<DataCodec>& data_codecs() override { return codecs_; }
Lally Singhe8386d22015-08-28 14:54:37 -040093
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 private:
Tommi7d013312016-05-19 19:58:38 +020095 const std::vector<DataCodec> codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096};
97
98// TODO(ldixon): Make into a special type of TypedMessageData.
99// Holds data to be passed on to a channel.
100struct SctpInboundPacket;
101
102class SctpDataMediaChannel : public DataMediaChannel,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000103 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104 public:
105 // DataMessageType is used for the SCTP "Payload Protocol Identifier", as
106 // defined in http://tools.ietf.org/html/rfc4960#section-14.4
107 //
108 // For the list of IANA approved values see:
109 // http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xml
110 // The value is not used by SCTP itself. It indicates the protocol running
111 // on top of SCTP.
112 enum PayloadProtocolIdentifier {
113 PPID_NONE = 0, // No protocol is specified.
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000114 // Matches the PPIDs in mozilla source and
115 // https://datatracker.ietf.org/doc/draft-ietf-rtcweb-data-protocol Sec. 9
116 // They're not yet assigned by IANA.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117 PPID_CONTROL = 50,
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000118 PPID_BINARY_PARTIAL = 52,
119 PPID_BINARY_LAST = 53,
120 PPID_TEXT_PARTIAL = 54,
121 PPID_TEXT_LAST = 51
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122 };
123
Peter Boström0c4e06b2015-10-07 12:23:21 +0200124 typedef std::set<uint32_t> StreamSet;
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000125
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126 // Given a thread which will be used to post messages (received data) to this
127 // SctpDataMediaChannel instance.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000128 explicit SctpDataMediaChannel(rtc::Thread* thread);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 virtual ~SctpDataMediaChannel();
130
131 // When SetSend is set to true, connects. When set to false, disconnects.
132 // Calling: "SetSend(true); SetSend(false); SetSend(true);" will connect,
133 // disconnect, and reconnect.
134 virtual bool SetSend(bool send);
135 // Unless SetReceive(true) is called, received packets will be discarded.
136 virtual bool SetReceive(bool receive);
137
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200138 virtual bool SetSendParameters(const DataSendParameters& params);
139 virtual bool SetRecvParameters(const DataRecvParameters& params);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000140 virtual bool AddSendStream(const StreamParams& sp);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200141 virtual bool RemoveSendStream(uint32_t ssrc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000142 virtual bool AddRecvStream(const StreamParams& sp);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200143 virtual bool RemoveRecvStream(uint32_t ssrc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000144
145 // Called when Sctp gets data. The data may be a notification or data for
146 // OnSctpInboundData. Called from the worker thread.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000147 virtual void OnMessage(rtc::Message* msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 // Send data down this channel (will be wrapped as SCTP packets then given to
149 // sctp that will then post the network interface by OnMessage).
150 // Returns true iff successful data somewhere on the send-queue/network.
151 virtual bool SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -0700152 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153 SendDataResult* result = NULL);
154 // A packet is received from the network interface. Posted to OnMessage.
jbaucheec21bd2016-03-20 06:15:43 -0700155 virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000156 const rtc::PacketTime& packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157
158 // Exposed to allow Post call from c-callbacks.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000159 rtc::Thread* worker_thread() const { return worker_thread_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 // Many of these things are unused by SCTP, but are needed to fulfill
162 // the MediaChannel interface.
jbaucheec21bd2016-03-20 06:15:43 -0700163 virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000164 const rtc::PacketTime& packet_time) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000165 virtual void OnReadyToSend(bool ready) {}
michaelt79e05882016-11-08 02:50:09 -0800166 virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167
Lally Singhe8386d22015-08-28 14:54:37 -0400168 void OnSendThresholdCallback();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 // Helper for debugging.
Tommi7d013312016-05-19 19:58:38 +0200170 void set_debug_name_for_testing(const char* debug_name) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171 debug_name_ = debug_name;
172 }
Lally Singhe8386d22015-08-28 14:54:37 -0400173 const struct socket* socket() const { return sock_; }
Tommi7d013312016-05-19 19:58:38 +0200174
175 private:
176 FRIEND_TEST_ALL_PREFIXES(SctpDataMediaChannelTest, EngineSignalsRightChannel);
177 static int SendThresholdCallback(struct socket* sock, uint32_t sb_free);
178 static SctpDataMediaChannel* GetChannelFromSocket(struct socket* sock);
179
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000180 private:
181 sockaddr_conn GetSctpSockAddr(int port);
182
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200183 bool SetSendCodecs(const std::vector<DataCodec>& codecs);
184 bool SetRecvCodecs(const std::vector<DataCodec>& codecs);
185
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000186 // Creates the socket and connects. Sets sending_ to true.
187 bool Connect();
188 // Closes the socket. Sets sending_ to false.
189 void Disconnect();
190
191 // Returns false when openning the socket failed; when successfull sets
192 // sending_ to true
193 bool OpenSctpSocket();
194 // Sets sending_ to false and sock_ to NULL.
195 void CloseSctpSocket();
196
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000197 // Sends a SCTP_RESET_STREAM for all streams in closing_ssids_.
198 bool SendQueuedStreamResets();
199
200 // Adds a stream.
201 bool AddStream(const StreamParams &sp);
202 // Queues a stream for reset.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200203 bool ResetStream(uint32_t ssrc);
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000204
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000205 // Called by OnMessage to send packet on the network.
jbaucheec21bd2016-03-20 06:15:43 -0700206 void OnPacketFromSctpToNetwork(rtc::CopyOnWriteBuffer* buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 // Called by OnMessage to decide what to do with the packet.
208 void OnInboundPacketFromSctpToChannel(SctpInboundPacket* packet);
209 void OnDataFromSctpToChannel(const ReceiveDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -0700210 const rtc::CopyOnWriteBuffer& buffer);
211 void OnNotificationFromSctp(const rtc::CopyOnWriteBuffer& buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 void OnNotificationAssocChange(const sctp_assoc_change& change);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000213
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000214 void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
215
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216 // Responsible for marshalling incoming data to the channels listeners, and
217 // outgoing data to the network interface.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000218 rtc::Thread* worker_thread_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219 // The local and remote SCTP port to use. These are passed along the wire
220 // and the listener and connector must be using the same port. It is not
wu@webrtc.org78187522013-10-07 23:32:02 +0000221 // related to the ports at the IP level. If set to -1, we default to
222 // kSctpDefaultPort.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223 int local_port_;
224 int remote_port_;
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000225 struct socket* sock_; // The socket created by usrsctp_socket(...).
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226
227 // sending_ is true iff there is a connected socket.
228 bool sending_;
229 // receiving_ controls whether inbound packets are thrown away.
230 bool receiving_;
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000231
232 // When a data channel opens a stream, it goes into open_streams_. When we
233 // want to close it, the stream's ID goes into queued_reset_streams_. When
234 // we actually transmit a RE-CONFIG chunk with that stream ID, the ID goes
235 // into sent_reset_streams_. When we get a response RE-CONFIG chunk back
236 // acknowledging the reset, we remove the stream ID from
237 // sent_reset_streams_. We use sent_reset_streams_ to differentiate
238 // between acknowledgment RE-CONFIG and peer-initiated RE-CONFIGs.
239 StreamSet open_streams_;
240 StreamSet queued_reset_streams_;
241 StreamSet sent_reset_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000242
Tommi7d013312016-05-19 19:58:38 +0200243 // A static human-readable name for debugging messages.
244 const char* debug_name_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000245};
246
247} // namespace cricket
248
kjellandera96e2d72016-02-04 23:52:28 -0800249#endif // WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_