_hook 数据结构
1
2 // 从 ap_hook 到 ap_run
3 // 宏 AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED ); 的具体实现
4 // connection.c
5 AP_DECLARE( void ) ap_hook_pre_connection(ap_HOOK_pre_connection_t * pf, const char * const * aszPre, const char * const * aszSucc, int nOrder)
6 {
7 ap_LINK_pre_connection_t * pHook;
8 if ( ! _hooks.link_pre_connection)
9 {
10 _hooks.link_pre_connection = apr_array_make(apr_hook_global_pool, 1 , sizeof (ap_LINK_pre_connection_t));
11 apr_hook_sort_register( " pre_connection " , & _hooks.link_pre_connection);
12 }
13 pHook = apr_array_push(_hooks.link_pre_connection);
14 pHook -> pFunc = pf;
15 pHook -> aszPredecessors = aszPre;
16 pHook -> aszSuccessors = aszSucc;
17 pHook -> nOrder = nOrder;
18 pHook -> szName = apr_hook_debug_current;
19 if (apr_hook_debug_enabled)
20 apr_hook_debug_show( " pre_connection " ,aszPre,aszSucc);
21 }
22 AP_DECLARE(apr_array_header_t * ) ap_hook_get_pre_connection( void )
23 {
24 return _hooks.link_pre_connection;
25 }
26 AP_DECLARE( int ) ap_run_pre_connection (conn_rec * c, void * csd)
27 {
28 ap_LINK_pre_connection_t * pHook; int n; int rv;
29 if ( ! _hooks.link_pre_connection)
30 return OK;
31 pHook = (ap_LINK_pre_connection_t * )_hooks.link_pre_connection -> elts;
32 for (n = 0 ; n < _hooks.link_pre_connection -> nelts ; ++ n)
33 {
34 rv = pHook[n].pFunc (c, csd);
35 if (rv != OK && rv != DECLINED) return rv;
36 }
37 return OK;
38 };
2 // 从 ap_hook 到 ap_run
3 // 宏 AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED ); 的具体实现
4 // connection.c
5 AP_DECLARE( void ) ap_hook_pre_connection(ap_HOOK_pre_connection_t * pf, const char * const * aszPre, const char * const * aszSucc, int nOrder)
6 {
7 ap_LINK_pre_connection_t * pHook;
8 if ( ! _hooks.link_pre_connection)
9 {
10 _hooks.link_pre_connection = apr_array_make(apr_hook_global_pool, 1 , sizeof (ap_LINK_pre_connection_t));
11 apr_hook_sort_register( " pre_connection " , & _hooks.link_pre_connection);
12 }
13 pHook = apr_array_push(_hooks.link_pre_connection);
14 pHook -> pFunc = pf;
15 pHook -> aszPredecessors = aszPre;
16 pHook -> aszSuccessors = aszSucc;
17 pHook -> nOrder = nOrder;
18 pHook -> szName = apr_hook_debug_current;
19 if (apr_hook_debug_enabled)
20 apr_hook_debug_show( " pre_connection " ,aszPre,aszSucc);
21 }
22 AP_DECLARE(apr_array_header_t * ) ap_hook_get_pre_connection( void )
23 {
24 return _hooks.link_pre_connection;
25 }
26 AP_DECLARE( int ) ap_run_pre_connection (conn_rec * c, void * csd)
27 {
28 ap_LINK_pre_connection_t * pHook; int n; int rv;
29 if ( ! _hooks.link_pre_connection)
30 return OK;
31 pHook = (ap_LINK_pre_connection_t * )_hooks.link_pre_connection -> elts;
32 for (n = 0 ; n < _hooks.link_pre_connection -> nelts ; ++ n)
33 {
34 rv = pHook[n].pFunc (c, csd);
35 if (rv != OK && rv != DECLINED) return rv;
36 }
37 return OK;
38 };
解码解释:
第5行 ap_hook_pre_connection 的第一个参数 pf 数据类型为 ap_HOOK_pre_connection_t ,实际是一个函数指针。也是用宏定义的:
//
宏 AP_DECLARE_HOOK(int,pre_connection,(conn_rec *c, void *csd))展开
// http_connection.h
typedef int ap_HOOK_pre_connection_t (conn_rec * c, void * csd);
AP_DECLARE( void ) ap_hook_pre_connection(ap_HOOK_pre_connection_t * pf, const char * const * aszPre, const char * const * aszSucc, int nOrder);
AP_DECLARE( int ) ap_run_pre_connection (conn_rec * c, void * csd);
AP_DECLARE(apr_array_header_t * ) ap_hook_get_pre_connection( void );
typedef struct ap_LINK_pre_connection_t
{
ap_HOOK_pre_connection_t * pFunc;
const char * szName;
const char * const * aszPredecessors;
const char * const * aszSuccessors;
int nOrder;
} ap_LINK_pre_connection_t;
// http_connection.h
typedef int ap_HOOK_pre_connection_t (conn_rec * c, void * csd);
AP_DECLARE( void ) ap_hook_pre_connection(ap_HOOK_pre_connection_t * pf, const char * const * aszPre, const char * const * aszSucc, int nOrder);
AP_DECLARE( int ) ap_run_pre_connection (conn_rec * c, void * csd);
AP_DECLARE(apr_array_header_t * ) ap_hook_get_pre_connection( void );
typedef struct ap_LINK_pre_connection_t
{
ap_HOOK_pre_connection_t * pFunc;
const char * szName;
const char * const * aszPredecessors;
const char * const * aszSuccessors;
int nOrder;
} ap_LINK_pre_connection_t;
第7 行的 _hook 定义于 connection.c ,它是一个由宏定义的文件级的变量。
从 hook 到 run--宏的展开
展开 ap_hook_宏和 ap_run宏
/* *
* 展开 apache2 的 ap_hook_宏和 ap_run宏
* 使用 gcc -E -I/usr/local/apache2/include macos.h 可得到实际的c 代码
* by fancp 2011-1-10 p_168@163.com
*
************************************************** */
#include < ap_config.h >
APR_HOOK_STRUCT(
APR_HOOK_LINK(create_request_bin)
)
AP_DECLARE_HOOK( int ,create_request_bin,(conn_rec * c, void * csd))
AP_IMPLEMENT_HOOK_RUN_ALL( int , create_request_bin,
(request_rec_bin * r), (r), OK, DECLINED)
/* *
* 展开 apache2 的 ap_hook_宏和 ap_run宏
* 使用 gcc -E -I/usr/local/apache2/include macos.h 可得到实际的c 代码
* by fancp 2011-1-10 p_168@163.com
*
************************************************** */
#include < ap_config.h >
APR_HOOK_STRUCT(
APR_HOOK_LINK(create_request_bin)
)
AP_DECLARE_HOOK( int ,create_request_bin,(conn_rec * c, void * csd))
AP_IMPLEMENT_HOOK_RUN_ALL( int , create_request_bin,
(request_rec_bin * r), (r), OK, DECLINED)
ap_filter_rec_t 数据结构
/*
**************************************
*
* util_filter.h
************************************** */
struct ap_filter_rec_t {
/* * The registered name for this filter */
const char * name;
/* * The function to call when this filter is invoked. */
ap_filter_func filter_func;
/* * The function to call directly before the handlers are invoked
* for a request. The init function is called once directly
* before running the handlers for a request or subrequest. The
* init function is never called for a connection filter (with
* ftype >= AP_FTYPE_CONNECTION). Any use of this function for
* filters for protocols other than HTTP is specified by the
* module supported that protocol.
*/
ap_init_filter_func filter_init_func;
/* * The type of filter, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION.
* An AP_FTYPE_CONTENT filter modifies the data based on information
* found in the content. An AP_FTYPE_CONNECTION filter modifies the
* data based on the type of connection.
*/
ap_filter_type ftype;
/* * The next filter_rec in the list */
struct ap_filter_rec_t * next;
/* * Providers for this filter */
ap_filter_provider_t * providers;
/* * Trace level for this filter */
int debug;
/* * Protocol flags for this filter */
unsigned int proto_flags;
};
*
* util_filter.h
************************************** */
struct ap_filter_rec_t {
/* * The registered name for this filter */
const char * name;
/* * The function to call when this filter is invoked. */
ap_filter_func filter_func;
/* * The function to call directly before the handlers are invoked
* for a request. The init function is called once directly
* before running the handlers for a request or subrequest. The
* init function is never called for a connection filter (with
* ftype >= AP_FTYPE_CONNECTION). Any use of this function for
* filters for protocols other than HTTP is specified by the
* module supported that protocol.
*/
ap_init_filter_func filter_init_func;
/* * The type of filter, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION.
* An AP_FTYPE_CONTENT filter modifies the data based on information
* found in the content. An AP_FTYPE_CONNECTION filter modifies the
* data based on the type of connection.
*/
ap_filter_type ftype;
/* * The next filter_rec in the list */
struct ap_filter_rec_t * next;
/* * Providers for this filter */
ap_filter_provider_t * providers;
/* * Trace level for this filter */
int debug;
/* * Protocol flags for this filter */
unsigned int proto_flags;
};
/*
* Read data from the next filter in the filter stack. Data should be
* modified in the bucket brigade that is passed in. The core allocates the
* bucket brigade, modules that wish to replace large chunks of data or to
* save data off to the side should probably create their own temporary
* brigade especially for that use.
*/
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t * next,
apr_bucket_brigade * bb,
ap_input_mode_t mode,
apr_read_type_e block,
apr_off_t readbytes)
{
if (next) {
return next -> frec -> filter_func.in_func(next, bb, mode, block,
readbytes);
}
return AP_NOBODY_READ;
}
* Read data from the next filter in the filter stack. Data should be
* modified in the bucket brigade that is passed in. The core allocates the
* bucket brigade, modules that wish to replace large chunks of data or to
* save data off to the side should probably create their own temporary
* brigade especially for that use.
*/
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t * next,
apr_bucket_brigade * bb,
ap_input_mode_t mode,
apr_read_type_e block,
apr_off_t readbytes)
{
if (next) {
return next -> frec -> filter_func.in_func(next, bb, mode, block,
readbytes);
}
return AP_NOBODY_READ;
}