1use bytes::BytesMut;
7use shared::error::*;
8use std::collections::{HashMap, VecDeque};
9use std::io::BufReader;
10use std::net::SocketAddr;
11use std::ops::Add;
12use std::time::{Duration, Instant};
13
14use crate::agent::*;
15use crate::message::*;
16use shared::{TaggedBytesMut, TransportContext, TransportMessage, TransportProtocol};
17
18const DEFAULT_TIMEOUT_RATE: Duration = Duration::from_millis(5);
19const DEFAULT_RTO: Duration = Duration::from_millis(300);
20const DEFAULT_MAX_ATTEMPTS: u32 = 7;
21const DEFAULT_MAX_BUFFER_SIZE: usize = 8;
22
23#[derive(Debug, Clone)]
28pub struct ClientTransaction {
29 id: TransactionId,
30 attempt: u32,
31 start: Instant,
32 rto: Duration,
33 raw: Vec<u8>,
34}
35
36impl ClientTransaction {
37 pub(crate) fn next_timeout(&self, now: Instant) -> Instant {
38 now.add((self.attempt + 1) * self.rto)
39 }
40}
41
42struct ClientSettings {
43 buffer_size: usize,
44 rto: Duration,
45 rto_rate: Duration,
46 max_attempts: u32,
47 closed: bool,
48}
49
50impl Default for ClientSettings {
51 fn default() -> Self {
52 ClientSettings {
53 buffer_size: DEFAULT_MAX_BUFFER_SIZE,
54 rto: DEFAULT_RTO,
55 rto_rate: DEFAULT_TIMEOUT_RATE,
56 max_attempts: DEFAULT_MAX_ATTEMPTS,
57 closed: false,
58 }
59 }
60}
61
62#[derive(Default)]
63pub struct ClientBuilder {
66 settings: ClientSettings,
67}
68
69impl ClientBuilder {
70 pub fn with_rto(mut self, rto: Duration) -> Self {
72 self.settings.rto = rto;
73 self
74 }
75
76 pub fn with_timeout_rate(mut self, d: Duration) -> Self {
78 self.settings.rto_rate = d;
79 self
80 }
81
82 pub fn with_buffer_size(mut self, buffer_size: usize) -> Self {
84 self.settings.buffer_size = buffer_size;
85 self
86 }
87
88 pub fn with_no_retransmit(mut self) -> Self {
93 self.settings.max_attempts = 0;
94 if self.settings.rto == Duration::from_secs(0) {
95 self.settings.rto = DEFAULT_MAX_ATTEMPTS * DEFAULT_RTO;
96 }
97 self
98 }
99
100 pub fn new() -> Self {
102 ClientBuilder {
103 settings: ClientSettings::default(),
104 }
105 }
106
107 pub fn build(
113 self,
114 local: SocketAddr,
115 remote: SocketAddr,
116 protocol: TransportProtocol,
117 ) -> Result<Client> {
118 Ok(Client::new(local, remote, protocol, self.settings))
119 }
120}
121
122pub struct Client {
124 local: SocketAddr,
125 remote: SocketAddr,
126 transport_protocol: TransportProtocol,
127 agent: Agent,
128 settings: ClientSettings,
129 transactions: HashMap<TransactionId, ClientTransaction>,
130 transmits: VecDeque<TransportMessage<BytesMut>>,
131}
132
133impl Client {
134 fn new(
135 local: SocketAddr,
136 remote: SocketAddr,
137 transport_protocol: TransportProtocol,
138 settings: ClientSettings,
139 ) -> Self {
140 Self {
141 local,
142 remote,
143 transport_protocol,
144 agent: Agent::new(),
145 settings,
146 transactions: HashMap::new(),
147 transmits: VecDeque::new(),
148 }
149 }
150
151 pub fn local_addr(&self) -> SocketAddr {
153 self.local
154 }
155
156 pub fn peer_addr(&self) -> SocketAddr {
158 self.remote
159 }
160}
161
162impl sansio::Protocol<TaggedBytesMut, Message, ()> for Client {
163 type Rout = ();
164 type Wout = TaggedBytesMut;
165 type Eout = StunEvent;
166 type Error = Error;
167 type Time = Instant;
168
169 fn handle_read(&mut self, msg: TaggedBytesMut) -> Result<()> {
170 let mut stun_msg = Message::new();
171 let mut reader = BufReader::new(&msg.message[..]);
172 stun_msg.read_from(&mut reader)?;
173 self.agent.handle_event(ClientAgent::Process(stun_msg))
174 }
175
176 fn poll_read(&mut self) -> Option<Self::Rout> {
177 None
178 }
179
180 fn handle_write(&mut self, m: Message) -> Result<()> {
181 if self.settings.closed {
182 return Err(Error::ErrClientClosed);
183 }
184
185 let payload = BytesMut::from(&m.raw[..]);
186
187 let ct = ClientTransaction {
188 id: m.transaction_id,
189 attempt: 0,
190 start: Instant::now(),
191 rto: self.settings.rto,
192 raw: m.raw,
193 };
194 let deadline = ct.next_timeout(ct.start);
195 self.transactions.entry(ct.id).or_insert(ct);
196 self.agent
197 .handle_event(ClientAgent::Start(m.transaction_id, deadline))?;
198
199 self.transmits.push_back(TransportMessage {
200 now: Instant::now(),
201 transport: TransportContext {
202 local_addr: self.local,
203 peer_addr: self.remote,
204 ecn: None,
205 transport_protocol: self.transport_protocol,
206 },
207 message: payload,
208 });
209
210 Ok(())
211 }
212
213 fn poll_write(&mut self) -> Option<Self::Wout> {
221 self.transmits.pop_front()
222 }
223
224 fn poll_event(&mut self) -> Option<Self::Eout> {
225 while let Some(event) = self.agent.poll_event() {
226 let mut ct = if self.transactions.contains_key(&event.id) {
227 self.transactions.remove(&event.id).unwrap()
228 } else {
229 continue;
230 };
231
232 if let StunEvent::Message(_) = &event.evt {
233 return Some(event.evt);
234 }
235 if ct.attempt >= self.settings.max_attempts {
236 return Some(event.evt);
237 }
238
239 ct.attempt += 1;
241
242 let payload = BytesMut::from(&ct.raw[..]);
243 let timeout = ct.next_timeout(Instant::now());
244 let id = ct.id;
245
246 self.transactions.entry(ct.id).or_insert(ct);
248
249 if self
251 .agent
252 .handle_event(ClientAgent::Start(id, timeout))
253 .is_err()
254 {
255 self.transactions.remove(&id);
256 return Some(event.evt);
257 }
258
259 self.transmits.push_back(TransportMessage {
261 now: Instant::now(),
262 transport: TransportContext {
263 local_addr: self.local,
264 peer_addr: self.remote,
265 ecn: None,
266 transport_protocol: self.transport_protocol,
267 },
268 message: payload,
269 });
270 }
271
272 None
273 }
274
275 fn poll_timeout(&mut self) -> Option<Self::Time> {
276 self.agent.poll_timeout()
277 }
278
279 fn handle_timeout(&mut self, now: Instant) -> Result<()> {
280 self.agent.handle_event(ClientAgent::Collect(now))
281 }
282
283 fn close(&mut self) -> Result<()> {
284 if self.settings.closed {
285 return Err(Error::ErrClientClosed);
286 }
287 self.settings.closed = true;
288 self.agent.handle_event(ClientAgent::Close)
289 }
290}