1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  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.
9  */
10 
11 #ifndef MEDIA_SCTP_SCTP_TRANSPORT_H_
12 #define MEDIA_SCTP_SCTP_TRANSPORT_H_
13 
14 #include <errno.h>
15 
16 #include <cstdint>
17 #include <map>
18 #include <memory>
19 #include <set>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/types/optional.h"
24 #include "rtc_base/async_invoker.h"
25 #include "rtc_base/buffer.h"
26 #include "rtc_base/constructor_magic.h"
27 #include "rtc_base/copy_on_write_buffer.h"
28 #include "rtc_base/third_party/sigslot/sigslot.h"
29 #include "rtc_base/thread.h"
30 // For SendDataParams/ReceiveDataParams.
31 #include "media/base/media_channel.h"
32 #include "media/sctp/sctp_transport_internal.h"
33 
34 // Defined by "usrsctplib/usrsctp.h"
35 struct sockaddr_conn;
36 struct sctp_assoc_change;
37 struct sctp_rcvinfo;
38 struct sctp_stream_reset_event;
39 struct sctp_sendv_spa;
40 
41 // Defined by <sys/socket.h>
42 struct socket;
43 namespace cricket {
44 
45 // Holds data to be passed on to a transport.
46 struct SctpInboundPacket;
47 
48 // From transport calls, data flows like this:
49 // [network thread (although it can in princple be another thread)]
50 //  1.  SctpTransport::SendData(data)
51 //  2.  usrsctp_sendv(data)
52 // [network thread returns; sctp thread then calls the following]
53 //  3.  OnSctpOutboundPacket(wrapped_data)
54 // [sctp thread returns having async invoked on the network thread]
55 //  4.  SctpTransport::OnPacketFromSctpToNetwork(wrapped_data)
56 //  5.  DtlsTransport::SendPacket(wrapped_data)
57 //  6.  ... across network ... a packet is sent back ...
58 //  7.  SctpTransport::OnPacketReceived(wrapped_data)
59 //  8.  usrsctp_conninput(wrapped_data)
60 // [network thread returns; sctp thread then calls the following]
61 //  9.  OnSctpInboundData(data)
62 //  10. SctpTransport::OnDataFromSctpToTransport(data)
63 // [sctp thread returns having async invoked on the network thread]
64 //  11. SctpTransport::OnDataFromSctpToTransport(data)
65 //  12. SctpTransport::SignalDataReceived(data)
66 // [from the same thread, methods registered/connected to
67 //  SctpTransport are called with the recieved data]
68 class SctpTransport : public SctpTransportInternal,
69                       public sigslot::has_slots<> {
70  public:
71   // |network_thread| is where packets will be processed and callbacks from
72   // this transport will be posted, and is the only thread on which public
73   // methods can be called.
74   // |transport| is not required (can be null).
75   SctpTransport(rtc::Thread* network_thread,
76                 rtc::PacketTransportInternal* transport);
77   ~SctpTransport() override;
78 
79   // SctpTransportInternal overrides (see sctptransportinternal.h for comments).
80   void SetDtlsTransport(rtc::PacketTransportInternal* transport) override;
81   bool Start(int local_port, int remote_port, int max_message_size) override;
82   bool OpenStream(int sid) override;
83   bool ResetStream(int sid) override;
84   bool SendData(const SendDataParams& params,
85                 const rtc::CopyOnWriteBuffer& payload,
86                 SendDataResult* result = nullptr) override;
87   bool ReadyToSendData() override;
max_message_size()88   int max_message_size() const override { return max_message_size_; }
max_outbound_streams()89   absl::optional<int> max_outbound_streams() const override {
90     return max_outbound_streams_;
91   }
max_inbound_streams()92   absl::optional<int> max_inbound_streams() const override {
93     return max_inbound_streams_;
94   }
set_debug_name_for_testing(const char * debug_name)95   void set_debug_name_for_testing(const char* debug_name) override {
96     debug_name_ = debug_name;
97   }
98   int InjectDataOrNotificationFromSctpForTesting(void* data,
99                                                  size_t length,
100                                                  struct sctp_rcvinfo rcv,
101                                                  int flags);
102 
103   // Exposed to allow Post call from c-callbacks.
104   // TODO(deadbeef): Remove this or at least make it return a const pointer.
network_thread()105   rtc::Thread* network_thread() const { return network_thread_; }
106 
107  private:
108   // A message to be sent by the sctp library. This class is used to track the
109   // progress of writing a single message to the sctp library in the presence of
110   // partial writes. In this case, the Advance() function is provided in order
111   // to advance over what has already been accepted by the sctp library and
112   // avoid copying the remaining partial message buffer.
113   class OutgoingMessage {
114    public:
OutgoingMessage(const rtc::CopyOnWriteBuffer & buffer,const SendDataParams & send_params)115     OutgoingMessage(const rtc::CopyOnWriteBuffer& buffer,
116                     const SendDataParams& send_params)
117         : buffer_(buffer), send_params_(send_params) {}
118 
119     // Advances the buffer by the incremented amount. Must not advance further
120     // than the current data size.
Advance(size_t increment)121     void Advance(size_t increment) {
122       RTC_DCHECK_LE(increment + offset_, buffer_.size());
123       offset_ += increment;
124     }
125 
size()126     size_t size() const { return buffer_.size() - offset_; }
127 
data()128     const void* data() const { return buffer_.data() + offset_; }
129 
send_params()130     SendDataParams send_params() const { return send_params_; }
131 
132    private:
133     const rtc::CopyOnWriteBuffer buffer_;
134     const SendDataParams send_params_;
135     size_t offset_ = 0;
136   };
137 
138   void ConnectTransportSignals();
139   void DisconnectTransportSignals();
140 
141   // Creates the socket and connects.
142   bool Connect();
143 
144   // Returns false when opening the socket failed.
145   bool OpenSctpSocket();
146   // Helpet method to set socket options.
147   bool ConfigureSctpSocket();
148   // Sets |sock_ |to nullptr.
149   void CloseSctpSocket();
150 
151   // Sends a SCTP_RESET_STREAM for all streams in closing_ssids_.
152   bool SendQueuedStreamResets();
153 
154   // Sets the "ready to send" flag and fires signal if needed.
155   void SetReadyToSendData();
156 
157   // Sends the outgoing buffered message that was only partially accepted by the
158   // sctp lib because it did not have enough space. Returns true if the entire
159   // buffered message was accepted by the sctp lib.
160   bool SendBufferedMessage();
161 
162   // Tries to send the |payload| on the usrsctp lib. The message will be
163   // advanced by the amount that was sent.
164   SendDataResult SendMessageInternal(OutgoingMessage* message);
165 
166   // Callbacks from DTLS transport.
167   void OnWritableState(rtc::PacketTransportInternal* transport);
168   virtual void OnPacketRead(rtc::PacketTransportInternal* transport,
169                             const char* data,
170                             size_t len,
171                             const int64_t& packet_time_us,
172                             int flags);
173   void OnClosed(rtc::PacketTransportInternal* transport);
174 
175   // Methods related to usrsctp callbacks.
176   void OnSendThresholdCallback();
177   sockaddr_conn GetSctpSockAddr(int port);
178 
179   // Called using |invoker_| to send packet on the network.
180   void OnPacketFromSctpToNetwork(const rtc::CopyOnWriteBuffer& buffer);
181 
182   // Called on the SCTP thread.
183   // Flags are standard socket API flags (RFC 6458).
184   int OnDataOrNotificationFromSctp(void* data,
185                                    size_t length,
186                                    struct sctp_rcvinfo rcv,
187                                    int flags);
188   // Called using |invoker_| to decide what to do with the data.
189   void OnDataFromSctpToTransport(const ReceiveDataParams& params,
190                                  const rtc::CopyOnWriteBuffer& buffer);
191   // Called using |invoker_| to decide what to do with the notification.
192   void OnNotificationFromSctp(const rtc::CopyOnWriteBuffer& buffer);
193   void OnNotificationAssocChange(const sctp_assoc_change& change);
194 
195   void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
196 
197   // Responsible for marshalling incoming data to the transports listeners, and
198   // outgoing data to the network interface.
199   rtc::Thread* network_thread_;
200   // Helps pass inbound/outbound packets asynchronously to the network thread.
201   rtc::AsyncInvoker invoker_;
202   // Underlying DTLS transport.
203   rtc::PacketTransportInternal* transport_ = nullptr;
204 
205   // Track the data received from usrsctp between callbacks until the EOR bit
206   // arrives.
207   rtc::CopyOnWriteBuffer partial_incoming_message_;
208   ReceiveDataParams partial_params_;
209   int partial_flags_;
210   // A message that was attempted to be sent, but was only partially accepted by
211   // usrsctp lib with usrsctp_sendv() because it cannot buffer the full message.
212   // This occurs because we explicitly set the EOR bit when sending, so
213   // usrsctp_sendv() is not atomic.
214   absl::optional<OutgoingMessage> partial_outgoing_message_;
215 
216   bool was_ever_writable_ = false;
217   int local_port_ = kSctpDefaultPort;
218   int remote_port_ = kSctpDefaultPort;
219   int max_message_size_ = kSctpSendBufferSize;
220   struct socket* sock_ = nullptr;  // The socket created by usrsctp_socket(...).
221 
222   // Has Start been called? Don't create SCTP socket until it has.
223   bool started_ = false;
224   // Are we ready to queue data (SCTP socket created, and not blocked due to
225   // congestion control)? Different than |transport_|'s "ready to send".
226   bool ready_to_send_data_ = false;
227 
228   // Used to keep track of the status of each stream (or rather, each pair of
229   // incoming/outgoing streams with matching IDs). It's specifically used to
230   // keep track of the status of resets, but more information could be put here
231   // later.
232   //
233   // See datachannel.h for a summary of the closing procedure.
234   struct StreamStatus {
235     // Closure initiated by application via ResetStream? Note that
236     // this may be true while outgoing_reset_initiated is false if the outgoing
237     // reset needed to be queued.
238     bool closure_initiated = false;
239     // Whether we've initiated the outgoing stream reset via
240     // SCTP_RESET_STREAMS.
241     bool outgoing_reset_initiated = false;
242     // Whether usrsctp has indicated that the incoming/outgoing streams have
243     // been reset. It's expected that the peer will reset its outgoing stream
244     // (our incoming stream) after receiving the reset for our outgoing stream,
245     // though older versions of chromium won't do this. See crbug.com/559394
246     // for context.
247     bool outgoing_reset_complete = false;
248     bool incoming_reset_complete = false;
249 
250     // Some helper methods to improve code readability.
is_openStreamStatus251     bool is_open() const {
252       return !closure_initiated && !incoming_reset_complete &&
253              !outgoing_reset_complete;
254     }
255     // We need to send an outgoing reset if the application has closed the data
256     // channel, or if we received a reset of the incoming stream from the
257     // remote endpoint, indicating the data channel was closed remotely.
need_outgoing_resetStreamStatus258     bool need_outgoing_reset() const {
259       return (incoming_reset_complete || closure_initiated) &&
260              !outgoing_reset_initiated;
261     }
reset_completeStreamStatus262     bool reset_complete() const {
263       return outgoing_reset_complete && incoming_reset_complete;
264     }
265   };
266 
267   // Entries should only be removed from this map if |reset_complete| is
268   // true.
269   std::map<uint32_t, StreamStatus> stream_status_by_sid_;
270 
271   // A static human-readable name for debugging messages.
272   const char* debug_name_ = "SctpTransport";
273   // Hides usrsctp interactions from this header file.
274   class UsrSctpWrapper;
275   // Number of channels negotiated. Not set before negotiation completes.
276   absl::optional<int> max_outbound_streams_;
277   absl::optional<int> max_inbound_streams_;
278 
279   // Used for associating this transport with the underlying sctp socket in
280   // various callbacks.
281   uintptr_t id_ = 0;
282 
283   RTC_DISALLOW_COPY_AND_ASSIGN(SctpTransport);
284 };
285 
286 class SctpTransportFactory : public SctpTransportInternalFactory {
287  public:
SctpTransportFactory(rtc::Thread * network_thread)288   explicit SctpTransportFactory(rtc::Thread* network_thread)
289       : network_thread_(network_thread) {}
290 
CreateSctpTransport(rtc::PacketTransportInternal * transport)291   std::unique_ptr<SctpTransportInternal> CreateSctpTransport(
292       rtc::PacketTransportInternal* transport) override {
293     return std::unique_ptr<SctpTransportInternal>(
294         new SctpTransport(network_thread_, transport));
295   }
296 
297  private:
298   rtc::Thread* network_thread_;
299 };
300 
301 }  // namespace cricket
302 
303 #endif  // MEDIA_SCTP_SCTP_TRANSPORT_H_
304