s2n_quic_platform/socket/task/
events.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::features::Gso;
5use core::ops::ControlFlow;
6
7#[derive(Debug)]
8pub struct TxEvents {
9    count: usize,
10    is_blocked: bool,
11    gso: Gso,
12}
13
14impl TxEvents {
15    #[inline]
16    pub fn new(gso: Gso) -> Self {
17        Self {
18            count: 0,
19            is_blocked: false,
20            gso,
21        }
22    }
23
24    /// Returns if the task is blocked
25    #[inline]
26    pub fn is_blocked(&self) -> bool {
27        self.is_blocked
28    }
29
30    /// Returns if the task was blocked and resets the value
31    #[inline]
32    pub fn take_blocked(&mut self) -> bool {
33        core::mem::take(&mut self.is_blocked)
34    }
35
36    /// Sets the task to blocked
37    #[inline]
38    pub fn blocked(&mut self) {
39        self.is_blocked = true;
40    }
41
42    /// Returns and resets the number of messages sent
43    #[inline]
44    pub fn take_count(&mut self) -> usize {
45        core::mem::take(&mut self.count)
46    }
47}
48
49impl crate::syscall::SocketEvents for TxEvents {
50    #[inline]
51    fn on_complete(&mut self, count: usize) -> ControlFlow<(), ()> {
52        // increment the total sent packets and reset our blocked status
53        self.count += count;
54        self.is_blocked = false;
55        ControlFlow::Continue(())
56    }
57
58    #[inline]
59    fn on_error(&mut self, error: ::std::io::Error) -> ControlFlow<(), ()> {
60        use std::io::ErrorKind::*;
61
62        match error.kind() {
63            WouldBlock => {
64                // record that we're blocked
65                self.is_blocked = true;
66                ControlFlow::Break(())
67            }
68            Interrupted => {
69                // if we got interrupted break and have the task try again
70                ControlFlow::Break(())
71            }
72            _ => {
73                // let the GSO settings know there was an error on the socket, which may indicate
74                // it needs to be disabled
75                let _ = self.gso.handle_socket_error(&error);
76
77                // ignore all other errors and just consider the packet sent
78                self.count += 1;
79
80                // We `continue` instead of break because it's very unlikely the message would be
81                // accepted at a later time, so we just discard the packet.
82                ControlFlow::Continue(())
83            }
84        }
85    }
86}
87
88#[derive(Debug, Default)]
89pub struct RxEvents {
90    count: usize,
91    is_blocked: bool,
92}
93
94impl RxEvents {
95    /// Returns if the task is blocked
96    #[inline]
97    pub fn is_blocked(&self) -> bool {
98        self.is_blocked
99    }
100
101    /// Returns if the task was blocked and resets the value
102    #[inline]
103    pub fn take_blocked(&mut self) -> bool {
104        core::mem::take(&mut self.is_blocked)
105    }
106
107    /// Sets the task to blocked
108    #[inline]
109    pub fn blocked(&mut self) {
110        self.is_blocked = true;
111    }
112
113    /// Returns and resets the number of messages sent
114    #[inline]
115    pub fn take_count(&mut self) -> usize {
116        core::mem::take(&mut self.count)
117    }
118}
119
120impl crate::syscall::SocketEvents for RxEvents {
121    #[inline]
122    fn on_complete(&mut self, count: usize) -> ControlFlow<(), ()> {
123        // increment the total sent packets and reset our blocked status
124        self.count += count;
125        self.is_blocked = false;
126        ControlFlow::Continue(())
127    }
128
129    #[inline]
130    fn on_error(&mut self, error: ::std::io::Error) -> ControlFlow<(), ()> {
131        use std::io::ErrorKind::*;
132
133        match error.kind() {
134            WouldBlock => {
135                // record that we're blocked
136                self.is_blocked = true;
137                ControlFlow::Break(())
138            }
139            Interrupted => {
140                // if we got interrupted break and have the task try again
141                ControlFlow::Break(())
142            }
143            _ => {
144                // ignore all other errors and have the task try again
145                ControlFlow::Break(())
146            }
147        }
148    }
149}