1use std::ffi::CString;
2use std::io::ErrorKind;
3
4use crate::session::Session;
5use crate::types::*;
6use freeswitch_sys::switch_loadable_module_create_interface;
7
8#[repr(transparent)]
9pub struct StreamHandle(pub *mut switch_stream_handle_t);
10
11impl std::io::Write for StreamHandle {
12 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
13 unsafe {
14 if self.0.is_null() {
15 return std::io::Result::Err(std::io::Error::new(
16 ErrorKind::Other,
17 "No FSStream writer",
18 ));
19 }
20 if let Some(w) = (*self.0).write_function {
21 let cs = CString::new(buf)
22 .map_err(|_| std::io::Error::new(ErrorKind::InvalidData, ""))?;
23 let res = (w)(self.0, cs.as_ptr());
26 if res == switch_status_t::SWITCH_STATUS_SUCCESS {
27 Ok(buf.len())
28 } else {
29 std::io::Result::Err(std::io::Error::new(
30 ErrorKind::Other,
31 "FSStream writer Error",
32 ))
33 }
34 } else {
35 std::io::Result::Err(std::io::Error::new(ErrorKind::Other, "No FSStream writer"))
36 }
37 }
38 }
39
40 fn flush(&mut self) -> std::io::Result<()> {
41 Ok(())
42 }
43}
44
45pub trait LoadableModule {
50 fn load(module: FSModuleInterface, pool: FSModulePool) -> switch_status_t;
51 fn shutdown() -> switch_status_t {
52 switch_status_t::SWITCH_STATUS_SUCCESS
53 }
54 fn runtime() -> switch_status_t {
55 switch_status_t::SWITCH_STATUS_TERM
56 }
57}
58
59#[repr(transparent)]
61pub struct FSModuleInterface(pub *mut *mut switch_loadable_module_interface_t);
62
63#[repr(transparent)]
64pub struct FSModulePool(pub *mut switch_memory_pool_t);
65
66impl FSModuleInterface {
67 pub unsafe fn create(
69 name: &str,
70 pool: *mut switch_memory_pool_t,
71 ) -> *mut switch_loadable_module_interface_t {
72 let mod_name = CString::new(name.to_owned()).unwrap().into_raw();
73 freeswitch_sys::switch_loadable_module_create_module_interface(pool, mod_name)
74 }
75
76 pub fn add_api<T: ApiInterface>(&self, _i: T) {
78 let t = switch_module_interface_name_t::SWITCH_API_INTERFACE;
79 unsafe {
82 let ptr =
83 switch_loadable_module_create_interface(*self.0, t) as *mut switch_api_interface_t;
84 let interface = &mut *ptr;
85 interface.interface_name = CString::new(T::NAME).unwrap().into_raw();
86 interface.desc = CString::new(T::DESC).unwrap().into_raw();
87 interface.function = Some(T::api_fn_raw);
88 }
89 }
90}
91
92pub trait ApiInterface {
93 const NAME: &'static str;
94 const DESC: &'static str;
95 fn api_fn(
96 cmd: &str,
97 session: Option<&Session>,
98 stream: StreamHandle,
99 ) -> freeswitch_sys::switch_status_t;
100 unsafe extern "C" fn api_fn_raw(
101 cmd: *const ::std::os::raw::c_char,
102 session: *mut freeswitch_sys::switch_core_session_t,
103 stream: *mut freeswitch_sys::switch_stream_handle_t,
104 ) -> freeswitch_sys::switch_status_t;
105}