gpt4 book ai didi

FreeSWITCH添加自定义endpoint

转载 作者:我是一只小鸟 更新时间:2023-05-28 14:33:19 31 4
gpt4 key购买 nike

操作系统 :CentOS 7.6_x64     
FreeSWITCH版本 :1.10.9
 
日常开发过程中会遇到需要扩展FreeSWITCH对接其它系统的情况,这里记录下编写FreeSWITCH自定义endpoint的过程。

1、模块定义函数

使用FreeSWITCH自带的框架来定义模块函数,函数指针及参数列表定义如下(src/include/switch_types.h)
                  
                    #define
                  
                   SWITCH_MODULE_LOAD_ARGS (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)

                  
                    #define
                  
                   SWITCH_MODULE_RUNTIME_ARGS (void)

                  
                    #define
                  
                   SWITCH_MODULE_SHUTDOWN_ARGS (void)
                  
                    
typedef switch_status_t (
                  
                  *
                  
                    switch_module_load_t) SWITCH_MODULE_LOAD_ARGS;
typedef switch_status_t (
                  
                  *
                  
                    switch_module_runtime_t) SWITCH_MODULE_RUNTIME_ARGS;
typedef switch_status_t (
                  
                  *
                  
                    switch_module_shutdown_t) SWITCH_MODULE_SHUTDOWN_ARGS;

                  
                  
                    #define
                  
                   SWITCH_MODULE_LOAD_FUNCTION(name) switch_status_t name SWITCH_MODULE_LOAD_ARGS

                  
                    #define
                  
                   SWITCH_MODULE_RUNTIME_FUNCTION(name) switch_status_t name SWITCH_MODULE_RUNTIME_ARGS

                  
                    #define
                  
                   SWITCH_MODULE_SHUTDOWN_FUNCTION(name) switch_status_t name SWITCH_MODULE_SHUTDOWN_ARGS
                
 

1、模块加载

SWITCH_MODULE_LOAD_FUNCTION
模块加载函数,负责系统启动时或运行时加载模块,可以进行配置读取及资源初始化。

2、模块卸载

SWITCH_MODULE_SHUTDOWN_FUNCTION
模块卸载函数,负载模块卸载及相关资源回收。

3、模块运行时

SWITCH_MODULE_RUNTIME_FUNCTION
模块运行时函数,可以启动线程处理请求,监听socket等。

4、模块定义

SWITCH_MODULE_DEFINITION
相关代码:
                    typedef 
                    
                      struct
                    
                    
                       switch_loadable_module_function_table {
    
                    
                    
                      int
                    
                    
                       switch_api_version;
    switch_module_load_t load;
    switch_module_shutdown_t shutdown;
    switch_module_runtime_t runtime;
    switch_module_flag_t flags;
} switch_loadable_module_function_table_t;


                    
                    
                      #define
                    
                     SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags)                   \

                    
                      static
                    
                    
                      const
                    
                    
                      char
                    
                     modname[] =
                    
                        #name ;                                                      \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface 
                    
                    =
                    
                       { \
    SWITCH_API_VERSION,                                                                     \
    load,                                                                                   \
    shutdown,                                                                               \
    runtime,                                                                                \
    flags                                                                                   \
}


                    
                    
                      #define
                    
                     SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)                             \
                    
                      
        SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, SMODF_NONE)
                    
                     
                  

2、模块加载流程

FreeSWITCH使用 switch_loadable_module_load_module 或 switch_loadable_module_load_module_ex 进行模块加载,具体实现逻辑可以在 switch_loadable_module.c 中查看,这里做下简单介绍。 

1、模块加载函数

通过 switch_loadable_module_load_module 函数加载模块,函数调用链如下:
                      
                        switch_loadable_module_load_module 
        
                      
                      =>
                      
                         switch_loadable_module_load_module_ex  
        
                      
                      =>
                      
                         switch_loadable_module_load_file
            
                      
                      =>
                      
                         switch_loadable_module_process
            
                      
                      => switch_core_launch_thread  =>  switch_loadable_module_exec
                    
