ftth_rsipstack/dialog/
server_dialog.rs

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