From 50d8b24cdb8a1171ea9e0ac8c0e54a9e96949b17 Mon Sep 17 00:00:00 2001 From: humboldt_xie Date: Tue, 26 Feb 2013 21:44:27 +0800 Subject: [PATCH 01/22] add req socket send function connect function suport 4 args ( add the custom pool) --- src/ngx_tcp_lua_common.h | 1 - src/ngx_tcp_lua_module.c | 2 +- src/ngx_tcp_lua_output.c | 13 ++- src/ngx_tcp_lua_output.h | 1 + src/ngx_tcp_lua_socket.c | 188 ++++++++++++++++++++++++++++++++++++--- src/ngx_tcp_lua_util.c | 2 +- src/ngx_tcp_session.h | 1 - 7 files changed, 183 insertions(+), 25 deletions(-) diff --git a/src/ngx_tcp_lua_common.h b/src/ngx_tcp_lua_common.h index 9782037..18e32e3 100755 --- a/src/ngx_tcp_lua_common.h +++ b/src/ngx_tcp_lua_common.h @@ -67,7 +67,6 @@ typedef struct ngx_tcp_lua_srv_conf_s { } ngx_tcp_lua_srv_conf_t; -typedef void (*ngx_tcp_cleanup_pt)(void *data); typedef struct ngx_tcp_lua_ctx_s { diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 8c0eca9..bf66d63 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -228,7 +228,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) rc = ngx_tcp_lua_process_by_chunk(L, s); - if (rc == NGX_DONE || rc == NGX_OK) { + if (rc == NGX_DONE || rc == NGX_OK || rc == NGX_ERROR) { ngx_tcp_finalize_session(s); return; } diff --git a/src/ngx_tcp_lua_output.c b/src/ngx_tcp_lua_output.c index bc3b678..ba88f73 100755 --- a/src/ngx_tcp_lua_output.c +++ b/src/ngx_tcp_lua_output.c @@ -5,14 +5,13 @@ static int ngx_tcp_lua_ngx_print(lua_State *L); -static int ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline); static int ngx_tcp_lua_ngx_print(lua_State *L) { dd("calling lua print"); - return ngx_tcp_lua_ngx_echo(L, 0); + return ngx_tcp_lua_ngx_echo(L, 0,1); } @@ -20,12 +19,12 @@ static int ngx_tcp_lua_ngx_say(lua_State *L) { dd("calling"); - return ngx_tcp_lua_ngx_echo(L, 1); + return ngx_tcp_lua_ngx_echo(L, 1,1); } -static int -ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline) +int +ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline,unsigned start) { ngx_tcp_session_t *s; ngx_tcp_lua_ctx_t *ctx; @@ -63,7 +62,7 @@ ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline) nargs = lua_gettop(L); size = 0; - for (i = 1; i <= nargs; i++) { + for (i = start; i <= nargs; i++) { type = lua_type(L, i); @@ -131,7 +130,7 @@ ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline) return luaL_error(L, "out of memory"); } - for (i = 1; i <= nargs; i++) { + for (i = start; i <= nargs; i++) { type = lua_type(L, i); switch (type) { case LUA_TNUMBER: diff --git a/src/ngx_tcp_lua_output.h b/src/ngx_tcp_lua_output.h index 48d3dd3..00376f1 100644 --- a/src/ngx_tcp_lua_output.h +++ b/src/ngx_tcp_lua_output.h @@ -6,6 +6,7 @@ void ngx_tcp_lua_inject_output_api(lua_State *L); size_t ngx_tcp_lua_calc_strlen_in_table(lua_State *L, int arg_i, unsigned strict); u_char *ngx_tcp_lua_copy_str_in_table(lua_State *L, u_char *dst); +int ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline,unsigned start); #endif diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 7c93ef2..e0d7b10 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -12,6 +12,7 @@ #define NGX_TCP_LUA_SOCKET_FT_BUFTOOSMALL 0x0010 #define NGX_TCP_LUA_SOCKET_FT_NOMEM 0x0020 +extern int ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline,unsigned start); enum { SOCKET_CTX_INDEX = 1, SOCKET_TIMEOUT_INDEX = 2, @@ -37,10 +38,8 @@ static ngx_int_t ngx_tcp_lua_socket_read_all(void *data, ssize_t bytes); static ngx_int_t ngx_tcp_lua_socket_read_line(void *data, ssize_t bytes); static ngx_int_t ngx_tcp_lua_socket_read(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u); -static int -ngx_tcp_lua_socket_tcp_send(lua_State *L); -static int -ngx_tcp_lua_socket_tcp_send_retval_handler(ngx_tcp_session_t *s, +static int ngx_tcp_lua_socket_tcp_send(lua_State *L); +static int ngx_tcp_lua_socket_tcp_send_retval_handler(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u, lua_State *L); static int ngx_tcp_lua_socket_tcp_close(lua_State *L); static int ngx_tcp_lua_socket_tcp_setoption(lua_State *L); @@ -73,6 +72,7 @@ static ngx_int_t ngx_tcp_lua_socket_compile_pattern(u_char *data, size_t len, static ngx_int_t ngx_tcp_lua_socket_read_until(void *data, ssize_t bytes); static int ngx_tcp_lua_socket_cleanup_compiled_pattern(lua_State *L); static int ngx_tcp_lua_req_socket(lua_State *L); +static int ngx_tcp_lua_req_socket_tcp_send(lua_State *L); static void ngx_tcp_lua_req_socket_rev_handler(ngx_tcp_session_t *s); static int ngx_tcp_lua_socket_downstream_destroy(lua_State *L); static void ngx_tcp_lua_req_socket_cleanup(void *data); @@ -137,6 +137,9 @@ ngx_tcp_lua_inject_socket_api(ngx_log_t *log, lua_State *L) lua_pushcfunction(L, ngx_tcp_lua_socket_tcp_receiveuntil); lua_setfield(L, -2, "receiveuntil"); + lua_pushcfunction(L, ngx_tcp_lua_req_socket_tcp_send); + lua_setfield(L, -2, "send"); + lua_pushcfunction(L, ngx_tcp_lua_socket_tcp_settimeout); lua_setfield(L, -2, "settimeout"); /* ngx socket mt */ @@ -196,6 +199,117 @@ ngx_tcp_lua_inject_req_socket_api(lua_State *L) } +static int +ngx_tcp_lua_req_socket_tcp_send(lua_State *L) +{ + ngx_tcp_session_t *s; + ngx_tcp_lua_ctx_t *ctx; + const char *p; + size_t len; + size_t size; + ngx_buf_t *b; + ngx_chain_t *cl, *chain; + int i; + int nargs; + int type; + const char *msg; + //ngx_buf_tag_t tag; + if (lua_gettop(L) != 2) { + return luaL_error(L, "expecting 2 arguments (including the object), " + "but got %d", lua_gettop(L)); + } + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + s = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (s == NULL) { + return luaL_error(L, "no request object found"); + } + + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); + + if (ctx == NULL) { + return luaL_error(L, "no request ctx found"); + } + +/* + if (ctx->eof) { + return luaL_error(L, "seen eof already"); + } +*/ + size = 0; + type = lua_type(L, 2); + switch (type) { + case LUA_TNUMBER: + case LUA_TSTRING: + lua_tolstring(L, 2, &size); + break; + + case LUA_TTABLE: + size = ngx_tcp_lua_calc_strlen_in_table(L, 2, 1 /* strict */); + break; + + default: + msg = lua_pushfstring(L, "string, number, boolean, nil, " + "or array table expected, got %s", + lua_typename(L, type)); + + return luaL_argerror(L, 2, msg); + } + + if (size == 0) { + /* do nothing for empty strings */ + return 0; + } + + b = ngx_create_temp_buf(s->pool, size); + if (b == NULL) { + return luaL_error(L, "out of memory"); + } + + switch (type) { + case LUA_TNUMBER: + case LUA_TSTRING: + p = (u_char *) lua_tolstring(L, -1, &size); + b->last = ngx_copy(b->last, (u_char *) p, size); + break; + + case LUA_TTABLE: + b->last = ngx_tcp_lua_copy_str_in_table(L, b->last); + break; + default: + return luaL_error(L, "impossible to reach here"); + } + +#if 0 + if (b->last != b->end) { + return luaL_error(L, "buffer error: %p != %p", b->last, b->end); + } +#endif + + cl = ngx_alloc_chain_link(s->pool); + if (cl == NULL) { + return luaL_error(L, "out of memory"); + } + + cl->next = NULL; + cl->buf = b; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + newline ? "lua say response" : "lua print response"); + + chain = s->connection->send_chain(s->connection, cl, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "tcp_lua write chain %p", chain); + + lua_pushinteger(L, size); + return 1; +} + + static int ngx_tcp_lua_socket_tcp(lua_State *L) { @@ -250,13 +364,16 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) ngx_tcp_lua_srv_conf_t *lscf; ngx_peer_connection_t *pc; int timeout; + unsigned custom_pool; + int key_index; + const char *msg; ngx_tcp_lua_socket_upstream_t *u; n = lua_gettop(L); - if (n != 2 && n != 3) { - return luaL_error(L, "ngx.socket connect: expecting 2 or 3 arguments " - "(including the object), but seen %d", n); + if (n != 2 && n != 3 && n != 4) { + return luaL_error(L, "ngx.socket connect: expecting 2, 3, or 4 " + "arguments (including the object), but seen %d", n); } lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); @@ -287,6 +404,39 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) ngx_memcpy(host.data, p, len); host.data[len] = '\0'; + key_index = 2; + custom_pool = 0; + + if (lua_type(L, n) == LUA_TTABLE) { + + /* found the last optional option table */ + + lua_getfield(L, n, "pool"); + + switch (lua_type(L, -1)) { + case LUA_TNUMBER: + lua_tostring(L, -1); + + case LUA_TSTRING: + custom_pool = 1; + + lua_pushvalue(L, -1); + lua_rawseti(L, 1, SOCKET_KEY_INDEX); + + key_index = n + 1; + + break; + + default: + msg = lua_pushfstring(L, "bad \"pool\" option type: %s", + luaL_typename(L, -1)); + luaL_argerror(L, n, msg); + break; + } + + n--; + } + if (n == 3) { port = luaL_checkinteger(L, 3); @@ -296,9 +446,11 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) return 2; } - lua_pushliteral(L, ":"); - lua_insert(L, 3); - lua_concat(L, 3); + if (!custom_pool) { + lua_pushliteral(L, ":"); + lua_insert(L, 3); + lua_concat(L, 3); + } dd("socket key: %s", lua_tostring(L, -1)); @@ -306,16 +458,24 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) port = 0; } - /* the key's index is 2 */ + if (!custom_pool) { + /* the key's index is 2 */ - lua_pushvalue(L, -1); - lua_rawseti(L, 1, SOCKET_KEY_INDEX); + lua_pushvalue(L, 2); + lua_rawseti(L, 1, SOCKET_KEY_INDEX); + } lua_rawgeti(L, 1, SOCKET_CTX_INDEX); u = lua_touserdata(L, -1); lua_pop(L, 1); if (u) { + if (u->waiting) { + lua_pushnil(L); + lua_pushliteral(L, "socket busy"); + return 2; + } + if (u->is_downstream) { return luaL_error(L, "attempt to re-connect a request socket"); } @@ -377,7 +537,7 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) s->connection->single_connection = 0; - rc = ngx_tcp_lua_get_keepalive_peer(s, L, 2, u); + rc = ngx_tcp_lua_get_keepalive_peer(s, L, key_index, u); if (rc == NGX_OK) { lua_pushinteger(L, 1); diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 22949e9..9f1e28b 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -510,7 +510,7 @@ ngx_tcp_lua_wev_handler(ngx_tcp_session_t *s) return; } - if (rc == NGX_DONE || rc == NGX_OK) { + if (rc == NGX_DONE || rc == NGX_OK || rc==NGX_ERROR) { ngx_tcp_finalize_session(s); return; } diff --git a/src/ngx_tcp_session.h b/src/ngx_tcp_session.h index a422881..8bc994d 100755 --- a/src/ngx_tcp_session.h +++ b/src/ngx_tcp_session.h @@ -48,7 +48,6 @@ struct ngx_tcp_session_s { typedef void (*ngx_tcp_cleanup_pt)(void *data); - struct ngx_tcp_cleanup_s { ngx_tcp_cleanup_pt handler; void *data; From cda2e3e865e38966ee66a033ec8c72774bf671cd Mon Sep 17 00:00:00 2001 From: humboldt Date: Mon, 11 Mar 2013 19:29:48 +0800 Subject: [PATCH 02/22] add shared --- src/ngx_tcp.c | 6 ++++- src/ngx_tcp.h | 2 +- src/ngx_tcp_core_module.c | 55 ++++++++++++++++++++++++++++++++++++++- src/ngx_tcp_lua_module.c | 11 ++++++-- src/ngx_tcp_lua_util.c | 9 +++++++ 5 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index fd10c03..019e5f5 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -610,8 +610,11 @@ static ngx_listening_t * ngx_tcp_add_listening(ngx_conf_t *cf, ngx_tcp_conf_addr_t *addr) { ngx_listening_t *ls; - //ngx_tcp_core_srv_conf_t *cscf; + ngx_tcp_core_srv_conf_t *cscf; + //cscf=ngx_tcp_conf_get_module_srv_conf(cf, ngx_tcp_core_module); + cscf=ngx_tcp_get_module_srv_conf(addr->ctx,ngx_tcp_core_module); + ls = ngx_create_listening(cf, addr->sockaddr, addr->socklen); if (ls == NULL) { return NULL; @@ -624,6 +627,7 @@ ngx_tcp_add_listening(ngx_conf_t *cf, ngx_tcp_conf_addr_t *addr) ls->pool_size = 256; //cscf->connection_pool_size; ls->post_accept_timeout = 10000; //cscf->client_header_timeout; + /*ls->logp = cscf->error_log; &cf->cycle->new_log*/ ls->logp = &cf->cycle->new_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; diff --git a/src/ngx_tcp.h b/src/ngx_tcp.h index d2acaf8..76784aa 100755 --- a/src/ngx_tcp.h +++ b/src/ngx_tcp.h @@ -186,7 +186,7 @@ struct ngx_tcp_core_srv_conf_s { /* server ctx */ ngx_tcp_conf_ctx_t *ctx; - + off_t directio_alignment; /* directio_alignment */ size_t client_body_buffer_size; /* client_body_buffer_size */ diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 69a140d..4588ef8 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -26,6 +26,8 @@ static char *ngx_tcp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_tcp_log_set_access_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +/*static char *ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf);*/ static ngx_command_t ngx_tcp_core_commands[] = { @@ -131,6 +133,13 @@ static ngx_command_t ngx_tcp_core_commands[] = { 0, NULL }, + /*{ ngx_string("error_log"), + NGX_TCP_MAIN_CONF|NGX_TCP_SRV_CONF|NGX_CONF_1MORE, + ngx_tcp_core_error_log, + NGX_TCP_SRV_CONF_OFFSET, + 0, + NULL },*/ + { ngx_string("directio_alignment"), NGX_TCP_MAIN_CONF|NGX_TCP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_off_slot, @@ -230,7 +239,6 @@ ngx_tcp_core_create_srv_conf(ngx_conf_t *cf) * * cscf->protocol = NULL; */ - if (ngx_array_init(&cscf->server_names, cf->pool, 4, sizeof(ngx_tcp_server_name_t)) != NGX_OK) @@ -329,6 +337,15 @@ ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) conf->rules = prev->rules; } + /*if (conf->error_log == NULL) { + if (prev->error_log) { + conf->error_log = prev->error_log; + } else { + conf->error_log = &cf->cycle->new_log; + } + }*/ + + if (lscf->open_file_cache == NGX_CONF_UNSET_PTR) { lscf->open_file_cache = plscf->open_file_cache; @@ -890,3 +907,39 @@ ngx_tcp_log_set_access_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +/*static char * +ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_tcp_core_srv_conf_t *clcf = conf; + + ngx_str_t *value, name; + + return NGX_CONF_OK; + + if (clcf->error_log) { + return "is duplicate"; + } + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "stderr") == 0) { + ngx_str_null(&name); + + } else { + name = value[1]; + } + + clcf->error_log = ngx_log_create(cf->cycle, &name); + if (clcf->error_log == NULL) { + return NGX_CONF_ERROR; + } + + if (cf->args->nelts == 2) { + clcf->error_log->log_level = NGX_LOG_ERR; + return NGX_CONF_OK; + } + + return ngx_log_set_levels(cf, clcf->error_log); +}*/ diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index bf66d63..4954006 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -1,4 +1,5 @@ +#include "lua_module/ngx_http_lua_directive.h" #include "ngx_tcp_lua_common.h" #include "ngx_tcp_lua_cache.h" #include "ngx_tcp_lua_util.h" @@ -26,7 +27,6 @@ void ngx_tcp_lua_reset_ctx(ngx_tcp_session_t *r, lua_State *L, ngx_tcp_lua_ctx_t static char *ngx_tcp_lua_lowat_check(ngx_conf_t *cf, void *post, void *data); char *ngx_tcp_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - static ngx_tcp_protocol_t ngx_tcp_lua_protocol = { ngx_string("tcp_lua"), @@ -46,6 +46,12 @@ static ngx_conf_post_t ngx_tcp_lua_lowat_post = static ngx_command_t ngx_tcp_lua_commands[] = { + { ngx_string("lua_shared_dict"), + NGX_TCP_MAIN_CONF|NGX_CONF_TAKE2, + ngx_http_lua_shared_dict, + 0, + 0, + NULL }, { ngx_string("lua_package_cpath"), NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1, ngx_tcp_lua_package_cpath, @@ -174,8 +180,8 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) c = s->connection; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp lua init and load src"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp lua init and load src"); lscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_lua_module); lmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_lua_module); L = lmcf->lua; @@ -354,6 +360,7 @@ ngx_tcp_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->pool_size, prev->pool_size, 30); + return NGX_CONF_OK; } diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 9f1e28b..c14db25 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -1,4 +1,7 @@ +//http ext +#include "lua_module/ngx_http_lua_shdict.h" +//tcp only #include "ngx_md5.h" #include "ngx_tcp_lua_util.h" #include "ngx_tcp_lua_output.h" @@ -110,6 +113,10 @@ ngx_tcp_lua_init_globals(ngx_conf_t *cf, lua_State *L) static void ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) { + ngx_http_lua_main_conf_t *lmcf; + + lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_tcp_lua_module); + lua_createtable(L, 0 /* narr */, 89 /* nrec */); /* ngx.* */ ngx_tcp_lua_inject_core_consts(L); @@ -122,6 +129,8 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) ngx_tcp_lua_inject_socket_api(cf->log, L); + ngx_http_lua_inject_shdict_api(lmcf, L); + lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ lua_pushvalue(L, -3); /* ngx package loaded ngx */ From 3a06f53d0bc7309b9f14912e65d7471518c5bdc4 Mon Sep 17 00:00:00 2001 From: humboldt Date: Mon, 11 Mar 2013 19:42:25 +0800 Subject: [PATCH 03/22] add error_log --- src/ngx_tcp.c | 4 ++-- src/ngx_tcp.h | 4 ++++ src/ngx_tcp_core_module.c | 18 ++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index 019e5f5..e95780a 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -627,8 +627,8 @@ ngx_tcp_add_listening(ngx_conf_t *cf, ngx_tcp_conf_addr_t *addr) ls->pool_size = 256; //cscf->connection_pool_size; ls->post_accept_timeout = 10000; //cscf->client_header_timeout; - /*ls->logp = cscf->error_log; &cf->cycle->new_log*/ - ls->logp = &cf->cycle->new_log; + ls->logp = cscf->error_log; + /*ls->logp = &cf->cycle->new_log;*/ ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; diff --git a/src/ngx_tcp.h b/src/ngx_tcp.h index 76784aa..8e0f93f 100755 --- a/src/ngx_tcp.h +++ b/src/ngx_tcp.h @@ -182,6 +182,8 @@ struct ngx_tcp_core_srv_conf_s { /*ACL rules*/ ngx_array_t *rules; + ngx_log_t *error_log; + ngx_tcp_log_srv_conf_t *access_log; /* server ctx */ @@ -190,6 +192,8 @@ struct ngx_tcp_core_srv_conf_s { off_t directio_alignment; /* directio_alignment */ size_t client_body_buffer_size; /* client_body_buffer_size */ + + }; diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 4588ef8..05d9372 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -26,8 +26,8 @@ static char *ngx_tcp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_tcp_log_set_access_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -/*static char *ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf);*/ +static char *ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_command_t ngx_tcp_core_commands[] = { @@ -133,12 +133,12 @@ static ngx_command_t ngx_tcp_core_commands[] = { 0, NULL }, - /*{ ngx_string("error_log"), + { ngx_string("error_log"), NGX_TCP_MAIN_CONF|NGX_TCP_SRV_CONF|NGX_CONF_1MORE, ngx_tcp_core_error_log, NGX_TCP_SRV_CONF_OFFSET, 0, - NULL },*/ + NULL }, { ngx_string("directio_alignment"), NGX_TCP_MAIN_CONF|NGX_TCP_SRV_CONF|NGX_CONF_TAKE1, @@ -337,13 +337,13 @@ ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) conf->rules = prev->rules; } - /*if (conf->error_log == NULL) { + if (conf->error_log == NULL) { if (prev->error_log) { conf->error_log = prev->error_log; } else { conf->error_log = &cf->cycle->new_log; } - }*/ + } if (lscf->open_file_cache == NGX_CONF_UNSET_PTR) { @@ -909,15 +909,13 @@ ngx_tcp_log_set_access_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } -/*static char * +static char * ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_tcp_core_srv_conf_t *clcf = conf; ngx_str_t *value, name; - return NGX_CONF_OK; - if (clcf->error_log) { return "is duplicate"; } @@ -942,4 +940,4 @@ ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } return ngx_log_set_levels(cf, clcf->error_log); -}*/ +} From 93bac4eaf0d5b4614b70b2c86d0666cdf483f295 Mon Sep 17 00:00:00 2001 From: humboldt Date: Thu, 11 Jul 2013 14:40:16 +0800 Subject: [PATCH 04/22] remove http shared --- src/ngx_tcp_lua_module.c | 6 +++--- src/ngx_tcp_lua_util.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 4954006..11929e5 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -1,5 +1,5 @@ -#include "lua_module/ngx_http_lua_directive.h" +//#include "lua_module/ngx_http_lua_directive.h" #include "ngx_tcp_lua_common.h" #include "ngx_tcp_lua_cache.h" #include "ngx_tcp_lua_util.h" @@ -46,12 +46,12 @@ static ngx_conf_post_t ngx_tcp_lua_lowat_post = static ngx_command_t ngx_tcp_lua_commands[] = { - { ngx_string("lua_shared_dict"), + /*{ ngx_string("lua_shared_dict"), NGX_TCP_MAIN_CONF|NGX_CONF_TAKE2, ngx_http_lua_shared_dict, 0, 0, - NULL }, + NULL },*/ { ngx_string("lua_package_cpath"), NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1, ngx_tcp_lua_package_cpath, diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index c14db25..720ae3b 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -1,6 +1,6 @@ //http ext -#include "lua_module/ngx_http_lua_shdict.h" +//#include "lua_module/ngx_http_lua_shdict.h" //tcp only #include "ngx_md5.h" #include "ngx_tcp_lua_util.h" @@ -113,10 +113,10 @@ ngx_tcp_lua_init_globals(ngx_conf_t *cf, lua_State *L) static void ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) { - ngx_http_lua_main_conf_t *lmcf; + /*ngx_http_lua_main_conf_t *lmcf; lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_tcp_lua_module); - +*/ lua_createtable(L, 0 /* narr */, 89 /* nrec */); /* ngx.* */ ngx_tcp_lua_inject_core_consts(L); @@ -129,7 +129,7 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) ngx_tcp_lua_inject_socket_api(cf->log, L); - ngx_http_lua_inject_shdict_api(lmcf, L); + //ngx_http_lua_inject_shdict_api(lmcf, L); lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ From 38b52817f12c043e665b0bbb56c0c0a575f5b8f4 Mon Sep 17 00:00:00 2001 From: humboldt Date: Thu, 24 Oct 2013 10:31:42 +0800 Subject: [PATCH 05/22] add exit function --- src/ngx_tcp.h | 2 +- src/ngx_tcp_lua_common.h | 1 + src/ngx_tcp_lua_module.c | 3 ++- src/ngx_tcp_lua_output.c | 30 ++++++++++++++++++++++++++++++ src/ngx_tcp_lua_util.c | 6 ++++-- 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/ngx_tcp.h b/src/ngx_tcp.h index 8e0f93f..57b15ab 100755 --- a/src/ngx_tcp.h +++ b/src/ngx_tcp.h @@ -182,7 +182,7 @@ struct ngx_tcp_core_srv_conf_s { /*ACL rules*/ ngx_array_t *rules; - ngx_log_t *error_log; + ngx_log_t *error_log; ngx_tcp_log_srv_conf_t *access_log; diff --git a/src/ngx_tcp_lua_common.h b/src/ngx_tcp_lua_common.h index 18e32e3..7a91b5c 100755 --- a/src/ngx_tcp_lua_common.h +++ b/src/ngx_tcp_lua_common.h @@ -89,6 +89,7 @@ typedef struct ngx_tcp_lua_ctx_s { unsigned socket_busy:1; unsigned socket_ready:1; + unsigned exited:1; } ngx_tcp_lua_ctx_t; #define DDEBUG 0 diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 11929e5..e7343f0 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -588,8 +588,9 @@ ngx_tcp_lua_process_by_chunk(lua_State *L, ngx_tcp_session_t *s) dd("setting new ctx, ctx = %p", ctx); - ctx->cc_ref = LUA_NOREF; + ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; + ctx->exited = 0; ngx_tcp_set_ctx(s, ctx, ngx_tcp_lua_module); diff --git a/src/ngx_tcp_lua_output.c b/src/ngx_tcp_lua_output.c index ba88f73..36578b1 100755 --- a/src/ngx_tcp_lua_output.c +++ b/src/ngx_tcp_lua_output.c @@ -207,6 +207,32 @@ ngx_tcp_lua_ngx_echo(lua_State *L, unsigned newline,unsigned start) return 0; } +int +ngx_tcp_lua_ngx_exit(lua_State *L) +{ + ngx_tcp_session_t *s; + ngx_tcp_lua_ctx_t *ctx; + //ngx_buf_tag_t tag; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + s = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (s == NULL) { + return luaL_error(L, "no request object found"); + } + + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); + + if (ctx == NULL) { + return luaL_error(L, "no request ctx found"); + } + ctx->exited = 1; + + + return lua_yield(L,0); +} void ngx_tcp_lua_inject_output_api(lua_State *L) @@ -217,6 +243,9 @@ ngx_tcp_lua_inject_output_api(lua_State *L) lua_pushcfunction(L, ngx_tcp_lua_ngx_print); lua_setfield(L, -2, "print"); + lua_pushcfunction(L, ngx_tcp_lua_ngx_exit); + lua_setfield(L, -2, "exit"); + } @@ -404,3 +433,4 @@ ngx_tcp_lua_copy_str_in_table(lua_State *L, u_char *dst) } + diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 720ae3b..1a257cc 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -393,9 +393,11 @@ ngx_tcp_lua_run_thread(lua_State *L, ngx_tcp_session_t *s, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua thread yielded"); + if(ctx->exited != 1){ - lua_settop(cc, 0); - return NGX_AGAIN; + lua_settop(cc, 0); + return NGX_AGAIN; + } case 0: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, From b4d6966920fb3e256f3d497eb8bc09069f773654 Mon Sep 17 00:00:00 2001 From: humboldt Date: Wed, 13 Nov 2013 11:16:55 +0800 Subject: [PATCH 06/22] add shdict string time --- src/ngx_tcp_lua_shdict.c | 1185 ++++++++++++++++++++++++++++++++++++++ src/ngx_tcp_lua_shdict.h | 47 ++ src/ngx_tcp_lua_string.c | 662 +++++++++++++++++++++ src/ngx_tcp_lua_string.h | 12 + src/ngx_tcp_lua_time.c | 217 +++++++ src/ngx_tcp_lua_time.h | 12 + 6 files changed, 2135 insertions(+) create mode 100644 src/ngx_tcp_lua_shdict.c create mode 100644 src/ngx_tcp_lua_shdict.h create mode 100644 src/ngx_tcp_lua_string.c create mode 100644 src/ngx_tcp_lua_string.h create mode 100644 src/ngx_tcp_lua_time.c create mode 100644 src/ngx_tcp_lua_time.h diff --git a/src/ngx_tcp_lua_shdict.c b/src/ngx_tcp_lua_shdict.c new file mode 100644 index 0000000..19bd3fd --- /dev/null +++ b/src/ngx_tcp_lua_shdict.c @@ -0,0 +1,1185 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif +//#include "ddebug.h" + + +#include "ngx_tcp_lua_shdict.h" + +typedef struct { + uint8_t type; + + union { + int b; /* boolean */ + lua_Number n; /* number */ + ngx_str_t s; /* string */ + } value; + +} ngx_tcp_lua_value_t; + +static int ngx_tcp_lua_shdict_set(lua_State *L); +static int ngx_tcp_lua_shdict_get(lua_State *L); +static int ngx_tcp_lua_shdict_expire(ngx_tcp_lua_shdict_ctx_t *ctx, + ngx_uint_t n); +static ngx_int_t ngx_tcp_lua_shdict_lookup(ngx_shm_zone_t *shm_zone, + ngx_uint_t hash, u_char *kdata, size_t klen, + ngx_tcp_lua_shdict_node_t **sdp); +static int ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags); +static int ngx_tcp_lua_shdict_add(lua_State *L); +static int ngx_tcp_lua_shdict_replace(lua_State *L); +static int ngx_tcp_lua_shdict_incr(lua_State *L); +static int ngx_tcp_lua_shdict_delete(lua_State *L); +static int ngx_tcp_lua_shdict_flush_all(lua_State *L); +static int ngx_tcp_lua_shdict_flush_expired(lua_State *L); + + +#define NGX_TCP_LUA_SHDICT_ADD 0x0001 +#define NGX_TCP_LUA_SHDICT_REPLACE 0x0002 + + +ngx_int_t +ngx_tcp_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) +{ + ngx_tcp_lua_shdict_ctx_t *octx = data; + + size_t len; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_main_conf_t *lmcf; + + dd("init zone"); + + ctx = shm_zone->data; + + if (octx) { + ctx->sh = octx->sh; + ctx->shpool = octx->shpool; + + goto done; + } + + ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; + + if (shm_zone->shm.exists) { + ctx->sh = ctx->shpool->data; + + goto done; + } + + ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_tcp_lua_shdict_shctx_t)); + if (ctx->sh == NULL) { + return NGX_ERROR; + } + + ctx->shpool->data = ctx->sh; + + ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, + ngx_tcp_lua_shdict_rbtree_insert_value); + + ngx_queue_init(&ctx->sh->queue); + + len = sizeof(" in lua_shared_dict zone \"\"") + shm_zone->shm.name.len; + + ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len); + if (ctx->shpool->log_ctx == NULL) { + return NGX_ERROR; + } + + ngx_sprintf(ctx->shpool->log_ctx, " in lua_shared_dict zone \"%V\"%Z", + &shm_zone->shm.name); + +done: + dd("get lmcf"); + + lmcf = ctx->main_conf; + + dd("lmcf->lua: %p", lmcf->lua); + + lmcf->shm_zones_inited++; + + /*if (lmcf->shm_zones_inited == lmcf->shm_zones->nelts && lmcf->init_handler) + { + if (lmcf->init_handler(ctx->log, lmcf, lmcf->lua) != 0) { + /* an error happened * / + return NGX_ERROR; + } + }*/ + + return NGX_OK; +} + + +void +ngx_tcp_lua_shdict_rbtree_insert_value(ngx_rbtree_node_t *temp, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) +{ + ngx_rbtree_node_t **p; + ngx_tcp_lua_shdict_node_t *sdn, *sdnt; + + for ( ;; ) { + + if (node->key < temp->key) { + + p = &temp->left; + + } else if (node->key > temp->key) { + + p = &temp->right; + + } else { /* node->key == temp->key */ + + sdn = (ngx_tcp_lua_shdict_node_t *) &node->color; + sdnt = (ngx_tcp_lua_shdict_node_t *) &temp->color; + + p = (ngx_memn2cmp(sdn->data, sdnt->data, sdn->key_len, + sdnt->key_len) < 0) ? &temp->left : &temp->right; + } + + if (*p == sentinel) { + break; + } + + temp = *p; + } + + *p = node; + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + ngx_rbt_red(node); +} + + +static ngx_int_t +ngx_tcp_lua_shdict_lookup(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, + u_char *kdata, size_t klen, ngx_tcp_lua_shdict_node_t **sdp) +{ + ngx_int_t rc; + ngx_time_t *tp; + uint64_t now; + int64_t ms; + ngx_rbtree_node_t *node, *sentinel; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_shdict_node_t *sd; + + ctx = shm_zone->data; + + node = ctx->sh->rbtree.root; + sentinel = ctx->sh->rbtree.sentinel; + + while (node != sentinel) { + + if (hash < node->key) { + node = node->left; + continue; + } + + if (hash > node->key) { + node = node->right; + continue; + } + + /* hash == node->key */ + + sd = (ngx_tcp_lua_shdict_node_t *) &node->color; + + rc = ngx_memn2cmp(kdata, sd->data, klen, (size_t) sd->key_len); + + if (rc == 0) { + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + + *sdp = sd; + + dd("node expires: %lld", (long long) sd->expires); + + if (sd->expires != 0) { + tp = ngx_timeofday(); + + now = (uint64_t) tp->sec * 1000 + tp->msec; + ms = sd->expires - now; + + dd("time to live: %lld", (long long) ms); + + if (ms < 0) { + dd("node already expired"); + return NGX_DONE; + } + } + + return NGX_OK; + } + + node = (rc < 0) ? node->left : node->right; + } + + *sdp = NULL; + + return NGX_DECLINED; +} + + +static int +ngx_tcp_lua_shdict_expire(ngx_tcp_lua_shdict_ctx_t *ctx, ngx_uint_t n) +{ + ngx_time_t *tp; + uint64_t now; + ngx_queue_t *q; + int64_t ms; + ngx_rbtree_node_t *node; + ngx_tcp_lua_shdict_node_t *sd; + int freed = 0; + + tp = ngx_timeofday(); + + now = (uint64_t) tp->sec * 1000 + tp->msec; + + /* + * n == 1 deletes one or two expired entries + * n == 0 deletes oldest entry by force + * and one or two zero rate entries + */ + + while (n < 3) { + + if (ngx_queue_empty(&ctx->sh->queue)) { + return freed; + } + + q = ngx_queue_last(&ctx->sh->queue); + + sd = ngx_queue_data(q, ngx_tcp_lua_shdict_node_t, queue); + + if (n++ != 0) { + + if (sd->expires == 0) { + return freed; + } + + ms = sd->expires - now; + if (ms > 0) { + return freed; + } + } + + ngx_queue_remove(q); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + + freed++; + } + + return freed; +} + + +void +ngx_tcp_lua_inject_shdict_api(ngx_tcp_lua_main_conf_t *lmcf, lua_State *L) +{ + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_uint_t i; + ngx_shm_zone_t **zone; + + if (lmcf->shm_zones != NULL) { + lua_createtable(L, 0, lmcf->shm_zones->nelts /* nrec */); + /* ngx.shared */ + + lua_createtable(L, 0 /* narr */, 9 /* nrec */); /* shared mt */ + + lua_pushcfunction(L, ngx_tcp_lua_shdict_get); + lua_setfield(L, -2, "get"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_set); + lua_setfield(L, -2, "set"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_add); + lua_setfield(L, -2, "add"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_replace); + lua_setfield(L, -2, "replace"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_incr); + lua_setfield(L, -2, "incr"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_delete); + lua_setfield(L, -2, "delete"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_flush_all); + lua_setfield(L, -2, "flush_all"); + + lua_pushcfunction(L, ngx_tcp_lua_shdict_flush_expired); + lua_setfield(L, -2, "flush_expired"); + + lua_pushvalue(L, -1); /* shared mt mt */ + lua_setfield(L, -2, "__index"); /* shared mt */ + + zone = lmcf->shm_zones->elts; + + for (i = 0; i < lmcf->shm_zones->nelts; i++) { + ctx = zone[i]->data; + + lua_pushlstring(L, (char *) ctx->name.data, ctx->name.len); + /* shared mt key */ + + lua_pushlightuserdata(L, zone[i]); /* shared mt key ud */ + lua_pushvalue(L, -3); /* shared mt key ud mt */ + lua_setmetatable(L, -2); /* shared mt key ud */ + lua_rawset(L, -4); /* shared mt */ + } + + lua_pop(L, 1); /* shared */ + + } else { + lua_newtable(L); /* ngx.shared */ + } + + lua_setfield(L, -2, "shared"); +} + + +static int +ngx_tcp_lua_shdict_get(lua_State *L) +{ + int n; + ngx_str_t name; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_shdict_node_t *sd; + ngx_str_t value; + int value_type; + lua_Number num; + u_char c; + ngx_shm_zone_t *zone; + uint32_t user_flags = 0; + + n = lua_gettop(L); + + if (n != 2) { + return luaL_error(L, "expecting exactly two arguments, " + "but only seen %d", n); + } + + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + + zone = lua_touserdata(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); + } + + ctx = zone->data; + + name = ctx->name; + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + lua_pushnil(L); + return 1; + } + + if (key.len > 65535) { + return luaL_error(L, + "the key argument is more than 65535 bytes: \"%s\"", + key.data); + } + + hash = ngx_crc32_short(key.data, key.len); + +#if (NGX_DEBUG) + ngx_log_debug2(NGX_LOG_DEBUG_TCP, ctx->log, 0, + "fetching key \"%V\" in shared dict \"%V\"", &key, &name); +#endif /* NGX_DEBUG */ + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_tcp_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_tcp_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returns %d", (int) rc); + + if (rc == NGX_DECLINED || rc == NGX_DONE) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + lua_pushnil(L); + return 1; + } + + /* rc == NGX_OK */ + + value_type = sd->value_type; + + dd("data: %p", sd->data); + dd("key len: %d", (int) sd->key_len); + + value.data = sd->data + sd->key_len; + value.len = (size_t) sd->value_len; + + switch (value_type) { + case LUA_TSTRING: + + lua_pushlstring(L, (char *) value.data, value.len); + break; + + case LUA_TNUMBER: + + if (value.len != sizeof(lua_Number)) { + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad lua number value size found for key %s " + "in shared_dict %s: %lu", key.data, name.data, + (unsigned long) value.len); + } + + num = *(lua_Number *) value.data; + + lua_pushnumber(L, num); + break; + + case LUA_TBOOLEAN: + + if (value.len != sizeof(u_char)) { + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad lua boolean value size found for key %s " + "in shared_dict %s: %lu", key.data, name.data, + (unsigned long) value.len); + } + + c = *value.data; + + lua_pushboolean(L, c ? 1 : 0); + break; + + default: + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad value type found for key %s in " + "shared_dict %s: %d", key.data, name.data, + value_type); + } + + user_flags = sd->user_flags; + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + if (user_flags) { + lua_pushinteger(L, (lua_Integer) user_flags); + return 2; + } + + return 1; +} + + +static int +ngx_tcp_lua_shdict_delete(lua_State *L) +{ + int n; + + n = lua_gettop(L); + + if (n != 2) { + return luaL_error(L, "expecting 2 arguments, " + "but only seen %d", n); + } + + lua_pushnil(L); + + return ngx_tcp_lua_shdict_set_helper(L, 0); +} + + +static int +ngx_tcp_lua_shdict_flush_all(lua_State *L) +{ + ngx_queue_t *q; + ngx_tcp_lua_shdict_node_t *sd; + int n; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_shm_zone_t *zone; + + n = lua_gettop(L); + + if (n != 1) { + return luaL_error(L, "expecting 1 argument, " + "but seen %d", n); + } + + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + + zone = lua_touserdata(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); + } + + ctx = zone->data; + + ngx_shmtx_lock(&ctx->shpool->mutex); + + for (q = ngx_queue_head(&ctx->sh->queue); + q != ngx_queue_sentinel(&ctx->sh->queue); + q = ngx_queue_next(q)) + { + sd = ngx_queue_data(q, ngx_tcp_lua_shdict_node_t, queue); + sd->expires = 1; + } + + ngx_tcp_lua_shdict_expire(ctx, 0); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return 0; +} + + +static int +ngx_tcp_lua_shdict_flush_expired(lua_State *L) +{ + ngx_queue_t *q, *prev; + ngx_tcp_lua_shdict_node_t *sd; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_shm_zone_t *zone; + ngx_time_t *tp; + int freed = 0; + int attempts = 0; + ngx_rbtree_node_t *node; + uint64_t now; + int n; + + n = lua_gettop(L); + + if (n != 1 && n != 2) { + return luaL_error(L, "expecting 1 or 2 argument(s), " + "but saw %d", n); + } + + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + + zone = lua_touserdata(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); + } + + if (n == 2) { + attempts = luaL_checknumber(L, 2); + } + + ctx = zone->data; + + ngx_shmtx_lock(&ctx->shpool->mutex); + + if (ngx_queue_empty(&ctx->sh->queue)) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + lua_pushnumber(L, 0); + return 1; + } + + tp = ngx_timeofday(); + + now = (uint64_t) tp->sec * 1000 + tp->msec; + + q = ngx_queue_last(&ctx->sh->queue); + + while (q != ngx_queue_sentinel(&ctx->sh->queue)) { + prev = ngx_queue_prev(q); + + sd = ngx_queue_data(q, ngx_tcp_lua_shdict_node_t, queue); + + if (sd->expires != 0 && sd->expires <= now) { + ngx_queue_remove(q); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + + freed++; + + if (attempts && freed == attempts) { + break; + } + } + + q = prev; + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, freed); + return 1; +} + + +static int +ngx_tcp_lua_shdict_add(lua_State *L) +{ + return ngx_tcp_lua_shdict_set_helper(L, NGX_TCP_LUA_SHDICT_ADD); +} + + +static int +ngx_tcp_lua_shdict_replace(lua_State *L) +{ + return ngx_tcp_lua_shdict_set_helper(L, NGX_TCP_LUA_SHDICT_REPLACE); +} + + +static int +ngx_tcp_lua_shdict_set(lua_State *L) +{ + return ngx_tcp_lua_shdict_set_helper(L, 0); +} + + +static int +ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) +{ + int i, n; + ngx_str_t name; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_shdict_node_t *sd; + ngx_str_t value; + int value_type; + lua_Number num; + u_char c; + lua_Number exptime = 0; + u_char *p; + ngx_rbtree_node_t *node; + ngx_time_t *tp; + ngx_shm_zone_t *zone; + int forcible = 0; + /* indicates whether to foricibly override other + * valid entries */ + int32_t user_flags = 0; + + n = lua_gettop(L); + + if (n != 3 && n != 4 && n != 5) { + return luaL_error(L, "expecting 3, 4 or 5 arguments, " + "but only seen %d", n); + } + + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + + zone = lua_touserdata(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); + } + + ctx = zone->data; + + name = ctx->name; + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + return luaL_error(L, "attempt to use empty keys"); + } + + if (key.len > 65535) { + return luaL_error(L, + "the key argument is more than 65535 bytes: %d", + (int) key.len); + } + + hash = ngx_crc32_short(key.data, key.len); + + value_type = lua_type(L, 3); + + switch (value_type) { + case LUA_TSTRING: + value.data = (u_char *) lua_tolstring(L, 3, &value.len); + break; + + case LUA_TNUMBER: + value.len = sizeof(lua_Number); + num = lua_tonumber(L, 3); + value.data = (u_char *) # + break; + + case LUA_TBOOLEAN: + value.len = sizeof(u_char); + c = lua_toboolean(L, 3) ? 1 : 0; + value.data = &c; + break; + + case LUA_TNIL: + if (flags & (NGX_TCP_LUA_SHDICT_ADD|NGX_TCP_LUA_SHDICT_REPLACE)) { + return luaL_error(L, "attempt to add or replace nil values"); + } + + value.len = 0; + value.data = NULL; + break; + + default: + return luaL_error(L, "unsupported value type for key \"%s\" in " + "shared_dict \"%s\": %s", key.data, name.data, + lua_typename(L, value_type)); + } + + if (n >= 4) { + exptime = luaL_checknumber(L, 4); + if (exptime < 0) { + exptime = 0; + } + } + + if (n == 5) { + user_flags = (uint32_t) luaL_checkinteger(L, 5); + } + + dd("looking up key %s in shared dict %s", key.data, name.data); + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_tcp_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_tcp_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + if (flags & NGX_TCP_LUA_SHDICT_REPLACE) { + + if (rc == NGX_DECLINED || rc == NGX_DONE) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "not found"); + lua_pushboolean(L, forcible); + return 3; + } + + /* rc == NGX_OK */ + + goto replace; + } + + if (flags & NGX_TCP_LUA_SHDICT_ADD) { + + if (rc == NGX_OK) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "exists"); + lua_pushboolean(L, forcible); + return 3; + } + + if (rc == NGX_DONE) { + /* exists but expired */ + + dd("go to replace"); + goto replace; + } + + /* rc == NGX_DECLINED */ + + dd("go to insert"); + goto insert; + } + + if (rc == NGX_OK || rc == NGX_DONE) { + + if (value_type == LUA_TNIL) { + goto remove; + } + +replace: + if (value.data && value.len == (size_t) sd->value_len) { + + ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + "lua shared dict set: found old entry and value size matched, " + "reusing it"); + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + + sd->key_len = key.len; + + if (exptime > 0) { + tp = ngx_timeofday(); + sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + + exptime * 1000; + + } else { + sd->expires = 0; + } + + sd->user_flags = user_flags; + + sd->value_len = (uint32_t) value.len; + + dd("setting value type to %d", value_type); + + sd->value_type = value_type; + + p = ngx_copy(sd->data, key.data, key.len); + ngx_memcpy(p, value.data, value.len); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 1); + lua_pushnil(L); + lua_pushboolean(L, forcible); + return 3; + } + + ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + "lua shared dict set: found old entry bug value size NOT matched, " + "removing it first"); + +remove: + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + + } + +insert: + /* rc == NGX_DECLINED or value size unmatch */ + + if (value.data == NULL) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 1); + lua_pushnil(L); + lua_pushboolean(L, 0); + return 3; + } + + ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + "lua shared dict set: creating a new entry"); + + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_tcp_lua_shdict_node_t, data) + + key.len + + value.len; + + node = ngx_slab_alloc_locked(ctx->shpool, n); + + if (node == NULL) { + + ngx_log_debug1(NGX_LOG_DEBUG_TCP, ctx->log, 0, + "lua shared dict set: overriding non-expired items due to memory " + "shortage for entry \"%V\"", &name); + + for (i = 0; i < 30; i++) { + if (ngx_tcp_lua_shdict_expire(ctx, 0) == 0) { + break; + } + + forcible = 1; + + node = ngx_slab_alloc_locked(ctx->shpool, n); + if (node != NULL) { + goto allocated; + } + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "no memory"); + lua_pushboolean(L, forcible); + return 3; + } + +allocated: + sd = (ngx_tcp_lua_shdict_node_t *) &node->color; + + node->key = hash; + sd->key_len = key.len; + + if (exptime > 0) { + tp = ngx_timeofday(); + sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + + exptime * 1000; + + } else { + sd->expires = 0; + } + + sd->user_flags = user_flags; + + sd->value_len = (uint32_t) value.len; + + dd("setting value type to %d", value_type); + + sd->value_type = value_type; + + p = ngx_copy(sd->data, key.data, key.len); + ngx_memcpy(p, value.data, value.len); + + ngx_rbtree_insert(&ctx->sh->rbtree, node); + + ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 1); + lua_pushnil(L); + lua_pushboolean(L, forcible); + return 3; +} + + +static int +ngx_tcp_lua_shdict_incr(lua_State *L) +{ + int n; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_shdict_node_t *sd; + lua_Number num; + u_char *p; + ngx_shm_zone_t *zone; + lua_Number value; + + n = lua_gettop(L); + + if (n != 3) { + return luaL_error(L, "expecting 3 arguments, " + "but only seen %d", n); + } + + luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + + zone = lua_touserdata(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); + } + + ctx = zone->data; + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + return luaL_error(L, "attempt to use empty keys"); + } + + if (key.len > 65535) { + return luaL_error(L, + "the key argument is more than 65535 bytes: %d", + (int) key.len); + } + + hash = ngx_crc32_short(key.data, key.len); + + value = luaL_checknumber(L, 3); + + dd("looking up key %.*s in shared dict %.*s", (int) key.len, key.data, + (int) ctx->name.len, ctx->name.data); + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_tcp_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_tcp_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + if (rc == NGX_DECLINED || rc == NGX_DONE) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "not found"); + return 2; + } + + /* rc == NGX_OK */ + + if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(lua_Number)) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "not a number"); + return 2; + } + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + + dd("setting value type to %d", (int) sd->value_type); + + p = sd->data + key.len; + + num = *(lua_Number *) p; + + num += value; + + ngx_memcpy(p, (lua_Number *) &num, sizeof(lua_Number)); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, num); + lua_pushnil(L); + return 2; +} + + +ngx_int_t +ngx_tcp_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, + size_t key_len, ngx_tcp_lua_value_t*value) +{ + u_char *data; + size_t len; + uint32_t hash; + ngx_int_t rc; + ngx_tcp_lua_shdict_ctx_t *ctx; + ngx_tcp_lua_shdict_node_t *sd; + + if (zone == NULL) { + return NGX_ERROR; + } + + hash = ngx_crc32_short(key_data, key_len); + + ctx = zone->data; + + ngx_shmtx_lock(&ctx->shpool->mutex); + + rc = ngx_tcp_lua_shdict_lookup(zone, hash, key_data, key_len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + if (rc == NGX_DECLINED || rc == NGX_DONE) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return rc; + } + + /* rc == NGX_OK */ + + value->type = sd->value_type; + + dd("type: %d", (int) value->type); + + data = sd->data + sd->key_len; + len = (size_t) sd->value_len; + + switch (value->type) { + case LUA_TSTRING: + + if (value->value.s.data == NULL || value->value.s.len == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "no string buffer " + "initialized"); + return NGX_ERROR; + } + + if (len > value->value.s.len) { + len = value->value.s.len; + + } else { + value->value.s.len = len; + } + + ngx_memcpy(value->value.s.data, data, len); + break; + + case LUA_TNUMBER: + + if (len != sizeof(lua_Number)) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua number " + "value size found for key %*s: %lu", key_len, + key_data, (unsigned long) len); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_ERROR; + } + + ngx_memcpy(&value->value.b, data, len); + break; + + case LUA_TBOOLEAN: + + if (len != sizeof(u_char)) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua boolean " + "value size found for key %*s: %lu", key_len, + key_data, (unsigned long) len); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_ERROR; + } + + value->value.b = *data; + break; + + default: + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua value type " + "found for key %*s: %d", key_len, key_data, + (int) value->type); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_ERROR; + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_OK; +} + + +ngx_shm_zone_t * +ngx_tcp_lua_find_zone(u_char *name_data, size_t name_len) +{ + ngx_str_t *name; + ngx_uint_t i; + ngx_shm_zone_t *zone; + volatile ngx_list_part_t *part; + + part = &ngx_cycle->shared_memory.part; + zone = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + zone = part->elts; + i = 0; + } + + name = &zone[i].shm.name; + + dd("name: [%.*s] %d", (int) name->len, name->data, (int) name->len); + dd("name2: [%.*s] %d", (int) name_len, name_data, (int) name_len); + + if (name->len == name_len + && ngx_strncmp(name->data, name_data, name_len) == 0) + { + return zone; + } + } + + return NULL; +} + diff --git a/src/ngx_tcp_lua_shdict.h b/src/ngx_tcp_lua_shdict.h new file mode 100644 index 0000000..cad0154 --- /dev/null +++ b/src/ngx_tcp_lua_shdict.h @@ -0,0 +1,47 @@ +#ifndef NGX_TCP_LUA_SHDICT_H +#define NGX_TCP_LUA_SHDICT_H +//from lua_ngx_http 7.2 + +#include "ngx_tcp_lua_common.h" + + +typedef struct { + u_char color; + u_char dummy; + u_short key_len; + ngx_queue_t queue; + uint64_t expires; + uint8_t value_type; + uint32_t value_len; + uint32_t user_flags; + u_char data[1]; +} ngx_tcp_lua_shdict_node_t; + + +typedef struct { + ngx_rbtree_t rbtree; + ngx_rbtree_node_t sentinel; + ngx_queue_t queue; +} ngx_tcp_lua_shdict_shctx_t; + + +typedef struct { + ngx_tcp_lua_shdict_shctx_t *sh; + ngx_slab_pool_t *shpool; + ngx_str_t name; + ngx_tcp_lua_main_conf_t *main_conf; + ngx_log_t *log; +} ngx_tcp_lua_shdict_ctx_t; + + +ngx_int_t ngx_tcp_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data); + +void ngx_tcp_lua_shdict_rbtree_insert_value(ngx_rbtree_node_t *temp, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); + +void ngx_tcp_lua_inject_shdict_api(ngx_tcp_lua_main_conf_t *lmcf, + lua_State *L); + + +#endif /* NGX_HTTP_LUA_SHDICT_H */ + diff --git a/src/ngx_tcp_lua_string.c b/src/ngx_tcp_lua_string.c new file mode 100644 index 0000000..b68b9d0 --- /dev/null +++ b/src/ngx_tcp_lua_string.c @@ -0,0 +1,662 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif +//#include "ddebug.h" + + +#include "ngx_tcp_lua_string.h" +#include "ngx_tcp_lua_util.h" +//#include "ngx_tcp_lua_args.h" +#include "ngx_crc32.h" + +#if NGX_HAVE_SHA1 +#include "ngx_sha1.h" +#endif + +#include "ngx_md5.h" + +#if (NGX_OPENSSL) +#include +#include +#endif + + +#ifndef SHA_DIGEST_LENGTH +#define SHA_DIGEST_LENGTH 20 +#endif + + +static uintptr_t ngx_tcp_lua_ngx_escape_sql_str(u_char *dst, u_char *src, + size_t size); +static int ngx_tcp_lua_ngx_escape_uri(lua_State *L); +static int ngx_tcp_lua_ngx_unescape_uri(lua_State *L); +static int ngx_tcp_lua_ngx_quote_sql_str(lua_State *L); +static int ngx_tcp_lua_ngx_md5(lua_State *L); +static int ngx_tcp_lua_ngx_md5_bin(lua_State *L); + +#if (NGX_HAVE_SHA1) +static int ngx_tcp_lua_ngx_sha1_bin(lua_State *L); +#endif + +static int ngx_tcp_lua_ngx_decode_base64(lua_State *L); +static int ngx_tcp_lua_ngx_encode_base64(lua_State *L); +static int ngx_tcp_lua_ngx_crc32_short(lua_State *L); +static int ngx_tcp_lua_ngx_crc32_long(lua_State *L); +static int ngx_tcp_lua_ngx_encode_args(lua_State *L); +static int ngx_tcp_lua_ngx_decode_args(lua_State *L); +#if (NGX_OPENSSL) +static int ngx_tcp_lua_ngx_hmac_sha1(lua_State *L); +#endif + + +void +ngx_tcp_lua_inject_string_api(lua_State *L) +{ + /*lua_pushcfunction(L, ngx_tcp_lua_ngx_escape_uri); + lua_setfield(L, -2, "escape_uri"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_unescape_uri); + lua_setfield(L, -2, "unescape_uri"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_encode_args); + lua_setfield(L, -2, "encode_args"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_decode_args); + lua_setfield(L, -2, "decode_args");*/ + + lua_pushcfunction(L, ngx_tcp_lua_ngx_quote_sql_str); + lua_setfield(L, -2, "quote_sql_str"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_decode_base64); + lua_setfield(L, -2, "decode_base64"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_encode_base64); + lua_setfield(L, -2, "encode_base64"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_md5_bin); + lua_setfield(L, -2, "md5_bin"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_md5); + lua_setfield(L, -2, "md5"); + +#if (NGX_HAVE_SHA1) + lua_pushcfunction(L, ngx_tcp_lua_ngx_sha1_bin); + lua_setfield(L, -2, "sha1_bin"); +#endif + + lua_pushcfunction(L, ngx_tcp_lua_ngx_crc32_short); + lua_setfield(L, -2, "crc32_short"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_crc32_long); + lua_setfield(L, -2, "crc32_long"); + +#if (NGX_OPENSSL) + lua_pushcfunction(L, ngx_tcp_lua_ngx_hmac_sha1); + lua_setfield(L, -2, "hmac_sha1"); +#endif +} + +/* +static int +ngx_tcp_lua_ngx_escape_uri(lua_State *L) +{ + ngx_tcp_session_t *r; + size_t len, dlen; + uintptr_t escape; + u_char *src, *dst; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + src = (u_char *) luaL_checklstring(L, 1, &len); + + if (len == 0) { + lua_pushlstring(L, NULL, 0); + return 1; + } + + escape = 2 * ngx_tcp_lua_escape_uri(NULL, src, len, NGX_ESCAPE_URI); + + dlen = escape + len; + + dst = ngx_palloc(r->pool, dlen); + if (dst == NULL) { + return luaL_error(L, "memory allocation error"); + } + + if (escape == 0) { + ngx_memcpy(dst, src, len); + + } else { + ngx_tcp_lua_escape_uri(dst, src, len, NGX_ESCAPE_URI); + } + + lua_pushlstring(L, (char *) dst, dlen); + + return 1; +}*/ + +/* +static int +ngx_tcp_lua_ngx_unescape_uri(lua_State *L) +{ + ngx_tcp_session_t *r; + size_t len, dlen; + u_char *p; + u_char *src, *dst; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + src = (u_char *) luaL_checklstring(L, 1, &len); + + / * the unescaped string can only be smaller * / + dlen = len; + + p = ngx_palloc(r->pool, dlen); + if (p == NULL) { + return luaL_error(L, "memory allocation error"); + } + + dst = p; + + ngx_tcp_lua_unescape_uri(&dst, &src, len, NGX_UNESCAPE_URI_COMPONENT); + + lua_pushlstring(L, (char *) p, dst - p); + + return 1; +}*/ + + +static int +ngx_tcp_lua_ngx_quote_sql_str(lua_State *L) +{ + ngx_tcp_session_t *r; + size_t len, dlen, escape; + u_char *p; + u_char *src, *dst; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + src = (u_char *) luaL_checklstring(L, 1, &len); + + if (len == 0) { + dst = (u_char *) "''"; + dlen = sizeof("''") - 1; + lua_pushlstring(L, (char *) dst, dlen); + return 1; + } + + escape = ngx_tcp_lua_ngx_escape_sql_str(NULL, src, len); + + dlen = sizeof("''") - 1 + len + escape; + + p = ngx_palloc(r->pool, dlen); + if (p == NULL) { + return luaL_error(L, "out of memory"); + } + + dst = p; + + *p++ = '\''; + + if (escape == 0) { + p = ngx_copy(p, src, len); + + } else { + p = (u_char *) ngx_tcp_lua_ngx_escape_sql_str(p, src, len); + } + + *p++ = '\''; + + if (p != dst + dlen) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "ngx.quote_sql_str: buffer error"); + return NGX_ERROR; + } + + lua_pushlstring(L, (char *) dst, p - dst); + + return 1; +} + + +static uintptr_t +ngx_tcp_lua_ngx_escape_sql_str(u_char *dst, u_char *src, + size_t size) +{ + ngx_uint_t n; + + if (dst == NULL) { + /* find the number of chars to be escaped */ + n = 0; + while (size) { + /* the highest bit of all the UTF-8 chars + * is always 1 */ + if ((*src & 0x80) == 0) { + switch (*src) { + case '\r': + case '\n': + case '\\': + case '\'': + case '"': + case '\032': + n++; + break; + default: + break; + } + } + src++; + size--; + } + + return (uintptr_t) n; + } + + while (size) { + if ((*src & 0x80) == 0) { + switch (*src) { + case '\r': + *dst++ = '\\'; + *dst++ = 'r'; + break; + + case '\n': + *dst++ = '\\'; + *dst++ = 'n'; + break; + + case '\\': + *dst++ = '\\'; + *dst++ = '\\'; + break; + + case '\'': + *dst++ = '\\'; + *dst++ = '\''; + break; + + case '"': + *dst++ = '\\'; + *dst++ = '"'; + break; + + case '\032': + *dst++ = '\\'; + *dst++ = *src; + break; + + default: + *dst++ = *src; + break; + } + } else { + *dst++ = *src; + } + src++; + size--; + } /* while (size) */ + + return (uintptr_t) dst; +} + + +static int +ngx_tcp_lua_ngx_md5(lua_State *L) +{ + u_char *src; + size_t slen; + + ngx_md5_t md5; + u_char md5_buf[MD5_DIGEST_LENGTH]; + u_char hex_buf[2 * sizeof(md5_buf)]; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + if (strcmp(luaL_typename(L, 1), (char *) "nil") == 0) { + src = (u_char *) ""; + slen = 0; + + } else { + src = (u_char *) luaL_checklstring(L, 1, &slen); + } + + ngx_md5_init(&md5); + ngx_md5_update(&md5, src, slen); + ngx_md5_final(md5_buf, &md5); + + ngx_hex_dump(hex_buf, md5_buf, sizeof(md5_buf)); + + lua_pushlstring(L, (char *) hex_buf, sizeof(hex_buf)); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_md5_bin(lua_State *L) +{ + u_char *src; + size_t slen; + + ngx_md5_t md5; + u_char md5_buf[MD5_DIGEST_LENGTH]; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + if (lua_isnil(L, 1)) { + src = (u_char *) ""; + slen = 0; + + } else { + src = (u_char *) luaL_checklstring(L, 1, &slen); + } + + dd("slen: %d", (int) slen); + + ngx_md5_init(&md5); + ngx_md5_update(&md5, src, slen); + ngx_md5_final(md5_buf, &md5); + + lua_pushlstring(L, (char *) md5_buf, sizeof(md5_buf)); + + return 1; +} + + +#if (NGX_HAVE_SHA1) +static int +ngx_tcp_lua_ngx_sha1_bin(lua_State *L) +{ + u_char *src; + size_t slen; + + ngx_sha1_t sha; + u_char sha_buf[SHA_DIGEST_LENGTH]; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + if (lua_isnil(L, 1)) { + src = (u_char *) ""; + slen = 0; + + } else { + src = (u_char *) luaL_checklstring(L, 1, &slen); + } + + dd("slen: %d", (int) slen); + + ngx_sha1_init(&sha); + ngx_sha1_update(&sha, src, slen); + ngx_sha1_final(sha_buf, &sha); + + lua_pushlstring(L, (char *) sha_buf, sizeof(sha_buf)); + + return 1; +} +#endif + + +static int +ngx_tcp_lua_ngx_decode_base64(lua_State *L) +{ + ngx_tcp_session_t *r; + ngx_str_t p, src; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + if (strcmp(luaL_typename(L, 1), (char *) "nil") == 0) { + src.data = (u_char *) ""; + src.len = 0; + + } else { + src.data = (u_char *) luaL_checklstring(L, 1, &src.len); + } + + p.len = ngx_base64_decoded_length(src.len); + + p.data = ngx_palloc(r->pool, p.len); + if (p.data == NULL) { + return NGX_ERROR; + } + + if (ngx_decode_base64(&p, &src) == NGX_OK) { + lua_pushlstring(L, (char *) p.data, p.len); + + } else { + lua_pushnil(L); + } + + ngx_pfree(r->pool, p.data); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_encode_base64(lua_State *L) +{ + ngx_tcp_session_t *r; + ngx_str_t p, src; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + if (strcmp(luaL_typename(L, 1), (char *) "nil") == 0) { + src.data = (u_char *) ""; + src.len = 0; + + } else { + src.data = (u_char *) luaL_checklstring(L, 1, &src.len); + } + + p.len = ngx_base64_encoded_length(src.len); + + p.data = ngx_palloc(r->pool, p.len); + if (p.data == NULL) { + return NGX_ERROR; + } + + ngx_encode_base64(&p, &src); + + lua_pushlstring(L, (char *) p.data, p.len); + + ngx_pfree(r->pool, p.data); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_crc32_short(lua_State *L) +{ + u_char *p; + size_t len; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument, but got %d", + lua_gettop(L)); + } + + p = (u_char *) luaL_checklstring(L, 1, &len); + + lua_pushnumber(L, (lua_Number) ngx_crc32_short(p, len)); + return 1; +} + + +static int +ngx_tcp_lua_ngx_crc32_long(lua_State *L) +{ + u_char *p; + size_t len; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument, but got %d", + lua_gettop(L)); + } + + p = (u_char *) luaL_checklstring(L, 1, &len); + + lua_pushnumber(L, (lua_Number) ngx_crc32_long(p, len)); + return 1; +} + + +/*static int +ngx_tcp_lua_ngx_encode_args(lua_State *L) { + ngx_tcp_session_t *r; + ngx_str_t args; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting 1 argument but seen %d", + lua_gettop(L)); + } + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + luaL_checktype(L, 1, LUA_TTABLE); + + ngx_tcp_lua_process_args_option(r, L, 1, &args); + + lua_pushlstring(L, (char *) args.data, args.len); + + ngx_pfree(r->pool, args.data); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_decode_args(lua_State *L) { + ngx_tcp_session_t *r; + u_char *buf; + u_char *last; + size_t len = 0; + int n; + int max; + + n = lua_gettop(L); + + if (n != 1 && n != 2) { + return luaL_error(L, "expecting 1 or 2 arguments but seen %d", n); + } + + buf = (u_char *) luaL_checklstring(L, 1, &len); + + if (n == 2) { + max = luaL_checkint(L, 2); + lua_pop(L, 1); + + } else { + max = NGX_HTTP_LUA_MAX_ARGS; + } + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + r = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + lua_createtable(L, 0, 4); + + last = buf + len; + + return ngx_tcp_lua_parse_args(r, L, buf, last, max); +}*/ + + +#if (NGX_OPENSSL) + +static int +ngx_tcp_lua_ngx_hmac_sha1(lua_State *L) +{ + u_char *sec, *sts; + size_t lsec, lsts; + unsigned int md_len; + unsigned char md[EVP_MAX_MD_SIZE]; + const EVP_MD *evp_md; + + if (lua_gettop(L) != 2) { + return luaL_error(L, "expecting one argument, but got %d", + lua_gettop(L)); + } + + sec = (u_char *) luaL_checklstring(L, 1, &lsec); + sts = (u_char *) luaL_checklstring(L, 2, &lsts); + + evp_md = EVP_sha1(); + + HMAC(evp_md, sec, lsec, sts, lsts, md, &md_len); + + lua_pushlstring(L, (char *) md, md_len); + + return 1; +} +#endif + diff --git a/src/ngx_tcp_lua_string.h b/src/ngx_tcp_lua_string.h new file mode 100644 index 0000000..3f87a60 --- /dev/null +++ b/src/ngx_tcp_lua_string.h @@ -0,0 +1,12 @@ +#ifndef NGX_TCP_LUA_STRING_H +#define NGX_TCP_LUA_STRING_H + + +#include "ngx_tcp_lua_common.h" + + +void ngx_tcp_lua_inject_string_api(lua_State *L); + + +#endif /* NGX_TCP_LUA_STRING_H */ + diff --git a/src/ngx_tcp_lua_time.c b/src/ngx_tcp_lua_time.c new file mode 100644 index 0000000..722d953 --- /dev/null +++ b/src/ngx_tcp_lua_time.c @@ -0,0 +1,217 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif +//#include "ddebug.h" + +#include "ngx_tcp_lua_time.h" + + +static int ngx_tcp_lua_ngx_today(lua_State *L); +static int ngx_tcp_lua_ngx_time(lua_State *L); +static int ngx_tcp_lua_ngx_now(lua_State *L); +static int ngx_tcp_lua_ngx_localtime(lua_State *L); +static int ngx_tcp_lua_ngx_utctime(lua_State *L); +static int ngx_tcp_lua_ngx_cookie_time(lua_State *L); +static int ngx_tcp_lua_ngx_http_time(lua_State *L); +static int ngx_tcp_lua_ngx_parse_http_time(lua_State *L); +static int ngx_tcp_lua_ngx_update_time(lua_State *L); + + +static int +ngx_tcp_lua_ngx_today(lua_State *L) +{ + time_t now; + ngx_tm_t tm; + u_char buf[sizeof("2010-11-19") - 1]; + + now = ngx_time(); + ngx_gmtime(now + ngx_cached_time->gmtoff * 60, &tm); + + ngx_sprintf(buf, "%04d-%02d-%02d", tm.ngx_tm_year, tm.ngx_tm_mon, + tm.ngx_tm_mday); + + lua_pushlstring(L, (char *) buf, sizeof(buf)); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_localtime(lua_State *L) +{ + ngx_tm_t tm; + + u_char buf[sizeof("2010-11-19 20:56:31") - 1]; + + ngx_gmtime(ngx_time() + ngx_cached_time->gmtoff * 60, &tm); + + ngx_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.ngx_tm_year, + tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, + tm.ngx_tm_sec); + + lua_pushlstring(L, (char *) buf, sizeof(buf)); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_time(lua_State *L) +{ + lua_pushnumber(L, (lua_Number) ngx_time()); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_now(lua_State *L) +{ + ngx_time_t *tp; + + tp = ngx_timeofday(); + + lua_pushnumber(L, (lua_Number) (tp->sec + tp->msec / 1000.0L)); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_update_time(lua_State *L) +{ + ngx_time_update(); + return 0; +} + + +static int +ngx_tcp_lua_ngx_utctime(lua_State *L) +{ + ngx_tm_t tm; + + u_char buf[sizeof("2010-11-19 20:56:31") - 1]; + + ngx_gmtime(ngx_time(), &tm); + + ngx_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", tm.ngx_tm_year, + tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, + tm.ngx_tm_sec); + + lua_pushlstring(L, (char *) buf, sizeof(buf)); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_cookie_time(lua_State *L) +{ + time_t t; + u_char *p; + + u_char buf[sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1]; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + t = (time_t) luaL_checknumber(L, 1); + + p = buf; + p = ngx_http_cookie_time(p, t); + + lua_pushlstring(L, (char *) buf, p - buf); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_http_time(lua_State *L) +{ + time_t t; + u_char *p; + + u_char buf[sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1]; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + t = (time_t) luaL_checknumber(L, 1); + + p = buf; + p = ngx_http_time(p, t); + + lua_pushlstring(L, (char *) buf, p - buf); + + return 1; +} + + +static int +ngx_tcp_lua_ngx_parse_http_time(lua_State *L) +{ + u_char *p; + size_t len; + time_t time; + + if (lua_gettop(L) != 1) { + return luaL_error(L, "expecting one argument"); + } + + p = (u_char *) luaL_checklstring(L, 1, &len); + + time = ngx_http_parse_time(p, len); + if (time == NGX_ERROR) { + lua_pushnil(L); + return 1; + } + + lua_pushnumber(L, (lua_Number) time); + + return 1; +} + + +void +ngx_tcp_lua_inject_time_api(lua_State *L) +{ + lua_pushcfunction(L, ngx_tcp_lua_ngx_utctime); + lua_setfield(L, -2, "utctime"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_time); + lua_setfield(L, -2, "get_now_ts"); /* deprecated */ + + lua_pushcfunction(L, ngx_tcp_lua_ngx_localtime); + lua_setfield(L, -2, "get_now"); /* deprecated */ + + lua_pushcfunction(L, ngx_tcp_lua_ngx_localtime); + lua_setfield(L, -2, "localtime"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_time); + lua_setfield(L, -2, "time"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_now); + lua_setfield(L, -2, "now"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_update_time); + lua_setfield(L, -2, "update_time"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_today); + lua_setfield(L, -2, "get_today"); /* deprecated */ + + lua_pushcfunction(L, ngx_tcp_lua_ngx_today); + lua_setfield(L, -2, "today"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_cookie_time); + lua_setfield(L, -2, "cookie_time"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_http_time); + lua_setfield(L, -2, "http_time"); + + lua_pushcfunction(L, ngx_tcp_lua_ngx_parse_http_time); + lua_setfield(L, -2, "parse_http_time"); +} + diff --git a/src/ngx_tcp_lua_time.h b/src/ngx_tcp_lua_time.h new file mode 100644 index 0000000..819a298 --- /dev/null +++ b/src/ngx_tcp_lua_time.h @@ -0,0 +1,12 @@ +#ifndef NGX_TCP_LUA_TIME_H +#define NGX_TCP_LUA_TIME_H + + +#include "ngx_tcp_lua_common.h" + + +void ngx_tcp_lua_inject_time_api(lua_State *L); + + +#endif /* NGX_HTTP_LUA_TIME_H */ + From e7e96d5533bc12894d7cc9fed4b7d6be2c20a353 Mon Sep 17 00:00:00 2001 From: humboldt Date: Wed, 13 Nov 2013 13:32:20 +0800 Subject: [PATCH 07/22] fix conf --- config | 5 +- src/ngx_tcp_lua_common.h | 17 ++++++- src/ngx_tcp_lua_module.c | 98 ++++++++++++++++++++++++++++++++++++++-- src/ngx_tcp_lua_output.c | 2 +- src/ngx_tcp_lua_shdict.c | 6 +++ src/ngx_tcp_lua_util.c | 32 +++++++------ 6 files changed, 138 insertions(+), 22 deletions(-) diff --git a/config b/config index 9546490..a0b687c 100644 --- a/config +++ b/config @@ -168,5 +168,8 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_tcp.c \ $ngx_addon_dir/src/ngx_tcp_lua_exception.c \ $ngx_addon_dir/src/ngx_tcp_lua_output.c \ $ngx_addon_dir/src/ngx_tcp_lua_socket.c \ - $ngx_addon_dir/src/ngx_tcp_lua_log.c" + $ngx_addon_dir/src/ngx_tcp_lua_log.c \ + $ngx_addon_dir/src/ngx_tcp_lua_time.c \ + $ngx_addon_dir/src/ngx_tcp_lua_shdict.c \ + $ngx_addon_dir/src/ngx_tcp_lua_string.c" diff --git a/src/ngx_tcp_lua_common.h b/src/ngx_tcp_lua_common.h index 7a91b5c..cac7372 100755 --- a/src/ngx_tcp_lua_common.h +++ b/src/ngx_tcp_lua_common.h @@ -36,14 +36,27 @@ #define NGX_TCP_LUA_FILE_KEY_LEN \ (NGX_TCP_LUA_FILE_TAG_LEN + 2 * MD5_DIGEST_LENGTH) -typedef struct ngx_tcp_lua_main_conf_s { +typedef struct ngx_tcp_lua_main_conf_s ngx_tcp_lua_main_conf_t; + +typedef ngx_int_t (*ngx_tcp_lua_conf_handler_pt)(ngx_log_t *log, + ngx_tcp_lua_main_conf_t *lmcf, lua_State *L); + +struct ngx_tcp_lua_main_conf_s { lua_State *lua; ngx_str_t lua_path; ngx_str_t lua_cpath; + ngx_tcp_lua_conf_handler_pt init_handler; + ngx_pool_t *pool; -} ngx_tcp_lua_main_conf_t; + + ngx_array_t *shm_zones; /* of ngx_shm_zone_t* */ + + ngx_uint_t shm_zones_inited; + + unsigned requires_shm:1; +} ; typedef struct ngx_tcp_lua_srv_conf_s { diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index e7343f0..65de4de 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -3,6 +3,7 @@ #include "ngx_tcp_lua_common.h" #include "ngx_tcp_lua_cache.h" #include "ngx_tcp_lua_util.h" +#include "ngx_tcp_lua_shdict.h" static void ngx_tcp_lua_init_session(ngx_tcp_session_t *s); @@ -27,6 +28,9 @@ void ngx_tcp_lua_reset_ctx(ngx_tcp_session_t *r, lua_State *L, ngx_tcp_lua_ctx_t static char *ngx_tcp_lua_lowat_check(ngx_conf_t *cf, void *post, void *data); char *ngx_tcp_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char * ngx_tcp_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + + static ngx_tcp_protocol_t ngx_tcp_lua_protocol = { ngx_string("tcp_lua"), @@ -46,12 +50,12 @@ static ngx_conf_post_t ngx_tcp_lua_lowat_post = static ngx_command_t ngx_tcp_lua_commands[] = { - /*{ ngx_string("lua_shared_dict"), + { ngx_string("lua_shared_dict"), NGX_TCP_MAIN_CONF|NGX_CONF_TAKE2, - ngx_http_lua_shared_dict, + ngx_tcp_lua_shared_dict, 0, 0, - NULL },*/ + NULL }, { ngx_string("lua_package_cpath"), NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1, ngx_tcp_lua_package_cpath, @@ -710,3 +714,91 @@ ngx_tcp_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +char * +ngx_tcp_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_tcp_lua_main_conf_t *lmcf = conf; + + ngx_str_t *value, name; + ngx_shm_zone_t *zone; + ngx_shm_zone_t **zp; + ngx_tcp_lua_shdict_ctx_t *ctx; + ssize_t size; + + if (lmcf->shm_zones == NULL) { + lmcf->shm_zones = ngx_palloc(cf->pool, sizeof(ngx_array_t)); + if (lmcf->shm_zones == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid shm_zones "); + return NGX_CONF_ERROR; + } + + ngx_array_init(lmcf->shm_zones, cf->pool, 2, sizeof(ngx_shm_zone_t *)); + } + + value = cf->args->elts; + + ctx = NULL; + + if (value[1].len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid lua shared dict name \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + name = value[1]; + + size = ngx_parse_size(&value[2]); + /*ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "shared dict name \"%d\" %d size \"%V\"",name.data,lmcf->shm_zones->nelts ,&value[2]);*/ + + if (size <= 8191) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid lua shared dict size \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } + + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_tcp_lua_shdict_ctx_t)); + if (ctx == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "alloc ctx error"); + return NGX_CONF_ERROR; + } + + ctx->name = name; + ctx->main_conf = lmcf; + ctx->log = &cf->cycle->new_log; + + zone = ngx_shared_memory_add(cf, &name, (size_t) size, + &ngx_tcp_lua_module); + if (zone == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "add shm_zones error"); + return NGX_CONF_ERROR; + } + + if (zone->data) { + ctx = zone->data; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "lua_shared_dict \"%V\" is already defined as \"%V\"", + &name, &ctx->name); + return NGX_CONF_ERROR; + } + + zone->init = ngx_tcp_lua_shdict_init_zone; + zone->data = ctx; + + zp = ngx_array_push(lmcf->shm_zones); + if (zp == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "push shm_zones error"); + return NGX_CONF_ERROR; + } + + *zp = zone; + + lmcf->requires_shm = 1; + + return NGX_CONF_OK; +} diff --git a/src/ngx_tcp_lua_output.c b/src/ngx_tcp_lua_output.c index 36578b1..151e8df 100755 --- a/src/ngx_tcp_lua_output.c +++ b/src/ngx_tcp_lua_output.c @@ -228,7 +228,7 @@ ngx_tcp_lua_ngx_exit(lua_State *L) if (ctx == NULL) { return luaL_error(L, "no request ctx found"); } - ctx->exited = 1; + ctx->exited = 1; return lua_yield(L,0); diff --git a/src/ngx_tcp_lua_shdict.c b/src/ngx_tcp_lua_shdict.c index 19bd3fd..3fa7481 100644 --- a/src/ngx_tcp_lua_shdict.c +++ b/src/ngx_tcp_lua_shdict.c @@ -284,6 +284,8 @@ ngx_tcp_lua_inject_shdict_api(ngx_tcp_lua_main_conf_t *lmcf, lua_State *L) ngx_uint_t i; ngx_shm_zone_t **zone; + //ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, " init shm api %d\n",lmcf->shm_zones->nelts); + if (lmcf->shm_zones != NULL) { lua_createtable(L, 0, lmcf->shm_zones->nelts /* nrec */); /* ngx.shared */ @@ -320,8 +322,11 @@ ngx_tcp_lua_inject_shdict_api(ngx_tcp_lua_main_conf_t *lmcf, lua_State *L) zone = lmcf->shm_zones->elts; for (i = 0; i < lmcf->shm_zones->nelts; i++) { + ctx = zone[i]->data; + //ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0," set shm %d %s\n", ctx->name.data,(char*)ctx->name.data); + lua_pushlstring(L, (char *) ctx->name.data, ctx->name.len); /* shared mt key */ @@ -1123,6 +1128,7 @@ ngx_tcp_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, if (len != sizeof(u_char)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua boolean " "value size found for key %*s: %lu", key_len, + key_data, (unsigned long) len); ngx_shmtx_unlock(&ctx->shpool->mutex); diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 1a257cc..ad36826 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -1,6 +1,4 @@ -//http ext -//#include "lua_module/ngx_http_lua_shdict.h" //tcp only #include "ngx_md5.h" #include "ngx_tcp_lua_util.h" @@ -8,6 +6,9 @@ #include "ngx_tcp_lua_socket.h" #include "ngx_tcp_lua_exception.h" #include "ngx_tcp_lua_log.h" +#include "ngx_tcp_lua_string.h" +#include "ngx_tcp_lua_time.h" +#include "ngx_tcp_lua_shdict.h" char ngx_tcp_lua_code_cache_key; @@ -27,7 +28,7 @@ static char ngx_tcp_lua_coroutines_key; #define AUX_MARK "\1" void ngx_tcp_lua_create_new_global_table(lua_State *L, int narr, int nrec); -static void ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L); +static void ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t *lmcf); void ngx_tcp_lua_inject_core_consts(lua_State *L); @@ -95,7 +96,7 @@ ngx_tcp_lua_init_registry(ngx_conf_t *cf, lua_State *L) static void -ngx_tcp_lua_init_globals(ngx_conf_t *cf, lua_State *L) +ngx_tcp_lua_init_globals(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t *lmcf) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "lua initializing lua globals"); @@ -106,17 +107,14 @@ ngx_tcp_lua_init_globals(ngx_conf_t *cf, lua_State *L) /* }}} */ - ngx_tcp_lua_inject_ngx_api(cf, L); + ngx_tcp_lua_inject_ngx_api(cf, L, lmcf); } static void -ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) +ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t *lmcf) { - /*ngx_http_lua_main_conf_t *lmcf; - lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_tcp_lua_module); -*/ lua_createtable(L, 0 /* narr */, 89 /* nrec */); /* ngx.* */ ngx_tcp_lua_inject_core_consts(L); @@ -124,12 +122,16 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L) ngx_tcp_lua_inject_log_api(L); ngx_tcp_lua_inject_output_api(L); + + ngx_tcp_lua_inject_string_api(L); ngx_tcp_lua_inject_req_socket_api(L); ngx_tcp_lua_inject_socket_api(cf->log, L); - //ngx_http_lua_inject_shdict_api(lmcf, L); + ngx_tcp_lua_inject_time_api(L); + + ngx_tcp_lua_inject_shdict_api(lmcf, L); lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ @@ -220,7 +222,7 @@ ngx_tcp_lua_new_state(ngx_conf_t *cf, ngx_tcp_lua_main_conf_t *lmcf) lua_remove(L, -1); /* remove the "package" table */ ngx_tcp_lua_init_registry(cf, L); - ngx_tcp_lua_init_globals(cf, L); + ngx_tcp_lua_init_globals(cf, L, lmcf); return L; } @@ -393,11 +395,11 @@ ngx_tcp_lua_run_thread(lua_State *L, ngx_tcp_session_t *s, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua thread yielded"); - if(ctx->exited != 1){ + if(ctx->exited != 1){ - lua_settop(cc, 0); - return NGX_AGAIN; - } + lua_settop(cc, 0); + return NGX_AGAIN; + } case 0: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, From a11a08c281d03df3732c744db922127c8838ad35 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Wed, 26 Mar 2014 11:25:25 +0800 Subject: [PATCH 08/22] add string --- src/.ngx_tcp_lua_socket.c.swp | Bin 0 -> 126976 bytes src/log | 106 ++++++++++++ src/lua_module_x | 1 + src/ngx_tcp_lua_shdict.c | 2 +- src/ngx_tcp_lua_socket.c | 23 +-- src/ngx_tcp_lua_string.c | 313 ++++++++++++++++++++++++++++++++-- src/ngx_tcp_lua_string.h | 2 +- src/ngx_tcp_lua_time.c | 4 +- src/ngx_tcp_lua_util.c | 3 + src/ngx_tcp_lua_variable.c | 283 ++++++++++++++++++++++++++++++ src/ngx_tcp_lua_variable.h | 12 ++ 11 files changed, 721 insertions(+), 28 deletions(-) create mode 100644 src/.ngx_tcp_lua_socket.c.swp create mode 100644 src/log create mode 120000 src/lua_module_x create mode 100644 src/ngx_tcp_lua_variable.c create mode 100644 src/ngx_tcp_lua_variable.h diff --git a/src/.ngx_tcp_lua_socket.c.swp b/src/.ngx_tcp_lua_socket.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..f192f4e233459dd3b3d1dd31631cdd8df4605c0c GIT binary patch literal 126976 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 CfUj8q literal 0 HcmV?d00001 diff --git a/src/log b/src/log new file mode 100644 index 0000000..0e3ac73 --- /dev/null +++ b/src/log @@ -0,0 +1,106 @@ +ngx_tcp_access.c: if (s->connection->sockaddr->sa_family != AF_INET) { +ngx_tcp_access.c: sin = (struct sockaddr_in *) s->connection->sockaddr; +ngx_tcp_access.c: ngx_log_debug3(NGX_LOG_DEBUG, s->connection->log, 0, +ngx_tcp_access.c: ngx_log_error(NGX_LOG_NOTICE, s->connection->log, 0, +ngx_tcp_lua_log.c: if (s && s->connection && s->connection->log) { +ngx_tcp_lua_log.c: if (s && s->connection && s->connection->log) { +ngx_tcp_lua_log.c: if (level > s->connection->log->log_level) { +ngx_tcp_lua_log.c: ngx_log_error(level, s->connection->log, 0, "%s%s", ident, buf); +ngx_tcp_lua_module.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_module.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_module.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +ngx_tcp_lua_output.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_output.c: chain = s->connection->send_chain(s->connection, cl, 0); +ngx_tcp_lua_output.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: chain = s->connection->send_chain(s->connection, cl, 0); +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: pc->log = s->connection->log; +ngx_tcp_lua_socket.c: s->connection->single_connection = 0; +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug4(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: c->sendfile &= s->connection->sendfile; +ngx_tcp_lua_socket.c: c->log = s->connection->log; +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->session->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, u->session->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, u->session->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug3(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: cl = ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_tcp_lua_socket_free_pool(r->connection->log, spool); +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: s->connection->log); +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: pc->log = s->connection->log; +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_socket.c: cl = ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, +ngx_tcp_lua_socket.c: new_cl = ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, +ngx_tcp_lua_util.c: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, +ngx_tcp_session.c: if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE, +ngx_tcp_session.c: ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, +ngx_tcp_session.c: if (setsockopt(s->connection->fd, IPPROTO_TCP, TCP_NODELAY, +ngx_tcp_session.c: ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, +ngx_tcp_session.c: s->connection->tcp_nodelay = NGX_TCP_NODELAY_SET; +ngx_tcp_session.c: ngx_tcp_send(s->connection->write); +ngx_tcp_session.c: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, s->connection->log, 0, +ngx_tcp_session.c: ngx_log_debug0(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, +ngx_tcp_session.c: && s->connection->read->active) +ngx_tcp_session.c: if (ngx_del_event(s->connection->read, NGX_READ_EVENT, 0) != NGX_OK) { diff --git a/src/lua_module_x b/src/lua_module_x new file mode 120000 index 0000000..4d6fbe3 --- /dev/null +++ b/src/lua_module_x @@ -0,0 +1 @@ +../../lua-nginx-module-0.7.2/src/ \ No newline at end of file diff --git a/src/ngx_tcp_lua_shdict.c b/src/ngx_tcp_lua_shdict.c index 3fa7481..07ea367 100644 --- a/src/ngx_tcp_lua_shdict.c +++ b/src/ngx_tcp_lua_shdict.c @@ -99,7 +99,7 @@ ngx_tcp_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) /*if (lmcf->shm_zones_inited == lmcf->shm_zones->nelts && lmcf->init_handler) { if (lmcf->init_handler(ctx->log, lmcf, lmcf->lua) != 0) { - /* an error happened * / + * an error happened * / return NGX_ERROR; } }*/ diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index e0d7b10..b008a26 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -204,15 +204,12 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) { ngx_tcp_session_t *s; ngx_tcp_lua_ctx_t *ctx; - const char *p; - size_t len; - size_t size; - ngx_buf_t *b; - ngx_chain_t *cl, *chain; - int i; - int nargs; - int type; - const char *msg; + const u_char *p; + size_t size; + ngx_buf_t *b; + ngx_chain_t *cl, *chain; + int type; + const char *msg; //ngx_buf_tag_t tag; if (lua_gettop(L) != 2) { return luaL_error(L, "expecting 2 arguments (including the object), " @@ -2241,7 +2238,13 @@ ngx_tcp_lua_socket_test_connect(ngx_connection_t *c) } if (err) { - (void) ngx_connection_error(c, err, "connect() failed"); + char errstr[255]; + char * addr=""; + if(c->sockaddr){ + addr= inet_ntoa(((struct sockaddr_in*)(c->sockaddr))->sin_addr); + } + snprintf(errstr,255,"connect() %s failed",addr); + (void) ngx_connection_error(c, err, errstr); return err; } } diff --git a/src/ngx_tcp_lua_string.c b/src/ngx_tcp_lua_string.c index b68b9d0..a04ae37 100644 --- a/src/ngx_tcp_lua_string.c +++ b/src/ngx_tcp_lua_string.c @@ -42,8 +42,8 @@ static int ngx_tcp_lua_ngx_decode_base64(lua_State *L); static int ngx_tcp_lua_ngx_encode_base64(lua_State *L); static int ngx_tcp_lua_ngx_crc32_short(lua_State *L); static int ngx_tcp_lua_ngx_crc32_long(lua_State *L); -static int ngx_tcp_lua_ngx_encode_args(lua_State *L); -static int ngx_tcp_lua_ngx_decode_args(lua_State *L); +//static int ngx_tcp_lua_ngx_encode_args(lua_State *L); +//static int ngx_tcp_lua_ngx_decode_args(lua_State *L); #if (NGX_OPENSSL) static int ngx_tcp_lua_ngx_hmac_sha1(lua_State *L); #endif @@ -52,13 +52,13 @@ static int ngx_tcp_lua_ngx_hmac_sha1(lua_State *L); void ngx_tcp_lua_inject_string_api(lua_State *L) { - /*lua_pushcfunction(L, ngx_tcp_lua_ngx_escape_uri); + lua_pushcfunction(L, ngx_tcp_lua_ngx_escape_uri); lua_setfield(L, -2, "escape_uri"); lua_pushcfunction(L, ngx_tcp_lua_ngx_unescape_uri); lua_setfield(L, -2, "unescape_uri"); - lua_pushcfunction(L, ngx_tcp_lua_ngx_encode_args); + /*lua_pushcfunction(L, ngx_tcp_lua_ngx_encode_args); lua_setfield(L, -2, "encode_args"); lua_pushcfunction(L, ngx_tcp_lua_ngx_decode_args); @@ -96,7 +96,293 @@ ngx_tcp_lua_inject_string_api(lua_State *L) #endif } -/* + +uintptr_t +ngx_tcp_lua_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) +{ + ngx_uint_t n; + uint32_t *escape; + static u_char hex[] = "0123456789abcdef"; + + /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ + + static uint32_t uri[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0xfc00886d, /* 1111 1100 0000 0000 1000 1000 0110 1101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x78000000, /* 0111 1000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xa8000000, /* 1010 1000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */ + + static uint32_t args[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ + + static uint32_t html[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* " ", """, "%", "'", %00-%1F, %7F-%FF */ + + static uint32_t refresh[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* " ", "%", %00-%1F */ + + static uint32_t memcached[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x00000021, /* 0000 0000 0000 0000 0000 0000 0010 0001 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + }; + + /* mail_auth is the same as memcached */ + + static uint32_t *map[] = + { uri, args, html, refresh, memcached, memcached }; + + + escape = map[type]; + + if (dst == NULL) { + + /* find the number of the characters to be escaped */ + + n = 0; + + while (size) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + n++; + } + src++; + size--; + } + + return (uintptr_t) n; + } + + while (size) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + *dst++ = '%'; + *dst++ = hex[*src >> 4]; + *dst++ = hex[*src & 0xf]; + src++; + + } else { + *dst++ = *src++; + } + size--; + } + + return (uintptr_t) dst; +} + + +/* XXX we also decode '+' to ' ' */ +void +ngx_tcp_lua_unescape_uri(u_char **dst, u_char **src, size_t size, + ngx_uint_t type) +{ + u_char *d, *s, ch, c, decoded; + enum { + sw_usual = 0, + sw_quoted, + sw_quoted_second + } state; + + d = *dst; + s = *src; + + state = 0; + decoded = 0; + + while (size--) { + + ch = *s++; + + switch (state) { + case sw_usual: + if (ch == '?' + && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT))) + { + *d++ = ch; + goto done; + } + + if (ch == '%') { + state = sw_quoted; + break; + } + + if (ch == '+') { + *d++ = ' '; + break; + } + + *d++ = ch; + break; + + case sw_quoted: + + if (ch >= '0' && ch <= '9') { + decoded = (u_char) (ch - '0'); + state = sw_quoted_second; + break; + } + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { + decoded = (u_char) (c - 'a' + 10); + state = sw_quoted_second; + break; + } + + /* the invalid quoted character */ + + state = sw_usual; + + *d++ = ch; + + break; + + case sw_quoted_second: + + state = sw_usual; + + if (ch >= '0' && ch <= '9') { + ch = (u_char) ((decoded << 4) + ch - '0'); + + if (type & NGX_UNESCAPE_REDIRECT) { + if (ch > '%' && ch < 0x7f) { + *d++ = ch; + break; + } + + *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1); + break; + } + + *d++ = ch; + + break; + } + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { + ch = (u_char) ((decoded << 4) + c - 'a' + 10); + + if (type & NGX_UNESCAPE_URI) { + if (ch == '?') { + *d++ = ch; + goto done; + } + + *d++ = ch; + break; + } + + if (type & NGX_UNESCAPE_REDIRECT) { + if (ch == '?') { + *d++ = ch; + goto done; + } + + if (ch > '%' && ch < 0x7f) { + *d++ = ch; + break; + } + + *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1); + break; + } + + *d++ = ch; + + break; + } + + /* the invalid quoted character */ + + break; + } + } + +done: + + *dst = d; + *src = s; +} + + + static int ngx_tcp_lua_ngx_escape_uri(lua_State *L) { @@ -144,9 +430,9 @@ ngx_tcp_lua_ngx_escape_uri(lua_State *L) lua_pushlstring(L, (char *) dst, dlen); return 1; -}*/ +} + -/* static int ngx_tcp_lua_ngx_unescape_uri(lua_State *L) { @@ -170,7 +456,7 @@ ngx_tcp_lua_ngx_unescape_uri(lua_State *L) src = (u_char *) luaL_checklstring(L, 1, &len); - / * the unescaped string can only be smaller * / + /* the unescaped string can only be smaller */ dlen = len; p = ngx_palloc(r->pool, dlen); @@ -185,7 +471,7 @@ ngx_tcp_lua_ngx_unescape_uri(lua_State *L) lua_pushlstring(L, (char *) p, dst - p); return 1; -}*/ +} static int @@ -579,17 +865,16 @@ ngx_tcp_lua_ngx_encode_args(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - ngx_tcp_lua_process_args_option(r, L, 1, &args); + ngx_http_lua_process_args_option(r, L, 1, &args); lua_pushlstring(L, (char *) args.data, args.len); ngx_pfree(r->pool, args.data); return 1; -} - +}*/ -static int +/*static int ngx_tcp_lua_ngx_decode_args(lua_State *L) { ngx_tcp_session_t *r; u_char *buf; @@ -627,7 +912,7 @@ ngx_tcp_lua_ngx_decode_args(lua_State *L) { last = buf + len; - return ngx_tcp_lua_parse_args(r, L, buf, last, max); + return ngx_http_lua_parse_args(r, L, buf, last, max); }*/ diff --git a/src/ngx_tcp_lua_string.h b/src/ngx_tcp_lua_string.h index 3f87a60..8804186 100644 --- a/src/ngx_tcp_lua_string.h +++ b/src/ngx_tcp_lua_string.h @@ -3,7 +3,7 @@ #include "ngx_tcp_lua_common.h" - +#define NGX_UNESCAPE_URI_COMPONENT 0 void ngx_tcp_lua_inject_string_api(lua_State *L); diff --git a/src/ngx_tcp_lua_time.c b/src/ngx_tcp_lua_time.c index 722d953..e05ec8a 100644 --- a/src/ngx_tcp_lua_time.c +++ b/src/ngx_tcp_lua_time.c @@ -2,10 +2,10 @@ #define DDEBUG 0 #endif //#include "ddebug.h" - #include "ngx_tcp_lua_time.h" - +extern u_char *ngx_http_time(u_char *buf, time_t t); +extern time_t ngx_http_parse_time(u_char *value, size_t len); static int ngx_tcp_lua_ngx_today(lua_State *L); static int ngx_tcp_lua_ngx_time(lua_State *L); static int ngx_tcp_lua_ngx_now(lua_State *L); diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index ad36826..7af1f31 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -9,6 +9,7 @@ #include "ngx_tcp_lua_string.h" #include "ngx_tcp_lua_time.h" #include "ngx_tcp_lua_shdict.h" +#include "ngx_tcp_lua_variable.h" char ngx_tcp_lua_code_cache_key; @@ -133,6 +134,8 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t ngx_tcp_lua_inject_shdict_api(lmcf, L); + ngx_tcp_lua_inject_variable_api(L); + lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ lua_pushvalue(L, -3); /* ngx package loaded ngx */ diff --git a/src/ngx_tcp_lua_variable.c b/src/ngx_tcp_lua_variable.c new file mode 100644 index 0000000..fc50030 --- /dev/null +++ b/src/ngx_tcp_lua_variable.c @@ -0,0 +1,283 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif + +#include "ngx_tcp_lua_variable.h" +#include "ngx_tcp_lua_util.h" +#include "ngx_http_variables.h" + + +static int ngx_tcp_lua_var_get(lua_State *L); +static int ngx_tcp_lua_var_set(lua_State *L); + + +void +ngx_tcp_lua_inject_variable_api(lua_State *L) +{ + /* register reference maps */ + lua_newtable(L); /* ngx.var */ + + lua_createtable(L, 0, 2 /* nrec */); /* metatable for .var */ + lua_pushcfunction(L, ngx_tcp_lua_var_get); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, ngx_tcp_lua_var_set); + lua_setfield(L, -2, "__newindex"); + lua_setmetatable(L, -2); + + lua_setfield(L, -2, "var"); +} + + +/** + * Get nginx internal variables content + * + * @retval Always return a string or nil on Lua stack. Return nil when failed + * to get content, and actual content string when found the specified variable. + * @seealso ngx_tcp_lua_var_set + * */ +static int +ngx_tcp_lua_var_get(lua_State *L) +{ + ngx_tcp_session_t *s; + u_char *p, *lowcase; + size_t len; + ngx_uint_t hash; + ngx_str_t name; + ngx_http_variable_value_t *vv; +/* +#if (NGX_PCRE) + u_char *val; + ngx_uint_t n; + LUA_NUMBER index; + int *cap; +#endif +*/ + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + s = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (s == NULL) { + return luaL_error(L, "no request object found"); + } + +/*#if (NGX_PCRE)*/ +#if (0) + if (lua_type(L, -1) == LUA_TNUMBER) { + /* it is a regex capturing variable */ + + index = lua_tonumber(L, -1); + + if (index <= 0) { + lua_pushnil(L); + return 1; + } + + n = (ngx_uint_t) index * 2; + + /*dd("n = %d, ncaptures = %d", (int) n, (int) s->ncaptures);*/ + + if (s->captures == NULL || s->captures_data == NULL || + n >= s->ncaptures) + { + lua_pushnil(L); + return 1; + } + + /* n >= 0 && n < r->ncaptures */ + + cap = s->captures; + + p = s->captures_data; + + val = &p[cap[n]]; + + lua_pushlstring(L, (const char *) val, (size_t) (cap[n + 1] - cap[n])); + + return 1; + } +#endif + + p = (u_char *) luaL_checklstring(L, -1, &len); + + lowcase = ngx_palloc(s->pool, len); + if (lowcase == NULL) { + return luaL_error(L, "memory allocation error"); + } + + hash = ngx_hash_strlow(lowcase, p, len); + + name.len = len; + name.data = lowcase; + + vv = ngx_http_get_variable(s, &name, hash); + + if (vv == NULL || vv->not_found) { + lua_pushnil(L); + return 1; + } + + lua_pushlstring(L, (const char *) vv->data, (size_t) vv->len); + + return 1; +} + + +/** + * Set nginx internal variable content + * + * @retval Always return a boolean on Lua stack. Return true when variable + * content was modified successfully, false otherwise. + * @seealso ngx_tcp_lua_var_get + * */ +static int +ngx_tcp_lua_var_set(lua_State *L) +{ + ngx_http_variable_t *v; + ngx_http_variable_value_t *vv; + ngx_tcp_core_main_conf_t *cmcf; + u_char *p, *lowcase, *val; + size_t len; + ngx_str_t name; + ngx_uint_t hash; + ngx_tcp_session_t *s; + int value_type; + const char *msg; + + lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); + lua_rawget(L, LUA_GLOBALSINDEX); + s = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (s == NULL) { + return luaL_error(L, "no request object found"); + } + + /* we skip the first argument that is the table */ + + /* we read the variable name */ + + p = (u_char *) luaL_checklstring(L, 2, &len); + + lowcase = ngx_palloc(r->pool, len + 1); + if (lowcase == NULL) { + return luaL_error(L, "memory allocation error"); + } + + lowcase[len] = '\0'; + + hash = ngx_hash_strlow(lowcase, p, len); + + name.len = len; + name.data = lowcase; + + /* we read the variable new value */ + + value_type = lua_type(L, 3); + switch (value_type) { + case LUA_TNUMBER: + case LUA_TSTRING: + p = (u_char *) luaL_checklstring(L, 3, &len); + + val = ngx_palloc(r->pool, len); + if (val == NULL) { + return luaL_error(L, "memory allocation erorr"); + } + + ngx_memcpy(val, p, len); + + break; + + case LUA_TNIL: + /* undef the variable */ + + val = NULL; + len = 0; + + break; + + default: + msg = lua_pushfstring(L, "string, number, or nil expected, " + "but got %s", lua_typename(L, value_type)); + return luaL_argerror(L, 1, msg); + } + + /* we fetch the variable itself */ + + cmcf = ngx_tcp_get_module_main_conf(r, ngx_tcp_core_module); + + v = ngx_hash_find(&cmcf->variables_hash, hash, name.data, name.len); + + if (v) { + if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { + return luaL_error(L, "variable \"%s\" not changeable", lowcase); + } + + if (v->set_handler) { + + dd("set variables with set_handler"); + + vv = ngx_palloc(r->pool, sizeof(ngx_tcp_variable_value_t)); + if (vv == NULL) { + return luaL_error(L, "out of memory"); + } + + if (value_type == LUA_TNIL) { + vv->valid = 0; + vv->not_found = 1; + vv->no_cacheable = 0; + vv->data = NULL; + vv->len = 0; + + } else { + vv->valid = 1; + vv->not_found = 0; + vv->no_cacheable = 0; + + vv->data = val; + vv->len = len; + } + + v->set_handler(r, vv, v->data); + + return 0; + } + + if (v->flags & NGX_HTTP_VAR_INDEXED) { + vv = &r->variables[v->index]; + + dd("set indexed variable"); + + if (value_type == LUA_TNIL) { + vv->valid = 0; + vv->not_found = 1; + vv->no_cacheable = 0; + + vv->data = NULL; + vv->len = 0; + + } else { + vv->valid = 1; + vv->not_found = 0; + vv->no_cacheable = 0; + + vv->data = val; + vv->len = len; + } + + return 0; + } + + return luaL_error(L, "variable \"%s\" cannot be assigned a value", + lowcase); + } + + /* variable not found */ + + return luaL_error(L, "varaible \"%s\" not found for writing; " + "maybe it is a built-in variable that is not changeable " + "or you sould have used \"set $%s '';\" earlier " + "in the config file", lowcase, lowcase); +} + diff --git a/src/ngx_tcp_lua_variable.h b/src/ngx_tcp_lua_variable.h new file mode 100644 index 0000000..d5717bc --- /dev/null +++ b/src/ngx_tcp_lua_variable.h @@ -0,0 +1,12 @@ +#ifndef NGX_TCP_LUA_VARIABLE_H +#define NGX_TCP_LUA_VARIABLE_H + + +#include "ngx_tcp_lua_common.h" + + +void ngx_tcp_lua_inject_variable_api(lua_State *L); + + +#endif /* NGX_HTTP_LUA_VARIABLE_H */ + From fc46b9f4312fefefa3bcb737ed67b070707604a6 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Wed, 2 Apr 2014 13:09:44 +0800 Subject: [PATCH 09/22] fix ngx.req.socket() use old upstream userdata,and release memory after send_chain --- config | 3 ++- src/ngx_tcp_lua_shdict.c | 10 ++++----- src/ngx_tcp_lua_socket.c | 46 +++++++++++++++++++++++++++++++++----- src/ngx_tcp_lua_util.c | 3 ++- src/ngx_tcp_lua_util.h | 2 ++ src/ngx_tcp_lua_variable.c | 2 +- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/config b/config index a0b687c..1cdebba 100644 --- a/config +++ b/config @@ -171,5 +171,6 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_tcp.c \ $ngx_addon_dir/src/ngx_tcp_lua_log.c \ $ngx_addon_dir/src/ngx_tcp_lua_time.c \ $ngx_addon_dir/src/ngx_tcp_lua_shdict.c \ - $ngx_addon_dir/src/ngx_tcp_lua_string.c" + $ngx_addon_dir/src/ngx_tcp_lua_string.c " + diff --git a/src/ngx_tcp_lua_shdict.c b/src/ngx_tcp_lua_shdict.c index 07ea367..9fe83ae 100644 --- a/src/ngx_tcp_lua_shdict.c +++ b/src/ngx_tcp_lua_shdict.c @@ -397,7 +397,7 @@ ngx_tcp_lua_shdict_get(lua_State *L) hash = ngx_crc32_short(key.data, key.len); #if (NGX_DEBUG) - ngx_log_debug2(NGX_LOG_DEBUG_TCP, ctx->log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "fetching key \"%V\" in shared dict \"%V\"", &key, &name); #endif /* NGX_DEBUG */ @@ -811,7 +811,7 @@ ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) replace: if (value.data && value.len == (size_t) sd->value_len) { - ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value size matched, " "reusing it"); @@ -848,7 +848,7 @@ ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) return 3; } - ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry bug value size NOT matched, " "removing it first"); @@ -876,7 +876,7 @@ ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) return 3; } - ngx_log_debug0(NGX_LOG_DEBUG_TCP, ctx->log, 0, + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: creating a new entry"); n = offsetof(ngx_rbtree_node_t, color) @@ -888,7 +888,7 @@ ngx_tcp_lua_shdict_set_helper(lua_State *L, int flags) if (node == NULL) { - ngx_log_debug1(NGX_LOG_DEBUG_TCP, ctx->log, 0, + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: overriding non-expired items due to memory " "shortage for entry \"%V\"", &name); diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index b008a26..16f7fe5 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -260,11 +260,19 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) /* do nothing for empty strings */ return 0; } - - b = ngx_create_temp_buf(s->pool, size); - if (b == NULL) { + cl=ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, + &ctx->free_recv_bufs, + size, + (ngx_buf_tag_t) + &ngx_tcp_lua_module); + if (cl == NULL) { return luaL_error(L, "out of memory"); } + b=cl->buf; + /*b = ngx_create_temp_buf(s->pool, size); + if (b == NULL) { + return luaL_error(L, "out of memory"); + }*/ switch (type) { case LUA_TNUMBER: @@ -286,18 +294,27 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) } #endif +#if 0 cl = ngx_alloc_chain_link(s->pool); if (cl == NULL) { return luaL_error(L, "out of memory"); } + cl->next = NULL; cl->buf = b; +#endif - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, - newline ? "lua say response" : "lua print response"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); chain = s->connection->send_chain(s->connection, cl, 0); + + if(chain==cl){ + size=size - ( cl->buf->last - cl->buf->pos ); + } + /* free buf */ + cl->next=ctx->free_recv_bufs; + ctx->free_recv_bufs=cl; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "tcp_lua write chain %p", chain); @@ -1159,7 +1176,7 @@ ngx_tcp_lua_socket_tcp_receive(lua_State *L) u->buffer = *u->buf_in->buf; } - dd("tcp receive: buf_in: %p, bufs_in: %p", u->buf_in, u->bufs_in); + dd("tcp receive:u:%p buf_in: %p, bufs_in: %p",u, u->buf_in, u->bufs_in); u->waiting = 0; @@ -2802,6 +2819,17 @@ ngx_tcp_lua_req_socket(lua_State *L) s = lua_touserdata(L, -1); lua_pop(L, 1); + lua_pushlightuserdata(L, &ngx_tcp_lua_request_socket_key); + lua_rawget(L, LUA_GLOBALSINDEX); + if(!lua_isnil(L,-1)){ + lua_settop(L, 1); + lua_pushnil(L); + return 2; + }else{ + lua_pop(L,1); + } + + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); @@ -2869,6 +2897,10 @@ ngx_tcp_lua_req_socket(lua_State *L) ngx_del_timer(c->read); } + lua_pushlightuserdata(L, &ngx_tcp_lua_request_socket_key); + lua_pushvalue (L,1); + lua_rawset(L, LUA_GLOBALSINDEX); + lua_settop(L, 1); lua_pushnil(L); return 2; @@ -3531,6 +3563,8 @@ ngx_tcp_lua_socket_push_input_data(ngx_tcp_session_t *s, ngx_pfree(s->pool, p); done: + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "push_input done ll:%p nbufs:%d free:%p",ll,nbufs,ctx->free_recv_bufs); if (nbufs > 1 && ll) { dd("recycle buffers: %d", (int) (nbufs - 1)); diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 7af1f31..0dc5dca 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -17,6 +17,7 @@ char ngx_tcp_lua_ctx_tables_key; char ngx_tcp_lua_regex_cache_key; char ngx_tcp_lua_socket_pool_key; char ngx_tcp_lua_request_key; +char ngx_tcp_lua_request_socket_key; /* coroutine anchoring table key in Lua vm registry */ @@ -134,7 +135,7 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t ngx_tcp_lua_inject_shdict_api(lmcf, L); - ngx_tcp_lua_inject_variable_api(L); + /*ngx_tcp_lua_inject_variable_api(L);*/ lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ diff --git a/src/ngx_tcp_lua_util.h b/src/ngx_tcp_lua_util.h index efe3669..67d32d8 100644 --- a/src/ngx_tcp_lua_util.h +++ b/src/ngx_tcp_lua_util.h @@ -28,6 +28,8 @@ extern char ngx_tcp_lua_request_key; extern char ngx_tcp_lua_cf_log_key; +/* char whose address we'll use as key for the nginx request socket pointer */ +extern char ngx_tcp_lua_request_socket_key; lua_State *ngx_tcp_lua_new_state(ngx_conf_t *cf, ngx_tcp_lua_main_conf_t *lmcf); lua_State *ngx_tcp_lua_new_thread(ngx_tcp_session_t *s, lua_State *L, int *ref); diff --git a/src/ngx_tcp_lua_variable.c b/src/ngx_tcp_lua_variable.c index fc50030..545585d 100644 --- a/src/ngx_tcp_lua_variable.c +++ b/src/ngx_tcp_lua_variable.c @@ -63,7 +63,7 @@ ngx_tcp_lua_var_get(lua_State *L) } /*#if (NGX_PCRE)*/ -#if (0) +#if 0 if (lua_type(L, -1) == LUA_TNUMBER) { /* it is a regex capturing variable */ From 37de7087845e709967f8b59a9982878513258807 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Wed, 2 Apr 2014 13:52:06 +0800 Subject: [PATCH 10/22] add preconfiguration --- src/ngx_tcp.c | 15 +++++++++++++++ src/ngx_tcp.h | 1 + src/ngx_tcp_core_module.c | 10 +++++++++- src/ngx_tcp_lua_module.c | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index e95780a..b1c9cde 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -151,6 +151,21 @@ ngx_tcp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) pcf = *cf; cf->ctx = ctx; + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_TCP_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->preconfiguration) { + if (module->preconfiguration(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + } + cf->module_type = NGX_TCP_MODULE; cf->cmd_type = NGX_TCP_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); diff --git a/src/ngx_tcp.h b/src/ngx_tcp.h index 57b15ab..453425e 100755 --- a/src/ngx_tcp.h +++ b/src/ngx_tcp.h @@ -224,6 +224,7 @@ struct ngx_tcp_protocol_s { typedef struct { ngx_tcp_protocol_t *protocol; + ngx_int_t (*preconfiguration)(ngx_conf_t *cf); ngx_int_t (*postconfiguration)(ngx_conf_t *cf); void *(*create_main_conf)(ngx_conf_t *cf); diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 05d9372..3994639 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -6,6 +6,7 @@ #include "ngx_tcp.h" +static void *ngx_tcp_core_preconfiguration(ngx_conf_t *cf); static void *ngx_tcp_core_create_main_conf(ngx_conf_t *cf); static void *ngx_tcp_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, @@ -160,7 +161,8 @@ static ngx_command_t ngx_tcp_core_commands[] = { static ngx_tcp_module_t ngx_tcp_core_module_ctx = { NULL, /* protocol */ - NULL, + ngx_tcp_core_preconfiguration, /*preconfiguration*/ + NULL, /*postconfiguration*/ ngx_tcp_core_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ @@ -188,6 +190,12 @@ ngx_module_t ngx_tcp_core_module = { static ngx_str_t ngx_tcp_access_log = ngx_string("logs/tcp_access.log"); +static void * +ngx_tcp_core_preconfiguration(ngx_conf_t *cf) +{ + return NGX_OK; + /*return ngx_tcp_variables_add_core_vars(cf);*/ +} static void * ngx_tcp_core_create_main_conf(ngx_conf_t *cf) diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 65de4de..4ab4fa2 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -144,6 +144,7 @@ static ngx_command_t ngx_tcp_lua_commands[] = { static ngx_tcp_module_t ngx_tcp_lua_module_ctx = { &ngx_tcp_lua_protocol, /* protocol */ + NULL, /* preconfiguration */ ngx_tcp_lua_init, /* postconfiguration */ ngx_tcp_lua_create_main_conf, /* create main configuration */ From 5d9e52ae693e28703a891ed449569d3dd72b7453 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Wed, 16 Apr 2014 11:20:47 +0800 Subject: [PATCH 11/22] add variable module and ngx.var --- src/ngx_tcp_variables.c | 1008 +++++++++++++++++++++++++++++++++++++++ src/ngx_tcp_variables.h | 120 +++++ test/t/0005-req_var.t | 29 ++ 3 files changed, 1157 insertions(+) create mode 100644 src/ngx_tcp_variables.c create mode 100644 src/ngx_tcp_variables.h create mode 100644 test/t/0005-req_var.t diff --git a/src/ngx_tcp_variables.c b/src/ngx_tcp_variables.c new file mode 100644 index 0000000..22b72db --- /dev/null +++ b/src/ngx_tcp_variables.c @@ -0,0 +1,1008 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include "ngx_tcp.h" +#include "ngx_tcp_variables.h" +/* +static ngx_int_t ngx_tcp_variable_unknown_header_in(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_tcp_variable_unknown_header_out(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +#if (NGX_HAVE_TCP_INFO) +static ngx_int_t ngx_tcp_variable_tcpinfo(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +#endif +*/ + +static ngx_int_t ngx_tcp_variable_binary_remote_addr(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_tcp_variable_remote_addr(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_tcp_variable_remote_port(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); + + +static ngx_int_t ngx_tcp_variable_nginx_version(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_tcp_variable_hostname(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_tcp_variable_pid(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); + +/* + * TODO: + * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED + * REMOTE_HOST (null), REMOTE_IDENT (null), + * SERVER_SOFTWARE + * + * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner) + */ + +/* + * the $tcp_host, $tcp_user_agent, $tcp_referer, $tcp_via, + * and $tcp_x_forwarded_for variables may be handled by generic + * ngx_tcp_variable_unknown_header_in(), but for performance reasons + * they are handled using dedicated entries + */ + +static ngx_tcp_variable_t ngx_tcp_core_variables[] = { + + { ngx_string("binary_remote_addr"), NULL, + ngx_tcp_variable_binary_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_addr"), NULL, ngx_tcp_variable_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_port"), NULL, ngx_tcp_variable_remote_port, 0, 0, 0 }, + + { ngx_string("nginx_version"), NULL, ngx_tcp_variable_nginx_version, + 0, 0, 0 }, + + { ngx_string("hostname"), NULL, ngx_tcp_variable_hostname, + 0, 0, 0 }, + + { ngx_string("pid"), NULL, ngx_tcp_variable_pid, + 0, 0, 0 }, + +#if (NGX_HAVE_TCP_INFO) + { ngx_string("tcpinfo_rtt"), NULL, ngx_tcp_variable_tcpinfo, + 0, NGX_TCP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rttvar"), NULL, ngx_tcp_variable_tcpinfo, + 1, NGX_TCP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_tcp_variable_tcpinfo, + 2, NGX_TCP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rcv_space"), NULL, ngx_tcp_variable_tcpinfo, + 3, NGX_TCP_VAR_NOCACHEABLE, 0 }, +#endif + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +ngx_tcp_variable_value_t ngx_tcp_variable_null_value = + ngx_tcp_variable(""); +ngx_tcp_variable_value_t ngx_tcp_variable_true_value = + ngx_tcp_variable("1"); + + +ngx_tcp_variable_t * +ngx_tcp_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) +{ + ngx_int_t rc; + ngx_uint_t i; + ngx_hash_key_t *key; + ngx_tcp_variable_t *v; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + + key = cmcf->variables_keys->keys.elts; + for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { + if (name->len != key[i].key.len + || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) + { + continue; + } + + v = key[i].value; + + if (!(v->flags & NGX_TCP_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + return v; + } + + v = ngx_palloc(cf->pool, sizeof(ngx_tcp_variable_t)); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); + + if (rc == NGX_ERROR) { + return NULL; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", name); + return NULL; + } + + return v; +} + + +ngx_int_t +ngx_tcp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) +{ + ngx_uint_t i; + ngx_tcp_variable_t *v; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + + v = cmcf->variables.elts; + + if (v == NULL) { + if (ngx_array_init(&cmcf->variables, cf->pool, 4, + sizeof(ngx_tcp_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + } else { + for (i = 0; i < cmcf->variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + return i; + } + } + + v = ngx_array_push(&cmcf->variables); + if (v == NULL) { + return NGX_ERROR; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NGX_ERROR; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = 0; + v->index = cmcf->variables.nelts - 1; + + return v->index; +} + + +/*ngx_tcp_variable_value_t * +ngx_tcp_get_indexed_variable(ngx_tcp_session_t *s, ngx_uint_t index) +{ + ngx_tcp_variable_t *v; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); + + if (cmcf->variables.nelts <= index) { + ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0, + "unknown variable index: %d", index); + return NULL; + } + + if (s->variables[index].not_found || s->variables[index].valid) { + return &s->variables[index]; + } + + v = cmcf->variables.elts; + + if (v[index].get_handler(r, &s->variables[index], v[index].data) + == NGX_OK) + { + if (v[index].flags & NGX_TCP_VAR_NOCACHEABLE) { + s->variables[index].no_cacheable = 1; + } + + return &s->variables[index]; + } + + s->variables[index].valid = 0; + s->variables[index].not_found = 1; + + return NULL; +}*/ + + +/*ngx_tcp_variable_value_t * +ngx_tcp_get_flushed_variable(ngx_tcp_session_t *s, ngx_uint_t index) +{ + ngx_tcp_variable_value_t *v; + + v = &s->variables[index]; + + if (v->valid || v->not_found) { + if (!v->no_cacheable) { + return v; + } + + v->valid = 0; + v->not_found = 0; + } + + return ngx_tcp_get_indexed_variable(r, index); +}*/ + + +ngx_tcp_variable_value_t * +ngx_tcp_get_variable(ngx_tcp_session_t *s, ngx_str_t *name, ngx_uint_t key) +{ + ngx_tcp_variable_t *v; + ngx_tcp_variable_value_t *vv; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); + + v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); + + if (v) { + if (v->flags & NGX_TCP_VAR_INDEXED) { + return NULL;//ngx_tcp_get_flushed_variable(r, v->index); + + } else { + + vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); + + if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { + return vv; + } + + return NULL; + } + } + + vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); + if (vv == NULL) { + return NULL; + } + + /*if (ngx_strncmp(name->data, "tcp_", 5) == 0) { + + if (ngx_tcp_variable_unknown_header_in(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "sent_tcp_", 10) == 0) { + + if (ngx_tcp_variable_unknown_header_out(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "upstream_tcp_", 14) == 0) { + + if (ngx_tcp_upstream_header_variable(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + }*/ + + + vv->not_found = 1; + + return vv; +} + + + + + + + + + + + + + + +#if 0 +static ngx_int_t +ngx_tcp_variable_unknown_header_in(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + return ngx_tcp_variable_unknown_header(v, (ngx_str_t *) data, + &s->headers_in.headers.part, + sizeof("tcp_") - 1); +} + + +static ngx_int_t +ngx_tcp_variable_unknown_header_out(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + return ngx_tcp_variable_unknown_header(v, (ngx_str_t *) data, + &s->headers_out.headers.part, + sizeof("sent_tcp_") - 1); +} + + +ngx_int_t +ngx_tcp_variable_unknown_header(ngx_tcp_variable_value_t *v, ngx_str_t *var, + ngx_list_part_t *part, size_t prefix) +{ + u_char ch; + ngx_uint_t i, n; + ngx_table_elt_t *header; + + header = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) { + ch = header[i].key.data[n]; + + if (ch >= 'A' && ch <= 'Z') { + ch |= 0x20; + + } else if (ch == '-') { + ch = '_'; + } + + if (var->data[n + prefix] != ch) { + break; + } + } + + if (n + prefix == var->len && n == header[i].key.len) { + v->len = header[i].value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = header[i].value.data; + + return NGX_OK; + } + } + + v->not_found = 1; + + return NGX_OK; +} +#endif + + + + + +#if (NGX_HAVE_TCP_INFO) + +static ngx_int_t +ngx_tcp_variable_tcpinfo(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, + uintptr_t data) +{ + struct tcp_info ti; + socklen_t len; + uint32_t value; + + len = sizeof(struct tcp_info); + if (getsockopt(s->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_pnalloc(s->pool, NGX_INT32_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (data) { + case 0: + value = ti.tcpi_rtt; + break; + + case 1: + value = ti.tcpi_rttvar; + break; + + case 2: + value = ti.tcpi_snd_cwnd; + break; + + case 3: + value = ti.tcpi_rcv_space; + break; + + /* suppress warning */ + default: + value = 0; + break; + } + + v->len = ngx_sprintf(v->data, "%uD", value) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +#endif + + + +static ngx_int_t +ngx_tcp_variable_binary_remote_addr(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (s->connection->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; + + v->len = sizeof(struct in6_addr); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = sin6->sin6_addr.s6_addr; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) s->connection->sockaddr; + + v->len = sizeof(in_addr_t); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) &sin->sin_addr; + + break; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_tcp_variable_remote_addr(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + v->len = s->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s->connection->addr_text.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_tcp_variable_remote_port(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(s->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (s->connection->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; + port = ntohs(sin6->sin6_port); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) s->connection->sockaddr; + port = ntohs(sin->sin_port); + break; + } + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + +static ngx_int_t +ngx_tcp_variable_nginx_version(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + v->len = sizeof(NGINX_VERSION) - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) NGINX_VERSION; + + return NGX_OK; +} + + +static ngx_int_t +ngx_tcp_variable_hostname(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + v->len = ngx_cycle->hostname.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ngx_cycle->hostname.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_tcp_variable_pid(ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->pool, NGX_INT64_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%P", ngx_pid) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + +#if 0 +void * +ngx_tcp_map_find(ngx_tcp_session_t *s, ngx_tcp_map_t *map, ngx_str_t *match) +{ + void *value; + u_char *low; + size_t len; + ngx_uint_t key; + + len = match->len; + + if (len) { + low = ngx_pnalloc(s->pool, len); + if (low == NULL) { + return NULL; + } + + } else { + low = NULL; + } + + key = ngx_hash_strlow(low, match->data, len); + + value = ngx_hash_find_combined(&map->hash, key, low, len); + if (value) { + return value; + } + +#if (NGX_PCRE) + + if (len && map->nregex) { + ngx_int_t n; + ngx_uint_t i; + ngx_tcp_map_regex_t *reg; + + reg = map->regex; + + for (i = 0; i < map->nregex; i++) { + + n = ngx_tcp_regex_exec(r, reg[i].regex, match); + + if (n == NGX_OK) { + return reg[i].value; + } + + if (n == NGX_DECLINED) { + continue; + } + + /* NGX_ERROR */ + + return NULL; + } + } + +#endif + + return NULL; +} +#endif + +#if 0 +#if (NGX_PCRE) + +static ngx_int_t +ngx_tcp_variable_not_found(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, + uintptr_t data) +{ + v->not_found = 1; + return NGX_OK; +} + + +ngx_tcp_regex_t * +ngx_tcp_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) +{ + u_char *p; + size_t size; + ngx_str_t name; + ngx_uint_t i, n; + ngx_tcp_variable_t *v; + ngx_tcp_regex_t *re; + ngx_tcp_regex_variable_t *rv; + ngx_tcp_core_main_conf_t *cmcf; + + rc->pool = cf->pool; + + if (ngx_regex_compile(rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); + return NULL; + } + + re = ngx_pcalloc(cf->pool, sizeof(ngx_tcp_regex_t)); + if (re == NULL) { + return NULL; + } + + re->regex = rc->regex; + re->ncaptures = rc->captures; + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures); + + n = (ngx_uint_t) rc->named_captures; + + if (n == 0) { + return re; + } + + rv = ngx_palloc(rc->pool, n * sizeof(ngx_tcp_regex_variable_t)); + if (rv == NULL) { + return NULL; + } + + re->variables = rv; + re->nvariables = n; + re->name = rc->pattern; + + size = rc->name_size; + p = rc->names; + + for (i = 0; i < n; i++) { + rv[i].capture = 2 * ((p[0] << 8) + p[1]); + + name.data = &p[2]; + name.len = ngx_strlen(name.data); + + v = ngx_tcp_add_variable(cf, &name, NGX_TCP_VAR_CHANGEABLE); + if (v == NULL) { + return NULL; + } + + rv[i].index = ngx_tcp_get_variable_index(cf, &name); + if (rv[i].index == NGX_ERROR) { + return NULL; + } + + v->get_handler = ngx_tcp_variable_not_found; + + p += size; + } + + return re; +} + + +ngx_int_t +ngx_tcp_regex_exec(ngx_tcp_session_t *s, ngx_tcp_regex_t *re, ngx_str_t *s) +{ + ngx_int_t rc, index; + ngx_uint_t i, n, len; + ngx_tcp_variable_value_t *vv; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); + + if (re->ncaptures) { + len = cmcf->ncaptures; + + if (r->captures == NULL) { + r->captures = ngx_palloc(r->pool, len * sizeof(int)); + if (r->captures == NULL) { + return NGX_ERROR; + } + } + + } else { + len = 0; + } + + rc = ngx_regex_exec(re->regex, s, r->captures, len); + + if (rc == NGX_REGEX_NO_MATCHED) { + return NGX_DECLINED; + } + + if (rc < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + rc, s, &re->name); + return NGX_ERROR; + } + + for (i = 0; i < re->nvariables; i++) { + + n = re->variables[i].capture; + index = re->variables[i].index; + vv = &r->variables[index]; + + vv->len = r->captures[n + 1] - r->captures[n]; + vv->valid = 1; + vv->no_cacheable = 0; + vv->not_found = 0; + vv->data = &s->data[r->captures[n]]; + +#if (NGX_DEBUG) + { + ngx_tcp_variable_t *v; + + v = cmcf->variables.elts; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "tcp regex set $%V to \"%*s\"", + &v[index].name, vv->len, vv->data); + } +#endif + } + + r->ncaptures = rc * 2; + r->captures_data = s->data; + + return NGX_OK; +} + +#endif + + + + +#endif + +ngx_int_t +ngx_tcp_variables_add_core_vars(ngx_conf_t *cf) +{ + ngx_int_t rc; + ngx_tcp_variable_t *cv, *v; + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + + cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, + sizeof(ngx_hash_keys_arrays_t)); + if (cmcf->variables_keys == NULL) { + return NGX_ERROR; + } + + cmcf->variables_keys->pool = cf->pool; + cmcf->variables_keys->temp_pool = cf->pool; + + if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) + != NGX_OK) + { + return NGX_ERROR; + } + + for (cv = ngx_tcp_core_variables; cv->name.len; cv++) { + v = ngx_palloc(cf->pool, sizeof(ngx_tcp_variable_t)); + if (v == NULL) { + return NGX_ERROR; + } + + *v = *cv; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, + NGX_HASH_READONLY_KEY); + + if (rc == NGX_OK) { + continue; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", &v->name); + } + + return NGX_ERROR; + } + + return NGX_OK; +} +ngx_int_t +ngx_tcp_variables_init_vars(ngx_conf_t *cf) +{ + ngx_uint_t i, n; + ngx_hash_key_t *key; + ngx_hash_init_t hash; + ngx_tcp_variable_t *v, *av; + ngx_tcp_core_main_conf_t *cmcf; + + /* set the handlers for the indexed tcp variables */ + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + + v = cmcf->variables.elts; + key = cmcf->variables_keys->keys.elts; + + for (i = 0; i < cmcf->variables.nelts; i++) { + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + + av = key[n].value; + + if (av->get_handler + && v[i].name.len == key[n].key.len + && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) + == 0) + { + v[i].get_handler = av->get_handler; + v[i].data = av->data; + + av->flags |= NGX_TCP_VAR_INDEXED; + v[i].flags = av->flags; + + av->index = i; + + goto next; + } + } + + /*if (ngx_strncmp(v[i].name.data, "tcp_", 5) == 0) { + v[i].get_handler = ngx_tcp_variable_unknown_header_in; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "sent_tcp_", 10) == 0) { + v[i].get_handler = ngx_tcp_variable_unknown_header_out; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "upstream_tcp_", 14) == 0) { + v[i].get_handler = ngx_tcp_upstream_header_variable; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = NGX_TCP_VAR_NOCACHEABLE; + + continue; + }*/ + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); + + return NGX_ERROR; + + next: + continue; + } + + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + av = key[n].value; + + if (av->flags & NGX_TCP_VAR_NOHASH) { + key[n].key.data = NULL; + } + } + + + hash.hash = &cmcf->variables_hash; + hash.key = ngx_hash_key; + hash.max_size = cmcf->variables_hash_max_size; + hash.bucket_size = cmcf->variables_hash_bucket_size; + hash.name = "variables_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, + cmcf->variables_keys->keys.nelts) + != NGX_OK) + { + return NGX_ERROR; + } + + cmcf->variables_keys = NULL; + + return NGX_OK; +} diff --git a/src/ngx_tcp_variables.h b/src/ngx_tcp_variables.h new file mode 100644 index 0000000..7a05e9d --- /dev/null +++ b/src/ngx_tcp_variables.h @@ -0,0 +1,120 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_TCP_VARIABLES_H_INCLUDED_ +#define _NGX_TCP_VARIABLES_H_INCLUDED_ + + +#include +#include +#include "ngx_tcp.h" + + +typedef ngx_variable_value_t ngx_tcp_variable_value_t; + +#define ngx_tcp_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } + +typedef struct ngx_tcp_variable_s ngx_tcp_variable_t; + +typedef void (*ngx_tcp_set_variable_pt) (ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); +typedef ngx_int_t (*ngx_tcp_get_variable_pt) (ngx_tcp_session_t *s, + ngx_tcp_variable_value_t *v, uintptr_t data); + + +#define NGX_TCP_VAR_CHANGEABLE 1 +#define NGX_TCP_VAR_NOCACHEABLE 2 +#define NGX_TCP_VAR_INDEXED 4 +#define NGX_TCP_VAR_NOHASH 8 + + +struct ngx_tcp_variable_s { + ngx_str_t name; /* must be first to build the hash */ + ngx_tcp_set_variable_pt set_handler; + ngx_tcp_get_variable_pt get_handler; + uintptr_t data; + ngx_uint_t flags; + ngx_uint_t index; +}; + + +ngx_tcp_variable_t *ngx_tcp_add_variable(ngx_conf_t *cf, ngx_str_t *name, + ngx_uint_t flags); + +ngx_int_t ngx_tcp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); + +ngx_tcp_variable_value_t *ngx_tcp_get_indexed_variable(ngx_tcp_session_t *s, + ngx_uint_t index); + +ngx_tcp_variable_value_t *ngx_tcp_get_flushed_variable(ngx_tcp_session_t *s, + ngx_uint_t index); + + +ngx_tcp_variable_value_t *ngx_tcp_get_variable(ngx_tcp_session_t *s, + ngx_str_t *name, ngx_uint_t key); + +/*ngx_int_t ngx_tcp_variable_unknown_header(ngx_tcp_variable_value_t *v, + ngx_str_t *var, ngx_list_part_t *part, size_t prefix);*/ + + +#define ngx_tcp_clear_variable(r, index) r->variables0[index].text.data = NULL; + +#if 0 +#if (NGX_PCRE) + +typedef struct { + ngx_uint_t capture; + ngx_int_t index; +} ngx_tcp_regex_variable_t; + + +typedef struct { + ngx_regex_t *regex; + ngx_uint_t ncaptures; + ngx_tcp_regex_variable_t *variables; + ngx_uint_t nvariables; + ngx_str_t name; +} ngx_tcp_regex_t; + + +typedef struct { + ngx_tcp_regex_t *regex; + void *value; +} ngx_tcp_map_regex_t; + + +ngx_tcp_regex_t *ngx_tcp_regex_compile(ngx_conf_t *cf, + ngx_regex_compile_t *rc); +ngx_int_t ngx_tcp_regex_exec(ngx_tcp_session_t *s, ngx_tcp_regex_t *re, + ngx_str_t *s); + +#endif + + +typedef struct { + ngx_hash_combined_t hash; +#if (NGX_PCRE) + ngx_tcp_map_regex_t *regex; + ngx_uint_t nregex; +#endif +} ngx_tcp_map_t; + + +void *ngx_tcp_map_find(ngx_tcp_session_t *s, ngx_tcp_map_t *map, + ngx_str_t *match); + + + + + +#endif +extern ngx_tcp_variable_value_t ngx_tcp_variable_null_value; +extern ngx_tcp_variable_value_t ngx_tcp_variable_true_value; + +ngx_int_t ngx_tcp_variables_add_core_vars(ngx_conf_t *cf); +ngx_int_t ngx_tcp_variables_init_vars(ngx_conf_t *cf); +#endif /* _NGX_HTTP_VARIABLES_H_INCLUDED_ */ diff --git a/test/t/0005-req_var.t b/test/t/0005-req_var.t new file mode 100644 index 0000000..d175253 --- /dev/null +++ b/test/t/0005-req_var.t @@ -0,0 +1,29 @@ +use Test::Nginx::Socket; +repeat_each(1); +plan tests => 1 * repeat_each() * blocks(); + +run_tests(); + +__DATA__ + +=== TEST 1: receive() +--- config +--- main_config +tcp { + server { + listen 1980; + error_log /root/nginx/ngx-moomin-bundle/nginx-tcp-lua-module/test/req_var.log; + process_by_lua ' + local sock = ngx.req.socket() + local re = sock:receive() + if re == nil then + ngx.print("error") + end + ngx.print(ngx.var.remote_addr) + '; + } +} +--- raw_request +foooooo +--- raw_response: 127.0.0.1 + From 0fa9ccdf93dee25eb4e47128a7ac7eabdade8167 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Wed, 16 Apr 2014 11:21:17 +0800 Subject: [PATCH 12/22] add variable module and ngx.var --- config | 2 ++ src/ngx_tcp.c | 3 +++ src/ngx_tcp.h | 5 +++++ src/ngx_tcp_core_module.c | 41 +++++++++++++++++++++++++++++++++++--- src/ngx_tcp_lua_util.c | 2 +- src/ngx_tcp_lua_variable.c | 31 ++++++++++++++-------------- test/t/0000-req_receive.t | 20 +++++++++++++++++++ 7 files changed, 84 insertions(+), 20 deletions(-) diff --git a/config b/config index 1cdebba..654b673 100644 --- a/config +++ b/config @@ -171,6 +171,8 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_tcp.c \ $ngx_addon_dir/src/ngx_tcp_lua_log.c \ $ngx_addon_dir/src/ngx_tcp_lua_time.c \ $ngx_addon_dir/src/ngx_tcp_lua_shdict.c \ + $ngx_addon_dir/src/ngx_tcp_variables.c \ + $ngx_addon_dir/src/ngx_tcp_lua_variable.c \ $ngx_addon_dir/src/ngx_tcp_lua_string.c " diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index b1c9cde..0d62de2 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -232,6 +232,9 @@ ngx_tcp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } + if (ngx_tcp_variables_init_vars(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } /* * tcp{}'s cf->ctx was needed while the configuration merging * and in postconfiguration process diff --git a/src/ngx_tcp.h b/src/ngx_tcp.h index 453425e..1dd410f 100755 --- a/src/ngx_tcp.h +++ b/src/ngx_tcp.h @@ -135,6 +135,11 @@ typedef struct { ngx_array_t servers; /* ngx_tcp_core_srv_conf_t */ ngx_array_t listen; /* ngx_tcp_listen_t */ ngx_array_t virtual_servers; /* ngx_tcp_virtual_server_t */ + ngx_uint_t variables_hash_max_size; + ngx_uint_t variables_hash_bucket_size; + ngx_hash_t variables_hash; + ngx_array_t variables; /* ngx_http_variable_t */ + ngx_hash_keys_arrays_t *variables_keys; } ngx_tcp_core_main_conf_t; typedef struct { diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 3994639..0cdd0fe 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -7,6 +7,7 @@ static void *ngx_tcp_core_preconfiguration(ngx_conf_t *cf); +static void * ngx_tcp_core_init_main_conf(ngx_conf_t *cf) ; static void *ngx_tcp_core_create_main_conf(ngx_conf_t *cf); static void *ngx_tcp_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, @@ -32,6 +33,19 @@ static char *ngx_tcp_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, static ngx_command_t ngx_tcp_core_commands[] = { + { ngx_string("variables_hash_max_size"), + NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_TCP_MAIN_CONF_OFFSET, + offsetof(ngx_tcp_core_main_conf_t, variables_hash_max_size), + NULL }, + + { ngx_string("variables_hash_bucket_size"), + NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_TCP_MAIN_CONF_OFFSET, + offsetof(ngx_tcp_core_main_conf_t, variables_hash_bucket_size), + NULL }, { ngx_string("server"), NGX_TCP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS, ngx_tcp_core_server, @@ -165,7 +179,7 @@ static ngx_tcp_module_t ngx_tcp_core_module_ctx = { NULL, /*postconfiguration*/ ngx_tcp_core_create_main_conf, /* create main configuration */ - NULL, /* init main configuration */ + ngx_tcp_core_init_main_conf, /* init main configuration */ ngx_tcp_core_create_srv_conf, /* create server configuration */ ngx_tcp_core_merge_srv_conf /* merge server configuration */ @@ -193,8 +207,8 @@ static ngx_str_t ngx_tcp_access_log = ngx_string("logs/tcp_access.log"); static void * ngx_tcp_core_preconfiguration(ngx_conf_t *cf) { - return NGX_OK; - /*return ngx_tcp_variables_add_core_vars(cf);*/ + //return NGX_OK; + return ngx_tcp_variables_add_core_vars(cf); } static void * @@ -226,10 +240,31 @@ ngx_tcp_core_create_main_conf(ngx_conf_t *cf) return NULL; } + cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT; + cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT; return cmcf; } +static void * +ngx_tcp_core_init_main_conf(ngx_conf_t *cf) +{ + ngx_tcp_core_main_conf_t *cmcf; + + cmcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_core_module); + + if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) { + cmcf->variables_hash_max_size = 512; + } + + if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) { + cmcf->variables_hash_bucket_size = 64; + } + + cmcf->variables_hash_bucket_size = ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size); + return NGX_CONF_OK; + +} static void * ngx_tcp_core_create_srv_conf(ngx_conf_t *cf) diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 0dc5dca..185f94a 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -135,7 +135,7 @@ ngx_tcp_lua_inject_ngx_api(ngx_conf_t *cf, lua_State *L,ngx_tcp_lua_main_conf_t ngx_tcp_lua_inject_shdict_api(lmcf, L); - /*ngx_tcp_lua_inject_variable_api(L);*/ + ngx_tcp_lua_inject_variable_api(L); lua_getglobal(L, "package"); /* ngx package */ lua_getfield(L, -1, "loaded"); /* ngx package loaded */ diff --git a/src/ngx_tcp_lua_variable.c b/src/ngx_tcp_lua_variable.c index 545585d..8aa00c8 100644 --- a/src/ngx_tcp_lua_variable.c +++ b/src/ngx_tcp_lua_variable.c @@ -4,7 +4,7 @@ #include "ngx_tcp_lua_variable.h" #include "ngx_tcp_lua_util.h" -#include "ngx_http_variables.h" +#include "ngx_tcp_variables.h" static int ngx_tcp_lua_var_get(lua_State *L); @@ -43,7 +43,7 @@ ngx_tcp_lua_var_get(lua_State *L) size_t len; ngx_uint_t hash; ngx_str_t name; - ngx_http_variable_value_t *vv; + ngx_tcp_variable_value_t *vv; /* #if (NGX_PCRE) u_char *val; @@ -85,7 +85,7 @@ ngx_tcp_lua_var_get(lua_State *L) return 1; } - /* n >= 0 && n < r->ncaptures */ + /* n >= 0 && n < s->ncaptures */ cap = s->captures; @@ -110,8 +110,7 @@ ngx_tcp_lua_var_get(lua_State *L) name.len = len; name.data = lowcase; - - vv = ngx_http_get_variable(s, &name, hash); + vv = ngx_tcp_get_variable(s, &name, hash); if (vv == NULL || vv->not_found) { lua_pushnil(L); @@ -134,8 +133,8 @@ ngx_tcp_lua_var_get(lua_State *L) static int ngx_tcp_lua_var_set(lua_State *L) { - ngx_http_variable_t *v; - ngx_http_variable_value_t *vv; + ngx_tcp_variable_t *v; + ngx_tcp_variable_value_t *vv; ngx_tcp_core_main_conf_t *cmcf; u_char *p, *lowcase, *val; size_t len; @@ -160,7 +159,7 @@ ngx_tcp_lua_var_set(lua_State *L) p = (u_char *) luaL_checklstring(L, 2, &len); - lowcase = ngx_palloc(r->pool, len + 1); + lowcase = ngx_palloc(s->pool, len + 1); if (lowcase == NULL) { return luaL_error(L, "memory allocation error"); } @@ -180,7 +179,7 @@ ngx_tcp_lua_var_set(lua_State *L) case LUA_TSTRING: p = (u_char *) luaL_checklstring(L, 3, &len); - val = ngx_palloc(r->pool, len); + val = ngx_palloc(s->pool, len); if (val == NULL) { return luaL_error(L, "memory allocation erorr"); } @@ -205,12 +204,12 @@ ngx_tcp_lua_var_set(lua_State *L) /* we fetch the variable itself */ - cmcf = ngx_tcp_get_module_main_conf(r, ngx_tcp_core_module); + cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); v = ngx_hash_find(&cmcf->variables_hash, hash, name.data, name.len); if (v) { - if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { + if (!(v->flags & NGX_TCP_VAR_CHANGEABLE)) { return luaL_error(L, "variable \"%s\" not changeable", lowcase); } @@ -218,7 +217,7 @@ ngx_tcp_lua_var_set(lua_State *L) dd("set variables with set_handler"); - vv = ngx_palloc(r->pool, sizeof(ngx_tcp_variable_value_t)); + vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); if (vv == NULL) { return luaL_error(L, "out of memory"); } @@ -239,13 +238,13 @@ ngx_tcp_lua_var_set(lua_State *L) vv->len = len; } - v->set_handler(r, vv, v->data); + v->set_handler(s, vv, v->data); return 0; } - if (v->flags & NGX_HTTP_VAR_INDEXED) { - vv = &r->variables[v->index]; + /*if (v->flags & NGX_TCP_VAR_INDEXED) { + vv = &s->variables[v->index]; dd("set indexed variable"); @@ -267,7 +266,7 @@ ngx_tcp_lua_var_set(lua_State *L) } return 0; - } + }*/ return luaL_error(L, "variable \"%s\" cannot be assigned a value", lowcase); diff --git a/test/t/0000-req_receive.t b/test/t/0000-req_receive.t index 50290bb..7dff4a9 100644 --- a/test/t/0000-req_receive.t +++ b/test/t/0000-req_receive.t @@ -66,3 +66,23 @@ tcp { foofoofoofoo --- raw_response: foofoofoofoo + +=== TEST 4: receive() +--- config +--- main_config +tcp { + server { + listen 1980; + process_by_lua ' + local sock = ngx.req.socket() + local re = sock:receive() + if re == nil then + ngx.print("error") + end + ngx.print(ngx.var.remote_addr) + '; + } +} +--- raw_request +foooooo +--- raw_response: 127.0.0.1 From 799912038c0ec4b08b69a1a676ce41a71ca02d02 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Thu, 8 May 2014 15:14:52 +0800 Subject: [PATCH 13/22] fix req.socket.send to async and AGAIN --- src/.ngx_tcp_lua_socket.c.swp | Bin 126976 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/.ngx_tcp_lua_socket.c.swp diff --git a/src/.ngx_tcp_lua_socket.c.swp b/src/.ngx_tcp_lua_socket.c.swp deleted file mode 100644 index f192f4e233459dd3b3d1dd31631cdd8df4605c0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126976 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 CfUj8q From 09ab94c34f1e9f4bededa0c8dbaf0bf766765dd6 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Thu, 8 May 2014 15:14:59 +0800 Subject: [PATCH 14/22] fix req.socket.send to async and AGAIN --- README.md | 1 + src/ngx_tcp_lua_module.c | 4 +- src/ngx_tcp_lua_socket.c | 85 +++++++++++++++++++++++++-------------- test/t/0000-req_receive.t | 22 ++++++++++ 4 files changed, 81 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d92d7c9..9fcc750 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ ngx.req.socket receive receiveuntil + send ngx.say/ngx.print ------------ diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 4ab4fa2..c94e720 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -204,7 +204,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "failed to load Lua inlined code: %s", err); - + ngx_tcp_finalize_session(s); return; } } else { @@ -213,6 +213,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) lscf->lua_src.len); if (script_path == NULL) { + ngx_tcp_finalize_session(s); return; } @@ -226,6 +227,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to load Lua code: %s", err); + ngx_tcp_finalize_session(s); return; } diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 16f7fe5..34696a8 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -208,7 +208,10 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) size_t size; ngx_buf_t *b; ngx_chain_t *cl, *chain; + ngx_tcp_core_srv_conf_t *cscf; + ngx_tcp_lua_socket_upstream_t *u; int type; + ngx_int_t rc; const char *msg; //ngx_buf_tag_t tag; if (lua_gettop(L) != 2) { @@ -225,6 +228,12 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "no request object found"); } + luaL_checktype(L, 1, LUA_TTABLE); + + lua_rawgeti(L, 1, SOCKET_CTX_INDEX); + u = lua_touserdata(L, -1); + lua_pop(L, 1); + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); if (ctx == NULL) { @@ -287,40 +296,55 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) default: return luaL_error(L, "impossible to reach here"); } +//asyn send back + u->request_bufs = cl; -#if 0 - if (b->last != b->end) { - return luaL_error(L, "buffer error: %p != %p", b->last, b->end); + u->request_len = size; + u->request_sent = 0; + u->ft_type = 0; + + /* mimic ngx_tcp_upstream_init_request here */ + + if (u->output.pool == NULL) { + cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); + + u->output.alignment = cscf->directio_alignment; + u->output.pool = s->pool; + u->output.bufs.num = 1; + u->output.bufs.size = cscf->client_body_buffer_size; + u->output.output_filter = ngx_chain_writer; + u->output.filter_ctx = &u->writer; + u->output.tag = (ngx_buf_tag_t) &ngx_tcp_lua_module; + + u->writer.pool = s->pool; } -#endif -#if 0 - cl = ngx_alloc_chain_link(s->pool); - if (cl == NULL) { - return luaL_error(L, "out of memory"); + u->waiting = 0; + rc = ngx_tcp_lua_socket_send(s, u); + + dd("socket send returned %d", (int) rc); + + if (rc == NGX_ERROR) { + return ngx_tcp_lua_socket_error_retval_handler(s, u, L); } + if (rc == NGX_OK) { + lua_pushinteger(L, size); + return 1; + } - cl->next = NULL; - cl->buf = b; -#endif + /* rc == NGX_AGAIN */ + /* set s->write_event_handler to go on session process */ + s->write_event_handler = ngx_tcp_lua_wev_handler; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); - - chain = s->connection->send_chain(s->connection, cl, 0); - - if(chain==cl){ - size=size - ( cl->buf->last - cl->buf->pos ); - } - /* free buf */ - cl->next=ctx->free_recv_bufs; - ctx->free_recv_bufs=cl; + u->waiting = 1; + u->prepare_retvals = ngx_tcp_lua_socket_tcp_send_retval_handler; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, - "tcp_lua write chain %p", chain); - - lua_pushinteger(L, size); - return 1; + ctx->data = u; + ctx->socket_busy = 1; + ctx->socket_ready = 0; + + return lua_yield(L, 0); } @@ -2869,6 +2893,11 @@ ngx_tcp_lua_req_socket(lua_State *L) u->connect_timeout = u->conf->connect_timeout; u->send_timeout = u->conf->send_timeout; + u->writer.out = NULL; + u->writer.last = &u->writer.out; + u->writer.connection = s->connection; + u->writer.limit = 0; + cln = ngx_tcp_cleanup_add(s, 0); if (cln == NULL) { u->ft_type |= NGX_TCP_LUA_SOCKET_FT_ERROR; @@ -3276,10 +3305,6 @@ ngx_tcp_lua_get_keepalive_peer(ngx_tcp_session_t *s, lua_State *L, u->reused = item->reused + 1; - u->writer.out = NULL; - u->writer.last = &u->writer.out; - u->writer.connection = c; - u->writer.limit = 0; //u->request_sent = 0; #if 1 diff --git a/test/t/0000-req_receive.t b/test/t/0000-req_receive.t index 7dff4a9..180b128 100644 --- a/test/t/0000-req_receive.t +++ b/test/t/0000-req_receive.t @@ -86,3 +86,25 @@ tcp { --- raw_request foooooo --- raw_response: 127.0.0.1 + + +=== TEST 5: receive() +--- config +--- main_config +tcp { + server { + listen 1980; + process_by_lua ' + local sock = ngx.req.socket() + local re = sock:receive() + if re == nil then + ngx.print("error") + end + sock:send(re); + '; + } +} +--- raw_request +foooooo +--- raw_response: foooooo + From 94af2092c8f437c098160529201c223669a74333 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Fri, 9 May 2014 12:17:18 +0800 Subject: [PATCH 15/22] revert asyn send and fix error --- src/ngx_tcp.c | 1 + src/ngx_tcp_core_module.c | 11 ++++--- src/ngx_tcp_lua_socket.c | 66 ++++++++++----------------------------- 3 files changed, 23 insertions(+), 55 deletions(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index 0d62de2..be7faac 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -3,6 +3,7 @@ #include #include #include "ngx_tcp.h" +#include "ngx_tcp_variables.h" static char *ngx_tcp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 0cdd0fe..b887534 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -4,10 +4,11 @@ #include #include #include "ngx_tcp.h" +#include "ngx_tcp_variables.h" -static void *ngx_tcp_core_preconfiguration(ngx_conf_t *cf); -static void * ngx_tcp_core_init_main_conf(ngx_conf_t *cf) ; +static ngx_int_t ngx_tcp_core_preconfiguration(ngx_conf_t *cf); +static char *ngx_tcp_core_init_main_conf(ngx_conf_t *cf, void *conf) ; static void *ngx_tcp_core_create_main_conf(ngx_conf_t *cf); static void *ngx_tcp_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, @@ -204,7 +205,7 @@ ngx_module_t ngx_tcp_core_module = { static ngx_str_t ngx_tcp_access_log = ngx_string("logs/tcp_access.log"); -static void * +static ngx_int_t ngx_tcp_core_preconfiguration(ngx_conf_t *cf) { //return NGX_OK; @@ -246,8 +247,8 @@ ngx_tcp_core_create_main_conf(ngx_conf_t *cf) return cmcf; } -static void * -ngx_tcp_core_init_main_conf(ngx_conf_t *cf) +static char * +ngx_tcp_core_init_main_conf(ngx_conf_t *cf,void *conf) { ngx_tcp_core_main_conf_t *cmcf; diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 34696a8..2242f50 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -207,11 +207,9 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) const u_char *p; size_t size; ngx_buf_t *b; - ngx_chain_t *cl, *chain; - ngx_tcp_core_srv_conf_t *cscf; + ngx_chain_t *cl ,*chain ; ngx_tcp_lua_socket_upstream_t *u; int type; - ngx_int_t rc; const char *msg; //ngx_buf_tag_t tag; if (lua_gettop(L) != 2) { @@ -270,7 +268,7 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return 0; } cl=ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, - &ctx->free_recv_bufs, + &ctx->free_bufs, size, (ngx_buf_tag_t) &ngx_tcp_lua_module); @@ -297,54 +295,22 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "impossible to reach here"); } //asyn send back - u->request_bufs = cl; - - u->request_len = size; - u->request_sent = 0; - u->ft_type = 0; - - /* mimic ngx_tcp_upstream_init_request here */ - - if (u->output.pool == NULL) { - cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); - - u->output.alignment = cscf->directio_alignment; - u->output.pool = s->pool; - u->output.bufs.num = 1; - u->output.bufs.size = cscf->client_body_buffer_size; - u->output.output_filter = ngx_chain_writer; - u->output.filter_ctx = &u->writer; - u->output.tag = (ngx_buf_tag_t) &ngx_tcp_lua_module; - - u->writer.pool = s->pool; - } - - u->waiting = 0; - rc = ngx_tcp_lua_socket_send(s, u); - - dd("socket send returned %d", (int) rc); - - if (rc == NGX_ERROR) { - return ngx_tcp_lua_socket_error_retval_handler(s, u, L); - } + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); + + chain = s->connection->send_chain(s->connection, cl, 0); - if (rc == NGX_OK) { - lua_pushinteger(L, size); - return 1; - } - - /* rc == NGX_AGAIN */ - /* set s->write_event_handler to go on session process */ - s->write_event_handler = ngx_tcp_lua_wev_handler; - - u->waiting = 1; - u->prepare_retvals = ngx_tcp_lua_socket_tcp_send_retval_handler; - - ctx->data = u; - ctx->socket_busy = 1; - ctx->socket_ready = 0; + if(chain==cl){ + size=size - ( cl->buf->last - cl->buf->pos ); + } + /* free buf */ + cl->next=ctx->free_recv_bufs; + ctx->free_recv_bufs=cl; - return lua_yield(L, 0); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "tcp_lua write chain %p", chain); + + lua_pushinteger(L, size); + return 1; } From 61c82ecb3c632e3d54dfd52d6e8c776fdf76b8b8 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Fri, 9 May 2014 16:11:03 +0800 Subject: [PATCH 16/22] revert --- src/ngx_tcp_lua_common.h | 3 +- src/ngx_tcp_lua_socket.c | 65 ++++++++++++++++++++++++++++++++-------- src/ngx_tcp_lua_util.c | 36 +++++++++++++++++++++- src/ngx_tcp_lua_util.h | 1 + 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/ngx_tcp_lua_common.h b/src/ngx_tcp_lua_common.h index cac7372..7399719 100755 --- a/src/ngx_tcp_lua_common.h +++ b/src/ngx_tcp_lua_common.h @@ -92,7 +92,8 @@ typedef struct ngx_tcp_lua_ctx_s { int ctx_ref; /* reference to anchor request ctx data in lua registry */ - + + ngx_chain_t *out; ngx_chain_t *busy_bufs; ngx_chain_t *free_bufs; ngx_chain_t *free_recv_bufs; diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 2242f50..803f029 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -48,6 +48,8 @@ static int ngx_tcp_lua_socket_tcp_getreusedtimes(lua_State *L); static int ngx_tcp_lua_socket_tcp_setkeepalive(lua_State *L); static void ngx_tcp_lua_socket_tcp_handler(ngx_event_t *ev); static ngx_int_t ngx_tcp_lua_socket_tcp_get_peer(ngx_peer_connection_t *pc, void *data); +static void ngx_tcp_lua_req_send_handler(ngx_tcp_session_t *s, + ngx_tcp_lua_socket_upstream_t *u); static void ngx_tcp_lua_socket_read_handler(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u); static void ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, @@ -205,12 +207,14 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) ngx_tcp_session_t *s; ngx_tcp_lua_ctx_t *ctx; const u_char *p; - size_t size; + size_t size,len; ngx_buf_t *b; - ngx_chain_t *cl ,*chain ; + ngx_chain_t *cl ,*chain; ngx_tcp_lua_socket_upstream_t *u; int type; + ngx_int_t rc; const char *msg; + ngx_connection_t *c; //ngx_buf_tag_t tag; if (lua_gettop(L) != 2) { return luaL_error(L, "expecting 2 arguments (including the object), " @@ -276,10 +280,6 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "out of memory"); } b=cl->buf; - /*b = ngx_create_temp_buf(s->pool, size); - if (b == NULL) { - return luaL_error(L, "out of memory"); - }*/ switch (type) { case LUA_TNUMBER: @@ -295,8 +295,43 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "impossible to reach here"); } //asyn send back +#if 0 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); - + ctx->out=cl; + c=s->connection; + + rc=ngx_tcp_lua_send(s,&len); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "tcp_lua send %d chain %p",rc ,ctx->out); + if(rc==NGX_OK){ + lua_pushinteger(L,len); + return 1; + } + if(rc==NGX_ERROR){ + lua_pushnil(L); + lua_pushliteral(L,"send error"); + return 2; + } + + u->write_event_handler = ngx_tcp_lua_req_send_handler; + u->read_event_handler = ngx_tcp_lua_socket_dummy_handler; + + if (c->write->timer_set) { + ngx_del_timer(c->write); + } + ngx_add_timer(c->write, u->send_timeout); + + if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) { + ngx_tcp_lua_socket_handle_error(s, u, + NGX_TCP_LUA_SOCKET_FT_ERROR); + return NGX_ERROR; + } + + s->write_event_handler = ngx_tcp_lua_wev_handler; + return lua_yield(L, 0); +#endif + + #if 1 chain = s->connection->send_chain(s->connection, cl, 0); if(chain==cl){ @@ -311,6 +346,7 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) lua_pushinteger(L, size); return 1; + #endif } @@ -1877,6 +1913,15 @@ ngx_tcp_lua_socket_read_handler(ngx_tcp_session_t *s, } } +static void +ngx_tcp_lua_req_send_handler(ngx_tcp_session_t *s, + ngx_tcp_lua_socket_upstream_t *u) +{ + if (s->connection->write->timer_set) { + ngx_del_timer(s->connection->write); + } + s->write_event_handler(s); +} static void ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, @@ -1902,7 +1947,6 @@ ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, } } - static ngx_int_t ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u) @@ -2859,11 +2903,6 @@ ngx_tcp_lua_req_socket(lua_State *L) u->connect_timeout = u->conf->connect_timeout; u->send_timeout = u->conf->send_timeout; - u->writer.out = NULL; - u->writer.last = &u->writer.out; - u->writer.connection = s->connection; - u->writer.limit = 0; - cln = ngx_tcp_cleanup_add(s, 0); if (cln == NULL) { u->ft_type |= NGX_TCP_LUA_SOCKET_FT_ERROR; diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index 185f94a..d004424 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -466,12 +466,46 @@ ngx_tcp_lua_run_thread(lua_State *L, ngx_tcp_session_t *s, } +ngx_int_t +ngx_tcp_lua_send(ngx_tcp_session_t *s,size_t *len) +{ + ngx_tcp_lua_ctx_t *ctx; + ngx_event_t *wev; + ngx_chain_t *cl ,*chain ,**ll; + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); + wev=s->connection->write; + if(ctx->out==NULL){ + return NGX_OK; + } + chain = s->connection->send_chain(s->connection, ctx->out, 0); + if(chain==NGX_CHAIN_ERROR){ + return NGX_ERROR; + } + *len=0; + if(!wev->ready){ + return NGX_AGAIN; + } + ll=&ctx->out->next; + for (cl = ctx->out; cl->next; cl= cl->next) { + *len += cl->buf->last-cl->buf->start; + ll=&cl->next; + } + *ll=ctx->free_bufs; + ctx->free_bufs=ctx->out; + ctx->out=NULL; + return NGX_OK; + /* free buf */ + /*cl->next=ctx->free_recv_bufs; + ctx->free_recv_bufs=cl;*/ + +}; void ngx_tcp_lua_wev_handler(ngx_tcp_session_t *s) { int nret = 0; ngx_int_t rc; + size_t len; ngx_event_t *wev; ngx_connection_t *c; ngx_tcp_lua_ctx_t *ctx; @@ -493,7 +527,7 @@ ngx_tcp_lua_wev_handler(ngx_tcp_session_t *s) return; } - if (!ctx->socket_busy && ctx->socket_ready) { + if (!ctx->socket_busy && ctx->socket_ready) { dd("resuming socket api"); diff --git a/src/ngx_tcp_lua_util.h b/src/ngx_tcp_lua_util.h index 67d32d8..c9a45a0 100644 --- a/src/ngx_tcp_lua_util.h +++ b/src/ngx_tcp_lua_util.h @@ -31,6 +31,7 @@ extern char ngx_tcp_lua_cf_log_key; /* char whose address we'll use as key for the nginx request socket pointer */ extern char ngx_tcp_lua_request_socket_key; +ngx_int_t ngx_tcp_lua_send(ngx_tcp_session_t *s,size_t *len); lua_State *ngx_tcp_lua_new_state(ngx_conf_t *cf, ngx_tcp_lua_main_conf_t *lmcf); lua_State *ngx_tcp_lua_new_thread(ngx_tcp_session_t *s, lua_State *L, int *ref); void ngx_tcp_lua_request_cleanup(void *data); From b7697f0449083661c6a631131b47feb7895a255f Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Fri, 9 May 2014 17:41:55 +0800 Subject: [PATCH 17/22] return to old --- src/ngx_tcp.c | 1 - src/ngx_tcp_core_module.c | 11 +++-- src/ngx_tcp_lua_common.h | 3 +- src/ngx_tcp_lua_module.c | 4 +- src/ngx_tcp_lua_socket.c | 86 +++++++++++++-------------------------- src/ngx_tcp_lua_util.c | 36 +--------------- src/ngx_tcp_lua_util.h | 1 - 7 files changed, 36 insertions(+), 106 deletions(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index be7faac..0d62de2 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -3,7 +3,6 @@ #include #include #include "ngx_tcp.h" -#include "ngx_tcp_variables.h" static char *ngx_tcp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index b887534..0cdd0fe 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -4,11 +4,10 @@ #include #include #include "ngx_tcp.h" -#include "ngx_tcp_variables.h" -static ngx_int_t ngx_tcp_core_preconfiguration(ngx_conf_t *cf); -static char *ngx_tcp_core_init_main_conf(ngx_conf_t *cf, void *conf) ; +static void *ngx_tcp_core_preconfiguration(ngx_conf_t *cf); +static void * ngx_tcp_core_init_main_conf(ngx_conf_t *cf) ; static void *ngx_tcp_core_create_main_conf(ngx_conf_t *cf); static void *ngx_tcp_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, @@ -205,7 +204,7 @@ ngx_module_t ngx_tcp_core_module = { static ngx_str_t ngx_tcp_access_log = ngx_string("logs/tcp_access.log"); -static ngx_int_t +static void * ngx_tcp_core_preconfiguration(ngx_conf_t *cf) { //return NGX_OK; @@ -247,8 +246,8 @@ ngx_tcp_core_create_main_conf(ngx_conf_t *cf) return cmcf; } -static char * -ngx_tcp_core_init_main_conf(ngx_conf_t *cf,void *conf) +static void * +ngx_tcp_core_init_main_conf(ngx_conf_t *cf) { ngx_tcp_core_main_conf_t *cmcf; diff --git a/src/ngx_tcp_lua_common.h b/src/ngx_tcp_lua_common.h index 7399719..cac7372 100755 --- a/src/ngx_tcp_lua_common.h +++ b/src/ngx_tcp_lua_common.h @@ -92,8 +92,7 @@ typedef struct ngx_tcp_lua_ctx_s { int ctx_ref; /* reference to anchor request ctx data in lua registry */ - - ngx_chain_t *out; + ngx_chain_t *busy_bufs; ngx_chain_t *free_bufs; ngx_chain_t *free_recv_bufs; diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index c94e720..4ab4fa2 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -204,7 +204,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "failed to load Lua inlined code: %s", err); - ngx_tcp_finalize_session(s); + return; } } else { @@ -213,7 +213,6 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) lscf->lua_src.len); if (script_path == NULL) { - ngx_tcp_finalize_session(s); return; } @@ -227,7 +226,6 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to load Lua code: %s", err); - ngx_tcp_finalize_session(s); return; } diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 803f029..16f7fe5 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -48,8 +48,6 @@ static int ngx_tcp_lua_socket_tcp_getreusedtimes(lua_State *L); static int ngx_tcp_lua_socket_tcp_setkeepalive(lua_State *L); static void ngx_tcp_lua_socket_tcp_handler(ngx_event_t *ev); static ngx_int_t ngx_tcp_lua_socket_tcp_get_peer(ngx_peer_connection_t *pc, void *data); -static void ngx_tcp_lua_req_send_handler(ngx_tcp_session_t *s, - ngx_tcp_lua_socket_upstream_t *u); static void ngx_tcp_lua_socket_read_handler(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u); static void ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, @@ -207,14 +205,11 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) ngx_tcp_session_t *s; ngx_tcp_lua_ctx_t *ctx; const u_char *p; - size_t size,len; + size_t size; ngx_buf_t *b; - ngx_chain_t *cl ,*chain; - ngx_tcp_lua_socket_upstream_t *u; + ngx_chain_t *cl, *chain; int type; - ngx_int_t rc; const char *msg; - ngx_connection_t *c; //ngx_buf_tag_t tag; if (lua_gettop(L) != 2) { return luaL_error(L, "expecting 2 arguments (including the object), " @@ -230,12 +225,6 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "no request object found"); } - luaL_checktype(L, 1, LUA_TTABLE); - - lua_rawgeti(L, 1, SOCKET_CTX_INDEX); - u = lua_touserdata(L, -1); - lua_pop(L, 1); - ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); if (ctx == NULL) { @@ -272,7 +261,7 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return 0; } cl=ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, - &ctx->free_bufs, + &ctx->free_recv_bufs, size, (ngx_buf_tag_t) &ngx_tcp_lua_module); @@ -280,6 +269,10 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) return luaL_error(L, "out of memory"); } b=cl->buf; + /*b = ngx_create_temp_buf(s->pool, size); + if (b == NULL) { + return luaL_error(L, "out of memory"); + }*/ switch (type) { case LUA_TNUMBER: @@ -294,46 +287,28 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) default: return luaL_error(L, "impossible to reach here"); } -//asyn send back -#if 0 - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); - ctx->out=cl; - c=s->connection; - - rc=ngx_tcp_lua_send(s,&len); - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, - "tcp_lua send %d chain %p",rc ,ctx->out); - if(rc==NGX_OK){ - lua_pushinteger(L,len); - return 1; - } - if(rc==NGX_ERROR){ - lua_pushnil(L); - lua_pushliteral(L,"send error"); - return 2; - } - u->write_event_handler = ngx_tcp_lua_req_send_handler; - u->read_event_handler = ngx_tcp_lua_socket_dummy_handler; +#if 0 + if (b->last != b->end) { + return luaL_error(L, "buffer error: %p != %p", b->last, b->end); + } +#endif - if (c->write->timer_set) { - ngx_del_timer(c->write); +#if 0 + cl = ngx_alloc_chain_link(s->pool); + if (cl == NULL) { + return luaL_error(L, "out of memory"); } - ngx_add_timer(c->write, u->send_timeout); - if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) { - ngx_tcp_lua_socket_handle_error(s, u, - NGX_TCP_LUA_SOCKET_FT_ERROR); - return NGX_ERROR; - } - s->write_event_handler = ngx_tcp_lua_wev_handler; - return lua_yield(L, 0); + cl->next = NULL; + cl->buf = b; #endif - - #if 1 - chain = s->connection->send_chain(s->connection, cl, 0); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); + + chain = s->connection->send_chain(s->connection, cl, 0); + if(chain==cl){ size=size - ( cl->buf->last - cl->buf->pos ); } @@ -345,8 +320,7 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) "tcp_lua write chain %p", chain); lua_pushinteger(L, size); - return 1; - #endif + return 1; } @@ -1913,15 +1887,6 @@ ngx_tcp_lua_socket_read_handler(ngx_tcp_session_t *s, } } -static void -ngx_tcp_lua_req_send_handler(ngx_tcp_session_t *s, - ngx_tcp_lua_socket_upstream_t *u) -{ - if (s->connection->write->timer_set) { - ngx_del_timer(s->connection->write); - } - s->write_event_handler(s); -} static void ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, @@ -1947,6 +1912,7 @@ ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, } } + static ngx_int_t ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, ngx_tcp_lua_socket_upstream_t *u) @@ -3310,6 +3276,10 @@ ngx_tcp_lua_get_keepalive_peer(ngx_tcp_session_t *s, lua_State *L, u->reused = item->reused + 1; + u->writer.out = NULL; + u->writer.last = &u->writer.out; + u->writer.connection = c; + u->writer.limit = 0; //u->request_sent = 0; #if 1 diff --git a/src/ngx_tcp_lua_util.c b/src/ngx_tcp_lua_util.c index d004424..185f94a 100755 --- a/src/ngx_tcp_lua_util.c +++ b/src/ngx_tcp_lua_util.c @@ -466,46 +466,12 @@ ngx_tcp_lua_run_thread(lua_State *L, ngx_tcp_session_t *s, } -ngx_int_t -ngx_tcp_lua_send(ngx_tcp_session_t *s,size_t *len) -{ - ngx_tcp_lua_ctx_t *ctx; - ngx_event_t *wev; - ngx_chain_t *cl ,*chain ,**ll; - ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); - wev=s->connection->write; - if(ctx->out==NULL){ - return NGX_OK; - } - chain = s->connection->send_chain(s->connection, ctx->out, 0); - if(chain==NGX_CHAIN_ERROR){ - return NGX_ERROR; - } - *len=0; - if(!wev->ready){ - return NGX_AGAIN; - } - ll=&ctx->out->next; - for (cl = ctx->out; cl->next; cl= cl->next) { - *len += cl->buf->last-cl->buf->start; - ll=&cl->next; - } - *ll=ctx->free_bufs; - ctx->free_bufs=ctx->out; - ctx->out=NULL; - return NGX_OK; - /* free buf */ - /*cl->next=ctx->free_recv_bufs; - ctx->free_recv_bufs=cl;*/ - -}; void ngx_tcp_lua_wev_handler(ngx_tcp_session_t *s) { int nret = 0; ngx_int_t rc; - size_t len; ngx_event_t *wev; ngx_connection_t *c; ngx_tcp_lua_ctx_t *ctx; @@ -527,7 +493,7 @@ ngx_tcp_lua_wev_handler(ngx_tcp_session_t *s) return; } - if (!ctx->socket_busy && ctx->socket_ready) { + if (!ctx->socket_busy && ctx->socket_ready) { dd("resuming socket api"); diff --git a/src/ngx_tcp_lua_util.h b/src/ngx_tcp_lua_util.h index c9a45a0..67d32d8 100644 --- a/src/ngx_tcp_lua_util.h +++ b/src/ngx_tcp_lua_util.h @@ -31,7 +31,6 @@ extern char ngx_tcp_lua_cf_log_key; /* char whose address we'll use as key for the nginx request socket pointer */ extern char ngx_tcp_lua_request_socket_key; -ngx_int_t ngx_tcp_lua_send(ngx_tcp_session_t *s,size_t *len); lua_State *ngx_tcp_lua_new_state(ngx_conf_t *cf, ngx_tcp_lua_main_conf_t *lmcf); lua_State *ngx_tcp_lua_new_thread(ngx_tcp_session_t *s, lua_State *L, int *ref); void ngx_tcp_lua_request_cleanup(void *data); From f5b80d1ab976774f5fe664b06268550ba7207f51 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Thu, 9 Oct 2014 10:18:11 +0800 Subject: [PATCH 18/22] fix compile --- src/ngx_tcp.c | 1 + src/ngx_tcp_core_module.c | 11 ++++++----- src/ngx_tcp_variables.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ngx_tcp.c b/src/ngx_tcp.c index 0d62de2..be7faac 100644 --- a/src/ngx_tcp.c +++ b/src/ngx_tcp.c @@ -3,6 +3,7 @@ #include #include #include "ngx_tcp.h" +#include "ngx_tcp_variables.h" static char *ngx_tcp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/ngx_tcp_core_module.c b/src/ngx_tcp_core_module.c index 0cdd0fe..b887534 100755 --- a/src/ngx_tcp_core_module.c +++ b/src/ngx_tcp_core_module.c @@ -4,10 +4,11 @@ #include #include #include "ngx_tcp.h" +#include "ngx_tcp_variables.h" -static void *ngx_tcp_core_preconfiguration(ngx_conf_t *cf); -static void * ngx_tcp_core_init_main_conf(ngx_conf_t *cf) ; +static ngx_int_t ngx_tcp_core_preconfiguration(ngx_conf_t *cf); +static char *ngx_tcp_core_init_main_conf(ngx_conf_t *cf, void *conf) ; static void *ngx_tcp_core_create_main_conf(ngx_conf_t *cf); static void *ngx_tcp_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_tcp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, @@ -204,7 +205,7 @@ ngx_module_t ngx_tcp_core_module = { static ngx_str_t ngx_tcp_access_log = ngx_string("logs/tcp_access.log"); -static void * +static ngx_int_t ngx_tcp_core_preconfiguration(ngx_conf_t *cf) { //return NGX_OK; @@ -246,8 +247,8 @@ ngx_tcp_core_create_main_conf(ngx_conf_t *cf) return cmcf; } -static void * -ngx_tcp_core_init_main_conf(ngx_conf_t *cf) +static char * +ngx_tcp_core_init_main_conf(ngx_conf_t *cf,void *conf) { ngx_tcp_core_main_conf_t *cmcf; diff --git a/src/ngx_tcp_variables.c b/src/ngx_tcp_variables.c index 22b72db..a30c52f 100644 --- a/src/ngx_tcp_variables.c +++ b/src/ngx_tcp_variables.c @@ -15,11 +15,11 @@ static ngx_int_t ngx_tcp_variable_unknown_header_in(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_tcp_variable_unknown_header_out(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, uintptr_t data); +*/ #if (NGX_HAVE_TCP_INFO) static ngx_int_t ngx_tcp_variable_tcpinfo(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, uintptr_t data); #endif -*/ static ngx_int_t ngx_tcp_variable_binary_remote_addr(ngx_tcp_session_t *s, ngx_tcp_variable_value_t *v, uintptr_t data); From fcb7dfa71d319e1bd3ab07e4c3c9a4c04bfab41b Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Mon, 4 May 2015 18:33:51 +0800 Subject: [PATCH 19/22] fix req socket send large data --- src/lua_module_x | 1 - src/ngx_tcp_lua_socket.c | 19 +++++++++++++------ test/lib/Test/Nginx/Util.pm | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) delete mode 120000 src/lua_module_x diff --git a/src/lua_module_x b/src/lua_module_x deleted file mode 120000 index 4d6fbe3..0000000 --- a/src/lua_module_x +++ /dev/null @@ -1 +0,0 @@ -../../lua-nginx-module-0.7.2/src/ \ No newline at end of file diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 16f7fe5..723f940 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -137,7 +137,8 @@ ngx_tcp_lua_inject_socket_api(ngx_log_t *log, lua_State *L) lua_pushcfunction(L, ngx_tcp_lua_socket_tcp_receiveuntil); lua_setfield(L, -2, "receiveuntil"); - lua_pushcfunction(L, ngx_tcp_lua_req_socket_tcp_send); + //lua_pushcfunction(L, ngx_tcp_lua_req_socket_tcp_send); + lua_pushcfunction(L, ngx_tcp_lua_socket_tcp_send); lua_setfield(L, -2, "send"); lua_pushcfunction(L, ngx_tcp_lua_socket_tcp_settimeout); @@ -1560,9 +1561,6 @@ ngx_tcp_lua_socket_tcp_send(lua_State *L) return 2; } - if (u->is_downstream) { - return luaL_error(L, "attempt to write to request sockets"); - } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua socket send timeout: %M", u->send_timeout); @@ -1586,6 +1584,11 @@ ngx_tcp_lua_socket_tcp_send(lua_State *L) return luaL_argerror(L, 2, msg); } + if (u->is_downstream) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "downstream write" ); + } + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); cl = ngx_tcp_lua_chains_get_free_buf(s->connection->log, s->pool, @@ -1923,8 +1926,8 @@ ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, c = u->peer.connection; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, - "lua socket send data: %p", u); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "lua socket send data: %p connect:%p log:%p ", u,c,c->log); dd("lua connection log: %p", c->log); @@ -2888,6 +2891,10 @@ ngx_tcp_lua_req_socket(lua_State *L) c = s->connection; pc->connection = c; + u->writer.out = NULL; + u->writer.last = &u->writer.out; + u->writer.connection = c; + u->writer.limit = 0; ctx->data = u; diff --git a/test/lib/Test/Nginx/Util.pm b/test/lib/Test/Nginx/Util.pm index 822da2e..9776970 100644 --- a/test/lib/Test/Nginx/Util.pm +++ b/test/lib/Test/Nginx/Util.pm @@ -53,7 +53,7 @@ our $Timeout = $ENV{TEST_NGINX_TIMEOUT} || 3; our $CheckLeak = $ENV{TEST_NGINX_CHECK_LEAK} || 0; -our $ServerAddr = 'localhost'; +our $ServerAddr = '127.0.0.1'; our $StapOutFileHandle; @@ -637,7 +637,7 @@ $http_config server { listen $ServerPort; - server_name 'localhost'; + server_name '127.0.0.1'; client_max_body_size 30M; #client_body_buffer_size 4k; From bee9f660f26d94b8ea14d1c62fffea2c68bedf2a Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Tue, 5 May 2015 13:34:48 +0800 Subject: [PATCH 20/22] close request connnect when failed to load Lua code --- src/ngx_tcp_lua_module.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ngx_tcp_lua_module.c b/src/ngx_tcp_lua_module.c index 4ab4fa2..4c23d73 100755 --- a/src/ngx_tcp_lua_module.c +++ b/src/ngx_tcp_lua_module.c @@ -205,6 +205,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "failed to load Lua inlined code: %s", err); + ngx_tcp_finalize_session(s); return; } } else { @@ -213,6 +214,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) lscf->lua_src.len); if (script_path == NULL) { + ngx_tcp_finalize_session(s); return; } @@ -227,6 +229,7 @@ ngx_tcp_lua_init_session(ngx_tcp_session_t *s) ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to load Lua code: %s", err); + ngx_tcp_finalize_session(s); return; } } From 843776e5c661071d5821db921d21d138bf720486 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Mon, 8 Jun 2015 15:37:40 +0800 Subject: [PATCH 21/22] fix long conn send memory leak --- src/ngx_tcp_lua_socket.c | 131 +++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 33 deletions(-) diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index 723f940..bfc189a 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -97,6 +97,16 @@ static int ngx_tcp_lua_socket_upstream_destroy(lua_State *L); static ngx_int_t ngx_tcp_lua_get_keepalive_peer(ngx_tcp_session_t *s, lua_State *L, int key_index, ngx_tcp_lua_socket_upstream_t *u); +static int chain_size(ngx_chain_t *cl) +{ + int size=0; + while(cl!=NULL){ + size++; + cl=cl->next; + } + return size; +} + void ngx_tcp_lua_inject_socket_api(ngx_log_t *log, lua_State *L) @@ -269,7 +279,7 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) if (cl == NULL) { return luaL_error(L, "out of memory"); } - b=cl->buf; + b=cl->buf; /*b = ngx_create_temp_buf(s->pool, size); if (b == NULL) { return luaL_error(L, "out of memory"); @@ -309,18 +319,18 @@ ngx_tcp_lua_req_socket_tcp_send(lua_State *L) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "lua send response" ); chain = s->connection->send_chain(s->connection, cl, 0); - - if(chain==cl){ - size=size - ( cl->buf->last - cl->buf->pos ); - } - /* free buf */ - cl->next=ctx->free_recv_bufs; - ctx->free_recv_bufs=cl; + + if(chain==cl){ + size=size - ( cl->buf->last - cl->buf->pos ); + } + /* free buf */ + cl->next=ctx->free_recv_bufs; + ctx->free_recv_bufs=cl; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, "tcp_lua write chain %p", chain); - lua_pushinteger(L, size); + lua_pushinteger(L, size); return 1; } @@ -1515,6 +1525,30 @@ ngx_tcp_lua_socket_read(ngx_tcp_session_t *s, return rc; } +static void +ngx_tcp_lua_socket_write_handler(ngx_tcp_session_t *s) +{ + ngx_tcp_lua_ctx_t *ctx; + ngx_tcp_lua_socket_upstream_t *u; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "lua request socket write event handler"); + + ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); + if (ctx == NULL) { + return; + } + + u = ctx->data; + + if (u && u->write_event_handler) { + u->write_event_handler(s, u); + } + if (!ctx->socket_busy && ctx->socket_ready) { + ngx_tcp_lua_wev_handler(s); + } + +} static int ngx_tcp_lua_socket_tcp_send(lua_State *L) @@ -1585,8 +1619,8 @@ ngx_tcp_lua_socket_tcp_send(lua_State *L) } if (u->is_downstream) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, - "downstream write" ); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "downstream write" ); } ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); @@ -1616,6 +1650,8 @@ ngx_tcp_lua_socket_tcp_send(lua_State *L) default: return luaL_error(L, "impossible to reach here"); } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP,s->connection->log, 0,"request chain size %d\n",chain_size(u->request_bufs)); + u->request_bufs = cl; @@ -1658,7 +1694,7 @@ ngx_tcp_lua_socket_tcp_send(lua_State *L) /* rc == NGX_AGAIN */ /* set s->write_event_handler to go on session process */ - s->write_event_handler = ngx_tcp_lua_wev_handler; + s->write_event_handler = ngx_tcp_lua_socket_write_handler; u->waiting = 1; u->prepare_retvals = ngx_tcp_lua_socket_tcp_send_retval_handler; @@ -1915,6 +1951,32 @@ ngx_tcp_lua_socket_send_handler(ngx_tcp_session_t *s, } } +static ngx_int_t ngx_tcp_send_chain(ngx_connection_t *c, + ngx_buf_t *b) +{ + ngx_int_t n; + for (;;) { + n = c->send(c, b->pos, b->last - b->pos); + + if (n < 0) { + /* NGX_ERROR || NGX_AGAIN */ + break; + } + + b->pos += n; + if (b->pos == b->last) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua tcp socket sent all the data"); + return NGX_OK; + } + /* keep sending more data */ + } + if(n==NGX_ERROR){ + return NGX_ERROR; + } + + return NGX_AGAIN; +} static ngx_int_t ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, @@ -1931,7 +1993,7 @@ ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, dd("lua connection log: %p", c->log); - rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs); + rc = ngx_tcp_send_chain(c,u->request_bufs->buf);//ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs); dd("output chain returned: %d", (int) rc); @@ -1947,6 +2009,8 @@ ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, } if (rc == NGX_AGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua socket again "); u->write_event_handler = ngx_tcp_lua_socket_send_handler; u->read_event_handler = ngx_tcp_lua_socket_dummy_handler; @@ -1980,6 +2044,8 @@ ngx_tcp_lua_socket_send(ngx_tcp_session_t *s, &ctx->free_bufs, &ctx->busy_bufs, &u->request_bufs, (ngx_buf_tag_t) &ngx_tcp_lua_module); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "chain size: free:%d busy:%d request:%d", chain_size(&ctx->free_bufs),chain_size(&ctx->busy_bufs) ,chain_size(u->request_bufs)); u->request_sent = 0; u->write_event_handler = ngx_tcp_lua_socket_dummy_handler; @@ -2258,12 +2324,12 @@ ngx_tcp_lua_socket_test_connect(ngx_connection_t *c) } if (err) { - char errstr[255]; - char * addr=""; - if(c->sockaddr){ - addr= inet_ntoa(((struct sockaddr_in*)(c->sockaddr))->sin_addr); - } - snprintf(errstr,255,"connect() %s failed",addr); + char errstr[255]; + char * addr=""; + if(c->sockaddr){ + addr= inet_ntoa(((struct sockaddr_in*)(c->sockaddr))->sin_addr); + } + snprintf(errstr,255,"connect() %s failed",addr); (void) ngx_connection_error(c, err, errstr); return err; } @@ -2824,13 +2890,13 @@ ngx_tcp_lua_req_socket(lua_State *L) lua_pushlightuserdata(L, &ngx_tcp_lua_request_socket_key); lua_rawget(L, LUA_GLOBALSINDEX); - if(!lua_isnil(L,-1)){ - lua_settop(L, 1); - lua_pushnil(L); - return 2; - }else{ - lua_pop(L,1); - } + if(!lua_isnil(L,-1)){ + lua_settop(L, 1); + lua_pushnil(L); + return 2; + }else{ + lua_pop(L,1); + } ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module); @@ -2891,10 +2957,10 @@ ngx_tcp_lua_req_socket(lua_State *L) c = s->connection; pc->connection = c; - u->writer.out = NULL; - u->writer.last = &u->writer.out; - u->writer.connection = c; - u->writer.limit = 0; + u->writer.out = NULL; + u->writer.last = &u->writer.out; + u->writer.connection = c; + u->writer.limit = 0; ctx->data = u; @@ -2905,15 +2971,14 @@ ngx_tcp_lua_req_socket(lua_State *L) } lua_pushlightuserdata(L, &ngx_tcp_lua_request_socket_key); - lua_pushvalue (L,1); - lua_rawset(L, LUA_GLOBALSINDEX); + lua_pushvalue (L,1); + lua_rawset(L, LUA_GLOBALSINDEX); lua_settop(L, 1); lua_pushnil(L); return 2; } - static void ngx_tcp_lua_req_socket_rev_handler(ngx_tcp_session_t *s) { From 3675bda8947ee2de2382a1fa26f69208e3785827 Mon Sep 17 00:00:00 2001 From: humboldt-xie Date: Mon, 8 Jun 2015 21:01:03 +0800 Subject: [PATCH 22/22] fix lua socket connect host.data memory leak --- src/ngx_tcp_lua_socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ngx_tcp_lua_socket.c b/src/ngx_tcp_lua_socket.c index bfc189a..b43d00f 100755 --- a/src/ngx_tcp_lua_socket.c +++ b/src/ngx_tcp_lua_socket.c @@ -419,15 +419,15 @@ ngx_tcp_lua_socket_tcp_connect(lua_State *L) p = (u_char *) luaL_checklstring(L, 2, &len); - host.data = ngx_palloc(s->pool, len + 1); + host.data = p;//ngx_palloc(s->pool, len + 1); if (host.data == NULL) { return luaL_error(L, "out of memory"); } host.len = len; - ngx_memcpy(host.data, p, len); - host.data[len] = '\0'; + /*ngx_memcpy(host.data, p, len); + host.data[len] = '\0';*/ key_index = 2; custom_pool = 0;