File: callback_deferrer.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (117 lines) | stat: -rw-r--r-- 4,572 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#ifndef NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_
#define NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_

#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/task_queue_base.h"
#include "net/dcsctp/public/dcsctp_message.h"
#include "net/dcsctp/public/dcsctp_socket.h"

namespace dcsctp {
// Defers callbacks until they can be safely triggered.
//
// There are a lot of callbacks from the dcSCTP library to the client,
// such as when messages are received or streams are closed. When the client
// receives these callbacks, the client is expected to be able to call into the
// library - from within the callback. For example, sending a reply message when
// a certain SCTP message has been received, or to reconnect when the connection
// was closed for any reason. This means that the dcSCTP library must always be
// in a consistent and stable state when these callbacks are delivered, and to
// ensure that's the case, callbacks are not immediately delivered from where
// they originate, but instead queued (deferred) by this class. At the end of
// any public API method that may result in callbacks, they are triggered and
// then delivered.
//
// There are a number of exceptions, which is clearly annotated in the API.
class CallbackDeferrer : public DcSctpSocketCallbacks {
 public:
  class ScopedDeferrer {
   public:
    explicit ScopedDeferrer(CallbackDeferrer& callback_deferrer)
        : callback_deferrer_(callback_deferrer) {
      callback_deferrer_.Prepare();
    }

    ~ScopedDeferrer() { callback_deferrer_.TriggerDeferred(); }

   private:
    CallbackDeferrer& callback_deferrer_;
  };

  explicit CallbackDeferrer(DcSctpSocketCallbacks& underlying)
      : underlying_(underlying) {}

  // Implementation of DcSctpSocketCallbacks
  SendPacketStatus SendPacketWithStatus(
      webrtc::ArrayView<const uint8_t> data) override;
  std::unique_ptr<Timeout> CreateTimeout(
      webrtc::TaskQueueBase::DelayPrecision precision) override;
  TimeMs TimeMillis() override;
  webrtc::Timestamp Now() override { return underlying_.Now(); }
  uint32_t GetRandomInt(uint32_t low, uint32_t high) override;
  void OnMessageReceived(DcSctpMessage message) override;
  void OnMessageReady() override;
  void OnError(ErrorKind error, absl::string_view message) override;
  void OnAborted(ErrorKind error, absl::string_view message) override;
  void OnConnected() override;
  void OnClosed() override;
  void OnConnectionRestarted() override;
  void OnStreamsResetFailed(webrtc::ArrayView<const StreamID> outgoing_streams,
                            absl::string_view reason) override;
  void OnStreamsResetPerformed(
      webrtc::ArrayView<const StreamID> outgoing_streams) override;
  void OnIncomingStreamsReset(
      webrtc::ArrayView<const StreamID> incoming_streams) override;
  void OnBufferedAmountLow(StreamID stream_id) override;
  void OnTotalBufferedAmountLow() override;

  void OnLifecycleMessageExpired(LifecycleId lifecycle_id,
                                 bool maybe_delivered) override;
  void OnLifecycleMessageFullySent(LifecycleId lifecycle_id) override;
  void OnLifecycleMessageDelivered(LifecycleId lifecycle_id) override;
  void OnLifecycleEnd(LifecycleId lifecycle_id) override;

 private:
  struct Error {
    ErrorKind error;
    std::string message;
  };
  struct StreamReset {
    std::vector<StreamID> streams;
    std::string message;
  };
  // Use a pre-sized variant for storage to avoid double heap allocation. This
  // variant can hold all cases of stored data.
  using CallbackData =
      std::variant<std::monostate, DcSctpMessage, Error, StreamReset, StreamID>;
  using Callback = void (*)(CallbackData, DcSctpSocketCallbacks&);

  void Prepare();
  void TriggerDeferred();

  DcSctpSocketCallbacks& underlying_;
  bool prepared_ = false;
  std::vector<std::pair<Callback, CallbackData>> deferred_;
};
}  // namespace dcsctp

#endif  // NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_