事无两极,一切皆是权衡

终于发现,这个世界遍地是金钱,到处是女人!

导航

openimscore(ser)系统简析

Posted on 2009-06-25 16:34  中国小可  阅读(1235)  评论(0)    收藏  举报

1. 目录

2. 如何实现plug-in. 1

3. ModuleInterface. 2

4. 全局数据结构... 3

5. 进程关系... 3

6. receive_msg过程... 4

7. Helloworld注册服务器的数据流过程展现... 5

2. 如何实现plug-in

要实现动态加载库文件,以palg-in的方式工作一定是以Dynamic Loader的方式实现的。

实现Dynamic Load方式的几个重要函数:

#include <dlfcn.h>

void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);

经查找发现dlopen()在sr_module.c:load_module(path)中只调用一次:

Sr_mocule.c:

handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */

dlsym()发现三次:

Sr_mocule.c:

m_ver=(char **)dlsym(handle, DLSYM_PREFIX "module_version");

m_flags=(char **)dlsym(handle, DLSYM_PREFIX "module_flags");

exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");

dlclose()一次

sr_module.c

load_module(path)dlclose(handle);

从上边的几次调用来看,只有

exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");

才是从dynamic library中查找Symbol的,查找的符号是module_exports。找查到后把值赋给exp,再向下看:

exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");

if ( (error =(char*)dlerror())!=0 ){

LOG(L_ERR, "ERROR: load_module: %s\n", error);

goto error1;

}

if (register_module(exp, path, handle)<0) goto error1;

return 0;

把exp,path,hanmdle传给register_module()。正如其名,register_moduel把传入的module添加到全局变量modules上。

也就是说每一个module必须得实现接口module_exports,实际上的确如此。Module_exports把core部分和module部分连接起来。到每个module中发现module_exprotsq包含了如下信息:

Module name

Exported functions

RPC method

Exported parameters

Initialization function

定义模块的初始化函数。

Response function

Destroy function

OnCancel function

Child init function

3. ModuleInterface

要进行二次开发了解ModuelInterface是必要条件。具体以可参考serdev.pdf的Chapter 7. The Module Interface。(些处的版本是ser 0.8.7 module_exports已与现在的版本不同)

在此只简要说明一下:

主要的结构:

Structure sr_module , Structure module_exports

Structure sr_module,一个单向链表,所有注册到系统中的module表要保存在这个单向链表中。

Structure module_exports,每一个module考必须有一个这新导出结构,用来描述导出接口,用来让core部分进行调用。

下边对module_exports的部分成员进行说明:

module_exports. cmd_export_t

导出命令数组,它是一个多维数组,每一维中的意义是:

1)name:Command name

2)cmd_function:命令对应的function

3)param_no:function使用的parameters个数

4)fixup_function:???(Point to the function called to "fix" the parameters)

5)flags : function flags

module_exports.rpc_export_t

??( null terminated array of exported rpc methods)

Module_exports. response_function

??( function called when the module should

be "destroyed", e.g: on ser exit;

can be null)

Module_exports.child_init_function

在多进程结构中,每当调用完fork()后,将调用些函数。

4. 全局数据结构

类型:数据名称

定义位置

作用

modules

Sr_module.c

一个单向链表,用来记录module信息

dont_fork

Main.c

指定子进程个数

debug

Main.c

Log输出的门限,大于些值时才把log输出到syslog

socket_info :udp_listen

socket_info: tcp_listen

socket_info: tls_listen

Socket_info.h

网络接口,socket 双向链表

process_count

Main.c

进程数,包括主进程

5. 进程关系

Main_Process

Slow Process

Time Process

Netwrok

6. receive_msg过程

先理解receive_msg的处理过程,十分有助于理解系统如何处理sip消息。Receive_msg位于Receive.c文件中。它是由udp_rcv_loop()从socket中收到数据后,然后传给receive_msg().

Receive_msg做了下列工作:

1. 把msg从buf形式打包成为msg,并把socket等相关数据,都存放在msg 结构中。

2. clear_branches();

3. reset_static_buffer();

4. exec_pre_req_cb(msg);

5. run_actions(main_rt.rlist[DEFAULT_RT], msg)

6. exec_post_req_cb(msg);

7. exec_pre_rpl_cb(msg)

8. exec_post_rpl_cb(msg);

9. reset_avps();

10. free_sip_msg(msg);

11. pkg_free(msg);

在些基本上看到了一个msg从生成到结束(pkg_free(msg))。

Script_cb.c中的操作:

add_callback

register_script_cb

destroy_cb_list

destroy_script_cb

exec_pre_cb

exec_post_cb

exec_pre_req_cb

exec_post_reg_cb

exec_pre_rpl_cb

exec_post_rpl_cb

Action.c中

Do_action

Run_action

7. Helloworld注册服务器的数据流过程展现