Skip to content

Commit 4dac2ac

Browse files
alonbgzhuizhuhaomeng
alonbg
authored andcommitted
feature: add support for tcp/udp bind.
1 parent 35071d9 commit 4dac2ac

12 files changed

+1143
-39
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,4 @@ src/ringbuf.c
7676
src/ringbuf.h
7777
src/ssl.c
7878
src/ssl.h
79+
*.project

src/ngx_stream_lua_socket_tcp.c

+147-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929

3030
static int ngx_stream_lua_socket_tcp(lua_State *L);
31+
static int ngx_stream_lua_socket_tcp_bind(lua_State *L);
3132
static int ngx_stream_lua_socket_tcp_connect(lua_State *L);
3233
#if (NGX_STREAM_SSL)
3334
static int ngx_stream_lua_socket_tcp_sslhandshake(lua_State *L);
@@ -183,9 +184,11 @@ static void ngx_stream_lua_ssl_handshake_handler(ngx_connection_t *c);
183184
static int ngx_stream_lua_ssl_free_session(lua_State *L);
184185
#endif
185186
static void ngx_stream_lua_socket_tcp_close_connection(ngx_connection_t *c);
187+
static void ngx_stream_lua_inject_socket_option_consts(lua_State *L);
186188

187189
static int ngx_stream_lua_socket_tcp_peek(lua_State *L);
188-
static ngx_int_t ngx_stream_lua_socket_tcp_peek_resume(ngx_stream_lua_request_t *r);
190+
static ngx_int_t ngx_stream_lua_socket_tcp_peek_resume(
191+
ngx_stream_lua_request_t *r);
189192
static int ngx_stream_lua_socket_tcp_shutdown(lua_State *L);
190193

191194

@@ -195,6 +198,8 @@ enum {
195198
SOCKET_CONNECT_TIMEOUT_INDEX = 2,
196199
SOCKET_SEND_TIMEOUT_INDEX = 4,
197200
SOCKET_READ_TIMEOUT_INDEX = 5,
201+
SOCKET_BIND_INDEX = 6, /* only in upstream cosocket */
202+
SOCKET_IP_TRANSPARENT_INDEX = 7
198203
};
199204

200205

@@ -249,11 +254,24 @@ static char ngx_stream_lua_ssl_session_metatable_key;
249254
#endif
250255

251256