通过 switch_dso_data_sym 根据定义的 XXX_module_interface 从动态库里面获取回调函数指针,使用 switch_loadable_module_function_table_t 数据结构进行回调函数绑定。
switch_dso_data_sym 函数实现如下(src/switch_dso.c):
                        
                          void
                        
                         *switch_dso_data_sym(switch_dso_lib_t lib, 
                        
                          const
                        
                        
                          char
                        
                         *sym, 
                        
                          char
                        
                         **
                        
                          err)
{
    
                        
                        
                          void
                        
                         *addr =
                        
                           dlsym(lib, sym);
    
                        
                        
                          if
                        
                         (!
                        
                          addr) {
        
                        
                        
                          char
                        
                         *err_str =
                        
                           NULL;
        dlerror();

        
                        
                        
                          if
                        
                         (!(addr =
                        
                           dlsym(lib, sym))) {
            err_str 
                        
                        = (
                        
                          char
                        
                         *
                        
                          )dlerror();
        }

        
                        
                        
                          if
                        
                        
                           (err_str) {
            
                        
                        *err =
                        
                           strdup(err_str);
        }
    }
    
                        
                        
                          return
                        
                        
                           addr;
}
                        
                      
switch_loadable_module_exec函数:
                          
                            static
                          
                          
                            void
                          
                           *SWITCH_THREAD_FUNC switch_loadable_module_exec(switch_thread_t *thread, 
                          
                            void
                          
                           *
                          
                            obj)
{


    switch_status_t status 
                          
                          =
                          
                             SWITCH_STATUS_SUCCESS;
    switch_core_thread_session_t 
                          
                          *ts =
                          
                             obj;
    switch_loadable_module_t 
                          
                          *module = ts->objs[
                          
                            0
                          
                          
                            ];
    
                          
                          
                            int
                          
                          
                             restarts;

    switch_assert(thread 
                          
                          !=
                          
                             NULL);
    switch_assert(module 
                          
                          !=
                          
                             NULL);

    
                          
                          
                            for
                          
                           (restarts = 
                          
                            0
                          
                          ; status != SWITCH_STATUS_TERM && !module->shutting_down; restarts++
                          
                            ) {
        status 
                          
                          = module->
                          
                            switch_module_runtime();
    }
    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, 
                          
                          
                            "
                          
                          
                            Thread ended for %s\n
                          
                          
                            "
                          
                          , module->module_interface->
                          
                            module_name);

    
                          
                          
                            if
                          
                           (ts->
                          
                            pool) {
        switch_memory_pool_t 
                          
                          *pool = ts->
                          
                            pool;
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, 
                          
                          
                            "
                          
                          
                            Destroying Pool for %s\n
                          
                          
                            "
                          
                          , module->module_interface->
                          
                            module_name);
        switch_core_destroy_memory_pool(
                          
                          &
                          
                            pool);
    }
    switch_thread_exit(thread, 
                          
                          
                            0
                          
                          
                            );
    
                          
                          
                            return
                          
                          
                             NULL;
}
                          
                        
switch_loadable_module_exec 函数为独立线程中运行,模块运行时通过 module->switch_module_runtime() 触发。

2、FreeSWITCH启动时加载模块

1)整体结构

 函数调用链如下:

                          
                            main 
    
                          
                          =>
                          
                             switch_core_init_and_modload 
        
                          
                          =>
                          
                             switch_core_init
        
                          
                          => switch_loadable_module_init => switch_loadable_module_load_module
                        
main函数在switch.c中实现。 
 
