@@ -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 (
@@ -198,8 +197,10 @@ enum {
198197 SOCKET_CONNECT_TIMEOUT_INDEX = 2 ,
199198 SOCKET_SEND_TIMEOUT_INDEX = 4 ,
200199 SOCKET_READ_TIMEOUT_INDEX = 5 ,
201- SOCKET_BIND_INDEX = 6 , /* only in upstream cosocket */
202- SOCKET_IP_TRANSPARENT_INDEX = 7
200+ SOCKET_CLIENT_CERT_INDEX = 6 ,
201+ SOCKET_CLIENT_PKEY_INDEX = 7 ,
202+ SOCKET_BIND_INDEX = 8 , /* only in upstream cosocket */
203+ SOCKET_IP_TRANSPARENT_INDEX = 9
203204};
204205
205206
@@ -210,6 +211,14 @@ enum {
210211 SOCKET_OP_RESUME_CONN
211212};
212213
214+ enum {
215+ NGX_STREAM_LUA_SOCKOPT_KEEPALIVE = 1 ,
216+ NGX_STREAM_LUA_SOCKOPT_REUSEADDR ,
217+ NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY ,
218+ NGX_STREAM_LUA_SOCKOPT_SNDBUF ,
219+ NGX_STREAM_LUA_SOCKOPT_RCVBUF ,
220+ };
221+
213222
214223#define ngx_stream_lua_socket_check_busy_connecting (r , u , L ) \
215224 if ((u)->conn_waiting) { \
@@ -253,25 +262,14 @@ static char ngx_stream_lua_pattern_udata_metatable_key;
253262static char ngx_stream_lua_ssl_session_metatable_key ;
254263#endif
255264
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- }
265+ #define ngx_stream_lua_tcp_socket_metatable_literal_key "__tcp_cosocket_mt"
266266
267267
268268void
269269ngx_stream_lua_inject_socket_tcp_api (ngx_log_t * log , lua_State * L )
270270{
271271 ngx_int_t rc ;
272272
273- ngx_stream_lua_inject_socket_option_consts (L );
274-
275273 lua_createtable (L , 0 , 4 /* nrec */ ); /* ngx.socket */
276274
277275 lua_pushcfunction (L , ngx_stream_lua_socket_tcp );
@@ -337,7 +335,7 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
337335 /* {{{tcp object metatable */
338336 lua_pushlightuserdata (L , ngx_stream_lua_lightudata_mask (
339337 tcp_socket_metatable_key ));
340- lua_createtable (L , 0 /* narr */ , 15 /* nrec */ );
338+ lua_createtable (L , 0 /* narr */ , 17 /* nrec */ );
341339
342340 lua_pushcfunction (L , ngx_stream_lua_socket_tcp_bind );
343341 lua_setfield (L , -2 , "bind" );
@@ -367,12 +365,12 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
367365 lua_pushcfunction (L , ngx_stream_lua_socket_tcp_close );
368366 lua_setfield (L , -2 , "close" );
369367
370- lua_pushcfunction (L , ngx_stream_lua_socket_tcp_setoption );
371- lua_setfield (L , -2 , "setoption" );
372-
373368 lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settimeout );
374369 lua_setfield (L , -2 , "settimeout" ); /* ngx socket mt */
375370
371+ lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settransparent );
372+ lua_setfield (L , -2 , "settransparent" ); /* ngx socket mt */
373+
376374 lua_pushcfunction (L , ngx_stream_lua_socket_tcp_settimeouts );
377375 lua_setfield (L , -2 , "settimeouts" ); /* ngx socket mt */
378376
@@ -388,6 +386,12 @@ ngx_stream_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
388386 lua_pushvalue (L , -1 );
389387 lua_setfield (L , -2 , "__index" );
390388 lua_rawset (L , LUA_REGISTRYINDEX );
389+
390+ lua_pushliteral (L , ngx_stream_lua_tcp_socket_metatable_literal_key );
391+ lua_pushlightuserdata (L , ngx_stream_lua_lightudata_mask (
392+ tcp_socket_metatable_key ));
393+ lua_rawget (L , LUA_REGISTRYINDEX );
394+ lua_rawset (L , LUA_REGISTRYINDEX );
391395 /* }}} */
392396
393397 /* {{{upstream userdata metatable */
@@ -903,8 +907,7 @@ ngx_stream_lua_socket_tcp_bind(lua_State *L)
903907 return luaL_error (L , "no ctx found" );
904908 }
905909
906- ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_CONTENT
907- | NGX_STREAM_LUA_CONTEXT_TIMER );
910+ ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_YIELDABLE );
908911
909912 luaL_checktype (L , 1 , LUA_TTABLE );
910913
@@ -1161,7 +1164,7 @@ ngx_stream_lua_socket_tcp_connect(lua_State *L)
11611164#if (NGX_HAVE_TRANSPARENT_PROXY )
11621165 lua_rawgeti (L , 1 , SOCKET_IP_TRANSPARENT_INDEX );
11631166
1164- if (lua_tointeger (L , -1 ) > 0 ) {
1167+ if (lua_toboolean (L , -1 )) {
11651168 pc -> transparent = 1 ;
11661169 ngx_log_debug0 (NGX_LOG_DEBUG_STREAM , r -> connection -> log , 0 ,
11671170 "stream lua set TCP upstream with IP_TRANSPARENT" );
@@ -3349,53 +3352,123 @@ ngx_stream_lua_socket_tcp_shutdown(lua_State *L)
33493352}
33503353
33513354
3352- static int
3353- ngx_stream_lua_socket_tcp_setoption (lua_State * L )
3355+ int
3356+ ngx_stream_lua_ffi_socket_tcp_getoption (ngx_stream_lua_socket_tcp_upstream_t * u ,
3357+ int option , int * val , u_char * err , size_t * errlen )
33543358{
3355- ngx_stream_lua_ctx_t * ctx ;
3356- int n ;
3357- int option ;
3359+ socklen_t len ;
3360+ int fd , rc ;
33583361
3359- ngx_stream_lua_request_t * r ;
3362+ if (u == NULL || u -> peer .connection == NULL ) {
3363+ * errlen = ngx_snprintf (err , * errlen , "closed" ) - err ;
3364+ return NGX_ERROR ;
3365+ }
33603366
3361- n = lua_gettop ( L ) ;
3367+ fd = u -> peer . connection -> fd ;
33623368
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 ));
3369+ if (fd == (int ) -1 ) {
3370+ * errlen = ngx_snprintf (err , * errlen , "invalid socket fd" ) - err ;
3371+ return NGX_ERROR ;
33673372 }
33683373
3369- r = ngx_stream_lua_get_req (L );
3370- if (r == NULL ) {
3371- return luaL_error (L , "no request found" );
3374+ len = sizeof (int );
3375+
3376+ switch (option ) {
3377+ case NGX_STREAM_LUA_SOCKOPT_KEEPALIVE :
3378+ rc = getsockopt (fd , SOL_SOCKET , SO_KEEPALIVE , (void * ) val , & len );
3379+ break ;
3380+
3381+ case NGX_STREAM_LUA_SOCKOPT_REUSEADDR :
3382+ rc = getsockopt (fd , SOL_SOCKET , SO_REUSEADDR , (void * ) val , & len );
3383+ break ;
3384+
3385+ case NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY :
3386+ rc = getsockopt (fd , IPPROTO_TCP , TCP_NODELAY , (void * ) val , & len );
3387+ break ;
3388+
3389+ case NGX_STREAM_LUA_SOCKOPT_SNDBUF :
3390+ rc = getsockopt (fd , SOL_SOCKET , SO_RCVBUF , (void * ) val , & len );
3391+ break ;
3392+
3393+ case NGX_STREAM_LUA_SOCKOPT_RCVBUF :
3394+ rc = getsockopt (fd , SOL_SOCKET , SO_SNDBUF , (void * ) val , & len );
3395+ break ;
3396+
3397+ default :
3398+ * errlen = ngx_snprintf (err , * errlen , "unsupported option %d" , option )
3399+ - err ;
3400+ return NGX_ERROR ;
33723401 }
33733402
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- }
3403+ if ( rc == -1 ) {
3404+ * errlen = ngx_strerror ( ngx_errno , err , NGX_MAX_ERROR_STR ) - err ;
3405+ return NGX_ERROR ;
3406+ }
33783407
3379- ngx_stream_lua_check_context ( L , ctx , NGX_STREAM_LUA_CONTEXT_CONTENT
3380- | NGX_STREAM_LUA_CONTEXT_TIMER );
3408+ return NGX_OK ;
3409+ }
33813410
3382- luaL_checktype (L , 1 , LUA_TTABLE );
33833411
3384- option = luaL_checkint (L , 2 );
3412+ int
3413+ ngx_stream_lua_ffi_socket_tcp_setoption (
3414+ ngx_stream_lua_socket_tcp_upstream_t * u ,
3415+ int option , int val , u_char * err , size_t * errlen )
3416+ {
3417+ socklen_t len ;
3418+ int fd , rc ;
33853419
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 );
3420+ if (u == NULL || u -> peer .connection == NULL ) {
3421+ * errlen = ngx_snprintf (err , * errlen , "closed" ) - err ;
3422+ return NGX_ERROR ;
3423+ }
3424+
3425+ fd = u -> peer .connection -> fd ;
33953426
3427+ if (fd == (int ) -1 ) {
3428+ * errlen = ngx_snprintf (err , * errlen , "invalid socket fd" ) - err ;
3429+ return NGX_ERROR ;
33963430 }
33973431
3398- return 1 ;
3432+ len = sizeof (int );
3433+
3434+ switch (option ) {
3435+ case NGX_STREAM_LUA_SOCKOPT_KEEPALIVE :
3436+ rc = setsockopt (fd , SOL_SOCKET , SO_KEEPALIVE ,
3437+ (const void * ) & val , len );
3438+ break ;
3439+
3440+ case NGX_STREAM_LUA_SOCKOPT_REUSEADDR :
3441+ rc = setsockopt (fd , SOL_SOCKET , SO_REUSEADDR ,
3442+ (const void * ) & val , len );
3443+ break ;
3444+
3445+ case NGX_STREAM_LUA_SOCKOPT_TCP_NODELAY :
3446+ rc = setsockopt (fd , IPPROTO_TCP , TCP_NODELAY ,
3447+ (const void * ) & val , len );
3448+ break ;
3449+
3450+ case NGX_STREAM_LUA_SOCKOPT_SNDBUF :
3451+ rc = setsockopt (fd , SOL_SOCKET , SO_RCVBUF ,
3452+ (const void * ) & val , len );
3453+ break ;
3454+
3455+ case NGX_STREAM_LUA_SOCKOPT_RCVBUF :
3456+ rc = setsockopt (fd , SOL_SOCKET , SO_SNDBUF ,
3457+ (const void * ) & val , len );
3458+ break ;
3459+
3460+ default :
3461+ * errlen = ngx_snprintf (err , * errlen , "unsupported option: %d" , option )
3462+ - err ;
3463+ return NGX_ERROR ;
3464+ }
3465+
3466+ if (rc == -1 ) {
3467+ * errlen = ngx_strerror (ngx_errno , err , NGX_MAX_ERROR_STR ) - err ;
3468+ return NGX_ERROR ;
3469+ }
3470+
3471+ return NGX_OK ;
33993472}
34003473
34013474
@@ -3510,6 +3583,43 @@ ngx_stream_lua_socket_tcp_settimeouts(lua_State *L)
35103583}
35113584
35123585
3586+ static int
3587+ ngx_stream_lua_socket_tcp_settransparent (lua_State * L )
3588+ {
3589+ ngx_stream_lua_ctx_t * ctx ;
3590+ int n ;
3591+
3592+ ngx_stream_lua_request_t * r ;
3593+
3594+ n = lua_gettop (L );
3595+
3596+ if (n != 1 ) {
3597+ return luaL_error (L , "ngx.socket settransparent: expecting 1"
3598+ "argument (including the object) but seen %d" ,
3599+ lua_gettop (L ));
3600+ }
3601+
3602+ r = ngx_stream_lua_get_req (L );
3603+ if (r == NULL ) {
3604+ return luaL_error (L , "no request found" );
3605+ }
3606+
3607+ ctx = ngx_stream_lua_get_module_ctx (r , ngx_stream_lua_module );
3608+ if (ctx == NULL ) {
3609+ return luaL_error (L , "no ctx found" );
3610+ }
3611+
3612+ ngx_stream_lua_check_context (L , ctx , NGX_STREAM_LUA_CONTEXT_YIELDABLE );
3613+
3614+ luaL_checktype (L , 1 , LUA_TTABLE );
3615+
3616+ lua_rawseti (L , 1 , SOCKET_IP_TRANSPARENT_INDEX );
3617+ lua_pushboolean (L , 1 );
3618+
3619+ return 1 ;
3620+ }
3621+
3622+
35133623static void
35143624ngx_stream_lua_socket_tcp_handler (ngx_event_t * ev )
35153625{
0 commit comments