257+
static void
258+
ngx_stream_lua_inject_socket_option_consts(lua_State *L)
259+
{
260+
/* {{{ socket option constants */
261+
#if (NGX_HAVE_TRANSPARENT_PROXY)
262+
lua_pushinteger(L, NGX_STREAM_LUA_SOCKET_OPTION_TRANSPARENT);
263+
lua_setfield(L, -2, "IP_TRANSPARENT");
264+
#endif
265+
}
266+
267+
252268
void
253269
ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
254270
{
255271
ngx_int_t rc;
256272

273+
ngx_stream_lua_inject_socket_option_consts(L);
274+
257275
lua_createtable(L, 0, 4 /* nrec */); /* ngx.socket */
258276

259277
lua_pushcfunction(L, ngx_stream_lua_socket_tcp);
@@ -319,7 +337,10 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
319337
/* {{{tcp object metatable */
320338
lua_pushlightuserdata(L, ngx_stream_lua_lightudata_mask(
321339
tcp_socket_metatable_key));
322-
lua_createtable(L, 0 /* narr */, 14 /* nrec */);
340+
lua_createtable(L, 0 /* narr */, 15 /* nrec */);
341+
342+
lua_pushcfunction(L, ngx_stream_lua_socket_tcp_bind);
343+
lua_setfield(L, -2, "bind");
323344

324345
lua_pushcfunction(L, ngx_stream_lua_socket_tcp_connect);
325346
lua_setfield(L, -2, "connect");
@@ -457,7 +478,8 @@ ngx_stream_lua_socket_tcp(lua_State *L)
457478

458479
static void
459480
ngx_stream_lua_socket_tcp_create_socket_pool(lua_State *L,
460-
ngx_stream_lua_request_t *r, ngx_str_t key, ngx_int_t pool_size, ngx_int_t backlog,
481+
ngx_stream_lua_request_t *r, ngx_str_t key, ngx_int_t pool_size,
482+
ngx_int_t backlog,
461483
ngx_stream_lua_socket_pool_t **spool)
462484
{
463485
u_char *p;
@@ -854,6 +876,55 @@ ngx_stream_lua_socket_tcp_connect_helper(lua_State *L,
854876
}
855877

856878

879+
static int
880+
ngx_stream_lua_socket_tcp_bind(lua_State *L)
881+
{
882+
ngx_stream_lua_ctx_t *ctx;
883+
int n;
884+
u_char *text;
885+
size_t len;
886+
ngx_addr_t *local;
887+
888+
ngx_stream_lua_request_t *r;
889+
890+
n = lua_gettop(L);
891+
if (n != 2) {
892+
return luaL_error(L, "expecting 2 arguments, but got %d",
893+
lua_gettop(L));
894+
}
895+
896+
r = ngx_stream_lua_get_req(L);
897+
if (r == NULL) {
898+
return luaL_error(L, "no request found");
899+
}
900+
901+
ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_lua_module);
902+
if (ctx == NULL) {
903+
return luaL_error(L, "no ctx found");
904+
}
905+
906+
ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT
907+
| NGX_STREAM_LUA_CONTEXT_TIMER);
908+
909+
luaL_checktype(L, 1, LUA_TTABLE);
910+
911+
text = (u_char *) luaL_checklstring(L, 2, &len);
912+
local = ngx_stream_lua_parse_addr(L, text, len);
913+
if (local == NULL) {
914+
lua_pushnil(L);
915+
lua_pushfstring(L, "bad address");
916+
return 2;
917+
}
918+
919+
/* TODO: we may reuse the userdata here */
920+
lua_rawseti(L, 1, SOCKET_BIND_INDEX);
921+
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
922+
"lua tcp socket bind ip: %V", &local->name);
923+
lua_pushboolean(L, 1);
924+
return 1;
925+
}
926+
927+
857928
static int
858929
ngx_stream_lua_socket_tcp_connect(lua_State *L)
859930
{
@@ -864,6 +935,7 @@ ngx_stream_lua_socket_tcp_connect(lua_State *L)
864935
u_char *p;
865936
size_t len;
866937
ngx_peer_connection_t *pc;
938+
ngx_addr_t *local;
867939
int connect_timeout, send_timeout, read_timeout;
868940
unsigned custom_pool;
869941
int key_index;
@@ -1078,6 +1150,26 @@ ngx_stream_lua_socket_tcp_connect(lua_State *L)
10781150

10791151
lua_pop(L, 3);
10801152

1153+
lua_rawgeti(L, 1, SOCKET_BIND_INDEX);
1154+
local = lua_touserdata(L, -1);
1155+
lua_pop(L, 1);
1156+
1157+
if (local) {
1158+
u->peer.local = local;
1159+
}
1160+
1161+
#if (NGX_HAVE_TRANSPARENT_PROXY)
1162+
lua_rawgeti(L, 1, SOCKET_IP_TRANSPARENT_INDEX);
1163+
1164+
if (lua_tointeger(L, -1) > 0) {
1165+
pc->transparent = 1;
1166+
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
1167+
"stream lua set TCP upstream with IP_TRANSPARENT");
1168+
}
1169+
1170+
lua_pop(L, 1);
1171+
#endif
1172+
10811173
if (connect_timeout > 0) {
10821174
u->connect_timeout = (ngx_msec_t) connect_timeout;
10831175

@@ -1205,7 +1297,8 @@ ngx_stream_lua_socket_resolve_handler(ngx_resolver_ctx_t *ctx)
12051297
addr.data = text;
12061298

12071299
for (i = 0; i < ctx->naddrs; i++) {
1208-
addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
1300+
addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr,
1301+
ur->addrs[i].socklen,
12091302
text, NGX_SOCKADDR_STRLEN, 0);
12101303

12111304
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
@@ -3259,8 +3352,50 @@ ngx_stream_lua_socket_tcp_shutdown(lua_State *L)
32593352
static int
32603353
ngx_stream_lua_socket_tcp_setoption(lua_State *L)
32613354
{
3262-
/* TODO */
3263-
return 0;
3355+
ngx_stream_lua_ctx_t *ctx;
3356+
int n;
3357+
int option;
3358+
3359+
ngx_stream_lua_request_t *r;
3360+
3361+
n = lua_gettop(L);
3362+
3363+
if (n < 2) {
3364+
return luaL_error(L, "ngx.socket setoption: expecting 2 or 3 "
3365+
"arguments (including the object) but seen %d",
3366+
lua_gettop(L));
3367+
}
3368+
3369+
r = ngx_stream_lua_get_req(L);
3370+
if (r == NULL) {
3371+
return luaL_error(L, "no request found");
3372+
}
3373+
3374+
ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_lua_module);
3375+
if (ctx == NULL) {
3376+
return luaL_error(L, "no ctx found");
3377+
}
3378+
3379+
ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT
3380+
| NGX_STREAM_LUA_CONTEXT_TIMER);
3381+
3382+
luaL_checktype(L, 1, LUA_TTABLE);
3383+
3384+
option = luaL_checkint(L, 2);
3385+
3386+
switch (option) {
3387+
#if (NGX_HAVE_TRANSPARENT_PROXY)
3388+
case NGX_STREAM_LUA_SOCKET_OPTION_TRANSPARENT:
3389+
lua_rawseti(L, 1, SOCKET_IP_TRANSPARENT_INDEX);
3390+
lua_pushboolean(L, 1);
3391+
break;
3392+
#endif
3393+
default:
3394+
return luaL_error(L, "invalid tcp socket option: %d", option);
3395+
3396+
}
3397+
3398+
return 1;
32643399
}
32653400

