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