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