Skip to content

Commit 82defd6

Browse files
author
alonbg
committed
udp bind
1 parent b81cb1c commit 82defd6

File tree

4 files changed

+291
-15
lines changed

4 files changed

+291
-15
lines changed

src/ngx_stream_lua_socket_udp.c

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828

2929
static int ngx_stream_lua_socket_udp(lua_State *L);
30+
static int ngx_stream_lua_socket_udp_bind(lua_State *L);
3031
static int ngx_stream_lua_socket_udp_setpeername(lua_State *L);
3132
static int ngx_stream_lua_socket_udp_send(lua_State *L);
3233
static int ngx_stream_lua_socket_udp_receive(lua_State *L);
@@ -54,7 +55,7 @@ static void ngx_stream_lua_socket_udp_read_handler(ngx_stream_session_t *s,
5455
ngx_stream_lua_socket_udp_upstream_t *u);
5556
static void ngx_stream_lua_socket_udp_handle_success(ngx_stream_session_t *s,
5657
ngx_stream_lua_socket_udp_upstream_t *u);
57-
static ngx_int_t ngx_stream_lua_udp_connect(
58+
static ngx_int_t ngx_stream_lua_udp_connect(lua_State *L,
5859
ngx_stream_lua_udp_connection_t *uc);
5960
static int ngx_stream_lua_socket_udp_close(lua_State *L);
6061
static ngx_int_t ngx_stream_lua_socket_udp_resume(ngx_stream_session_t *s,
@@ -65,7 +66,8 @@ static void ngx_stream_lua_udp_socket_cleanup(ngx_stream_lua_co_ctx_t *coctx);
6566

6667
enum {
6768
SOCKET_CTX_INDEX = 1,
68-
SOCKET_TIMEOUT_INDEX = 2
69+
SOCKET_TIMEOUT_INDEX = 2,
70+
SOCKET_BIND_INDEX = 3 /* only in upstream cosocket */
6971
};
7072

7173

@@ -84,7 +86,10 @@ ngx_stream_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L)
8486

8587
/* udp socket object metatable */
8688
lua_pushlightuserdata(L, &ngx_stream_lua_socket_udp_metatable_key);
87-
lua_createtable(L, 0 /* narr */, 6 /* nrec */);
89+
lua_createtable(L, 0 /* narr */, 7 /* nrec */);
90+
91+
lua_pushcfunction(L, ngx_stream_lua_socket_udp_bind);
92+
lua_setfield(L, -2, "bind"); /* ngx socket mt */
8893

8994
lua_pushcfunction(L, ngx_stream_lua_socket_udp_setpeername);
9095
lua_setfield(L, -2, "setpeername"); /* ngx socket mt */
@@ -142,7 +147,7 @@ ngx_stream_lua_socket_udp(lua_State *L)
142147
ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT
143148
| NGX_STREAM_LUA_CONTEXT_TIMER);
144149

145-
lua_createtable(L, 3 /* narr */, 1 /* nrec */);
150+
lua_createtable(L, 4 /* narr */, 1 /* nrec */);
146151
lua_pushlightuserdata(L, &ngx_stream_lua_socket_udp_metatable_key);
147152
lua_rawget(L, LUA_REGISTRYINDEX);
148153
lua_setmetatable(L, -2);
@@ -153,6 +158,54 @@ ngx_stream_lua_socket_udp(lua_State *L)
153158
}
154159

155160

161+
static int
162+
ngx_stream_lua_socket_udp_bind(lua_State *L)
163+
{
164+
ngx_stream_session_t *s;
165+
ngx_stream_lua_ctx_t *ctx;
166+
int n;
167+
u_char *text;
168+
size_t len;
169+
ngx_addr_t *local;
170+
171+
n = lua_gettop(L);
172+
if (n != 2) {
173+
return luaL_error(L, "expecting 2 arguments, but got %d",
174+
lua_gettop(L));
175+
}
176+
177+
s = ngx_stream_lua_get_session(L);
178+
if (s == NULL) {
179+
return luaL_error(L, "no request found");
180+
}
181+
182+
ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module);
183+
if (ctx == NULL) {
184+
return luaL_error(L, "no ctx found");
185+
}
186+
187+
ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT
188+
| NGX_STREAM_LUA_CONTEXT_TIMER);
189+
190+
luaL_checktype(L, 1, LUA_TTABLE);
191+
192+
text = (u_char *) luaL_checklstring(L, 2, &len);
193+
local = ngx_stream_lua_parse_addr(L, text, len);
194+
if (local == NULL) {
195+
lua_pushnil(L);
196+
lua_pushfstring(L, "bad address");
197+
return 2;
198+
}
199+
200+
/* TODO: we may reuse the userdata here */
201+
lua_rawseti(L, 1, SOCKET_BIND_INDEX);
202+
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
203+
"lua udp socket bind ip: %V", &local->name);
204+
lua_pushboolean(L, 1);
205+
return 1;
206+
}
207+
208+
156209
static int
157210
ngx_stream_lua_socket_udp_setpeername(lua_State *L)
158211
{
@@ -652,7 +705,7 @@ ngx_stream_lua_socket_resolve_retval_handler(ngx_stream_session_t *s,
652705
return 2;
653706
}
654707

655-
rc = ngx_stream_lua_udp_connect(uc);
708+
rc = ngx_stream_lua_udp_connect(L, uc);
656709

657710
if (rc != NGX_OK) {
658711
u->socket_errno = ngx_socket_errno;
@@ -1318,11 +1371,12 @@ ngx_stream_lua_socket_udp_handle_success(ngx_stream_session_t *s,
13181371

13191372

13201373
static ngx_int_t
1321-
ngx_stream_lua_udp_connect(ngx_stream_lua_udp_connection_t *uc)
1374+
ngx_stream_lua_udp_connect(lua_State *L, ngx_stream_lua_udp_connection_t *uc)
13221375
{
13231376
int rc;
13241377
ngx_int_t event;
13251378
ngx_event_t *rev, *wev;
1379+
ngx_addr_t *local;
13261380
ngx_socket_t s;
13271381
ngx_connection_t *c;
13281382

@@ -1393,6 +1447,20 @@ ngx_stream_lua_udp_connect(ngx_stream_lua_udp_connection_t *uc)
13931447
}
13941448
#endif
13951449

1450+
lua_rawgeti(L, 1, SOCKET_BIND_INDEX);
1451+
local = lua_touserdata(L, -1);
1452+
lua_pop(L, 1);
1453+
1454+
if (local && (uc->sockaddr->sa_family == AF_INET
1455+
|| uc->sockaddr->sa_family == AF_INET6)) {
1456+
if (bind(uc->connection->fd,
1457+
local->sockaddr, local->socklen) != 0) {
1458+
ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
1459+
"bind(%V) failed", &local->name);
1460+
return NGX_ERROR;
1461+
}
1462+
}
1463+
13961464
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
13971465
"connect to %V, fd:%d #%d", &uc->server, s, c->number);
13981466

t/062-count.t

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ worker: 4
249249
ngx.say("n = ", n)
250250
}
251251
--- stream_response
252-
n = 6
252+
n = 7
253253
--- no_error_log
254254
[error]
255255
@@ -279,3 +279,19 @@ n = 6
279279
n = 5
280280
--- no_error_log
281281
[error]
282+
283+
284+
=== TEST 15: entries under the metatable of tcp sockets
285+
--- stream_server_config
286+
content_by_lua_block {
287+
local n = 0
288+
local sock = ngx.socket.tcp()
289+
for k, v in pairs(getmetatable(sock)) do
290+
n = n + 1
291+
end
292+
ngx.say("n = ", n)
293+
}
294+
--- stream_response
295+
n = 12
296+
--- no_error_log
297+
[error]