2)加载顺序
先加载系统核心模块:
                            switch_loadable_module_load_module_ex(
                            
                              ""
                            
                            , 
                            
                              "
                            
                            
                              CORE_SOFTTIMER_MODULE
                            
                            
                              "
                            
                            , SWITCH_FALSE, SWITCH_FALSE, &
                            
                              err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
switch_loadable_module_load_module_ex(
                            
                            
                              ""
                            
                            , 
                            
                              "
                            
                            
                              CORE_PCM_MODULE
                            
                            
                              "
                            
                            , SWITCH_FALSE, SWITCH_FALSE, &
                            
                              err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
switch_loadable_module_load_module_ex(
                            
                            
                              ""
                            
                            , 
                            
                              "
                            
                            
                              CORE_SPEEX_MODULE
                            
                            
                              "
                            
                            , SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
                          
使用 switch_xml_open_cfg 函数(src/switch_xml.c中定义)先后加载以下文件中定义的模块:
pre_load_modules.conf
modules.conf
post_load_modules.conf
具体格式参考 conf/autoload_configs/modules.conf.xml
 
3)xml加载过程
 函数调用链如下:
                              main =>
                              
                                 switch_core_init_and_modload 
        
                              
                              =>
                              
                                 switch_core_init 
            
                              
                              =>
                              
                                 switch_xml_init 
                
                              
                              => switch_xml_open_root => XML_OPEN_ROOT_FUNCTION
                            
其中 SWITCH_GLOBAL_filenames 变量定义如下(main => switch_core_set_globals):
                                
                                  if
                                
                                 (!SWITCH_GLOBAL_filenames.conf_name && (SWITCH_GLOBAL_filenames.conf_name = (
                                
                                  char
                                
                                 *) 
                                
                                  malloc
                                
                                
                                  (BUFSIZE))) {
        switch_snprintf(SWITCH_GLOBAL_filenames.conf_name, BUFSIZE, 
                                
                                
                                  "
                                
                                
                                  %s
                                
                                
                                  "
                                
                                , 
                                
                                  "
                                
                                
                                  freeswitch.xml
                                
                                
                                  "
                                
                                
                                  );
}
                                
                              
XML_OPEN_ROOT_FUNCTION实现如下(src/switch_xml.c):
                                  
                                    static
                                  
                                   switch_xml_open_root_function_t XML_OPEN_ROOT_FUNCTION =
                                  
                                     (switch_xml_open_root_function_t)__switch_xml_open_root;

SWITCH_DECLARE_NONSTD(switch_xml_t) __switch_xml_open_root(uint8_t reload, 
                                  
                                  
                                    const
                                  
                                  
                                    char
                                  
                                   **err, 
                                  
                                    void
                                  
                                   *
                                  
                                    user_data)
{
    
                                  
                                  
                                    char
                                  
                                   path_buf[
                                  
                                    1024
                                  
                                  
                                    ];
    uint8_t errcnt 
                                  
                                  = 
                                  
                                    0
                                  
                                  
                                    ;
    switch_xml_t new_main, r 
                                  
                                  =
                                  
                                     NULL;

    
                                  
                                  
                                    if
                                  
                                  
                                     (MAIN_XML_ROOT) {
        
                                  
                                  
                                    if
                                  
                                   (!
                                  
                                    reload) {
            r 
                                  
                                  =
                                  
                                     switch_xml_root();
            
                                  
                                  
                                    goto
                                  
                                  
                                     done;
        }
    }

    switch_snprintf(path_buf, 
                                  
                                  
                                    sizeof
                                  
                                  (path_buf), 
                                  
                                    "
                                  
                                  
                                    %s%s%s
                                  
                                  
                                    "
                                  
                                  
                                    , SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, SWITCH_GLOBAL_filenames.conf_name);
    
                                  
                                  
                                    if
                                  
                                   ((new_main =
                                  
                                     switch_xml_parse_file(path_buf))) {
        
                                  
                                  *err =
                                  
                                     switch_xml_error(new_main);
        switch_copy_string(not_so_threadsafe_error_buffer, 
                                  
                                  *err, 
                                  
                                    sizeof
                                  
                                  
                                    (not_so_threadsafe_error_buffer));
        
                                  
                                  *err =
                                  
                                     not_so_threadsafe_error_buffer;
        
                                  
                                  
                                    if
                                  
                                   (!zstr(*
                                  
                                    err)) {
            switch_xml_free(new_main);
            new_main 
                                  
                                  =
                                  
                                     NULL;
            errcnt
                                  
                                  ++
                                  
                                    ;
        } 
                                  
                                  
                                    else
                                  
                                  
                                     {
            
                                  
                                  *err = 
                                  
                                    "
                                  
                                  
                                    Success
                                  
                                  
                                    "
                                  
                                  
                                    ;
            switch_xml_set_root(new_main);

        }
    } 
                                  
                                  
                                    else
                                  
                                  
                                     {
        
                                  
                                  *err = 
                                  
                                    "
                                  
                                  
                                    Cannot Open log directory or XML Root!
                                  
                                  
                                    "
                                  
                                  
                                    ;
        errcnt
                                  
                                  ++
                                  
                                    ;
    }

    
                                  
                                  
                                    if
                                  
                                   (errcnt == 
                                  
                                    0
                                  
                                  
                                    ) {
        r 
                                  
                                  =
                                  
                                     switch_xml_root();
    }

 done:

    
                                  
                                  
                                    return
                                  
                                  
                                     r;
}
                                  
                                
freeswitch.xml 为xml文件的总入口,配置的有加载各个模块的数据:
                                    
                                      <
                                    
                                    
                                      section 
                                    
                                    
                                      name
                                    
                                    
                                      ="configuration"
                                    
                                    
                                       description
                                    
                                    
                                      ="Various Configuration"
                                    
                                    
                                      >
                                    
                                    
                                      <
                                    
                                    
                                      X-PRE-PROCESS 
                                    
                                    
                                      cmd
                                    
                                    
                                      ="include"
                                    
                                    
                                       data
                                    
                                    
                                      ="autoload_configs/*.xml"
                                    
                                    
                                      />
                                    
                                    
                                      </
                                    
                                    
                                      section
                                    
                                    
                                      >
                                    
                                  

3、控制台动态加载

在fs_cli中可以使用load及reload加载模块,具体流程如下:
                                      
                                        fs_cli => load ... => SWITCH_STANDARD_API(load_function) => switch_loadable_module_load_module 

fs_cli => reload ... => SWITCH_STANDARD_API(reload_function) => switch_loadable_module_unload_module 
                                                             => switch_loadable_module_load_module
                                      
                                    

3、关键数据结构

1、switch_loadable_module_t

作用:用于定义模块信息。
结构体定义:
                                        
                                          struct
                                        
                                        
                                           switch_loadable_module {
    
                                        
                                        
                                          char
                                        
                                         *
                                        
                                          key;
    
                                        
                                        
                                          char
                                        
                                         *
                                        
                                          filename;
    
                                        
                                        
                                          int
                                        
                                        
                                           perm;
    switch_loadable_module_interface_t 
                                        
                                        *
                                        
                                          module_interface;
    switch_dso_lib_t lib;
    switch_module_load_t switch_module_load;
    switch_module_runtime_t switch_module_runtime;
    switch_module_shutdown_t switch_module_shutdown;
    switch_memory_pool_t 
                                        
                                        *
                                        
                                          pool;
    switch_status_t status;
    switch_thread_t 
                                        
                                        *
                                        
                                          thread;
    switch_bool_t shutting_down;
    switch_loadable_module_type_t type;
};

typedef 
                                        
                                        
                                          struct
                                        
                                         switch_loadable_module switch_loadable_module_t;
                                      
字段解释:
key =》 模块文件名称
filename => 模块文件路径(动态库路径)
perm =》 定义模块是否允许被卸载
module_interface =》 模块接口(由switch_module_load函数赋值)
lib =》 动态库句柄(dlopen函数返回)
switch_module_load =》 模块加载函数
switch_module_runtime =》 模块运行时函数
switch_module_shutdown =》 模块关闭(卸载)函数
pool =》 模块内存池
status =》 switch_module_shutdown 函数的返回值
shutting_down => 模块是否关闭

2、switch_loadable_module_interface

作用: 模块接口(入口)
结构体定义:
                                          
                                            struct
                                          
                                          
                                             switch_loadable_module_interface {
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the name of the module 
                                          
                                          
                                            */
                                          
                                          
                                            const
                                          
                                          
                                            char
                                          
                                           *
                                          
                                            module_name;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of endpoints the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_endpoint_interface_t 
                                          
                                          *
                                          
                                            endpoint_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of timers the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_timer_interface_t 
                                          
                                          *
                                          
                                            timer_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of dialplans the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_dialplan_interface_t 
                                          
                                          *
                                          
                                            dialplan_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of codecs the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_codec_interface_t 
                                          
                                          *
                                          
                                            codec_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of applications the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_application_interface_t 
                                          
                                          *
                                          
                                            application_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of chat applications the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_chat_application_interface_t 
                                          
                                          *
                                          
                                            chat_application_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of api functions the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_api_interface_t 
                                          
                                          *
                                          
                                            api_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of json api functions the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_json_api_interface_t 
                                          
                                          *
                                          
                                            json_api_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of file formats the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_file_interface_t 
                                          
                                          *
                                          
                                            file_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of speech interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_speech_interface_t 
                                          
                                          *
                                          
                                            speech_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of directory interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_directory_interface_t 
                                          
                                          *
                                          
                                            directory_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of chat interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_chat_interface_t 
                                          
                                          *
                                          
                                            chat_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of say interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_say_interface_t 
                                          
                                          *
                                          
                                            say_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of asr interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_asr_interface_t 
                                          
                                          *
                                          
                                            asr_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of management interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_management_interface_t 
                                          
                                          *
                                          
                                            management_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of limit interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_limit_interface_t 
                                          
                                          *
                                          
                                            limit_interface;
    
                                          
                                          
                                            /*
                                          
                                          
                                            ! the table of database interfaces the module has implemented 
                                          
                                          
                                            */
                                          
                                          
                                            
    switch_database_interface_t 
                                          
                                          *
                                          
                                            database_interface;
    switch_thread_rwlock_t 
                                          
                                          *
                                          
                                            rwlock;
    
                                          
                                          
                                            int
                                          
                                          
                                             refs;
    switch_memory_pool_t 
                                          
                                          *
                                          
                                            pool;
};

typedef 
                                          
                                          
                                            struct
                                          
                                           switch_loadable_module_interface switch_loadable_module_interface_t;
                                        
字段解释:
module_name => 模块的名称
endpoint_interface => 模块endpoint的具体实现
timer_interface => 模块timer的具体实现
dialplan_interface => 模块dialplan的具体实现
codec_interface => 模块编解码的具体实现
application_interface => 模块提供的app工具的具体实现
chat_application_interface => 模块提供的文本聊天app工具的具体实现
api_interface => 模块提供的api具体实现
json_api_interface => 模块提供的json格式api的具体实现
file_interface => 模块支持的文件格式的具体实现(比如mp4、mkv等文件格式)
speech_interface => 模块使用的speech接口实现
directory_interface => 模块使用的directory接口实现
chat_interface => 模块使用的chat接口实现
say_interface => 模块使用的say接口实现
asr_interface => 模块使用的asr接口实现
management_interface => 模块使用的管理接口实现
limit_interface => 模块使用的limit接口实现
database_interface => 模块使用的limit接口实现
rwlock => 模块使用的锁
refs => 模块锁的计数器
pool =》 模块内存池
使用 switch_loadable_module_create_module_interface 来创建 switch_loadable_module_interface_t 实例。
                              SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, 
                              
                                const
                              
                              
                                char
                              
                               *
                              
                                name)
{
    switch_loadable_module_interface_t 
                              
                              *
                              
                                mod;

    mod 
                              
                              = switch_core_alloc(pool, 
                              
                                sizeof
                              
                              
                                (switch_loadable_module_interface_t));
    switch_assert(mod 
                              
                              !=
                              
                                 NULL);

    mod
                              
                              ->pool =
                              
                                 pool;

    mod
                              
                              ->module_name = switch_core_strdup(mod->
                              
                                pool, name);
    switch_thread_rwlock_create(
                              
                              &mod->rwlock, mod->
                              
                                pool);
    
                              
                              
                                return
                              
                              
                                 mod;
}
                              
                            
使用 switch_loadable_module_create_interface 来创建模块里面的子接口,示例如下:
                                *module_interface =
                                
                                   switch_loadable_module_create_module_interface(pool, modname);

rtc_endpoint_interface 
                                
                                = switch_loadable_module_create_interface(*
                                
                                  module_interface, SWITCH_ENDPOINT_INTERFACE);
rtc_endpoint_interface
                                
                                ->interface_name = 
                                
                                  "
                                
                                
                                  rtc
                                
                                
                                  "
                                
                                
                                  ;
rtc_endpoint_interface
                                
                                ->io_routines = &
                                
                                  rtc_io_routines;
rtc_endpoint_interface
                                
                                ->state_handler = &
                                
                                  rtc_event_handlers;
rtc_endpoint_interface
                                
                                ->recover_callback = rtc_recover_callback;
                              
具体实现如下:
                                  SWITCH_DECLARE(
                                  
                                    void
                                  
                                   *) switch_loadable_module_create_interface(switch_loadable_module_interface_t *
                                  
                                    mod, switch_module_interface_name_t iname)
{

    
                                  
                                  
                                    switch
                                  
                                  
                                     (iname) {
    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_ENDPOINT_INTERFACE:
        ALLOC_INTERFACE(endpoint)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_TIMER_INTERFACE:
        ALLOC_INTERFACE(timer)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_DIALPLAN_INTERFACE:
        ALLOC_INTERFACE(dialplan)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_CODEC_INTERFACE:
        ALLOC_INTERFACE(codec)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_APPLICATION_INTERFACE:
        ALLOC_INTERFACE(application)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_CHAT_APPLICATION_INTERFACE:
        ALLOC_INTERFACE(chat_application)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_API_INTERFACE:
        ALLOC_INTERFACE(api)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_JSON_API_INTERFACE:
        ALLOC_INTERFACE(json_api)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_FILE_INTERFACE:
        ALLOC_INTERFACE(file)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_SPEECH_INTERFACE:
        ALLOC_INTERFACE(speech)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_DIRECTORY_INTERFACE:
        ALLOC_INTERFACE(directory)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_CHAT_INTERFACE:
        ALLOC_INTERFACE(chat)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_SAY_INTERFACE:
        ALLOC_INTERFACE(say)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_ASR_INTERFACE:
        ALLOC_INTERFACE(asr)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_MANAGEMENT_INTERFACE:
        ALLOC_INTERFACE(management)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_LIMIT_INTERFACE:
        ALLOC_INTERFACE(limit)

    
                                  
                                  
                                    case
                                  
                                  
                                     SWITCH_DATABASE_INTERFACE:
        ALLOC_INTERFACE(database)

    
                                  
                                  
                                    default
                                  
                                  
                                    :
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, 
                                  
                                  
                                    "
                                  
                                  
                                    Invalid Module Type!\n
                                  
                                  
                                    "
                                  
                                  
                                    );
        
                                  
                                  
                                    return
                                  
                                  
                                     NULL;
    }
}
                                  
                                

