mirror of
https://github.com/lionsoul2014/ip2region.git
synced 2025-12-08 19:25:22 +00:00
Ipv6 search is ready
This commit is contained in:
parent
b01253e6b3
commit
2fe0d1f59e
@ -62,10 +62,29 @@ if string.len(dbFile) < 2 or string.len(srcFile) < 2 then
|
||||
return
|
||||
end
|
||||
|
||||
-- verify the xdb from header
|
||||
if xdb.verify(dbFile) == false then
|
||||
print(string.format("failed to verify the xdb file: %s", dbFile))
|
||||
return
|
||||
end
|
||||
|
||||
-- detect the version from the xdb header
|
||||
header, err = xdb.load_header(dbFile)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to load header: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
version, err = xdb.version_from_header(header);
|
||||
if err ~= nil then
|
||||
print(string.format("failed to detect version from header: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
-- create the searcher based on the cache-policy
|
||||
local searcher, v_index, content
|
||||
if cachePolicy == "file" then
|
||||
searcher, err = xdb.new_with_file_only(dbFile)
|
||||
searcher, err = xdb.new_with_file_only(version, dbFile)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to create searcher: %s", err))
|
||||
return
|
||||
@ -77,7 +96,7 @@ elseif cachePolicy == "vectorIndex" then
|
||||
return
|
||||
end
|
||||
|
||||
searcher, err = xdb.new_with_vector_index(dbFile, v_index)
|
||||
searcher, err = xdb.new_with_vector_index(version, dbFile, v_index)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to create vector index searcher: %s", err))
|
||||
return
|
||||
@ -89,7 +108,7 @@ elseif cachePolicy == "content" then
|
||||
return
|
||||
end
|
||||
|
||||
searcher, err = xdb.new_with_buffer(content)
|
||||
searcher, err = xdb.new_with_buffer(version, content)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to create content buffer searcher: %s", err))
|
||||
return
|
||||
@ -116,7 +135,7 @@ for l in lines do
|
||||
goto continue
|
||||
end
|
||||
|
||||
for v1, v2, v3 in string.gmatch(l, "([%d%.]+)|([%d%.]+)|([^\n]+)") do
|
||||
for v1, v2, v3 in string.gmatch(l, "([^|]+)|([^|]+)|([^\n]+)") do
|
||||
-- print(sip_str, eip_str, region)
|
||||
sip_str = v1
|
||||
eip_str = v2
|
||||
@ -124,36 +143,35 @@ for l in lines do
|
||||
break
|
||||
end
|
||||
|
||||
sip, err = xdb.check_ip(sip_str)
|
||||
sip_bytes, err = xdb.parse_ip(sip_str)
|
||||
if err ~= nil then
|
||||
print(string.format("invalid start ip `%s`", sip_str))
|
||||
return
|
||||
end
|
||||
|
||||
eip, err = xdb.check_ip(eip_str)
|
||||
eip_bytes, err = xdb.parse_ip(eip_str)
|
||||
if err ~= nil then
|
||||
print(string.format("invalid end ip `%s`", sip_str))
|
||||
return
|
||||
end
|
||||
|
||||
if sip > eip then
|
||||
if xdb.ip_compare(sip_bytes, eip_bytes) > 0 then
|
||||
print(string.format("start ip(%s) should not be greater than end ip(%s)\n", sip_str, eip_str))
|
||||
return
|
||||
end
|
||||
|
||||
mip = (sip + eip) >> 1
|
||||
for _, ip in ipairs({sip, (sip + mip) >> 1, mip, (mip + eip) >> 1, eip}) do
|
||||
for _, ip_bytes in ipairs({sip_bytes, eip_bytes}) do
|
||||
t_time = xdb.now()
|
||||
region, err = searcher:search(ip)
|
||||
region, err = searcher:search(ip_bytes)
|
||||
c_time = c_time + xdb.now() - t_time
|
||||
if err ~= nil then
|
||||
print(string.format("failed to search ip `%s`", xdb.long2ip(ip)))
|
||||
print(string.format("failed to search ip `%s`", xdb.ip_to_string(ip_bytes)))
|
||||
return
|
||||
end
|
||||
|
||||
-- check the region
|
||||
if region ~= s_region then
|
||||
printf(string.format("failed search(%s) with (%s != %s)\n", xdb.long2ip(ip), region, s_region))
|
||||
printf(string.format("failed search(%s) with (%s != %s)\n", xdb.ip_to_string(ip_bytes), region, s_region))
|
||||
return
|
||||
end
|
||||
|
||||
@ -172,6 +190,8 @@ if content ~= nil then
|
||||
content:close()
|
||||
end
|
||||
|
||||
xdb.cleanup();
|
||||
|
||||
-- print the stats
|
||||
local avg_costs = 0
|
||||
if count > 0 then
|
||||
|
||||
@ -59,7 +59,24 @@ if string.len(dbFile) < 2 then
|
||||
return
|
||||
end
|
||||
|
||||
local version = xdb.IPv4
|
||||
-- verify the xdb from header
|
||||
if xdb.verify(dbFile) == false then
|
||||
print(string.format("failed to verify the xdb file: %s", dbFile))
|
||||
return
|
||||
end
|
||||
|
||||
-- detect the version from the xdb header
|
||||
header, err = xdb.load_header(dbFile)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to load header: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
version, err = xdb.version_from_header(header);
|
||||
if err ~= nil then
|
||||
print(string.format("failed to detect version from header: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
-- create the searcher based on the cache-policy
|
||||
local searcher, v_index, content
|
||||
@ -100,8 +117,9 @@ end
|
||||
|
||||
-- do the search
|
||||
print(string.format([[
|
||||
ip2region xdb searcher test program, cachePolicy: %s
|
||||
type 'quit' to exit]], cachePolicy))
|
||||
ip2region xdb searcher test program
|
||||
source xdb: %s (%s, %s)
|
||||
type 'quit' to exit]], dbFile, "IPv4", cachePolicy))
|
||||
local region, err = "", nil
|
||||
local ip_int, s_time, c_time = 0, 0, 0
|
||||
while ( true ) do
|
||||
@ -143,4 +161,6 @@ if v_index ~= nil then
|
||||
end
|
||||
if content ~= nil then
|
||||
content:close()
|
||||
end
|
||||
end
|
||||
|
||||
xdb.cleanup();
|
||||
@ -24,7 +24,8 @@ function test_parse_ip()
|
||||
if err ~= nil then
|
||||
print(string.format("invalid ip address `%s`: %s", ip_src, err))
|
||||
else
|
||||
print(string.format("parse_ip(%s): %s", ip_src, xdb.ip_to_string(ip_bytes)))
|
||||
local ip_string = xdb.ip_to_string(ip_bytes);
|
||||
print(string.format("parse_ip(%s)->%s ? %s", ip_src, ip_string, ip_src==ip_string))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -116,4 +117,5 @@ local s_time = xdb.now();
|
||||
print(string.format("+---calling test function %s ...", func_name))
|
||||
_G[func_name]();
|
||||
local cost_time = xdb.now() - s_time
|
||||
xdb.cleanup();
|
||||
print(string.format("|---done, took: %.3fμs", cost_time))
|
||||
@ -257,16 +257,48 @@ static int lua_xdb_load_content_from_file(lua_State *L) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lua_xdb_version_from_header(lua_State *L) {
|
||||
xdb_version_t *version;
|
||||
xdb_buffer_t *buffer;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via '.' and xdb header expected");
|
||||
// header buffer checking
|
||||
buffer = luaL_checkudata(L, 1, XDB_BUFFER_METATABLE_NAME);
|
||||
if (buffer->type != xdb_header_buffer) {
|
||||
return luaL_error(L, "invalid xdb header buffer");
|
||||
}
|
||||
|
||||
version = xdb_version_from_header((xdb_header_t *) buffer->ptr);
|
||||
if (version == NULL) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "failed to detect version from header");
|
||||
} else {
|
||||
lua_pushlightuserdata(L, version);
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lua_xdb_verify_from_file(lua_State *L) {
|
||||
const char *db_path;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via '.' and the xdb file path expected");
|
||||
db_path = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, xdb_verify_from_file(db_path) == 0 ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_xdb_parse_ip(lua_State *L) {
|
||||
int err;
|
||||
const char *ip_str;
|
||||
bytes_ip_t ip_bytes[18] = {'\0'};
|
||||
bytes_ip_t ip_bytes[19] = {'\0'};
|
||||
xdb_version_t *version;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via '.' and string ip expected, eg: 1.2.3.4 / 3000::");
|
||||
ip_str = luaL_checkstring(L, 1);
|
||||
|
||||
version = xdb_parse_ip(ip_str, ip_bytes, sizeof(ip_bytes));
|
||||
version = xdb_parse_ip(ip_str, ip_bytes + 2, sizeof(ip_bytes) - 2);
|
||||
if (version == NULL) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "failed to parse the `%s`", ip_str);
|
||||
@ -275,32 +307,46 @@ static int lua_xdb_parse_ip(lua_State *L) {
|
||||
|
||||
// append the magic char for later analysis
|
||||
// printf("ip:%s, version->id: %d\n", ip_str, version->id);
|
||||
ip_bytes[version->bytes] = '&';
|
||||
ip_bytes[version->bytes+1] = '\0';
|
||||
lua_pushstring(L, ip_bytes);
|
||||
ip_bytes[0] = '&';
|
||||
ip_bytes[1] = (bytes_ip_t) version->id;
|
||||
lua_pushlstring(L, ip_bytes, version->bytes + 2);
|
||||
lua_pushnil(L);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lua_xdb_ip_to_string(lua_State *L) {
|
||||
int err, len;
|
||||
int err, vid, bytes;
|
||||
const bytes_ip_t *ip_bytes;
|
||||
char ip_string[INET6_ADDRSTRLEN] = {'\0'};
|
||||
char ip_string[INET6_ADDRSTRLEN + 1] = {'\0'};
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via '.' and bytes ip expected");
|
||||
ip_bytes = luaL_checkstring(L, 1);
|
||||
len = strlen(ip_bytes);
|
||||
if (len == 5 && ip_bytes[4] == '&') {
|
||||
// binary IPv4 bytes
|
||||
} else if (len == 17 || ip_bytes[16] == '&') { // IPv6
|
||||
// binary IPv6 bytes
|
||||
if (strlen(ip_bytes) < 2) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "invalid binary ip bytes specified");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ip_bytes[0] != '&') {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "invalid binary ip bytes specified");
|
||||
return 2;
|
||||
}
|
||||
|
||||
vid = ip_bytes[1] & 0xFF;
|
||||
if (vid == xdb_ipv4_id) {
|
||||
// IPv4
|
||||
bytes = xdb_ipv4_bytes;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
// IPv6
|
||||
bytes = xdb_ipv6_bytes;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "invalid binary ip bytes specified");
|
||||
return 2;
|
||||
}
|
||||
|
||||
err = xdb_ip_to_string(ip_bytes, len-1, ip_string, sizeof(ip_string));
|
||||
err = xdb_ip_to_string(ip_bytes + 2, bytes, ip_string, sizeof(ip_string));
|
||||
if (err != 0) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "failed to conver the ip bytes to string");
|
||||
@ -312,6 +358,59 @@ static int lua_xdb_ip_to_string(lua_State *L) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int _validate_bytes_ip(const bytes_ip_t *ip_bytes) {
|
||||
if (strlen(ip_bytes) < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ip_bytes[0] != '&') {
|
||||
return 2;
|
||||
}
|
||||
|
||||
int vid = ip_bytes[1] & 0xFF;
|
||||
if (vid != xdb_ipv4_id && vid != xdb_ipv6_id) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_xdb_ip_compare(lua_State *L) {
|
||||
int err, vid, bytes;
|
||||
const bytes_ip_t *ip1_bytes, *ip2_bytes;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 2, 1, "call via '.' bytes ip1 and ip2 expected");
|
||||
ip1_bytes = luaL_checkstring(L, 1);
|
||||
ip2_bytes = luaL_checkstring(L, 2);
|
||||
|
||||
// validate the ip1
|
||||
err = _validate_bytes_ip(ip1_bytes);
|
||||
if (err != 0) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "failed to validate ip1 with errcode=%d", err);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// validate the ip2
|
||||
err = _validate_bytes_ip(ip2_bytes);
|
||||
if (err != 0) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "failed to validate ip2 with errcode=%d", err);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ip1_bytes[1] != ip2_bytes[1]) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "ip version of ip1 and ip2 are not the same");
|
||||
return 2;
|
||||
}
|
||||
|
||||
err = xdb_ip_sub_compare(ip1_bytes + 2, (ip1_bytes[1] & 0xFF), ip2_bytes, 2);
|
||||
lua_pushinteger(L, err);
|
||||
lua_pushnil(L);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lua_xdb_now(lua_State *L) {
|
||||
lua_pushinteger(L, xdb_now());
|
||||
return 1;
|
||||
@ -332,13 +431,10 @@ static int lua_xdb_new_with_file_only(lua_State *L) {
|
||||
luaL_argcheck(L, lua_gettop(L) == 2, 1, "call via '.' and ip version / xdb file path expected");
|
||||
|
||||
// check the ip version
|
||||
vid = luaL_checkinteger(L, 1);
|
||||
if (vid == xdb_ipv4_id) {
|
||||
version = XDB_IPv4;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
version = XDB_IPv6;
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
return luaL_error(L, "invalid verison id (`%d`) specified", vid);
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
}
|
||||
|
||||
// check the db path
|
||||
@ -372,18 +468,15 @@ static int lua_xdb_new_with_vector_index(lua_State *L) {
|
||||
xdb_searcher_t *searcher;
|
||||
xdb_buffer_t *xBuffer;
|
||||
const char *db_path;
|
||||
int err, vid;
|
||||
int err;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 3, 1, "call via '.', ip version / xdb file path / vector index buffer expected");
|
||||
|
||||
// ip version checking
|
||||
vid = luaL_checkinteger(L, 1);
|
||||
if (vid == xdb_ipv4_id) {
|
||||
version = XDB_IPv4;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
version = XDB_IPv6;
|
||||
// check the ip version
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
return luaL_error(L, "invalid verison id (`%d`) specified", vid);
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
}
|
||||
|
||||
// db_path checking
|
||||
@ -422,18 +515,15 @@ static int lua_xdb_new_with_buffer(lua_State *L) {
|
||||
xdb_version_t *version;
|
||||
xdb_searcher_t *searcher;
|
||||
xdb_buffer_t *xBuffer;
|
||||
int err, vid;
|
||||
int err;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 2, 1, "call via '.' and ip version / xdb content buffer expected");
|
||||
|
||||
// ip version checking
|
||||
vid = luaL_checkinteger(L, 1);
|
||||
if (vid == xdb_ipv4_id) {
|
||||
version = XDB_IPv4;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
version = XDB_IPv6;
|
||||
// check the ip version
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
return luaL_error(L, "invalid verison id (`%d`) specified", vid);
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
}
|
||||
|
||||
// content buffer checking
|
||||
@ -479,7 +569,7 @@ static int lua_xdb_close(lua_State *L) {
|
||||
}
|
||||
|
||||
static int lua_xdb_search(lua_State *L) {
|
||||
int err, len, ip_len;
|
||||
int err, vid, ip_len;
|
||||
const char *ip_string;
|
||||
bytes_ip_t ip_buffer[INET6_ADDRSTRLEN] = {'\0'};
|
||||
const bytes_ip_t *ip_bytes;
|
||||
@ -495,16 +585,26 @@ static int lua_xdb_search(lua_State *L) {
|
||||
ip_string = luaL_checkstring(L, 2);
|
||||
|
||||
// ip string type checking
|
||||
len = strlen(ip_string);
|
||||
if (len == 5 && ip_string[4] == '&') {
|
||||
// binary IPv4
|
||||
ip_len = 4;
|
||||
ip_bytes = ip_string;
|
||||
} else if (len == 17 && ip_string[16] == '&') {
|
||||
// binary IPv6
|
||||
ip_len = 16;
|
||||
ip_bytes = ip_string;
|
||||
printf("ipv6 binary string\n");
|
||||
if (strlen(ip_string) < 2) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "invalid ip address `%s`", ip_string);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (ip_string[0] == '&') {
|
||||
vid = ip_string[1] & 0xFF;
|
||||
if (vid == xdb_ipv4_id) {
|
||||
ip_len = xdb_ipv4_bytes;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
ip_len = xdb_ipv6_bytes;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "invalid binary ip bytes specified");
|
||||
return 2;
|
||||
}
|
||||
|
||||
ip_bytes = ip_string + 2;
|
||||
// printf("ip_len: %d, vid: %d\n", ip_len, vid);
|
||||
} else {
|
||||
version = xdb_parse_ip(ip_string, ip_buffer, sizeof(ip_buffer));
|
||||
if (version == NULL) {
|
||||
@ -552,6 +652,12 @@ static int lua_xdb_tostring(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// cleanup the current module
|
||||
static int lua_xdb_cleanup(lua_State *L) {
|
||||
xdb_clean_winsock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// module method define, should be access via ':'
|
||||
static const struct luaL_Reg xdb_searcher_methods[] = {
|
||||
{"search", lua_xdb_search},
|
||||
@ -570,15 +676,26 @@ static const struct luaL_Reg xdb_searcher_functions[] = {
|
||||
{"load_header", lua_xdb_load_header_from_file},
|
||||
{"load_vector_index", lua_xdb_load_vector_index_from_file},
|
||||
{"load_content", lua_xdb_load_content_from_file},
|
||||
{"verify", lua_xdb_verify_from_file},
|
||||
{"version_from_header", lua_xdb_version_from_header},
|
||||
{"parse_ip", lua_xdb_parse_ip},
|
||||
{"ip_to_string", lua_xdb_ip_to_string},
|
||||
{"ip_compare", lua_xdb_ip_compare},
|
||||
{"now", lua_xdb_now},
|
||||
{"close", lua_xdb_close},
|
||||
{"cleanup", lua_xdb_cleanup},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
// module register function
|
||||
int luaopen_xdb_searcher(lua_State *L)
|
||||
{
|
||||
int err = xdb_init_winsock();
|
||||
if (err != 0) {
|
||||
luaL_error(L, "failed to init the winsock with errno=%d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create a metatable for xdb buffer object
|
||||
luaL_newmetatable(L, XDB_BUFFER_METATABLE_NAME);
|
||||
lua_pushvalue(L, -1);
|
||||
@ -593,9 +710,9 @@ int luaopen_xdb_searcher(lua_State *L)
|
||||
luaL_setfuncs(L, xdb_searcher_functions, 0);
|
||||
|
||||
// register the constants attributes
|
||||
lua_pushinteger(L, xdb_ipv4_id);
|
||||
lua_pushlightuserdata(L, XDB_IPv4);
|
||||
lua_setfield(L, -2, "IPv4");
|
||||
lua_pushinteger(L, xdb_ipv6_id);
|
||||
lua_pushlightuserdata(L, XDB_IPv6);
|
||||
lua_setfield(L, -2, "IPv6");
|
||||
lua_pushinteger(L, xdb_header_buffer);
|
||||
lua_setfield(L, -2, "header_buffer");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user