Skip to main content

ringo_core/
backend.rs

1use std::sync::mpsc::Receiver;
2
3use anyhow::Result;
4
5use crate::account::{Account, BackendOptions};
6use crate::event::{AppEvent, InviteHeaders};
7use crate::phone::Phone;
8
9pub use crate::baresip::BaresipBackend;
10pub use crate::baresip::call_count;
11pub use crate::baresip::is_registered;
12pub use crate::baresip::received_audio;
13pub use crate::baresip::sent_audio;
14pub use crate::baresip::{sip_trace_file, sip_trace_stderr};
15
16/// Shut down the backend's global runtime: hang up calls, tear down the user
17/// agents, stop the event loop and join its thread. Call once at process exit;
18/// a no-op if the backend was never started. Agnostic façade over the concrete
19/// backend's teardown (the FFI backend stops its libre event thread here).
20pub fn shutdown() {
21    crate::baresip::stop_re_thread();
22}
23
24/// A backend provides SIP user-agent functionality — library init, event
25/// translation and the phone command interface. The FFI backend links
26/// libbaresip directly (statically with `vendored`, or dynamically via
27/// pkg-config).
28pub trait Backend: Send {
29    /// Spawn the backend (process or library), start I/O tasks on `rt`, and
30    /// return a [`Session`] handle. The session owns the event stream, phone
31    /// command interface, and optional header-polling closure. Connect retry
32    /// happens internally; `AppEvent::BackendConnectFailed` lands in the event
33    /// stream on failure.
34    fn spawn_session(
35        &self,
36        rt: &tokio::runtime::Handle,
37        name: &str,
38        account: &Account,
39        options: &BackendOptions,
40    ) -> Result<Session>;
41}
42
43/// A live backend session. Dropping this tears down the backend (stops the
44/// process / closes the library) and cleans up resources.
45pub struct Session {
46    /// Event stream (already translated to backend-neutral `AppEvent`s).
47    pub events: Receiver<AppEvent>,
48    /// Phone command interface.
49    pub phone: Box<dyn Phone>,
50    /// Poll for inbound INVITE headers. Returns `None` when there is nothing
51    /// new; `Some(headers)` when new headers have been parsed. `None` on the
52    /// closure itself means the backend exposes headers directly in events
53    /// (no trace polling needed).
54    pub header_poll: Option<Box<dyn Fn() -> Option<InviteHeaders> + Send + Sync>>,
55    /// Opaque handle — drop ends the backend session + cleanup.
56    pub handle: Box<dyn Send>,
57}
58
59impl Session {
60    pub fn new(
61        events: Receiver<AppEvent>,
62        phone: Box<dyn Phone>,
63        header_poll: Option<Box<dyn Fn() -> Option<InviteHeaders> + Send + Sync>>,
64        handle: Box<dyn Send>,
65    ) -> Self {
66        Self {
67            events,
68            phone,
69            header_poll,
70            handle,
71        }
72    }
73}