DataChannelDcSctp.h (8291B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef NETWERK_SCTP_DATACHANNEL_DATACHANNELDCSCTP_H_ 8 #define NETWERK_SCTP_DATACHANNEL_DATACHANNELDCSCTP_H_ 9 10 #include "DataChannel.h" 11 #include "net/dcsctp/public/dcsctp_socket.h" 12 #include "net/dcsctp/public/dcsctp_socket_factory.h" 13 14 namespace mozilla { 15 using namespace dcsctp; 16 17 class DataChannelConnectionDcSctp : public DataChannelConnection, 18 public DcSctpSocketCallbacks { 19 public: 20 DataChannelConnectionDcSctp(DataConnectionListener* aListener, 21 nsISerialEventTarget* aTarget, 22 MediaTransportHandler* aHandler); 23 24 // DataChannelConnection API 25 void Destroy() override; 26 bool RaiseStreamLimitTo(uint16_t aNewLimit) override; 27 void OnTransportReady() override; 28 bool Init(const uint16_t aLocalPort, const uint16_t aNumStreams) override; 29 int SendMessage(DataChannel& aChannel, OutgoingMsg&& aMsg) override; 30 void OnSctpPacketReceived(const MediaPacket& aPacket) override; 31 bool ResetStreams(nsTArray<uint16_t>& aStreams) override; 32 // This is called after an ACK comes in, to prompt subclasses to deliver 33 // anything they've buffered while awaiting the ACK. 34 void OnStreamOpen(uint16_t aStream) override; 35 36 // DcSctpSocketCallbacks API 37 38 // Called when the library wants the packet serialized as `data` to be sent. 39 // 40 // Note that it's NOT ALLOWED to call into this library from within this 41 // callback. 42 SendPacketStatus SendPacketWithStatus( 43 webrtc::ArrayView<const uint8_t> aData) override; 44 45 // Called when the library wants to create a Timeout. The callback must return 46 // an object that implements that interface. 47 // 48 // Low precision tasks are scheduled more efficiently by using leeway to 49 // reduce Idle Wake Ups and is the preferred precision whenever possible. High 50 // precision timeouts do not have this leeway, but is still limited by OS 51 // timer precision. At the time of writing, kLow's additional leeway may be up 52 // to 17 ms, but please see webrtc::TaskQueueBase::DelayPrecision for 53 // up-to-date information. 54 // 55 // Note that it's NOT ALLOWED to call into this library from within this 56 // callback. 57 std::unique_ptr<Timeout> CreateTimeout( 58 webrtc::TaskQueueBase::DelayPrecision aPrecision) override; 59 void HandleTimeout(TimeoutID aId); 60 61 // Called when the library needs a random number uniformly distributed between 62 // `low` (inclusive) and `high` (exclusive). The random numbers used by the 63 // library are not used for cryptographic purposes. There are no requirements 64 // that the random number generator must be secure. 65 // 66 // Note that it's NOT ALLOWED to call into this library from within this 67 // callback. 68 uint32_t GetRandomInt(uint32_t aLow, uint32_t aHigh) override; 69 70 // Called when the library has received an SCTP message in full and delivers 71 // it to the upper layer. 72 // 73 // It is allowed to call into this library from within this callback. 74 void OnMessageReceived(DcSctpMessage aMessage) override; 75 76 // Triggered when an non-fatal error is reported by either this library or 77 // from the other peer (by sending an ERROR command). These should be logged, 78 // but no other action need to be taken as the association is still viable. 79 // 80 // It is allowed to call into this library from within this callback. 81 void OnError(ErrorKind aError, absl::string_view aMessage) override; 82 83 // Triggered when the socket has aborted - either as decided by this socket 84 // due to e.g. too many retransmission attempts, or by the peer when 85 // receiving an ABORT command. No other callbacks will be done after this 86 // callback, unless reconnecting. 87 // 88 // It is allowed to call into this library from within this callback. 89 void OnAborted(ErrorKind aError, absl::string_view aMessage) override; 90 91 // Called when calling `Connect` succeeds, but also for incoming successful 92 // connection attempts. 93 // 94 // It is allowed to call into this library from within this callback. 95 void OnConnected() override; 96 97 // Called when the socket is closed in a controlled way. No other 98 // callbacks will be done after this callback, unless reconnecting. 99 // 100 // It is allowed to call into this library from within this callback. 101 void OnClosed() override; 102 103 // On connection restarted (by peer). This is just a notification, and the 104 // association is expected to work fine after this call, but there could have 105 // been packet loss as a result of restarting the association. 106 // 107 // It is allowed to call into this library from within this callback. 108 void OnConnectionRestarted() override; 109 110 // Indicates that a stream reset request has failed. 111 // 112 // It is allowed to call into this library from within this callback. 113 void OnStreamsResetFailed(webrtc::ArrayView<const StreamID> aOutgoingStreams, 114 absl::string_view aReason) override; 115 116 // Indicates that a stream reset request has been performed. 117 // 118 // It is allowed to call into this library from within this callback. 119 void OnStreamsResetPerformed( 120 webrtc::ArrayView<const StreamID> aOutgoingStreams) override; 121 122 // When a peer has reset some of its outgoing streams, this will be called. An 123 // empty list indicates that all streams have been reset. 124 // 125 // It is allowed to call into this library from within this callback. 126 void OnIncomingStreamsReset( 127 webrtc::ArrayView<const StreamID> aIncomingStreams) override; 128 129 // Will be called when the amount of data buffered to be sent falls to or 130 // below the threshold set when calling `SetBufferedAmountLowThreshold`. 131 // 132 // It is allowed to call into this library from within this callback. 133 void OnBufferedAmountLow(StreamID aStreamId) override; 134 135 void OnLifecycleMessageFullySent(LifecycleId aLifecycleId) override; 136 void OnLifecycleMessageExpired(LifecycleId aLifecycleId, 137 bool aMaybeDelivered) override; 138 139 private: 140 void UpdateBufferedAmount(StreamID aStreamId); 141 void OnDCEPMessageDone(LifecycleId aLifecycleId); 142 143 bool HasPreChannelData(uint16_t aStream) const; 144 145 std::unique_ptr<DcSctpSocketInterface> mDcSctp; 146 std::set<uint16_t> mStreamsAwaitingAck; 147 148 // dcsctp counts DCEP payloads as part of bufferedAmount and bufferedamountlow 149 // This is wrong. dcsctp does not make it easy to tell whether any DCEP has 150 // been sent when bufferedAmount decreases. We can set bufferedAmount 151 // thresholds to detect when any data is sent, but those callbacks don't tell 152 // us whether that data was DCEP or not. We can also monitor the lifecycle of 153 // packets, but we will not be able to detect when a large packet is partially 154 // sent. We need to combine these approaches to figure out how much actual 155 // data is buffered. We take advantage of a couple of things: 156 // 157 // 1. DCEP messages are small enough that partial sends will not happen, 158 // meaning that we can expect OnLifecycleMessageFullySent to accurately 159 // reflect how much DCEP has just been sent. 160 // 2. OnBufferedAmountLow and OnLifecycleMessageFullySent are called in the 161 // same task when data is sent. 162 // 163 // The basic idea is to track the total of both DCEP and data bytes using the 164 // OnBufferedAmountLow callback, and subtract the DCEP bytes if we see 165 // OnLifecycleMessageFullySent callback/s for the DCEP messages. This 166 // subtraction is done in a dispatched task; inside of that task we will not 167 // have cases where OnBufferedAmountLow has fired, but the corresponding 168 // OnLifecycleMessageFullySent (if any) have not. 169 170 std::map<uint16_t, size_t> mBufferedAmounts; 171 std::map<uint16_t, int> mDCEPBytesSent; 172 uint64_t mNextLifecycleId = 1; 173 // lifecycle-id -> (stream-id, amount) 174 std::map<uint64_t, std::pair<uint16_t, size_t>> mBufferedDCEPBytes; 175 // Holding tank for messages whose channel has not been created yet. 176 std::vector<IncomingMsg> mPreChannelData; 177 }; 178 179 } // namespace mozilla 180 181 #endif // NETWERK_SCTP_DATACHANNEL_DATACHANNELDCSCTP_H_