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