mirror of
https://github.com/lionsoul2014/ip2region.git
synced 2026-02-01 17:46:15 +00:00
commit
208a3baab6
4
binding/ngx-ip2region/README.md
Normal file
4
binding/ngx-ip2region/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
#说明
|
||||
|
||||
- 本模块依赖[ip2region](https://github.com/lionsoul2014/ip2region/tree/master/binding/c)项目,需要手动下载ip2region.c 和 ip2region.h文件后进行编译
|
||||
|
||||
44
binding/ngx-ip2region/config
Normal file
44
binding/ngx-ip2region/config
Normal file
@ -0,0 +1,44 @@
|
||||
ngx_addon_name="ngx_ip2region_module"
|
||||
|
||||
IP2REGION_CORE_MODULES=" \
|
||||
ngx_ip2region_module \
|
||||
"
|
||||
|
||||
IP2REGION_DEPS=" \
|
||||
$ngx_addon_dir/ip2region.h \
|
||||
$ngx_addon_dir/ngx_ip2region.h \
|
||||
"
|
||||
|
||||
IP2REGION_CORE_SRCS=" \
|
||||
$ngx_addon_dir/ip2region.c \
|
||||
$ngx_addon_dir/ngx_ip2region_module.c \
|
||||
"
|
||||
|
||||
|
||||
|
||||
if [ -f auto/module ] ; then
|
||||
ngx_module_incs=$ngx_addon_dir
|
||||
ngx_module_deps=$IP2REGION_DEPS
|
||||
|
||||
if [ $ngx_module_link = DYNAMIC ] ; then
|
||||
ngx_module_name="$IP2REGION_CORE_MODULES"
|
||||
ngx_module_srcs="$IP2REGION_CORE_SRCS"
|
||||
|
||||
. auto/module
|
||||
|
||||
else
|
||||
ngx_module_type=CORE
|
||||
ngx_module_name=$IP2REGION_CORE_MODULES
|
||||
ngx_module_srcs=$IP2REGION_CORE_SRCS
|
||||
|
||||
. auto/module
|
||||
fi
|
||||
|
||||
else
|
||||
CORE_MODULES="$CORE_MODULES $IP2REGION_CORE_MODULES"
|
||||
|
||||
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $IP2REGION_DEPS"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $IP2REGION_CORE_SRCS"
|
||||
|
||||
CFLAGS="$CFLAGS -I$ngx_addon_dir "
|
||||
fi
|
||||
23
binding/ngx-ip2region/ngx_ip2region.h
Normal file
23
binding/ngx-ip2region/ngx_ip2region.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __NGX_IP2REGION_H__
|
||||
#define __NGX_IP2REGION_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../binding/c/ip2region.h"
|
||||
|
||||
typedef struct ngx_ip2region_conf_s {
|
||||
ngx_str_t db_file;
|
||||
ngx_uint_t algo;
|
||||
} ngx_ip2region_conf_t;
|
||||
|
||||
typedef uint_t (*search_func_ptr)(ip2region_t, uint_t, datablock_t);
|
||||
|
||||
extern ngx_int_t ngx_ip2region_search(ngx_str_t *addr_text, ngx_str_t *isp, ngx_str_t *city);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
260
binding/ngx-ip2region/ngx_ip2region_module.c
Normal file
260
binding/ngx-ip2region/ngx_ip2region_module.c
Normal file
@ -0,0 +1,260 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#include "ngx_ip2region.h"
|
||||
|
||||
|
||||
static void *ngx_ip2region_create_conf(ngx_cycle_t *cycle);
|
||||
static char *ngx_ip2region_init_conf(ngx_cycle_t *cycle, void *conf);
|
||||
|
||||
static ngx_int_t ngx_ip2region_init_process(ngx_cycle_t *cycle);
|
||||
static void ngx_ip2region_exit_process(ngx_cycle_t *cycle);
|
||||
|
||||
static ip2region_entry g_ip2region_entry;
|
||||
|
||||
|
||||
search_func_ptr ip2region_search_func;
|
||||
|
||||
|
||||
#define NGX_IP2REGION_MEMORY 0
|
||||
#define NGX_IP2REGION_BINARY 1
|
||||
#define NGX_IP2REGION_BTREE 2
|
||||
|
||||
static ngx_conf_enum_t ngx_ip2region_search_algo[] = {
|
||||
{ ngx_string("memory"), NGX_IP2REGION_MEMORY },
|
||||
{ ngx_string("binary"), NGX_IP2REGION_BINARY },
|
||||
{ ngx_string("btree"), NGX_IP2REGION_BTREE},
|
||||
{ ngx_null_string, 0 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_command_t ngx_ip2region_commands[] = {
|
||||
|
||||
{
|
||||
ngx_string("ip2region_db_file"),
|
||||
NGX_MAIN_CONF | NGX_DIRECT_CONF | NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
0,
|
||||
offsetof(ngx_ip2region_conf_t, db_file),
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
ngx_string("ip2region_algo"),
|
||||
NGX_MAIN_CONF | NGX_DIRECT_CONF | NGX_CONF_TAKE1,
|
||||
ngx_conf_set_enum_slot,
|
||||
0,
|
||||
offsetof(ngx_ip2region_conf_t, algo),
|
||||
&ngx_ip2region_search_algo
|
||||
},
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_core_module_t ngx_ip2region_module_ctx = {
|
||||
ngx_string("ip2region"),
|
||||
ngx_ip2region_create_conf,
|
||||
ngx_ip2region_init_conf,
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_ip2region_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_ip2region_module_ctx, /* module context */
|
||||
ngx_ip2region_commands, /* module directives */
|
||||
NGX_CORE_MODULE, /* module type */
|
||||
NULL, /* init master */
|
||||
NULL, /* init module */
|
||||
ngx_ip2region_init_process, /* init process */
|
||||
NULL, /* init thread */
|
||||
NULL, /* exit thread */
|
||||
ngx_ip2region_exit_process, /* exit process */
|
||||
NULL, /* exit master */
|
||||
NGX_MODULE_V1_PADDING
|
||||
};
|
||||
|
||||
static void *
|
||||
ngx_ip2region_create_conf(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_ip2region_conf_t *ip2region_conf;
|
||||
ip2region_conf = ngx_pcalloc(cycle->pool, sizeof(ngx_ip2region_conf_t));
|
||||
|
||||
if(ip2region_conf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ip2region_conf->algo = NGX_CONF_UNSET_UINT;
|
||||
return ip2region_conf;
|
||||
}
|
||||
|
||||
static char *
|
||||
ngx_ip2region_init_conf(ngx_cycle_t *cycle, void *conf)
|
||||
{
|
||||
ngx_ip2region_conf_t *ip2region_conf = (ngx_ip2region_conf_t *)conf;
|
||||
|
||||
if(ip2region_conf->db_file.len == 0) {
|
||||
//ngx_str_set(&ip2region_conf->db_file, "conf/ip2region.db");
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
if(ngx_conf_full_name(cycle, &ip2region_conf->db_file, 0) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_INFO, ngx_cycle->log, 0, "%V", &ip2region_conf->db_file);
|
||||
|
||||
if(ip2region_conf->algo == NGX_CONF_UNSET_UINT) {
|
||||
ip2region_conf->algo = NGX_IP2REGION_MEMORY;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t
|
||||
ngx_ip2region_init_process(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_ip2region_conf_t *conf = (ngx_ip2region_conf_t *)ngx_get_conf(ngx_cycle->conf_ctx, ngx_ip2region_module);
|
||||
|
||||
if(conf->db_file.len == 0) {
|
||||
ngx_log_debug0(NGX_LOG_INFO, ngx_cycle->log, 0, "ip2region not init");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if(!ip2region_create(&g_ip2region_entry, (char *)conf->db_file.data)) {
|
||||
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "ip2region create failed: %V", &conf->db_file);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
switch(conf->algo) {
|
||||
default:
|
||||
case NGX_IP2REGION_MEMORY:
|
||||
ip2region_search_func = ip2region_memory_search;
|
||||
break;
|
||||
|
||||
case NGX_IP2REGION_BINARY:
|
||||
ip2region_search_func = ip2region_binary_search;
|
||||
break;
|
||||
|
||||
case NGX_IP2REGION_BTREE:
|
||||
ip2region_search_func = ip2region_btree_search;
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "ip2region create succcess: algo=%ui", conf->algo);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ngx_ip2region_exit_process(ngx_cycle_t *cycle)
|
||||
{
|
||||
ip2region_destroy(&g_ip2region_entry);
|
||||
ngx_log_debug0(NGX_LOG_INFO, ngx_cycle->log, 0, "ip2region destroy");
|
||||
}
|
||||
|
||||
static ngx_inline u_char *
|
||||
ngx_strrchr(u_char *first, u_char *p, u_char c)
|
||||
{
|
||||
while(p >= first) {
|
||||
if(*p == c) {
|
||||
return p;
|
||||
}
|
||||
|
||||
p--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ngx_inline uint32_t
|
||||
ngx_inet_aton(u_char *data, ngx_uint_t len)
|
||||
{
|
||||
long long result = 0;
|
||||
long long temp = 0;
|
||||
u_char *last = data + len;
|
||||
int point = 0;
|
||||
|
||||
while(data <= last) {
|
||||
if(*data == '.' || data == last) {
|
||||
if(temp > 255) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
result = (result << 8) + temp;
|
||||
temp = 0;
|
||||
++point;
|
||||
|
||||
if(point == 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
} else if(*data <= '9' && *data >= '0') {
|
||||
temp = temp * 10 + (*data - '0');
|
||||
|
||||
} else {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
++data;
|
||||
}
|
||||
|
||||
if(point != 4) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ngx_int_t
|
||||
ngx_ip2region_search(ngx_str_t *addr_text, ngx_str_t *isp, ngx_str_t *city)
|
||||
{
|
||||
if(g_ip2region_entry.dbHandler == NULL) {
|
||||
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "search error ip %V, ip2region doesn't create", addr_text);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
uint32_t addr_binary = ngx_inet_aton(addr_text->data, addr_text->len);
|
||||
|
||||
if(addr_binary == (uint32_t)NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "search error ip %V: bad ip address", addr_text);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
datablock_entry datablock;
|
||||
ngx_memzero(&datablock, sizeof(datablock));
|
||||
uint_t rc = ip2region_search_func(&g_ip2region_entry, (uint_t)addr_binary, &datablock);
|
||||
|
||||
if(!rc) {
|
||||
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "%V search failed", addr_text);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_INFO, ngx_cycle->log, 0, "%V: %s", addr_text, datablock.region);
|
||||
//城市Id 国家|区域|省份|城市|ISP
|
||||
u_char *end = (u_char *)(datablock.region + ngx_strlen(datablock.region));
|
||||
u_char *pos = ngx_strrchr((u_char *)datablock.region, end, '|');
|
||||
|
||||
if(!pos) {
|
||||
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "search isp failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
u_char isp_buffer[64] = {0};
|
||||
ngx_snprintf(isp_buffer, sizeof(isp_buffer), "%*s%Z", end - pos, pos + 1);
|
||||
ngx_log_debug3(NGX_LOG_INFO, ngx_cycle->log, 0, "%V: %s [%s]", addr_text, datablock.region, (char *)isp_buffer);
|
||||
|
||||
if(city) {
|
||||
end = pos - 1;
|
||||
u_char *pos_city = ngx_strrchr((u_char *)datablock.region, end, '|');
|
||||
|
||||
if(!pos_city) {
|
||||
ngx_log_debug0(NGX_LOG_ERR, ngx_cycle->log, 0, "search city failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
u_char city_buffer[64] = {0};
|
||||
ngx_snprintf(city_buffer, sizeof(city_buffer), "%*s%Z", end - pos_city, pos_city + 1);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user