32663401

@@ -4252,7 +4387,8 @@ ngx_stream_lua_socket_tcp_conn_op_resume_handler(ngx_event_t *ev)
42524387

42534388

42544389
static int
4255-
ngx_stream_lua_socket_tcp_conn_op_resume_retval_handler(ngx_stream_lua_request_t *r,
4390+
ngx_stream_lua_socket_tcp_conn_op_resume_retval_handler(
4391+
ngx_stream_lua_request_t *r,
42564392
ngx_stream_lua_socket_tcp_upstream_t *u, lua_State *L)
42574393
{
42584394
int nret;
@@ -5048,7 +5184,9 @@ ngx_stream_lua_req_socket_tcp(lua_State *L)
50485184
raw = 1;
50495185

50505186
r = ngx_stream_lua_get_req(L);
5051-
5187+
if (r == NULL) {
5188+
return luaL_error(L, "no request found");
5189+
}
50525190

50535191
ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_lua_module);
50545192
if (ctx == NULL) {
@@ -5068,8 +5206,6 @@ ngx_stream_lua_req_socket_tcp(lua_State *L)
50685206
return 2;
50695207
}
50705208

5071-
5072-
50735209
dd("ctx acquired raw req socket: %d", ctx->acquired_raw_req_socket);
50745210

50755211
if (ctx->acquired_raw_req_socket) {
@@ -5192,6 +5328,7 @@ ngx_stream_lua_req_socket_rev_handler(ngx_stream_lua_request_t *r)
51925328
u->read_event_handler(r, u);
51935329
}
51945330

5331+
51955332
static int
51965333
ngx_stream_lua_socket_tcp_getreusedtimes(lua_State *L)
51975334
{

src/ngx_stream_lua_socket_tcp.h

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#define NGX_STREAM_LUA_SOCKET_FT_CLIENTABORT 0x0080
3030
#define NGX_STREAM_LUA_SOCKET_FT_SSL 0x0100
3131

32+
#if (NGX_HAVE_TRANSPARENT_PROXY)
33+
#define NGX_STREAM_LUA_SOCKET_OPTION_TRANSPARENT 1
34+
#endif
3235

3336
typedef struct ngx_stream_lua_socket_tcp_upstream_s
3437
ngx_stream_lua_socket_tcp_upstream_t;

0 commit comments

Comments
 (0)