1 /* 2 * Copyright (c) 2021 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 #ifndef NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_ 11 #define NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_ 12 13 #include <cstdint> 14 #include <functional> 15 #include <memory> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "absl/strings/string_view.h" 21 #include "api/array_view.h" 22 #include "api/ref_counted_base.h" 23 #include "api/scoped_refptr.h" 24 #include "api/task_queue/task_queue_base.h" 25 #include "net/dcsctp/public/dcsctp_message.h" 26 #include "net/dcsctp/public/dcsctp_socket.h" 27 28 namespace dcsctp { 29 // Defers callbacks until they can be safely triggered. 30 // 31 // There are a lot of callbacks from the dcSCTP library to the client, 32 // such as when messages are received or streams are closed. When the client 33 // receives these callbacks, the client is expected to be able to call into the 34 // library - from within the callback. For example, sending a reply message when 35 // a certain SCTP message has been received, or to reconnect when the connection 36 // was closed for any reason. This means that the dcSCTP library must always be 37 // in a consistent and stable state when these callbacks are delivered, and to 38 // ensure that's the case, callbacks are not immediately delivered from where 39 // they originate, but instead queued (deferred) by this class. At the end of 40 // any public API method that may result in callbacks, they are triggered and 41 // then delivered. 42 // 43 // There are a number of exceptions, which is clearly annotated in the API. 44 class CallbackDeferrer : public DcSctpSocketCallbacks { 45 public: 46 class ScopedDeferrer { 47 public: ScopedDeferrer(CallbackDeferrer & callback_deferrer)48 explicit ScopedDeferrer(CallbackDeferrer& callback_deferrer) 49 : callback_deferrer_(callback_deferrer) { 50 callback_deferrer_.Prepare(); 51 } 52 ~ScopedDeferrer()53 ~ScopedDeferrer() { callback_deferrer_.TriggerDeferred(); } 54 55 private: 56 CallbackDeferrer& callback_deferrer_; 57 }; 58 CallbackDeferrer(DcSctpSocketCallbacks & underlying)59 explicit CallbackDeferrer(DcSctpSocketCallbacks& underlying) 60 : underlying_(underlying) {} 61 62 // Implementation of DcSctpSocketCallbacks 63 SendPacketStatus SendPacketWithStatus( 64 rtc::ArrayView<const uint8_t> data) override; 65 std::unique_ptr<Timeout> CreateTimeout( 66 webrtc::TaskQueueBase::DelayPrecision precision) override; 67 TimeMs TimeMillis() override; 68 uint32_t GetRandomInt(uint32_t low, uint32_t high) override; 69 void OnMessageReceived(DcSctpMessage message) override; 70 void OnError(ErrorKind error, absl::string_view message) override; 71 void OnAborted(ErrorKind error, absl::string_view message) override; 72 void OnConnected() override; 73 void OnClosed() override; 74 void OnConnectionRestarted() override; 75 void OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams, 76 absl::string_view reason) override; 77 void OnStreamsResetPerformed( 78 rtc::ArrayView<const StreamID> outgoing_streams) override; 79 void OnIncomingStreamsReset( 80 rtc::ArrayView<const StreamID> incoming_streams) override; 81 void OnBufferedAmountLow(StreamID stream_id) override; 82 void OnTotalBufferedAmountLow() override; 83 84 void OnLifecycleMessageExpired(LifecycleId lifecycle_id, 85 bool maybe_delivered) override; 86 void OnLifecycleMessageFullySent(LifecycleId lifecycle_id) override; 87 void OnLifecycleMessageDelivered(LifecycleId lifecycle_id) override; 88 void OnLifecycleEnd(LifecycleId lifecycle_id) override; 89 90 private: 91 void Prepare(); 92 void TriggerDeferred(); 93 94 DcSctpSocketCallbacks& underlying_; 95 bool prepared_ = false; 96 std::vector<std::function<void(DcSctpSocketCallbacks& cb)>> deferred_; 97 }; 98 } // namespace dcsctp 99 100 #endif // NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_ 101