ftth_rsipstack/dialog/server_dialog.rs
1use super::dialog::{Dialog, DialogInnerRef, DialogState, TerminatedReason};
2use super::DialogId;
3use crate::dialog::dialog::DialogInner;
4use crate::transport::SipConnection;
5use crate::{
6 transaction::transaction::{Transaction, TransactionEvent},
7 Result,
8};
9use rsip::{prelude::HeadersExt, Header, Request, SipMessage, StatusCode};
10use std::sync::atomic::Ordering;
11use tokio_util::sync::CancellationToken;
12use tracing::{debug, info, trace, warn};
13
14/// Server-side INVITE Dialog (UAS)
15///
16/// `ServerInviteDialog` represents a server-side INVITE dialog in SIP. This is used
17/// when the local user agent acts as a User Agent Server (UAS) and receives
18/// an INVITE transaction from a remote party to establish a session.
19///
20/// # Key Features
21///
22/// * **Session Acceptance** - Accepts or rejects incoming INVITE requests
23/// * **In-dialog Requests** - Handles UPDATE, INFO, OPTIONS within established dialogs
24/// * **Session Termination** - Handles BYE for ending sessions
25/// * **Re-INVITE Support** - Supports session modification via re-INVITE
26/// * **ACK Handling** - Properly handles ACK for 2xx responses
27/// * **State Management** - Tracks dialog state transitions
28///
29/// # Dialog Lifecycle
30///
31/// 1. **Creation** - Dialog created when receiving INVITE
32/// 2. **Processing** - Can send provisional responses (1xx)
33/// 3. **Decision** - Accept (2xx) or reject (3xx-6xx) the INVITE
34/// 4. **Wait ACK** - If accepted, wait for ACK from client
35/// 5. **Confirmed** - ACK received, dialog established
36/// 6. **Active** - Can handle in-dialog requests
37/// 7. **Termination** - Receives BYE or sends BYE to end session
38///
39/// # Examples
40///
41/// ## Basic Call Handling
42///
43/// ```rust,no_run
44/// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
45/// # fn example() -> rsipstack::Result<()> {
46/// # let dialog: ServerInviteDialog = todo!(); // Dialog is typically created by DialogLayer
47/// # let answer_sdp = vec![];
48/// // After receiving INVITE:
49///
50/// // Accept the call
51/// dialog.accept(None, Some(answer_sdp))?;
52///
53/// // Or reject the call
54/// dialog.reject(None, None)?;
55/// # Ok(())
56/// # }
57/// ```
58///
59/// ```rust,no_run
60/// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
61/// # async fn example() -> rsipstack::Result<()> {
62/// # let dialog: ServerInviteDialog = todo!();
63/// // End an established call
64/// dialog.bye().await?;
65/// # Ok(())
66/// # }
67/// ```
68///
69/// ## Session Modification
70///
71/// ```rust,no_run
72/// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
73/// # async fn example() -> rsipstack::Result<()> {
74/// # let dialog: ServerInviteDialog = todo!();
75/// # let new_sdp = vec![];
76/// // Send re-INVITE to modify session
77/// let headers = vec![
78/// rsip::Header::ContentType("application/sdp".into())
79/// ];
80/// let response = dialog.reinvite(Some(headers), Some(new_sdp)).await?;
81/// # Ok(())
82/// # }
83/// ```
84///
85/// # Thread Safety
86///
87/// ServerInviteDialog is thread-safe and can be cloned and shared across tasks.
88/// All operations are atomic and properly synchronized.
89#[derive(Clone)]
90pub struct ServerInviteDialog {
91 pub(super) inner: DialogInnerRef,
92}
93
94impl ServerInviteDialog {
95 /// Get the dialog identifier
96 ///
97 /// Returns the unique DialogId that identifies this dialog instance.
98 /// The DialogId consists of Call-ID, from-tag, and to-tag.
99 pub fn id(&self) -> DialogId {
100 self.inner.id.lock().unwrap().clone()
101 }
102
103 pub fn state(&self) -> DialogState {
104 self.inner.state.lock().unwrap().clone()
105 }
106
107 /// Get the cancellation token for this dialog
108 ///
109 /// Returns a reference to the CancellationToken that can be used to
110 /// cancel ongoing operations for this dialog.
111 pub fn cancel_token(&self) -> &CancellationToken {
112 &self.inner.cancel_token
113 }
114
115 /// Get the initial INVITE request
116 ///
117 /// Returns a reference to the initial INVITE request that created
118 /// this dialog. This can be used to access the original request
119 /// headers, body, and other information.
120 pub fn initial_request(&self) -> &Request {
121 &self.inner.initial_request
122 }
123
124 pub fn ringing(&self, headers: Option<Vec<Header>>, body: Option<Vec<u8>>) -> Result<()> {
125 if !self.inner.can_cancel() {
126 return Ok(());
127 }
128 info!(id = %self.id(), "sending ringing response");
129 let resp = self.inner.make_response(
130 &self.inner.initial_request,
131 if body.is_some() {
132 StatusCode::SessionProgress
133 } else {
134 StatusCode::Ringing
135 },
136 headers,
137 body,
138 );
139 self.inner
140 .tu_sender
141 .send(TransactionEvent::Respond(resp.clone()))?;
142 self.inner.transition(DialogState::Early(self.id(), resp))?;
143 Ok(())
144 }
145 /// Accept the incoming INVITE request
146 ///
147 /// Sends a 200 OK response to accept the incoming INVITE request.
148 /// This establishes the dialog and transitions it to the WaitAck state,
149 /// waiting for the ACK from the client.
150 ///
151 /// # Parameters
152 ///
153 /// * `headers` - Optional additional headers to include in the response
154 /// * `body` - Optional message body (typically SDP answer)
155 ///
156 /// # Returns
157 ///
158 /// * `Ok(())` - Response sent successfully
159 /// * `Err(Error)` - Failed to send response or transaction terminated
160 ///
161 /// # Examples
162 ///
163 /// ```rust,no_run
164 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
165 /// # fn example() -> rsipstack::Result<()> {
166 /// # let dialog: ServerInviteDialog = todo!();
167 /// // Accept with SDP answer
168 /// let answer_sdp = b"v=0\r\no=- 123 456 IN IP4 192.168.1.1\r\n...";
169 /// let headers = vec![
170 /// rsip::Header::ContentType("application/sdp".into())
171 /// ];
172 /// dialog.accept(Some(headers), Some(answer_sdp.to_vec()))?;
173 /// # Ok(())
174 /// # }
175 /// ```
176 pub fn accept(&self, headers: Option<Vec<Header>>, body: Option<Vec<u8>>) -> Result<()> {
177 let resp = self.inner.make_response(
178 &self.inner.initial_request,
179 rsip::StatusCode::OK,
180 headers,
181 body,
182 );
183 let via = self.inner.initial_request.via_header()?;
184 let (via_transport, via_received) = SipConnection::parse_target_from_via(via)?;
185 let mut params = vec![];
186 if via_transport != rsip::transport::Transport::Udp {
187 params.push(rsip::param::Param::Transport(via_transport));
188 }
189 let contact = rsip::headers::typed::Contact {
190 uri: rsip::Uri {
191 host_with_port: via_received,
192 params,
193 ..Default::default()
194 },
195 display_name: None,
196 params: vec![],
197 };
198 debug!(id = %self.id(), "accepting dialog with contact: {}", contact);
199 self.inner
200 .remote_contact
201 .lock()
202 .unwrap()
203 .replace(contact.untyped());
204 self.inner
205 .tu_sender
206 .send(TransactionEvent::Respond(resp.clone()))?;
207
208 self.inner
209 .transition(DialogState::WaitAck(self.id(), resp))?;
210 Ok(())
211 }
212
213 /// Accept the incoming INVITE request with NAT-aware Contact header
214 ///
215 /// Sends a 200 OK response to accept the incoming INVITE request, automatically
216 /// adding a Contact header with the provided public address for proper NAT traversal.
217 /// This is the recommended method when working with NAT environments.
218 ///
219 /// # Parameters
220 ///
221 /// * `username` - SIP username for the Contact header
222 /// * `public_address` - Optional public address discovered via registration
223 /// * `local_address` - Local SIP address as fallback
224 /// * `headers` - Optional additional headers to include
225 /// * `body` - Optional SDP answer body
226 ///
227 /// # Returns
228 ///
229 /// * `Ok(())` - Response sent successfully
230 /// * `Err(Error)` - Failed to send response or transaction terminated
231 ///
232 /// # Examples
233 ///
234 /// ```rust,no_run
235 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
236 /// # use rsipstack::transport::SipAddr;
237 /// # use std::net::{IpAddr, Ipv4Addr};
238 /// # fn example() -> rsipstack::Result<()> {
239 /// # let dialog: ServerInviteDialog = todo!();
240 /// # let local_addr: SipAddr = todo!();
241 /// let public_addr = Some(rsip::HostWithPort {
242 /// host: IpAddr::V4(Ipv4Addr::new(203, 0, 113, 1)).into(),
243 /// port: Some(5060.into()),
244 /// });
245 /// let answer_sdp = b"v=0\r\no=- 123 456 IN IP4 203.0.113.1\r\n...";
246 /// let headers = vec![
247 /// rsip::Header::ContentType("application/sdp".into())
248 /// ];
249 ///
250 /// dialog.accept_with_public_contact(
251 /// "alice",
252 /// public_addr,
253 /// &local_addr,
254 /// Some(headers),
255 /// Some(answer_sdp.to_vec())
256 /// )?;
257 /// # Ok(())
258 /// # }
259 /// ```
260 pub fn accept_with_public_contact(
261 &self,
262 username: &str,
263 public_address: Option<rsip::HostWithPort>,
264 local_address: &crate::transport::SipAddr,
265 headers: Option<Vec<Header>>,
266 body: Option<Vec<u8>>,
267 ) -> Result<()> {
268 use super::registration::Registration;
269
270 // Create NAT-aware Contact header
271 let contact_header =
272 Registration::create_nat_aware_contact(username, public_address, local_address);
273
274 // Combine provided headers with Contact header
275 let mut final_headers = headers.unwrap_or_default();
276 final_headers.push(contact_header.into());
277
278 // Use the regular accept method with the enhanced headers
279 self.accept(Some(final_headers), body)
280 }
281
282 /// Reject the incoming INVITE request
283 ///
284 /// Sends a reject response to reject the incoming INVITE request.
285 /// Sends a 603 Decline by default, or a custom status code if provided.
286 /// This terminates the dialog creation process.
287 ///
288 /// # Returns
289 ///
290 /// * `Ok(())` - Response sent successfully
291 /// * `Err(Error)` - Failed to send response or transaction terminated
292 ///
293 /// # Examples
294 ///
295 /// ```rust,no_run
296 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
297 /// # fn example() -> rsipstack::Result<()> {
298 /// # let dialog: ServerInviteDialog = todo!();
299 /// // Reject the incoming call
300 /// dialog.reject(Some(rsip::StatusCode::BusyHere), Some("Busy here".into()))?;
301 /// # Ok(())
302 /// # }
303 /// ```
304 pub fn reject(&self, code: Option<rsip::StatusCode>, reason: Option<String>) -> Result<()> {
305 if self.inner.is_terminated() || self.inner.is_confirmed() {
306 return Ok(());
307 }
308 info!(id=%self.id(), ?code, ?reason, "rejecting dialog");
309 let headers = if let Some(reason) = reason {
310 Some(vec![rsip::Header::Other("Reason".into(), reason.into())])
311 } else {
312 None
313 };
314 let resp = self.inner.make_response(
315 &self.inner.initial_request,
316 code.unwrap_or(rsip::StatusCode::Decline),
317 headers,
318 None,
319 );
320 self.inner
321 .tu_sender
322 .send(TransactionEvent::Respond(resp))
323 .ok();
324 self.inner.transition(DialogState::Terminated(
325 self.id(),
326 TerminatedReason::UasDecline,
327 ))
328 }
329
330 /// Send a BYE request to terminate the dialog
331 ///
332 /// Sends a BYE request to gracefully terminate an established dialog.
333 /// This should only be called for confirmed dialogs. If the dialog
334 /// is not confirmed, this method returns immediately without error.
335 ///
336 /// # Returns
337 ///
338 /// * `Ok(())` - BYE was sent successfully or dialog not confirmed
339 /// * `Err(Error)` - Failed to send BYE request
340 ///
341 /// # Examples
342 ///
343 /// ```rust,no_run
344 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
345 /// # async fn example() -> rsipstack::Result<()> {
346 /// # let dialog: ServerInviteDialog = todo!();
347 /// // End an established call
348 /// dialog.bye().await?;
349 /// # Ok(())
350 /// # }
351 /// ```
352 pub async fn bye(&self) -> Result<()> {
353 if !self.inner.is_confirmed() {
354 return Ok(());
355 }
356 info!(id=%self.id(), "sending bye request");
357
358 let request = self.inner.make_request_with_vias(
359 rsip::Method::Bye,
360 None,
361 self.inner.build_vias_from_request()?,
362 None,
363 None,
364 )?;
365
366 match self.inner.do_request(request).await {
367 Ok(_) => {}
368 Err(e) => {
369 info!(id=%self.id(),"bye error: {}", e);
370 }
371 };
372 self.inner
373 .transition(DialogState::Terminated(self.id(), TerminatedReason::UasBye))?;
374 Ok(())
375 }
376
377 /// Send a re-INVITE request to modify the session
378 ///
379 /// Sends a re-INVITE request within an established dialog to modify
380 /// the session parameters (e.g., change media, add/remove streams).
381 /// This can only be called for confirmed dialogs.
382 ///
383 /// # Parameters
384 ///
385 /// * `headers` - Optional additional headers to include
386 /// * `body` - Optional message body (typically new SDP)
387 ///
388 /// # Returns
389 ///
390 /// * `Ok(Some(Response))` - Response to the re-INVITE
391 /// * `Ok(None)` - Dialog not confirmed, no request sent
392 /// * `Err(Error)` - Failed to send re-INVITE
393 ///
394 /// # Examples
395 ///
396 /// ```rust,no_run
397 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
398 /// # async fn example() -> rsipstack::Result<()> {
399 /// # let dialog: ServerInviteDialog = todo!();
400 /// let new_sdp = b"v=0\r\no=- 123 456 IN IP4 192.168.1.1\r\n...";
401 /// let response = dialog.reinvite(None, Some(new_sdp.to_vec())).await?;
402 /// # Ok(())
403 /// # }
404 /// ```
405 pub async fn reinvite(
406 &self,
407 headers: Option<Vec<rsip::Header>>,
408 body: Option<Vec<u8>>,
409 ) -> Result<Option<rsip::Response>> {
410 if !self.inner.is_confirmed() {
411 return Ok(None);
412 }
413 info!(id=%self.id(), "sending re-invite request, body: \n{:?}", body);
414 let request = self.inner.make_request_with_vias(
415 rsip::Method::Invite,
416 None,
417 self.inner.build_vias_from_request()?,
418 headers,
419 body,
420 )?;
421 let resp = self.inner.do_request(request.clone()).await;
422 match resp {
423 Ok(Some(ref resp)) => {
424 if resp.status_code == StatusCode::OK {
425 self.inner
426 .transition(DialogState::Updated(self.id(), request))?;
427 }
428 }
429 _ => {}
430 }
431 resp
432 }
433
434 /// Send an UPDATE request to modify session parameters
435 ///
436 /// Sends an UPDATE request within an established dialog to modify
437 /// session parameters without the complexity of a re-INVITE.
438 /// This is typically used for smaller session modifications.
439 ///
440 /// # Parameters
441 ///
442 /// * `headers` - Optional additional headers to include
443 /// * `body` - Optional message body (typically SDP)
444 ///
445 /// # Returns
446 ///
447 /// * `Ok(Some(Response))` - Response to the UPDATE
448 /// * `Ok(None)` - Dialog not confirmed, no request sent
449 /// * `Err(Error)` - Failed to send UPDATE
450 ///
451 /// # Examples
452 ///
453 /// ```rust,no_run
454 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
455 /// # async fn example() -> rsipstack::Result<()> {
456 /// # let dialog: ServerInviteDialog = todo!();
457 /// # let sdp_body = vec![];
458 /// let response = dialog.update(None, Some(sdp_body)).await?;
459 /// # Ok(())
460 /// # }
461 /// ```
462 pub async fn update(
463 &self,
464 headers: Option<Vec<rsip::Header>>,
465 body: Option<Vec<u8>>,
466 ) -> Result<Option<rsip::Response>> {
467 if !self.inner.is_confirmed() {
468 return Ok(None);
469 }
470 info!(id=%self.id(), "sending update request, body: \n{:?}", body);
471 let request = self.inner.make_request_with_vias(
472 rsip::Method::Update,
473 None,
474 self.inner.build_vias_from_request()?,
475 headers,
476 body,
477 )?;
478 self.inner.do_request(request.clone()).await
479 }
480
481 /// Send an INFO request for mid-dialog information
482 ///
483 /// Sends an INFO request within an established dialog to exchange
484 /// application-level information. This is commonly used for DTMF
485 /// tones, but can carry any application-specific data.
486 ///
487 /// # Parameters
488 ///
489 /// * `headers` - Optional additional headers to include
490 /// * `body` - Optional message body (application-specific data)
491 ///
492 /// # Returns
493 ///
494 /// * `Ok(Some(Response))` - Response to the INFO
495 /// * `Ok(None)` - Dialog not confirmed, no request sent
496 /// * `Err(Error)` - Failed to send INFO
497 ///
498 /// # Examples
499 ///
500 /// ```rust,no_run
501 /// # use rsipstack::dialog::server_dialog::ServerInviteDialog;
502 /// # async fn example() -> rsipstack::Result<()> {
503 /// # let dialog: ServerInviteDialog = todo!();
504 /// // Send DTMF tone
505 /// let dtmf_body = b"Signal=1\r\nDuration=100\r\n";
506 /// let headers = vec![
507 /// rsip::Header::ContentType("application/dtmf-relay".into())
508 /// ];
509 /// let response = dialog.info(Some(headers), Some(dtmf_body.to_vec())).await?;
510 /// # Ok(())
511 /// # }
512 /// ```
513 pub async fn info(
514 &self,
515 headers: Option<Vec<rsip::Header>>,
516 body: Option<Vec<u8>>,
517 ) -> Result<Option<rsip::Response>> {
518 if !self.inner.is_confirmed() {
519 return Ok(None);
520 }
521 info!(id=%self.id(), "sending info request, body: \n{:?}", body);
522 let request = self.inner.make_request_with_vias(
523 rsip::Method::Info,
524 None,
525 self.inner.build_vias_from_request()?,
526 headers,
527 body,
528 )?;
529 self.inner.do_request(request.clone()).await
530 }
531
532 /// Handle incoming transaction for this dialog
533 ///
534 /// Processes incoming SIP requests that are routed to this dialog.
535 /// This method handles sequence number validation and dispatches
536 /// to appropriate handlers based on the request method and dialog state.
537 ///
538 /// # Parameters
539 ///
540 /// * `tx` - The incoming transaction to handle
541 ///
542 /// # Returns
543 ///
544 /// * `Ok(())` - Request handled successfully
545 /// * `Err(Error)` - Failed to handle request
546 ///
547 /// # Supported Methods
548 ///
549 /// * `ACK` - Confirms 2xx response (transitions to Confirmed state)
550 /// * `BYE` - Terminates the dialog
551 /// * `INFO` - Handles information exchange
552 /// * `OPTIONS` - Handles capability queries
553 /// * `UPDATE` - Handles session updates
554 /// * `INVITE` - Handles initial INVITE or re-INVITE
555 pub async fn handle(&mut self, tx: &mut Transaction) -> Result<()> {
556 debug!(
557 id = %self.id(),
558 "handle request: {} state:{}",
559 tx.original,
560 self.inner.state.lock().unwrap()
561 );
562
563 let cseq = tx.original.cseq_header()?.seq()?;
564 let remote_seq = self.inner.remote_seq.load(Ordering::Relaxed);
565 if remote_seq > 0 && cseq < remote_seq {
566 info!(
567 id=%self.id(),
568 "received old request {} remote_seq: {} > {}",
569 tx.original.method(),
570 remote_seq,
571 cseq
572 );
573 // discard old request
574 return Ok(());
575 }
576
577 self.inner
578 .remote_seq
579 .compare_exchange(remote_seq, cseq, Ordering::Relaxed, Ordering::Relaxed)
580 .ok();
581
582 if self.inner.is_confirmed() {
583 match tx.original.method {
584 rsip::Method::Cancel => {
585 info!(id=%self.id(),
586 "invalid request received {} {}",
587 tx.original.method, tx.original.uri
588 );
589 tx.reply(rsip::StatusCode::OK).await?;
590 return Ok(());
591 }
592 rsip::Method::Invite | rsip::Method::Ack => {
593 info!(id=%self.id(),
594 "invalid request received {} {}",
595 tx.original.method, tx.original.uri
596 );
597 return Err(crate::Error::DialogError(
598 "invalid request in confirmed state".to_string(),
599 self.id(),
600 rsip::StatusCode::MethodNotAllowed,
601 ));
602 }
603 rsip::Method::Bye => return self.handle_bye(tx).await,
604 rsip::Method::Info => return self.handle_info(tx).await,
605 rsip::Method::Options => return self.handle_options(tx).await,
606 rsip::Method::Update => return self.handle_update(tx).await,
607 _ => {
608 info!(id=%self.id(),"invalid request method: {:?}", tx.original.method);
609 tx.reply(rsip::StatusCode::MethodNotAllowed).await?;
610 return Err(crate::Error::DialogError(
611 "invalid request".to_string(),
612 self.id(),
613 rsip::StatusCode::MethodNotAllowed,
614 ));
615 }
616 }
617 } else {
618 match tx.original.method {
619 rsip::Method::Ack => {
620 self.inner.tu_sender.send(TransactionEvent::Received(
621 tx.original.clone().into(),
622 tx.connection.clone(),
623 ))?;
624 }
625 _ => {}
626 }
627 }
628 self.handle_invite(tx).await
629 }
630
631 async fn handle_bye(&mut self, tx: &mut Transaction) -> Result<()> {
632 info!(id = %self.id(), "received bye {}", tx.original.uri);
633 self.inner
634 .transition(DialogState::Terminated(self.id(), TerminatedReason::UacBye))?;
635 tx.reply(rsip::StatusCode::OK).await?;
636 Ok(())
637 }
638
639 async fn handle_info(&mut self, tx: &mut Transaction) -> Result<()> {
640 info!(id = %self.id(), "received info {}", tx.original.uri);
641 self.inner
642 .transition(DialogState::Info(self.id(), tx.original.clone()))?;
643 tx.reply(rsip::StatusCode::OK).await?;
644 Ok(())
645 }
646
647 async fn handle_options(&mut self, tx: &mut Transaction) -> Result<()> {
648 info!(id = %self.id(), "received options {}", tx.original.uri);
649 self.inner
650 .transition(DialogState::Options(self.id(), tx.original.clone()))?;
651 tx.reply(rsip::StatusCode::OK).await?;
652 Ok(())
653 }
654
655 async fn handle_update(&mut self, tx: &mut Transaction) -> Result<()> {
656 info!(id = %self.id(), "received update {}", tx.original.uri);
657 self.inner
658 .transition(DialogState::Updated(self.id(), tx.original.clone()))?;
659 tx.reply(rsip::StatusCode::OK).await?;
660 Ok(())
661 }
662
663 async fn handle_invite(&mut self, tx: &mut Transaction) -> Result<()> {
664 let handle_loop = async {
665 if !self.inner.is_confirmed() && matches!(tx.original.method, rsip::Method::Invite) {
666 match self.inner.transition(DialogState::Calling(self.id())) {
667 Ok(_) => {
668 tx.send_trying().await.ok();
669 }
670 Err(_) => {}
671 }
672 }
673
674 while let Some(msg) = tx.receive().await {
675 match msg {
676 SipMessage::Request(req) => match req.method {
677 rsip::Method::Ack => {
678 if self.inner.is_terminated() {
679 // dialog already terminated, ignore
680 break;
681 }
682 info!(id = %self.id(),"received ack {}", req.uri);
683 match req.contact_header() {
684 Ok(contact) => {
685 self.inner
686 .remote_contact
687 .lock()
688 .unwrap()
689 .replace(contact.clone());
690 }
691 _ => {}
692 }
693
694 self.inner.transition(DialogState::Confirmed(
695 self.id(),
696 tx.last_response.clone().unwrap_or_default(),
697 ))?;
698 DialogInner::serve_keepalive_options(self.inner.clone());
699 break;
700 }
701 rsip::Method::Cancel => {
702 info!(id = %self.id(),"received cancel {}", req.uri);
703 tx.reply(rsip::StatusCode::RequestTerminated).await?;
704 self.inner.transition(DialogState::Terminated(
705 self.id(),
706 TerminatedReason::UacCancel,
707 ))?;
708 }
709 _ => {}
710 },
711 SipMessage::Response(_) => {}
712 }
713 }
714 Ok::<(), crate::Error>(())
715 };
716 match handle_loop.await {
717 Ok(_) => {
718 trace!(id = %self.id(),"process done");
719 Ok(())
720 }
721 Err(e) => {
722 warn!(id = %self.id(),"handle_invite error: {:?}", e);
723 Err(e)
724 }
725 }
726 }
727}
728
729impl TryFrom<&Dialog> for ServerInviteDialog {
730 type Error = crate::Error;
731
732 fn try_from(dlg: &Dialog) -> Result<Self> {
733 match dlg {
734 Dialog::ServerInvite(dlg) => Ok(dlg.clone()),
735 _ => Err(crate::Error::DialogError(
736 "Dialog is not a ServerInviteDialog".to_string(),
737 dlg.id(),
738 rsip::StatusCode::BadRequest,
739 )),
740 }
741 }
742}