xref: /aosp_15_r20/external/webrtc/net/dcsctp/public/dcsctp_socket.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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_PUBLIC_DCSCTP_SOCKET_H_
11 #define NET_DCSCTP_PUBLIC_DCSCTP_SOCKET_H_
12 
13 #include <cstdint>
14 #include <memory>
15 #include <utility>
16 
17 #include "absl/strings/string_view.h"
18 #include "absl/types/optional.h"
19 #include "api/array_view.h"
20 #include "api/task_queue/task_queue_base.h"
21 #include "net/dcsctp/public/dcsctp_handover_state.h"
22 #include "net/dcsctp/public/dcsctp_message.h"
23 #include "net/dcsctp/public/dcsctp_options.h"
24 #include "net/dcsctp/public/packet_observer.h"
25 #include "net/dcsctp/public/timeout.h"
26 #include "net/dcsctp/public/types.h"
27 
28 namespace dcsctp {
29 
30 // The socket/association state
31 enum class SocketState {
32   // The socket is closed.
33   kClosed,
34   // The socket has initiated a connection, which is not yet established. Note
35   // that for incoming connections and for reconnections when the socket is
36   // already connected, the socket will not transition to this state.
37   kConnecting,
38   // The socket is connected, and the connection is established.
39   kConnected,
40   // The socket is shutting down, and the connection is not yet closed.
41   kShuttingDown,
42 };
43 
44 // Send options for sending messages
45 struct SendOptions {
46   // If the message should be sent with unordered message delivery.
47   IsUnordered unordered = IsUnordered(false);
48 
49   // If set, will discard messages that haven't been correctly sent and
50   // received before the lifetime has expired. This is only available if the
51   // peer supports Partial Reliability Extension (RFC3758).
52   absl::optional<DurationMs> lifetime = absl::nullopt;
53 
54   // If set, limits the number of retransmissions. This is only available
55   // if the peer supports Partial Reliability Extension (RFC3758).
56   absl::optional<size_t> max_retransmissions = absl::nullopt;
57 
58   // If set, will generate lifecycle events for this message. See e.g.
59   // `DcSctpSocketCallbacks::OnLifecycleMessageFullySent`. This value is decided
60   // by the client and the library will provide it to all lifecycle callbacks.
61   LifecycleId lifecycle_id = LifecycleId::NotSet();
62 };
63 
64 enum class ErrorKind {
65   // Indicates that no error has occurred. This will never be the case when
66   // `OnError` or `OnAborted` is called.
67   kNoError,
68   // There have been too many retries or timeouts, and the library has given up.
69   kTooManyRetries,
70   // A command was received that is only possible to execute when the socket is
71   // connected, which it is not.
72   kNotConnected,
73   // Parsing of the command or its parameters failed.
74   kParseFailed,
75   // Commands are received in the wrong sequence, which indicates a
76   // synchronisation mismatch between the peers.
77   kWrongSequence,
78   // The peer has reported an issue using ERROR or ABORT command.
79   kPeerReported,
80   // The peer has performed a protocol violation.
81   kProtocolViolation,
82   // The receive or send buffers have been exhausted.
83   kResourceExhaustion,
84   // The client has performed an invalid operation.
85   kUnsupportedOperation,
86 };
87 
ToString(ErrorKind error)88 inline constexpr absl::string_view ToString(ErrorKind error) {
89   switch (error) {
90     case ErrorKind::kNoError:
91       return "NO_ERROR";
92     case ErrorKind::kTooManyRetries:
93       return "TOO_MANY_RETRIES";
94     case ErrorKind::kNotConnected:
95       return "NOT_CONNECTED";
96     case ErrorKind::kParseFailed:
97       return "PARSE_FAILED";
98     case ErrorKind::kWrongSequence:
99       return "WRONG_SEQUENCE";
100     case ErrorKind::kPeerReported:
101       return "PEER_REPORTED";
102     case ErrorKind::kProtocolViolation:
103       return "PROTOCOL_VIOLATION";
104     case ErrorKind::kResourceExhaustion:
105       return "RESOURCE_EXHAUSTION";
106     case ErrorKind::kUnsupportedOperation:
107       return "UNSUPPORTED_OPERATION";
108   }
109 }
110 
111 enum class SendStatus {
112   // The message was enqueued successfully. As sending the message is done
113   // asynchronously, this is no guarantee that the message has been actually
114   // sent.
115   kSuccess,
116   // The message was rejected as the payload was empty (which is not allowed in
117   // SCTP).
118   kErrorMessageEmpty,
119   // The message was rejected as the payload was larger than what has been set
120   // as `DcSctpOptions.max_message_size`.
121   kErrorMessageTooLarge,
122   // The message could not be enqueued as the socket is out of resources. This
123   // mainly indicates that the send queue is full.
124   kErrorResourceExhaustion,
125   // The message could not be sent as the socket is shutting down.
126   kErrorShuttingDown,
127 };
128 
ToString(SendStatus error)129 inline constexpr absl::string_view ToString(SendStatus error) {
130   switch (error) {
131     case SendStatus::kSuccess:
132       return "SUCCESS";
133     case SendStatus::kErrorMessageEmpty:
134       return "ERROR_MESSAGE_EMPTY";
135     case SendStatus::kErrorMessageTooLarge:
136       return "ERROR_MESSAGE_TOO_LARGE";
137     case SendStatus::kErrorResourceExhaustion:
138       return "ERROR_RESOURCE_EXHAUSTION";
139     case SendStatus::kErrorShuttingDown:
140       return "ERROR_SHUTTING_DOWN";
141   }
142 }
143 
144 // Return value of ResetStreams.
145 enum class ResetStreamsStatus {
146   // If the connection is not yet established, this will be returned.
147   kNotConnected,
148   // Indicates that ResetStreams operation has been successfully initiated.
149   kPerformed,
150   // Indicates that ResetStreams has failed as it's not supported by the peer.
151   kNotSupported,
152 };
153 
ToString(ResetStreamsStatus error)154 inline constexpr absl::string_view ToString(ResetStreamsStatus error) {
155   switch (error) {
156     case ResetStreamsStatus::kNotConnected:
157       return "NOT_CONNECTED";
158     case ResetStreamsStatus::kPerformed:
159       return "PERFORMED";
160     case ResetStreamsStatus::kNotSupported:
161       return "NOT_SUPPORTED";
162   }
163 }
164 
165 // Return value of DcSctpSocketCallbacks::SendPacketWithStatus.
166 enum class SendPacketStatus {
167   // Indicates that the packet was successfully sent. As sending is unreliable,
168   // there are no guarantees that the packet was actually delivered.
169   kSuccess,
170   // The packet was not sent due to a temporary failure, such as the local send
171   // buffer becoming exhausted. This return value indicates that the socket will
172   // recover and sending that packet can be retried at a later time.
173   kTemporaryFailure,
174   // The packet was not sent due to other reasons.
175   kError,
176 };
177 
178 // Represent known SCTP implementations.
179 enum class SctpImplementation {
180   // There is not enough information toto determine any SCTP implementation.
181   kUnknown,
182   // This implementation.
183   kDcsctp,
184   // https://github.com/sctplab/usrsctp.
185   kUsrSctp,
186   // Any other implementation.
187   kOther,
188 };
189 
ToString(SctpImplementation implementation)190 inline constexpr absl::string_view ToString(SctpImplementation implementation) {
191   switch (implementation) {
192     case SctpImplementation::kUnknown:
193       return "unknown";
194     case SctpImplementation::kDcsctp:
195       return "dcsctp";
196     case SctpImplementation::kUsrSctp:
197       return "usrsctp";
198     case SctpImplementation::kOther:
199       return "other";
200   }
201 }
202 
203 // Tracked metrics, which is the return value of GetMetrics. Optional members
204 // will be unset when they are not yet known.
205 struct Metrics {
206   // Transmission stats and metrics.
207 
208   // Number of packets sent.
209   size_t tx_packets_count = 0;
210 
211   // Number of messages requested to be sent.
212   size_t tx_messages_count = 0;
213 
214   // The current congestion window (cwnd) in bytes, corresponding to spinfo_cwnd
215   // defined in RFC6458.
216   size_t cwnd_bytes = 0;
217 
218   // Smoothed round trip time, corresponding to spinfo_srtt defined in RFC6458.
219   int srtt_ms = 0;
220 
221   // Number of data items in the retransmission queue that haven’t been
222   // acked/nacked yet and are in-flight. Corresponding to sstat_unackdata
223   // defined in RFC6458. This may be an approximation when there are messages in
224   // the send queue that haven't been fragmented/packetized yet.
225   size_t unack_data_count = 0;
226 
227   // Receive stats and metrics.
228 
229   // Number of packets received.
230   size_t rx_packets_count = 0;
231 
232   // Number of messages received.
233   size_t rx_messages_count = 0;
234 
235   // The peer’s last announced receiver window size, corresponding to
236   // sstat_rwnd defined in RFC6458.
237   uint32_t peer_rwnd_bytes = 0;
238 
239   // Returns the detected SCTP implementation of the peer. As this is not
240   // explicitly signalled during the connection establishment, heuristics is
241   // used to analyze e.g. the state cookie in the INIT-ACK chunk.
242   SctpImplementation peer_implementation = SctpImplementation::kUnknown;
243 
244   // Indicates if RFC8260 User Message Interleaving has been negotiated by both
245   // peers.
246   bool uses_message_interleaving = false;
247 
248   // The number of negotiated incoming and outgoing streams, which is configured
249   // locally as `DcSctpOptions::announced_maximum_incoming_streams` and
250   // `DcSctpOptions::announced_maximum_outgoing_streams`, and which will be
251   // signaled by the peer during connection.
252   uint16_t negotiated_maximum_incoming_streams = 0;
253   uint16_t negotiated_maximum_outgoing_streams = 0;
254 };
255 
256 // Callbacks that the DcSctpSocket will call synchronously to the owning
257 // client. It is allowed to call back into the library from callbacks that start
258 // with "On". It has been explicitly documented when it's not allowed to call
259 // back into this library from within a callback.
260 //
261 // Theses callbacks are only synchronously triggered as a result of the client
262 // calling a public method in `DcSctpSocketInterface`.
263 class DcSctpSocketCallbacks {
264  public:
265   virtual ~DcSctpSocketCallbacks() = default;
266 
267   // Called when the library wants the packet serialized as `data` to be sent.
268   //
269   // TODO(bugs.webrtc.org/12943): This method is deprecated, see
270   // `SendPacketWithStatus`.
271   //
272   // Note that it's NOT ALLOWED to call into this library from within this
273   // callback.
SendPacket(rtc::ArrayView<const uint8_t> data)274   virtual void SendPacket(rtc::ArrayView<const uint8_t> data) {}
275 
276   // Called when the library wants the packet serialized as `data` to be sent.
277   //
278   // Note that it's NOT ALLOWED to call into this library from within this
279   // callback.
SendPacketWithStatus(rtc::ArrayView<const uint8_t> data)280   virtual SendPacketStatus SendPacketWithStatus(
281       rtc::ArrayView<const uint8_t> data) {
282     SendPacket(data);
283     return SendPacketStatus::kSuccess;
284   }
285 
286   // Called when the library wants to create a Timeout. The callback must return
287   // an object that implements that interface.
288   //
289   // Low precision tasks are scheduled more efficiently by using leeway to
290   // reduce Idle Wake Ups and is the preferred precision whenever possible. High
291   // precision timeouts do not have this leeway, but is still limited by OS
292   // timer precision. At the time of writing, kLow's additional leeway may be up
293   // to 17 ms, but please see webrtc::TaskQueueBase::DelayPrecision for
294   // up-to-date information.
295   //
296   // Note that it's NOT ALLOWED to call into this library from within this
297   // callback.
CreateTimeout(webrtc::TaskQueueBase::DelayPrecision precision)298   virtual std::unique_ptr<Timeout> CreateTimeout(
299       webrtc::TaskQueueBase::DelayPrecision precision) {
300     // TODO(hbos): When dependencies have migrated to this new signature, make
301     // this pure virtual and delete the other version.
302     return CreateTimeout();
303   }
304   // TODO(hbos): When dependencies have migrated to the other signature, delete
305   // this version.
CreateTimeout()306   virtual std::unique_ptr<Timeout> CreateTimeout() {
307     return CreateTimeout(webrtc::TaskQueueBase::DelayPrecision::kLow);
308   }
309 
310   // Returns the current time in milliseconds (from any epoch).
311   //
312   // Note that it's NOT ALLOWED to call into this library from within this
313   // callback.
314   virtual TimeMs TimeMillis() = 0;
315 
316   // Called when the library needs a random number uniformly distributed between
317   // `low` (inclusive) and `high` (exclusive). The random numbers used by the
318   // library are not used for cryptographic purposes. There are no requirements
319   // that the random number generator must be secure.
320   //
321   // Note that it's NOT ALLOWED to call into this library from within this
322   // callback.
323   virtual uint32_t GetRandomInt(uint32_t low, uint32_t high) = 0;
324 
325   // Triggered when the outgoing message buffer is empty, meaning that there are
326   // no more queued messages, but there can still be packets in-flight or to be
327   // retransmitted. (in contrast to SCTP_SENDER_DRY_EVENT).
328   //
329   // Note that it's NOT ALLOWED to call into this library from within this
330   // callback.
331   ABSL_DEPRECATED("Use OnTotalBufferedAmountLow instead")
NotifyOutgoingMessageBufferEmpty()332   virtual void NotifyOutgoingMessageBufferEmpty() {}
333 
334   // Called when the library has received an SCTP message in full and delivers
335   // it to the upper layer.
336   //
337   // It is allowed to call into this library from within this callback.
338   virtual void OnMessageReceived(DcSctpMessage message) = 0;
339 
340   // Triggered when an non-fatal error is reported by either this library or
341   // from the other peer (by sending an ERROR command). These should be logged,
342   // but no other action need to be taken as the association is still viable.
343   //
344   // It is allowed to call into this library from within this callback.
345   virtual void OnError(ErrorKind error, absl::string_view message) = 0;
346 
347   // Triggered when the socket has aborted - either as decided by this socket
348   // due to e.g. too many retransmission attempts, or by the peer when
349   // receiving an ABORT command. No other callbacks will be done after this
350   // callback, unless reconnecting.
351   //
352   // It is allowed to call into this library from within this callback.
353   virtual void OnAborted(ErrorKind error, absl::string_view message) = 0;
354 
355   // Called when calling `Connect` succeeds, but also for incoming successful
356   // connection attempts.
357   //
358   // It is allowed to call into this library from within this callback.
359   virtual void OnConnected() = 0;
360 
361   // Called when the socket is closed in a controlled way. No other
362   // callbacks will be done after this callback, unless reconnecting.
363   //
364   // It is allowed to call into this library from within this callback.
365   virtual void OnClosed() = 0;
366 
367   // On connection restarted (by peer). This is just a notification, and the
368   // association is expected to work fine after this call, but there could have
369   // been packet loss as a result of restarting the association.
370   //
371   // It is allowed to call into this library from within this callback.
372   virtual void OnConnectionRestarted() = 0;
373 
374   // Indicates that a stream reset request has failed.
375   //
376   // It is allowed to call into this library from within this callback.
377   virtual void OnStreamsResetFailed(
378       rtc::ArrayView<const StreamID> outgoing_streams,
379       absl::string_view reason) = 0;
380 
381   // Indicates that a stream reset request has been performed.
382   //
383   // It is allowed to call into this library from within this callback.
384   virtual void OnStreamsResetPerformed(
385       rtc::ArrayView<const StreamID> outgoing_streams) = 0;
386 
387   // When a peer has reset some of its outgoing streams, this will be called. An
388   // empty list indicates that all streams have been reset.
389   //
390   // It is allowed to call into this library from within this callback.
391   virtual void OnIncomingStreamsReset(
392       rtc::ArrayView<const StreamID> incoming_streams) = 0;
393 
394   // Will be called when the amount of data buffered to be sent falls to or
395   // below the threshold set when calling `SetBufferedAmountLowThreshold`.
396   //
397   // It is allowed to call into this library from within this callback.
OnBufferedAmountLow(StreamID stream_id)398   virtual void OnBufferedAmountLow(StreamID stream_id) {}
399 
400   // Will be called when the total amount of data buffered (in the entire send
401   // buffer, for all streams) falls to or below the threshold specified in
402   // `DcSctpOptions::total_buffered_amount_low_threshold`.
OnTotalBufferedAmountLow()403   virtual void OnTotalBufferedAmountLow() {}
404 
405   // == Lifecycle Events ==
406   //
407   // If a `lifecycle_id` is provided as `SendOptions`, lifecycle callbacks will
408   // be triggered as the message is processed by the library.
409   //
410   // The possible transitions are shown in the graph below:
411   //
412   //        DcSctpSocket::Send  ────────────────────────┐
413   //                │                                   │
414   //                │                                   │
415   //                v                                   v
416   //    OnLifecycleMessageFullySent ───────> OnLifecycleMessageExpired
417   //                │                                   │
418   //                │                                   │
419   //                v                                   v
420   //    OnLifeCycleMessageDelivered ────────────> OnLifecycleEnd
421 
422   // OnLifecycleMessageFullySent will be called when a message has been fully
423   // sent, meaning that the last fragment has been produced from the send queue
424   // and sent on the network. Note that this will trigger at most once per
425   // message even if the message was retransmitted due to packet loss.
426   //
427   // This is a lifecycle event.
428   //
429   // Note that it's NOT ALLOWED to call into this library from within this
430   // callback.
OnLifecycleMessageFullySent(LifecycleId lifecycle_id)431   virtual void OnLifecycleMessageFullySent(LifecycleId lifecycle_id) {}
432 
433   // OnLifecycleMessageExpired will be called when a message has expired. If it
434   // was expired with data remaining in the send queue that had not been sent
435   // ever, `maybe_delivered` will be set to false. If `maybe_delivered` is true,
436   // the message has at least once been sent and may have been correctly
437   // received by the peer, but it has expired before the receiver managed to
438   // acknowledge it. This means that if `maybe_delivered` is true, it's unknown
439   // if the message was lost or was delivered, and if `maybe_delivered` is
440   // false, it's guaranteed to not be delivered.
441   //
442   // It's guaranteed that `OnLifecycleMessageDelivered` is not called if this
443   // callback has triggered.
444   //
445   // This is a lifecycle event.
446   //
447   // Note that it's NOT ALLOWED to call into this library from within this
448   // callback.
OnLifecycleMessageExpired(LifecycleId lifecycle_id,bool maybe_delivered)449   virtual void OnLifecycleMessageExpired(LifecycleId lifecycle_id,
450                                          bool maybe_delivered) {}
451 
452   // OnLifecycleMessageDelivered will be called when a non-expired message has
453   // been acknowledged by the peer as delivered.
454   //
455   // Note that this will trigger only when the peer moves its cumulative TSN ack
456   // beyond this message, and will not fire for messages acked using
457   // gap-ack-blocks as those are renegable. This means that this may fire a bit
458   // later than the message was actually first "acked" by the peer, as -
459   // according to the protocol - those acks may be unacked later by the client.
460   //
461   // It's guaranteed that `OnLifecycleMessageExpired` is not called if this
462   // callback has triggered.
463   //
464   // This is a lifecycle event.
465   //
466   // Note that it's NOT ALLOWED to call into this library from within this
467   // callback.
OnLifecycleMessageDelivered(LifecycleId lifecycle_id)468   virtual void OnLifecycleMessageDelivered(LifecycleId lifecycle_id) {}
469 
470   // OnLifecycleEnd will be called when a lifecycle event has reached its end.
471   // It will be called when processing of a message is complete, no matter how
472   // it completed. It will be called after all other lifecycle events, if any.
473   //
474   // Note that it's possible that this callback triggers without any other
475   // lifecycle callbacks having been called before in case of errors, such as
476   // attempting to send an empty message or failing to enqueue a message if the
477   // send queue is full.
478   //
479   // NOTE: When the socket is deallocated, there will be no `OnLifecycleEnd`
480   // callbacks sent for messages that were enqueued. But as long as the socket
481   // is alive, `OnLifecycleEnd` callbacks are guaranteed to be sent as messages
482   // are either expired or successfully acknowledged.
483   //
484   // This is a lifecycle event.
485   //
486   // Note that it's NOT ALLOWED to call into this library from within this
487   // callback.
OnLifecycleEnd(LifecycleId lifecycle_id)488   virtual void OnLifecycleEnd(LifecycleId lifecycle_id) {}
489 };
490 
491 // The DcSctpSocket implementation implements the following interface.
492 // This class is thread-compatible.
493 class DcSctpSocketInterface {
494  public:
495   virtual ~DcSctpSocketInterface() = default;
496 
497   // To be called when an incoming SCTP packet is to be processed.
498   virtual void ReceivePacket(rtc::ArrayView<const uint8_t> data) = 0;
499 
500   // To be called when a timeout has expired. The `timeout_id` is provided
501   // when the timeout was initiated.
502   virtual void HandleTimeout(TimeoutID timeout_id) = 0;
503 
504   // Connects the socket. This is an asynchronous operation, and
505   // `DcSctpSocketCallbacks::OnConnected` will be called on success.
506   virtual void Connect() = 0;
507 
508   // Puts this socket to the state in which the original socket was when its
509   // `DcSctpSocketHandoverState` was captured by `GetHandoverStateAndClose`.
510   // `RestoreFromState` is allowed only on the closed socket.
511   // `DcSctpSocketCallbacks::OnConnected` will be called if a connected socket
512   // state is restored.
513   // `DcSctpSocketCallbacks::OnError` will be called on error.
514   virtual void RestoreFromState(const DcSctpSocketHandoverState& state) = 0;
515 
516   // Gracefully shutdowns the socket and sends all outstanding data. This is an
517   // asynchronous operation and `DcSctpSocketCallbacks::OnClosed` will be called
518   // on success.
519   virtual void Shutdown() = 0;
520 
521   // Closes the connection non-gracefully. Will send ABORT if the connection is
522   // not already closed. No callbacks will be made after Close() has returned.
523   virtual void Close() = 0;
524 
525   // The socket state.
526   virtual SocketState state() const = 0;
527 
528   // The options it was created with.
529   virtual const DcSctpOptions& options() const = 0;
530 
531   // Update the options max_message_size.
532   virtual void SetMaxMessageSize(size_t max_message_size) = 0;
533 
534   // Sets the priority of an outgoing stream. The initial value, when not set,
535   // is `DcSctpOptions::default_stream_priority`.
536   virtual void SetStreamPriority(StreamID stream_id,
537                                  StreamPriority priority) = 0;
538 
539   // Returns the currently set priority for an outgoing stream. The initial
540   // value, when not set, is `DcSctpOptions::default_stream_priority`.
541   virtual StreamPriority GetStreamPriority(StreamID stream_id) const = 0;
542 
543   // Sends the message `message` using the provided send options.
544   // Sending a message is an asynchronous operation, and the `OnError` callback
545   // may be invoked to indicate any errors in sending the message.
546   //
547   // The association does not have to be established before calling this method.
548   // If it's called before there is an established association, the message will
549   // be queued.
550   virtual SendStatus Send(DcSctpMessage message,
551                           const SendOptions& send_options) = 0;
552 
553   // Resetting streams is an asynchronous operation and the results will
554   // be notified using `DcSctpSocketCallbacks::OnStreamsResetDone()` on success
555   // and `DcSctpSocketCallbacks::OnStreamsResetFailed()` on failure. Note that
556   // only outgoing streams can be reset.
557   //
558   // When it's known that the peer has reset its own outgoing streams,
559   // `DcSctpSocketCallbacks::OnIncomingStreamReset` is called.
560   //
561   // Note that resetting a stream will also remove all queued messages on those
562   // streams, but will ensure that the currently sent message (if any) is fully
563   // sent before closing the stream.
564   //
565   // Resetting streams can only be done on an established association that
566   // supports stream resetting. Calling this method on e.g. a closed association
567   // or streams that don't support resetting will not perform any operation.
568   virtual ResetStreamsStatus ResetStreams(
569       rtc::ArrayView<const StreamID> outgoing_streams) = 0;
570 
571   // Returns the number of bytes of data currently queued to be sent on a given
572   // stream.
573   virtual size_t buffered_amount(StreamID stream_id) const = 0;
574 
575   // Returns the number of buffered outgoing bytes that is considered "low" for
576   // a given stream. See `SetBufferedAmountLowThreshold`.
577   virtual size_t buffered_amount_low_threshold(StreamID stream_id) const = 0;
578 
579   // Used to specify the number of bytes of buffered outgoing data that is
580   // considered "low" for a given stream, which will trigger an
581   // OnBufferedAmountLow event. The default value is zero (0).
582   virtual void SetBufferedAmountLowThreshold(StreamID stream_id,
583                                              size_t bytes) = 0;
584 
585   // Retrieves the latest metrics. If the socket is not fully connected,
586   // `absl::nullopt` will be returned.
587   virtual absl::optional<Metrics> GetMetrics() const = 0;
588 
589   // Returns empty bitmask if the socket is in the state in which a snapshot of
590   // the state can be made by `GetHandoverStateAndClose()`. Return value is
591   // invalidated by a call to any non-const method.
592   virtual HandoverReadinessStatus GetHandoverReadiness() const = 0;
593 
594   // Collects a snapshot of the socket state that can be used to reconstruct
595   // this socket in another process. On success this socket object is closed
596   // synchronously and no callbacks will be made after the method has returned.
597   // The method fails if the socket is not in a state ready for handover.
598   // nullopt indicates the failure. `DcSctpSocketCallbacks::OnClosed` will be
599   // called on success.
600   virtual absl::optional<DcSctpSocketHandoverState>
601   GetHandoverStateAndClose() = 0;
602 
603   // Returns the detected SCTP implementation of the peer. As this is not
604   // explicitly signalled during the connection establishment, heuristics is
605   // used to analyze e.g. the state cookie in the INIT-ACK chunk.
606   //
607   // If this method is called too early (before
608   // `DcSctpSocketCallbacks::OnConnected` has triggered), this will likely
609   // return `SctpImplementation::kUnknown`.
610   ABSL_DEPRECATED("See Metrics::peer_implementation instead")
peer_implementation()611   virtual SctpImplementation peer_implementation() const {
612     return SctpImplementation::kUnknown;
613   }
614 };
615 }  // namespace dcsctp
616 
617 #endif  // NET_DCSCTP_PUBLIC_DCSCTP_SOCKET_H_
618