1 /* 2 * Copyright 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 // This file contains interfaces for DataChannels 12 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcdatachannel 13 14 #ifndef API_DATA_CHANNEL_INTERFACE_H_ 15 #define API_DATA_CHANNEL_INTERFACE_H_ 16 17 #include <stddef.h> 18 #include <stdint.h> 19 20 #include <string> 21 22 #include "absl/types/optional.h" 23 #include "api/priority.h" 24 #include "api/rtc_error.h" 25 #include "rtc_base/checks.h" 26 #include "rtc_base/copy_on_write_buffer.h" 27 #include "rtc_base/ref_count.h" 28 #include "rtc_base/system/rtc_export.h" 29 30 namespace webrtc { 31 32 // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelinit 33 // TODO(deadbeef): Use absl::optional for the "-1 if unset" things. 34 struct DataChannelInit { 35 // Deprecated. Reliability is assumed, and channel will be unreliable if 36 // maxRetransmitTime or MaxRetransmits is set. 37 bool reliable = false; 38 39 // True if ordered delivery is required. 40 bool ordered = true; 41 42 // The max period of time in milliseconds in which retransmissions will be 43 // sent. After this time, no more retransmissions will be sent. 44 // 45 // Cannot be set along with |maxRetransmits|. 46 // This is called |maxPacketLifeTime| in the WebRTC JS API. 47 absl::optional<int> maxRetransmitTime; 48 49 // The max number of retransmissions. 50 // 51 // Cannot be set along with |maxRetransmitTime|. 52 absl::optional<int> maxRetransmits; 53 54 // This is set by the application and opaque to the WebRTC implementation. 55 std::string protocol; 56 57 // True if the channel has been externally negotiated and we do not send an 58 // in-band signalling in the form of an "open" message. If this is true, |id| 59 // below must be set; otherwise it should be unset and will be negotiated 60 // in-band. 61 bool negotiated = false; 62 63 // The stream id, or SID, for SCTP data channels. -1 if unset (see above). 64 int id = -1; 65 66 // https://w3c.github.io/webrtc-priority/#new-rtcdatachannelinit-member 67 absl::optional<Priority> priority; 68 }; 69 70 // At the JavaScript level, data can be passed in as a string or a blob, so 71 // this structure's |binary| flag tells whether the data should be interpreted 72 // as binary or text. 73 struct DataBuffer { DataBufferDataBuffer74 DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary) 75 : data(data), binary(binary) {} 76 // For convenience for unit tests. DataBufferDataBuffer77 explicit DataBuffer(const std::string& text) 78 : data(text.data(), text.length()), binary(false) {} sizeDataBuffer79 size_t size() const { return data.size(); } 80 81 rtc::CopyOnWriteBuffer data; 82 // Indicates if the received data contains UTF-8 or binary data. 83 // Note that the upper layers are left to verify the UTF-8 encoding. 84 // TODO(jiayl): prefer to use an enum instead of a bool. 85 bool binary; 86 }; 87 88 // Used to implement RTCDataChannel events. 89 // 90 // The code responding to these callbacks should unwind the stack before 91 // using any other webrtc APIs; re-entrancy is not supported. 92 class DataChannelObserver { 93 public: 94 // The data channel state have changed. 95 virtual void OnStateChange() = 0; 96 // A data buffer was successfully received. 97 virtual void OnMessage(const DataBuffer& buffer) = 0; 98 // The data channel's buffered_amount has changed. OnBufferedAmountChange(uint64_t sent_data_size)99 virtual void OnBufferedAmountChange(uint64_t sent_data_size) {} 100 101 protected: 102 virtual ~DataChannelObserver() = default; 103 }; 104 105 class RTC_EXPORT DataChannelInterface : public rtc::RefCountInterface { 106 public: 107 // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelstate 108 // Unlikely to change, but keep in sync with DataChannel.java:State and 109 // RTCDataChannel.h:RTCDataChannelState. 110 enum DataState { 111 kConnecting, 112 kOpen, // The DataChannel is ready to send data. 113 kClosing, 114 kClosed 115 }; 116 DataStateString(DataState state)117 static const char* DataStateString(DataState state) { 118 switch (state) { 119 case kConnecting: 120 return "connecting"; 121 case kOpen: 122 return "open"; 123 case kClosing: 124 return "closing"; 125 case kClosed: 126 return "closed"; 127 } 128 RTC_CHECK(false) << "Unknown DataChannel state: " << state; 129 return ""; 130 } 131 132 // Used to receive events from the data channel. Only one observer can be 133 // registered at a time. UnregisterObserver should be called before the 134 // observer object is destroyed. 135 virtual void RegisterObserver(DataChannelObserver* observer) = 0; 136 virtual void UnregisterObserver() = 0; 137 138 // The label attribute represents a label that can be used to distinguish this 139 // DataChannel object from other DataChannel objects. 140 virtual std::string label() const = 0; 141 142 // The accessors below simply return the properties from the DataChannelInit 143 // the data channel was constructed with. 144 virtual bool reliable() const = 0; 145 // TODO(deadbeef): Remove these dummy implementations when all classes have 146 // implemented these APIs. They should all just return the values the 147 // DataChannel was created with. 148 virtual bool ordered() const; 149 // TODO(hta): Deprecate and remove the following two functions. 150 virtual uint16_t maxRetransmitTime() const; 151 virtual uint16_t maxRetransmits() const; 152 virtual absl::optional<int> maxRetransmitsOpt() const; 153 virtual absl::optional<int> maxPacketLifeTime() const; 154 virtual std::string protocol() const; 155 virtual bool negotiated() const; 156 157 // Returns the ID from the DataChannelInit, if it was negotiated out-of-band. 158 // If negotiated in-band, this ID will be populated once the DTLS role is 159 // determined, and until then this will return -1. 160 virtual int id() const = 0; priority()161 virtual Priority priority() const { return Priority::kLow; } 162 virtual DataState state() const = 0; 163 // When state is kClosed, and the DataChannel was not closed using 164 // the closing procedure, returns the error information about the closing. 165 // The default implementation returns "no error". error()166 virtual RTCError error() const { return RTCError(); } 167 virtual uint32_t messages_sent() const = 0; 168 virtual uint64_t bytes_sent() const = 0; 169 virtual uint32_t messages_received() const = 0; 170 virtual uint64_t bytes_received() const = 0; 171 172 // Returns the number of bytes of application data (UTF-8 text and binary 173 // data) that have been queued using Send but have not yet been processed at 174 // the SCTP level. See comment above Send below. 175 virtual uint64_t buffered_amount() const = 0; 176 177 // Begins the graceful data channel closing procedure. See: 178 // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7 179 virtual void Close() = 0; 180 181 // Sends |data| to the remote peer. If the data can't be sent at the SCTP 182 // level (due to congestion control), it's buffered at the data channel level, 183 // up to a maximum of 16MB. If Send is called while this buffer is full, the 184 // data channel will be closed abruptly. 185 // 186 // So, it's important to use buffered_amount() and OnBufferedAmountChange to 187 // ensure the data channel is used efficiently but without filling this 188 // buffer. 189 virtual bool Send(const DataBuffer& buffer) = 0; 190 191 protected: 192 ~DataChannelInterface() override = default; 193 }; 194 195 } // namespace webrtc 196 197 #endif // API_DATA_CHANNEL_INTERFACE_H_ 198