3、switch_endpoint_interface_t

作用:endpoint的入口
结构体定义:
                                    
                                      struct
                                    
                                    
                                       switch_endpoint_interface {
    
                                    
                                    
                                      /*
                                    
                                    
                                      ! the interface's name 
                                    
                                    
                                      */
                                    
                                    
                                      const
                                    
                                    
                                      char
                                    
                                     *
                                    
                                      interface_name;

    
                                    
                                    
                                      /*
                                    
                                    
                                      ! channel abstraction methods 
                                    
                                    
                                      */
                                    
                                    
                                      
    switch_io_routines_t 
                                    
                                    *
                                    
                                      io_routines;

    
                                    
                                    
                                      /*
                                    
                                    
                                      ! state machine methods 
                                    
                                    
                                      */
                                    
                                    
                                      
    switch_state_handler_table_t 
                                    
                                    *
                                    
                                      state_handler;

    
                                    
                                    
                                      /*
                                    
                                    
                                      ! private information 
                                    
                                    
                                      */
                                    
                                    
                                      void
                                    
                                     *
                                    
                                      private_info;

    switch_thread_rwlock_t 
                                    
                                    *
                                    
                                      rwlock;
    
                                    
                                    
                                      int
                                    
                                    
                                       refs;
    switch_mutex_t 
                                    
                                    *
                                    
                                      reflock;

    
                                    
                                    
                                      /*
                                    
                                    
                                       parent 
                                    
                                    
                                      */
                                    
                                    
                                      
    switch_loadable_module_interface_t 
                                    
                                    *
                                    
                                      parent;

    
                                    
                                    
                                      /*
                                    
                                    
                                       to facilitate linking 
                                    
                                    
                                      */
                                    
                                    
                                      struct
                                    
                                     switch_endpoint_interface *
                                    
                                      next;

    switch_core_recover_callback_t recover_callback;

};

