27
27
28
28
29
29
static int ngx_stream_lua_socket_udp (lua_State * L );
30
+ static int ngx_stream_lua_socket_udp_bind (lua_State * L );
30
31
static int ngx_stream_lua_socket_udp_setpeername (lua_State * L );
31
32
static int ngx_stream_lua_socket_udp_send (lua_State * L );
32
33
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,
54
55
ngx_stream_lua_socket_udp_upstream_t * u );
55
56
static void ngx_stream_lua_socket_udp_handle_success (ngx_stream_session_t * s ,
56
57
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 ,
58
59
ngx_stream_lua_udp_connection_t * uc );
59
60
static int ngx_stream_lua_socket_udp_close (lua_State * L );
60
61
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);
65
66
66
67
enum {
67
68
SOCKET_CTX_INDEX = 1 ,
68
- SOCKET_TIMEOUT_INDEX = 2
69
+ SOCKET_TIMEOUT_INDEX = 2 ,
70
+ SOCKET_BIND_INDEX = 3 /* only in upstream cosocket */
69
71
};
70
72
71
73
@@ -84,7 +86,10 @@ ngx_stream_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L)
84
86
85
87
/* udp socket object metatable */
86
88
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 */
88
93
89
94
lua_pushcfunction (L , ngx_stream_lua_socket_udp_setpeername );
90
95
lua_setfield (L , -2 , "setpeername" ); /* ngx socket mt */
@@ -142,7 +147,7 @@ ngx_stream_lua_socket_udp(lua_State *L)
142
147
ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_CONTENT
143
148
| NGX_STREAM_LUA_CONTEXT_TIMER );
144
149
145
- lua_createtable (L , 3 /* narr */ , 1 /* nrec */ );
150
+ lua_createtable (L , 4 /* narr */ , 1 /* nrec */ );
146
151
lua_pushlightuserdata (L , & ngx_stream_lua_socket_udp_metatable_key );
147
152
lua_rawget (L , LUA_REGISTRYINDEX );
148
153
lua_setmetatable (L , -2 );
@@ -153,6 +158,54 @@ ngx_stream_lua_socket_udp(lua_State *L)
153
158
}
154
159
155
160
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
+
156
209
static int
157
210
ngx_stream_lua_socket_udp_setpeername (lua_State * L )
158
211
{
@@ -652,7 +705,7 @@ ngx_stream_lua_socket_resolve_retval_handler(ngx_stream_session_t *s,
652
705
return 2 ;
653
706
}
654
707
655
- rc = ngx_stream_lua_udp_connect (uc );
708
+ rc = ngx_stream_lua_udp_connect (L , uc );
656
709
657
710
if (rc != NGX_OK ) {
658
711
u -> socket_errno = ngx_socket_errno ;
@@ -1318,11 +1371,12 @@ ngx_stream_lua_socket_udp_handle_success(ngx_stream_session_t *s,
1318
1371
1319
1372
1320
1373
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 )
1322
1375
{
1323
1376
int rc ;
1324
1377
ngx_int_t event ;
1325
1378
ngx_event_t * rev , * wev ;
1379
+ ngx_addr_t * local ;
1326
1380
ngx_socket_t s ;
1327
1381
ngx_connection_t * c ;
1328
1382
@@ -1393,6 +1447,20 @@ ngx_stream_lua_udp_connect(ngx_stream_lua_udp_connection_t *uc)
1393
1447
}
1394
1448
#endif
1395
1449
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
+
1396
1464
ngx_log_debug3 (NGX_LOG_DEBUG_EVENT , & uc -> log , 0 ,
1397
1465
"connect to %V, fd:%d #%d" , & uc -> server , s , c -> number );
1398
1466
0 commit comments