xref: /aosp_15_r20/external/webrtc/net/dcsctp/socket/callback_deferrer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/socket/callback_deferrer.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include "api/make_ref_counted.h"
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker namespace dcsctp {
15*d9f75844SAndroid Build Coastguard Worker namespace {
16*d9f75844SAndroid Build Coastguard Worker // A wrapper around the move-only DcSctpMessage, to let it be captured in a
17*d9f75844SAndroid Build Coastguard Worker // lambda.
18*d9f75844SAndroid Build Coastguard Worker class MessageDeliverer {
19*d9f75844SAndroid Build Coastguard Worker  public:
MessageDeliverer(DcSctpMessage && message)20*d9f75844SAndroid Build Coastguard Worker   explicit MessageDeliverer(DcSctpMessage&& message)
21*d9f75844SAndroid Build Coastguard Worker       : state_(rtc::make_ref_counted<State>(std::move(message))) {}
22*d9f75844SAndroid Build Coastguard Worker 
Deliver(DcSctpSocketCallbacks & c)23*d9f75844SAndroid Build Coastguard Worker   void Deliver(DcSctpSocketCallbacks& c) {
24*d9f75844SAndroid Build Coastguard Worker     // Really ensure that it's only called once.
25*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!state_->has_delivered);
26*d9f75844SAndroid Build Coastguard Worker     state_->has_delivered = true;
27*d9f75844SAndroid Build Coastguard Worker     c.OnMessageReceived(std::move(state_->message));
28*d9f75844SAndroid Build Coastguard Worker   }
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker  private:
31*d9f75844SAndroid Build Coastguard Worker   struct State : public rtc::RefCountInterface {
Statedcsctp::__anon33e266ca0111::MessageDeliverer::State32*d9f75844SAndroid Build Coastguard Worker     explicit State(DcSctpMessage&& m)
33*d9f75844SAndroid Build Coastguard Worker         : has_delivered(false), message(std::move(m)) {}
34*d9f75844SAndroid Build Coastguard Worker     bool has_delivered;
35*d9f75844SAndroid Build Coastguard Worker     DcSctpMessage message;
36*d9f75844SAndroid Build Coastguard Worker   };
37*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<State> state_;
38*d9f75844SAndroid Build Coastguard Worker };
39*d9f75844SAndroid Build Coastguard Worker }  // namespace
40*d9f75844SAndroid Build Coastguard Worker 
Prepare()41*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::Prepare() {
42*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!prepared_);
43*d9f75844SAndroid Build Coastguard Worker   prepared_ = true;
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker 
TriggerDeferred()46*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::TriggerDeferred() {
47*d9f75844SAndroid Build Coastguard Worker   // Need to swap here. The client may call into the library from within a
48*d9f75844SAndroid Build Coastguard Worker   // callback, and that might result in adding new callbacks to this instance,
49*d9f75844SAndroid Build Coastguard Worker   // and the vector can't be modified while iterated on.
50*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
51*d9f75844SAndroid Build Coastguard Worker   std::vector<std::function<void(DcSctpSocketCallbacks & cb)>> deferred;
52*d9f75844SAndroid Build Coastguard Worker   deferred.swap(deferred_);
53*d9f75844SAndroid Build Coastguard Worker   prepared_ = false;
54*d9f75844SAndroid Build Coastguard Worker 
55*d9f75844SAndroid Build Coastguard Worker   for (auto& cb : deferred) {
56*d9f75844SAndroid Build Coastguard Worker     cb(underlying_);
57*d9f75844SAndroid Build Coastguard Worker   }
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker 
SendPacketWithStatus(rtc::ArrayView<const uint8_t> data)60*d9f75844SAndroid Build Coastguard Worker SendPacketStatus CallbackDeferrer::SendPacketWithStatus(
61*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const uint8_t> data) {
62*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
63*d9f75844SAndroid Build Coastguard Worker   return underlying_.SendPacketWithStatus(data);
64*d9f75844SAndroid Build Coastguard Worker }
65*d9f75844SAndroid Build Coastguard Worker 
CreateTimeout(webrtc::TaskQueueBase::DelayPrecision precision)66*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timeout> CallbackDeferrer::CreateTimeout(
67*d9f75844SAndroid Build Coastguard Worker     webrtc::TaskQueueBase::DelayPrecision precision) {
68*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
69*d9f75844SAndroid Build Coastguard Worker   return underlying_.CreateTimeout(precision);
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker 
TimeMillis()72*d9f75844SAndroid Build Coastguard Worker TimeMs CallbackDeferrer::TimeMillis() {
73*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
74*d9f75844SAndroid Build Coastguard Worker   return underlying_.TimeMillis();
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker 
GetRandomInt(uint32_t low,uint32_t high)77*d9f75844SAndroid Build Coastguard Worker uint32_t CallbackDeferrer::GetRandomInt(uint32_t low, uint32_t high) {
78*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
79*d9f75844SAndroid Build Coastguard Worker   return underlying_.GetRandomInt(low, high);
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker 
OnMessageReceived(DcSctpMessage message)82*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnMessageReceived(DcSctpMessage message) {
83*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
84*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
85*d9f75844SAndroid Build Coastguard Worker       [deliverer = MessageDeliverer(std::move(message))](
86*d9f75844SAndroid Build Coastguard Worker           DcSctpSocketCallbacks& cb) mutable { deliverer.Deliver(cb); });
87*d9f75844SAndroid Build Coastguard Worker }
88*d9f75844SAndroid Build Coastguard Worker 
OnError(ErrorKind error,absl::string_view message)89*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnError(ErrorKind error, absl::string_view message) {
90*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
91*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
92*d9f75844SAndroid Build Coastguard Worker       [error, message = std::string(message)](DcSctpSocketCallbacks& cb) {
93*d9f75844SAndroid Build Coastguard Worker         cb.OnError(error, message);
94*d9f75844SAndroid Build Coastguard Worker       });
95*d9f75844SAndroid Build Coastguard Worker }
96*d9f75844SAndroid Build Coastguard Worker 
OnAborted(ErrorKind error,absl::string_view message)97*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnAborted(ErrorKind error, absl::string_view message) {
98*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
99*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
100*d9f75844SAndroid Build Coastguard Worker       [error, message = std::string(message)](DcSctpSocketCallbacks& cb) {
101*d9f75844SAndroid Build Coastguard Worker         cb.OnAborted(error, message);
102*d9f75844SAndroid Build Coastguard Worker       });
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker 
OnConnected()105*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnConnected() {
106*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
107*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back([](DcSctpSocketCallbacks& cb) { cb.OnConnected(); });
108*d9f75844SAndroid Build Coastguard Worker }
109*d9f75844SAndroid Build Coastguard Worker 
OnClosed()110*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnClosed() {
111*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
112*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back([](DcSctpSocketCallbacks& cb) { cb.OnClosed(); });
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker 
OnConnectionRestarted()115*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnConnectionRestarted() {
116*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
117*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
118*d9f75844SAndroid Build Coastguard Worker       [](DcSctpSocketCallbacks& cb) { cb.OnConnectionRestarted(); });
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker 
OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams,absl::string_view reason)121*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnStreamsResetFailed(
122*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const StreamID> outgoing_streams,
123*d9f75844SAndroid Build Coastguard Worker     absl::string_view reason) {
124*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
125*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
126*d9f75844SAndroid Build Coastguard Worker       [streams = std::vector<StreamID>(outgoing_streams.begin(),
127*d9f75844SAndroid Build Coastguard Worker                                        outgoing_streams.end()),
128*d9f75844SAndroid Build Coastguard Worker        reason = std::string(reason)](DcSctpSocketCallbacks& cb) {
129*d9f75844SAndroid Build Coastguard Worker         cb.OnStreamsResetFailed(streams, reason);
130*d9f75844SAndroid Build Coastguard Worker       });
131*d9f75844SAndroid Build Coastguard Worker }
132*d9f75844SAndroid Build Coastguard Worker 
OnStreamsResetPerformed(rtc::ArrayView<const StreamID> outgoing_streams)133*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnStreamsResetPerformed(
134*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const StreamID> outgoing_streams) {
135*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
136*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
137*d9f75844SAndroid Build Coastguard Worker       [streams = std::vector<StreamID>(outgoing_streams.begin(),
138*d9f75844SAndroid Build Coastguard Worker                                        outgoing_streams.end())](
139*d9f75844SAndroid Build Coastguard Worker           DcSctpSocketCallbacks& cb) { cb.OnStreamsResetPerformed(streams); });
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker 
OnIncomingStreamsReset(rtc::ArrayView<const StreamID> incoming_streams)142*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnIncomingStreamsReset(
143*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const StreamID> incoming_streams) {
144*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
145*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
146*d9f75844SAndroid Build Coastguard Worker       [streams = std::vector<StreamID>(incoming_streams.begin(),
147*d9f75844SAndroid Build Coastguard Worker                                        incoming_streams.end())](
148*d9f75844SAndroid Build Coastguard Worker           DcSctpSocketCallbacks& cb) { cb.OnIncomingStreamsReset(streams); });
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker 
OnBufferedAmountLow(StreamID stream_id)151*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnBufferedAmountLow(StreamID stream_id) {
152*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
153*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back([stream_id](DcSctpSocketCallbacks& cb) {
154*d9f75844SAndroid Build Coastguard Worker     cb.OnBufferedAmountLow(stream_id);
155*d9f75844SAndroid Build Coastguard Worker   });
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker 
OnTotalBufferedAmountLow()158*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnTotalBufferedAmountLow() {
159*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(prepared_);
160*d9f75844SAndroid Build Coastguard Worker   deferred_.emplace_back(
161*d9f75844SAndroid Build Coastguard Worker       [](DcSctpSocketCallbacks& cb) { cb.OnTotalBufferedAmountLow(); });
162*d9f75844SAndroid Build Coastguard Worker }
163*d9f75844SAndroid Build Coastguard Worker 
OnLifecycleMessageExpired(LifecycleId lifecycle_id,bool maybe_delivered)164*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnLifecycleMessageExpired(LifecycleId lifecycle_id,
165*d9f75844SAndroid Build Coastguard Worker                                                  bool maybe_delivered) {
166*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
167*d9f75844SAndroid Build Coastguard Worker   underlying_.OnLifecycleMessageExpired(lifecycle_id, maybe_delivered);
168*d9f75844SAndroid Build Coastguard Worker }
OnLifecycleMessageFullySent(LifecycleId lifecycle_id)169*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnLifecycleMessageFullySent(LifecycleId lifecycle_id) {
170*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
171*d9f75844SAndroid Build Coastguard Worker   underlying_.OnLifecycleMessageFullySent(lifecycle_id);
172*d9f75844SAndroid Build Coastguard Worker }
OnLifecycleMessageDelivered(LifecycleId lifecycle_id)173*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnLifecycleMessageDelivered(LifecycleId lifecycle_id) {
174*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
175*d9f75844SAndroid Build Coastguard Worker   underlying_.OnLifecycleMessageDelivered(lifecycle_id);
176*d9f75844SAndroid Build Coastguard Worker }
OnLifecycleEnd(LifecycleId lifecycle_id)177*d9f75844SAndroid Build Coastguard Worker void CallbackDeferrer::OnLifecycleEnd(LifecycleId lifecycle_id) {
178*d9f75844SAndroid Build Coastguard Worker   // Will not be deferred - call directly.
179*d9f75844SAndroid Build Coastguard Worker   underlying_.OnLifecycleEnd(lifecycle_id);
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker }  // namespace dcsctp
182