t/141-tcp-socket-bind.t

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua::Stream;
44
repeat_each(2);
55
#repeat_each(1);
66

7-
plan tests => repeat_each() * (blocks() * 3 + 1);
7+
plan tests => repeat_each() * (blocks() * 3 + 2);
88

99
my $local_ip = `ifconfig | grep -oE '([0-9]{1,3}\\.?){4}' | grep '\\.' | grep -v '127.0.0.1' | head -n 1`;
1010
chomp $local_ip;
@@ -35,18 +35,19 @@ server {
3535
local ip = "127.0.0.1"
3636
local port = 2986
3737
local sock = ngx.socket.tcp()
38+
3839
local ok, err = sock:bind(ip)
3940
if not ok then
4041
ngx.log(ngx.ERR, err)
4142
return
4243
end
44+
4345
local ok, err = sock:connect("127.0.0.1", port)
4446
if not ok then
4547
ngx.log(ngx.ERR, err)
4648
return
4749
end
4850

49-
5051
local line, err, part = sock:receive()
5152
if line then
5253
ngx.say(line)
@@ -74,11 +75,13 @@ server {
7475
local ip = "$TEST_NGINX_SERVER_IP"
7576
local port = 2986
7677
local sock = ngx.socket.tcp()
78+
7779
local ok, err = sock:bind(ip)
7880
if not ok then
7981
ngx.log(ngx.ERR, err)
8082
return
8183
end
84+
8285
local ok, err = sock:connect("127.0.0.1", port)
8386
if not ok then
8487
ngx.log(ngx.ERR, err)
@@ -112,9 +115,10 @@ server {
112115
local ip = "$TEST_NGINX_NOT_EXIST_IP"
113116
local port = 2986
114117
local sock = ngx.socket.tcp()
118+
115119
local ok, err = sock:bind(ip)
116120
if not ok then
117-
ngx.log(ngx.ERR, err)
121+
ngx.log(ngx.INFO, err)
118122
end
119123

120124
local ok, err = sock:connect("127.0.0.1", port)
@@ -126,8 +130,10 @@ server {
126130
--- stream_response
127131
cannot assign requested address
128132
--- error_log eval
129-
["bind(8.8.8.8) failed",
130-
"lua tcp socket bind ip: 8.8.8.8"]
133+
["bind($ENV{TEST_NGINX_NOT_EXIST_IP}) failed",
134+
"lua tcp socket bind ip: $ENV{TEST_NGINX_NOT_EXIST_IP}"]
135+
--- no_error_log
136+
[error]
131137

132138

133139
=== TEST 4: upstream sockets bind invalid ip
@@ -143,19 +149,27 @@ server {
143149
local ip = "$TEST_NGINX_INVALID_IP"
144150
local port = 2986
145151
local sock = ngx.socket.tcp()
152+
146153
local ok, err = sock:bind(ip)
147154
if not ok then
148-
ngx.say("failed to bind: ", err)
155+
ngx.say(err)
149156
end
150157

151158
local ok, err = sock:connect("127.0.0.1", port)
152159
if not ok then
153160
ngx.log(ngx.ERR, err)
154161
end
162+
163+
local line, err, part = sock:receive()
164+
if line then
165+
ngx.say(line)
166+
else
167+
ngx.log(ngx.ERR, err)
168+
end
155169
}
156170

157171
--- stream_response
158-
failed to bind: bad address
159-
--- error_log eval
172+
bad address
173+
127.0.0.1
160174
--- no_error_log
161175
[error]

0 commit comments

Comments
 (0)