2828
2929
3030static int ngx_stream_lua_socket_tcp (lua_State * L );
31+ static int ngx_stream_lua_socket_tcp_bind (lua_State * L );
3132static int ngx_stream_lua_socket_tcp_connect (lua_State * L );
3233#if (NGX_STREAM_SSL )
3334static 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);
183184static int ngx_stream_lua_ssl_free_session (lua_State * L );
184185#endif
185186static 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
187189static 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 );
189192static 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+
252268void
253269ngx_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
458479static void
459480ngx_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+
857928static int
858929ngx_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)
32593352static int
32603353ngx_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
42544389static 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+
51955332static int
51965333ngx_stream_lua_socket_tcp_getreusedtimes (lua_State * L )
51975334{
0 commit comments