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}