typedef 
                                    
                                    
                                      struct
                                    
                                     switch_endpoint_interface switch_endpoint_interface_t;
                                  
字段解释:
interface_name => endpoint名称,比如:"rtc"
io_routines => endpoint对应的io操作回调函数
state_handler => endpoint对应的事件处理回调函数
private_info => endpoint私有参数配置(比如编码格式、采样率等)
rwlock => endpoint锁
refs => endpoint锁的引用次数
reflock => endpoint引用锁
parent => endpoint所属模块
next => next指针
recover_callback => endpoint对应的recover回调函数

4、switch_io_routines

作用:存储io操作的回调函数
结构体定义:
                                      
                                        struct
                                      
                                      
                                         switch_io_routines {
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! creates an outgoing session from given session, caller profile 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_outgoing_channel_t outgoing_channel;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! read a frame from a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_read_frame_t read_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! write a frame to a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_write_frame_t write_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! send a kill signal to the session's channel 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_kill_channel_t kill_channel;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! send a string of DTMF digits to a session's channel 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_send_dtmf_t send_dtmf;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! receive a message from another session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_receive_message_t receive_message;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! queue a message for another session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_receive_event_t receive_event;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! change a sessions channel state 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_state_change_t state_change;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! read a video frame from a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_read_video_frame_t read_video_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! write a video frame to a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_write_video_frame_t write_video_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! read a video frame from a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_read_text_frame_t read_text_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! write a video frame to a session 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_write_text_frame_t write_text_frame;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! change a sessions channel run state 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_state_run_t state_run;
    
                                      
                                      
                                        /*
                                      
                                      
                                        ! get sessions jitterbuffer 
                                      
                                      
                                        */
                                      
                                      
                                        
    switch_io_get_jb_t get_jb;
    
                                      
                                      
                                        void
                                      
                                       *padding[
                                      
                                        10
                                      
                                      
                                        ];
};

