update 2026-10-07 11:52:44

This commit is contained in:
action committed 2026-10-07 11:52:44 +08:00
1 parent d6cc6efa77
commit 617f7ca2a6
4898 files changed
-1713675

No files matched your search

@@ -1,24 +0,0 @@
Copyright (C) 2016-2020, by Jie Wu "AlexWoo" <wj19840501@gmail.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
@@ -1,37 +0,0 @@
# Module nginx-toolkit-module
---
## Instructions
Nginx event toolkit modules. It contains modules below, and will add more in the future.
- [ngx-event-timer-module](doc/ngx-event-timer-module.md)
Independent timer for nginx
- [ngx-event-resolver-module](doc/ngx-event-resolver-module.md)
Common resovler in event modules, just like http resolver, stream resolver in nginx, but can be used by http modules, stream modules and other modules
- [ngx-dynamic-resolver-module](doc/ngx-dynamic-resolver-module.md)
System will resolver domain in dynamic resolver every few seconds configured
The module will return addr whose domain is resolved in dynamic resolver, otherwise, the module will add domain into dynamic resolver, resolv domain by event resolver, and call callback when resolved
- [ngx-dynamic-conf-module](doc/ngx-dynamic-conf-module.md)
System will reload conf when nginx dynamic config file change. Developer can use this module to reload file without reload nginx worker
Now it support NGX\_CORE\_MODULE and NGX\_HTTP\_MODULE
- [ngx-map](doc/ngx-map.md)
A map implement use ngx\_rbtree
- [ngx-rbuf](doc/ngx-rbuf.md)
A recycled chainbuf for nginx
- [ngx-toolkit-misc](doc/ngx-toolkit-misc.md)
Misc toolkit functions
@@ -1,47 +0,0 @@
ngx_addon_name=ngx_toolkit_module
CORE_MODULES="$CORE_MODULES \
ngx_http_dynamic_module \
"
EVENT_MODULES="$EVENT_MODULES \
ngx_event_timer_module \
ngx_dynamic_conf_module \
ngx_event_resolver_module \
ngx_dynamic_resolver_module \
"
HTTP_MODULES="$HTTP_MODULES \
ngx_http_dynamic_core_module \
ngx_http_trace_module \
"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/ngx_event_timer_module.c \
$ngx_addon_dir/ngx_event_resolver.c \
$ngx_addon_dir/ngx_dynamic_resolver.c \
$ngx_addon_dir/ngx_dynamic_conf.c \
$ngx_addon_dir/ngx_http_dynamic.c \
$ngx_addon_dir/ngx_toolkit_misc.c \
$ngx_addon_dir/ngx_map.c \
$ngx_addon_dir/ngx_rbuf.c \
$ngx_addon_dir/ngx_poold.c \
$ngx_addon_dir/ngx_timerd.c \
$ngx_addon_dir/ngx_http_trace_module.c \
"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ngx_addon_dir/ngx_event_timer_module.h \
$ngx_addon_dir/ngx_event_resolver.h \
$ngx_addon_dir/ngx_dynamic_resolver.h \
$ngx_addon_dir/ngx_dynamic_conf.h \
$ngx_addon_dir/ngx_http_dynamic.h \
$ngx_addon_dir/ngx_toolkit_misc.h \
$ngx_addon_dir/ngx_map.h \
$ngx_addon_dir/ngx_rbuf.h \
$ngx_addon_dir/ngx_poold.h \
$ngx_addon_dir/ngx_timerd.h \
"
CFLAGS="$CFLAGS -I $ngx_addon_dir"
@@ -1,343 +0,0 @@
# Module ngx-dynamic-conf-module
---
## Instructions
System will reload conf when nginx dynamic config file change. Developer can use this module to reload file without reload nginx worker.
Now it support NGX\_CORE\_MODULE and NGX\_HTTP\_MODULE
## Directives
Syntax : dynamic_conf dynamic_file time;
Default : -
Context : main
Set dynamic config file and interval system checked file changed.
Syntax : dynamic_log log_file level;
Default : -
Context : main
Set dynamic conf load log file and log level. If not configured, use cycle log as default.
Example:
dynamic_conf conf/nginx_dynamic.conf 10;
dynamic_log logs/error_dynamic.log info;
## API
### MAIN dynamic conf
**header file**
For using this API, You should include the header file as below:
#include "ngx_dynamic_conf.h"
**dynamic module define**
typedef struct {
ngx_str_t name;
void *(*create_conf)(ngx_conf_t *cf);
char *(*init_conf)(ngx_conf_t *cf, void *conf);
} ngx_dynamic_core_module_t;
dynamic conf module define as below
ngx_module_t ngx_test_module = {
NGX_MODULE_V1,
&ngx_test_module_ctx, /* module context */
ngx_test_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
(uintptr_t) &ngx_test_module_dctx, /* module dynamic context */
(uintptr_t) ngx_test_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
**module dynamic context** struct define as above, **module dynamic directives** define use ngx\_command\_t. Use ngx\_dynamic\_core\_test\_module define in t/ngx\_dynamic\_conf\_test\_module.c as reference
**ngx\_dynamic\_conf\_parse**
ngx_int_t ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init)
- return value:
- return NGX\_OK for successd, NGX\_ERROR for failed
- paras:
- cf : ngx\_conf\_t passed from ngx\_dynamic\_conf\_load_conf
- init : only ngx\_dynamic\_conf\_load\_conf set 1, otherwise set 0
This interface is supported for other dynamic conf module, such as ngx\_conf\_parse
**ngx\_dynamic\_regex\_compile**
typedef struct {
ngx_regex_t *regex;
ngx_str_t name;
} ngx_dynamic_regex_t;
ngx_dynamic_regex_t *ngx_dynamic_regex_compile(ngx_conf_t *cf,
ngx_regex_compile_t *rc);
- return value:
- return regex context
- paras:
- cf: ngx\_conf\_t passed in dynamic cmd handler
- rc: regex options
compile regex
**ngx\_get\_dconf**
void *ngx_get_dconf(ngx_module_t *m)
return NGX\_CORE\_MODULE dynamic config for module
### HTTP dynamic conf
**header file**
For using this API, You should include the header file as below:
#include "ngx_dynamic_conf.h"
**dynamic module define**
dynamic conf module define is same as MAIN dynamic conf
http dynamic conf context define as below:
typedef struct {
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*init_srv_conf)(ngx_conf_t *cf, void *conf);
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*init_loc_conf)(ngx_conf_t *cf, void *conf);
} ngx_http_dynamic_module_t;
**notice:** http dynamic conf do not support merge
**ngx\_http\_get\_module\_main\_dconf**
void *ngx_http_get_module_main_dconf(ngx_http_request_t *r, ngx_module_t *m);
return http request main dynamic conf for module m
**ngx\_http\_get\_module\_srv\_dconf**
void *ngx_http_get_module_srv_dconf(ngx_http_request_t *r, ngx_module_t *m);
return http request srv dynamic conf for module m
**ngx\_http\_get\_module\_loc\_dconf**
void *ngx_http_get_module_loc_dconf(ngx_http_request_t *r, ngx_module_t *m);
return http request loc dynamic conf for module m
## Build
cd to NGINX source directory & run this:
./configure --add-module=/path/to/nginx-toolkit-module/
make && make install
## Example
See
- t/ngx\_dynamic\_conf\_test\_module.c as MAIN conf for usage of dynamic conf
- t/ngx\_http\_dynamic\_test\_module.c as HTTP conf for usage of http dynamic conf
**Build:**
./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t
make && make install
**Configure:**
dynamic_conf conf/nginx_dynamic.conf 10;
dynamic_log logs/error_dynamic.log info;
http {
...
server {
...
location /dynamic_conf_test/ {
dynamic_conf_test;
}
}
}
**Dynamic Configure:**
dynamic_test_i 200;
dynamic_test_s hello_world;
http {
main_int 1000;
main_str gogogo;
#defult server
server {
srv_int 1;
srv_str default;
}
#wildcard_head
server {
srv_int 2;
srv_str wildcard_head;
serverid baidu;
server_name *.baidu.com;
}
#wildcard_tail
server {
srv_int 3;
srv_str wildcard_tail;
serverid google;
server_name www.google.*;
}
#hash
server {
srv_int 4;
srv_str hash;
serverid sina;
server_name sports.sina.com.cn;
location = / {
loc_int 1;
loc_str =/;
}
location / {
loc_int 2;
loc_str /;
}
location ^~ /test1/ {
loc_int 3;
loc_str ^~/test1/;
}
location ~* \.(gif|jpg|jpeg)$ {
loc_int 4;
loc_str ~*\.(gif|jpg|jpeg)$;
}
location /test {
loc_int 5;
loc_str /test;
}
}
#pcre
server {
srv_int 5;
srv_str pcre;
serverid test;
server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.test\.com$;
}
#multi
server {
srv_int 6;
srv_str multi;
serverid others;
server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.haha\.com$ www.sohu.com;
server_name *.qq.com;
}
}
**Test:**
- Main for dynamic config
get conf configured in dynamic config file for test module
curl -v 'http://127.0.0.1/dynamic_conf_test/test'
change config in dynamic config, the test api will return new config value after dynamic conf refresh
- Main for http
curl -v 'http://127.0.0.1/'
change config in http block of dynamic config, the test api will return new config value after dynamic conf refresh
- Server for http
- defult server
curl -v 'http://127.0.0.1/http_dynamic_test/test'
curl -v -H 'Host: github.com' 'http://127.0.0.1/http_dynamic_test/test'
- wildcard_head
curl -v -H 'Host: map.baidu.com' 'http://127.0.0.1/http_dynamic_test/test'
- wildcard_tail
curl -v -H 'Host: www.google.co.jp' 'http://127.0.0.1/http_dynamic_test/test'
- hash
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/http_dynamic_test/test'
- pcre
curl -v -H 'Host: flvdl7a8e4223.test.com' 'http://127.0.0.1/http_dynamic_test/test'
- multi
curl -v -H 'Host: flvdl7a8e4223.haha.com' 'http://127.0.0.1/http_dynamic_test/test'
curl -v -H 'Host: www.sohu.com' 'http://127.0.0.1/http_dynamic_test/test'
curl -v -H 'Host: v.qq.com' 'http://127.0.0.1/http_dynamic_test/test'
- Location for http
- no location
curl -v -H 'Host: flvdl7a8e4223.haha.com' 'http://127.0.0.1/'
- location = /
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/'
- location /
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/t'
- location ^~ /test1/
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test1/123'
- ~* \.(gif|jpg|jpeg)$
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test/123.gif'
- /test
curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test/123'
@@ -1,157 +0,0 @@
# Module ngx-dynamic-resolver-module
---
## Instructions
System will resolver domain in dynamic resolver every few seconds configured.
The module will return addr whose domain is resolved in dynamic resolver, otherwise, the module will add domain into dynamic resolver, resolv domain by event resolver, and call callback when resolved.
## Directives
Syntax : dynamic_refresh_interval time;
Default : dynamic_refresh_interval 5m;
Context : events
Set time interval for DNS query frequency, 0 for shutdown this function.
Syntax : dynamic_domain_buckets number;
Default : dynamic_domain_buckets 101;
Context : events
Bucket for dynamic resolver domain hash table. Use prime key is Recommended.
Example:
events {
resolver 192.168.84.254 valid=1m;
dynamic_refresh_interval 5m;
dynamic_domain_buckets 1001;
}
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_dynamic_resolver.h"
**start resolver**
void ngx_dynamic_resolver_start_resolver(ngx_str_t *domain,
ngx_dynamic_resolver_handler_pt h, void *data);
- return value:
- None
- paras:
- domain: domain for DNS query
- h : callback handler
- data : data for callback
h's protype is:
typedef void (* ngx_dynamic_resolver_handler_pt)(void *data,
struct sockaddr *sa, socklen_t socklen);
- return value:
- None
- paras:
- data : user private data set in ngx\_dynamic\_resolver\_start\_resolver
- sa : sock address get
- socklen: sock address len, 0 for get none address
**gethostbyname**
socklen_t ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain, struct sockaddr *sa);
- return value:
- socklen for successd
- 0 for failed
- paras:
- domain: domain for query
- sa : sock address get
**add domain**
void ngx_dynamic_resolver_add_domain(ngx_str_t *domain);
- return value:
- None
- paras:
- domain: domain for query
**del domain**
void ngx_dynamic_resolver_del_domain(ngx_str_t *domain);
- return value:
- None
- paras:
- domain: domain for DNS query
## Build
cd to NGINX source directory & run this:
./configure --add-module=/path/to/nginx-toolkit-module/
make && make install
## Example
See t/ngx\_dynamic\_resolver\_test\_module.c as reference
Build:
./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t
make && make install
Configure:
events {
resolver 192.168.84.254 valid=1m;
dynamic_refresh_interval 5m;
}
http {
...
server {
...
location /dynamic_resolver_test/ {
dynamic_resolver_test 192.168.84.4 www.test1.com;
}
}
}
Test:
- sync resolver
curl -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test1.com&sync=1'
- start resolver
curl -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test.com'
- del domain
curl -XDELETE -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test.com'
@@ -1,126 +0,0 @@
# Module ngx-event-resolver-module
---
## Instructions
Common resovler in event modules, just like http resolver, stream resolver in nginx, but can be used by http modules, stream modules and other modules
## Directives
Syntax : resolver address ... [valid=time] [ipv6=on|off];
Default : -
Context : events
Configures name servers used to resolve names into addresses, for example:
> resolver 127.0.0.1 [::1]:5353;
An address can be specified as a domain name or IP address, and an optional port. If port is not specified, the port 53 is used. Name servers are queried in a round-robin fashion.
By default, nginx will look up both IPv4 and IPv6 addresses while resolving. If looking up of IPv6 addresses is not desired, the ipv6=off parameter can be specified.
By default, nginx caches answers using the TTL value of a response. The optional valid parameter allows overriding it:
> resolver 127.0.0.1 [::1]:5353 valid=30s;
Syntax : resolver_timeout time;
Default : resolver_timeout 60s;
Context : events
Sets a timeout for name resolution, for example:
> resolver\_timeout 5s;
Example:
events {
resolver 192.168.84.254 valid=20s;
resolver_timeout 10s;
}
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_event_resolver.h"
**resolver a domain**
void ngx_event_resolver_start_resolver(ngx_str_t *domain,
ngx_event_resolver_handler_pt h, void *data);
- return value:
None
- paras:
- domain: domain for resolving
- h : callback handler
- data : data for callback
h's protype is:
typedef void (* ngx_event_resolver_handler_pt)(void *data,
ngx_resolver_addr_t *addrs, ngx_uint_t naddrs);
- return value:
None
- paras:
- data : user private data set in ngx\_event\_resolver\_start\_resolver
- addrs : addrs resolv by DNS
- naddrs: number of addrs resolv by DNS
## Build
cd to NGINX source directory & run this:
./configure --add-module=/path/to/nginx-toolkit-module/
make && make install
## Example
See t/ngx\_event\_resolver\_test\_module.c as reference
Build:
./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t
make && make install
Configure:
events {
resolver 192.168.84.254 114.114.114.114 valid=20s;
resolver_timeout 10s;
}
http {
...
server {
...
location /event_resolver_test/ {
event_resolver_test;
}
}
}
Install bind server
/path/to/nginx-toolkit-module/t/dns_install.sh
modify /var/named/test.com.zone dns ip address to fit your enviroment
Test:
- add domain for resolving
curl -v "http://127.0.0.1/event_resolver_test/domain?domain=www.test.com"
@@ -1,112 +0,0 @@
# Module ngx-event-timer-module
---
## Instructions
Independent timer for nginx
## Directives
Syntax : worker_timers number;
Default : worker_timers 1024;
Context : events
Sets the maximum number of timers that can be used in worker process.
events {
...
worker_timers 1024;
}
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_event_timer_module.h"
**registe domain**
ngx_int_t ngx_event_timer_add_timer(ngx_msec_t tv,
ngx_timer_handler_pt h, void *data);
- return value:
return timerid for successd, NGX_ERROR for failed.
Error:
- h is NULL
- not enough timer for assigned
- paras:
- tv : timer interval to trigger handler
- h : timer handler
- data : data of h para
Register a timer handler, timer interval is tv, measured by millisecond. When timer triggered, h will be called, using data as function parameters.
h's protype is:
typedef void (* ngx_timer_handler_pt)(void *data);
- return value:
None
- paras:
- data: data set in ngx\_event\_timer\_add\_timer, for paras transmit
**del timer**
void ngx_event_timer_del_timer(ngx_uint_t timerid);
- return value:
void
- paras:
- timerid: return by ngx\_event\_timer\_add\_timer
Deregister timer handler.
## Build
cd to NGINX source directory & run this:
./configure --add-module=/path/to/nginx-toolkit-module/
make && make install
## Example
See t/ngx\_event\_timer\_test\_module.c as reference
Build:
./configure --add-module=/path/to/nginx-toolkit-module/t/ --add-module=/path/to/nginx-toolkit-module/
make && make install
Configure:
location /event_timer_test/ {
event_timer_test;
}
Test:
add timer
curl -XPOST -v "http://127.0.0.1/event_timer_test/timer?time=3s"
Test module will start a timer when process init. It will log after 3 seconds, set in args:
2016/12/10 18:48:37 [error] 20295#0: event timer test timer handler
del timer
curl -XDELETE -v "http://127.0.0.1/event_timer_test/timer?timerid=1"
Test module will stop a timer whose timerid is 1
@@ -1,112 +0,0 @@
# ngx-map
---
## Instructions
A map implement use ngx_rbtree
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_map.h"
**structure**
typedef struct {
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_map_hash_pt hash;
ngx_cmp_pt cmp;
} ngx_map_t;
typedef struct {
ngx_rbtree_node_t rn;
intptr_t raw_key;
ngx_map_t *map;
} ngx_map_node_t;
use ngx\_map\_t instance as a map, use ngx\_map\_init to initial. Put ngx\_map\_node\_t in your structure, and set raw_key, then you can insert your node in the map. Use raw_key, you can find node in map, or delete node in map.
**ngx\_map\_init**
void ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp)
Interface for init a map, hash is hash func handler to calculate hashkey for rawkey, cmp is compare func handler for compare two raw_key, when raw_keys' hashkey is same.
We support base hash and cmp func as below:
/* ngx_str_t */
ngx_rbtree_key_t ngx_map_hash_str(intptr_t key)
int ngx_cmp_str(intptr_t key1, intptr_t key2)
/* ngx_uint_t */
ngx_rbtree_key_t ngx_map_hash_uint(intptr_t key)
int ngx_cmp_uint(intptr_t key1, intptr_t key2)
/* ngx_int_t */
ngx_rbtree_key_t ngx_map_hash_int(intptr_t key)
int ngx_cmp_int(intptr_t key1, intptr_t key2)
User also can use own hash and cmp func with protype below:
/*
* key: key for map node
*/
typedef ngx_rbtree_key_t (* ngx_map_hash_pt)(intptr_t key);
/*
* if key1 < key2, return -1
* if key1 = key2, return 0
* if key1 > key2, return 1
*/
typedef int (* ngx_cmp_pt)(intptr_t key1, intptr_t key2);
**ngx\_map\_empty**
#define ngx_map_empty(map) (map->rbtree.root == map->rbtree.sentinel)
If map is empty, return 1, else, return false
**ngx\_map\_begin**
ngx_map_node_t *ngx_map_begin(ngx_map_t *map)
Return the mininum key node of map
**ngx\_map\_rbegin**
ngx_map_node_t *ngx_map_rbegin(ngx_map_t *map)
Return the maxinum key node of map
**ngx\_map\_next**
ngx_map_node_t *ngx_map_next(ngx_map_node_t *n)
Return the next node of n, if n is the maximum key node in map, return NULL
**ngx\_map\_prev**
ngx_map_node_t *ngx_map_prev(ngx_map_node_t *n)
Return the previous node of n, if n is the mininum key node in map, return NULL
**ngx\_map\_insert**
void ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered)
Interface for insert a node in map. New node will force replace old node in map if raw_key is same when covered set to 1. Otherwise, new node can't insert in map
**ngx\_map\_delete**
void ngx_map_delete(ngx_map_t *map, intptr_t key)
Interface for delete a node in map, if node's raw_key equal to key in paras. If node is not exist, do nothing.
**ngx\_map\_find**
ngx_map_node_t *ngx_map_find(ngx_map_t *map, intptr_t key)
Interface for find a node in map, if node's raw_key equal to key in paras. If node is not exist, return NULL.
@@ -1,19 +0,0 @@
# ngx-poold
---
## Instructions
Pool debug for check whether pool is destroy or destroy twice
## API
**NGX\_CREATE\_POOL**
#define NGX_CREATE_POOL(size, log)
Replace NGX\_CREATE\_POOL instead of ngx\_create\_pool, it will record position creating pool. must use with NGX\_DESTROY\_POOL
**NGX\_DESTROY\_POOL**
#define NGX_DESTROY_POOL(pool)
Replace NGX\_DESTROY\_POOL instead of ngx\_destroy\_pool, it will delete info which NGX\_CREATE\_POOL add. If pool not register in record pool, the pool will not destroy, and log delete twice log and position call the NGX\_DESTROY\_POOL.
@@ -1,40 +0,0 @@
# ngx-rbuf
---
## Instructions
A recycled chainbuf for nginx
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_rbuf.h"
**ngx\_get\_chainbuf**
ngx_chain_t *ngx_get_chainbuf(size_t size, ngx_flag_t alloc_rbuf);
Interface for get a chain with buf, if alloc\_rbuf is set to 1, rbuf will alloc a buf with size set in paras; if alloc\_rbuf is set to 0, size is nonsense here.
Notice, for recycled buf better memory manager, the size should be same for the same usage. Such as chunk size in nginx rtmp module.
**ngx\_put\_chainbuf**
void ngx_put_chainbuf(ngx_chain_t *cl);
Interface for recycle chain with buf alloc from rbuf
**ngx\_rbuf\_statee**
ngx_chain_t *ngx_rbuf_state(ngx_http_request_t *r);
Interface for query rbuf state, result:
ngx_rbuf_nalloc_node: 1
ngx_rbuf_nalloc_buf: 1
ngx_rbuf_nfree_buf: 1
ngx_rbuf_nalloc_chain: 3
ngx_rbuf_nalloc_chain: 3
@@ -1,89 +0,0 @@
# ngx-toolkit-misc
---
## Instructions
Misc toolkit functions
## API
**header file**
For using this API, You should include the header file as below:
#include "ngx_toolkit_misc.h"
**structure**
/*
* scheme://[user@]host[:port]/path[?args][#fragment]
*/
typedef struct {
ngx_str_t scheme;
ngx_str_t user;
ngx_str_t host;
ngx_str_t port;
ngx_str_t path;
ngx_str_t args;
ngx_str_t fragment;
ngx_str_t host_with_port; /* host[:port] */
ngx_str_t uri_with_args; /* /path[?args][#fragment] */
} ngx_request_url_t;
**ngx\_parse\_request\_url**
ngx_int_t ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url);
parse request url format as: scheme://[user@]host[:port]/path[?args][#fragment]
- return value:
- NGX_OK: parse success
- NGX_ERROR: request url format error
- paras:
- request_url: url parse result return to user, all paras in request url is segment point to url
- url: request url for parse
**ngx\_request\_port**
in_port_t ngx_request_port(ngx_str_t *scheme, ngx_str_t *port);
convert port to in_port_t according to scheme and port
- return value:
- If port is set to correct number range in [1, 65535], return port
- If port is set to non correct value, return 0
- If port is not set, return default value for scheme:
- 80 for http
- 443 for https
- 1935 for rtmp
- 0 for others now
- values:
- scheme : sheme string like http https or rtmp
- port : port for convert to in_port_t
**ngx\_md5\_file**
#define NGX_MD5KEY_LEN 32
ngx_int_t ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN]);
calculating file md5key as md5sum in shell
- return value:
- NGX_OK: calculating success
- NGX_ERROR: calculating error such as file is not exist
- paras:
- fd: file desc for calculating md5key
- md5key: md5key result
@@ -1,963 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_dynamic_conf.h"
#include "ngx_toolkit_misc.h"
#include "ngx_event_timer_module.h"
static ngx_int_t ngx_dynamic_conf_process_init(ngx_cycle_t *cycle);
static void *ngx_dynamic_conf_module_create_conf(ngx_cycle_t *cycle);
static char *ngx_dynamic_conf_module_init_conf(ngx_cycle_t *cycle, void *conf);
static char *ngx_dynamic_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_dynamic_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
#define NGX_CONF_BUFFER 4096
ngx_uint_t ngx_core_max_module;
static ngx_uint_t arg_number[] = {
NGX_CONF_NOARGS,
NGX_CONF_TAKE1,
NGX_CONF_TAKE2,
NGX_CONF_TAKE3,
NGX_CONF_TAKE4,
NGX_CONF_TAKE5,
NGX_CONF_TAKE6,
NGX_CONF_TAKE7
};
typedef struct {
void **module_conf; /* index is module index */
ngx_pool_t *pool; /* dynamic conf alloc pool */
} ngx_dynamic_conf_ctx_t;
typedef struct {
ngx_dynamic_conf_ctx_t *conf[2];
unsigned used; /* 0 and 1 for index of conf */
ngx_str_t file;
ngx_msec_t refresh;
ngx_log_t *log;
u_char md5key[NGX_MD5KEY_LEN + 1];
} ngx_dynamic_conf_conf_t;
static ngx_command_t ngx_dynamic_conf_commands[] = {
{ ngx_string("dynamic_conf"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE2,
ngx_dynamic_conf,
0,
0,
NULL },
{ ngx_string("dynamic_log"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
ngx_dynamic_log,
0,
0,
NULL },
ngx_null_command
};
ngx_core_module_t ngx_dynamic_conf_module_ctx = {
ngx_string("dynamic_conf"),
ngx_dynamic_conf_module_create_conf,
ngx_dynamic_conf_module_init_conf
};
ngx_module_t ngx_dynamic_conf_module = {
NGX_MODULE_V1,
&ngx_dynamic_conf_module_ctx, /* module context */
ngx_dynamic_conf_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_dynamic_conf_process_init, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_dynamic_conf_module_create_conf(ngx_cycle_t *cycle)
{
ngx_dynamic_conf_conf_t *conf;
conf = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_conf_conf_t));
if (conf == NULL) {
return NULL;
}
conf->refresh = NGX_CONF_UNSET_MSEC;
return conf;
}
static char *
ngx_dynamic_conf_module_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_dynamic_conf_conf_t *dccf;
dccf = conf;
ngx_conf_init_msec_value(dccf->refresh, 60000);
if (dccf->log == NULL) {
dccf->log = &cycle->new_log;
}
return NGX_CONF_OK;
}
static char *
ngx_dynamic_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_dynamic_conf_conf_t *dccf;
ngx_str_t *value;
ngx_fd_t fd;
dccf = conf;
if (dccf->file.len) {
return "is duplicate";
}
value = cf->args->elts;
dccf->file = value[1];
if (ngx_conf_full_name(cf->cycle, &dccf->file, 0)) {
return NGX_CONF_ERROR;
}
/* test file, ngx_conf_full_name will fill '\0' at end of file name */
fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, "dynamic conf "
ngx_open_file_n " \"%s\" failed", dccf->file.data);
return NGX_CONF_ERROR;
}
ngx_close_file(fd);
dccf->refresh = ngx_parse_time(&value[2], 0);
if (dccf->refresh == (ngx_msec_t) NGX_ERROR) {
return "invalid refresh";
}
dccf->used = 1;
return NGX_CONF_OK;
}
static char *
ngx_dynamic_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_dynamic_conf_conf_t *dccf = conf;
return ngx_log_set_log(cf, &dccf->log);
}
static ngx_int_t
ngx_dynamic_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
char *rv;
ngx_uint_t i, found;
ngx_str_t *name;
ngx_command_t *cmd;
void *conf;
name = cf->args->elts;
found = 0;
for (i = 0; cf->cycle->modules[i]; ++i) {
cmd = (ngx_command_t *) cf->cycle->modules[i]->spare_hook1;
if (cmd == NULL) {
continue;
}
for (/* void */; cmd->name.len; ++cmd) {
if (name->len != cmd->name.len) {
continue;
}
if (ngx_strcmp(name->data, cmd->name.data) != 0) {
continue;
}
found = 1;
if (cf->cycle->modules[i]->type != NGX_CONF_MODULE
&& cf->cycle->modules[i]->type != cf->module_type)
{
continue;
}
/* is the directive's location right ? */
if (!(cmd->type & cf->cmd_type)) {
continue;
}
if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"directive \"%s\" is not terminated by \";\"",
name->data);
return NGX_ERROR;
}
if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"directive \"%s\" has no opening \"{\"",
name->data);
return NGX_ERROR;
}
/* is the directive's argument count right ? */
if (!(cmd->type & NGX_CONF_ANY)) {
if (cmd->type & NGX_CONF_FLAG) {
if (cf->args->nelts != 2) {
goto invalid;
}
} else if (cmd->type & NGX_CONF_1MORE) {
if (cf->args->nelts < 2) {
goto invalid;
}
} else if (cmd->type & NGX_CONF_2MORE) {
if (cf->args->nelts < 3) {
goto invalid;
}
} else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
goto invalid;
} else if (!(cmd->type & arg_number[cf->args->nelts - 1])) {
goto invalid;
}
}
/* set up the directive's configuration context */
conf = ((void **) cf->ctx)[cf->cycle->modules[i]->ctx_index];
rv = cmd->set(cf, cmd, conf);
if (rv == NGX_CONF_OK) {
return NGX_OK;
}
if (rv == NGX_CONF_ERROR) {
return NGX_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"%s\" directive %s", name->data, rv);
return NGX_ERROR;
}
}
if (found) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"%s\" directive is not allowed here", name->data);
return NGX_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown directive \"%s\"", name->data);
return NGX_ERROR;
invalid:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid number of arguments in \"%s\" directive",
name->data);
return NGX_ERROR;
}
/* same as ngx_conf_read_token in ngx_conf_file.c */
static ngx_int_t
ngx_dynamic_conf_read_token(ngx_conf_t *cf)
{
u_char *start, ch, *src, *dst;
off_t file_size;
size_t len;
ssize_t n, size;
ngx_uint_t found, need_space, last_space, sharp_comment,
variable;
ngx_uint_t quoted, s_quoted, d_quoted, start_line;
ngx_str_t *word;
ngx_buf_t *b;
found = 0;
need_space = 0;
last_space = 1;
sharp_comment = 0;
variable = 0;
quoted = 0;
s_quoted = 0;
d_quoted = 0;
cf->args->nelts = 0;
b = cf->conf_file->buffer;
start = b->pos;
start_line = cf->conf_file->line;
file_size = ngx_file_size(&cf->conf_file->file.info);
for ( ;; ) {
if (b->pos >= b->last) {
if (cf->conf_file->file.offset >= file_size) {
if (cf->args->nelts > 0 || !last_space) {
if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of parameter, "
"expecting \";\"");
return NGX_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of file, "
"expecting \";\" or \"}\"");
return NGX_ERROR;
}
return NGX_CONF_FILE_DONE;
}
len = b->pos - start;
if (len == NGX_CONF_BUFFER) {
cf->conf_file->line = start_line;
if (d_quoted) {
ch = '"';
} else if (s_quoted) {
ch = '\'';
} else {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"too long parameter \"%*s...\" started",
10, start);
return NGX_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"too long parameter, probably "
"missing terminating \"%c\" character", ch);
return NGX_ERROR;
}
if (len) {
ngx_memmove(b->start, start, len);
}
size = (ssize_t) (file_size - cf->conf_file->file.offset);
if (size > b->end - (b->start + len)) {
size = b->end - (b->start + len);
}
n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
cf->conf_file->file.offset);
if (n == NGX_ERROR) {
return NGX_ERROR;
}
if (n != size) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
ngx_read_file_n " returned "
"only %z bytes instead of %z",
n, size);
return NGX_ERROR;
}
b->pos = b->start + len;
b->last = b->pos + n;
start = b->start;
}
ch = *b->pos++;
if (ch == LF) {
cf->conf_file->line++;
if (sharp_comment) {
sharp_comment = 0;
}
}
if (sharp_comment) {
continue;
}
if (quoted) {
quoted = 0;
continue;
}
if (need_space) {
if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
last_space = 1;
need_space = 0;
continue;
}
if (ch == ';') {
return NGX_OK;
}
if (ch == '{') {
return NGX_CONF_BLOCK_START;
}
if (ch == ')') {
last_space = 1;
need_space = 0;
} else {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected \"%c\"", ch);
return NGX_ERROR;
}
}
if (last_space) {
if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
continue;
}
start = b->pos - 1;
start_line = cf->conf_file->line;
switch (ch) {
case ';':
case '{':
if (cf->args->nelts == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected \"%c\"", ch);
return NGX_ERROR;
}
if (ch == '{') {
return NGX_CONF_BLOCK_START;
}
return NGX_OK;
case '}':
if (cf->args->nelts != 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected \"}\"");
return NGX_ERROR;
}
return NGX_CONF_BLOCK_DONE;
case '#':
sharp_comment = 1;
continue;
case '\\':
quoted = 1;
last_space = 0;
continue;
case '"':
start++;
d_quoted = 1;
last_space = 0;
continue;
case '\'':
start++;
s_quoted = 1;
last_space = 0;
continue;
default:
last_space = 0;
}
} else {
if (ch == '{' && variable) {
continue;
}
variable = 0;
if (ch == '\\') {
quoted = 1;
continue;
}
if (ch == '$') {
variable = 1;
continue;
}
if (d_quoted) {
if (ch == '"') {
d_quoted = 0;
need_space = 1;
found = 1;
}
} else if (s_quoted) {
if (ch == '\'') {
s_quoted = 0;
need_space = 1;
found = 1;
}
} else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
|| ch == ';' || ch == '{')
{
last_space = 1;
found = 1;
}
if (found) {
word = ngx_array_push(cf->args);
if (word == NULL) {
return NGX_ERROR;
}
word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1);
if (word->data == NULL) {
return NGX_ERROR;
}
for (dst = word->data, src = start, len = 0;
src < b->pos - 1;
len++)
{
if (*src == '\\') {
switch (src[1]) {
case '"':
case '\'':
case '\\':
src++;
break;
case 't':
*dst++ = '\t';
src += 2;
continue;
case 'r':
*dst++ = '\r';
src += 2;
continue;
case 'n':
*dst++ = '\n';
src += 2;
continue;
}
}
*dst++ = *src++;
}
*dst = '\0';
word->len = len;
if (ch == ';') {
return NGX_OK;
}
if (ch == '{') {
return NGX_CONF_BLOCK_START;
}
found = 0;
}
}
}
}
ngx_int_t
ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init)
{
ngx_int_t rc;
enum {
parse_init = 0,
parse_block
} type;
type = init ? parse_init : parse_block;
for (;;) {
rc = ngx_dynamic_conf_read_token(cf);
/*
* ngx_conf_read_token() may return
*
* NGX_ERROR there is error
* NGX_OK the token terminated by ";" was found
* NGX_CONF_BLOCK_START the token terminated by "{" was found
* NGX_CONF_BLOCK_DONE the "}" was found
* NGX_CONF_FILE_DONE the configuration file is done
*/
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_CONF_BLOCK_DONE) {
if (type != parse_block) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
return NGX_ERROR;
}
return NGX_OK;
}
if (rc == NGX_CONF_FILE_DONE) {
if (type == parse_block) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of file, expecting \"}\"");
return NGX_ERROR;
}
return NGX_OK;
}
rc = ngx_dynamic_conf_handler(cf, rc);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
}
}
static ngx_int_t
ngx_dynamic_conf_load_conf(ngx_fd_t fd, ngx_dynamic_conf_conf_t *dccf)
{
ngx_dynamic_conf_ctx_t *conf;
ngx_dynamic_core_module_t *module;
ngx_pool_t *pool;
ngx_conf_t cf;
ngx_buf_t buf;
ngx_conf_file_t conf_file;
u_char buffer[NGX_CONF_BUFFER];
ngx_uint_t i;
void *rv;
ngx_memzero(&cf, sizeof(ngx_conf_t));
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, dccf->log);
if (pool == NULL) {
return NGX_ERROR;
}
pool->log = dccf->log;
conf = ngx_pcalloc(pool, sizeof(ngx_dynamic_conf_ctx_t));
if (conf == NULL) {
goto failed;
}
conf->pool = pool;
ngx_core_max_module = ngx_count_modules((ngx_cycle_t *) ngx_cycle,
NGX_CORE_MODULE);
conf->module_conf = ngx_pcalloc(pool, sizeof(void *) * ngx_core_max_module);
if (conf->module_conf == NULL) {
goto failed;
}
cf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
if (cf.args == NULL) {
goto failed;
}
cf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, dccf->log);
if (cf.temp_pool == NULL) {
goto failed;
}
cf.ctx = conf->module_conf;
cf.cycle = (ngx_cycle_t *) ngx_cycle;
cf.pool = pool;
cf.log = dccf->log;
cf.module_type = NGX_CORE_MODULE;
cf.cmd_type = NGX_MAIN_CONF;
cf.conf_file = &conf_file;
if (ngx_fd_info(fd, &cf.conf_file->file.info) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cf.log, ngx_errno,
ngx_fd_info_n " failed");
}
cf.conf_file->buffer = &buf;
buf.pos = buf.last = buf.start = buffer;
buf.end = buf.start + NGX_CONF_BUFFER;
buf.temporary = 1;
cf.conf_file->file.fd = fd;
cf.conf_file->file.name.len = dccf->file.len;
cf.conf_file->file.name.data = dccf->file.data;
cf.conf_file->file.offset = 0;
cf.conf_file->file.log = cf.log;
cf.conf_file->line = 1;
for (i = 0; ngx_cycle->modules[i]; ++i) {
if (ngx_cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = (ngx_dynamic_core_module_t *)
ngx_cycle->modules[i]->spare_hook0;
if (module == NULL) { /* dctx not configured */
continue;
}
if (module->create_conf) {
rv = module->create_conf(&cf);
if (rv == NULL) {
goto failed;
}
conf->module_conf[ngx_cycle->modules[i]->ctx_index] = rv;
}
}
if (ngx_dynamic_conf_parse(&cf, 1) != NGX_OK) {
goto failed;
}
for (i = 0; ngx_cycle->modules[i]; ++i) {
if (ngx_cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = (ngx_dynamic_core_module_t *) ngx_cycle->modules[i]->
spare_hook0;
if (module == NULL) {
continue;
}
if (module->init_conf) {
rv = conf->module_conf[ngx_cycle->modules[i]->ctx_index];
if (module->init_conf(&cf, rv) == NGX_CONF_ERROR) {
goto failed;
}
}
}
/* load conf ok, switch conf to new conf */
if (dccf->conf[dccf->used]) {
pool = dccf->conf[dccf->used]->pool;
dccf->conf[dccf->used] = NULL;
ngx_destroy_pool(pool);
}
dccf->used = dccf->used ? 0 : 1;
dccf->conf[dccf->used] = conf;
return NGX_OK;
failed:
if (cf.temp_pool) {
ngx_destroy_pool(cf.temp_pool);
}
ngx_destroy_pool(pool);
return NGX_ERROR;
}
static void
ngx_dynamic_conf_check_conf(void *data)
{
ngx_dynamic_conf_conf_t *dccf;
ngx_fd_t fd;
u_char md5key[NGX_MD5KEY_LEN];
NGX_START_TIMING
dccf = data;
if (ngx_exiting) { /* avoid nginx reload worker hungup */
return;
}
fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_ERR, dccf->log, ngx_errno,
ngx_open_file_n "\"%V\" failed", &dccf->file);
goto done;
}
/* check md5key for dynamic conf file */
if (ngx_md5_file(fd, md5key) == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "md5 file \"%V\" failed",
&dccf->file);
goto done;
}
if (ngx_memcmp(dccf->md5key, md5key, NGX_MD5KEY_LEN) == 0) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, dccf->log, 0,
"\"%V\" md5key not change", &dccf->file);
goto done;
}
/* parse dynamic conf */
if (ngx_dynamic_conf_load_conf(fd, dccf) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "load file \"%V\" failed",
&dccf->file);
goto done;
}
ngx_memcpy(dccf->md5key, md5key, NGX_MD5KEY_LEN);
ngx_log_error(NGX_LOG_INFO, dccf->log, 0,
"dynamic conf load successd, md5key: \"%s\"", dccf->md5key);
done:
ngx_close_file(fd);
ngx_event_timer_add_timer(dccf->refresh, ngx_dynamic_conf_check_conf, dccf);
NGX_STOP_TIMING(dccf->log, "ngx_dynamic_conf_check_conf")
}
static ngx_int_t ngx_dynamic_conf_process_init(ngx_cycle_t *cycle)
{
ngx_dynamic_conf_conf_t *dccf;
ngx_fd_t fd;
u_char md5key[NGX_MD5KEY_LEN];
NGX_START_TIMING
dccf = (ngx_dynamic_conf_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_dynamic_conf_module);
if (dccf->file.len == 0) { /* dynamic conf not configured */
return NGX_OK;
}
fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_ERR, dccf->log, ngx_errno,
ngx_open_file_n "\"%V\" failed", &dccf->file);
return NGX_ERROR;
}
/* parse dynamic conf */
if (ngx_dynamic_conf_load_conf(fd, dccf) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "load file \"%V\" failed",
&dccf->file);
return NGX_ERROR;
}
/* calc md5key for dynamic conf file */
if (ngx_md5_file(fd, md5key) == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "md5 file \"%V\" failed",
&dccf->file);
return NGX_ERROR;
}
ngx_close_file(fd);
ngx_memcpy(dccf->md5key, md5key, NGX_MD5KEY_LEN);
ngx_log_error(NGX_LOG_INFO, dccf->log, 0,
"dynamic conf load successd, md5key: \"%s\"", dccf->md5key);
/* add dynamic conf parse timer */
ngx_event_timer_add_timer(dccf->refresh, ngx_dynamic_conf_check_conf, dccf);
NGX_STOP_TIMING(dccf->log, "ngx_dynamic_conf_process_init")
return NGX_OK;
}
#if (NGX_PCRE)
ngx_dynamic_regex_t *
ngx_dynamic_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
{
ngx_dynamic_regex_t *re;
rc->pool = cf->pool;
if (ngx_regex_compile(rc) != NGX_OK) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
return NULL;
}
re = ngx_pcalloc(cf->pool, sizeof(ngx_regex_elt_t));
if (re == NULL) {
return NULL;
}
re->regex = rc->regex;
re->name = rc->pattern;
return re;
}
#endif
int
ngx_dynamic_cmp_dns_wildcards(const void *one, const void *two)
{
ngx_hash_key_t *first, *second;
first = (ngx_hash_key_t *) one;
second = (ngx_hash_key_t *) two;
return ngx_dns_strcmp(first->key.data, second->key.data);
}
void *
ngx_get_dconf(ngx_module_t *m)
{
ngx_dynamic_conf_conf_t *dccf;
dccf = (ngx_dynamic_conf_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_dynamic_conf_module);
if (dccf->conf[dccf->used] == 0) { /* dynamic conf not configured */
return NULL;
}
return dccf->conf[dccf->used]->module_conf[m->ctx_index];
}
@@ -1,84 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_DYNAMIC_COMMAND_H_INCLUDED_
#define _NGX_DYNAMIC_COMMAND_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
typedef struct {
ngx_str_t name;
void *(*create_conf)(ngx_conf_t *cf);
char *(*init_conf)(ngx_conf_t *cf, void *conf);
} ngx_dynamic_core_module_t;
#if (NGX_PCRE)
typedef struct {
ngx_regex_t *regex;
ngx_str_t name;
} ngx_dynamic_regex_t;
#endif
#if 0
/*
* if use dynamic conf, module define should use
* NGX_MODULE_V1_DYNAMIC_PADDING and set
* module dynamic context and
* module dynamic directives as bellow
*/
ngx_module_t ngx_test_module = {
NGX_MODULE_V1,
&ngx_test_module_ctx, /* module context */
ngx_test_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
&ngx_test_module_dctx, /* module dynamic context */
ngx_test_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
#endif
#define NGX_MODULE_V1_DYNAMIC_PADDING 0, 0, 0, 0, 0, 0
extern ngx_uint_t ngx_core_max_module;
/*
* return value:
* return NGX_OK for successd, NGX_ERROR for failed
* paras:
* cf: ngx_conf_t passed from ngx_dynamic_conf_load_conf
* init: only ngx_dynamic_conf_load_conf set 1, otherwise set 0
*/
ngx_int_t ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init);
/*
* return value:
* return regex context
* paras:
* cf: ngx_conf_t passed in dynamic cmd handler
* rc: regex options
*/
#if (NGX_PCRE)
ngx_dynamic_regex_t *ngx_dynamic_regex_compile(ngx_conf_t *cf,
ngx_regex_compile_t *rc);
#endif
int ngx_dynamic_cmp_dns_wildcards(const void *one, const void *two);
void *ngx_get_dconf(ngx_module_t *m);
#endif
@@ -1,700 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include "ngx_event_timer_module.h"
#include "ngx_event_resolver.h"
#include "ngx_dynamic_resolver.h"
#include "ngx_toolkit_misc.h"
static ngx_int_t ngx_dynamic_resolver_process_init(ngx_cycle_t *cycle);
static void *ngx_dynamic_resolver_create_conf(ngx_cycle_t *cycle);
static char *ngx_dynamic_resolver_init_conf(ngx_cycle_t *cycle, void *conf);
#define MAX_DOMAIN_LEN 128
#define MAX_ADDRS 8
typedef struct ngx_dynamic_resolver_ctx_s ngx_dynamic_resolver_ctx_t;
typedef struct ngx_dynamic_resolver_domain_s ngx_dynamic_resolver_domain_t;
struct ngx_dynamic_resolver_ctx_s {
ngx_dynamic_resolver_handler_pt h;
void *data;
ngx_dynamic_resolver_ctx_t *next;
};
typedef struct {
struct sockaddr sockaddr;
socklen_t socklen;
u_short priority;
u_short weight;
} ngx_dynamic_resolver_addr_t;
struct ngx_dynamic_resolver_domain_s {
ngx_str_t domain;
u_char domain_cstr[MAX_DOMAIN_LEN];
ngx_uint_t naddrs;
ngx_dynamic_resolver_addr_t addrs[MAX_ADDRS];
ngx_dynamic_resolver_ctx_t *ctx;
ngx_dynamic_resolver_domain_t *next;
};
typedef struct {
ngx_msec_t refresh_interval;
size_t domain_buckets;
ngx_dynamic_resolver_domain_t **resolver_hash;
ngx_dynamic_resolver_ctx_t *free_ctx;
ngx_dynamic_resolver_domain_t *free_domain;
ngx_uint_t nalloc_ctx;
ngx_uint_t nfree_ctx;
ngx_uint_t nalloc_domain;
ngx_uint_t nfree_domain;
} ngx_dynamic_resolver_conf_t;
static ngx_str_t dynamic_resolver_name = ngx_string("dynamic_resolver");
static ngx_command_t ngx_dynamic_resolver_commands[] = {
{ ngx_string("dynamic_refresh_interval"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
0,
offsetof(ngx_dynamic_resolver_conf_t, refresh_interval),
NULL },
{ ngx_string("dynamic_domain_buckets"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_dynamic_resolver_conf_t, domain_buckets),
NULL },
ngx_null_command
};
ngx_event_module_t ngx_dynamic_resolver_module_ctx = {
&dynamic_resolver_name,
ngx_dynamic_resolver_create_conf, /* create configuration */
ngx_dynamic_resolver_init_conf, /* init configuration */
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/* this module use ngx_cycle->log */
ngx_module_t ngx_dynamic_resolver_module = {
NGX_MODULE_V1,
&ngx_dynamic_resolver_module_ctx, /* module context */
ngx_dynamic_resolver_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_dynamic_resolver_process_init, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_dynamic_resolver_create_conf(ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *conf;
conf = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_resolver_conf_t));
if (conf == NULL) {
return NULL;
}
conf->refresh_interval = NGX_CONF_UNSET_MSEC;
conf->domain_buckets = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_dynamic_resolver_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_dynamic_resolver_conf_t *drcf = conf;
ngx_conf_init_msec_value(drcf->refresh_interval, 5000);
ngx_conf_init_uint_value(drcf->domain_buckets, 101);
if (drcf->refresh_interval > 0 && drcf->domain_buckets > 0) {
drcf->resolver_hash = ngx_pcalloc(cycle->pool,
sizeof(ngx_dynamic_resolver_domain_t *) * drcf->domain_buckets);
}
return NGX_CONF_OK;
}
/* reuse for ngx_dynamic_resolver_ctx_t */
static ngx_dynamic_resolver_ctx_t *
ngx_dynamic_resolver_get_ctx(ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_ctx_t *ctx;
drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module);
ctx = drcf->free_ctx;
if (ctx == NULL) {
ctx = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_resolver_ctx_t));
if (ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver, "
"alloc memory dynamic resolver ctx failed");
return NULL;
}
++drcf->nalloc_ctx;
} else {
drcf->free_ctx = drcf->free_ctx->next;
ngx_memzero(ctx, sizeof(ngx_dynamic_resolver_ctx_t));
--drcf->nfree_ctx;
}
return ctx;
}
static void
ngx_dynamic_resolver_put_ctx(ngx_dynamic_resolver_ctx_t *ctx,
ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module);
ctx->next = drcf->free_ctx;
drcf->free_ctx = ctx;
++drcf->nfree_ctx;
}
/* reuse for ngx_dynamic_resolver_domain_t */
static ngx_dynamic_resolver_domain_t *
ngx_dynamic_resolver_get_domain(ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t *domain;
drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module);
domain = drcf->free_domain;
if (domain == NULL) {
domain = ngx_pcalloc(cycle->pool,
sizeof(ngx_dynamic_resolver_domain_t));
if (domain == NULL) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver, "
"alloc memory dynamic resolver domain failed");
return NULL;
}
++drcf->nalloc_domain;
} else {
drcf->free_domain = drcf->free_domain->next;
ngx_memzero(domain, sizeof(ngx_dynamic_resolver_domain_t));
--drcf->nfree_domain;
}
return domain;
}
static void
ngx_dynamic_resolver_put_domain(ngx_dynamic_resolver_domain_t *domain,
ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module);
domain->next = drcf->free_domain;
drcf->free_domain = domain;
++drcf->nfree_domain;
}
static void
ngx_dynamic_resolver_on_result(void *data, ngx_resolver_addr_t *addrs,
ngx_uint_t naddrs)
{
ngx_dynamic_resolver_domain_t *domain;
ngx_dynamic_resolver_ctx_t *ctx;
ngx_uint_t i, n;
domain = data;
if (domain == NULL) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver, "
"%V has been deleted", &domain->domain);
return;
}
if (naddrs == 0) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver, "
"domain '%V' resolver failed", &domain->domain);
while (domain->ctx) {
ctx = domain->ctx;
domain->ctx = ctx->next;
ctx->h(ctx->data, NULL, 0);
ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle);
}
return;
}
domain->naddrs = ngx_min(naddrs, MAX_ADDRS);
for (i = 0; i < domain->naddrs; ++i) {
ngx_memcpy(&domain->addrs[i].sockaddr, addrs[i].sockaddr,
addrs[i].socklen);
domain->addrs[i].socklen = addrs[i].socklen;
domain->addrs[i].priority = addrs[i].priority;
domain->addrs[i].weight = addrs[i].weight;
n = ngx_random() % domain->naddrs;
while (domain->ctx) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver, resolver '%V' successd",
&domain->domain);
ctx = domain->ctx;
domain->ctx = ctx->next;
ctx->h(ctx->data, &domain->addrs[n].sockaddr,
domain->addrs[n].socklen);
ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle);
++n;
n %= domain->naddrs;
}
}
}
static void
ngx_dynamic_resolver_on_timer(void *data)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t *domain;
ngx_uint_t i;
if (ngx_exiting) {
return;
}
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
for (i = 0; i < drcf->domain_buckets; ++i) {
domain = drcf->resolver_hash[i];
while (domain) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver, on timer start resolver %V",
&domain->domain);
ngx_event_resolver_start_resolver(&domain->domain,
ngx_dynamic_resolver_on_result, domain);
domain = domain->next;
}
}
ngx_event_timer_add_timer(drcf->refresh_interval,
ngx_dynamic_resolver_on_timer, NULL);
}
static ngx_int_t
ngx_dynamic_resolver_process_init(ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
if (drcf->refresh_interval == 0) {
return NGX_OK;
}
ngx_event_timer_add_timer(0, ngx_dynamic_resolver_on_timer, NULL);
return NGX_OK;
}
void
ngx_dynamic_resolver_add_domain(ngx_str_t *domain, ngx_cycle_t *cycle)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t *d;
ngx_uint_t idx;
struct sockaddr sa;
socklen_t len;
u_char temp[MAX_DOMAIN_LEN];
if (domain == NULL || domain->len == 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"dynamic resolver add, domain is NULL");
return;
}
len = ngx_sock_pton(&sa, domain->data, domain->len);
/* addr is IP address */
if (len) {
ngx_log_error(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"dynamic resolver add, domain is ipv4/ipv6/unix address");
return;
}
drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module);
if (drcf->refresh_interval == 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver add, "
"dynamic resolver closed when add domain");
return;
}
if (domain->len > MAX_DOMAIN_LEN) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver add, "
"domain length(%z) is too long", domain->len);
return;
}
ngx_memzero(temp, MAX_DOMAIN_LEN);
idx = ngx_hash_strlow(temp, domain->data, domain->len);
idx %= drcf->domain_buckets;
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "dynamic resolver add, "
"prepare add %V in %d slot", domain, idx);
for (d = drcf->resolver_hash[idx]; d; d = d->next) {
if (d->domain.len == domain->len &&
ngx_memcmp(d->domain.data, temp, domain->len) == 0)
{
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"dynamic resolver add, %V is in dynamic resolv hash table",
domain);
return;
}
}
d = ngx_dynamic_resolver_get_domain(cycle);
if (d == NULL) {
return;
}
/* add domain in dynamic resolver */
d->next = drcf->resolver_hash[idx];
drcf->resolver_hash[idx] = d;
ngx_memcpy(d->domain_cstr, temp, MAX_DOMAIN_LEN);
d->domain.data = d->domain_cstr;
d->domain.len = domain->len;
}
void
ngx_dynamic_resolver_del_domain(ngx_str_t *domain)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t **pd, *d;
ngx_dynamic_resolver_ctx_t *ctx;
ngx_uint_t idx;
struct sockaddr sa;
socklen_t len;
u_char temp[MAX_DOMAIN_LEN];
if (domain == NULL || domain->len == 0) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic resolver del, domain is NULL");
return;
}
len = ngx_sock_pton(&sa, domain->data, domain->len);
/* addr is IP address */
if (len) {
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver del, domain is ipv4/ipv6/unix address");
return;
}
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
if (drcf->refresh_interval == 0) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver del, "
"dynamic resolver closed when del domain");
return;
}
if (domain->len > MAX_DOMAIN_LEN) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver del, "
"domain length(%z) is too long", domain->len);
return;
}
ngx_memzero(temp, MAX_DOMAIN_LEN);
idx = ngx_hash_strlow(temp, domain->data, domain->len);
idx %= drcf->domain_buckets;
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver del, "
"prepare del %V in %d slot", domain, idx);
for (pd = &drcf->resolver_hash[idx]; *pd; pd = &(*pd)->next) {
if ((*pd)->domain.len == domain->len &&
ngx_memcmp((*pd)->domain.data, temp, domain->len) == 0)
{
d= *pd;
*pd = (*pd)->next;
while (d->ctx) {
ctx = d->ctx;
d->ctx = ctx->next;
ctx->h(ctx->data, NULL, 0);
ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle);
}
ngx_dynamic_resolver_put_domain(d, (ngx_cycle_t *) ngx_cycle);
return;
}
}
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver del, "
"%V is not in dynamic resolv hash table", domain);
}
void
ngx_dynamic_resolver_start_resolver(ngx_str_t *domain,
ngx_dynamic_resolver_handler_pt h, void *data)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t *d;
ngx_dynamic_resolver_ctx_t *ctx;
ngx_uint_t idx, n;
struct sockaddr sa;
socklen_t len;
u_char temp[MAX_DOMAIN_LEN];
if (domain == NULL || domain->len == 0) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic resolver async, domain is NULL");
return;
}
len = ngx_sock_pton(&sa, domain->data, domain->len);
/* addr is ipv4/ipv6/unix address */
if (len) {
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver async, domain is ipv4/ipv6/unix address");
h(data, &sa, len);
return;
}
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
if (drcf->refresh_interval == 0) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver async, "
"dynamic resolver closed when start resolver");
goto failed;
}
if (domain->len > MAX_DOMAIN_LEN) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver async, "
"domain length(%z) is too long", domain->len);
goto failed;
}
ngx_memzero(temp, MAX_DOMAIN_LEN);
idx = ngx_hash_strlow(temp, domain->data, domain->len);
idx %= drcf->domain_buckets;
d = drcf->resolver_hash[idx];
while (d) {
if (d->domain.len == domain->len &&
ngx_memcmp(d->domain.data, temp, domain->len) == 0)
{
break;
}
d = d->next;
}
if (d == NULL) { /* not found */
d = ngx_dynamic_resolver_get_domain((ngx_cycle_t *) ngx_cycle);
if (d == NULL) {
goto failed;
}
/* add domain in dynamic resolver */
d->next = drcf->resolver_hash[idx];
drcf->resolver_hash[idx] = d;
ngx_memcpy(d->domain_cstr, temp, MAX_DOMAIN_LEN);
d->domain.data = d->domain_cstr;
d->domain.len = domain->len;
}
/* domain is not resolved */
if (d->naddrs == 0) {
/* add call back in resolver list */
ctx = ngx_dynamic_resolver_get_ctx((ngx_cycle_t *) ngx_cycle);
if (ctx == NULL) {
goto failed;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver async, domain '%V' is not resolved",
&d->domain);
ctx->h = h;
ctx->data = data;
ctx->next = d->ctx;
d->ctx = ctx;
ngx_event_resolver_start_resolver(&d->domain,
ngx_dynamic_resolver_on_result, d);
return;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver async, domain '%V' is resolved, call directly",
&d->domain);
/* call callback */
n = ngx_random() % d->naddrs;
h(data, &d->addrs[n].sockaddr, d->addrs[n].socklen);
return;
failed:
h(data, NULL, 0);
}
socklen_t
ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain, struct sockaddr *sa)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_dynamic_resolver_domain_t *d;
ngx_uint_t idx, n;
socklen_t len;
u_char temp[MAX_DOMAIN_LEN];
if (domain == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic resolver sync, domain is NULL");
return 0;
}
len = ngx_sock_pton(sa, domain->data, domain->len);
/* addr is ipv4/ipv6/unix address */
if (len) {
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"dynamic resolver sync, domain is ipv4/ipv6/unix address");
return len;
}
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
if (drcf->refresh_interval == 0) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver sync, "
"dynamic resolver closed when start resolver");
return 0;
}
if (domain->len > MAX_DOMAIN_LEN) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver sync, "
"domain length(%z) is too long", domain->len);
return 0;
}
ngx_memzero(temp, MAX_DOMAIN_LEN);
idx = ngx_hash_strlow(temp, domain->data, domain->len);
idx %= drcf->domain_buckets;
d = drcf->resolver_hash[idx];
while (d) {
if (d->domain.len == domain->len &&
ngx_memcmp(d->domain.data, temp, domain->len) == 0)
{
if (d->naddrs == 0) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"dynamic resolver sync, domain '%V' is not resolved",
&d->domain);
return 0;
}
n = ngx_random() % d->naddrs;
ngx_memcpy(sa, &d->addrs[n].sockaddr, d->addrs[n].socklen);
return d->addrs[n].socklen;
}
d = d->next;
}
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver sync, "
"domain '%V' is not in dynamic resolver table", domain);
return 0;
}
ngx_chain_t *
ngx_dynamic_resolver_state(ngx_http_request_t *r)
{
ngx_dynamic_resolver_conf_t *drcf;
ngx_chain_t *cl;
ngx_buf_t *b;
size_t len;
drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module);
len = sizeof("##########dynamic resolver state##########\n") - 1
+ sizeof("ngx_dynamic_resolver alloc ctx: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_dynamic_resolver free ctx: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_dynamic_resolver alloc domain: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_dynamic_resolver free domain: \n") - 1 + NGX_OFF_T_LEN;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########dynamic resolver state##########\n"
"ngx_dynamic_resolver alloc ctx: %ui\n"
"ngx_dynamic_resolver free ctx: %ui\n"
"ngx_dynamic_resolver alloc domain: %ui\n"
"ngx_dynamic_resolver free domain: %ui\n",
drcf->nalloc_ctx, drcf->nfree_ctx,
drcf->nalloc_domain, drcf->nfree_domain);
return cl;
}
@@ -1,75 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_DYNAMIC_RESOLVER_H_INCLUDED_
#define _NGX_DYNAMIC_RESOLVER_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
/*
* paras:
* data : user private data set in ngx_dynamic_resolver_start_resolver
* sa : sock address get
* socklen: sock address len, 0 for get none address
*/
typedef void (* ngx_dynamic_resolver_handler_pt)(void *data,
struct sockaddr *sa, socklen_t socklen);
/*
* add domain into dynamic resolver
*
* paras:
* domain: domain for DNS query
*/
void ngx_dynamic_resolver_add_domain(ngx_str_t *domain, ngx_cycle_t *cycle);
/*
* del domain from dynamic resolver
*
* paras:
* domain: domain for DNS query
*/
void ngx_dynamic_resolver_del_domain(ngx_str_t *domain);
/*
* get addr from dynamic resolver by domain if exist,
* otherwise, get from resolver configured into event resolver
* and add domain into dynamic resolver
*
* paras:
* domain: domain for DNS query
* h : callback handler
* data : data for callback
*/
void ngx_dynamic_resolver_start_resolver(ngx_str_t *domain,
ngx_dynamic_resolver_handler_pt h, void *data);
/*
* get addr from dynamic resolver by domain,
*
* return:
* 0 for failed
* socklen for successd
*
* paras:
* domain: domain for query
* sa : sockaddr for domain
*/
socklen_t ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain,
struct sockaddr *sa);
/*
* paras:
* r: http request to query status of dynamic resolver
*/
ngx_chain_t *ngx_dynamic_resolver_state(ngx_http_request_t *r);
#endif
@@ -1,281 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_event_resolver.h"
static void *ngx_event_resolver_create_conf(ngx_cycle_t *cycle);
static char *ngx_event_resolver_init_conf(ngx_cycle_t *cycle, void *conf);
static char *ngx_event_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
typedef struct ngx_event_resolver_ctx_s ngx_event_resolver_ctx_t;
struct ngx_event_resolver_ctx_s {
ngx_event_resolver_handler_pt handler;
void *data;
ngx_event_resolver_ctx_t *next;
};
typedef struct {
ngx_msec_t resolver_timeout;
ngx_resolver_t *resolver;
ngx_event_resolver_ctx_t *free_ctx;
ngx_uint_t nalloc;
ngx_uint_t nfree;
} ngx_event_resolver_conf_t;
static ngx_str_t event_resolver_name = ngx_string("event_resolver");
static ngx_command_t ngx_event_resolver_commands[] = {
{ ngx_string("resolver"),
NGX_EVENT_CONF|NGX_CONF_1MORE,
ngx_event_resolver,
0,
0,
NULL },
{ ngx_string("resolver_timeout"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
0,
offsetof(ngx_event_resolver_conf_t, resolver_timeout),
NULL },
ngx_null_command
};
ngx_event_module_t ngx_event_resolver_module_ctx = {
&event_resolver_name,
ngx_event_resolver_create_conf, /* create configuration */
ngx_event_resolver_init_conf, /* init configuration */
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/* this module use ngx_cycle->log */
ngx_module_t ngx_event_resolver_module = {
NGX_MODULE_V1,
&ngx_event_resolver_module_ctx, /* module context */
ngx_event_resolver_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_event_resolver_create_conf(ngx_cycle_t *cycle)
{
ngx_event_resolver_conf_t *conf;
conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_resolver_conf_t));
if (conf == NULL) {
return NULL;
}
conf->resolver_timeout = NGX_CONF_UNSET_MSEC;
return conf;
}
static char *
ngx_event_resolver_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_event_resolver_conf_t *ercf = conf;
ngx_conf_init_msec_value(ercf->resolver_timeout, 60000);
return NGX_CONF_OK;
}
static char *
ngx_event_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_event_resolver_conf_t *ercf = conf;
ngx_str_t *value;
if (ercf->resolver) {
return "is duplicate";
}
value = cf->args->elts;
ercf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
if (ercf->resolver == NULL) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
static ngx_event_resolver_ctx_t *
ngx_event_resolver_get_ctx()
{
ngx_event_resolver_ctx_t *ctx;
ngx_event_resolver_conf_t *ercf;
ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module);
ctx = ercf->free_ctx;
if (ctx == NULL) {
ctx = ngx_pcalloc(ngx_cycle->pool, sizeof(ngx_event_resolver_ctx_t));
++ercf->nalloc;
} else {
ercf->free_ctx = ctx->next;
ctx->next = NULL;
--ercf->nfree;
}
return ctx;
}
static void
ngx_event_resolver_put_ctx(ngx_event_resolver_ctx_t *ctx)
{
ngx_event_resolver_conf_t *ercf;
ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module);
ctx->next = ercf->free_ctx;
ercf->free_ctx = ctx;
++ercf->nfree;
}
static void
ngx_event_resolver_handler(ngx_resolver_ctx_t *ctx)
{
ngx_event_resolver_ctx_t *erctx;
erctx = ctx->data;
if (ctx->state) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"event resolver, domain '%V' could not be resolved (%i: %s)",
&ctx->name, ctx->state, ngx_resolver_strerror(ctx->state));
erctx->handler(erctx->data, NULL, 0);
goto failed;
}
erctx->handler(erctx->data, ctx->addrs, ctx->naddrs);
failed:
ngx_resolve_name_done(ctx);
ngx_event_resolver_put_ctx(erctx);
}
void
ngx_event_resolver_start_resolver(ngx_str_t *domain,
ngx_event_resolver_handler_pt h, void *data)
{
ngx_event_resolver_conf_t *ercf;
ngx_event_resolver_ctx_t *erctx;
ngx_resolver_ctx_t *ctx, temp;
ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module);
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "event resolver, "
"start resolv domain '%V'", domain);
if (ercf->resolver == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, "
"resolver does not configured");
h(data, NULL, 0);
return;
}
temp.name = *domain;
erctx = ngx_event_resolver_get_ctx();
if (erctx == NULL) {
return;
}
erctx->handler = h;
erctx->data = data;
ctx = ngx_resolve_start(ercf->resolver, &temp);
if (ctx == NULL) {
goto failed;
}
if (ctx == NGX_NO_RESOLVER) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, "
"no resolver defined to resolv %V", domain);
goto failed;
}
ctx->name = *domain;
ctx->handler = ngx_event_resolver_handler;
ctx->data = erctx;
ctx->timeout = ercf->resolver_timeout;
if (ngx_resolve_name(ctx) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, "
"resolv %V failed", domain);
goto failed;
}
return;
failed:
h(data, NULL, 0);
if (ctx == NULL || ctx == NGX_NO_RESOLVER) {
ngx_resolve_name_done(ctx);
ngx_event_resolver_put_ctx(erctx);
}
}
ngx_chain_t *
ngx_event_resolver_state(ngx_http_request_t *r)
{
ngx_event_resolver_conf_t *ercf;
ngx_chain_t *cl;
ngx_buf_t *b;
size_t len;
ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module);
len = sizeof("##########event resolver state##########\n") - 1
+ sizeof("ngx_event_resolver alloc: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_event_resolver free: \n") - 1 + NGX_OFF_T_LEN;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########event resolver state##########\n"
"ngx_event_resolver alloc: %ui\nngx_event_resolver free: %ui\n",
ercf->nalloc, ercf->nfree);
return cl;
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_EVENT_RESOLVER_H_INCLUDED_
#define _NGX_EVENT_RESOLVER_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
/*
* paras:
* data : user private data set in ngx_event_resolver_start_resolver
* addrs : addrs resolv by DNS
* naddrs: number of addrs resolv by DNS
*/
typedef void (* ngx_event_resolver_handler_pt)(void *data,
ngx_resolver_addr_t *addrs, ngx_uint_t naddrs);
/*
* paras:
* domain: domain for resolving
* h : callback handler
* data : data for callback
*/
void ngx_event_resolver_start_resolver(ngx_str_t *domain,
ngx_event_resolver_handler_pt h, void *data);
/*
* paras:
* r: http request to query status of event resolver
*/
ngx_chain_t *ngx_event_resolver_state(ngx_http_request_t *r);
#endif
@@ -1,271 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_event_timer_module.h"
static ngx_int_t ngx_event_timer_process_init(ngx_cycle_t *cycle);
static void *ngx_event_timer_create_conf(ngx_cycle_t *cycle);
static char *ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf);
typedef struct {
ngx_uint_t timerid;
ngx_event_t event;
ngx_timer_handler_pt handler;
void *data;
} ngx_event_timer_ctx_t;
typedef struct {
ngx_uint_t timer_n;
ngx_event_timer_ctx_t *timer_ctx; /* array to store timers */
ngx_event_timer_ctx_t *free_timers; /* timer unused */
ngx_uint_t free_timer_n;
} ngx_event_timer_conf_t;
static ngx_str_t event_timer_name = ngx_string("event_timer");
static ngx_command_t ngx_event_timer_commands[] = {
{ ngx_string("worker_timers"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_event_timer_conf_t, timer_n),
NULL },
ngx_null_command
};
ngx_event_module_t ngx_event_timer_module_ctx = {
&event_timer_name,
ngx_event_timer_create_conf, /* create configuration */
ngx_event_timer_init_conf, /* init configuration */
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/* this module use ngx_cycle->log */
ngx_module_t ngx_event_timer_module = {
NGX_MODULE_V1,
&ngx_event_timer_module_ctx, /* module context */
ngx_event_timer_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_event_timer_process_init, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_event_timer_create_conf(ngx_cycle_t *cycle)
{
ngx_event_timer_conf_t *conf;
conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_timer_conf_t));
if (conf == NULL) {
return NULL;
}
conf->timer_n = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_event_timer_conf_t *etcf = conf;
ngx_conf_init_uint_value(etcf->timer_n, 1024);
return NGX_CONF_OK;
}
static ngx_int_t
ngx_event_timer_process_init(ngx_cycle_t *cycle)
{
ngx_event_timer_conf_t *etcf;
ngx_event_timer_ctx_t *t, *next;
ngx_uint_t i;
etcf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_timer_module);
if (etcf->timer_n == 0) {
return NGX_OK;
}
etcf->timer_ctx =
ngx_alloc(sizeof(ngx_event_timer_ctx_t) * etcf->timer_n, cycle->log);
if (etcf->timer_ctx == NULL) {
return NGX_ERROR;
}
t = etcf->timer_ctx;
i = etcf->timer_n;
next = NULL;
do {
--i;
t[i].timerid = i;
t[i].event.timer_set = 0;
t[i].event.log = NULL;
t[i].handler = NULL;
t[i].data = next;
next = &t[i];
} while (i);
etcf->free_timers = next;
etcf->free_timer_n = etcf->timer_n;
return NGX_OK;
}
static ngx_event_timer_ctx_t *
ngx_event_timer_get_timer()
{
ngx_event_timer_conf_t *etcf;
ngx_event_timer_ctx_t *free;
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
free = etcf->free_timers;
if (etcf->free_timer_n == 0) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
"nginx event timer module, no free timer");
return NULL;
}
etcf->free_timers = free->data;
--etcf->free_timer_n;
return free;
}
static void
ngx_event_timer_free_timer(ngx_event_timer_ctx_t *ctx)
{
ngx_event_timer_conf_t *etcf;
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
ctx->data = etcf->free_timers;
etcf->free_timers = ctx;
++etcf->free_timer_n;
}
static void
ngx_event_timer_event_handler(ngx_event_t *e)
{
ngx_event_timer_ctx_t *ctx;
ctx = e->data;
if (ctx->handler) {
ctx->handler(ctx->data);
}
ngx_event_timer_free_timer(ctx);
}
ngx_int_t
ngx_event_timer_add_timer(ngx_msec_t tv, ngx_timer_handler_pt h, void *data)
{
ngx_event_timer_ctx_t *ctx;
if (h == NULL) {
return NGX_ERROR;
}
ctx = ngx_event_timer_get_timer();
if (ctx == NULL) {
return NGX_ERROR;
}
ctx->event.handler = ngx_event_timer_event_handler;
ctx->event.data = ctx;
ctx->handler = h;
ctx->data = data;
if (ctx->event.log == NULL) {
ctx->event.log = ngx_cycle->log;
}
ngx_event_add_timer(&ctx->event, tv);
return ctx->timerid;
}
void
ngx_event_timer_del_timer(ngx_uint_t timerid)
{
ngx_event_timer_ctx_t *ctx;
ngx_event_timer_conf_t *etcf;
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
ctx = &etcf->timer_ctx[timerid];
if (!ctx->event.timer_set) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
"timer has already deleted");
return;
}
ngx_event_del_timer(&ctx->event);
ngx_event_timer_free_timer(ctx);
}
ngx_chain_t *
ngx_event_timer_state(ngx_http_request_t *r)
{
ngx_event_timer_conf_t *etcf;
ngx_chain_t *cl;
ngx_buf_t *b;
size_t len;
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
len = sizeof("##########event timer state##########\n") - 1
+ sizeof("ngx_event_timer alloc: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_event_timer free: \n") - 1 + NGX_OFF_T_LEN;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########event timer state##########\n"
"ngx_event_timer alloc: %ui\nngx_event_timer free: %ui\n",
etcf->timer_n, etcf->free_timer_n);
return cl;
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_EVENT_TIMER_MODULE_H_INCLUDED_
#define _NGX_EVENT_TIMER_MODULE_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
typedef void (* ngx_timer_handler_pt)(void *data);
/*
* return value:
* return timerid for successd, NGX_ERROR for failed
* paras:
* tv : timer interval to trigger handler
* h : timer handler
* data : data of h para
*/
ngx_int_t ngx_event_timer_add_timer(ngx_msec_t tv,
ngx_timer_handler_pt h, void *data);
/*
* paras:
* timerid: value return in ngx_timer_add_timer
*/
void ngx_event_timer_del_timer(ngx_uint_t timerid);
/*
* paras:
* r: http request to query status of event timer
*/
ngx_chain_t *ngx_event_timer_state(ngx_http_request_t *r);
#endif
File diff suppressed because it is too large. Load diff
@@ -1,31 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_HTTP_DYNAMIC_H_INCLUDED_
#define _NGX_HTTP_DYNAMIC_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
typedef struct {
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*init_srv_conf)(ngx_conf_t *cf, void *conf);
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*init_loc_conf)(ngx_conf_t *cf, void *conf);
} ngx_http_dynamic_module_t;
void *ngx_http_get_module_main_dconf(ngx_http_request_t *r, ngx_module_t *m);
void *ngx_http_get_module_srv_dconf(ngx_http_request_t *r, ngx_module_t *m);
void *ngx_http_get_module_loc_dconf(ngx_http_request_t *r, ngx_module_t *m);
#endif
@@ -1,527 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_flag_t trace;
} ngx_http_trace_main_conf_t;
typedef struct {
u_char traceid[32]; /* X-NTM-Traceid */
u_char cid[32]; /* X-NTM-Currentid */
u_char pid[32]; /* X-NTM-Parentid */
ngx_flag_t debug; /* X-NTM-Debug */
} ngx_http_trace_ctx_t;
static void *ngx_http_trace_create_main_conf(ngx_conf_t *cf);
static char *ngx_http_trace_init_main_conf(ngx_conf_t *cf, void *conf);
static char *ngx_http_trace(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_trace_add_variables(ngx_conf_t *cf);
static ngx_int_t ngx_http_trace_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_trace_traceid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_trace_currentid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_trace_parentid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_trace_debug_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_trace_newid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_command_t ngx_http_trace_commands[] = {
{ ngx_string("http_trace"),
NGX_HTTP_MAIN_CONF|NGX_CONF_NOARGS,
ngx_http_trace,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_trace_module_ctx = {
ngx_http_trace_add_variables, /* preconfiguration */
ngx_http_trace_init, /* postconfiguration */
ngx_http_trace_create_main_conf, /* create main configuration */
ngx_http_trace_init_main_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_trace_module = {
NGX_MODULE_V1,
&ngx_http_trace_module_ctx, /* module context */
ngx_http_trace_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_http_variable_t ngx_http_trace_vars[] = {
{ ngx_string("ntm_traceid"), NULL,
ngx_http_trace_traceid_variable, 0, 0, 0 },
{ ngx_string("ntm_currentid"), NULL,
ngx_http_trace_currentid_variable, 0, 0, 0 },
{ ngx_string("ntm_parentid"), NULL,
ngx_http_trace_parentid_variable, 0, 0, 0 },
{ ngx_string("ntm_debug"), NULL,
ngx_http_trace_debug_variable, 0, 0, 0 },
{ ngx_string("ntm_newid"), NULL,
ngx_http_trace_newid_variable, 0, 0, 0 },
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
static void
ngx_http_trace_genid(u_char *id) {
ngx_sprintf(id, "%08xD%08xD%08xD%08xD",
(uint32_t) ngx_random(), (uint32_t) ngx_random(),
(uint32_t) ngx_random(), (uint32_t) ngx_random());
}
static u_char *
ngx_http_trace_log_error(ngx_log_t *log, u_char *buf, size_t len)
{
u_char *p;
ngx_http_request_t *r;
ngx_http_log_ctx_t *ctx;
ngx_http_trace_ctx_t *tctx;
ngx_str_t traceid, currentid, parentid;
if (log->action) {
p = ngx_snprintf(buf, len, " while %s", log->action);
len -= p - buf;
buf = p;
}
ctx = log->data;
p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
len -= p - buf;
buf = p;
r = ctx->request;
if (r) {
p = r->log_handler(r, ctx->current_request, p, len);
len -= p - buf;
buf = p;
} else {
p = ngx_snprintf(p, len, ", server: %V",
&ctx->connection->listening->addr_text);
len -= p - buf;
buf = p;
}
tctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (tctx) {
traceid.data = tctx->traceid;
traceid.len = sizeof(tctx->traceid);
currentid.data = tctx->cid;
currentid.len = sizeof(tctx->cid);
parentid.data = tctx->pid;
parentid.len = sizeof(tctx->pid);
p = ngx_snprintf(p, len, ", [NGINX-TRACE] traceid: %V, currentid: %V, "
"parentid: %V [NGINX-TRACE-END]",
&traceid, &currentid, &parentid);
}
return p;
}
// First request without X-NTM-Traceid X-NTM-Currentid or X-NTM-Parentid
// Need to gen these ids and set X-NTM headers in main request
static ngx_int_t
ngx_http_trace_first_request(ngx_http_request_t *r, ngx_http_trace_ctx_t *ctx)
{
ngx_table_elt_t *h;
ngx_http_trace_genid(ctx->traceid);
ngx_http_trace_genid(ctx->cid);
ngx_sprintf(ctx->pid, "00000000000000000000000000000000");
// Set X-NTM-Traceid
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
return NGX_ERROR;
}
h->key.data = (u_char *) "X-NTM-Traceid";
h->key.len = sizeof("X-NTM-Traceid") - 1;
h->value.data = ctx->traceid;
h->value.len = sizeof(ctx->traceid);
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len);
// Set X-NTM-Currentid
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
return NGX_ERROR;
}
h->key.data = (u_char *) "X-NTM-Currentid";
h->key.len = sizeof("X-NTM-Currentid") - 1;
h->value.data = ctx->cid;
h->value.len = sizeof(ctx->cid);
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len);
// Set X-NTM-Parentid
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
return NGX_ERROR;
}
h->key.data = (u_char *) "X-NTM-Parentid";
h->key.len = sizeof("X-NTM-Parentid") - 1;
h->value.data = ctx->pid;
h->value.len = sizeof(ctx->pid);
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
if (h->lowcase_key == NULL) {
return NGX_ERROR;
}
h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len);
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_handler(ngx_http_request_t *r)
{
ngx_http_trace_main_conf_t *tmcf;
ngx_http_trace_ctx_t *ctx;
ngx_http_variable_value_t v;
ngx_str_t header;
if (r != r->main) { // subrequest
return NGX_DECLINED;
}
tmcf = ngx_http_get_module_main_conf(r, ngx_http_trace_module);
if (!tmcf->trace) {
return NGX_DECLINED;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx) { // ctx already create, enter twice
return NGX_DECLINED;
}
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_trace_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_http_set_ctx(r, ctx, ngx_http_trace_module);
// traceid currentid parentid log into nginx error log
r->connection->log->handler = ngx_http_trace_log_error;
// Get X-NTM-Debug
header.data = (u_char *) "http_x_ntm_debug";
header.len = sizeof("http_x_ntm_debug") - 1;
ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part,
sizeof("http_") - 1);
if (!v.not_found && v.len == 1 && v.data[0] == '1') {
// Has header X-NTM-Debug: 1
ctx->debug = 1;
}
// Get X-NTM-Traceid
header.data = (u_char *) "http_x_ntm_traceid";
header.len = sizeof("http_x_ntm_traceid") - 1;
ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part,
sizeof("http_") - 1);
if (v.not_found) {
goto notfound;
}
ngx_memcpy(ctx->traceid, v.data, ngx_min(v.len, sizeof(ctx->traceid)));
// Get X-NTM-Currentid
header.data = (u_char *) "http_x_ntm_currentid";
header.len = sizeof("http_x_ntm_currentid") - 1;
ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part,
sizeof("http_") - 1);
if (v.not_found) {
goto notfound;
}
ngx_memcpy(ctx->cid, v.data, ngx_min(v.len, sizeof(ctx->cid)));
// Get X-NTM-Parentid
header.data = (u_char *) "http_x_ntm_parentid";
header.len = sizeof("http_x_ntm_parentid") - 1;
ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part,
sizeof("http_") - 1);
if (v.not_found) {
goto notfound;
}
ngx_memcpy(ctx->pid, v.data, ngx_min(v.len, sizeof(ctx->pid)));
return NGX_DECLINED;
notfound:
if (ngx_http_trace_first_request(r, ctx) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return NGX_DECLINED;
}
static ngx_int_t
ngx_http_trace_traceid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_trace_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx == NULL) {
v->not_found = 1;
return NGX_OK;
}
v->data = ctx->traceid;
v->len = sizeof(ctx->traceid);
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_currentid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_trace_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx == NULL) {
v->not_found = 1;
return NGX_OK;
}
v->data = ctx->cid;
v->len = sizeof(ctx->cid);
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_parentid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_trace_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx == NULL) {
v->not_found = 1;
return NGX_OK;
}
v->data = ctx->pid;
v->len = sizeof(ctx->pid);
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_debug_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_trace_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx == NULL) {
v->not_found = 1;
return NGX_OK;
}
if (ctx->debug) {
v->data = (u_char *) "1";
} else {
v->data = (u_char *) "0";
}
v->len = sizeof("1") - 1;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_newid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_trace_ctx_t *ctx;
u_char *newid;
ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module);
if (ctx == NULL) {
v->not_found = 1;
return NGX_OK;
}
newid = ngx_pcalloc(r->pool, sizeof(ctx->cid));
if (newid == NULL) {
return NGX_ERROR;
}
// fill newid
ngx_http_trace_genid(newid);
v->data = newid;
v->len = sizeof(ctx->cid);
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
return NGX_OK;
}
static void *
ngx_http_trace_create_main_conf(ngx_conf_t *cf)
{
ngx_http_trace_main_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_trace_main_conf_t));
if (conf == NULL) {
return NULL;
}
conf->trace = NGX_CONF_UNSET;
return conf;
}
static char *
ngx_http_trace_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_trace_main_conf_t *tmcf;
tmcf = conf;
ngx_conf_init_value(tmcf->trace, 0);
return NGX_CONF_OK;
}
static char *
ngx_http_trace(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_trace_main_conf_t *tmcf;
tmcf = conf;
if (tmcf->trace != NGX_CONF_UNSET) {
return "is duplicate";
}
tmcf->trace = 1;
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_trace_add_variables(ngx_conf_t *cf)
{
ngx_http_variable_t *var, *v;
for (v = ngx_http_trace_vars; v->name.len; v++) {
var = ngx_http_add_variable(cf, &v->name, v->flags);
if (var == NULL) {
return NGX_ERROR;
}
var->get_handler = v->get_handler;
var->data = v->data;
}
return NGX_OK;
}
static ngx_int_t
ngx_http_trace_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_trace_handler;
return NGX_OK;
}
@@ -1,327 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_map.h"
static void
ngx_map_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
ngx_rbtree_node_t *sentinel)
{
ngx_rbtree_node_t **p;
intptr_t *raw_key, *raw_key_temp;
ngx_map_t **map;
for (;;) {
if (node->key < temp->key) {
p = &temp->left;
} else if (node->key > temp->key) {
p = &temp->right;
} else {
raw_key = (intptr_t *)((char *) node
+ offsetof(ngx_map_node_t, raw_key));
raw_key_temp = (intptr_t *)((char *) temp
+ offsetof(ngx_map_node_t, raw_key));
map = (ngx_map_t **)((char *) node + offsetof(ngx_map_node_t, map));
switch ((*map)->cmp(*raw_key, *raw_key_temp)) {
case -1:
p = &temp->left;
break;
case 1:
p = &temp->right;
break;
default: /* key is duplicate */
return;
}
}
if (*p == sentinel) {
break;
}
temp = *p;
}
*p = node;
node->parent = temp;
node->left = sentinel;
node->right = sentinel;
ngx_rbt_red(node);
}
void
ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp)
{
ngx_rbtree_init(&map->rbtree, &map->sentinel, ngx_map_rbtree_insert_value);
map->hash = hash;
map->cmp = cmp;
}
ngx_map_node_t *
ngx_map_begin(ngx_map_t *map)
{
ngx_rbtree_node_t *p;
if (ngx_map_empty(map)) {
return NULL;
}
p = map->rbtree.root;
for (;;) {
if (p->left == map->rbtree.sentinel) {
break;
}
p = p->left;
}
return (ngx_map_node_t *) p;
}
ngx_map_node_t *
ngx_map_rbegin(ngx_map_t *map)
{
ngx_rbtree_node_t *p;
if (ngx_map_empty(map)) {
return NULL;
}
p = map->rbtree.root;
for (;;) {
if (p->right == map->rbtree.sentinel) {
break;
}
p = p->right;
}
return (ngx_map_node_t *) p;
}
ngx_map_node_t *
ngx_map_next(ngx_map_node_t *n)
{
ngx_map_t *map;
ngx_rbtree_node_t *p, *top;
map = n->map;
p = &n->rn;
top = NULL;
if (p->right != map->rbtree.sentinel) {
// current node has right subtree
top = p->right;
} else {
for (;;) {
if (p == map->rbtree.root) {
return NULL;
}
if (p->parent->left == p) {
return (ngx_map_node_t *) p->parent;
}
// p->parent->right == p
p = p->parent;
}
}
// get the mininum node
p = top;
for (;;) {
if (p->left == map->rbtree.sentinel) {
break;
}
p = p->left;
}
return (ngx_map_node_t *) p;
}
ngx_map_node_t *
ngx_map_prev(ngx_map_node_t *n)
{
ngx_map_t *map;
ngx_rbtree_node_t *p, *top;
map = n->map;
p = &n->rn;
top = NULL;
if (p->left != map->rbtree.sentinel) {
// current node has left subtree
top = p->left;
} else {
for (;;) {
if (p == map->rbtree.root) {
return NULL;
}
if (p->parent->right == p) {
return (ngx_map_node_t *) p->parent;
}
// p->parent->left == p
p = p->parent;
}
}
// get the maximum node
p = top;
for (;;) {
if (p->right == map->rbtree.sentinel) {
break;
}
p = p->right;
}
return (ngx_map_node_t *) p;
}
void
ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered)
{
ngx_map_node_t *n;
node->rn.key = map->hash(node->raw_key);
node->map = map;
n = ngx_map_find(map, node->raw_key);
if (n == NULL) {
ngx_rbtree_insert(&map->rbtree, &node->rn);
} else if (covered) {
ngx_map_delete(map, node->raw_key);
ngx_rbtree_insert(&map->rbtree, &node->rn);
}
}
void
ngx_map_delete(ngx_map_t *map, intptr_t key)
{
ngx_map_node_t *node;
node = ngx_map_find(map, key);
if (node) {
ngx_rbtree_delete(&map->rbtree, &node->rn);
}
}
ngx_map_node_t *
ngx_map_find(ngx_map_t *map, intptr_t key)
{
ngx_rbtree_node_t *p;
ngx_rbtree_key_t k;
intptr_t *key_temp;
if (ngx_map_empty(map)) {
return NULL;
}
k = map->hash(key);
p = map->rbtree.root;
for (;;) {
if (k < p->key) {
p = p->left;
} else if (k > p->key) {
p = p->right;
} else {
key_temp = (intptr_t *)((char *) p
+ offsetof(ngx_map_node_t, raw_key));
switch (map->cmp(key, *key_temp)) {
case -1:
p = p->left;
break;
case 1:
p = p->right;
break;
case 0:
return (ngx_map_node_t *) p;
}
}
if (p == map->rbtree.sentinel) {
return NULL;
}
}
}
/* ngx_str_t */
ngx_rbtree_key_t
ngx_map_hash_str(intptr_t key)
{
ngx_str_t *k;
k = (ngx_str_t *) key;
return ngx_hash_key(k->data, k->len);
}
int
ngx_cmp_str(intptr_t key1, intptr_t key2)
{
ngx_str_t *k1, *k2;
ngx_int_t rc;
k1 = (ngx_str_t *) key1;
k2 = (ngx_str_t *) key2;
rc = ngx_memn2cmp(k1->data, k2->data, k1->len, k2->len);
if (rc < 0) {
return -1;
} else if (rc > 0) {
return 1;
} else {
return 0;
}
}
/* ngx_uint_t */
ngx_rbtree_key_t
ngx_map_hash_uint(intptr_t key)
{
return (ngx_rbtree_key_t) key;
}
int
ngx_cmp_uint(intptr_t key1, intptr_t key2)
{
if ((ngx_uint_t) key1 < (ngx_uint_t) key2) {
return -1;
} else if ((ngx_uint_t) key1 > (ngx_uint_t) key2) {
return 1;
} else {
return 0;
}
}
/* ngx_int_t */
ngx_rbtree_key_t
ngx_map_hash_int(intptr_t key)
{
return (ngx_rbtree_key_t) key;
}
int
ngx_cmp_int(intptr_t key1, intptr_t key2)
{
if ((ngx_int_t) key1 < (ngx_int_t) key2) {
return -1;
} else if ((ngx_int_t) key1 > (ngx_int_t) key2) {
return 1;
} else {
return 0;
}
}
@@ -1,131 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_MAP_H_INCLUDED_
#define _NGX_MAP_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
/*
* key: key for map node
*/
typedef ngx_rbtree_key_t (* ngx_map_hash_pt)(intptr_t key);
/*
* if key1 < key2, return -1
* if key1 = key2, return 0
* if key1 > key2, return 1
*/
typedef int (* ngx_cmp_pt)(intptr_t key1, intptr_t key2);
/* ngx_str_t */
ngx_rbtree_key_t ngx_map_hash_str(intptr_t key);
int ngx_cmp_str(intptr_t key1, intptr_t key2);
/* ngx_uint_t */
ngx_rbtree_key_t ngx_map_hash_uint(intptr_t key);
int ngx_cmp_uint(intptr_t key1, intptr_t key2);
/* ngx_int_t */
ngx_rbtree_key_t ngx_map_hash_int(intptr_t key);
int ngx_cmp_int(intptr_t key1, intptr_t key2);
typedef struct {
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_map_hash_pt hash;
ngx_cmp_pt cmp;
} ngx_map_t;
typedef struct {
ngx_rbtree_node_t rn;
intptr_t raw_key;
ngx_map_t *map;
} ngx_map_node_t;
/*
* return value:
* None
* paras:
* map : map for initial
* hash: hash func for calc key's hash
* cmp : cmp func for cmp two keys
*/
void ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp);
/*
* return value:
* if map is empty return 1, else return 0
*/
#define ngx_map_empty(map) (map->rbtree.root == map->rbtree.sentinel)
/*
* return value:
* the mininum key map node, if map is empty, return NULL
* paras:
* map: map for operate
*/
ngx_map_node_t *ngx_map_begin(ngx_map_t *map);
/*
* return value:
* the maximum key map node, if map is empty, return NULL
* paras:
* map: map for operate
*/
ngx_map_node_t *ngx_map_rbegin(ngx_map_t *map);
/*
* return value:
* the next bigger key map node, if none, return NULL
* paras:
* n : current node
*/
ngx_map_node_t *ngx_map_next(ngx_map_node_t *n);
/*
* return value:
* the next smaller key map node, if none, return NULL
* paras:
* n : current node
*/
ngx_map_node_t *ngx_map_prev(ngx_map_node_t *n);
/*
* return value:
* None
* paras:
* map : map for operate
* node : map node for inserting into map
* covered: 1 for covered if key is same, 0 do nothing if key is same
*/
void ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered);
/*
* return value:
* None
* paras:
* map: map for operate
* key: map node key for deleting from map
*/
void ngx_map_delete(ngx_map_t *map, intptr_t key);
/*
* return value:
* node in map searching by key, NULL for not found
* paras:
* map: map for operate
* key: node key for searching
*/
ngx_map_node_t *ngx_map_find(ngx_map_t *map, intptr_t key);
#endif
@@ -1,190 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_poold.h"
#include "ngx_map.h"
typedef struct ngx_poold_node_s ngx_poold_node_t;
static ngx_pool_t *ngx_poold_pool;
static ngx_map_t ngx_poold_map;
static ngx_poold_node_t *ngx_poold_free_node;
static ngx_uint_t ngx_poold_nalloc;
static ngx_uint_t ngx_poold_nfree;
struct ngx_poold_node_s {
ngx_map_node_t m; /* map node */
ngx_poold_node_t *next; /* free node */
ngx_pool_t *pool;
char *file; /* file create pool */
int line; /* line create pool */
};
static ngx_int_t
ngx_poold_init()
{
ngx_poold_pool = ngx_create_pool(4096, ngx_cycle->log);
if (ngx_poold_pool == NULL) {
return NGX_ERROR;
}
ngx_map_init(&ngx_poold_map, ngx_map_hash_uint, ngx_cmp_uint);
ngx_poold_free_node = NULL;
ngx_poold_nalloc = 0;
ngx_poold_nfree = 0;
return NGX_OK;
}
static ngx_poold_node_t *
ngx_poold_get_node()
{
ngx_poold_node_t *n;
n = ngx_poold_free_node;
if (n == NULL) {
n = ngx_pcalloc(ngx_poold_pool, sizeof(ngx_poold_node_t));
if (n == NULL) {
return NULL;
}
++ngx_poold_nalloc;
} else {
ngx_poold_free_node = n->next;
ngx_memzero(n, sizeof(ngx_poold_node_t));
--ngx_poold_nfree;
}
return n;
}
static void
ngx_poold_put_node(ngx_poold_node_t *node)
{
if (ngx_poold_pool == NULL) {
return;
}
if (node == NULL) {
return;
}
node->next = ngx_poold_free_node;
ngx_poold_free_node = node;
++ngx_poold_nfree;
}
ngx_pool_t *
ngx_create_pool_debug(size_t size, ngx_log_t *log, char *file, int line)
{
ngx_poold_node_t *node;
if (ngx_poold_pool == NULL) {
ngx_poold_init();
}
/* construct a poold node */
node = ngx_poold_get_node();
node->pool = ngx_create_pool(size, log);
node->file = file;
node->line = line;
/* record node in poold map */
node->m.raw_key = (intptr_t) node->pool;
ngx_map_insert(&ngx_poold_map, &node->m, 0);
return node->pool;
}
void
ngx_destroy_pool_debug(ngx_pool_t *pool, char *file, int line)
{
ngx_poold_node_t *node;
ngx_map_node_t *m;
/* get node by pool */
m = ngx_map_find(&ngx_poold_map, (intptr_t) pool);
if (m == NULL) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"destroy pool twice: %s:%d", file, line);
return;
}
ngx_map_delete(&ngx_poold_map, (intptr_t) pool);
node = (ngx_poold_node_t *) ((char *) m - offsetof(ngx_poold_node_t, m));
ngx_destroy_pool(pool);
/* put node in poold map */
ngx_poold_put_node(node);
}
ngx_chain_t *
ngx_poold_state(ngx_http_request_t *r, unsigned detail)
{
ngx_chain_t *cl;
ngx_buf_t *b;
ngx_map_node_t *node;
ngx_poold_node_t *pn;
size_t len, len1;
ngx_uint_t n;
len = sizeof("##########ngx debug pool##########\n") - 1
+ sizeof("ngx_poold nalloc node: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_poold nfree node: \n") - 1 + NGX_OFF_T_LEN;
len1 = 0;
/* node for create pool */
if (detail) {
n = ngx_poold_nalloc - ngx_poold_nfree;
/* " file:line\n" */
len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1;
len += len1 * n;
}
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########ngx debug pool##########\n"
"ngx_poold nalloc node: %ui\nngx_poold nfree node: %ui\n",
ngx_poold_nalloc, ngx_poold_nfree);
if (detail) {
for (node = ngx_map_begin(&ngx_poold_map); node;
node = ngx_map_next(node))
{
/* m is first element of ngx_poold_node_t */
pn = (ngx_poold_node_t *) node;
b->last = ngx_snprintf(b->last, len1, " %s:%d\n",
pn->file, pn->line);
}
}
return cl;
}
@@ -1,56 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_POOL_DEBUG_H_INCLUDED_
#define _NGX_POOL_DEBUG_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#define NGX_CREATE_POOL(size, log) \
ngx_create_pool_debug(size, log, __FILE__, __LINE__)
#define NGX_DESTROY_POOL(pool) \
ngx_destroy_pool_debug(pool, __FILE__, __LINE__)
/*
* create pool and record where to create it for debugging
* such as pool not destroy
*
* paras:
* size: pool size for pool creating interface in raw ngx_create_pool
* log: log for pool creating interface in raw ngx_create_pool
* file: use __FILE__ for recording file
* line: use __LINE__ for recording line
* return:
* pool for successd, NULL for failed
*/
ngx_pool_t *ngx_create_pool_debug(size_t size, ngx_log_t *log,
char *file, int line);
/*
* destroy pool for debugging, use as pair for ngx_create_pool_debug
*
* paras:
* pool: pool for pool destroying interface in ran ngx_destroy_pool
* file: use __FILE__ for recording file
* line: use __LINE__ for recording line
*/
void ngx_destroy_pool_debug(ngx_pool_t *pool, char *file, int line);
/*
* paras:
* r: http request to query status of rbuf
*/
ngx_chain_t *ngx_poold_state(ngx_http_request_t *r, unsigned detail);
#endif
@@ -1,292 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_map.h"
static ngx_pool_t *ngx_rbuf_pool;
static ngx_map_t ngx_rbuf_map;
static ngx_chain_t *ngx_rbuf_free_chain;
static ngx_uint_t ngx_rbuf_nalloc_node;
static ngx_uint_t ngx_rbuf_nalloc_buf;
static ngx_uint_t ngx_rbuf_nfree_buf;
static ngx_uint_t ngx_rbuf_nalloc_chain;
static ngx_uint_t ngx_rbuf_nfree_chain;
static ngx_map_t ngx_rbuf_using;
#define ngx_rbuf_buf(b) \
(ngx_rbuf_t *) ((u_char *) (b) - offsetof(ngx_rbuf_t, buf))
typedef struct ngx_rbuf_s ngx_rbuf_t;
struct ngx_rbuf_s {
size_t size;
ngx_rbuf_t *next;
u_char buf[];
};
typedef struct {
ngx_map_node_t node;
ngx_rbuf_t *rbuf;
} ngx_rbuf_node_t;
typedef struct {
ngx_chain_t cl;
ngx_buf_t buf;
unsigned alloc;
ngx_map_node_t node;
char *file;
int line;
} ngx_chainbuf_t;
static ngx_int_t
ngx_rbuf_init()
{
ngx_rbuf_pool = ngx_create_pool(4096, ngx_cycle->log);
if (ngx_rbuf_pool == NULL) {
return NGX_ERROR;
}
ngx_map_init(&ngx_rbuf_map, ngx_map_hash_uint, ngx_cmp_uint);
ngx_map_init(&ngx_rbuf_using, ngx_map_hash_uint, ngx_cmp_uint);
ngx_rbuf_nalloc_node = 0;
ngx_rbuf_nalloc_buf = 0;
ngx_rbuf_nfree_buf = 0;
ngx_rbuf_nalloc_chain = 0;
ngx_rbuf_nfree_chain = 0;
return NGX_OK;
}
static ngx_rbuf_t *
ngx_rbuf_get_buf(size_t key)
{
ngx_rbuf_node_t *rn;
ngx_map_node_t *node;
ngx_rbuf_t *rb;
node = ngx_map_find(&ngx_rbuf_map, key);
if (node == NULL) { /* new key */
rn = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_node_t));
if (rn == NULL) {
return NULL;
}
node = &rn->node;
node->raw_key = key;
ngx_map_insert(&ngx_rbuf_map, node, 0);
++ngx_rbuf_nalloc_node;
} else {
rn = (ngx_rbuf_node_t *) node;
}
rb = rn->rbuf;
if (rb == NULL) {
rb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_t) + key);
if (rb == NULL) {
return NULL;
}
rb->size = key;
++ngx_rbuf_nalloc_buf;
} else {
rn->rbuf = rb->next;
rb->next = NULL;
--ngx_rbuf_nfree_buf;
}
return rb;
}
static void
ngx_rbuf_put_buf(ngx_rbuf_t *rb)
{
ngx_rbuf_node_t *rn;
ngx_map_node_t *node;
node = ngx_map_find(&ngx_rbuf_map, rb->size);
if (node == NULL) {
return;
}
rn = (ngx_rbuf_node_t *) node;
rb->next = rn->rbuf;
rn->rbuf = rb;
++ngx_rbuf_nfree_buf;
}
static u_char *
ngx_rbuf_alloc(size_t size)
{
ngx_rbuf_t *rb;
rb = ngx_rbuf_get_buf(size);
return rb->buf;
}
static void
ngx_rbuf_free(u_char *rb)
{
ngx_rbuf_t *rbuf;
rbuf = ngx_rbuf_buf(rb);
ngx_rbuf_put_buf(rbuf);
}
ngx_chain_t *
ngx_get_chainbuf_debug(size_t size, ngx_flag_t alloc_rbuf, char *file, int line)
{
ngx_chainbuf_t *cb;
ngx_chain_t *cl;
if (ngx_rbuf_pool == NULL) {
ngx_rbuf_init();
}
cl = ngx_rbuf_free_chain;
if (cl) {
ngx_rbuf_free_chain = cl->next;
cl->next = NULL;
cb = (ngx_chainbuf_t *) cl;
--ngx_rbuf_nfree_chain;
} else {
cb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_chainbuf_t));
if (cb == NULL) {
return NULL;
}
cl = &cb->cl;
cl->buf = &cb->buf;
++ngx_rbuf_nalloc_chain;
}
if (alloc_rbuf) {
cl->buf->last = cl->buf->pos = cl->buf->start = ngx_rbuf_alloc(size);
cl->buf->end = cl->buf->start + size;
cb->alloc = 1;
} else {
cl->buf->pos = cl->buf->last = cl->buf->start = cl->buf->end = NULL;
cb->alloc = 0;
}
cl->buf->memory = 1;
// record chainbuf in using map
cb->file = file;
cb->line = line;
cb->node.raw_key = (intptr_t) cl;
ngx_map_insert(&ngx_rbuf_using, &cb->node, 0);
return cl;
}
void
ngx_put_chainbuf_debug(ngx_chain_t *cl, char *file, int line)
{
ngx_chainbuf_t *cb;
if (ngx_rbuf_pool == NULL) {
return;
}
if (cl == NULL) {
return;
}
cb = (ngx_chainbuf_t *) cl;
if (cb->alloc) {
ngx_rbuf_free(cl->buf->start);
}
cl->next = ngx_rbuf_free_chain;
ngx_rbuf_free_chain = cl;
++ngx_rbuf_nfree_chain;
// delete chainbuf from using map
if (ngx_map_find(&ngx_rbuf_using, (intptr_t) cl) == NULL) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"destroy chainbuf twice: %s:%d", file, line);
return;
}
ngx_map_delete(&ngx_rbuf_using, (intptr_t) cl);
}
ngx_chain_t *
ngx_rbuf_state(ngx_http_request_t *r, unsigned detail)
{
ngx_chain_t *cl;
ngx_buf_t *b;
size_t len, len1;
ngx_uint_t n;
ngx_chainbuf_t *cb;
ngx_map_node_t *node;
len = sizeof("##########ngx rbuf state##########\n") - 1
+ sizeof("ngx_rbuf nalloc node: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_rbuf nalloc buf: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_rbuf nfree buf: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_rbuf nalloc chain: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_rbuf nfree chain: \n") - 1 + NGX_OFF_T_LEN;
len1 = 0;
if (detail) {
n = ngx_rbuf_nalloc_chain - ngx_rbuf_nfree_chain;
/* " file:line\n" */
len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1;
len += len1 * n;
}
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########ngx rbuf state##########\nngx_rbuf nalloc node: %ui\n"
"ngx_rbuf nalloc buf: %ui\nngx_rbuf nfree buf: %ui\n"
"ngx_rbuf nalloc chain: %ui\nngx_rbuf nfree chain: %ui\n",
ngx_rbuf_nalloc_node, ngx_rbuf_nalloc_buf, ngx_rbuf_nfree_buf,
ngx_rbuf_nalloc_chain, ngx_rbuf_nfree_chain);
if (detail) {
for (node = ngx_map_begin(&ngx_rbuf_using); node;
node = ngx_map_next(node))
{
cb = (ngx_chainbuf_t *) ((char *) node
- offsetof(ngx_chainbuf_t, node));
b->last = ngx_snprintf(b->last, len1, " %s:%d\n",
cb->file, cb->line);
}
}
return cl;
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_RBUF_H_INCLUDED_
#define _NGX_RBUF_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
ngx_chain_t *ngx_get_chainbuf_debug(size_t size, ngx_flag_t alloc_rbuf,
char *file, int line);
void ngx_put_chainbuf_debug(ngx_chain_t *cl, char *file, int len);
/*
* paras:
* size: buffer size for allocate
* alloc_rbuf: whether alloc rbuf
* return:
* nginx chain
*/
#define ngx_get_chainbuf(size, alloc_rbuf) \
ngx_get_chainbuf_debug(size, alloc_rbuf, __FILE__, __LINE__);
/*
* paras:
* cl: nginx chain return by ngx_rtmp_shared_get_chainbuf
*/
#define ngx_put_chainbuf(cl) \
ngx_put_chainbuf_debug(cl, __FILE__, __LINE__);
/*
* paras:
* cl: nginx chain return by ngx_rtmp_shared_get_chainbuf
*/
#define ngx_put_chainbufs(cl) \
{ \
ngx_chain_t *l; \
\
l = cl; \
while (l) { \
cl = l->next; \
ngx_put_chainbuf_debug(l, __FILE__, __LINE__); \
l = cl; \
} \
}
/*
* paras:
* r: http request to query status of rbuf
*/
ngx_chain_t *ngx_rbuf_state(ngx_http_request_t *r, unsigned detail);
#endif
@@ -1,269 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_timerd.h"
#include "ngx_map.h"
typedef struct ngx_timerd_node_s ngx_timerd_node_t;
static ngx_pool_t *ngx_timerd_pool;
static ngx_map_t ngx_timerd_map;
static ngx_timerd_node_t *ngx_timerd_free_node;
static ngx_uint_t timerd_footprint;
static ngx_uint_t ngx_timerd_nalloc;
static ngx_uint_t ngx_timerd_nfree;
struct ngx_timerd_node_s {
ngx_map_node_t m; /* map node */
ngx_timerd_node_t *next; /* free node */
ngx_uint_t footprint;
off_t fpoff;
ngx_event_t ev;
ngx_event_t *uev;
char *file; /* file create pool */
int line; /* line create pool */
};
static ngx_int_t
ngx_timerd_init()
{
ngx_timerd_pool = ngx_create_pool(4096, ngx_cycle->log);
if (ngx_timerd_pool == NULL) {
return NGX_ERROR;
}
ngx_map_init(&ngx_timerd_map, ngx_map_hash_uint, ngx_cmp_uint);
ngx_timerd_free_node = NULL;
ngx_timerd_nalloc = 0;
ngx_timerd_nfree = 0;
return NGX_OK;
}
static ngx_timerd_node_t *
ngx_timerd_get_node()
{
ngx_timerd_node_t *n;
n = ngx_timerd_free_node;
if (n == NULL) {
n = ngx_pcalloc(ngx_timerd_pool, sizeof(ngx_timerd_node_t));
if (n == NULL) {
return NULL;
}
++ngx_timerd_nalloc;
} else {
ngx_timerd_free_node = n->next;
ngx_memzero(n, sizeof(ngx_timerd_node_t));
--ngx_timerd_nfree;
}
return n;
}
static void
ngx_timerd_put_node(ngx_timerd_node_t *node)
{
if (ngx_timerd_pool == NULL) {
return;
}
if (node == NULL) {
return;
}
node->next = ngx_timerd_free_node;
ngx_timerd_free_node = node;
++ngx_timerd_nfree;
}
static void
ngx_timerd_wrap(ngx_event_t *ev)
{
ngx_timerd_node_t *node;
ngx_event_t *uev;
ngx_uint_t *fp;
node = ev->data;
uev = node->uev;
fp = (ngx_uint_t *) ((char *) (uev->data) + node->fpoff);
if (*fp != node->footprint) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"timer wrap, timer trigger but not timer owner: %s:%d",
node->file, node->line);
return;
}
ngx_map_delete(&ngx_timerd_map, (intptr_t) uev);
uev->timer_set = 0;
uev->timedout = 1;
uev->handler(uev);
ngx_timerd_put_node(node);
}
ngx_uint_t
ngx_timerd_footprint()
{
return timerd_footprint++;
}
void
ngx_add_timer_debug(ngx_event_t *ev, ngx_msec_t timer, off_t fpoff,
char *file, int line)
{
ngx_timerd_node_t *node;
ngx_map_node_t *m;
ngx_uint_t *fp;
if (ngx_timerd_pool == NULL) {
ngx_timerd_init();
}
fp = (ngx_uint_t *) ((char *) ev->data + fpoff);
m = ngx_map_find(&ngx_timerd_map, (intptr_t) ev);
if (m == NULL) { // first add
node = ngx_timerd_get_node();
node->m.raw_key = (intptr_t) ev;
ngx_map_insert(&ngx_timerd_map, &node->m, 0);
node->footprint = *fp;
node->fpoff = fpoff;
node->ev.log = ngx_cycle->log;
node->ev.data = node;
node->ev.handler = ngx_timerd_wrap;
node->uev = ev;
node->file = file;
node->line = line;
} else {
node = (ngx_timerd_node_t *) ((char *) m -
offsetof(ngx_timerd_node_t, m));
if (node->footprint != *fp) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"add timer but not timer owner(%s:%d): %s:%d",
node->file, node->line, file, line);
return;
}
}
ev->timer_set = 1;
ngx_add_timer(&node->ev, timer);
}
void
ngx_del_timer_debug(ngx_event_t *ev, ngx_uint_t footprint, char *file, int line)
{
ngx_timerd_node_t *node;
ngx_map_node_t *m;
/* get node by pool */
m = ngx_map_find(&ngx_timerd_map, (intptr_t) ev);
if (m == NULL) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"delete timer twice: %s:%d", file, line);
return;
}
node = (ngx_timerd_node_t *) ((char *) m - offsetof(ngx_timerd_node_t, m));
if (node->footprint != footprint) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"delete timer but not timer owner: %s:%d", file, line);
return;
}
ngx_map_delete(&ngx_timerd_map, (intptr_t) ev);
if (node->ev.timer_set) {
ev->timer_set = 0;
ngx_del_timer(&node->ev);
}
if (node->ev.posted) {
ngx_delete_posted_event(&node->ev);
}
/* put node in timerd map */
ngx_timerd_put_node(node);
}
ngx_chain_t *
ngx_timerd_state(ngx_http_request_t *r, unsigned detail)
{
ngx_chain_t *cl;
ngx_buf_t *b;
ngx_map_node_t *node;
ngx_timerd_node_t *pn;
size_t len, len1;
ngx_uint_t n;
len = sizeof("##########ngx debug pool##########\n") - 1
+ sizeof("ngx_timerd nalloc node: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_timerd nfree node: \n") - 1 + NGX_OFF_T_LEN;
len1 = 0;
/* node for create pool */
if (detail) {
n = ngx_timerd_nalloc - ngx_timerd_nfree;
/* " file:line\n" */
len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1;
len += len1 * n;
}
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NULL;
}
cl->buf = b;
b->last = ngx_snprintf(b->last, len,
"##########ngx debug pool##########\n"
"ngx_timerd nalloc node: %ui\nngx_timerd nfree node: %ui\n",
ngx_timerd_nalloc, ngx_timerd_nfree);
if (detail) {
for (node = ngx_map_begin(&ngx_timerd_map); node;
node = ngx_map_next(node))
{
/* m is first element of ngx_timerd_node_t */
pn = (ngx_timerd_node_t *) node;
b->last = ngx_snprintf(b->last, len1, " %s:%d\n",
pn->file, pn->line);
}
}
return cl;
}
@@ -1,68 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_TIMER_DEBUG_H_INCLUDED_
#define _NGX_TIMER_DEBUG_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#define NGX_ADD_TIMER(ev, timer, fpoff) \
ngx_add_timer_debug(ev, timer, fpoff, __FILE__, __LINE__)
#define NGX_DEL_TIMER(ev, footprint) \
ngx_del_timer_debug(ev, footprint, __FILE__, __LINE__)
/*
* generate a new footprint
*
* return:
* footprint
*/
ngx_uint_t ngx_timerd_footprint();
/*
* add timer and record where to add it for debugging
* such as timer not destroy
*
* paras:
* ev: nginx event for timer
* timer: timer interval for triggering timer
* fpoff: footprint offset in event data
* file: use __FILE__ for recording file
* line: use __LINE__ for recording line
* return:
* pool for successd, NULL for failed
*/
void ngx_add_timer_debug(ngx_event_t *ev, ngx_msec_t timer, off_t fpoff,
char *file, int line);
/*
* destroy pool for debugging, use as pair for ngx_create_pool_debug
*
* paras:
* ev: nginx event for timer
* footprint: footprint value in user event data
* file: use __FILE__ for recording file
* line: use __LINE__ for recording line
*/
void ngx_del_timer_debug(ngx_event_t *ev, ngx_uint_t footprint,
char *file, int line);
/*
* paras:
* r: http request to query status of rbuf
*/
ngx_chain_t *ngx_timerd_state(ngx_http_request_t *r, unsigned detail);
#endif
@@ -1,383 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_toolkit_misc.h"
#include <ngx_md5.h>
typedef struct {
ngx_str_t scheme;
in_port_t port;
} ngx_scheme_port_t;
ngx_scheme_port_t ngx_sheme_port[] = {
{ ngx_string("http"), 80 },
{ ngx_string("https"), 443 },
{ ngx_string("rtmp"), 1935 },
{ ngx_null_string, 0 }
};
#define FILEBUFSIZE 8192
socklen_t
ngx_sock_pton_unix(struct sockaddr *sa, u_char *text, size_t len)
{
#if NGX_HAVE_UNIX_DOMAIN
u_char *path;
struct sockaddr_un *saun;
// skip 'unix:'
path = text + 5;
len -= 5;
if (len == 0) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"no path in the unix domain");
return 0;
}
++len; // sun_path need '\0' as end
if (len > sizeof(saun->sun_path)) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"too long path in the unix domain socket");
return 0;
}
saun = (struct sockaddr_un *) sa;
saun->sun_family = AF_UNIX;
(void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
return sizeof(struct sockaddr_un);
#else
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"the unix domain sockets are not supported on this platform");
return 0;
#endif
}
socklen_t
ngx_sock_pton_inet6(struct sockaddr *sa, u_char *text, size_t len)
{
#if NGX_HAVE_INET6
struct in6_addr inaddr6;
struct sockaddr_in6 *sin6;
u_char *p, *last;
ngx_int_t port;
size_t alen, plen;
last = text + len;
p = ngx_strlchr(text, last, ']');
if (p == NULL || p == last - 1) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"not a ipv6 address format");
return 0;
}
++text;
alen = p - text;
/*
* prevent MSVC8 warning:
* potentially uninitialized local variable 'inaddr6' used
*/
ngx_memzero(&inaddr6, sizeof(struct in6_addr));
if (ngx_inet6_addr(text, alen, inaddr6.s6_addr) != NGX_OK) {
// not ipv6 address
return 0;
}
sa->sa_family = AF_INET6;
sin6 = (struct sockaddr_in6 *) sa;
ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
++p;
if (*p == ':') { // has port
++p;
plen = last - p;
port = ngx_atoi(p, plen);
if (port < 0 || port > 65535) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"invalid port: %i", port);
return 0;
}
ngx_inet_set_port(sa, (in_port_t) port);
}
return sizeof(struct sockaddr_in6);
#else
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"the INET6 sockets are not supported on this platform");
return 0;
#endif
}
socklen_t
ngx_sock_pton_inet(struct sockaddr *sa, u_char *text, size_t len)
{
in_addr_t inaddr;
struct sockaddr_in *sin;
u_char *p, *last;
ngx_int_t port;
size_t alen, plen;
last = text + len;
p = ngx_strlchr(text, last, ':');
alen = len;
if (p != NULL) { // have port
alen = p - text;
}
inaddr = ngx_inet_addr(text, alen);
if (inaddr == INADDR_NONE) {
// not ipv4 address
return 0;
}
sa->sa_family = AF_INET;
sin = (struct sockaddr_in *) sa;
sin->sin_addr.s_addr = inaddr;
if (p != NULL) { // has port
++p;
plen = last - p;
port = ngx_atoi(p, plen);
if (port < 0 || port > 65535) {
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
"invalid port: %i", port);
return 0;
}
ngx_inet_set_port(sa, (in_port_t) port);
}
return sizeof(struct sockaddr_in);
}
ngx_int_t
ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url)
{
u_char *last, *host_last;
u_char *scheme;
u_char *user, *host, *port;
u_char *path, *args, *fragment;
/* NULL url */
if (url->len == 0) {
return NGX_ERROR;
}
last = url->data + url->len;
scheme = url->data;
user = (u_char *) ngx_strnstr(scheme, "://", last - scheme);
if (user == NULL) {
return NGX_ERROR;
}
request_url->scheme.data = scheme;
request_url->scheme.len = user - scheme;
user += 3;
if (user >= last) {
return NGX_ERROR;
}
host_last = ngx_strlchr(user, last, '/');
if (host_last == NULL) {
host_last = last;
}
host = ngx_strlchr(user, host_last, '@');
if (host == NULL) { /* no user */
host = user;
} else {
if (user == host) { /* user is "" */
return NGX_ERROR;
}
request_url->user.data = user;
request_url->user.len = host - user;
++host;
if (host == host_last) { /* no host */
return NGX_ERROR;
}
}
port = ngx_strlchr(host, host_last, ':');
if (port == NULL) { /* no port */
request_url->host.data = host;
request_url->host.len = host_last - host;
request_url->host_with_port = request_url->host;
} else {
request_url->host.data = host;
request_url->host.len = port - host;
++port;
if (port == host_last) { /* port error */
return NGX_ERROR;
}
request_url->port.data = port;
request_url->port.len = host_last - port;
request_url->host_with_port.data = host;
request_url->host_with_port.len = host_last - host;
}
path = ++host_last;
if (path >= last) { /* no path */
goto done;
}
args = ngx_strlchr(path, last, '?');
if (args == NULL) { /* no args */
request_url->path.data = path;
request_url->path.len = last - path;
request_url->uri_with_args = request_url->path;
goto done;
} else {
request_url->path.data = path;
request_url->path.len = args - path;
++args;
if (args == last) { /* args error */
return NGX_ERROR;
}
}
fragment = ngx_strlchr(args, last, '#');
if (fragment == NULL) { /* no fragment */
request_url->args.data = args;
request_url->args.len = last - args;
} else {
request_url->args.data = args;
request_url->args.len = fragment - args;
++fragment;
if (fragment == last) { /* fragment error */
return NGX_ERROR;
}
request_url->fragment.data = fragment;
request_url->fragment.len = last - fragment;
}
request_url->uri_with_args.data = path;
request_url->uri_with_args.len = last - path;
done:
return NGX_OK;
}
in_port_t
ngx_request_port(ngx_str_t *scheme, ngx_str_t *port)
{
ngx_int_t p;
ngx_scheme_port_t *sp;
if (port->len) {
p = ngx_atoi(port->data, port->len);
if (p < 1 || p > 65535) { /* invalid port */
return 0;
}
return p;
}
for (sp = ngx_sheme_port; sp->port != 0; ++sp) {
if (sp->scheme.len == scheme->len
&& ngx_memcmp(sp->scheme.data, scheme->data, scheme->len) == 0)
{
return sp->port;
}
}
return 0;
}
ngx_int_t
ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN])
{
ngx_md5_t ctx;
u_char buf[FILEBUFSIZE];
u_char md5[16];
ssize_t n;
ngx_uint_t i;
u_char *p;
ngx_md5_init(&ctx);
for (;;) {
n = ngx_read_fd(fd, buf, FILEBUFSIZE);
if (n == 0) { /* read eof of file */
break;
}
if (n == NGX_FILE_ERROR) {
return NGX_ERROR;
}
ngx_md5_update(&ctx, buf, n);
}
ngx_md5_final(md5, &ctx);
p = md5key;
for (i = 0; i < 16; ++i) {
p = ngx_sprintf(p, "%02xi", md5[i]);
}
return NGX_OK;
}
ngx_int_t
ngx_copy_str(ngx_pool_t *pool, ngx_str_t *dst, ngx_str_t *src)
{
if (src->len == 0) {
return NGX_OK;
}
dst->len = src->len;
dst->data = ngx_palloc(pool, src->len);
if (dst->data == NULL) {
return NGX_ERROR;
}
ngx_memcpy(dst->data, src->data, src->len);
return NGX_OK;
}
socklen_t
ngx_sock_pton(struct sockaddr *sa, u_char *text, size_t len)
{
if (len >= 5 && ngx_strncasecmp(text, (u_char *) "unix:", 5) == 0) {
return ngx_sock_pton_unix(sa, text, len);
}
if (len && text[0] == '[') {
return ngx_sock_pton_inet6(sa, text, len);
}
return ngx_sock_pton_inet(sa, text, len);
}
@@ -1,126 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_TOOLKIT_MISC_H_INCLUDED_
#define _NGX_TOOLKIT_MISC_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
/*
* scheme://[user@]host[:port]/path[?args][#fragment]
*/
typedef struct {
ngx_str_t scheme;
ngx_str_t user;
ngx_str_t host;
ngx_str_t port;
ngx_str_t path;
ngx_str_t args;
ngx_str_t fragment;
ngx_str_t host_with_port; /* host[:port] */
ngx_str_t uri_with_args; /* /path[?args][#fragment] */
} ngx_request_url_t;
#define NGX_MD5KEY_LEN 32
/*
* parse request url format as:
* scheme://[user@]host[:port]/path[?args][#fragment]
*
* return value:
* NGX_OK : parse success
* NGX_ERROR: request url format error
* paras:
* request_url: url parse result return to user,
* all paras in request url is segment point to url
* url : request url for parse
*/
ngx_int_t ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url);
/*
* convert port to in_port_t according to scheme and port
*
* return value:
* If port is set to correct number range in [1, 65535], return port
* If port is set to non correct value, return 0
* If port is not set, return default value for scheme:
* 80 for http
* 443 for https
* 1935 for rtmp
* 0 for others now
* values:
* scheme : sheme string like http https or rtmp
* port : port for convert to in_port_t
*/
in_port_t ngx_request_port(ngx_str_t *scheme, ngx_str_t *port);
/*
* calculating file md5key as md5sum in shell
*
* return value:
* NGX_OK : calculating success
* NGX_ERROR: calculating error such as file is not exist
* paras:
* fd : file desc for calculating md5key
* md5key: md5key result
*/
ngx_int_t ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN]);
/*
* copy str
*
* return value:
* NGX_OK: copy successd
* NGX_ERROR: copy failed
* paras:
* pool: for alloc space for storing str
* dst: str copy to
* src: str copy from
*/
ngx_int_t ngx_copy_str(ngx_pool_t *pool, ngx_str_t *dst, ngx_str_t *src);
/*
* parse text to struct sockaddr
*
* return value:
* 0: if text is not ipv4/ipv6/unix address
* >0: socklen for sa
*
* paras:
* sa: struct sockadd parse to
* text: ipv4/ipv6/unix address for parsing, text could have port
* len: text's length
*/
socklen_t ngx_sock_pton(struct sockaddr *sa, u_char *text, size_t len);
#ifdef NGX_DEBUG
#define NGX_START_TIMING \
struct timeval __start, __end; \
ngx_gettimeofday(&__start);
#define NGX_STOP_TIMING(log, msg) \
ngx_gettimeofday(&__end); \
ngx_log_error(NGX_LOG_INFO, log, 0, msg " spend %ui us", \
(__end.tv_sec - __start.tv_sec) * 1000000 \
+ (__end.tv_usec - __start.tv_usec));
#else
#define NGX_START_TIMING
#define NGX_STOP_TIMING(log, msg)
#endif
#endif
@@ -1,32 +0,0 @@
ngx_addon_name=ngx_toolkit_test_module
CORE_MODULES="$CORE_MODULES
ngx_dynamic_core_test_module \
"
HTTP_MODULES="$HTTP_MODULES \
ngx_event_timer_test_module \
ngx_event_resolver_test_module \
ngx_dynamic_resolver_test_module \
ngx_dynamic_conf_test_module \
ngx_http_dynamic_test_module \
ngx_toolkit_misc_test_module \
ngx_map_test_module \
ngx_rbuf_test_module \
ngx_poold_test_module \
ngx_timerd_test_module \
"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/ngx_event_timer_test_module.c \
$ngx_addon_dir/ngx_event_resolver_test_module.c \
$ngx_addon_dir/ngx_dynamic_resolver_test_module.c \
$ngx_addon_dir/ngx_dynamic_conf_test_module.c \
$ngx_addon_dir/ngx_http_dynamic_test_module.c \
$ngx_addon_dir/ngx_toolkit_misc_test_module.c \
$ngx_addon_dir/ngx_map_test_module.c \
$ngx_addon_dir/ngx_rbuf_test_module.c \
$ngx_addon_dir/ngx_poold_test_module.c \
$ngx_addon_dir/ngx_timerd_test_module.c \
"
@@ -1,7 +0,0 @@
#! /bin/bash
yum install -y bind bind-chroot bind-utils
cp -f named.conf /etc/
cp -f test.com.zone /var/named/
chgrp named /etc/named.conf
chgrp named /var/named/test.com.zone
@@ -1,24 +0,0 @@
Copyright (C) 2016-2020, by Jie Wu "AlexWoo" <wj19840501@gmail.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
@@ -1,25 +0,0 @@
options {
directory "/var/named";
recursion no;
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
zone "test.com." {
type master;
file "test.com.zone";
};
zone "test1.com." {
type master;
file "test1.com.zone";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
@@ -1,94 +0,0 @@
user root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
error_log logs/error.log info;
#error_log logs/error.log debug;
#pid logs/nginx.pid;
dynamic_conf conf/nginx_dynamic.conf 10;
dynamic_log logs/error_dynamic.log info;
events {
worker_connections 1024;
worker_timers 1024;
resolver 192.168.84.254 valid=20s;
resolver_timeout 10s;
dynamic_refresh_interval 5m;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location /trace1/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_set_header X-NTM-Parentid $ntm_currentid;
proxy_set_header X-NTM-Currentid $ntm_newid;
proxy_pass http://127.0.0.1/trace/;
}
location /trace/ {
echo $http_x_ntm_traceid;
echo $http_x_ntm_currentid;
echo $http_x_ntm_parentid;
echo $http_x_ntm_debug;
echo "trace variables";
echo $ntm_traceid;
echo $ntm_currentid;
echo $ntm_parentid;
echo $ntm_debug;
}
location /event_timer_test/ {
event_timer_test;
}
location /event_resolver_test/ {
event_resolver_test;
}
location /dynamic_resolver_test/ {
dynamic_resolver_test 192.168.84.4 www.test1.com;
}
location /dynamic_conf_test/ {
dynamic_conf_test;
}
location / {
http_dynamic_test;
}
location /map_test/ {
map_test;
}
location /toolkit_misc_test/ {
toolkit_misc_test;
}
location /rbuf_test/ {
rbuf_test;
}
location /poold_test/ {
poold_test;
}
}
}
@@ -1,74 +0,0 @@
dynamic_test_i 200;
dynamic_test_s hello_world;
http {
main_int 1000;
main_str gogogo;
#defult server
server {
srv_int 1;
srv_str default;
}
#wildcard_head
server {
srv_int 2;
srv_str wildcard_head;
server_name *.baidu.com;
}
#wildcard_tail
server {
srv_int 3;
srv_str wildcard_tail;
server_name www.google.*;
}
#hash
server {
srv_int 4;
srv_str hash;
server_name sports.sina.com.cn;
location = / {
loc_int 1;
loc_str =/;
}
location / {
loc_int 2;
loc_str /;
}
location ^~ /test1/ {
loc_int 3;
loc_str ^~/test1/;
}
location ~* \.(gif|jpg|jpeg)$ {
loc_int 4;
loc_str ~*\.(gif|jpg|jpeg)$;
}
location /test {
loc_int 5;
loc_str /test;
}
}
#pcre
server {
srv_int 5;
srv_str pcre;
server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.test\.com$;
}
#multi
server {
srv_int 6;
srv_str multi;
server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.haha\.com$ www.sohu.com;
server_name *.qq.com;
}
}
@@ -1,200 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_dynamic_conf.h"
/******************************************************************************/
static void *ngx_dynamic_core_test_create_conf(ngx_conf_t *cf);
static char *ngx_dynamic_core_test_init_conf(ngx_conf_t *cf, void *conf);
typedef struct {
ngx_uint_t i;
ngx_str_t s;
} ngx_dynamic_core_test_conf_t;
ngx_core_module_t ngx_dynamic_core_test_module_ctx = {
ngx_string("dynamic_core_test"),
NULL,
NULL
};
static ngx_command_t ngx_dynamic_core_test_dcommands[] = {
{ ngx_string("dynamic_test_i"),
NGX_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_dynamic_core_test_conf_t, i),
NULL },
{ ngx_string("dynamic_test_s"),
NGX_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_dynamic_core_test_conf_t, s),
NULL },
ngx_null_command
};
static ngx_dynamic_core_module_t ngx_dynamic_core_test_module_dctx = {
ngx_string("dynamic_core_test"),
ngx_dynamic_core_test_create_conf,
ngx_dynamic_core_test_init_conf
};
ngx_module_t ngx_dynamic_core_test_module = {
NGX_MODULE_V1,
&ngx_dynamic_core_test_module_ctx, /* module context */
NULL, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
(uintptr_t) &ngx_dynamic_core_test_module_dctx, /* module dynamic context */
(uintptr_t) ngx_dynamic_core_test_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
static void *
ngx_dynamic_core_test_create_conf(ngx_conf_t *cf)
{
ngx_dynamic_core_test_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_dynamic_core_test_conf_t));
if (conf == NULL) {
return NULL;
}
conf->i = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_dynamic_core_test_init_conf(ngx_conf_t *cf, void *conf)
{
ngx_dynamic_core_test_conf_t *dctcf;
dctcf = conf;
ngx_conf_init_uint_value(dctcf->i, 1000);
return NGX_CONF_OK;
}
/******************************************************************************/
static char *ngx_dynamic_conf_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#define MAXBUFSIZE 4096
static ngx_command_t ngx_dynamic_conf_test_commands[] = {
{ ngx_string("dynamic_conf_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_dynamic_conf_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_dynamic_conf_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_dynamic_conf_test_module = {
NGX_MODULE_V1,
&ngx_dynamic_conf_test_module_ctx, /* module context */
ngx_dynamic_conf_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_dynamic_conf_test_handler(ngx_http_request_t *r)
{
ngx_chain_t cl;
ngx_buf_t *b;
ngx_dynamic_core_test_conf_t *dctcf;
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic conf test handler");
b = ngx_create_temp_buf(r->pool, MAXBUFSIZE);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
dctcf = (ngx_dynamic_core_test_conf_t *)
ngx_get_dconf(&ngx_dynamic_core_test_module);
if (dctcf == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic conf test handler, dynamic conf not configured");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
b->last = ngx_snprintf(b->last, MAXBUFSIZE, "dynamic core test %ui [%V]\n",
dctcf->i, &dctcf->s);
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body");
return ngx_http_output_filter(r, &cl);
}
static char *
ngx_dynamic_conf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_dynamic_conf_test_handler;
return NGX_CONF_OK;
}
@@ -1,193 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_dynamic_resolver.h"
static char *ngx_dynamic_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
typedef struct {
ngx_flag_t sync;
} ngx_dynamic_resolver_test_ctx_t;
static ngx_command_t ngx_dynamic_resolver_test_commands[] = {
{ ngx_string("dynamic_resolver_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
ngx_dynamic_resolver_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_dynamic_resolver_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_dynamic_resolver_test_module = {
NGX_MODULE_V1,
&ngx_dynamic_resolver_test_module_ctx, /* module context */
ngx_dynamic_resolver_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void
ngx_dynamic_resolver_test_result(void *data, struct sockaddr *sa, socklen_t len)
{
ngx_dynamic_resolver_test_ctx_t *ctx;
ngx_chain_t cl;
ngx_buf_t *b;
ngx_int_t rc;
ngx_http_request_t *r;
u_char text[NGX_SOCKADDRLEN];
r = data;
r->headers_out.status = NGX_HTTP_OK;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send header");
if (len == 0) {
r->headers_out.content_length_n = 0;
r->header_only = 1;
}
ctx = ngx_http_get_module_ctx(r, ngx_dynamic_resolver_test_module);
if (ctx == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
ngx_http_finalize_request(r, rc);
return;
}
ngx_memzero(text, sizeof(text));
len = ngx_sock_ntop(sa, len, text, NGX_SOCKADDRLEN, 0) + 1;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
b->last = ngx_snprintf(b->last, len, "%s\n", text);
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body");
ngx_http_output_filter(r, &cl);
if (ctx->sync) {
return;
}
ngx_http_finalize_request(r, NGX_OK);
}
static ngx_int_t
ngx_dynamic_resolver_test_handler(ngx_http_request_t *r)
{
ngx_dynamic_resolver_test_ctx_t *ctx;
ngx_str_t domain, sync;
struct sockaddr sa;
socklen_t len;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"dynamic resolver test handler");
ctx = ngx_pcalloc(r->pool, sizeof(ngx_dynamic_resolver_test_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_http_set_ctx(r, ctx, ngx_dynamic_resolver_test_module);
if (ngx_http_arg(r, (u_char *) "domain", 6, &domain) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"dynamic resolver test, no domain in http args");
return NGX_HTTP_BAD_REQUEST;
}
if (ngx_http_arg(r, (u_char *) "sync", 4, &sync) == NGX_OK) {
ctx->sync = 1;
}
if (r->method == NGX_HTTP_GET && ctx->sync == 0) {
r->count++;
ngx_dynamic_resolver_start_resolver(&domain,
ngx_dynamic_resolver_test_result, r);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"dynamic resolver test, after start resolver");
return NGX_DONE;
} else if (r->method == NGX_HTTP_GET && ctx->sync) {
ngx_memzero(&sa, sizeof(sa));
len = ngx_dynamic_resolver_gethostbyname(&domain, &sa);
ngx_dynamic_resolver_test_result(r, &sa, len);
return NGX_OK;
} else if (r->method != NGX_HTTP_DELETE) {
return NGX_HTTP_BAD_REQUEST;
}
ngx_dynamic_resolver_del_domain(&domain);
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = 0;
r->header_only = 1;
return ngx_http_send_header(r);
}
static char *
ngx_dynamic_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
ngx_str_t *value;
ngx_uint_t i;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_dynamic_resolver_test_handler;
value = cf->args->elts;
for (i = 1; i < cf->args->nelts; ++i) {
ngx_dynamic_resolver_add_domain(&value[i], cf->cycle);
}
return NGX_CONF_OK;
}
@@ -1,150 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_event_resolver.h"
static char *ngx_event_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_event_resolver_test_commands[] = {
{ ngx_string("event_resolver_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_event_resolver_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_event_resolver_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_event_resolver_test_module = {
NGX_MODULE_V1,
&ngx_event_resolver_test_module_ctx, /* module context */
ngx_event_resolver_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void
ngx_event_resolver_test_result(void *data, ngx_resolver_addr_t *addrs,
ngx_uint_t naddrs)
{
ngx_chain_t *cl, **ll;
ngx_buf_t *b;
size_t len;
ngx_int_t rc;
ngx_uint_t i;
ngx_http_request_t *r;
u_char text[NGX_SOCKADDRLEN];
r = data;
r->headers_out.status = NGX_HTTP_OK;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send header");
if (naddrs == 0) {
r->headers_out.content_length_n = 0;
r->header_only = 1;
}
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
ngx_http_finalize_request(r, rc);
return;
}
ll = &cl;
for (i = 0; i < naddrs; ++i) {
len = ngx_sock_ntop(addrs[i].sockaddr, addrs[i].socklen, text,
NGX_SOCKADDRLEN, 0) + 1;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
b->last = ngx_snprintf(b->last, len, "%s\n", text);
if (i == naddrs - 1) {
b->last_buf = 1;
b->last_in_chain = 1;
}
*ll = ngx_alloc_chain_link(r->pool);
(*ll)->buf = b;
(*ll)->next = NULL;
ll = &(*ll)->next;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body");
ngx_http_output_filter(r, cl);
ngx_http_finalize_request(r, NGX_OK);
}
static ngx_int_t
ngx_event_resolver_test_handler(ngx_http_request_t *r)
{
ngx_str_t domain;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"event resolver test handler");
if (ngx_http_arg(r, (u_char *) "domain", sizeof("domain") - 1, &domain)
!= NGX_OK)
{
return NGX_HTTP_BAD_REQUEST;
}
++r->count;
ngx_event_resolver_start_resolver(&domain,
ngx_event_resolver_test_result, r);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"after start resolver");
return NGX_DONE;
}
static char *
ngx_event_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_event_resolver_test_handler;
return NGX_CONF_OK;
}
@@ -1,151 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_event_timer_module.h"
static char *ngx_event_timer_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_event_timer_test_commands[] = {
{ ngx_string("event_timer_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_event_timer_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_event_timer_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_event_timer_test_module = {
NGX_MODULE_V1,
&ngx_event_timer_test_module_ctx, /* module context */
ngx_event_timer_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void
ngx_event_timer_test_timer_handler(void *data)
{
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"event timer test timer handler");
}
static ngx_int_t
ngx_event_timer_test_handler(ngx_http_request_t *r)
{
ngx_chain_t cl;
ngx_buf_t *b;
size_t len;
ngx_int_t rc, timerid;
ngx_msec_t time;
ngx_str_t arg;
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"event timer test handler");
if (r->method == NGX_HTTP_DELETE) {
len = sizeof("delete timer timerid=NGX_OFF_T_LEN\n") - 1;
if (ngx_http_arg(r, (u_char *) "timerid", 7, &arg) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"event timer test, no timerid in http args");
return NGX_HTTP_BAD_REQUEST;
}
timerid = ngx_atoi(arg.data, arg.len);
if (timerid == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"event timer test, timerid arg not int type");
return NGX_HTTP_BAD_REQUEST;
}
ngx_event_timer_del_timer(timerid);
} else if (r->method == NGX_HTTP_POST) {
len = sizeof("add timer timerid=NGX_OFF_T_LEN\n") - 1;
if (ngx_http_arg(r, (u_char *) "time", 4, &arg) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"event timer test, no time in http args");
return NGX_HTTP_BAD_REQUEST;
}
time = ngx_parse_time(&arg, 0);
if (time == (ngx_msec_t) NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"event timer test, time arg not time type");
return NGX_HTTP_BAD_REQUEST;
}
timerid = ngx_event_timer_add_timer(time,
ngx_event_timer_test_timer_handler, NULL);
} else {
return NGX_HTTP_BAD_REQUEST;
}
r->headers_out.status = NGX_HTTP_OK;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
return rc;
}
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (r->method == NGX_HTTP_DELETE) {
b->last = ngx_snprintf(b->last, len,
"delete timer timerid=%i\n", timerid);
} else {
b->last = ngx_snprintf(b->last, len,
"add timer timerid=%i\n", timerid);
}
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
return ngx_http_output_filter(r, &cl);
}
static char *
ngx_event_timer_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_event_timer_test_handler;
return NGX_CONF_OK;
}
@@ -1,300 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_dynamic_conf.h"
#include "ngx_http_dynamic.h"
static char *ngx_http_dynamic_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void *ngx_http_dynamic_test_create_main_conf(ngx_conf_t *cf);
static char *ngx_http_dynamic_test_init_main_conf(ngx_conf_t *cf, void *conf);
static void *ngx_http_dynamic_test_create_srv_conf(ngx_conf_t *cf);
static char *ngx_http_dynamic_test_init_srv_conf(ngx_conf_t *cf, void *conf);
static void *ngx_http_dynamic_test_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_dynamic_test_init_loc_conf(ngx_conf_t *cf, void *conf);
#define MAXBUFSIZE 4096
typedef struct {
ngx_uint_t mi;
ngx_str_t ms;
} ngx_http_dynamic_test_main_conf_t;
typedef struct {
ngx_uint_t si;
ngx_str_t ss;
} ngx_http_dynamic_test_srv_conf_t;
typedef struct {
ngx_uint_t li;
ngx_str_t ls;
} ngx_http_dynamic_test_loc_conf_t;
static ngx_command_t ngx_http_dynamic_test_commands[] = {
{ ngx_string("http_dynamic_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_dynamic_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_dynamic_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
static ngx_command_t ngx_http_dynamic_test_dcommands[] = {
{ ngx_string("main_int"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_http_dynamic_test_main_conf_t, mi),
NULL },
{ ngx_string("main_str"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_http_dynamic_test_main_conf_t, ms),
NULL },
{ ngx_string("srv_int"),
NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_http_dynamic_test_srv_conf_t, si),
NULL },
{ ngx_string("srv_str"),
NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_http_dynamic_test_srv_conf_t, ss),
NULL },
{ ngx_string("loc_int"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_http_dynamic_test_loc_conf_t, li),
NULL },
{ ngx_string("loc_str"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_http_dynamic_test_loc_conf_t, ls),
NULL },
ngx_null_command
};
static ngx_http_dynamic_module_t ngx_http_dynamic_test_module_dctx = {
ngx_http_dynamic_test_create_main_conf, /* create main configuration */
ngx_http_dynamic_test_init_main_conf, /* init main configuration */
ngx_http_dynamic_test_create_srv_conf, /* create server configuration */
ngx_http_dynamic_test_init_srv_conf, /* init server configuration */
ngx_http_dynamic_test_create_loc_conf, /* create location configuration */
ngx_http_dynamic_test_init_loc_conf /* init location configuration */
};
ngx_module_t ngx_http_dynamic_test_module = {
NGX_MODULE_V1,
&ngx_http_dynamic_test_module_ctx, /* module context */
ngx_http_dynamic_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
(uintptr_t) &ngx_http_dynamic_test_module_dctx, /* module dynamic context */
(uintptr_t) ngx_http_dynamic_test_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
static void *
ngx_http_dynamic_test_create_main_conf(ngx_conf_t *cf)
{
ngx_http_dynamic_test_main_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_main_conf_t));
if (conf == NULL) {
return NULL;
}
conf->mi = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_http_dynamic_test_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_dynamic_test_main_conf_t *hdtmcf;
hdtmcf = conf;
ngx_conf_init_uint_value(hdtmcf->mi, 100);
if (hdtmcf->ms.len == 0) {
ngx_str_set(&hdtmcf->ms, "test for ms");
}
return NGX_CONF_OK;
}
static void *
ngx_http_dynamic_test_create_srv_conf(ngx_conf_t *cf)
{
ngx_http_dynamic_test_srv_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_srv_conf_t));
if (conf == NULL) {
return NULL;
}
conf->si = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_http_dynamic_test_init_srv_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_dynamic_test_srv_conf_t *hdtscf;
hdtscf = conf;
ngx_conf_init_uint_value(hdtscf->si, 100);
if (hdtscf->ss.len == 0) {
ngx_str_set(&hdtscf->ss, "test for ss");
}
return NGX_CONF_OK;
}
static void *
ngx_http_dynamic_test_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_dynamic_test_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_loc_conf_t));
if (conf == NULL) {
return NULL;
}
conf->li = NGX_CONF_UNSET_UINT;
return conf;
}
static char *
ngx_http_dynamic_test_init_loc_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_dynamic_test_loc_conf_t *hdtlcf;
hdtlcf = conf;
ngx_conf_init_uint_value(hdtlcf->li, 100);
if (hdtlcf->ls.len == 0) {
ngx_str_set(&hdtlcf->ls, "test for ls");
}
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_dynamic_test_handler(ngx_http_request_t *r)
{
ngx_chain_t cl;
ngx_buf_t *b;
ngx_http_dynamic_test_main_conf_t *hdtmcf;
ngx_http_dynamic_test_srv_conf_t *hdtscf;
ngx_http_dynamic_test_loc_conf_t *hdtlcf;
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "http dynamic test handler");
b = ngx_create_temp_buf(r->pool, MAXBUFSIZE);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
hdtmcf = ngx_http_get_module_main_dconf(r, &ngx_http_dynamic_test_module);
if (hdtmcf == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic conf test handler, dynamic main conf not configured");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
hdtscf = ngx_http_get_module_srv_dconf(r, &ngx_http_dynamic_test_module);
if (hdtscf == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic conf test handler, dynamic srv conf not configured");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
hdtlcf = ngx_http_get_module_loc_dconf(r, &ngx_http_dynamic_test_module);
if (hdtlcf == NULL) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"dynamic conf test handler, dynamic loc conf not configured");
}
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
b->last = ngx_snprintf(b->last, MAXBUFSIZE,
"dynamic core test mi:%ui ms:%V\n", hdtmcf->mi, &hdtmcf->ms);
b->last = ngx_snprintf(b->last, MAXBUFSIZE,
"dynamic core test si:%ui ss:%V\n", hdtscf->si, &hdtscf->ss);
if (hdtlcf) {
b->last = ngx_snprintf(b->last, MAXBUFSIZE,
"dynamic core test li:%ui ls:%V\n", hdtlcf->li, &hdtlcf->ls);
}
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body");
return ngx_http_output_filter(r, &cl);
}
static char *
ngx_http_dynamic_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_dynamic_test_handler;
return NGX_CONF_OK;
}
@@ -1,251 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_map.h"
#include "ngx_test_macro.h"
static char *ngx_map_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_map_test_commands[] = {
{ ngx_string("map_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_map_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_map_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_map_test_module = {
NGX_MODULE_V1,
&ngx_map_test_module_ctx, /* module context */
ngx_map_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
#define MAP_NODE_INIT_STR(n, k) \
ngx_map_node_t n; \
static ngx_str_t k = ngx_string(#k); \
ngx_memzero(&n, sizeof(ngx_map_node_t)); \
n.raw_key = (intptr_t) &k;
#define MAP_NODE_PRINT_KEY_STR(n) \
{ \
ngx_str_t *s = (ngx_str_t *) (n)->raw_key; \
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, \
"!!!!!!!!!!!!!!!!%V", s); \
}
static ngx_int_t
ngx_map_test_handler(ngx_http_request_t *r)
{
ngx_buf_t *b;
ngx_chain_t cl;
size_t len;
ngx_map_t map;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"map test handler");
ngx_memzero(&map, sizeof(ngx_map_t));
ngx_map_init(&map, ngx_map_hash_str, ngx_cmp_str);
MAP_NODE_INIT_STR(n1, k1)
MAP_NODE_INIT_STR(n2, k2)
MAP_NODE_INIT_STR(n3, k3)
MAP_NODE_INIT_STR(n4, k4)
MAP_NODE_INIT_STR(n5, k5)
MAP_NODE_INIT_STR(n6, k6)
MAP_NODE_INIT_STR(n7, k7)
MAP_NODE_INIT_STR(n8, k8)
MAP_NODE_INIT_STR(n9, k9)
MAP_NODE_INIT_STR(n10, k10)
ngx_map_node_t n11;
static ngx_str_t k11 = ngx_string("k5");
ngx_memzero(&n11, sizeof(ngx_map_node_t));
n11.raw_key = (intptr_t) &k11;
ngx_map_insert(&map, &n1, 0);
ngx_map_insert(&map, &n2, 0);
ngx_map_insert(&map, &n3, 0);
ngx_map_insert(&map, &n4, 0);
ngx_map_insert(&map, &n5, 0);
ngx_map_insert(&map, &n6, 0);
ngx_map_insert(&map, &n7, 0);
ngx_map_insert(&map, &n8, 0);
ngx_map_insert(&map, &n9, 0);
ngx_map_insert(&map, &n10, 0);
ngx_map_insert(&map, &n11, 0);
NGX_TEST_INIT
ngx_map_node_t *n;
n = ngx_map_begin(&map);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n1 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n2 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n3 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n4 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n5 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n6 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n7 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n8 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n9 == n)
n = ngx_map_next(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n10 == n)
n = ngx_map_next(n);
NGX_TEST_ISOK(NULL == n)
n = ngx_map_rbegin(&map);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n10 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n9 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n8 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n7 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n6 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n5 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n4 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n3 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n2 == n)
n = ngx_map_prev(n);
MAP_NODE_PRINT_KEY_STR(n)
NGX_TEST_ISOK(&n1 == n)
n = ngx_map_prev(n);
NGX_TEST_ISOK(NULL == n)
static ngx_str_t kk1 = ngx_string("k100");
NGX_TEST_ISOK(NULL == ngx_map_find(&map, (intptr_t) &kk1))
static ngx_str_t kk2 = ngx_string("k5");
NGX_TEST_ISOK(&n5 == ngx_map_find(&map, (intptr_t) &kk2))
ngx_map_insert(&map, &n11, 1);
NGX_TEST_ISOK(&n11 == ngx_map_find(&map, (intptr_t) &kk2))
static ngx_str_t kk3 = ngx_string("k8");
ngx_map_delete(&map, (intptr_t) &kk3);
NGX_TEST_ISOK(NULL == ngx_map_find(&map, (intptr_t) &kk3))
static ngx_str_t kk4 = ngx_string("k8");
ngx_map_insert(&map, &n8, 1);
NGX_TEST_ISOK(&n8 == ngx_map_find(&map, (intptr_t) &kk4))
static ngx_str_t kk5 = ngx_string("k7");
NGX_TEST_ISOK(&n7 == ngx_map_find(&map, (intptr_t) &kk5))
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
len = sizeof("TEST cases 4294967296, 4294967296 pass\n") - 1;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
b->last = ngx_snprintf(b->last, len, "TEST cases %d, %d pass\n",
count, pass);
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
return ngx_http_output_filter(r, &cl);
}
static char *
ngx_map_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_map_test_handler;
return NGX_CONF_OK;
}
@@ -1,90 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_poold.h"
static char *ngx_poold_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_poold_test_commands[] = {
{ ngx_string("poold_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_poold_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_poold_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_poold_test_module = {
NGX_MODULE_V1,
&ngx_poold_test_module_ctx, /* module context */
ngx_poold_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_poold_test_handler(ngx_http_request_t *r)
{
ngx_chain_t *out;
ngx_pool_t *pool;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "poold test handler");
pool = NGX_CREATE_POOL(4096, r->connection->log);
pool = NGX_CREATE_POOL(1024, r->connection->log);
NGX_DESTROY_POOL(pool);
NGX_DESTROY_POOL(pool);
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
out = ngx_poold_state(r, 1);
out->buf->last_buf = 1;
return ngx_http_output_filter(r, out);
}
static char *
ngx_poold_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_poold_test_handler;
return NGX_CONF_OK;
}
@@ -1,116 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "../ngx_rbuf.h"
static char *ngx_rbuf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_rbuf_test_commands[] = {
{ ngx_string("rbuf_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_rbuf_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_rbuf_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_rbuf_test_module = {
NGX_MODULE_V1,
&ngx_rbuf_test_module_ctx, /* module context */
ngx_rbuf_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_rbuf_test_handler(ngx_http_request_t *r)
{
ngx_str_t size;
ngx_int_t key;
ngx_chain_t *cl, *cl1, *cl2;
ngx_chain_t *out;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "rbuf test handler");
if (ngx_http_arg(r, (u_char *) "size", sizeof("size") - 1, &size)
!= NGX_OK)
{
return NGX_HTTP_BAD_REQUEST;
}
key = ngx_atoi(size.data, size.len);
cl = ngx_get_chainbuf(key, 1);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl: %p", cl);
cl1 = ngx_get_chainbuf(key, 0);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl1: %p", cl1);
cl1->buf->start = cl->buf->start;
cl1->buf->end = cl->buf->end;
cl1->buf->pos = cl->buf->pos;
cl1->buf->last = cl->buf->last;
cl2 = ngx_get_chainbuf(key, 0);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl2: %p", cl2);
cl2->buf->start = cl->buf->start;
cl2->buf->end = cl->buf->end;
cl2->buf->pos = cl->buf->pos;
cl2->buf->last = cl->buf->last;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "rbuf free");
ngx_put_chainbuf(cl2);
ngx_put_chainbuf(cl);
ngx_put_chainbuf(cl1);
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
out = ngx_rbuf_state(r, 1);
out->buf->last_buf = 1;
return ngx_http_output_filter(r, out);
}
static char *
ngx_rbuf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_rbuf_test_handler;
return NGX_CONF_OK;
}
@@ -1,41 +0,0 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_TEST_MACRO_H_INCLUDE_
#define _NGX_TEST_MACRO_H_INCLUDE_
#include <ngx_config.h>
#include <ngx_core.h>
static ngx_int_t count = 0;
static ngx_int_t pass = 0;
#define NGX_TEST_INIT count = 0, pass = 0;
#define NGX_TEST_ISOK(testcase) \
{ \
ngx_int_t __ret = testcase; \
++count; \
if (__ret) ++pass; \
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, " TEST "#testcase"%s",\
(__ret ? " ...OK" : " ...ERROR")); \
}
#define NGX_TEST_INT(di, si) \
(di == si)
static ngx_inline ngx_int_t
ngx_test_str(ngx_str_t *nstr, char *cstr)
{
size_t len;
len = ngx_strlen(cstr);
return (nstr->len == len && ngx_memcmp(nstr->data, cstr, len) == 0);
}
#endif
@@ -1,198 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_timerd.h"
static char *ngx_timerd_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
typedef struct {
ngx_pool_t *pool;
ngx_event_t ev;
ngx_uint_t footprint;
} ngx_timer_test_data_t;
static ngx_command_t ngx_timerd_test_commands[] = {
{ ngx_string("timerd_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_timerd_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_timerd_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_timerd_test_module = {
NGX_MODULE_V1,
&ngx_timerd_test_module_ctx, /* module context */
ngx_timerd_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void
ngx_timerd_test_timer(ngx_event_t *ev)
{
ngx_timer_test_data_t *data;
data = ev->data;
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "timerd test timer: %p %ui",
data, data->footprint);
}
static ngx_int_t
ngx_timerd_test_handler(ngx_http_request_t *r)
{
ngx_chain_t *out;
// normal timer trigger
ngx_timer_test_data_t *test;
ngx_pool_t *pool;
pool = ngx_create_pool(4096, r->connection->log);
test = ngx_pcalloc(pool, sizeof(ngx_timer_test_data_t));
test->pool = pool;
test->footprint = ngx_timerd_footprint();
test->ev.data = test;
test->ev.handler = ngx_timerd_test_timer;
NGX_ADD_TIMER(&test->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"!!!!!!!!!!normal timer trigger: %p %ui", test, test->footprint);
// delete timer twice
ngx_timer_test_data_t *test1;
ngx_pool_t *pool1;
pool1 = ngx_create_pool(4096, r->connection->log);
test1 = ngx_pcalloc(pool1, sizeof(ngx_timer_test_data_t));
test1->pool = pool1;
test1->footprint = ngx_timerd_footprint();
test1->ev.data = test1;
test1->ev.handler = ngx_timerd_test_timer;
NGX_ADD_TIMER(&test1->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"!!!!!!!!!!delete timer twice: %p %ui", test1, test1->footprint);
NGX_DEL_TIMER(&test1->ev, test1->footprint);
NGX_DEL_TIMER(&test1->ev, test1->footprint);
// timer trigger after event destroy
ngx_timer_test_data_t *test2;
ngx_pool_t *pool2;
pool2 = ngx_create_pool(4096, r->connection->log);
test2 = ngx_pcalloc(pool2, sizeof(ngx_timer_test_data_t));
test2->pool = pool2;
test2->footprint = ngx_timerd_footprint();
test2->ev.data = test2;
test2->ev.handler = ngx_timerd_test_timer;
NGX_ADD_TIMER(&test2->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"!!!!!!!!!!timer trigger after event destroy: %p %ui",
test2, test2->footprint);
test2->footprint = ngx_timerd_footprint();
ngx_destroy_pool(pool2);
// delete timer after event destroy
ngx_timer_test_data_t *test3;
ngx_pool_t *pool3;
pool3 = ngx_create_pool(4096, r->connection->log);
test3 = ngx_pcalloc(pool3, sizeof(ngx_timer_test_data_t));
test3->pool = pool3;
test3->footprint = ngx_timerd_footprint();
test3->ev.data = test3;
test3->ev.handler = ngx_timerd_test_timer;
NGX_ADD_TIMER(&test3->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"!!!!!!!!!!delete timer after event destroy: %p %ui",
test3, test3->footprint);
test3->footprint = ngx_timerd_footprint();
NGX_DEL_TIMER(&test3->ev, test3->footprint);
ngx_destroy_pool(pool3);
// add timer after event destroy
ngx_timer_test_data_t *test4;
ngx_pool_t *pool4;
pool4 = ngx_create_pool(4096, r->connection->log);
test4 = ngx_pcalloc(pool4, sizeof(ngx_timer_test_data_t));
test4->pool = pool4;
test4->footprint = ngx_timerd_footprint();
test4->ev.data = test4;
test4->ev.handler = ngx_timerd_test_timer;
NGX_ADD_TIMER(&test4->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"!!!!!!!!!!add timer after event destroy: %p %ui",
test4, test4->footprint);
test4->footprint = ngx_timerd_footprint();
NGX_ADD_TIMER(&test4->ev, 5000, offsetof(ngx_timer_test_data_t, footprint));
ngx_destroy_pool(pool4);
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
out = ngx_timerd_state(r, 1);
out->buf->last_buf = 1;
return ngx_http_output_filter(r, out);
}
static char *
ngx_timerd_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_timerd_test_handler;
return NGX_CONF_OK;
}
@@ -1,285 +0,0 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_toolkit_misc.h"
#include "ngx_test_macro.h"
static char *ngx_toolkit_misc_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_toolkit_misc_test_commands[] = {
{ ngx_string("toolkit_misc_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_toolkit_misc_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_toolkit_misc_test_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_toolkit_misc_test_module = {
NGX_MODULE_V1,
&ngx_toolkit_misc_test_module_ctx, /* module context */
ngx_toolkit_misc_test_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_parse_toolkit_misc_test(ngx_int_t ret, char *url, char *scheme, char *user,
char *host, char *port, char *path, char *args, char *fragment,
char *host_with_port, char *uri_with_args)
{
ngx_int_t _ret;
ngx_str_t _url;
ngx_request_url_t rurl;
ngx_memzero(&rurl, sizeof(ngx_request_url_t));
_url.data = (u_char *) url;
_url.len = ngx_strlen(url);
_ret = ngx_parse_request_url(&rurl, &_url);
if (ret != _ret) {
return 0;
}
if (_ret == NGX_ERROR) {
return 1;
}
#define TEST(para) \
if (para == NULL && rurl.para.len) { \
return 0; \
} else if (para && ngx_test_str(&rurl.para, para) == NGX_ERROR) { \
return 0; \
}
TEST(scheme)
TEST(user)
TEST(host)
TEST(port)
TEST(path)
TEST(args)
TEST(fragment)
TEST(host_with_port)
TEST(uri_with_args)
#undef TEST
return 1;
}
static ngx_int_t
ngx_request_port_test(in_port_t expect, char *scheme, char *port)
{
in_port_t ret;
ngx_str_t _scheme, _port;
_scheme.data = (u_char *) scheme;
_scheme.len = ngx_strlen(scheme);
_port.data = (u_char *) port;
_port.len = ngx_strlen(port);
ret = ngx_request_port(&_scheme, &_port);
return ret == expect;
}
static ngx_int_t
ngx_toolkit_misc_test_handler(ngx_http_request_t *r)
{
ngx_buf_t *b;
ngx_chain_t cl;
size_t len;
ngx_fd_t fd;
u_char md5key[NGX_MD5KEY_LEN];
ngx_str_t file;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"request url test handler");
NGX_TEST_INIT
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "test",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://alex@",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://alex@test",
"http",
"alex", "test", NULL,
NULL, NULL, NULL,
"test", NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://alex@test:",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://alex@test:8080",
"http",
"alex", "test", "8080",
NULL, NULL, NULL,
"test:8080", NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://@test:8080",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test",
"http",
NULL, "test", NULL,
NULL, NULL, NULL,
"test", NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://test:",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080",
"http",
NULL, "test", "8080",
NULL, NULL, NULL,
"test:8080", NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080/",
"http",
NULL, "test", "8080",
NULL, NULL, NULL,
"test:8080", NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080/live",
"http",
NULL, "test", "8080",
"live", NULL, NULL,
"test:8080", "live"));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK,
"http://alex@test/live/test",
"http",
"alex", "test", "8080",
"live/test", NULL, NULL,
"test", "live/test"));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR,
"http://alex@test:80/live/test?",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK,
"http://alex@test:80/live/test?a=b&c=d",
"http",
"alex", "test", "80",
"live/test", "a=b&c=d", NULL,
"test:80", "live/test?a=b&c=d"));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR,
"http://alex@/live/test?a=b&c=d",
NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL));
NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK,
"http://alex@test:8080/live/test?a=b&c=d#test",
"http",
"alex", "test", "8080",
"live/test", "a=b&c=d", "test",
"test:8080", "live/test?a=b&c=d#test"));
NGX_TEST_ISOK(ngx_request_port_test(0, "", "abcd"));
NGX_TEST_ISOK(ngx_request_port_test(1234, "", "1234"));
NGX_TEST_ISOK(ngx_request_port_test(0, "", "102222"));
NGX_TEST_ISOK(ngx_request_port_test(0, "rtp", ""));
NGX_TEST_ISOK(ngx_request_port_test(80, "http", ""));
NGX_TEST_ISOK(ngx_request_port_test(443, "https", ""));
NGX_TEST_ISOK(ngx_request_port_test(1935, "rtmp", ""));
file.data = (u_char *) "/usr/local/nginx/conf/md5testfile";
file.len = sizeof("/usr/local/nginx/conf/md5testfile") - 1;
fd = ngx_open_file(file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
ngx_open_file_n " %s failed", file.data);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (ngx_md5_file(fd, md5key)) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"md5 file %V failed", &file);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
NGX_TEST_ISOK(ngx_memcmp(md5key, "d4309a79dbeaeb6d7811734ce483db59", 32)
== 0);
ngx_close_file(fd);
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
len = sizeof("TEST cases 4294967296, 4294967296 pass\n") - 1;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
b->last = ngx_snprintf(b->last, len, "TEST cases %d, %d pass\n",
count, pass);
b->last_buf = 1;
b->last_in_chain = 1;
cl.buf = b;
cl.next = NULL;
return ngx_http_output_filter(r, &cl);
}
static char *
ngx_toolkit_misc_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_toolkit_misc_test_handler;
return NGX_CONF_OK;
}
@@ -1,14 +0,0 @@
$TTL 3H
@ IN SOA @ wj19840501.gmail.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ; minimum
)
@ IN NS dns
dns IN A 192.168.84.254
www IN A 1.1.1.1
www IN A 1.1.1.2
www IN A 1.1.1.3
@@ -1,14 +0,0 @@
$TTL 3H
@ IN SOA @ wj19840501.gmail.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ; minimum
)
@ IN NS dns
dns IN A 192.168.84.254
www IN A 1.1.1.4
www IN A 1.1.1.5
www IN A 1.1.1.6