寫在前面的話:裡面的截圖除非特殊說明,都是來自sr_module.h
參考:https://blog.csdn.net/ttomqq/article/details/38821411
一、關于版本
定義每一個子產品都要說明這個子產品的結構,以便于讓kamailio能解釋它,包括子產品導出函數的結構cmd_export_和子產品整體的結構module_exports。在sr_module.h中有兩種版本的子產品結構,一個是SER,一個是kam,是這樣定義的:
這裡的cmd_export_t和module_exports即可代表ser的也可以代表kam的。在自己定義子產品時候直接由結構的内容展現是哪種版本(個數)。
子產品導出函數結構:
子產品結構:
有預設使用哪種版本的定義,猜想應該是從這裡預設定義的:
預設版本是SER的,但是沒找到用另一個版本kam所代表的數值,在json_mod.c中就是用的kam版本的(下圖)
但是裡面的版本聲明 MODULE_VERSION仍然是SER的意思,這裡面應該有一些定義是沒注意到的,也就是什麼時候可以用kam版本,這個我沒找到,希望有大神能幫我解惑。
二、結構具體含義
1、對于子產品導出函數結構:
第一個參數是該module導出到opensips腳本中的函數名。
第二個參數是對應的具體執行函數。cmd_function的函數定義為
從第二個參數起都是字元串。具體使用多少個參數由結構體第三個參數決定。
對于cmd_function,傳回值小于0表示函數執行出錯,傳回值等于0會使該次腳本執行結束;傳回值大于0表示函數執行正常。
第四個參數fixup function,主要用于将腳本傳入的參數轉換成int、正規表達式等其他種類的參數。常用的類型轉換定義在mod_fix.h中,一般直接調用。
第五個參數用于描述該導出函數可以在哪段路由中被執行。可選的值定義在route.h中:
kam版本比ser的多了一個free_fixup_function參數,用于釋放fixup function執行時申請的記憶體。
2、對于子產品結構:
char* name: 子產品的名字。
ser_cmd_export_t* cmds:前面定義的子產品導出函數,這裡如果一個子產品裡多于兩個導出函數的情況下就要定義ser_cmd_export_t類型的結構體數組cmds[],每一個元素都是一個ser_cmd_export_t類型的結構體,各對應一個導出函數。
rpc_export_t* rpc_methods:遠端程式調用的導出函數(rpc.h中定義的)。
param_export_t* params:參數導出,很多參數的時候也是定義一個param_export_t類型的數組,每個數組元素都是對這個參數的說明,例如acc_mod.c中的184行(部分):
init_function init_f: 子產品初始化化函數,隻在啟動的時候被執行一次。
response_function response_f: 用于回複,有yes或no,null也行,不知道做什麼的。
destroy_function destroy_f: 子產品銷毀時被調用。
onbreak_function onbreak_f;:不知道做什麼的,onbreak_function在120行:
typedef void (*onbreak_function)(struct sip_msg*);是指向sip_msg結構體的一個指針。
child_init_function init_child_f: 子產品在每個子程序中的初始化函數。因kamailio的架構是多程序的,像資料庫連接配接這些必須在每個子程序内自己建立一份。
unsigned int dlflags: 一般都把值設為DEFAULT_DLFLAG,後面的stat_、nn_、pv_還沒看是做什麼的。
proc_export_t* procs: 定義子產品自己的獨立運作程序。
三、編寫一個簡單的子產品
1、寫子產品主體代碼test.c檔案
在目錄/usr/local/src/kamailio-5.1/kamailio/src/modules(也就是下載下傳kamailio源碼的位置那)建立一個名為test的檔案夾,編寫子產品主體代碼test.c檔案。
cd /usr/local/src/kamailio-5.1/kamailio/src/modules
sudo mkdir test
cd test
sudo vi test.c /*根據自己常用的編輯器來即可*/
test.c檔案如下:
/*
*時間:2018年3月29日16點24分
*作者:cxy
*子產品名:test
*導出函數名:my_test
*功能:在初始化的時候在日志輸出“cxy-initializing...”,在每一個request(invite,subscribe,
*register,cancel等等)到來時候輸出“Receive message 123456”,為了看是否子產品添加成功
*輸入:123456(或者其他)
*輸出:Receive message 123456(或者其他)
*/
#include "../../core/sr_module.h"
MODULE_VERSION
static int mod_init(void);
static int my_test(struct sip_msg* _msg, char *param);
/* Exported functions */
static cmd_export_t cmds[]={
{"my_test", (cmd_function)my_test, 1, 0, ANY_ROUTE}, /*在任何路由塊都能用*/
{0, 0, 0, 0, 0}
};
/* Module interface */
struct ser_module_exports exports = {
"test", /**< null terminated module name */
cmds, /**< null terminated array of the exported
commands */
0, /**< null terminated array of exported rpc methods */
0, /**< null terminated array of the exported module parameters */
mod_init, /**< Initialization function */
0, /**< function used for responses, returns yes or no; can be null */
0, /**< function called when the module should be "destroyed", e.g: on ser exit;
can be null */
0,
0, /**< function called by all processes after the fork */
};
static int my_test(struct sip_msg* _msg, char *param)
{
LM_INFO("Receive message %s\n", param);
return 1;
}
static int mod_init(void)
{
LM_INFO("cxy-initializing...\n");
return 0;
}
2、編寫Makefile檔案
如果這個module不需要連接配接其他額外的庫,隻要把NAME後面生成庫的名字改成test.so。如下所示:
#
#test makefile
#
#WARNING: do not run this directly. it should be run by the master Makefile
include ../../Makefile.defs
auto_gen=
NAME=test.so
LIBS=
DEFS+=-DSER_MOD_INTERFACE
include ../../Makefile.modules
3、編譯
編譯這個子產品,除非在src目錄下的主Makefile的exclude_modules中加入了這個子產品的名字,就不編譯這個子產品。
cd /usr/local/src/kamailio-5.1/kamailio
sudo make all
sudo make install
(按理說不用再次安裝吧?但是如果不再安裝的話我發現生成的庫檔案test.so不能被導入/usr/local/lib64/kamailio/modules中,還是說是應該要安裝一遍的?)
由于一開始我是仿照https://blog.csdn.net/ttomqq/article/details/38821411裡面的test子產品,修改了一些版本的差異,一開始我是按照kamailio版本寫的子產品但總是提示警告,提示我有多餘的元素。經過比較,不管是cmd子產品導出函數聲明還是module子產品導出聲明,SER版本的的确是比kam版本的元素個數要少(SER版本cmd有5個元素,module有9個;kam版本cmd有6個,module有12個)。預設版本是SER,是以下面的警告根源在版本這裡,改成了SER版本就行了。
4、載入新子產品
不載入的話kamailio不會自己添加這個功能的,在kamailio.cfg檔案中相應位置加入以下語句:
loadmodule "test.so"
把新編寫的子產品加入路由之中,在路由邏輯的request邏輯下插入:
my_test("123456");
5、驗證子產品是否添加成功
打開kamailio,注冊使用者并登陸,見https://blog.csdn.net/qq_36069590/article/details/79106771,可以看到路由被執行到時,日志有輸出:
PS:這裡有什麼說錯的麻煩能告訴我一下,謝謝!作為一個kamailio初學者,我感覺要學的東西太多了,這可能是和我專業不是計算機相關的有關吧。知識是一點點積累的,需要什麼就去學什麼就好了,涉及到基礎的東西就去系統的看看教材或視訊。今天花了一下午把昨天學到的東西記錄在這裡,在這裡就順便給自己打打氣,加油cxy。
任重而道遠,與君共勉。