typedef 
                                      
                                      
                                        struct
                                      
                                       switch_io_routines switch_io_routines_t;
                                    
字段解释:
outgoing_channel => 创建外呼channel的回调函数
read_frame => 读session音频数据的回调函数
write_frame => 写session音频数据的回调函数
kill_channel => kill信号处理函数,用于处理channel接收的kill信号
send_dtmf => send dtmf操作的回调函数,用于处理channel接收的DTMF字符串
receive_message => 处理channel消息的回调函数,用于处理其它channel发来的消息
receive_event => 发送channel消息的回调函数,用于向目标session发送自定义事件(比如rtc session、rtmp session等)
state_change => channel状态修改的回调函数
read_video_frame => 读session视频数据的回调函数
write_video_frame => 写session视频数据的回调函数
read_text_frame => 读session文本数据的回调函数
write_text_frame => 写session文本数据的回调函数
state_run => 改变session的运行状态,目前没见到有endpoint使用过
get_jb => 获取session的jitter_buffer

5、switch_state_handler_table_t

作用:用于存储状态机的回调函数。
定义如下:
                                        
                                          struct
                                        
                                        
                                           switch_state_handler_table {
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to init 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_init;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to routing 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_routing;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to execute 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_execute;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to hangup 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_hangup;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to exchange_media 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_exchange_media;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to soft_execute 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_soft_execute;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to consume_media 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_consume_media;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to hibernate 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_hibernate;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to reset 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_reset;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to park 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_park;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to reporting 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_reporting;
    
                                        
                                        
                                          /*
                                        
                                        
                                          ! executed when the state changes to destroy 
                                        
                                        
                                          */
                                        
                                        
                                          
    switch_state_handler_t on_destroy;
    
                                        
                                        
                                          int
                                        
                                        
                                           flags;
    
                                        
                                        
                                          void
                                        
                                         *padding[
                                        
                                          10
                                        
                                        
                                          ];
};


