撰寫 Apache module (三) - 實作注意事項
  • 4,354 views,
  • 2013-10-21,
  • 上傳者: Kuann Hung,
  •  0
最近完成了新的專案,就是處理 MP4 檔案的 Apache module。
 
大致內容是,當 user request mp4 檔案格式時,需 parse mp4 header 並取得 max_bps,avg_bps 等資訊。將資料送出時,則根據 mp4 檔案的所需頻寬送出,做 Rate control。
這部分的程式因為是幫公司寫的,所以不能分享 souce code,只能在這邊分享一些實作上需注意的事情。
事實上,這是我第一次寫 Apache module,只是看範例+code tracing 把它作出來,沒有深入研究。若有錯誤還希望有高手指正喔!
 
步驟
1.
Module Initization
a. register_hooks(apr_pool_t *p)
在開始寫 module 時,必須以 hook 的方式向 Apache 註冊你的 module,跟 windows 滿像的。
Hook 的方式是使用 ap_hook_handler,而 hook 的位置可以是:
APR_HOOK_REALLY_FIRST、APR_HOOK_FIRST、APR_HOOK_MIDDLE、APR_HOOK_LAST、APR_HOOK_REALLY_LAST。
原則上可參考 撰寫 Apache module (二) - 模組架構及流程 裡面的流程圖,這幾項主要是在多個 modules 中處理的流程。
b. ap_register_output_filter
如果你的專案需要針對檔案輸出做控制的話,則你需要註冊一個 output_filter。透過這個 filter 來處理。好比說我需要做的 rate control 就需要註冊一個 filter。
c. ap_hook_post_config
如果你需要讀取 httpd.conf 或是 conf.d/ 下的設定檔的話,你就要使用 ap_hook_post_config 來處理設定檔的部分。
d. AP_MODULE_DECLARE_DATA
除了 hook 之外,也要描述一下你的 module 的定義:
module AP_MODULE_DECLARE_DATA your_module = 
{
    STANDARD20_MODULE_STUFF,    // stuff that needs to be declared in every 2.0 mod 
    NULL,                       // create per-directory config structure            
    NULL,                       // merge per-directory config structures            
    NULL,                       // create per-server config structure               
    NULL,                       // merge per-server config structures               
    NULL,                       // command apr_table_t                              
    register_hooks              // register hooks                                   
};

e. command_rec
這裡需要定義你在 httpd.conf 中所需要的參數,以及參數的個數。(以下是我的定義)。
static const command_rec mp4_d_cmds[] =
{
    AP_INIT_FLAG("Mp4RateControl", mp4ratecontrol, NULL,
                 RSRC_CONF | ACCESS_CONF, 
                 "On or Off to enable or disable (default) the Mp4RateControl"),
    AP_INIT_TAKE1("Mp4Ratio", mp4ratio, NULL, RSRC_CONF | ACCESS_CONF,
                   "transfer ratio"),
    AP_INIT_TAKE1("Mp4FastStart", mp4faststart, NULL, RSRC_CONF | ACCESS_CONF,
                   "transfer N seconds data of the first request (in second) "),              
    {NULL}
};
2.
取得設定資料
前面的 module init 完成之後,先需要取得的就是設定檔資訊,這樣你的 module 運作時才可以抓到 user 的設定。
 
3.
進入程式 handle
當以上都設定,並取得設定資料後。當 Apache 服務啟動,並有 user request 時,程式就會被導入你的模組,可以用以下的 function 取得你的設定資料:
your_server_config *sconf =
    (your_server_config *) ap_get_module_config(r->server->
                                                     module_config,
                                                     &your_module);
your_config *conf =
    (your_config *) ap_get_module_config(r->per_dir_config,
                                              &your_module);
如果讀取完設定,並確定你要繼續處理的話,記得使用 ap_add_output_filter 註冊 output filter。
4.
模組間傳遞資料
在我的專案中,遇到較大的問題是:我同時註冊了一個 mp4 parsing 的 module 以及一個 rate control 的 filter 。比較麻煩的是要把 parsing 完的資料送到 rate control filter 中。由於看文件不如看程式,所以就追了一下程式碼,發現在 request_rec 中有一個 notes 的結構可以使用。文件中也明確地說到是用來在不同的 module 間傳遞資料使用。所以就利用 apr_table_set(), apr_table_get() 以下幾個 function 來把資料寫入 notes 並在 module 與 filter 之間傳遞。
5.
結語
這篇只分享一些實作的經驗,礙於工作的關係,不能將 code 分享出來。不過有問題可以一起討論。在製作的過程中,最大的麻煩是沒有好的 debug 工具。而且許多資料都被 apache 包起來了。只能自己寫一些 debug function,然後印出一大堆資訊來看程式到底怎麼跑,資料到底怎麼傳遞。
這算個比較急的案子,所以就只能用土方法,邊寫 code 邊看文件的方式把它趕緊做出來。或許以後有機會再好好認真看文件,找工具囉!
Facebook 討論區載入中...
資料夾 :
發表時間 :
2013-10-21 00:36:00
觀看數 :
4,354
發表人 :
Kuann Hung
部門 :
老洪的 IT 學習系統
QR Code :