lua c ext is ready for IPv6
This commit is contained in:
parent
13324d1575
commit
29fa8e25ab
|
|
@ -14,30 +14,73 @@ sudo make install
|
|||
|
||||
# 使用方式
|
||||
|
||||
### 关于 IPv4 和 IPv6
|
||||
该 xdb 查询客户端实现同时支持对 IPv4 和 IPv6 的查询,使用方式如下:
|
||||
```lua
|
||||
-- 引入 xdb searcher 扩展
|
||||
local xdb = require("xdb_searcher")
|
||||
|
||||
-- 如果是 IPv4: 设置 xdb 路径为 v4 的 xdb 文件,IP版本指定为 IPv4
|
||||
local db_path = "../../data/ip2region_v4.xdb" -- 或者你的 ipv4 xdb 的路径
|
||||
local version = xdb.IPv4
|
||||
|
||||
-- 如果是 IPv6: 设置 xdb 路径为 v6 的 xdb 文件,IP版本指定为 IPv6
|
||||
local db_path = "../../data/ip2region_v6.xdb"; -- 或者你的 ipv6 xdb 路径
|
||||
local version = xdb.IPv6
|
||||
|
||||
-- db_path 指定的 xdb 的 IP 版本必须和 version 指定的一致,不然查询执行的时候会报错
|
||||
-- 备注:以下演示直接使用 db_path 和 version 变量
|
||||
```
|
||||
|
||||
### XDB 文件验证
|
||||
建议您主动去验证 xdb 文件的适用性,因为后期的一些新功能可能会导致目前的 Searcher 版本无法适用你使用的 xdb 文件,验证可以避免运行过程中的一些不可预测的错误。 你不需要每次都去验证,例如在服务启动的时候,或者手动调用命令验证确认版本匹配即可,不要在每次创建的 Searcher 的时候运行验证,这样会影响查询的响应速度,尤其是高并发的使用场景。
|
||||
```lua
|
||||
local xdb = require("xdb_searcher")
|
||||
|
||||
-- verify the xdb
|
||||
if xdb.verify(db_path) == false then
|
||||
-- 适用性验证失败!!!
|
||||
-- 当前查询客户端实现不适用于 db_path 指定的 xdb 文件的查询.
|
||||
-- 应该停止启动服务,使用合适的 xdb 文件或者升级到适合 db_path 的 Searcher 实现。
|
||||
print(string.format("failed to verify the xdb file: %s", db_path))
|
||||
return
|
||||
end
|
||||
|
||||
-- 验证通过,当前使用的 Searcher 可以安全的用于对 db_path 指向的 xdb 的查询操作
|
||||
```
|
||||
|
||||
### 完全基于文件的查询
|
||||
```lua
|
||||
local xdb = require("xdb_searcher")
|
||||
|
||||
-- 1、从 db_path 创建基于文件的 xdb 查询对象
|
||||
local db_path = "ip2region.xdb file path"
|
||||
local searcher, err = xdb.new_with_file_only(db_path)
|
||||
-- 1、使用 version 从 db_path 创建基于文件的 xdb 查询对象
|
||||
local searcher, err = xdb.new_with_file_only(version, db_path)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to create searcher: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
-- 2、调用查询 API 进行查询
|
||||
-- 2、调用查询 API 进行查询,IPv4 和 IPv6 都支持
|
||||
local ip_str = "1.2.3.4"
|
||||
-- ip_str = "2001:4:112:ffff:ffff:ffff:ffff:ffff" // IPv6
|
||||
local s_time = xdb.now()
|
||||
region, err = searcher:search(ip_str)
|
||||
local c_time = xdb.now() - s_time
|
||||
if err ~= nil then
|
||||
print(string.format("failed to search(%s): %s", ip_str, err))
|
||||
return
|
||||
end
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, c_time))
|
||||
|
||||
-- 备注:并发使用,每个协程需要创建单独的 xdb 查询对象
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
||||
-- 3,关闭 xdb 查询器
|
||||
searcher:close()
|
||||
|
||||
--
|
||||
-- 4,模块资源清理,仅在需要将整个服务完全关闭前调用
|
||||
xdb.cleanup()
|
||||
```
|
||||
|
||||
### 缓存 `VectorIndex` 索引
|
||||
|
|
@ -46,8 +89,6 @@ print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
|||
```lua
|
||||
local xdb = require("xdb_searcher")
|
||||
|
||||
local db_path = "ip2region.xdb file path"
|
||||
|
||||
-- 1、从指定的 db_path 加载 VectorIndex 缓存,把下述的 v_index 对象做成全局变量。
|
||||
-- vectorIndex 加载一次即可,建议在服务启动的时候加载为全局对象。
|
||||
v_index, err = xdb.load_vector_index(db_path)
|
||||
|
|
@ -57,24 +98,33 @@ if err ~= nil then
|
|||
end
|
||||
|
||||
-- 2、使用全局的 v_index 创建带 VectorIndex 缓存的查询对象。
|
||||
searcher, err = xdb.new_with_vector_index(db_path, v_index)
|
||||
searcher, err = xdb.new_with_vector_index(version, db_path, v_index)
|
||||
if err ~= nil then
|
||||
print(string.format("failed to create vector index searcher: %s", err))
|
||||
return
|
||||
end
|
||||
|
||||
-- 3、调用查询 API
|
||||
-- 3、调用查询 API ,IPv4 和 IPv6 都支持
|
||||
local ip_str = "1.2.3.4"
|
||||
-- ip_str = "2001:4:112:ffff:ffff:ffff:ffff:ffff" // IPv6
|
||||
local s_time = xdb.now()
|
||||
region, err = searcher:search(ip_str)
|
||||
local c_time = xdb.now() = s_time
|
||||
if err ~= nil then
|
||||
print(string.format("failed to search(%s): %s", ip_str, err))
|
||||
return
|
||||
end
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, c_time))
|
||||
|
||||
-- 备注:并发使用,每个协程需要创建单独的 xdb 查询对象,但是共享全局的 v_index 对象
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
||||
-- 4,关闭 xdb 查询器
|
||||
searcher:close()
|
||||
|
||||
--
|
||||
-- 5,模块资源清理,仅在需要将整个服务完全关闭前调用
|
||||
xdb.cleanup()
|
||||
```
|
||||
|
||||
### 缓存整个 `xdb` 数据
|
||||
|
|
@ -83,36 +133,43 @@ print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
|||
```lua
|
||||
local xdb = require("xdb_searcher")
|
||||
|
||||
local db_path = "ip2region.xdb file path"
|
||||
|
||||
-- 1、从指定的 db_path 加载整个 xdb 到内存。
|
||||
-- xdb内容加载一次即可,建议在服务启动的时候加载为全局对象。
|
||||
content = xdb.load_content(db_path)
|
||||
local content = xdb.load_content(db_path)
|
||||
if content == nil then
|
||||
print(string.format("failed to load xdb content from '%s'", db_path))
|
||||
return
|
||||
end
|
||||
|
||||
-- 2、使用全局的 content 创建带完全基于内存的查询对象。
|
||||
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
|
||||
end
|
||||
|
||||
-- 3、调用查询 API
|
||||
-- 3、调用查询 API ,IPv4 和 IPv6 都支持
|
||||
local ip_str = "1.2.3.4"
|
||||
-- ip_str = "2001:4:112:ffff:ffff:ffff:ffff:ffff" // IPv6
|
||||
local s_time = xdb.now()
|
||||
region, err = searcher:search(ip_str)
|
||||
local c_time = xdb.now() - s_time
|
||||
if err ~= nil then
|
||||
print(string.format("failed to search(%s): %s", ip_str, err))
|
||||
return
|
||||
end
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, c_time))
|
||||
|
||||
-- 备注:并发使用,用 xdb 整个缓存创建的查询对象可以安全的用于并发。
|
||||
-- 建议在服务启动的时候创建好全局的 searcher 对象,然后全局并发使用。
|
||||
|
||||
print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
||||
-- 4,关闭 xdb 查询器
|
||||
searcher:close()
|
||||
|
||||
--
|
||||
-- 5,模块资源清理,仅在需要将整个服务完全关闭前调用
|
||||
xdb.cleanup()
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -120,21 +177,31 @@ print(string.format("{region: %s, took: %.5f μs}", region, xdb.now() - s_time))
|
|||
|
||||
通过 `search_test.lua` 脚本来进行查询测试:
|
||||
```bash
|
||||
➜ lua_c git:(lua_binding) ✗ lua ./search_test.lua
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./search_test.lua
|
||||
lua search_test.lua [command options]
|
||||
options:
|
||||
--db string ip2region binary xdb file path
|
||||
--cache-policy string cache policy: file/vectorIndex/content
|
||||
```
|
||||
|
||||
例如:使用默认的 data/ip2region.xdb 进行查询测试:
|
||||
例如:使用默认的 data/ip2region_v4.xdb 进行 IPv4 查询测试:
|
||||
```bash
|
||||
➜ lua_c git:(lua_binding) ✗ lua ./search_test.lua --db=../../data/ip2region.xdb --cache-policy=vectorIndex
|
||||
ip2region xdb searcher test program, cachePolicy: vectorIndex
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./search_test.lua --db=../../data/ip2region_v4.xdb
|
||||
ip2region xdb searcher test program
|
||||
source xdb: ../../data/ip2region_v4.xdb (IPv4, vectorIndex)
|
||||
type 'quit' to exit
|
||||
ip2region>> 1.2.3.4
|
||||
{region: 美国|0|华盛顿|0|谷歌, io_count: 7, took: 15μs}
|
||||
ip2region>>
|
||||
ip2region>> 120.229.45.2
|
||||
{region: 中国|广东省|深圳市|移动, io_count: 3, took: 34μs}
|
||||
```
|
||||
|
||||
例如:使用默认的 data/ip2region_v6.xdb 进行 IPv6 查询测试:
|
||||
```bash
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./search_test.lua --db=../../data/ip2region_v6.xdb
|
||||
ip2region xdb searcher test program
|
||||
source xdb: ../../data/ip2region_v6.xdb (IPv6, vectorIndex)
|
||||
type 'quit' to exit
|
||||
ip2region>> 240e:3b7:3276:33b0:958f:f34c:d04f:f6a
|
||||
{region: 中国|广东省|深圳市|家庭宽带, io_count: 14, took: 79μs}
|
||||
```
|
||||
|
||||
输入 ip 即可进行查询测试。也可以分别设置 `cache-policy` 为 file/vectorIndex/content 来测试三种不同缓存实现的效率。
|
||||
|
|
@ -144,7 +211,7 @@ ip2region>>
|
|||
|
||||
通过 `bench_test.lua` 脚本来进行自动 bench 测试,一方面确保 `xdb` 文件没有错误,另一方面通过大量的查询测试平均查询性能:
|
||||
```bash
|
||||
➜ lua_c git:(lua_binding) ✗ lua ./bench_test.lua
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./bench_test.lua
|
||||
lua bench_test.lua [command options]
|
||||
options:
|
||||
--db string ip2region binary xdb file path
|
||||
|
|
@ -152,10 +219,16 @@ options:
|
|||
--cache-policy string cache policy: file/vectorIndex/content
|
||||
```
|
||||
|
||||
例如:通过默认的 data/ip2region.xdb 和 data/ip.merge.txt 来进行 bench 测试:
|
||||
例如:通过默认的 data/ip2region_v4.xdb 和 data/ipv4_source.txt 来进行 IPv4 的 bench 测试:
|
||||
```bash
|
||||
➜ lua_c git:(lua_binding) ✗ lua ./bench_test.lua --db=../../data/ip2region.xdb --src=../../data/ip.merge.txt --cache-policy=vectorIndex
|
||||
Bench finished, {cachePolicy: vectorIndex, total: 3417955, took: 5.865 s, cost: 1.399 μs/op}
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./bench_test.lua --db=../../data/ip2region_v4.xdb --src=../../data/ipv4_source.txt
|
||||
Bench finished, {cachePolicy: vectorIndex, total: 1367686, took: 8.593 s, cost: 5.433 μs/op}
|
||||
```
|
||||
|
||||
例如:通过默认的 data/ip2region_v6.xdb 和 data/ipv6_source.txt 来进行 IPv6 的 bench 测试:
|
||||
```bash
|
||||
➜ lua_c git:(fr_lua_c_ipv6) ✗ lua ./bench_test.lua --db=../../data/ip2region_v6.xdb --src=../../data/ipv6_source.txt
|
||||
Bench finished, {cachePolicy: vectorIndex, total: 34159862, took: 829.008 s, cost: 23.176 μs/op}
|
||||
```
|
||||
|
||||
可以通过设置 `cache-policy` 参数来分别测试 file/vectorIndex/content 三种不同的缓存实现的的性能。
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ if string.len(dbFile) < 2 then
|
|||
return
|
||||
end
|
||||
|
||||
-- verify the xdb from header
|
||||
-- verify the xdb
|
||||
if xdb.verify(dbFile) == false then
|
||||
print(string.format("failed to verify the xdb file: %s", dbFile))
|
||||
return
|
||||
|
|
@ -119,7 +119,7 @@ end
|
|||
print(string.format([[
|
||||
ip2region xdb searcher test program
|
||||
source xdb: %s (%s, %s)
|
||||
type 'quit' to exit]], dbFile, "IPv4", cachePolicy))
|
||||
type 'quit' to exit]], dbFile, xdb.version_info(version).name, cachePolicy))
|
||||
local region, err = "", nil
|
||||
local ip_int, s_time, c_time = 0, 0, 0
|
||||
while ( true ) do
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ function test_load_header()
|
|||
end
|
||||
end
|
||||
|
||||
function test_version_info()
|
||||
local v4 = xdb.version_info(xdb.IPv4)
|
||||
print(string.format("{id:%d, name: %s, bytes: %d, segment_index_size: %d}", v4.id, v4.name, v4.bytes, v4.segment_index_size))
|
||||
local v6 = xdb.version_info(xdb.IPv6)
|
||||
print(string.format("{id:%d, name: %s, bytes: %d, segment_index_size: %d}", v6.id, v6.name, v6.bytes, v6.segment_index_size))
|
||||
local vx = xdb.version_info(3)
|
||||
end
|
||||
|
||||
function test_load_vector_index()
|
||||
v_index, err = xdb.load_vector_index("../../data/ip2region_v4.xdb")
|
||||
|
|
@ -91,14 +98,26 @@ end
|
|||
|
||||
|
||||
function test_search()
|
||||
-- ipv4
|
||||
local ip_str = "1.2.3.4"
|
||||
searcher, err = xdb.new_with_file_only(xdb.IPv4, "../../data/ip2region_v4.xdb")
|
||||
print(string.format("searcher.tostring=%s", searcher))
|
||||
local t_start = xdb.now()
|
||||
region, err = searcher:search(ip_str)
|
||||
local c_time = xdb.now() - t_start
|
||||
print(string.format("search(%s): {region=%s, io_count: %d, took: %dμs, err=%s}",
|
||||
ip_str, region, searcher:get_io_count(), c_time, err))
|
||||
searcher:close()
|
||||
|
||||
-- IPv6
|
||||
ip_str = "240e:3b7:3276:33b0:958f:f34c:d04f:f6a"
|
||||
searcher, err = xdb.new_with_file_only(xdb.IPv6, "../../data/ip2region_v6.xdb")
|
||||
print(string.format("searcher.tostring=%s", searcher))
|
||||
t_start = xdb.now()
|
||||
region, err = searcher:search(ip_str)
|
||||
c_time = xdb.now() - t_start
|
||||
print(string.format("search(%s): {region=%s, io_count: %d, took: %dμs, err=%s}",
|
||||
ip_str, region, searcher:get_io_count(), c_time, err))
|
||||
searcher:close()
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,15 @@ static int lua_xdb_load_content_from_file(lua_State *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_version_from_header(lua_State *L) {
|
||||
xdb_version_t *version;
|
||||
xdb_buffer_t *buffer;
|
||||
|
|
@ -272,19 +281,46 @@ static int lua_xdb_version_from_header(lua_State *L) {
|
|||
lua_pushnil(L);
|
||||
lua_pushstring(L, "failed to detect version from header");
|
||||
} else {
|
||||
lua_pushlightuserdata(L, version);
|
||||
lua_pushinteger(L, version->id);
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lua_xdb_verify_from_file(lua_State *L) {
|
||||
const char *db_path;
|
||||
static xdb_version_t *_get_version(lua_State *L, int arg) {
|
||||
int vid = luaL_checkinteger(L, arg);
|
||||
if (vid == xdb_ipv4_id) {
|
||||
return XDB_IPv4;
|
||||
} else if (vid == xdb_ipv6_id) {
|
||||
return XDB_IPv6;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
static int lua_xdb_version_info(lua_State *L) {
|
||||
xdb_version_t *version;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via '.' and version id expected");
|
||||
// check the ip version
|
||||
version = _get_version(L, 1);
|
||||
if (version == NULL) {
|
||||
return luaL_error(L, "invalid verison id specified");
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, version->id);
|
||||
lua_setfield(L, -2, "id");
|
||||
|
||||
lua_pushstring(L, version->name);
|
||||
lua_setfield(L, -2, "name");
|
||||
|
||||
lua_pushinteger(L, version->bytes);
|
||||
lua_setfield(L, -2, "bytes");
|
||||
|
||||
lua_pushinteger(L, version->segment_index_size);
|
||||
lua_setfield(L, -2, "segment_index_size");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -422,7 +458,7 @@ static int lua_xdb_now(lua_State *L) {
|
|||
// --- xdb searcher api
|
||||
|
||||
static int lua_xdb_new_with_file_only(lua_State *L) {
|
||||
int err, vid;
|
||||
int err;
|
||||
xdb_version_t *version;
|
||||
xdb_searcher_t *searcher;
|
||||
const char *db_path = NULL;
|
||||
|
|
@ -430,10 +466,9 @@ 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
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
version = _get_version(L, 1);
|
||||
if (version == NULL) {
|
||||
return luaL_error(L, "invalid verison id specified");
|
||||
}
|
||||
|
||||
// check the db path
|
||||
|
|
@ -472,10 +507,9 @@ static int lua_xdb_new_with_vector_index(lua_State *L) {
|
|||
luaL_argcheck(L, lua_gettop(L) == 3, 1, "call via '.', ip version / xdb file path / vector index buffer expected");
|
||||
|
||||
// check the ip version
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
version = _get_version(L, 1);
|
||||
if (version == NULL) {
|
||||
return luaL_error(L, "invalid verison id specified");
|
||||
}
|
||||
|
||||
// db_path checking
|
||||
|
|
@ -519,10 +553,9 @@ static int lua_xdb_new_with_buffer(lua_State *L) {
|
|||
luaL_argcheck(L, lua_gettop(L) == 2, 1, "call via '.' and ip version / xdb content buffer expected");
|
||||
|
||||
// check the ip version
|
||||
if (!lua_islightuserdata(L, 1)) {
|
||||
return luaL_error(L, "invalid verison resouce specified");
|
||||
} else {
|
||||
version = (xdb_version_t *) lua_touserdata(L, 1);
|
||||
version = _get_version(L, 1);
|
||||
if (version == NULL) {
|
||||
return luaL_error(L, "invalid verison id specified");
|
||||
}
|
||||
|
||||
// content buffer checking
|
||||
|
|
@ -647,7 +680,11 @@ static int lua_xdb_get_io_count(lua_State *L) {
|
|||
}
|
||||
|
||||
static int lua_xdb_tostring(lua_State *L) {
|
||||
lua_pushliteral(L, "xdb searcher object");
|
||||
xdb_searcher_t *searcher;
|
||||
|
||||
luaL_argcheck(L, lua_gettop(L) == 1, 1, "call via ':' or xdb searcher was broken");
|
||||
searcher = (xdb_searcher_t *) luaL_checkudata(L, 1, XDB_METATABLE_NAME);
|
||||
lua_pushfstring(L, "xdb %s searcher object", xdb_get_version(searcher)->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -677,6 +714,7 @@ static const struct luaL_Reg xdb_searcher_functions[] = {
|
|||
{"load_content", lua_xdb_load_content_from_file},
|
||||
{"verify", lua_xdb_verify_from_file},
|
||||
{"version_from_header", lua_xdb_version_from_header},
|
||||
{"version_info", lua_xdb_version_info},
|
||||
{"cleanup", lua_xdb_cleanup},
|
||||
{"parse_ip", lua_xdb_parse_ip},
|
||||
{"ip_to_string", lua_xdb_ip_to_string},
|
||||
|
|
@ -708,9 +746,9 @@ int luaopen_xdb_searcher(lua_State *L)
|
|||
luaL_setfuncs(L, xdb_searcher_functions, 0);
|
||||
|
||||
// register the constants attributes
|
||||
lua_pushlightuserdata(L, XDB_IPv4);
|
||||
lua_pushinteger(L, xdb_ipv4_id);
|
||||
lua_setfield(L, -2, "IPv4");
|
||||
lua_pushlightuserdata(L, XDB_IPv6);
|
||||
lua_pushinteger(L, xdb_ipv6_id);
|
||||
lua_setfield(L, -2, "IPv6");
|
||||
lua_pushinteger(L, xdb_header_buffer);
|
||||
lua_setfield(L, -2, "header_buffer");
|
||||
|
|
|
|||
Loading…
Reference in New Issue