typedef 
                                        
                                        
                                          struct
                                        
                                         switch_state_handler_table switch_state_handler_table_t;
                                      
参数解释:
on_init => channel进入 CS_INIT 状态的回调函数
on_routing => channel进入 CS_ROUTING 状态的回调函数
on_execute => channel进入 CS_EXECUTE 状态的回调函数,用于执行操作
on_hangup => channel进入 CS_HANGUP 状态的回调函数
on_exchange_media => channel进入 CS_EXCHANGE_MEDIA 状态的回调函数
on_soft_execute => channel进入 CS_SOFT_EXECUTE 状态的回调函数,用于从其它channel接收或发送数据
on_consume_media => channel进入 CS_CONSUME_MEDIA 状态的回调函数,
on_hibernate => channel进入 CS_HIBERNATE 状态的回调函数,sleep操作
on_reset => channel进入 CS_RESET 状态的回调函数
on_park => channel进入 CS_PARK 状态的回调函数
on_reporting => channel进入 CS_REPORTING 状态的回调函数
on_destroy => channel进入 CS_DESTROY 状态的回调函数
switch_core_state_machine.c中使用 STATE_MACRO 触发,部分触发代码如下:
                              
                                case
                              
                               CS_ROUTING:    
                              
                                /*
                              
                              
                                 Look for a dialplan and find something to do 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(routing, 
                              
                              
                                "
                              
                              
                                ROUTING
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_RESET:        
                              
                                /*
                              
                              
                                 Reset 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(reset, 
                              
                              
                                "
                              
                              
                                RESET
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;
    
                              
                              
                                /*
                              
                              
                                 These other states are intended for prolonged durations so we do not signal lock for them 
                              
                              
                                */
                              
                              
                                case
                              
                               CS_EXECUTE:    
                              
                                /*
                              
                              
                                 Execute an Operation 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(execute, 
                              
                              
                                "
                              
                              
                                EXECUTE
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_EXCHANGE_MEDIA:    
                              
                                /*
                              
                              
                                 loop all data back to source 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(exchange_media, 
                              
                              
                                "
                              
                              
                                EXCHANGE_MEDIA
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_SOFT_EXECUTE:    
                              
                                /*
                              
                              
                                 send/recieve data to/from another channel 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(soft_execute, 
                              
                              
                                "
                              
                              
                                SOFT_EXECUTE
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_PARK:        
                              
                                /*
                              
                              
                                 wait in limbo 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(park, 
                              
                              
                                "
                              
                              
                                PARK
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_CONSUME_MEDIA:    
                              
                                /*
                              
                              
                                 wait in limbo 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(consume_media, 
                              
                              
                                "
                              
                              
                                CONSUME_MEDIA
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              
                                ;

                              
                              
                                case
                              
                               CS_HIBERNATE:    
                              
                                /*
                              
                              
                                 sleep 
                              
                              
                                */
                              
                              
                                
    STATE_MACRO(hibernate, 
                              
                              
                                "
                              
                              
                                HIBERNATE
                              
                              
                                "
                              
                              
                                );
    
                              
                              
                                break
                              
                              ;
                            

