@@ -37,9 +37,9 @@ static int ngx_stream_lua_socket_tcp_receive(lua_State *L);
3737static  int  ngx_stream_lua_socket_tcp_receiveany (lua_State  * L );
3838static  int  ngx_stream_lua_socket_tcp_send (lua_State  * L );
3939static  int  ngx_stream_lua_socket_tcp_close (lua_State  * L );
40- static  int  ngx_stream_lua_socket_tcp_setoption (lua_State  * L );
4140static  int  ngx_stream_lua_socket_tcp_settimeout (lua_State  * L );
4241static  int  ngx_stream_lua_socket_tcp_settimeouts (lua_State  * L );
42+ static  int  ngx_stream_lua_socket_tcp_settransparent (lua_State  * L );
4343static  void  ngx_stream_lua_socket_tcp_handler (ngx_event_t  * ev );
4444static  ngx_int_t  ngx_stream_lua_socket_tcp_get_peer (ngx_peer_connection_t  * pc ,
4545    void  * data );
@@ -184,7 +184,6 @@ static void ngx_stream_lua_ssl_handshake_handler(ngx_connection_t *c);
184184static  int  ngx_stream_lua_ssl_free_session (lua_State  * L );
185185#endif 
186186static  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 );
188187
189188static  int  ngx_stream_lua_socket_tcp_peek (lua_State  * L );
190189static  ngx_int_t  ngx_stream_lua_socket_tcp_peek_resume (
@@ -210,6 +209,14 @@ enum {
210209    SOCKET_OP_RESUME_CONN 
211210};
212211
212+ enum  {
213+     NGX_STREAM_LUA_SOCKOPT_KEEPALIVE  =  1 ,
214+     NGX_STREAM_LUA_SOCKOPT_REUSEADDR ,
215+     NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY ,
216+     NGX_STREAM_LUA_SOCKOPT_SNDBUF ,
217+     NGX_STREAM_LUA_SOCKOPT_RCVBUF ,
218+ };
219+ 
213220
214221#define  ngx_stream_lua_socket_check_busy_connecting (r , u , L )                 \
215222    if ((u)->conn_waiting) {                                                 \
@@ -253,25 +260,14 @@ static char ngx_stream_lua_pattern_udata_metatable_key;
253260static  char  ngx_stream_lua_ssl_session_metatable_key ;
254261#endif 
255262
256- 
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- }
263+ #define  ngx_stream_lua_tcp_socket_metatable_literal_key   "__tcp_cosocket_mt"
266264
267265
268266void 
269267ngx_stream_lua_inject_socket_tcp_api (ngx_log_t  * log , lua_State  * L )
270268{
271269    ngx_int_t          rc ;
272270
273-     ngx_stream_lua_inject_socket_option_consts (L );
274- 
275271    lua_createtable (L , 0 , 4  /* nrec */ );    /* ngx.socket */ 
276272
277273    lua_pushcfunction (L , ngx_stream_lua_socket_tcp );
@@ -337,7 +333,7 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
337333    /* {{{tcp object metatable */ 
338334    lua_pushlightuserdata (L , ngx_stream_lua_lightudata_mask (
339335                          tcp_socket_metatable_key ));
340-     lua_createtable (L , 0  /* narr */ , 15  /* nrec */ );
336+     lua_createtable (L , 0  /* narr */ , 17  /* nrec */ );
341337
342338    lua_pushcfunction (L , ngx_stream_lua_socket_tcp_bind );
343339    lua_setfield (L , -2 , "bind" );
@@ -367,12 +363,12 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
367363    lua_pushcfunction (L , ngx_stream_lua_socket_tcp_close );
368364    lua_setfield (L , -2 , "close" );
369365
370-     lua_pushcfunction (L , ngx_stream_lua_socket_tcp_setoption );
371-     lua_setfield (L , -2 , "setoption" );
372- 
373366    lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settimeout );
374367    lua_setfield (L , -2 , "settimeout" ); /* ngx socket mt */ 
375368
369+     lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settransparent );
370+     lua_setfield (L , -2 , "settransparent" ); /* ngx socket mt */ 
371+ 
376372    lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settimeouts );
377373    lua_setfield (L , -2 , "settimeouts" ); /* ngx socket mt */ 
378374
@@ -388,6 +384,12 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
388384    lua_pushvalue (L , -1 );
389385    lua_setfield (L , -2 , "__index" );
390386    lua_rawset (L , LUA_REGISTRYINDEX );
387+ 
388+     lua_pushliteral (L , ngx_stream_lua_tcp_socket_metatable_literal_key );
389+     lua_pushlightuserdata (L , ngx_stream_lua_lightudata_mask (
390+                           tcp_socket_metatable_key ));
391+     lua_rawget (L , LUA_REGISTRYINDEX );
392+     lua_rawset (L , LUA_REGISTRYINDEX );
391393    /* }}} */ 
392394
393395    /* {{{upstream userdata metatable */ 
@@ -903,8 +905,7 @@ ngx_stream_lua_socket_tcp_bind(lua_State *L)
903905        return  luaL_error (L , "no ctx found" );
904906    }
905907
906-     ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_CONTENT 
907-                                  | NGX_STREAM_LUA_CONTEXT_TIMER );
908+     ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_YIELDABLE );
908909
909910    luaL_checktype (L , 1 , LUA_TTABLE );
910911
@@ -1161,7 +1162,7 @@ ngx_stream_lua_socket_tcp_connect(lua_State *L)
11611162#if  (NGX_HAVE_TRANSPARENT_PROXY )
11621163    lua_rawgeti (L , 1 , SOCKET_IP_TRANSPARENT_INDEX );
11631164
1164-     if  (lua_tointeger (L , -1 )  >   0 ) {
1165+     if  (lua_toboolean (L , -1 )) {
11651166        pc -> transparent  =  1 ;
11661167        ngx_log_debug0 (NGX_LOG_DEBUG_STREAM , r -> connection -> log , 0 ,
11671168                       "stream lua set TCP upstream with IP_TRANSPARENT" );
@@ -3349,53 +3350,123 @@ ngx_stream_lua_socket_tcp_shutdown(lua_State *L)
33493350}
33503351
33513352
3352- static  int 
3353- ngx_stream_lua_socket_tcp_setoption (lua_State  * L )
3353+ int 
3354+ ngx_stream_lua_ffi_socket_tcp_getoption (ngx_stream_lua_socket_tcp_upstream_t  * u ,
3355+     int  option , int  * val , u_char  * err , size_t  * errlen )
33543356{
3355-     ngx_stream_lua_ctx_t    * ctx ;
3356-     int                      n ;
3357-     int                      option ;
3357+     socklen_t  len ;
3358+     int        fd , rc ;
33583359
3359-     ngx_stream_lua_request_t   * r ;
3360+     if  (u  ==  NULL  ||  u -> peer .connection  ==  NULL ) {
3361+         * errlen  =  ngx_snprintf (err , * errlen , "closed" ) -  err ;
3362+         return  NGX_ERROR ;
3363+     }
33603364
3361-     n  =  lua_gettop ( L ) ;
3365+     fd  =  u -> peer . connection -> fd ;
33623366
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+     if  (fd  ==  (int ) -1 ) {
3368+         * errlen  =  ngx_snprintf (err , * errlen , "invalid socket fd" ) -  err ;
3369+         return  NGX_ERROR ;
33673370    }
33683371
3369-     r  =  ngx_stream_lua_get_req (L );
3370-     if  (r  ==  NULL ) {
3371-         return  luaL_error (L , "no request found" );
3372+     len  =  sizeof (int );
3373+ 
3374+     switch  (option ) {
3375+     case  NGX_STREAM_LUA_SOCKOPT_KEEPALIVE :
3376+         rc  =  getsockopt (fd , SOL_SOCKET , SO_KEEPALIVE , (void  * ) val , & len );
3377+         break ;
3378+ 
3379+     case  NGX_STREAM_LUA_SOCKOPT_REUSEADDR :
3380+         rc  =  getsockopt (fd , SOL_SOCKET , SO_REUSEADDR , (void  * ) val , & len );
3381+         break ;
3382+ 
3383+     case  NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY :
3384+         rc  =  getsockopt (fd , IPPROTO_TCP , TCP_NODELAY , (void  * ) val , & len );
3385+         break ;
3386+ 
3387+     case  NGX_STREAM_LUA_SOCKOPT_SNDBUF :
3388+         rc  =  getsockopt (fd , SOL_SOCKET , SO_RCVBUF , (void  * ) val , & len );
3389+         break ;
3390+ 
3391+     case  NGX_STREAM_LUA_SOCKOPT_RCVBUF :
3392+         rc  =  getsockopt (fd , SOL_SOCKET , SO_SNDBUF , (void  * ) val , & len );
3393+         break ;
3394+ 
3395+     default :
3396+         * errlen  =  ngx_snprintf (err , * errlen , "unsupported option %d" , option )
3397+                   -  err ;
3398+         return  NGX_ERROR ;
33723399    }
33733400
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-       }
3401+     if  ( rc   ==   -1 ) { 
3402+          * errlen   =   ngx_strerror ( ngx_errno ,  err ,  NGX_MAX_ERROR_STR )  -   err ; 
3403+         return  NGX_ERROR ;
3404+     }
33783405
3379-       ngx_stream_lua_check_context ( L ,  ctx ,  NGX_STREAM_LUA_CONTEXT_CONTENT 
3380-                                   |  NGX_STREAM_LUA_CONTEXT_TIMER ); 
3406+     return   NGX_OK ; 
3407+ } 
33813408
3382-      luaL_checktype (L , 1 , LUA_TTABLE );
33833409
3384-      option  =  luaL_checkint (L , 2 );
3410+ int 
3411+ ngx_stream_lua_ffi_socket_tcp_setoption (
3412+     ngx_stream_lua_socket_tcp_upstream_t  * u ,
3413+     int  option , int  val , u_char  * err , size_t  * errlen )
3414+ {
3415+     socklen_t  len ;
3416+     int        fd , rc ;
33853417
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 );
3418+     if  (u  ==  NULL  ||  u -> peer .connection  ==  NULL ) {
3419+         * errlen  =  ngx_snprintf (err , * errlen , "closed" ) -  err ;
3420+         return  NGX_ERROR ;
3421+     }
3422+ 
3423+     fd  =  u -> peer .connection -> fd ;
33953424
3425+     if  (fd  ==  (int ) -1 ) {
3426+         * errlen  =  ngx_snprintf (err , * errlen , "invalid socket fd" ) -  err ;
3427+         return  NGX_ERROR ;
33963428    }
33973429
3398-     return  1 ;
3430+     len  =  sizeof (int );
3431+ 
3432+     switch  (option ) {
3433+     case  NGX_STREAM_LUA_SOCKOPT_KEEPALIVE :
3434+         rc  =  setsockopt (fd , SOL_SOCKET , SO_KEEPALIVE ,
3435+                         (const  void  * ) & val , len );
3436+         break ;
3437+ 
3438+     case  NGX_STREAM_LUA_SOCKOPT_REUSEADDR :
3439+         rc  =  setsockopt (fd , SOL_SOCKET , SO_REUSEADDR ,
3440+                         (const  void  * ) & val , len );
3441+         break ;
3442+ 
3443+     case  NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY :
3444+         rc  =  setsockopt (fd , IPPROTO_TCP , TCP_NODELAY ,
3445+                         (const  void  * ) & val , len );
3446+         break ;
3447+ 
3448+     case  NGX_STREAM_LUA_SOCKOPT_SNDBUF :
3449+         rc  =  setsockopt (fd , SOL_SOCKET , SO_RCVBUF ,
3450+                         (const  void  * ) & val , len );
3451+         break ;
3452+ 
3453+     case  NGX_STREAM_LUA_SOCKOPT_RCVBUF :
3454+         rc  =  setsockopt (fd , SOL_SOCKET , SO_SNDBUF ,
3455+                         (const  void  * ) & val , len );
3456+         break ;
3457+ 
3458+     default :
3459+         * errlen  =  ngx_snprintf (err , * errlen , "unsupported option: %d" , option )
3460+                   -  err ;
3461+         return  NGX_ERROR ;
3462+     }
3463+ 
3464+     if  (rc  ==  -1 ) {
3465+         * errlen  =  ngx_strerror (ngx_errno , err , NGX_MAX_ERROR_STR ) -  err ;
3466+         return  NGX_ERROR ;
3467+     }
3468+ 
3469+     return  NGX_OK ;
33993470}
34003471
34013472
@@ -3510,6 +3581,43 @@ ngx_stream_lua_socket_tcp_settimeouts(lua_State *L)
35103581}
35113582
35123583
3584+ static  int 
3585+ ngx_stream_lua_socket_tcp_settransparent (lua_State  * L )
3586+ {
3587+     ngx_stream_lua_ctx_t    * ctx ;
3588+     int                      n ;
3589+ 
3590+     ngx_stream_lua_request_t   * r ;
3591+ 
3592+     n  =  lua_gettop (L );
3593+ 
3594+     if  (n  !=  1 ) {
3595+         return  luaL_error (L , "ngx.socket settransparent: expecting 1" 
3596+                           "argument (including the object) but seen %d" ,
3597+                           lua_gettop (L ));
3598+     }
3599+ 
3600+     r  =  ngx_stream_lua_get_req (L );
3601+     if  (r  ==  NULL ) {
3602+         return  luaL_error (L , "no request found" );
3603+     }
3604+ 
3605+     ctx  =  ngx_stream_lua_get_module_ctx (r , ngx_stream_lua_module );
3606+     if  (ctx  ==  NULL ) {
3607+         return  luaL_error (L , "no ctx found" );
3608+     }
3609+ 
3610+     ngx_stream_lua_check_context (L , ctx ,  NGX_STREAM_LUA_CONTEXT_YIELDABLE );
3611+ 
3612+     luaL_checktype (L , 1 , LUA_TTABLE );
3613+ 
3614+     lua_rawseti (L , 1 , SOCKET_IP_TRANSPARENT_INDEX );
3615+     lua_pushboolean (L , 1 );
3616+ 
3617+     return  1 ;
3618+ }
3619+ 
3620+ 
35133621static  void 
35143622ngx_stream_lua_socket_tcp_handler (ngx_event_t  * ev )
35153623{
0 commit comments