Created
August 18, 2016 19:33
-
-
Save agentzh/6c50d37510daef792ed220fa0d970393 to your computer and use it in GitHub Desktop.
My first hacked version of silly Lua DNS server atop NGINX (with patched ngx_stream_lua_module).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local bit = require "bit" | |
local byte = string.byte | |
local lshift = bit.lshift | |
local rshift = bit.rshift | |
local concat = table.concat | |
local insert = table.insert | |
local char = string.char | |
local band = bit.band | |
local sub = string.sub | |
local gsub = string.gsub | |
local clear_tb = require "table.clear" | |
local _M = {} | |
local labels = {} | |
local resp_tb = {} | |
local function _decode_name(buf, pos) | |
clear_tb(labels) | |
local nptrs = 0 | |
local p = pos | |
while nptrs < 128 do | |
local fst = byte(buf, p) | |
if not fst then | |
return nil, 'truncated'; | |
end | |
-- print("fst at ", p, ": ", fst) | |
if fst == 0 then | |
if nptrs == 0 then | |
pos = pos + 1 | |
end | |
break | |
end | |
if band(fst, 0xc0) ~= 0 then | |
-- being a pointer | |
if nptrs == 0 then | |
pos = pos + 2 | |
end | |
nptrs = nptrs + 1 | |
local snd = byte(buf, p + 1) | |
if not snd then | |
return nil, 'truncated' | |
end | |
p = lshift(band(fst, 0x3f), 8) + snd + 1 | |
-- print("resolving ptr ", p, ": ", byte(buf, p)) | |
else | |
-- being a label | |
local label = sub(buf, p + 1, p + fst) | |
insert(labels, label) | |
-- print("resolved label ", label) | |
p = p + fst + 1 | |
if nptrs == 0 then | |
pos = p | |
end | |
end | |
end | |
return concat(labels, "."), pos | |
end | |
function send_bad_req(id, sock) | |
if not id then | |
return | |
end | |
local ident_hi = char(rshift(id, 8)) | |
local ident_lo = char(band(id, 0xff)) | |
local ok, err = sock:send{ | |
ident_hi, ident_lo, "\x80\1\0\0\0\0\0\0\0\0", | |
} | |
if not ok then | |
ngx.log(ngx.ERR, "failed to send: ", err) | |
return | |
end | |
end | |
local function _encode_name(s) | |
return char(#s) .. s | |
end | |
local cname | |
function send_ans(id, sock, raw_quest_rr, raw_quest_name) | |
local ident_hi = char(rshift(id, 8)) | |
local ident_lo = char(band(id, 0xff)) | |
if not cname then | |
cname = "a.foo.com" | |
cname = gsub(cname, "([^.]+)%.?", _encode_name) .. '\0' | |
end | |
local len = #cname | |
local len_hi = char(rshift(len, 8)) | |
local len_lo = char(band(len, 0xff)) | |
resp_tb[1] = ident_hi | |
resp_tb[2] = ident_lo | |
resp_tb[3] = "\x84\0\0\1\0\1\0\0\0\0" | |
resp_tb[4] = raw_quest_rr | |
resp_tb[5] = raw_quest_name | |
resp_tb[6] = "\0\x05\0\x01\0\0\x0e\x10" | |
resp_tb[7] = len_hi | |
resp_tb[8] = len_lo | |
resp_tb[9] = cname | |
local ok, err = sock:send(resp_tb) | |
if not ok then | |
ngx.log(ngx.ERR, "failed to send: ", err) | |
return | |
end | |
end | |
function _M.go() | |
local sock, err = ngx.req.udp_socket() | |
if not sock then | |
ngx.log(ngx.ERR, "failed to get the request socket: ", err) | |
return ngx.exit(ngx.ERROR) | |
end | |
local req, err = sock:receive() | |
if not req then | |
ngx.log(ngx.ERR, "failed to receive: ", err) | |
return ngx.exit(ngx.ERROR) | |
end | |
local id | |
local n = #req | |
if n < 12 then | |
ngx.log(ngx.ERR, "request truncated") | |
return send_bad_req(id, sock) | |
end | |
local ident_hi = byte(req, 1) | |
local ident_lo = byte(req, 2) | |
id = lshift(ident_hi, 8) + ident_lo | |
-- print("req id: ", id) | |
local flags_hi = byte(req, 3) | |
local flags_lo = byte(req, 4) | |
local flags = lshift(flags_hi, 8) + flags_lo | |
if band(flags, 0x8000) == 1 then | |
ngx.log(ngx.ERR, "bad QR flag in the DNS request") | |
return send_bad_req(id, sock) | |
end | |
local code = band(flags, 0xf) | |
local nqs_hi = byte(req, 5) | |
local nqs_lo = byte(req, 6) | |
local nqs = lshift(nqs_hi, 8) + nqs_lo | |
if nqs ~= 1 then | |
ngx.log(ngx.ERR, "bad number of questions: ", nqs) | |
return send_bad_req(id, sock) | |
end | |
local nan_hi = byte(req, 7) | |
local nan_lo = byte(req, 8) | |
local nan = lshift(nan_hi, 8) + nan_lo | |
if nan ~= 0 then | |
ngx.log(ngx.ERR, "bad number of answers in the request: ", nan) | |
return send_bad_req(id, sock) | |
end | |
local quest_qname, pos = _decode_name(req, 13) | |
if not quest_qname then | |
ngx.log(ngx.ERR, "bad question") | |
return send_bad_req(id, sock) | |
end | |
local raw_quest_rr = sub(req, 13, pos + 3) | |
local raw_quest_name = sub(req, 13, pos - 1) | |
-- print("question qname: ", quest_qname) | |
return send_ans(id, sock, raw_quest_rr, raw_quest_name) | |
end | |
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
worker_processes 1; | |
daemon on; | |
master_process on; | |
error_log logs/error.log warn; | |
pid logs/nginx.pid; | |
stream { | |
lua_package_path '$prefix/lualib/?.lua;;'; | |
init_by_lua_block { | |
jit.opt.start("minstitch=2") | |
} | |
server { | |
listen 1235 udp; | |
content_by_lua_block { | |
require "dns_server".go() | |
} | |
} | |
} | |
events { | |
accept_mutex off; | |
worker_connections 1024; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/ngx_stream_lua_socket_tcp.c b/src/ngx_stream_lua_socket_tcp.c | |
index 4680811..4c44b39 100644 | |
--- a/src/ngx_stream_lua_socket_tcp.c | |
+++ b/src/ngx_stream_lua_socket_tcp.c | |
@@ -95,7 +95,7 @@ static int ngx_stream_lua_socket_receiveuntil_iterator(lua_State *L); | |
static ngx_int_t ngx_stream_lua_socket_compile_pattern(u_char *data, size_t len, | |
ngx_stream_lua_socket_compiled_pattern_t *cp, ngx_log_t *log); | |
static int ngx_stream_lua_socket_cleanup_compiled_pattern(lua_State *L); | |
-static int ngx_stream_lua_req_socket(lua_State *L); | |
+static int ngx_stream_lua_tcp_req_socket(lua_State *L); | |
static void ngx_stream_lua_req_socket_rev_handler(ngx_stream_session_t *s, | |
ngx_stream_lua_ctx_t *ctx); | |
static int ngx_stream_lua_socket_tcp_getreusedtimes(lua_State *L); | |
@@ -193,7 +193,7 @@ enum { | |
static char ngx_stream_lua_req_socket_metatable_key; | |
#endif | |
static char ngx_stream_lua_raw_req_socket_metatable_key; | |
-static char ngx_stream_lua_tcp_socket_metatable_key; | |
+static char ngx_stream_lua_socket_tcp_metatable_key; | |
static char ngx_stream_lua_upstream_udata_metatable_key; | |
static char ngx_stream_lua_downstream_udata_metatable_key; | |
static char ngx_stream_lua_pool_udata_metatable_key; | |
@@ -276,7 +276,7 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) | |
/* }}} */ | |
/* {{{tcp object metatable */ | |
- lua_pushlightuserdata(L, &ngx_stream_lua_tcp_socket_metatable_key); | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_socket_tcp_metatable_key); | |
lua_createtable(L, 0 /* narr */, 11 /* nrec */); | |
lua_pushcfunction(L, ngx_stream_lua_socket_tcp_connect); | |
@@ -364,14 +364,6 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) | |
} | |
-void | |
-ngx_stream_lua_inject_req_socket_api(lua_State *L) | |
-{ | |
- lua_pushcfunction(L, ngx_stream_lua_req_socket); | |
- lua_setfield(L, -2, "socket"); | |
-} | |
- | |
- | |
static int | |
ngx_stream_lua_socket_tcp(lua_State *L) | |
{ | |
@@ -397,7 +389,7 @@ ngx_stream_lua_socket_tcp(lua_State *L) | |
| NGX_STREAM_LUA_CONTEXT_TIMER); | |
lua_createtable(L, 3 /* narr */, 1 /* nrec */); | |
- lua_pushlightuserdata(L, &ngx_stream_lua_tcp_socket_metatable_key); | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_socket_tcp_metatable_key); | |
lua_rawget(L, LUA_REGISTRYINDEX); | |
lua_setmetatable(L, -2); | |
@@ -3919,14 +3911,22 @@ ngx_stream_lua_socket_cleanup_compiled_pattern(lua_State *L) | |
} | |
+void | |
+ngx_stream_lua_inject_tcp_req_socket_api(lua_State *L) | |
+{ | |
+ lua_pushcfunction(L, ngx_stream_lua_tcp_req_socket); | |
+ lua_setfield(L, -2, "socket"); | |
+} | |
+ | |
+ | |
static int | |
-ngx_stream_lua_req_socket(lua_State *L) | |
+ngx_stream_lua_tcp_req_socket(lua_State *L) | |
{ | |
int n, raw; | |
+ ngx_stream_session_t *s; | |
ngx_peer_connection_t *pc; | |
ngx_stream_lua_srv_conf_t *lscf; | |
ngx_connection_t *c; | |
- ngx_stream_session_t *s; | |
ngx_stream_lua_ctx_t *ctx; | |
ngx_stream_lua_co_ctx_t *coctx; | |
ngx_stream_lua_cleanup_t *cln; | |
@@ -3957,6 +3957,11 @@ ngx_stream_lua_req_socket(lua_State *L) | |
c = s->connection; | |
+ if (c->type != SOCK_STREAM) { | |
+ return luaL_error(L, "socket api does not match connection transport", | |
+ lua_gettop(L)); | |
+ } | |
+ | |
#if !defined(nginx_version) || nginx_version < 1003013 | |
lua_pushnil(L); | |
lua_pushliteral(L, "nginx version too old"); | |
diff --git a/src/ngx_stream_lua_socket_tcp.h b/src/ngx_stream_lua_socket_tcp.h | |
index 68bcfb0..ec6e4d7 100644 | |
--- a/src/ngx_stream_lua_socket_tcp.h | |
+++ b/src/ngx_stream_lua_socket_tcp.h | |
@@ -147,7 +147,7 @@ typedef struct { | |
void ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L); | |
-void ngx_stream_lua_inject_req_socket_api(lua_State *L); | |
+void ngx_stream_lua_inject_tcp_req_socket_api(lua_State *L); | |
void ngx_stream_lua_cleanup_conn_pools(lua_State *L); | |
diff --git a/src/ngx_stream_lua_socket_udp.c b/src/ngx_stream_lua_socket_udp.c | |
index c8014f0..366f7a4 100644 | |
--- a/src/ngx_stream_lua_socket_udp.c | |
+++ b/src/ngx_stream_lua_socket_udp.c | |
@@ -31,8 +31,10 @@ static int ngx_stream_lua_socket_udp_setpeername(lua_State *L); | |
static int ngx_stream_lua_socket_udp_send(lua_State *L); | |
static int ngx_stream_lua_socket_udp_receive(lua_State *L); | |
static int ngx_stream_lua_socket_udp_settimeout(lua_State *L); | |
+static int ngx_stream_lua_udp_req_socket(lua_State *L); | |
static void ngx_stream_lua_socket_udp_finalize(ngx_stream_session_t *s, | |
ngx_stream_lua_socket_udp_upstream_t *u); | |
+static int ngx_stream_lua_socket_udp_downstream_destroy(lua_State *L); | |
static int ngx_stream_lua_socket_udp_upstream_destroy(lua_State *L); | |
static int ngx_stream_lua_socket_resolve_retval_handler(ngx_stream_session_t *s, | |
ngx_stream_lua_socket_udp_upstream_t *u, lua_State *L); | |
@@ -69,8 +71,13 @@ enum { | |
}; | |
+#if 0 | |
+static char ngx_stream_lua_req_socket_metatable_key; | |
+#endif | |
+static char ngx_stream_lua_raw_req_socket_metatable_key; | |
static char ngx_stream_lua_socket_udp_metatable_key; | |
-static char ngx_stream_lua_udp_udata_metatable_key; | |
+static char ngx_stream_lua_upstream_udata_metatable_key; | |
+static char ngx_stream_lua_downstream_udata_metatable_key; | |
static u_char ngx_stream_lua_socket_udp_buffer[UDP_MAX_DATAGRAM_SIZE]; | |
@@ -106,18 +113,206 @@ ngx_stream_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L) | |
lua_rawset(L, LUA_REGISTRYINDEX); | |
/* }}} */ | |
- /* udp socket object metatable */ | |
- lua_pushlightuserdata(L, &ngx_stream_lua_udp_udata_metatable_key); | |
+ /* {{{upstream userdata metatable */ | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_upstream_udata_metatable_key); | |
lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ | |
lua_pushcfunction(L, ngx_stream_lua_socket_udp_upstream_destroy); | |
lua_setfield(L, -2, "__gc"); | |
lua_rawset(L, LUA_REGISTRYINDEX); | |
/* }}} */ | |
+ /* {{{downstream userdata metatable */ | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_downstream_udata_metatable_key); | |
+ lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_downstream_destroy); | |
+ lua_setfield(L, -2, "__gc"); | |
+ lua_rawset(L, LUA_REGISTRYINDEX); | |
+ /* }}} */ | |
+ | |
+#if 0 | |
+ /* {{{udp req socket object metatable */ | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_req_socket_metatable_key); | |
+ lua_createtable(L, 0 /* narr */, 3 /* nrec */); | |
+ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_receive); | |
+ lua_setfield(L, -2, "receive"); | |
+ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_settimeout); | |
+ lua_setfield(L, -2, "settimeout"); /* ngx socket mt */ | |
+ | |
+ lua_pushvalue(L, -1); | |
+ lua_setfield(L, -2, "__index"); | |
+ | |
+ lua_rawset(L, LUA_REGISTRYINDEX); | |
+ /* }}} */ | |
+#endif | |
+ | |
+ /* {{{raw udp req socket object metatable */ | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_raw_req_socket_metatable_key); | |
+ lua_createtable(L, 0 /* narr */, 4 /* nrec */); | |
+ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_receive); | |
+ lua_setfield(L, -2, "receive"); | |
+ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_send); | |
+ lua_setfield(L, -2, "send"); | |
+ | |
+ lua_pushcfunction(L, ngx_stream_lua_socket_udp_settimeout); | |
+ lua_setfield(L, -2, "settimeout"); /* ngx socket mt */ | |
+ | |
+ lua_pushvalue(L, -1); | |
+ lua_setfield(L, -2, "__index"); | |
+ lua_rawset(L, LUA_REGISTRYINDEX); | |
+ /* }}} */ | |
+ | |
lua_pop(L, 1); | |
} | |
+void | |
+ngx_stream_lua_inject_udp_req_socket_api(lua_State *L) | |
+{ | |
+ lua_pushcfunction(L, ngx_stream_lua_udp_req_socket); | |
+ lua_setfield(L, -2, "udp_socket"); | |
+} | |
+ | |
+ | |
+static int | |
+ngx_stream_lua_udp_req_socket(lua_State *L) | |
+{ | |
+ int n, raw; | |
+ ngx_stream_session_t *s; | |
+ ngx_stream_lua_udp_connection_t *pc; | |
+ ngx_stream_lua_srv_conf_t *lscf; | |
+ ngx_connection_t *c; | |
+ ngx_stream_lua_ctx_t *ctx; | |
+ ngx_stream_lua_co_ctx_t *coctx; | |
+ ngx_stream_lua_cleanup_t *cln; | |
+ | |
+ ngx_stream_lua_socket_udp_upstream_t *u; | |
+ | |
+ n = lua_gettop(L); | |
+ if (n == 0) { | |
+ raw = 0; | |
+ | |
+ } else if (n == 1) { | |
+ raw = lua_toboolean(L, 1); | |
+ lua_pop(L, 1); | |
+ | |
+ } else { | |
+ return luaL_error(L, "expecting zero arguments, but got %d", | |
+ lua_gettop(L)); | |
+ } | |
+ | |
+ s = ngx_stream_lua_get_session(L); | |
+ | |
+ ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module); | |
+ if (ctx == NULL) { | |
+ return luaL_error(L, "no ctx found"); | |
+ } | |
+ | |
+ ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT); | |
+ | |
+ c = s->connection; | |
+ | |
+ if (c->type != SOCK_DGRAM) { | |
+ return luaL_error(L, "socket api does not match connection transport", | |
+ lua_gettop(L)); | |
+ } | |
+ | |
+#if !defined(nginx_version) || nginx_version < 1003013 | |
+ lua_pushnil(L); | |
+ lua_pushliteral(L, "nginx version too old"); | |
+ return 2; | |
+#else | |
+ if (ctx->downstream_busy_bufs) { | |
+ lua_pushnil(L); | |
+ lua_pushliteral(L, "pending data to write"); | |
+ return 2; | |
+ } | |
+ | |
+ dd("ctx acquired raw req socket: %d", ctx->acquired_raw_req_socket); | |
+ | |
+ if (ctx->acquired_raw_req_socket) { | |
+ lua_pushnil(L); | |
+ lua_pushliteral(L, "duplicate call"); | |
+ return 2; | |
+ } | |
+ | |
+ ctx->acquired_raw_req_socket = 1; | |
+#endif | |
+ | |
+ lua_createtable(L, 3 /* narr */, 1 /* nrec */); /* the object */ | |
+ | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_raw_req_socket_metatable_key); | |
+ | |
+ lua_rawget(L, LUA_REGISTRYINDEX); | |
+ lua_setmetatable(L, -2); | |
+ | |
+ u = lua_newuserdata(L, sizeof(ngx_stream_lua_socket_udp_upstream_t)); | |
+ if (u == NULL) { | |
+ return luaL_error(L, "no memory"); | |
+ } | |
+ | |
+#if 1 | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_downstream_udata_metatable_key); | |
+ lua_rawget(L, LUA_REGISTRYINDEX); | |
+ lua_setmetatable(L, -2); | |
+#endif | |
+ | |
+ lua_rawseti(L, 1, SOCKET_CTX_INDEX); | |
+ | |
+ ngx_memzero(u, sizeof(ngx_stream_lua_socket_udp_upstream_t)); | |
+ | |
+ u->raw_downstream = 1; | |
+ | |
+ coctx = ctx->cur_co_ctx; | |
+ | |
+ u->session = s; | |
+ | |
+ lscf = ngx_stream_get_module_srv_conf(s, ngx_stream_lua_module); | |
+ | |
+ u->conf = lscf; | |
+ | |
+ u->read_timeout = u->conf->read_timeout; | |
+ | |
+ cln = ngx_stream_lua_cleanup_add(s, 0); | |
+ if (cln == NULL) { | |
+ u->ft_type |= NGX_STREAM_LUA_SOCKET_FT_ERROR; | |
+ lua_pushnil(L); | |
+ lua_pushliteral(L, "no memory"); | |
+ return 2; | |
+ } | |
+ | |
+ cln->handler = ngx_stream_lua_socket_udp_cleanup; | |
+ cln->data = u; | |
+ | |
+ u->cleanup = &cln->handler; | |
+ | |
+ pc = &u->udp_connection; | |
+ pc->log = *c->log; | |
+ pc->connection = c; | |
+ | |
+ dd("setting data to %p", u); | |
+ | |
+ coctx->data = u; | |
+ ctx->downstream = u; | |
+ | |
+ if (c->read->timer_set) { | |
+ ngx_del_timer(c->read); | |
+ } | |
+ | |
+ if (raw) { | |
+ if (c->write->timer_set) { | |
+ ngx_del_timer(c->write); | |
+ } | |
+ } | |
+ | |
+ lua_settop(L, 1); | |
+ return 1; | |
+} | |
+ | |
+ | |
static int | |
ngx_stream_lua_socket_udp(lua_State *L) | |
{ | |
@@ -259,7 +454,7 @@ ngx_stream_lua_socket_udp_setpeername(lua_State *L) | |
} | |
#if 1 | |
- lua_pushlightuserdata(L, &ngx_stream_lua_udp_udata_metatable_key); | |
+ lua_pushlightuserdata(L, &ngx_stream_lua_upstream_udata_metatable_key); | |
lua_rawget(L, LUA_REGISTRYINDEX); | |
lua_setmetatable(L, -2); | |
#endif | |
@@ -863,7 +1058,7 @@ ngx_stream_lua_socket_udp_send(lua_State *L) | |
dd("sending query %.*s", (int) query.len, query.data); | |
- n = ngx_send(u->udp_connection.connection, query.data, query.len); | |
+ n = ngx_udp_send(u->udp_connection.connection, query.data, query.len); | |
dd("ngx_send returns %d (query len %d)", (int) n, (int) query.len); | |
@@ -892,6 +1087,7 @@ ngx_stream_lua_socket_udp_receive(lua_State *L) | |
{ | |
ngx_stream_session_t *s; | |
ngx_stream_lua_socket_udp_upstream_t *u; | |
+ ngx_connection_t *c; | |
ngx_int_t rc; | |
ngx_stream_lua_ctx_t *ctx; | |
ngx_stream_lua_co_ctx_t *coctx; | |
@@ -961,7 +1157,19 @@ ngx_stream_lua_socket_udp_receive(lua_State *L) | |
"stream lua udp socket receive buffer size: %uz", | |
u->recv_buf_size); | |
- rc = ngx_stream_lua_socket_udp_read(s, u); | |
+ c = u->udp_connection.connection; | |
+ | |
+ if (u->raw_downstream && !u->connected) { | |
+ u->received = c->buffer->last - c->buffer->pos; | |
+ c->buffer->pos = | |
+ ngx_copy(ngx_stream_lua_socket_udp_buffer, c->buffer->pos, u->received); | |
+ ngx_stream_lua_socket_udp_handle_success(s, u); | |
+ u->connected = 1; | |
+ rc = NGX_OK; | |
+ | |
+ } else { | |
+ rc = ngx_stream_lua_socket_udp_read(s, u); | |
+ } | |
if (rc == NGX_ERROR) { | |
dd("read failed: %d", (int) u->ft_type); | |
@@ -1073,7 +1281,7 @@ ngx_stream_lua_socket_udp_finalize(ngx_stream_session_t *s, | |
u->resolved->ctx = NULL; | |
} | |
- if (u->udp_connection.connection) { | |
+ if (u->udp_connection.connection && !u->raw_downstream) { | |
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, | |
"stream lua close socket connection"); | |
@@ -1107,6 +1315,27 @@ ngx_stream_lua_socket_udp_upstream_destroy(lua_State *L) | |
} | |
+static int | |
+ngx_stream_lua_socket_udp_downstream_destroy(lua_State *L) | |
+{ | |
+ ngx_stream_lua_socket_udp_upstream_t *u; | |
+ | |
+ dd("downstream destory"); | |
+ | |
+ u = lua_touserdata(L, 1); | |
+ if (u == NULL) { | |
+ dd("u is NULL"); | |
+ return 0; | |
+ } | |
+ | |
+ if (u->cleanup) { | |
+ ngx_stream_lua_socket_udp_cleanup(u); /* it will clear u->cleanup */ | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+ | |
static void | |
ngx_stream_lua_socket_dummy_handler(ngx_stream_session_t *s, | |
ngx_stream_lua_socket_udp_upstream_t *u) | |
diff --git a/src/ngx_stream_lua_socket_udp.h b/src/ngx_stream_lua_socket_udp.h | |
index 7055c4f..e7ca378 100644 | |
--- a/src/ngx_stream_lua_socket_udp.h | |
+++ b/src/ngx_stream_lua_socket_udp.h | |
@@ -46,18 +46,20 @@ struct ngx_stream_lua_socket_udp_upstream_s { | |
ngx_stream_lua_resolved_t *resolved; | |
- ngx_uint_t ft_type; | |
- ngx_err_t socket_errno; | |
- size_t received; /* for receive */ | |
- size_t recv_buf_size; | |
+ ngx_uint_t ft_type; | |
+ ngx_err_t socket_errno; | |
+ size_t received; /* for receive */ | |
+ size_t recv_buf_size; | |
ngx_stream_lua_co_ctx_t *co_ctx; | |
- | |
- unsigned waiting; /* :1 */ | |
+ unsigned raw_downstream:1; | |
+ unsigned waiting:1; | |
+ unsigned connected:1; | |
}; | |
void ngx_stream_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L); | |
+void ngx_stream_lua_inject_udp_req_socket_api(lua_State *L); | |
#endif /* _NGX_STREAM_LUA_SOCKET_UDP_H_INCLUDED_ */ | |
diff --git a/src/ngx_stream_lua_util.c b/src/ngx_stream_lua_util.c | |
index cebad77..b05eda5 100644 | |
--- a/src/ngx_stream_lua_util.c | |
+++ b/src/ngx_stream_lua_util.c | |
@@ -491,6 +491,7 @@ ngx_stream_lua_new_thread(ngx_stream_session_t *s, lua_State *L, int *ref) | |
co = lua_newthread(L); | |
+#if 0 | |
/* {{{ inherit coroutine's globals to main thread's globals table | |
* for print() function will try to find tostring() in current | |
* globals table. | |
@@ -505,6 +506,7 @@ ngx_stream_lua_new_thread(ngx_stream_session_t *s, lua_State *L, int *ref) | |
ngx_stream_lua_set_globals_table(co); | |
/* }}} */ | |
+#endif | |
*ref = luaL_ref(L, -2); | |
@@ -3226,9 +3228,9 @@ ngx_stream_lua_inject_req_api(ngx_log_t *log, lua_State *L) | |
{ | |
/* ngx.req table */ | |
- lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* .req */ | |
- | |
- ngx_stream_lua_inject_req_socket_api(L); | |
+ lua_createtable(L, 0 /* narr */, 2 /* nrec */); /* .req */ | |
+ ngx_stream_lua_inject_tcp_req_socket_api(L); | |
+ ngx_stream_lua_inject_udp_req_socket_api(L); | |
lua_setfield(L, -2, "req"); | |
} | |
diff --git a/t/062-count.t b/t/062-count.t | |
index bdb531c..7933463 100644 | |
--- a/t/062-count.t | |
+++ b/t/062-count.t | |
@@ -46,7 +46,7 @@ ngx: 56 | |
ngx.say("n = ", n) | |
} | |
--- stream_response | |
-n = 1 | |
+n = 2 | |
--- no_error_log | |
[error] | |
diff --git a/t/138-req-udp-socket.t b/t/138-req-udp-socket.t | |
new file mode 100644 | |
index 0000000..24d2c46 | |
--- /dev/null | |
+++ b/t/138-req-udp-socket.t | |
@@ -0,0 +1,251 @@ | |
+# vim:set ft= ts=4 sw=4 et fdm=marker: | |
+ | |
+use Test::Nginx::Socket::Lua::Dgram; | |
+ | |
+repeat_each(2); | |
+ | |
+plan tests => repeat_each() * (blocks() * 3 + 1); | |
+ | |
+our $HtmlDir = html_dir; | |
+ | |
+#$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; | |
+ | |
+no_long_string(); | |
+#no_diff(); | |
+#log_level 'warn'; | |
+no_shuffle(); | |
+ | |
+run_tests(); | |
+ | |
+__DATA__ | |
+ | |
+=== TEST 1: sanity | |
+--- ONLY | |
+--- dgram_server_config | |
+ content_by_lua_block { | |
+ local sock, err = ngx.req.udp_socket() | |
+ if not sock then | |
+ ngx.log(ngx.ERR, "failed to get the request socket: ", err) | |
+ return ngx.exit(ngx.ERROR) | |
+ end | |
+ | |
+ local data, err = sock:receive() | |
+ if not data then | |
+ ngx.log(ngx.ERR, "failed to receive: ", err) | |
+ return ngx.exit(ngx.ERROR) | |
+ end | |
+ | |
+ -- print("data: ", data) | |
+ | |
+ local ok, err = sock:send("received: " .. data) | |
+ if not ok then | |
+ ngx.log(ngx.ERR, "failed to send: ", err) | |
+ return ngx.exit(ngx.ERROR) | |
+ end | |
+ } | |
+--- dgram_request chomp | |
+hello world! my | |
+--- dgram_response chomp | |
+received: hello world! my | |
+--- no_error_log | |
+[error] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
req.udp_socket is not supported now?