• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016 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_INTERNAL_H_
12 #define MEDIA_SCTP_SCTP_TRANSPORT_INTERNAL_H_
13 
14 // TODO(deadbeef): Move SCTP code out of media/, and make it not depend on
15 // anything in media/.
16 
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include "rtc_base/copy_on_write_buffer.h"
22 #include "rtc_base/thread.h"
23 // For SendDataParams/ReceiveDataParams.
24 // TODO(deadbeef): Use something else for SCTP. It's confusing that we use an
25 // SSRC field for SID.
26 #include "media/base/media_channel.h"
27 #include "p2p/base/packet_transport_internal.h"
28 
29 namespace cricket {
30 
31 // Constants that are important to API users
32 // The size of the SCTP association send buffer. 256kB, the usrsctp default.
33 constexpr int kSctpSendBufferSize = 256 * 1024;
34 
35 // The number of outgoing streams that we'll negotiate. Since stream IDs (SIDs)
36 // are 0-based, the highest usable SID is 1023.
37 //
38 // It's recommended to use the maximum of 65535 in:
39 // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.2
40 // However, we use 1024 in order to save memory. usrsctp allocates 104 bytes
41 // for each pair of incoming/outgoing streams (on a 64-bit system), so 65535
42 // streams would waste ~6MB.
43 //
44 // Note: "max" and "min" here are inclusive.
45 constexpr uint16_t kMaxSctpStreams = 1024;
46 constexpr uint16_t kMaxSctpSid = kMaxSctpStreams - 1;
47 constexpr uint16_t kMinSctpSid = 0;
48 
49 // This is the default SCTP port to use. It is passed along the wire and the
50 // connectee and connector must be using the same port. It is not related to the
51 // ports at the IP level. (Corresponds to: sockaddr_conn.sconn_port in
52 // usrsctp.h)
53 const int kSctpDefaultPort = 5000;
54 
55 // Abstract SctpTransport interface for use internally (by PeerConnection etc.).
56 // Exists to allow mock/fake SctpTransports to be created.
57 class SctpTransportInternal {
58  public:
~SctpTransportInternal()59   virtual ~SctpTransportInternal() {}
60 
61   // Changes what underlying DTLS transport is uses. Used when switching which
62   // bundled transport the SctpTransport uses.
63   virtual void SetDtlsTransport(rtc::PacketTransportInternal* transport) = 0;
64 
65   // When Start is called, connects as soon as possible; this can be called
66   // before DTLS completes, in which case the connection will begin when DTLS
67   // completes. This method can be called multiple times, though not if either
68   // of the ports are changed.
69   //
70   // |local_sctp_port| and |remote_sctp_port| are passed along the wire and the
71   // listener and connector must be using the same port. They are not related
72   // to the ports at the IP level. If set to -1, we default to
73   // kSctpDefaultPort.
74   // |max_message_size_| sets the max message size on the connection.
75   // It must be smaller than or equal to kSctpSendBufferSize.
76   // It can be changed by a secons Start() call.
77   //
78   // TODO(deadbeef): Support calling Start with different local/remote ports
79   // and create a new association? Not clear if this is something we need to
80   // support though. See: https://github.com/w3c/webrtc-pc/issues/979
81   virtual bool Start(int local_sctp_port,
82                      int remote_sctp_port,
83                      int max_message_size) = 0;
84 
85   // NOTE: Initially there was a "Stop" method here, but it was never used, so
86   // it was removed.
87 
88   // Informs SctpTransport that |sid| will start being used. Returns false if
89   // it is impossible to use |sid|, or if it's already in use.
90   // Until calling this, can't send data using |sid|.
91   // TODO(deadbeef): Actually implement the "returns false if |sid| can't be
92   // used" part. See:
93   // https://bugs.chromium.org/p/chromium/issues/detail?id=619849
94   virtual bool OpenStream(int sid) = 0;
95   // The inverse of OpenStream. Begins the closing procedure, which will
96   // eventually result in SignalClosingProcedureComplete on the side that
97   // initiates it, and both SignalClosingProcedureStartedRemotely and
98   // SignalClosingProcedureComplete on the other side.
99   virtual bool ResetStream(int sid) = 0;
100   // Send data down this channel (will be wrapped as SCTP packets then given to
101   // usrsctp that will then post the network interface).
102   // Returns true iff successful data somewhere on the send-queue/network.
103   // Uses |params.ssrc| as the SCTP sid.
104   virtual bool SendData(const SendDataParams& params,
105                         const rtc::CopyOnWriteBuffer& payload,
106                         SendDataResult* result = nullptr) = 0;
107 
108   // Indicates when the SCTP socket is created and not blocked by congestion
109   // control. This changes to false when SDR_BLOCK is returned from SendData,
110   // and
111   // changes to true when SignalReadyToSendData is fired. The underlying DTLS/
112   // ICE channels may be unwritable while ReadyToSendData is true, because data
113   // can still be queued in usrsctp.
114   virtual bool ReadyToSendData() = 0;
115   // Returns the current max message size, set with Start().
116   virtual int max_message_size() const = 0;
117   // Returns the current negotiated max # of outbound streams.
118   // Will return absl::nullopt if negotiation is incomplete.
119   virtual absl::optional<int> max_outbound_streams() const = 0;
120   // Returns the current negotiated max # of inbound streams.
121   virtual absl::optional<int> max_inbound_streams() const = 0;
122 
123   sigslot::signal0<> SignalReadyToSendData;
124   sigslot::signal0<> SignalAssociationChangeCommunicationUp;
125   // ReceiveDataParams includes SID, seq num, timestamp, etc. CopyOnWriteBuffer
126   // contains message payload.
127   sigslot::signal2<const ReceiveDataParams&, const rtc::CopyOnWriteBuffer&>
128       SignalDataReceived;
129   // Parameter is SID; fired when we receive an incoming stream reset on an
130   // open stream, indicating that the other side started the closing procedure.
131   // After resetting the outgoing stream, SignalClosingProcedureComplete will
132   // fire too.
133   sigslot::signal1<int> SignalClosingProcedureStartedRemotely;
134   // Parameter is SID; fired when closing procedure is complete (both incoming
135   // and outgoing streams reset).
136   sigslot::signal1<int> SignalClosingProcedureComplete;
137   // Fired when the underlying DTLS transport has closed due to an error
138   // or an incoming DTLS disconnect.
139   sigslot::signal0<> SignalClosedAbruptly;
140 
141   // Helper for debugging.
142   virtual void set_debug_name_for_testing(const char* debug_name) = 0;
143 };
144 
145 // Factory class which can be used to allow fake SctpTransports to be injected
146 // for testing. Or, theoretically, SctpTransportInternal implementations that
147 // use something other than usrsctp.
148 class SctpTransportInternalFactory {
149  public:
~SctpTransportInternalFactory()150   virtual ~SctpTransportInternalFactory() {}
151 
152   // Create an SCTP transport using |channel| for the underlying transport.
153   virtual std::unique_ptr<SctpTransportInternal> CreateSctpTransport(
154       rtc::PacketTransportInternal* channel) = 0;
155 };
156 
157 }  // namespace cricket
158 
159 #endif  // MEDIA_SCTP_SCTP_TRANSPORT_INTERNAL_H_
160