Skip to content

Instantly share code, notes, and snippets.

@agentzh
Created August 18, 2016 19:33
Show Gist options
  • Save agentzh/6c50d37510daef792ed220fa0d970393 to your computer and use it in GitHub Desktop.
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).
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
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;
}
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]
@dongbenxipao
Copy link

req.udp_socket is not supported now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment