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