4、模块编写示例 

1、编写c风格的endpoint模块

仿照mod_rtc模块编写,核心文件只有两个:
mod_rtc.c
Makefile.am
 
1)复制mod_artc目录
cp mod_rtc mod_ctest -r

  2)修改文件名 。

mv mod_rtc.c mod_ctest.c
 
3)修改文件内容,将rtc关键字替换成ctest

  4)修改编译选项 。

文件: freeswitch-1.10.9.-release/configure.ac
仿照rtc模块,添加ctest模块内容:
src/mod/endpoints/mod_ctest/Makefile

  。

5)开启模块编译
文件:freeswitch-1.10.9.-release/modules.conf
仿照rtc模块,添加ctest模块编译:
endpoints/mod_ctest

  。

6)生成Makefile
./rebootstrap.sh && ./configure

  7)安装模块 。

在 freeswitch-1.10.9.-release 根目录(或mod_ctest目录)执行如下指令:
make && make install

  8)加载模块 。

文件:conf/autoload_configs/modules.conf.xml
添加如下内容:
 
9)模块测试
控制台加载测试:
reload mod_ctest

c风格endpoint模块编译及运行效果视频:

关注微信公众号(聊聊博文,文末可扫码)后回复 2023052801 获取。  。

2、编写c++风格的endpoint模块

仿照mod_h323模块编写,目录结构、编译等参考c风格endpoint模块编写部分。
加载效果如下:

c++风格endpoint模块编译及运行效果视频:

关注微信公众号(聊聊博文,文末可扫码)后回复 2023052802 获取。  。

5、资源下载

本文涉及源码和文件,可以从如下途径获取:

关注微信公众号(聊聊博文,文末可扫码)后回复 20230528 获取.

  。

最后此篇关于FreeSWITCH添加自定义endpoint的文章就讲到这里了,如果你想了解更多关于FreeSWITCH添加自定义endpoint的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com