freeswitchrs/
mods.rs

1use super::*;
2use super::raw as fsr;
3use std::ffi::CString;
4use super::raw::module_interface_name as IntName;
5use std::os::raw::c_char;
6
7pub enum Stream { } // Temp until wrap stream
8pub type ApiFunc = fn(String, Option<&CoreSession>, Stream);
9pub type ApiRawFunc = unsafe extern "C" fn(cmd: *const c_char,
10                                           session: *mut fsr::core_session,
11                                           stream: *mut fsr::stream_handle)
12                                           -> fsr::status;
13
14pub struct ModInterface(*mut fsr::loadable_module_interface);
15impl ModInterface {
16    gen_from_ptr!(fsr::loadable_module_interface, ModInterface, ModInterface);
17
18    unsafe fn create_int(&self, iname: IntName) -> *mut ::std::os::raw::c_void {
19        fsr::loadable_module_create_interface((*self).0, iname)
20    }
21
22    pub fn add_raw_api(&self, name: &str, desc: &str, syntax: &str, func: ApiRawFunc) {
23        let name = fsr::str_to_ptr(name);
24        let desc = fsr::str_to_ptr(desc);
25        let syntax = fsr::str_to_ptr(syntax);
26        unsafe {
27            let ai = self.create_int(IntName::API_INTERFACE) as *mut fsr::api_interface;
28            ptr_not_null!(ai);
29            (*ai).interface_name = name;
30            (*ai).desc = desc;
31            (*ai).syntax = syntax;
32            (*ai).function = Some(func);
33        }
34    }
35
36    // Doing safe versions is a pain. Macros are ugly. Need to use libffi or similar
37    // to dynamically create thunks that'll wrap the safe functions.
38    // fn add_api(&mut self, name: &str, desc: &str, syntax: &str, func: ApiFunc) {
39    //     self.add_raw_api(name, desc, syntax, TODO_ALLOC_TRAMPOLINE(func));
40    // }
41}
42
43// Module Loading/Definition
44
45pub struct ModDefinition {
46    pub name: &'static str,
47    pub load: fn(&ModInterface) -> Status,
48    pub shutdown: Option<fn() -> Status>,
49    pub runtime: Option<fn() -> Status>,
50}
51
52pub unsafe fn wrap_mod_load(mod_def: &ModDefinition,
53                            mod_int: *mut *mut fsr::loadable_module_interface,
54                            mem_pool: *mut fsr::memory_pool)
55                            -> fsr::status {
56    // Name should be a constant [u8], but we'd need some macro or something
57    // to ensure null termination. Leaking the name here shouldn't matter.
58    // CString's into_raw pointer is not free()'able fwiw
59    let name = CString::new(mod_def.name).unwrap().into_raw();
60    *mod_int = fsr::loadable_module_create_module_interface(mem_pool, name);
61    if (*mod_int).is_null() {
62        return fsr::status::MEMERR;
63    }
64    let mi = &ModInterface::from_ptr(*mod_int);
65    (mod_def.load)(mi).to_raw()
66}
67// Want to end up with
68// unsafe mod_skelr_load( raw shit ) { wrap_mod_load(...) }
69#[macro_export]
70macro_rules! freeswitch_export_mod {
71    ($table:ident, $def:ident) => (
72#[no_mangle]
73pub unsafe extern "C" fn _mod_load(mod_int: *mut *mut fsr::loadable_module_interface,
74                                        mem_pool: *mut fsr::memory_pool)
75                                        -> fsr::status {
76    wrap_mod_load(&$def, mod_int, mem_pool)
77}
78#[no_mangle]
79#[allow(non_upper_case_globals)]
80pub static $table: fsr::loadable_module_function_table =
81    fsr::loadable_module_function_table {
82        api_version: 5,
83        load: Some(_mod_load),
84        shutdown: None,
85        runtime: None,
86        flags: fsr::module_flag_enum::NONE as u32,
87    };
88);}