1use std::time::Duration;
4
5use crate::message::{Header, Message, Method, Request, Response};
6use crate::name::HeaderName;
7use crate::transaction::timing::{Timer, Timers};
8use crate::transaction::{Output, Reason, Reliability, TuEvent};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ClientState {
17 Calling,
19 Trying,
21 Proceeding,
23 Completed,
25 Accepted,
27 Terminated,
29}
30
31impl ClientState {
32 #[must_use]
34 pub fn is_terminated(self) -> bool {
35 matches!(self, Self::Terminated)
36 }
37}
38
39#[derive(Debug)]
41pub struct ClientTransaction {
42 request: Request,
43 is_invite: bool,
44 state: ClientState,
45 reliability: Reliability,
46 timers: Timers,
47 interval: Duration,
49 ack: Option<Request>,
52}
53
54impl ClientTransaction {
55 #[must_use]
57 pub fn new(request: Request, reliability: Reliability, timers: Timers) -> (Self, Vec<Output>) {
58 let is_invite = request.method == Method::Invite;
59 let mut tx = Self {
60 request,
61 is_invite,
62 state: if is_invite {
63 ClientState::Calling
64 } else {
65 ClientState::Trying
66 },
67 reliability,
68 timers,
69 interval: timers.t1,
70 ack: None,
71 };
72
73 let mut out = vec![Output::send(Message::Request(tx.request.clone()))];
74 if !reliability.is_reliable() {
75 out.push(Output::SetTimer {
76 timer: if is_invite { Timer::A } else { Timer::E },
77 after: tx.interval,
78 });
79 }
80 out.push(Output::SetTimer {
81 timer: if is_invite { Timer::B } else { Timer::F },
82 after: timers.timeout(),
83 });
84 tx.state = if is_invite {
85 ClientState::Calling
86 } else {
87 ClientState::Trying
88 };
89 (tx, out)
90 }
91
92 #[must_use]
94 pub fn state(&self) -> ClientState {
95 self.state
96 }
97
98 #[must_use]
100 pub fn request(&self) -> &Request {
101 &self.request
102 }
103
104 pub fn on_response(&mut self, response: Response) -> Vec<Output> {
106 if self.is_invite {
107 self.invite_response(response)
108 } else {
109 self.non_invite_response(response)
110 }
111 }
112
113 fn invite_response(&mut self, response: Response) -> Vec<Output> {
114 let status = response.status;
115 match self.state {
116 ClientState::Calling | ClientState::Proceeding => {
117 let from_calling = self.state == ClientState::Calling;
118 let mut out = Vec::new();
119
120 if status.is_provisional() {
121 if from_calling {
122 out.push(Output::ClearTimer(Timer::A));
127 out.push(Output::ClearTimer(Timer::B));
128 }
129 self.state = ClientState::Proceeding;
130 out.push(Output::to_tu(TuEvent::Response(Box::new(response))));
131 return out;
132 }
133
134 if from_calling {
135 out.push(Output::ClearTimer(Timer::A));
136 }
137 out.push(Output::ClearTimer(Timer::B));
138
139 if status.is_success() {
140 self.state = ClientState::Accepted;
144 out.push(Output::to_tu(TuEvent::Response(Box::new(response))));
145 out.push(Output::SetTimer {
146 timer: Timer::M,
147 after: self.timers.timeout(),
148 });
149 } else {
150 let ack = make_ack(&self.request, &response);
153 out.push(Output::send(Message::Request(ack.clone())));
154 self.ack = Some(ack);
155 self.state = ClientState::Completed;
156 out.push(Output::to_tu(TuEvent::Response(Box::new(response))));
157 out.push(Output::SetTimer {
158 timer: Timer::D,
159 after: self.timers.timer_d(self.reliability),
160 });
161 }
162 out
163 }
164 ClientState::Completed => {
165 self.ack
168 .as_ref()
169 .map(|ack| Output::send(Message::Request(ack.clone())))
170 .into_iter()
171 .collect()
172 }
173 ClientState::Accepted => {
174 if status.is_success() {
175 vec![Output::to_tu(TuEvent::Response(Box::new(response)))]
178 } else {
179 Vec::new()
180 }
181 }
182 ClientState::Trying | ClientState::Terminated => Vec::new(),
183 }
184 }
185
186 fn non_invite_response(&mut self, response: Response) -> Vec<Output> {
187 match self.state {
188 ClientState::Trying | ClientState::Proceeding => {
189 if response.status.is_provisional() {
190 self.state = ClientState::Proceeding;
191 return vec![Output::to_tu(TuEvent::Response(Box::new(response)))];
192 }
193 self.state = ClientState::Completed;
194 vec![
195 Output::ClearTimer(Timer::E),
196 Output::ClearTimer(Timer::F),
197 Output::to_tu(TuEvent::Response(Box::new(response))),
198 Output::SetTimer {
199 timer: Timer::K,
200 after: self.timers.absorb(self.reliability),
201 },
202 ]
203 }
204 _ => Vec::new(),
206 }
207 }
208
209 pub fn on_timer(&mut self, timer: Timer) -> Vec<Output> {
211 match (self.state, timer) {
212 (ClientState::Calling, Timer::A) => {
213 self.interval = self.timers.double(self.interval);
214 vec![
215 Output::send(Message::Request(self.request.clone())),
216 Output::SetTimer {
217 timer: Timer::A,
218 after: self.interval,
219 },
220 ]
221 }
222 (ClientState::Trying, Timer::E) => {
223 self.interval = self.timers.double_capped(self.interval);
224 vec![
225 Output::send(Message::Request(self.request.clone())),
226 Output::SetTimer {
227 timer: Timer::E,
228 after: self.interval,
229 },
230 ]
231 }
232 (ClientState::Proceeding, Timer::E) if !self.is_invite => {
233 self.interval = self.timers.t2;
237 vec![
238 Output::send(Message::Request(self.request.clone())),
239 Output::SetTimer {
240 timer: Timer::E,
241 after: self.interval,
242 },
243 ]
244 }
245 (ClientState::Calling, Timer::B)
251 | (ClientState::Trying | ClientState::Proceeding, Timer::F) => {
252 self.state = ClientState::Terminated;
253 vec![
254 Output::to_tu(TuEvent::Timeout),
255 Output::Terminated(Reason::Timeout),
256 ]
257 }
258 (ClientState::Completed, Timer::D | Timer::K) | (ClientState::Accepted, Timer::M) => {
259 self.state = ClientState::Terminated;
260 vec![Output::Terminated(Reason::Completed)]
261 }
262 _ => Vec::new(),
263 }
264 }
265
266 pub fn on_transport_error(&mut self) -> Vec<Output> {
268 if self.state.is_terminated() {
269 return Vec::new();
270 }
271 self.state = ClientState::Terminated;
272 vec![
273 Output::to_tu(TuEvent::TransportError),
274 Output::Terminated(Reason::TransportError),
275 ]
276 }
277}
278
279fn make_ack(request: &Request, response: &Response) -> Request {
285 let mut ack = Request::new(Method::Ack, request.uri.clone());
286
287 if let Some(via) = request.headers.get(&HeaderName::Via) {
289 ack.headers.push(via.clone());
290 }
291 if let Some(from) = request.headers.get(&HeaderName::From) {
292 ack.headers.push(from.clone());
293 }
294 if let Some(to) = response.headers.get(&HeaderName::To) {
297 ack.headers.push(to.clone());
298 }
299 if let Some(call_id) = request.headers.get(&HeaderName::CallId) {
300 ack.headers.push(call_id.clone());
301 }
302 for route in request.headers.get_all(&HeaderName::Route) {
303 ack.headers.push(route.clone());
304 }
305 ack.headers.push(Header::new_unchecked(
308 HeaderName::MaxForwards,
309 bytes::Bytes::from_static(b"70"),
310 ));
311
312 let sequence = request
314 .headers
315 .value(&HeaderName::CSeq)
316 .and_then(|v| {
317 let digits: Vec<u8> = v.iter().copied().take_while(u8::is_ascii_digit).collect();
318 String::from_utf8(digits).ok()
319 })
320 .unwrap_or_default();
321 let mut cseq = sequence.into_bytes();
322 cseq.extend_from_slice(b" ACK");
323 ack.headers.push(Header::new_unchecked(
324 HeaderName::CSeq,
325 bytes::Bytes::from(cseq),
326 ));
327 ack.headers.push(Header::new_unchecked(
328 HeaderName::ContentLength,
329 bytes::Bytes::from_static(b"0"),
330 ));
331
332 ack
333}