From e517825ed1728433aab1e67f33716eefa05b643c Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Sun, 5 Jul 2020 17:04:27 -0700 Subject: [PATCH 1/3] fix(openresty-patches) add missing patch for FFI-based ngx.crc32 API * add the patch enabling FFI-based hashing APIs in stream subsystem (prerequisite). * add the subsequent patch enabling FFI-based ngx.crc32 API used by the dynamic upstream keepalive patch. --- ...core-0.1.17_04-hash_stream_subsystem.patch | 126 ++++++++++++++++++ ...a-resty-core-0.1.17_05-ffi_crc32_api.patch | 99 ++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_04-hash_stream_subsystem.patch create mode 100644 openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_05-ffi_crc32_api.patch diff --git a/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_04-hash_stream_subsystem.patch b/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_04-hash_stream_subsystem.patch new file mode 100644 index 00000000..d6e21523 --- /dev/null +++ b/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_04-hash_stream_subsystem.patch @@ -0,0 +1,126 @@ +From cdb96165ac3cb2ca1202a6be1a28d297aadb4d12 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 27 Aug 2019 10:44:54 -0700 +Subject: [PATCH] feature: enabled the FFI-based APIs for 'ngx.md5', + 'ngx.md5_bin', and 'ngx.sha1_bin' in the stream subsystem. + +--- + lib/resty/core.lua | 2 +- + lib/resty/core/hash.lua | 50 ++++++++++++++++++++++++++++++++--------- + 2 files changed, 41 insertions(+), 11 deletions(-) + +diff --git a/lua-resty-core-0.1.17/lib/resty/core.lua b/lua-resty-core-0.1.17/lib/resty/core.lua +index 57c9d17..4d2249f 100644 +--- a/lua-resty-core-0.1.17/lib/resty/core.lua ++++ b/lua-resty-core-0.1.17/lib/resty/core.lua +@@ -7,11 +7,11 @@ require "resty.core.regex" + require "resty.core.shdict" + require "resty.core.time" + require "resty.core.misc" ++require "resty.core.hash" + + + if subsystem == 'http' then + require "resty.core.uri" +- require "resty.core.hash" + require "resty.core.base64" + require "resty.core.exit" + require "resty.core.var" +diff --git a/lua-resty-core-0.1.17/lib/resty/core/hash.lua b/lua-resty-core-0.1.17/lib/resty/core/hash.lua +index de97270..4a09b00 100644 +--- a/lua-resty-core-0.1.17/lib/resty/core/hash.lua ++++ b/lua-resty-core-0.1.17/lib/resty/core/hash.lua +@@ -1,18 +1,27 @@ + -- Copyright (C) Yichun Zhang (agentzh) + + +-local ffi = require 'ffi' +-local ffi_string = ffi.string +-local ffi_new = ffi.new ++local ffi = require "ffi" ++local base = require "resty.core.base" ++ ++ + local C = ffi.C ++local ffi_new = ffi.new ++local ffi_string = ffi.string + local ngx = ngx + local type = type +-local tostring = tostring + local error = error +-local base = require "resty.core.base" ++local tostring = tostring ++local subsystem = ngx.config.subsystem ++ ++ ++local ngx_lua_ffi_md5 ++local ngx_lua_ffi_md5_bin ++local ngx_lua_ffi_sha1_bin + + +-ffi.cdef[[ ++if subsystem == "http" then ++ ffi.cdef[[ + void ngx_http_lua_ffi_md5_bin(const unsigned char *src, size_t len, + unsigned char *dst); + +@@ -21,7 +30,28 @@ ffi.cdef[[ + + int ngx_http_lua_ffi_sha1_bin(const unsigned char *src, size_t len, + unsigned char *dst); +-]] ++ ]] ++ ++ ngx_lua_ffi_md5 = C.ngx_http_lua_ffi_md5 ++ ngx_lua_ffi_md5_bin = C.ngx_http_lua_ffi_md5_bin ++ ngx_lua_ffi_sha1_bin = C.ngx_http_lua_ffi_sha1_bin ++ ++elseif subsystem == "stream" then ++ ffi.cdef[[ ++ void ngx_stream_lua_ffi_md5_bin(const unsigned char *src, size_t len, ++ unsigned char *dst); ++ ++ void ngx_stream_lua_ffi_md5(const unsigned char *src, size_t len, ++ unsigned char *dst); ++ ++ int ngx_stream_lua_ffi_sha1_bin(const unsigned char *src, size_t len, ++ unsigned char *dst); ++ ]] ++ ++ ngx_lua_ffi_md5 = C.ngx_stream_lua_ffi_md5 ++ ngx_lua_ffi_md5_bin = C.ngx_stream_lua_ffi_md5_bin ++ ngx_lua_ffi_sha1_bin = C.ngx_stream_lua_ffi_sha1_bin ++end + + + local MD5_DIGEST_LEN = 16 +@@ -35,7 +65,7 @@ ngx.md5_bin = function (s) + s = tostring(s) + end + end +- C.ngx_http_lua_ffi_md5_bin(s, #s, md5_buf) ++ ngx_lua_ffi_md5_bin(s, #s, md5_buf) + return ffi_string(md5_buf, MD5_DIGEST_LEN) + end + +@@ -51,7 +81,7 @@ ngx.md5 = function (s) + s = tostring(s) + end + end +- C.ngx_http_lua_ffi_md5(s, #s, md5_hex_buf) ++ ngx_lua_ffi_md5(s, #s, md5_hex_buf) + return ffi_string(md5_hex_buf, MD5_HEX_DIGEST_LEN) + end + +@@ -67,7 +97,7 @@ ngx.sha1_bin = function (s) + s = tostring(s) + end + end +- local ok = C.ngx_http_lua_ffi_sha1_bin(s, #s, sha_buf) ++ local ok = ngx_lua_ffi_sha1_bin(s, #s, sha_buf) + if ok == 0 then + error("SHA-1 support missing in Nginx") + end +-- +2.26.2 + diff --git a/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_05-ffi_crc32_api.patch b/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_05-ffi_crc32_api.patch new file mode 100644 index 00000000..c05db6b8 --- /dev/null +++ b/openresty-patches/patches/1.15.8.3/lua-resty-core-0.1.17_05-ffi_crc32_api.patch @@ -0,0 +1,99 @@ +From e3f3fad22b086f5079e2ca2cea0fa21a2634a355 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 10 Sep 2019 11:47:32 -0700 +Subject: [PATCH] feature: implemented 'ngx.crc32_short()' and + 'ngx.crc32_long()' via FFI. + +--- + lib/resty/core/hash.lua | 44 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/lua-resty-core-0.1.17/lib/resty/core/hash.lua b/lua-resty-core-0.1.17/lib/resty/core/hash.lua +index 4a09b00..062f3ff 100644 +--- a/lua-resty-core-0.1.17/lib/resty/core/hash.lua ++++ b/lua-resty-core-0.1.17/lib/resty/core/hash.lua +@@ -18,6 +18,8 @@ local subsystem = ngx.config.subsystem + local ngx_lua_ffi_md5 + local ngx_lua_ffi_md5_bin + local ngx_lua_ffi_sha1_bin ++local ngx_lua_ffi_crc32_long ++local ngx_lua_ffi_crc32_short + + + if subsystem == "http" then +@@ -30,11 +32,19 @@ if subsystem == "http" then + + int ngx_http_lua_ffi_sha1_bin(const unsigned char *src, size_t len, + unsigned char *dst); ++ ++ unsigned int ngx_http_lua_ffi_crc32_long(const unsigned char *src, ++ size_t len); ++ ++ unsigned int ngx_http_lua_ffi_crc32_short(const unsigned char *src, ++ size_t len); + ]] + + ngx_lua_ffi_md5 = C.ngx_http_lua_ffi_md5 + ngx_lua_ffi_md5_bin = C.ngx_http_lua_ffi_md5_bin + ngx_lua_ffi_sha1_bin = C.ngx_http_lua_ffi_sha1_bin ++ ngx_lua_ffi_crc32_short = C.ngx_http_lua_ffi_crc32_short ++ ngx_lua_ffi_crc32_long = C.ngx_http_lua_ffi_crc32_long + + elseif subsystem == "stream" then + ffi.cdef[[ +@@ -46,11 +56,19 @@ elseif subsystem == "stream" then + + int ngx_stream_lua_ffi_sha1_bin(const unsigned char *src, size_t len, + unsigned char *dst); ++ ++ unsigned int ngx_stream_lua_ffi_crc32_long(const unsigned char *src, ++ size_t len); ++ ++ unsigned int ngx_stream_lua_ffi_crc32_short(const unsigned char *src, ++ size_t len); + ]] + + ngx_lua_ffi_md5 = C.ngx_stream_lua_ffi_md5 + ngx_lua_ffi_md5_bin = C.ngx_stream_lua_ffi_md5_bin + ngx_lua_ffi_sha1_bin = C.ngx_stream_lua_ffi_sha1_bin ++ ngx_lua_ffi_crc32_short = C.ngx_stream_lua_ffi_crc32_short ++ ngx_lua_ffi_crc32_long = C.ngx_stream_lua_ffi_crc32_long + end + + +@@ -105,6 +123,32 @@ ngx.sha1_bin = function (s) + end + + ++ngx.crc32_short = function (s) ++ if type(s) ~= "string" then ++ if not s then ++ s = "" ++ else ++ s = tostring(s) ++ end ++ end ++ ++ return ngx_lua_ffi_crc32_short(s, #s) ++end ++ ++ ++ngx.crc32_long = function (s) ++ if type(s) ~= "string" then ++ if not s then ++ s = "" ++ else ++ s = tostring(s) ++ end ++ end ++ ++ return ngx_lua_ffi_crc32_long(s, #s) ++end ++ ++ + return { + version = base.version + } +-- +2.26.2 + From a91f3e2c5da4004568b933f222302a5feb4c7c8e Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Sun, 5 Jul 2020 21:05:52 -0700 Subject: [PATCH 2/3] feat(openresty-patches) add patches for OpenResty 1.17.8.1 --- ....1-20200102_01-dyn-lightuserdata-map.patch | 207 +++ ...a-resty-core-0.1.19_01-cosocket-mtls.patch | 446 ++++++ ...ore-0.1.19_02-dyn_upstream_keepalive.patch | 231 +++ ...-0.1.19_03-upstream_recreate_request.patch | 55 + ...core-0.1.19_04-stream_req_start_time.patch | 183 +++ ...-resty-websocket-0.07_01-client-mtls.patch | 64 + ...am_client_certificate_and_ssl_verify.patch | 52 + ...tokens-from-special-responses-output.patch | 38 + ...x-1.17.8_03-stream_proxy_ssl_disable.patch | 33 + .../ngx_lua-0.10.17_01-cosocket-mtls.patch | 970 ++++++++++++ ...ua-0.10.17_02-dyn_upstream_keepalive.patch | 1320 +++++++++++++++++ ...0.10.17_03-upstream_recreate_request.patch | 59 + ...eam_lua-0.0.8_01-inject-req-time-api.patch | 25 + ...m_lua-0.0.8_02-expose_request_struct.patch | 27 + 14 files changed, 3710 insertions(+) create mode 100644 openresty-patches/patches/1.17.8.1/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch create mode 100644 openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_01-cosocket-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch create mode 100644 openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_03-upstream_recreate_request.patch create mode 100644 openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_04-stream_req_start_time.patch create mode 100644 openresty-patches/patches/1.17.8.1/lua-resty-websocket-0.07_01-client-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.1/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch create mode 100644 openresty-patches/patches/1.17.8.1/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch create mode 100644 openresty-patches/patches/1.17.8.1/nginx-1.17.8_03-stream_proxy_ssl_disable.patch create mode 100644 openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_01-cosocket-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch create mode 100644 openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_03-upstream_recreate_request.patch create mode 100644 openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch create mode 100644 openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_02-expose_request_struct.patch diff --git a/openresty-patches/patches/1.17.8.1/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch b/openresty-patches/patches/1.17.8.1/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch new file mode 100644 index 00000000..d5d95269 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch @@ -0,0 +1,207 @@ +From 22945d38da972613a171231ba16f7c759d4512a1 Mon Sep 17 00:00:00 2001 +From: Javier Guerra +Date: Tue, 13 Aug 2019 05:05:17 -0700 +Subject: [PATCH] Dynamic remapping of lightuserdata values + +To allow architectures with VA larger than 47 bits, splits the space in 8 sections, each of 2^LJ_LUV_SECT_SHIFT bytes +(2^45 on ARM64 (32TiB), VA is 48 bits). Since the lightuserdata value must have zeros on all bits above 47, only +sections [0..3] are valid. The table `luv_sect_map[]` must map any section used by the memory layout into a valid +section. It should also be a symetric mapping, so a repeat of the transformation returns the original value. + +The `luv_init_map()` function uses a sample of different types of pointers to determine with sections are actually +used, and constructs the required table. +--- + src/lj_api.c | 5 +-- + src/lj_arch.h | 1 + + src/lj_cconv.c | 2 +- + src/lj_obj.h | 15 +++++++++ + src/lj_state.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 105 insertions(+), 3 deletions(-) + +diff --git a/LuaJIT-2.1-20200102/src/lj_api.c b/LuaJIT-2.1-20200102/src/lj_api.c +index 9c4864d..0a3f778 100644 +--- a/LuaJIT-2.1-20200102/src/lj_api.c ++++ b/LuaJIT-2.1-20200102/src/lj_api.c +@@ -595,7 +595,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx) + if (tvisudata(o)) + return uddata(udataV(o)); + else if (tvislightud(o)) +- return lightudV(o); ++ return lightuvmap(lightudV(o)); + else + return NULL; + } +@@ -696,6 +696,7 @@ LUA_API void lua_pushboolean(lua_State *L, int b) + + LUA_API void lua_pushlightuserdata(lua_State *L, void *p) + { ++ p = lightuvmap(p); + setlightudV(L->top, checklightudptr(L, p)); + incr_top(L); + } +@@ -1138,7 +1139,7 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) + fn->c.f = func; + setfuncV(L, top++, fn); + if (LJ_FR2) setnilV(top++); +- setlightudV(top++, checklightudptr(L, ud)); ++ setlightudV(top++, checklightudptr(L, lightuvmap(ud))); + cframe_nres(L->cframe) = 1+0; /* Zero results. */ + L->top = top; + return top-1; /* Now call the newly allocated C function. */ +diff --git a/LuaJIT-2.1-20200102/src/lj_arch.h b/LuaJIT-2.1-20200102/src/lj_arch.h +index 8f6bc52..cf1c641 100644 +--- a/LuaJIT-2.1-20200102/src/lj_arch.h ++++ b/LuaJIT-2.1-20200102/src/lj_arch.h +@@ -237,6 +237,7 @@ + #define LJ_TARGET_MASKROT 1 + #define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */ + #define LJ_TARGET_GC64 1 ++#define LJ_LUV_SECT_SHIFT 45 + #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL + + #define LJ_ARCH_VERSION 80 +diff --git a/LuaJIT-2.1-20200102/src/lj_cconv.c b/LuaJIT-2.1-20200102/src/lj_cconv.c +index 13b8230..05eed3a 100644 +--- a/LuaJIT-2.1-20200102/src/lj_cconv.c ++++ b/LuaJIT-2.1-20200102/src/lj_cconv.c +@@ -611,7 +611,7 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, + if (ud->udtype == UDTYPE_IO_FILE) + tmpptr = *(void **)tmpptr; + } else if (tvislightud(o)) { +- tmpptr = lightudV(o); ++ tmpptr = lightuvmap(lightudV(o)); + } else if (tvisfunc(o)) { + void *p = lj_ccallback_new(cts, d, funcV(o)); + if (p) { +diff --git a/LuaJIT-2.1-20200102/src/lj_obj.h b/LuaJIT-2.1-20200102/src/lj_obj.h +index a89ea0d..77a157b 100644 +--- a/LuaJIT-2.1-20200102/src/lj_obj.h ++++ b/LuaJIT-2.1-20200102/src/lj_obj.h +@@ -830,6 +830,21 @@ typedef union GCobj { + #define setpriV(o, i) (setitype((o), (i))) + #endif + ++#ifdef LJ_LUV_SECT_SHIFT ++#define LJ_LUV_SECT_MASK (7UL << LJ_LUV_SECT_SHIFT) ++extern uint8_t luv_sect_map[8]; ++#endif ++ ++static LJ_AINLINE void *lightuvmap(void *p) ++{ ++#ifdef LJ_LUV_SECT_SHIFT ++ uintptr_t section = luv_sect_map[((uintptr_t)p >> LJ_LUV_SECT_SHIFT) & 7]; ++ p = (void *)(((uintptr_t)p & ~LJ_LUV_SECT_MASK) | (section << LJ_LUV_SECT_SHIFT)); ++#endif ++ return p; ++} ++ ++#include + static LJ_AINLINE void setlightudV(TValue *o, void *p) + { + #if LJ_GC64 +diff --git a/LuaJIT-2.1-20200102/src/lj_state.c b/LuaJIT-2.1-20200102/src/lj_state.c +index a0fba2a..1ab3097 100644 +--- a/LuaJIT-2.1-20200102/src/lj_state.c ++++ b/LuaJIT-2.1-20200102/src/lj_state.c +@@ -29,6 +29,90 @@ + #include "lj_alloc.h" + #include "luajit.h" + ++/* -- lightuserdata remapping --------------------------------------------- */ ++ ++#ifdef LJ_LUV_SECT_SHIFT ++ ++static char checked_layout = 0; ++ ++#define LJ_LUV_SECT_MASK (7UL << LJ_LUV_SECT_SHIFT) ++uint8_t luv_sect_map[8] = { ++ 0, 1, 7, 3, 4, 5, 6, 2, /* 111 <-> 010 */ ++}; ++ ++ ++static void luvmap_mark_need(void *p) ++{ ++ int index = ((uintptr_t)p >> LJ_LUV_SECT_SHIFT) & 7; ++ ++ luv_sect_map[index] = index < 4 ? index : 128; ++} ++ ++static void luvmap_fold(void) ++{ ++ int i, j; ++ ++ for (i = 0; i < 8; ++i) { ++ if (luv_sect_map[i] == 128) { /* needed but invalid */ ++ for (j = 3; j >= 0; --j) { ++ if (luv_sect_map[j] == 255) { /* found unused, swap */ ++ luv_sect_map[i] = j; ++ luv_sect_map[j] = i; ++ break; ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ if (luv_sect_map[i] == 128) ++ abort(); /* unfixed section */ ++ ++ if (luv_sect_map[i] == 255) ++ luv_sect_map[i] = i; ++ } ++} ++ ++static void luv_init_map() { ++ int i; ++ ++ if (checked_layout != 0) ++ return; ++ ++ for (i = 0; i < 8; ++i) ++ luv_sect_map[i] = 255; ++ ++ char unused_local = 0; ++ void *p = malloc(1); lua_assert(c != NULL); ++ ++ luvmap_mark_need(NULL); /* common use */ ++ luvmap_mark_need(&checked_layout); /* global space */ ++ luvmap_mark_need(&unused_local); /* stack space */ ++ luvmap_mark_need(&luv_init_map); /* function space */ ++ luvmap_mark_need(p); /* heap space */ ++ ++ /* some modules mask pointers before pushing. */ ++ /* mark them as needed too */ ++ #define luv_mask47(p) ((void *) ((uintptr_t) (p) & ((1UL << 47) - 1))) ++ ++ luvmap_mark_need(luv_mask47(&checked_layout)); ++ luvmap_mark_need(luv_mask47(&unused_local)); ++ luvmap_mark_need(luv_mask47(&luv_init_map)); ++ luvmap_mark_need(luv_mask47(p)); ++ ++ #undef luv_mask47 ++ ++ free(p); ++ ++ luvmap_fold(); ++ checked_layout = 1; ++} ++ ++#else ++#define luv_init_map() ++#endif ++ ++ + /* -- Stack handling ------------------------------------------------------ */ + + /* Stack sizes. */ +@@ -186,6 +270,7 @@ lua_State *lj_state_newstate(lua_Alloc f, void *ud) + LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) + #endif + { ++ luv_init_map(); + GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); + lua_State *L = &GG->L; + global_State *g = &GG->g; +-- +2.17.1 + diff --git a/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_01-cosocket-mtls.patch b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_01-cosocket-mtls.patch new file mode 100644 index 00000000..058768ed --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_01-cosocket-mtls.patch @@ -0,0 +1,446 @@ +From ddf9dac29e0dd8376e51b369710e42c948e9d959 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:41:56 -0700 +Subject: =?UTF-8?q?feature:=20implement=20the=20`tcpsock:tlshandshake`=20a?= + =?UTF-8?q?nd=20`tcpsock:sslhandshake`=0Afunctions=20using=20FFI.?= + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 172 ++++++++++++++++++++++++++++++++++ + 2 files changed, 173 insertions(+) + create mode 100644 lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +new file mode 100644 +index 0000000..fe81de5 +--- /dev/null ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -0,0 +1,172 @@ ++local ffi = require("ffi") ++local base = require("resty.core.base") ++ ++local C = ffi.C ++local ffi_string = ffi.string ++local ffi_gc = ffi.gc ++local FFI_ERROR = base.FFI_ERROR ++local FFI_DONE = base.FFI_DONE ++local FFI_OK = base.FFI_OK ++local FFI_AGAIN = base.FFI_AGAIN ++local get_request = base.get_request ++local error = error ++local assert = assert ++local getmetatable = getmetatable ++local type = type ++local select = select ++local co_yield = coroutine._yield ++local table_new = require("table.new") ++local table_clear = require("table.clear") ++ ++if not pcall(ffi.typeof, "ngx_ssl_session_t") then ++ ffi.cdef[[ ++ typedef struct SSL_SESSION ngx_ssl_session_t; ++ ]] ++end ++ ++ffi.cdef[[ ++typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; ++ ++int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ int enable_session_reuse, ngx_str_t *server_name, int verify, ++ int ocsp_status_req, char **errmsg); ++int ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ char **errmsg, int *openssl_error_code); ++void ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess); ++]] ++ ++ ++local SOCKET_CTX_INDEX = 1 ++ ++ ++local errmsg = base.get_errmsg_ptr() ++local session_ptr = ffi.new("ngx_ssl_session_t *[1]") ++local server_name_str = ffi.new("ngx_str_t[1]") ++local openssl_error_code = ffi.new("int[1]") ++local cached_options = table_new(0, 4) ++ ++ ++local function tlshandshake(self, options) ++ if not options then ++ table_clear(cached_options) ++ options = cached_options ++ ++ elseif type(options) ~= "table" then ++ error("bad options table type") ++ end ++ ++ local r = get_request() ++ ++ if not r then ++ error("no request found") ++ end ++ ++ local reused_session = options.reused_session ++ session_ptr[0] = type(reused_session) == "cdata" and reused_session or nil ++ ++ if options.server_name then ++ server_name_str[0].data = options.server_name ++ server_name_str[0].len = #options.server_name ++ ++ else ++ server_name_str[0].data = nil ++ server_name_str[0].len = 0 ++ end ++ ++ local rc = ++ C.ngx_http_lua_ffi_socket_tcp_tlshandshake(r, self[SOCKET_CTX_INDEX], ++ session_ptr[0], ++ reused_session ~= false, ++ server_name_str, ++ options.verify and 1 or 0, ++ options.ocsp_status_req ++ and 1 or 0, ++ errmsg) ++ ++::again:: ++ ++ if rc == FFI_ERROR then ++ if openssl_error_code[0] ~= 0 then ++ return nil, openssl_error_code[0] .. ": " .. ffi_string(errmsg[0]) ++ end ++ ++ return nil, ffi_string(errmsg[0]) ++ end ++ ++ if rc == FFI_DONE then ++ return options.reused_session ++ end ++ ++ if rc == FFI_OK then ++ if options.reused_session == false then ++ return true ++ end ++ ++ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, ++ self[SOCKET_CTX_INDEX], session_ptr, errmsg, openssl_error_code) ++ ++ assert(rc == FFI_OK) ++ ++ if session_ptr[0] == nil then ++ return session_ptr[0] ++ end ++ ++ return ffi_gc(session_ptr[0], C.ngx_http_lua_ffi_tls_free_session) ++ end ++ ++ assert(rc == FFI_AGAIN) ++ ++ co_yield() ++ ++ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, ++ self[SOCKET_CTX_INDEX], session_ptr, errmsg, openssl_error_code) ++ ++ assert(rc == FFI_OK or rc == FFI_ERROR) ++ ++ goto again ++end ++ ++ ++local function sslhandshake(self, reused_session, server_name, ssl_verify, ++ send_status_req, ...) ++ ++ local n = select("#", ...) ++ if not self or n > 1 then ++ error("ngx.socket sslhandshake: expecting 1 ~ 5 " ++ .. "arguments (including the object), but seen " .. n) ++ end ++ ++ cached_options.reused_session = reused_session ++ cached_options.server_name = server_name ++ cached_options.verify = ssl_verify ++ cached_options.ocsp_status_req = send_status_req ++ ++ local res, err = tlshandshake(self, cached_options) ++ table_clear(cached_options) ++ ++ return res, err ++end ++ ++ ++do ++ local old_socket_tcp = ngx.socket.tcp ++ ++ function ngx.socket.tcp() ++ local sock = old_socket_tcp() ++ local mt = getmetatable(sock) ++ ++ mt.tlshandshake = tlshandshake ++ mt.sslhandshake = sslhandshake ++ ++ ngx.socket.tcp = old_socket_tcp ++ ++ return sock ++ end ++end ++ ++ ++return { ++ version = base.version ++} +-- +2.20.1 + + +From 1b73826f746a9dd04f60c560d47e778fbec2c2d9 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:55:05 -0700 +Subject: change: better error when request context couldn't be found. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index fe81de5..e18f40e 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -8,6 +8,7 @@ local FFI_ERROR = base.FFI_ERROR + local FFI_DONE = base.FFI_DONE + local FFI_OK = base.FFI_OK + local FFI_AGAIN = base.FFI_AGAIN ++local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX + local get_request = base.get_request + local error = error + local assert = assert +@@ -85,6 +86,10 @@ local function tlshandshake(self, options) + and 1 or 0, + errmsg) + ++ if rc == FFI_NO_REQ_CTX then ++ error("no request ctx found", 2) ++ end ++ + ::again:: + + if rc == FFI_ERROR then +-- +2.20.1 + + +From 0fea325cd7d6ca479afbc8abbc297b4a046bc8c3 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:23:08 -0700 +Subject: cosocket: added client certificate support with TLS handshake. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index e18f40e..ed45c8a 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -19,23 +19,18 @@ local co_yield = coroutine._yield + local table_new = require("table.new") + local table_clear = require("table.clear") + +-if not pcall(ffi.typeof, "ngx_ssl_session_t") then +- ffi.cdef[[ +- typedef struct SSL_SESSION ngx_ssl_session_t; +- ]] +-end +- + ffi.cdef[[ + typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; + + int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ ngx_http_lua_socket_tcp_upstream_t *u, void *sess, + int enable_session_reuse, ngx_str_t *server_name, int verify, +- int ocsp_status_req, char **errmsg); ++ int ocsp_status_req, void *chain, void *pkey, ++ char **errmsg); + int ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ ngx_http_lua_socket_tcp_upstream_t *u, void **sess, + char **errmsg, int *openssl_error_code); +-void ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess); ++void ngx_http_lua_ffi_tls_free_session(void *sess); + ]] + + +@@ -43,7 +38,7 @@ local SOCKET_CTX_INDEX = 1 + + + local errmsg = base.get_errmsg_ptr() +-local session_ptr = ffi.new("ngx_ssl_session_t *[1]") ++local session_ptr = ffi.new("void *[1]") + local server_name_str = ffi.new("ngx_str_t[1]") + local openssl_error_code = ffi.new("int[1]") + local cached_options = table_new(0, 4) +@@ -76,6 +71,21 @@ local function tlshandshake(self, options) + server_name_str[0].len = 0 + end + ++ local client_cert = options.client_cert ++ local client_priv_key = options.client_priv_key ++ if client_cert then ++ if not client_priv_key then ++ error("client certificate supplied without " ++ .. "corresponding private key", 2) ++ end ++ ++ if type(client_cert) ~= "cdata" ++ or type(client_priv_key) ~= "cdata" ++ then ++ error("wrong type of client certificate or private key supplied", 2) ++ end ++ end ++ + local rc = + C.ngx_http_lua_ffi_socket_tcp_tlshandshake(r, self[SOCKET_CTX_INDEX], + session_ptr[0], +@@ -84,6 +94,8 @@ local function tlshandshake(self, options) + options.verify and 1 or 0, + options.ocsp_status_req + and 1 or 0, ++ client_cert, ++ client_priv_key, + errmsg) + + if rc == FFI_NO_REQ_CTX then +-- +2.20.1 + + +From 3ed719e95bc9a0fd1a768c6ead1ca0b8b777905a Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:29:56 -0700 +Subject: style: fixed long line. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index ed45c8a..a867c73 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -20,7 +20,8 @@ local table_new = require("table.new") + local table_clear = require("table.clear") + + ffi.cdef[[ +-typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; ++typedef struct ngx_http_lua_socket_tcp_upstream_s ++ ngx_http_lua_socket_tcp_upstream_t; + + int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, void *sess, +-- +2.20.1 + + +From 036a7f9b431c7d00fb905533a8f57c7e93f8e0a2 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 24 Sep 2019 16:10:13 -0700 +Subject: =?UTF-8?q?fix:=20transparently=20propagate=20error=20message=20wh?= + =?UTF-8?q?en=20monkey=20patching=20TCP=0Asocket=20metatable.?= + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index a867c73..a4f4eee 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -14,6 +14,7 @@ local error = error + local assert = assert + local getmetatable = getmetatable + local type = type ++local pcall = pcall + local select = select + local co_yield = coroutine._yield + local table_new = require("table.new") +@@ -172,7 +173,11 @@ do + local old_socket_tcp = ngx.socket.tcp + + function ngx.socket.tcp() +- local sock = old_socket_tcp() ++ local ok, sock = pcall(old_socket_tcp) ++ if not ok then ++ error(sock, 2) ++ end ++ + local mt = getmetatable(sock) + + mt.tlshandshake = tlshandshake +-- +2.20.1 + + +From 75251e09f9950261ce7e587950907ff2982b2e51 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Mon, 28 Oct 2019 14:13:08 -0700 +Subject: load resty.core.socket_tcp to monkypatch the socket metatable + +--- + lua-resty-core-0.1.19/lib/resty/core.lua | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core.lua b/lua-resty-core-0.1.19/lib/resty/core.lua +index 57c9d17..7e8aca4 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core.lua +@@ -21,6 +21,7 @@ if subsystem == 'http' then + require "resty.core.worker" + require "resty.core.phase" + require "resty.core.ndk" ++ require "resty.core.socket_tcp" + end + + +-- +2.20.1 + + +From 8d4d81b2fbfac93b270ef70f6441f0d1c70d999e Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Thu, 5 Dec 2019 14:28:24 -0800 +Subject: [PATCH] do not change metatable to avoid conflicts with possible + other monkypatches on `ngx.socket.tcp` + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index a4f4eee..4cd2d77 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -12,7 +12,6 @@ local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX + local get_request = base.get_request + local error = error + local assert = assert +-local getmetatable = getmetatable + local type = type + local pcall = pcall + local select = select +@@ -178,12 +177,8 @@ do + error(sock, 2) + end + +- local mt = getmetatable(sock) +- +- mt.tlshandshake = tlshandshake +- mt.sslhandshake = sslhandshake +- +- ngx.socket.tcp = old_socket_tcp ++ sock.tlshandshake = tlshandshake ++ sock.sslhandshake = sslhandshake + + return sock + end +-- +2.20.1 + diff --git a/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch new file mode 100644 index 00000000..1f15f92e --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch @@ -0,0 +1,231 @@ +From 37feb95041f183ae4fbafeebc47dc104995e6f27 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:44:33 -0700 +Subject: [PATCH] feature: implemented the 'balancer.enable_keepalive()' API. + +--- + lua-resty-core-0.1.19/lib/ngx/balancer.lua | 165 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 151 insertions(+), 14 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/ngx/balancer.lua b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +index d584639..614312f 100644 +--- a/lua-resty-core-0.1.19/lib/ngx/balancer.lua ++++ b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +@@ -3,6 +3,7 @@ + + local base = require "resty.core.base" + base.allows_subsystem('http', 'stream') ++require "resty.core.hash" + + + local ffi = require "ffi" +@@ -17,8 +18,10 @@ local error = error + local type = type + local tonumber = tonumber + local max = math.max ++local ngx_crc32_long = ngx.crc32_long + local subsystem = ngx.config.subsystem + local ngx_lua_ffi_balancer_set_current_peer ++local ngx_lua_ffi_balancer_enable_keepalive + local ngx_lua_ffi_balancer_set_more_tries + local ngx_lua_ffi_balancer_get_last_failure + local ngx_lua_ffi_balancer_set_timeouts -- used by both stream and http +@@ -27,7 +30,11 @@ local ngx_lua_ffi_balancer_set_timeouts -- used by both stream and http + if subsystem == 'http' then + ffi.cdef[[ + int ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, +- const unsigned char *addr, size_t addr_len, int port, char **err); ++ const unsigned char *addr, size_t addr_len, int port, ++ unsigned int cpool_crc32, unsigned int cpool_size, char **err); ++ ++ int ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, ++ unsigned long timeout, unsigned int max_requests, char **err); + + int ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + int count, char **err); +@@ -43,6 +50,9 @@ if subsystem == 'http' then + ngx_lua_ffi_balancer_set_current_peer = + C.ngx_http_lua_ffi_balancer_set_current_peer + ++ ngx_lua_ffi_balancer_enable_keepalive = ++ C.ngx_http_lua_ffi_balancer_enable_keepalive ++ + ngx_lua_ffi_balancer_set_more_tries = + C.ngx_http_lua_ffi_balancer_set_more_tries + +@@ -93,6 +103,11 @@ else + end + + ++local DEFAULT_KEEPALIVE_POOL_SIZE = 30 ++local DEFAULT_KEEPALIVE_IDLE_TIMEOUT = 60000 ++local DEFAULT_KEEPALIVE_MAX_REQUESTS = 100 ++ ++ + local peer_state_names = { + [1] = "keepalive", + [2] = "next", +@@ -103,25 +118,147 @@ local peer_state_names = { + local _M = { version = base.version } + + +-function _M.set_current_peer(addr, port) +- local r = get_request() +- if not r then +- error("no request found") ++if subsystem == "http" then ++ function _M.set_current_peer(addr, port, opts) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ local pool_crc32 ++ local pool_size ++ ++ if opts then ++ if type(opts) ~= "table" then ++ error("bad argument #3 to 'set_current_peer' " .. ++ "(table expected, got " .. type(opts) .. ")", 2) ++ end ++ ++ local pool = opts.pool ++ pool_size = opts.pool_size ++ ++ if pool then ++ if type(pool) ~= "string" then ++ error("bad option 'pool' to 'set_current_peer' " .. ++ "(string expected, got " .. type(pool) .. ")", 2) ++ end ++ ++ pool_crc32 = ngx_crc32_long(pool) ++ end ++ ++ if pool_size then ++ if type(pool_size) ~= "number" then ++ error("bad option 'pool_size' to 'set_current_peer' " .. ++ "(number expected, got " .. type(pool_size) .. ")", 2) ++ ++ elseif pool_size < 1 then ++ error("bad option 'pool_size' to 'set_current_peer' " .. ++ "(expected > 0)", 2) ++ end ++ end ++ end ++ ++ if not port then ++ port = 0 ++ ++ elseif type(port) ~= "number" then ++ port = tonumber(port) ++ end ++ ++ if not pool_crc32 then ++ pool_crc32 = 0 ++ end ++ ++ if not pool_size then ++ pool_size = DEFAULT_KEEPALIVE_POOL_SIZE ++ end ++ ++ local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, port, ++ pool_crc32, pool_size, ++ errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end + +- if not port then +- port = 0 +- elseif type(port) ~= "number" then +- port = tonumber(port) ++else ++ function _M.set_current_peer(addr, port, opts) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ if opts then ++ error("bad argument #3 to 'set_current_peer' ('opts' not yet " .. ++ "implemented in " .. subsystem .. " subsystem)", 2) ++ end ++ ++ if not port then ++ port = 0 ++ ++ elseif type(port) ~= "number" then ++ port = tonumber(port) ++ end ++ ++ local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, ++ port, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end ++end + +- local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, +- port, errmsg) +- if rc == FFI_OK then +- return true ++ ++if subsystem == "http" then ++ function _M.enable_keepalive(idle_timeout, max_requests) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ if not idle_timeout then ++ idle_timeout = DEFAULT_KEEPALIVE_IDLE_TIMEOUT ++ ++ elseif type(idle_timeout) ~= "number" then ++ error("bad argument #1 to 'enable_keepalive' " .. ++ "(number expected, got " .. type(idle_timeout) .. ")", 2) ++ ++ elseif idle_timeout < 0 then ++ error("bad argument #1 to 'enable_keepalive' (expected >= 0)", 2) ++ ++ else ++ idle_timeout = idle_timeout * 1000 ++ end ++ ++ if not max_requests then ++ max_requests = DEFAULT_KEEPALIVE_MAX_REQUESTS ++ ++ elseif type(max_requests) ~= "number" then ++ error("bad argument #2 to 'enable_keepalive' " .. ++ "(number expected, got " .. type(max_requests) .. ")", 2) ++ ++ elseif max_requests < 0 then ++ error("bad argument #2 to 'enable_keepalive' (expected >= 0)", 2) ++ end ++ ++ local rc = ngx_lua_ffi_balancer_enable_keepalive(r, idle_timeout, ++ max_requests, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end + +- return nil, ffi_str(errmsg[0]) ++else ++ function _M.enable_keepalive() ++ error("'enable_keepalive' not yet implemented in " .. subsystem .. ++ " subsystem", 2) ++ end + end + + +-- +2.25.2 + diff --git a/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_03-upstream_recreate_request.patch b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_03-upstream_recreate_request.patch new file mode 100644 index 00000000..02f97617 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_03-upstream_recreate_request.patch @@ -0,0 +1,55 @@ +From daf26ee06cb4e276c96ea7e34a192f04d5fa7a22 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 23 Jun 2020 17:40:20 -0700 +Subject: [PATCH 1/2] feature: add the `balancer.recreate_request` function, + which allows user to recreate request buffer in balancer phase. + +This allows certain request parameters, such as headers (including +`Host` header) to be modified between balancer retries. +--- + lua-resty-core-0.1.19/lib/ngx/balancer.lua | 25 ++++++++++++++++++++++ + +diff --git a/lua-resty-core-0.1.19/lib/ngx/balancer.lua b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +index d584639..2bc16e1 100644 +--- a/lua-resty-core-0.1.19/lib/ngx/balancer.lua ++++ b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +@@ -38,6 +38,10 @@ if subsystem == 'http' then + int ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, + long read_timeout, char **err); ++ ++ int ++ ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r, ++ char **err); + ]] + + ngx_lua_ffi_balancer_set_current_peer = +@@ -207,4 +211,25 @@ function _M.set_timeouts(connect_timeout, send_timeout, read_timeout) + end + + ++if subsystem == 'http' then ++ function _M.recreate_request() ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ local rc = C.ngx_http_lua_ffi_balancer_recreate_request(r, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ if errmsg[0] ~= nil then ++ return nil, ffi_str(errmsg[0]) ++ end ++ ++ return nil, "failed to recreate the upstream request" ++ end ++end ++ ++ + return _M +-- +2.20.1 + diff --git a/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_04-stream_req_start_time.patch b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_04-stream_req_start_time.patch new file mode 100644 index 00000000..8a4e6619 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/lua-resty-core-0.1.19_04-stream_req_start_time.patch @@ -0,0 +1,183 @@ +From 674ef93db9595694459777d928f0aee7f6822cd1 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Mon, 13 Jul 2020 15:41:10 -0700 +Subject: [PATCH] bugfix: added the missing 'ngx.req.start_time' to the stream + subsystem. + +The `ngx.req.start_time()` API is part of `request.lua` which is was +understandably not loaded for the stream subsystem. There existed no +tests for this API in the stream subsystem, so the removal of its +underlying CFunction resulted in `ngx.req.start_time` being `nil` with +no test cases to realize it. +--- + lib/resty/core.lua | 2 +- + lib/resty/core/request.lua | 48 +++++++++++++++++++++++++++----------- + lib/resty/core/utils.lua | 36 ++++++++++++++-------------- + 3 files changed, 55 insertions(+), 31 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core.lua b/lua-resty-core-0.1.19/lib/resty/core.lua +index 54d9756..be287a9 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core.lua +@@ -12,10 +12,10 @@ require "resty.core.hash" + require "resty.core.uri" + require "resty.core.exit" + require "resty.core.base64" ++require "resty.core.request" + + + if subsystem == 'http' then +- require "resty.core.request" + require "resty.core.response" + require "resty.core.phase" + require "resty.core.ndk" +diff --git a/lua-resty-core-0.1.19/lib/resty/core/request.lua b/lua-resty-core-0.1.19/lib/resty/core/request.lua +index f912bfa..747b8c2 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/request.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/request.lua +@@ -3,10 +3,10 @@ + + local ffi = require 'ffi' + local base = require "resty.core.base" +-base.allows_subsystem("http") + local utils = require "resty.core.utils" + + ++local subsystem = ngx.config.subsystem + local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT + local FFI_DECLINED = base.FFI_DECLINED + local FFI_OK = base.FFI_OK +@@ -34,6 +34,40 @@ local _M = { + } + + ++local ngx_lua_ffi_req_start_time ++ ++ ++if subsystem == "stream" then ++ ffi.cdef[[ ++ double ngx_stream_lua_ffi_req_start_time(ngx_stream_lua_request_t *r); ++ ]] ++ ++ ngx_lua_ffi_req_start_time = C.ngx_stream_lua_ffi_req_start_time ++ ++elseif subsystem == "http" then ++ ffi.cdef[[ ++ double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r); ++ ]] ++ ++ ngx_lua_ffi_req_start_time = C.ngx_http_lua_ffi_req_start_time ++end ++ ++ ++function ngx.req.start_time() ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ return tonumber(ngx_lua_ffi_req_start_time(r)) ++end ++ ++ ++if subsystem == "stream" then ++ return _M ++end ++ ++ + local errmsg = base.get_errmsg_ptr() + local ffi_str_type = ffi.typeof("ngx_http_lua_ffi_str_t*") + local ffi_str_size = ffi.sizeof("ngx_http_lua_ffi_str_t") +@@ -59,8 +93,6 @@ ffi.cdef[[ + int ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, + unsigned char *buf, ngx_http_lua_ffi_table_elt_t *out, int count); + +- double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r); +- + int ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r); + + int ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r, +@@ -222,16 +254,6 @@ function ngx.req.get_uri_args(max_args) + end + + +-function ngx.req.start_time() +- local r = get_request() +- if not r then +- error("no request found") +- end +- +- return tonumber(C.ngx_http_lua_ffi_req_start_time(r)) +-end +- +- + do + local methods = { + [0x0002] = "GET", +diff --git a/lua-resty-core-0.1.19/lib/resty/core/utils.lua b/lua-resty-core-0.1.19/lib/resty/core/utils.lua +index 398d7d5..98a0cac 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/utils.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/utils.lua +@@ -3,7 +3,6 @@ + + local ffi = require "ffi" + local base = require "resty.core.base" +-base.allows_subsystem("http") + + + local C = ffi.C +@@ -12,12 +11,7 @@ local ffi_copy = ffi.copy + local byte = string.byte + local str_find = string.find + local get_string_buf = base.get_string_buf +- +- +-ffi.cdef[[ +- void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len, +- const unsigned char find, const unsigned char replace); +-]] ++local subsystem = ngx.config.subsystem + + + local _M = { +@@ -25,19 +19,27 @@ local _M = { + } + + +-function _M.str_replace_char(str, find, replace) +- if not str_find(str, find, nil, true) then +- return str +- end ++if subsystem == "http" then ++ ffi.cdef[[ ++ void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len, ++ const unsigned char find, const unsigned char replace); ++ ]] ++ + +- local len = #str +- local buf = get_string_buf(len) +- ffi_copy(buf, str) ++ function _M.str_replace_char(str, find, replace) ++ if not str_find(str, find, nil, true) then ++ return str ++ end + +- C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), +- byte(replace)) ++ local len = #str ++ local buf = get_string_buf(len) ++ ffi_copy(buf, str) + +- return ffi_str(buf, len) ++ C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), ++ byte(replace)) ++ ++ return ffi_str(buf, len) ++ end + end + + +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.1/lua-resty-websocket-0.07_01-client-mtls.patch b/openresty-patches/patches/1.17.8.1/lua-resty-websocket-0.07_01-client-mtls.patch new file mode 100644 index 00000000..e2e629ed --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/lua-resty-websocket-0.07_01-client-mtls.patch @@ -0,0 +1,64 @@ +diff --git a/lua-resty-websocket-0.07/lib/resty/websocket/client.lua b/lua-resty-websocket-0.07/lib/resty/websocket/client.lua +index 13d4b99..47dc4c2 100644 +--- a/lua-resty-websocket-0.07/lib/resty/websocket/client.lua ++++ b/lua-resty-websocket-0.07/lib/resty/websocket/client.lua +@@ -98,7 +98,7 @@ function _M.connect(self, uri, opts) + path = "/" + end + +- local ssl_verify, proto_header, origin_header, sock_opts = false ++ local ssl_verify, proto_header, origin_header, sock_opts, tls_opts = false + + if opts then + local protos = opts.protocols +@@ -122,11 +122,37 @@ function _M.connect(self, uri, opts) + sock_opts = { pool = pool } + end + ++ local client_cert = opts.client_cert ++ local client_priv_key = opts.client_priv_key ++ ++ if client_cert then ++ assert(client_priv_key, ++ "client_priv_key must be provided with client_cert") ++ ++ tls_opts = { client_cert = client_cert, ++ client_priv_key = client_priv_key, } ++ end ++ + if opts.ssl_verify then + if not ssl_support then + return nil, "ngx_lua 0.9.11+ required for SSL sockets" + end +- ssl_verify = true ++ ++ tls_opts = tls_opts or {} ++ tls_opts.verify = true ++ end ++ ++ if opts.server_name then ++ if not ssl_support then ++ return nil, "ngx_lua 0.9.11+ required for SSL sockets" ++ end ++ ++ tls_opts = tls_opts or {} ++ tls_opts.server_name = opts.server_name ++ ++ elseif host then ++ tls_opts = tls_opts or {} ++ tls_opts.server_name = host + end + end + +@@ -144,9 +170,9 @@ function _M.connect(self, uri, opts) + if not ssl_support then + return nil, "ngx_lua 0.9.11+ required for SSL sockets" + end +- ok, err = sock:sslhandshake(false, host, ssl_verify) ++ ok, err = sock:tlshandshake(tls_opts) + if not ok then +- return nil, "ssl handshake failed: " .. err ++ return nil, "tls handshake failed: " .. err + end + end + diff --git a/openresty-patches/patches/1.17.8.1/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch new file mode 100644 index 00000000..2638aa85 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch @@ -0,0 +1,52 @@ +diff --git a/nginx-1.17.8/src/http/ngx_http_upstream.c b/nginx-1.17.8/src/http/ngx_http_upstream.c +index 90710557..539a4db9 100644 +--- a/nginx-1.17.8/src/http/ngx_http_upstream.c ++++ b/nginx-1.17.8/src/http/ngx_http_upstream.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#if (NGX_HTTP_LUA_KONG) ++#include ++#endif + + + #if (NGX_HTTP_CACHE) +@@ -1691,7 +1691,14 @@ + c->sendfile = 0; + u->output.sendfile = 0; + ++ ++#if (NGX_HTTP_LUA_KONG) ++ if (u->conf->ssl_server_name ++ || ngx_http_lua_kong_get_upstream_ssl_verify(r, u->conf->ssl_verify)) ++ { ++#else + if (u->conf->ssl_server_name || u->conf->ssl_verify) { ++#endif + if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); +@@ -1719,6 +1722,10 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, + } + } + ++#if (NGX_HTTP_LUA_KONG) ++ ngx_http_lua_kong_set_upstream_ssl(r, c); ++#endif ++ + r->connection->log->action = "SSL handshaking to upstream"; + + rc = ngx_ssl_handshake(c); +@@ -1768,7 +1768,11 @@ + + if (c->ssl->handshaked) { + ++#if (NGX_HTTP_LUA_KONG) ++ if (ngx_http_lua_kong_get_upstream_ssl_verify(r, u->conf->ssl_verify)) { ++#else + if (u->conf->ssl_verify) { ++#endif + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { diff --git a/openresty-patches/patches/1.17.8.1/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch new file mode 100644 index 00000000..c6a8690d --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch @@ -0,0 +1,38 @@ +From 66f96c49ec4a222c4061e18aa8c3f8655b52327d Mon Sep 17 00:00:00 2001 +From: Aapo Talvensaari +Date: Fri, 16 Aug 2019 13:41:49 +0300 +Subject: [PATCH] remove server tokens from special responses output + +--- + nginx-1.17.8/src/http/ngx_http_special_response.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/nginx-1.17.8/src/http/ngx_http_special_response.c b/nginx-1.17.8/src/http/ngx_http_special_response.c +index 4b8bbf5..524cc7b 100644 +--- a/nginx-1.17.8/src/http/ngx_http_special_response.c ++++ b/nginx-1.17.8/src/http/ngx_http_special_response.c +@@ -19,21 +19,18 @@ static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r); + + + static u_char ngx_http_error_full_tail[] = +-"
" NGINX_VER "
" CRLF + "" CRLF + "" CRLF + ; + + + static u_char ngx_http_error_build_tail[] = +-"
" NGINX_VER_BUILD "
" CRLF + "" CRLF + "" CRLF + ; + + + static u_char ngx_http_error_tail[] = +-"
openresty
" CRLF + "" CRLF + "" CRLF + ; +-- +2.22.0 + diff --git a/openresty-patches/patches/1.17.8.1/nginx-1.17.8_03-stream_proxy_ssl_disable.patch b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_03-stream_proxy_ssl_disable.patch new file mode 100644 index 00000000..817296d0 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/nginx-1.17.8_03-stream_proxy_ssl_disable.patch @@ -0,0 +1,33 @@ +diff --git a/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c b/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c +index 09493135..fc8f8479 100644 +--- a/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c ++++ b/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#if (NGX_STREAM_LUA_KONG) ++#include ++#endif + + + typedef struct { +@@ -799,8 +802,18 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) + + #if (NGX_STREAM_SSL) + ++#if (NGX_STREAM_LUA_KONG) ++ ++ if (pc->type == SOCK_STREAM && pscf->ssl ++ && !ngx_stream_lua_kong_get_proxy_ssl_disable(s)) ++ { ++ ++#else ++ + if (pc->type == SOCK_STREAM && pscf->ssl) { + ++#endif ++ + if (u->proxy_protocol) { + if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { + return; diff --git a/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_01-cosocket-mtls.patch b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_01-cosocket-mtls.patch new file mode 100644 index 00000000..9aa58ba7 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_01-cosocket-mtls.patch @@ -0,0 +1,970 @@ +From 9bec4f8703054c91534570d6985e3a83843c8ac5 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:39:05 -0700 +Subject: [PATCH 1/5] cosocket: add function `tcpsock:tlshandshake`, retired + the Lua C API based `tcpsock:sslhandshake` implementation. + +--- + src/ngx_http_lua_socket_tcp.c | 387 +++++++++++++++------------------- + src/ngx_http_lua_socket_tcp.h | 3 + + 2 files changed, 177 insertions(+), 213 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 30a4e7b2..2551b5a7 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -23,6 +23,9 @@ static int ngx_http_lua_socket_tcp(lua_State *L); + static int ngx_http_lua_socket_tcp_connect(lua_State *L); + #if (NGX_HTTP_SSL) + static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L); ++static void ngx_http_lua_tls_handshake_handler(ngx_connection_t *c); ++static int ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); + #endif + static int ngx_http_lua_socket_tcp_receive(lua_State *L); + static int ngx_http_lua_socket_tcp_receiveany(lua_State *L); +@@ -152,12 +155,6 @@ static void + ngx_http_lua_socket_empty_resolve_handler(ngx_resolver_ctx_t *ctx); + static int ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L, ngx_uint_t ft_type); +-#if (NGX_HTTP_SSL) +-static int ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); +-static void ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c); +-static int ngx_http_lua_ssl_free_session(lua_State *L); +-#endif + static void ngx_http_lua_socket_tcp_close_connection(ngx_connection_t *c); + + +@@ -309,13 +306,6 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) + lua_pushcfunction(L, ngx_http_lua_socket_tcp_connect); + lua_setfield(L, -2, "connect"); + +-#if (NGX_HTTP_SSL) +- +- lua_pushcfunction(L, ngx_http_lua_socket_tcp_sslhandshake); +- lua_setfield(L, -2, "sslhandshake"); +- +-#endif +- + lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); + lua_setfield(L, -2, "receive"); + +@@ -386,19 +376,6 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) + lua_setfield(L, -2, "__gc"); + lua_rawset(L, LUA_REGISTRYINDEX); + /* }}} */ +- +-#if (NGX_HTTP_SSL) +- +- /* {{{ssl session userdata metatable */ +- lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( +- ssl_session_metatable_key)); +- lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ +- lua_pushcfunction(L, ngx_http_lua_ssl_free_session); +- lua_setfield(L, -2, "__gc"); +- lua_rawset(L, LUA_REGISTRYINDEX); +- /* }}} */ +- +-#endif + } + + +@@ -1531,64 +1508,69 @@ ngx_http_lua_socket_conn_error_retval_handler(ngx_http_request_t *r, + + #if (NGX_HTTP_SSL) + +-static int +-ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) ++static const char * ++ngx_http_lua_socket_tcp_check_busy(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, unsigned int ops) + { +- int n, top; +- ngx_int_t rc; +- ngx_str_t name = ngx_null_string; +- ngx_connection_t *c; +- ngx_ssl_session_t **psession; +- ngx_http_request_t *r; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_co_ctx_t *coctx; +- +- ngx_http_lua_socket_tcp_upstream_t *u; +- +- /* Lua function arguments: self [,session] [,host] [,verify] +- [,send_status_req] */ ++ if (ops & SOCKET_OP_CONNECT && u->conn_waiting) { ++ return "socket busy connecting"; ++ } + +- n = lua_gettop(L); +- if (n < 1 || n > 5) { +- return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 5 " +- "arguments (including the object), but seen %d", n); ++ if (ops & SOCKET_OP_READ && u->read_waiting) { ++ return "socket busy reading"; + } + +- r = ngx_http_lua_get_req(L); +- if (r == NULL) { +- return luaL_error(L, "no request found"); ++ if (ops & SOCKET_OP_WRITE ++ && (u->write_waiting ++ || (u->raw_downstream ++ && (r->connection->buffered & NGX_HTTP_LOWLEVEL_BUFFERED)))) ++ { ++ return "socket busy writing"; + } + +- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "lua tcp socket ssl handshake"); ++ return NULL; ++} + +- luaL_checktype(L, 1, LUA_TTABLE); ++int ++ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ int enable_session_reuse, ngx_str_t *server_name, int verify, ++ int ocsp_status_req, const char **errmsg) ++{ ++ ngx_int_t rc; ++ ngx_connection_t *c; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_co_ctx_t *coctx; ++ const char *busy_rc; + +- lua_rawgeti(L, 1, SOCKET_CTX_INDEX); +- u = lua_touserdata(L, -1); ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua tcp socket tls handshake"); + + if (u == NULL + || u->peer.connection == NULL + || u->read_closed + || u->write_closed) + { +- lua_pushnil(L); +- lua_pushliteral(L, "closed"); +- return 2; ++ *errmsg = "closed"; ++ return NGX_ERROR; + } + + if (u->request != r) { +- return luaL_error(L, "bad request"); ++ *errmsg = "bad request"; ++ return NGX_ERROR; + } + +- ngx_http_lua_socket_check_busy_connecting(r, u, L); +- ngx_http_lua_socket_check_busy_reading(r, u, L); +- ngx_http_lua_socket_check_busy_writing(r, u, L); ++ busy_rc = ngx_http_lua_socket_tcp_check_busy(r, u, SOCKET_OP_CONNECT ++ | SOCKET_OP_READ ++ | SOCKET_OP_WRITE); ++ if (busy_rc != NULL) { ++ *errmsg = busy_rc; ++ return NGX_ERROR; ++ } + + if (u->raw_downstream || u->body_downstream) { +- lua_pushnil(L); +- lua_pushliteral(L, "not supported for downstream"); +- return 2; ++ *errmsg = "not supported for downstream"; ++ return NGX_ERROR; + } + + c = u->peer.connection; +@@ -1596,122 +1578,96 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) + u->ssl_session_reuse = 1; + + if (c->ssl && c->ssl->handshaked) { +- switch (lua_type(L, 2)) { +- case LUA_TUSERDATA: +- lua_pushvalue(L, 2); +- break; ++ if (sess != NULL) { ++ return NGX_DONE; ++ } + +- case LUA_TBOOLEAN: +- if (!lua_toboolean(L, 2)) { +- /* avoid generating the ssl session */ +- lua_pushboolean(L, 1); +- break; +- } +- /* fall through */ ++ u->ssl_session_reuse = enable_session_reuse; + +- default: +- ngx_http_lua_ssl_handshake_retval_handler(r, u, L); +- break; +- } ++ (void) ngx_http_lua_tls_handshake_retval_handler(r, u, NULL); + +- return 1; ++ return NGX_OK; + } + + if (ngx_ssl_create_connection(u->conf->ssl, c, + NGX_SSL_BUFFER|NGX_SSL_CLIENT) + != NGX_OK) + { +- lua_pushnil(L); +- lua_pushliteral(L, "failed to create ssl connection"); +- return 2; ++ *errmsg = "failed to create ssl connection"; ++ return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { +- return luaL_error(L, "no ctx found"); ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "no ngx_lua ctx found while TLS handshaking"); ++ ++ ngx_http_lua_assert(NULL); ++ ++ *errmsg = "no ctx found"; ++ return NGX_ERROR; + } + + coctx = ctx->cur_co_ctx; + + c->sendfile = 0; + +- if (n >= 2) { +- if (lua_type(L, 2) == LUA_TBOOLEAN) { +- u->ssl_session_reuse = lua_toboolean(L, 2); +- +- } else { +- psession = lua_touserdata(L, 2); +- +- if (psession != NULL && *psession != NULL) { +- if (ngx_ssl_set_session(c, *psession) != NGX_OK) { +- lua_pushnil(L); +- lua_pushliteral(L, "lua ssl set session failed"); +- return 2; +- } +- +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua ssl set session: %p", *psession); +- } ++ if (sess != NULL) { ++ if (ngx_ssl_set_session(c, sess) != NGX_OK) { ++ *errmsg = "lua tls set session failed"; ++ return NGX_ERROR; + } + +- if (n >= 3) { +- name.data = (u_char *) lua_tolstring(L, 3, &name.len); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "lua tls set session: %p", sess); + +- if (name.data) { +- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "lua ssl server name: \"%*s\"", name.len, +- name.data); ++ } else { ++ u->ssl_session_reuse = enable_session_reuse; ++ } + +-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ++ if (server_name != NULL && server_name->data != NULL) { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua tls server name: \"%V\"", server_name); + +- if (SSL_set_tlsext_host_name(c->ssl->connection, +- (char *) name.data) +- == 0) +- { +- lua_pushnil(L); +- lua_pushliteral(L, "SSL_set_tlsext_host_name failed"); +- return 2; +- } ++#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ++ if (SSL_set_tlsext_host_name(c->ssl->connection, ++ (char *) server_name->data) ++ == 0) ++ { ++ *errmsg = "SSL_set_tlsext_host_name failed"; ++ return NGX_ERROR; ++ } + + #else +- +- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua socket SNI disabled because the current " +- "version of OpenSSL lacks the support"); +- ++ *errmsg = "OpenSSL has no SNI support"; ++ return NGX_ERROR; + #endif +- } ++ } + +- if (n >= 4) { +- u->ssl_verify = lua_toboolean(L, 4); ++ u->ssl_verify = verify; + +- if (n >= 5) { +- if (lua_toboolean(L, 5)) { ++ if (ocsp_status_req) { + #ifdef NGX_HTTP_LUA_USE_OCSP +- SSL_set_tlsext_status_type(c->ssl->connection, +- TLSEXT_STATUSTYPE_ocsp); ++ SSL_set_tlsext_status_type(c->ssl->connection, ++ TLSEXT_STATUSTYPE_ocsp); ++ + #else +- return luaL_error(L, "no OCSP support"); ++ *errmsg = "no OCSP support"; ++ return NGX_ERROR; + #endif +- } +- } +- } +- } + } + +- dd("found sni name: %.*s %p", (int) name.len, name.data, name.data); +- +- if (name.len == 0) { ++ if (server_name->len == 0) { + u->ssl_name.len = 0; + + } else { + if (u->ssl_name.data) { + /* buffer already allocated */ + +- if (u->ssl_name.len >= name.len) { ++ if (u->ssl_name.len >= server_name->len) { + /* reuse it */ +- ngx_memcpy(u->ssl_name.data, name.data, name.len); +- u->ssl_name.len = name.len; ++ ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ u->ssl_name.len = server_name->len; + + } else { + ngx_free(u->ssl_name.data); +@@ -1722,17 +1678,16 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) + + new_ssl_name: + +- u->ssl_name.data = ngx_alloc(name.len, ngx_cycle->log); ++ u->ssl_name.data = ngx_alloc(server_name->len, ngx_cycle->log); + if (u->ssl_name.data == NULL) { + u->ssl_name.len = 0; + +- lua_pushnil(L); +- lua_pushliteral(L, "no memory"); +- return 2; ++ *errmsg = "no memory"; ++ return NGX_ERROR; + } + +- ngx_memcpy(u->ssl_name.data, name.data, name.len); +- u->ssl_name.len = name.len; ++ ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ u->ssl_name.len = server_name->len; + } + } + +@@ -1746,7 +1701,8 @@ new_ssl_name: + + rc = ngx_ssl_handshake(c); + +- dd("ngx_ssl_handshake returned %d", (int) rc); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "ngx_ssl_handshake returned %d", rc); + + if (rc == NGX_AGAIN) { + if (c->write->timer_set) { +@@ -1756,13 +1712,13 @@ new_ssl_name: + ngx_add_timer(c->read, u->connect_timeout); + + u->conn_waiting = 1; +- u->write_prepare_retvals = ngx_http_lua_ssl_handshake_retval_handler; ++ u->write_prepare_retvals = ngx_http_lua_tls_handshake_retval_handler; + + ngx_http_lua_cleanup_pending_operation(coctx); + coctx->cleanup = ngx_http_lua_coctx_cleanup; + coctx->data = u; + +- c->ssl->handler = ngx_http_lua_ssl_handshake_handler; ++ c->ssl->handler = ngx_http_lua_tls_handshake_handler; + + if (ctx->entered_content_phase) { + r->write_event_handler = ngx_http_lua_content_wev_handler; +@@ -1771,21 +1727,25 @@ new_ssl_name: + r->write_event_handler = ngx_http_core_run_phases; + } + +- return lua_yield(L, 0); ++ return NGX_AGAIN; ++ } ++ ++ ngx_http_lua_tls_handshake_handler(c); ++ ++ if (rc == NGX_ERROR) { ++ *errmsg = u->error_ret; ++ ++ return NGX_ERROR; + } + +- top = lua_gettop(L); +- ngx_http_lua_ssl_handshake_handler(c); +- return lua_gettop(L) - top; ++ return NGX_OK; + } + + + static void +-ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) ++ngx_http_lua_tls_handshake_handler(ngx_connection_t *c) + { +- const char *err; + int waiting; +- lua_State *L; + ngx_int_t rc; + ngx_connection_t *dc; /* downstream connection */ + ngx_http_request_t *r; +@@ -1808,11 +1768,9 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + waiting = u->conn_waiting; + + dc = r->connection; +- L = u->write_co_ctx->co; + + if (c->read->timedout) { +- lua_pushnil(L); +- lua_pushliteral(L, "timeout"); ++ u->error_ret = "timeout"; + goto failed; + } + +@@ -1821,19 +1779,18 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + } + + if (c->ssl->handshaked) { +- + if (u->ssl_verify) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { +- lua_pushnil(L); +- err = lua_pushfstring(L, "%d: %s", (int) rc, +- X509_verify_cert_error_string(rc)); ++ u->error_ret = X509_verify_cert_error_string(rc); ++ u->openssl_error_code_ret = rc; + + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + if (llcf->log_socket_errors) { +- ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua ssl " +- "certificate verify error: (%s)", err); ++ ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua tls " ++ "certificate verify error: (%d: %s)", ++ rc, u->error_ret); + } + + goto failed; +@@ -1844,12 +1801,11 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + if (u->ssl_name.len + && ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) + { +- lua_pushnil(L); +- lua_pushliteral(L, "certificate host mismatch"); ++ u->error_ret = "certificate host mismatch"; + + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + if (llcf->log_socket_errors) { +- ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua ssl " ++ ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua tls " + "certificate does not match host \"%V\"", + &u->ssl_name); + } +@@ -1864,7 +1820,7 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + ngx_http_lua_socket_handle_conn_success(r, u); + + } else { +- (void) ngx_http_lua_ssl_handshake_retval_handler(r, u, L); ++ (void) ngx_http_lua_tls_handshake_retval_handler(r, u, NULL); + } + + if (waiting) { +@@ -1874,60 +1830,84 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + return; + } + +- lua_pushnil(L); +- lua_pushliteral(L, "handshake failed"); ++ u->error_ret = "handshake failed"; + + failed: + + if (waiting) { + u->write_prepare_retvals = +- ngx_http_lua_socket_conn_error_retval_handler; +- ngx_http_lua_socket_handle_conn_error(r, u, +- NGX_HTTP_LUA_SOCKET_FT_SSL); ++ ngx_http_lua_socket_conn_error_retval_handler; ++ ngx_http_lua_socket_handle_conn_error(r, u, NGX_HTTP_LUA_SOCKET_FT_SSL); + ngx_http_run_posted_requests(dc); + + } else { +- (void) ngx_http_lua_socket_conn_error_retval_handler(r, u, L); ++ u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_SSL; ++ ++ (void) ngx_http_lua_socket_conn_error_retval_handler(r, u, NULL); + } + } + + ++ ++int ++ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ const char **errmsg, int *openssl_error_code) ++{ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua cosocket get TLS handshake result for upstream: %p", u); ++ ++ if (u->error_ret != NULL) { ++ *errmsg = u->error_ret; ++ *openssl_error_code = u->openssl_error_code_ret; ++ ++ return NGX_ERROR; ++ } ++ ++ *sess = u->ssl_session_ret; ++ ++ return NGX_OK; ++} ++ ++ + static int +-ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, ++ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L) + { + ngx_connection_t *c; +- ngx_ssl_session_t *ssl_session, **ud; ++ ngx_ssl_session_t *ssl_session; + + if (!u->ssl_session_reuse) { +- lua_pushboolean(L, 1); +- return 1; ++ return 0; + } + +- ud = lua_newuserdata(L, sizeof(ngx_ssl_session_t *)); +- + c = u->peer.connection; + + ssl_session = ngx_ssl_get_session(c); + if (ssl_session == NULL) { +- *ud = NULL; ++ u->ssl_session_ret = NULL; + + } else { +- *ud = ssl_session; ++ u->ssl_session_ret = ssl_session; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua ssl save session: %p", ssl_session); +- +- /* set up the __gc metamethod */ +- lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( +- ssl_session_metatable_key)); +- lua_rawget(L, LUA_REGISTRYINDEX); +- lua_setmetatable(L, -2); ++ "lua tls save session: %p", ssl_session); + } + +- return 1; ++ return 0; + } + ++ ++void ++ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess) ++{ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, ++ "lua tls free session: %p", sess); ++ ++ ngx_ssl_free_session(sess); ++} ++ ++ + #endif /* NGX_HTTP_SSL */ + + +@@ -1980,12 +1960,14 @@ ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r, + u_char errstr[NGX_MAX_ERROR_STR]; + u_char *p; + +- if (ft_type & (NGX_HTTP_LUA_SOCKET_FT_RESOLVER +- | NGX_HTTP_LUA_SOCKET_FT_SSL)) +- { ++ if (ft_type & NGX_HTTP_LUA_SOCKET_FT_RESOLVER) { + return 2; + } + ++ if (ft_type & NGX_HTTP_LUA_SOCKET_FT_SSL) { ++ return 0; ++ } ++ + lua_pushnil(L); + + if (ft_type & NGX_HTTP_LUA_SOCKET_FT_TIMEOUT) { +@@ -6058,27 +6040,6 @@ ngx_http_lua_coctx_cleanup(void *data) + } + + +-#if (NGX_HTTP_SSL) +- +-static int +-ngx_http_lua_ssl_free_session(lua_State *L) +-{ +- ngx_ssl_session_t **psession; +- +- psession = lua_touserdata(L, 1); +- if (psession && *psession != NULL) { +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, +- "lua ssl free session: %p", *psession); +- +- ngx_ssl_free_session(*psession); +- } +- +- return 0; +-} +- +-#endif /* NGX_HTTP_SSL */ +- +- + void + ngx_http_lua_cleanup_conn_pools(lua_State *L) + { +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h +index 091e4378..bb618702 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h +@@ -114,6 +114,9 @@ struct ngx_http_lua_socket_tcp_upstream_s { + + #if (NGX_HTTP_SSL) + ngx_str_t ssl_name; ++ ngx_ssl_session_t *ssl_session_ret; ++ const char *error_ret; ++ int openssl_error_code_ret; + #endif + + unsigned ft_type:16; +-- +2.26.2 + + +From 958140f6113bc4ac33f0880682097f52682d0b81 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:54:32 -0700 +Subject: [PATCH 2/5] change: better error when request context couldn't be + found. + +--- + src/ngx_http_lua_socket_tcp.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 2551b5a7..8ae931bd 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1599,13 +1599,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { +- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, +- "no ngx_lua ctx found while TLS handshaking"); +- +- ngx_http_lua_assert(NULL); +- +- *errmsg = "no ctx found"; +- return NGX_ERROR; ++ return NGX_HTTP_LUA_FFI_NO_REQ_CTX; + } + + coctx = ctx->cur_co_ctx; +-- +2.26.2 + + +From 10bfa00f44a474d0c7667517d98243732c447612 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:24:07 -0700 +Subject: [PATCH 3/5] feature: TCP cosocket client certificate support. closes + #534 + +--- + src/ngx_http_lua_socket_tcp.c | 60 +++++++++++++++++++++++++++++++---- + 1 file changed, 54 insertions(+), 6 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 8ae931bd..f49e609c 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -22,7 +22,6 @@ + static int ngx_http_lua_socket_tcp(lua_State *L); + static int ngx_http_lua_socket_tcp_connect(lua_State *L); + #if (NGX_HTTP_SSL) +-static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L); + static void ngx_http_lua_tls_handshake_handler(ngx_connection_t *c); + static int ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); +@@ -213,9 +212,6 @@ static char ngx_http_lua_upstream_udata_metatable_key; + static char ngx_http_lua_downstream_udata_metatable_key; + static char ngx_http_lua_pool_udata_metatable_key; + static char ngx_http_lua_pattern_udata_metatable_key; +-#if (NGX_HTTP_SSL) +-static char ngx_http_lua_ssl_session_metatable_key; +-#endif + + + void +@@ -1535,13 +1531,16 @@ int + ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, + int enable_session_reuse, ngx_str_t *server_name, int verify, +- int ocsp_status_req, const char **errmsg) ++ int ocsp_status_req, STACK_OF(X509) *chain, EVP_PKEY *pkey, ++ const char **errmsg) + { +- ngx_int_t rc; ++ ngx_int_t rc, i; + ngx_connection_t *c; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_co_ctx_t *coctx; + const char *busy_rc; ++ ngx_ssl_conn_t *ssl_conn; ++ X509 *x509; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua tcp socket tls handshake"); +@@ -1597,6 +1596,8 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ ssl_conn = c->ssl->connection; ++ + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return NGX_HTTP_LUA_FFI_NO_REQ_CTX; +@@ -1619,6 +1620,53 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + u->ssl_session_reuse = enable_session_reuse; + } + ++ if (chain != NULL) { ++ ngx_http_lua_assert(pkey != NULL); /* ensured by resty.core */ ++ ++ if (sk_X509_num(chain) < 1) { ++ ERR_clear_error(); ++ *errmsg = "invalid client certificate chain"; ++ return NGX_ERROR; ++ } ++ ++ x509 = sk_X509_value(chain, 0); ++ if (x509 == NULL) { ++ ERR_clear_error(); ++ *errmsg = "lua tls fetch client certificate from chain failed"; ++ return NGX_ERROR; ++ } ++ ++ if (SSL_use_certificate(ssl_conn, x509) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua tls set client certificate failed"; ++ return NGX_ERROR; ++ } ++ ++ /* read rest of the chain */ ++ ++ for (i = 1; i < sk_X509_num(chain); i++) { ++ x509 = sk_X509_value(chain, i); ++ if (x509 == NULL) { ++ ERR_clear_error(); ++ *errmsg = "lua tls fetch client intermediate certificate " ++ "from chain failed"; ++ return NGX_ERROR; ++ } ++ ++ if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua tls set client intermediate certificate failed"; ++ return NGX_ERROR; ++ } ++ } ++ ++ if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua ssl set client private key failed"; ++ return NGX_ERROR; ++ } ++ } ++ + if (server_name != NULL && server_name->data != NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua tls server name: \"%V\"", server_name); +-- +2.26.2 + + +From 87e157b594987a63d797fd74907c00c3ed69dc19 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:25:20 -0700 +Subject: [PATCH 4/5] style: style fixes. + +--- + src/ngx_http_lua_socket_tcp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index f49e609c..ce8132d3 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1708,7 +1708,8 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + if (u->ssl_name.len >= server_name->len) { + /* reuse it */ +- ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ ngx_memcpy(u->ssl_name.data, server_name->data, ++ server_name->len); + u->ssl_name.len = server_name->len; + + } else { +-- +2.26.2 + + +From f1d1b6352eb6d386593263e80ba3eab0ba710f59 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Mon, 6 Jan 2020 17:56:10 -0800 +Subject: [PATCH 5/5] cleanup + +--- + src/ngx_http_lua_socket_tcp.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index ce8132d3..c4d8d269 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1527,6 +1527,7 @@ ngx_http_lua_socket_tcp_check_busy(ngx_http_request_t *r, + return NULL; + } + ++ + int + ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, +@@ -1568,7 +1569,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + } + + if (u->raw_downstream || u->body_downstream) { +- *errmsg = "not supported for downstream"; ++ *errmsg = "not supported for downstream sockets"; + return NGX_ERROR; + } + +@@ -1609,7 +1610,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + if (sess != NULL) { + if (ngx_ssl_set_session(c, sess) != NGX_OK) { +- *errmsg = "lua tls set session failed"; ++ *errmsg = "tls set session failed"; + return NGX_ERROR; + } + +@@ -1632,13 +1633,13 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + x509 = sk_X509_value(chain, 0); + if (x509 == NULL) { + ERR_clear_error(); +- *errmsg = "lua tls fetch client certificate from chain failed"; ++ *errmsg = "tls fetch client certificate from chain failed"; + return NGX_ERROR; + } + + if (SSL_use_certificate(ssl_conn, x509) == 0) { + ERR_clear_error(); +- *errmsg = "lua tls set client certificate failed"; ++ *errmsg = "tls set client certificate failed"; + return NGX_ERROR; + } + +@@ -1648,21 +1649,21 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + x509 = sk_X509_value(chain, i); + if (x509 == NULL) { + ERR_clear_error(); +- *errmsg = "lua tls fetch client intermediate certificate " +- "from chain failed"; ++ *errmsg = "tls fetch client intermediate certificate from " ++ "chain failed"; + return NGX_ERROR; + } + + if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { + ERR_clear_error(); +- *errmsg = "lua tls set client intermediate certificate failed"; ++ *errmsg = "tls set client intermediate certificate failed"; + return NGX_ERROR; + } + } + + if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { + ERR_clear_error(); +- *errmsg = "lua ssl set client private key failed"; ++ *errmsg = "tls set client private key failed"; + return NGX_ERROR; + } + } +@@ -1681,7 +1682,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + } + + #else +- *errmsg = "OpenSSL has no SNI support"; ++ *errmsg = "no TLS extension support"; + return NGX_ERROR; + #endif + } +@@ -1724,7 +1725,6 @@ new_ssl_name: + u->ssl_name.data = ngx_alloc(server_name->len, ngx_cycle->log); + if (u->ssl_name.data == NULL) { + u->ssl_name.len = 0; +- + *errmsg = "no memory"; + return NGX_ERROR; + } +@@ -1745,7 +1745,7 @@ new_ssl_name: + rc = ngx_ssl_handshake(c); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "ngx_ssl_handshake returned %d", rc); ++ "ngx_ssl_handshake returned: %d", rc); + + if (rc == NGX_AGAIN) { + if (c->write->timer_set) { +@@ -1777,7 +1777,6 @@ new_ssl_name: + + if (rc == NGX_ERROR) { + *errmsg = u->error_ret; +- + return NGX_ERROR; + } + +@@ -1891,7 +1890,6 @@ failed: + } + + +- + int + ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch new file mode 100644 index 00000000..165a9ab9 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch @@ -0,0 +1,1320 @@ +From 2d12ac3e4045258b7a174b0505d92f63c26d82fc Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:44 -0700 +Subject: [PATCH 1/3] feature: implemented keepalive pooling in + 'balancer_by_lua*'. + +--- + src/ngx_http_lua_balancer.c | 738 ++++++++++++++++++++++++++++++------ + src/ngx_http_lua_common.h | 4 + + src/ngx_http_lua_module.c | 3 + + 3 files changed, 629 insertions(+), 116 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index f71a3e00..0d403716 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -16,46 +16,102 @@ + #include "ngx_http_lua_directive.h" + + ++typedef struct { ++ ngx_uint_t size; ++ ngx_uint_t connections; ++ ++ uint32_t crc32; ++ ++ lua_State *lua_vm; ++ ++ ngx_queue_t cache; ++ ngx_queue_t free; ++} ngx_http_lua_balancer_keepalive_pool_t; ++ ++ ++typedef struct { ++ ngx_queue_t queue; ++ ngx_connection_t *connection; ++ ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++} ngx_http_lua_balancer_keepalive_item_t; ++ ++ + struct ngx_http_lua_balancer_peer_data_s { +- /* the round robin data must be first */ +- ngx_http_upstream_rr_peer_data_t rrp; ++ ngx_uint_t cpool_size; ++ ngx_uint_t keepalive_requests; ++ ngx_msec_t keepalive_timeout; ++ ++ ngx_uint_t more_tries; ++ ngx_uint_t total_tries; + +- ngx_http_lua_srv_conf_t *conf; +- ngx_http_request_t *request; ++ int last_peer_state; + +- ngx_uint_t more_tries; +- ngx_uint_t total_tries; ++ uint32_t cpool_crc32; + +- struct sockaddr *sockaddr; +- socklen_t socklen; ++ void *data; + +- ngx_str_t *host; +- in_port_t port; ++ ngx_event_get_peer_pt original_get_peer; ++ ngx_event_free_peer_pt original_free_peer; + +- int last_peer_state; ++#if (NGX_HTTP_SSL) ++ ngx_event_set_peer_session_pt original_set_session; ++ ngx_event_save_peer_session_pt original_save_session; ++#endif ++ ++ ngx_http_request_t *request; ++ ngx_http_lua_srv_conf_t *conf; ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++ ++ ngx_str_t *host; ++ ++ struct sockaddr *sockaddr; ++ socklen_t socklen; ++ ++ unsigned keepalive:1; + + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) +- unsigned cloned_upstream_conf; /* :1 */ ++ unsigned cloned_upstream_conf:1; + #endif + }; + + +-#if (NGX_HTTP_SSL) +-static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, +- void *data); +-static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, +- void *data); +-#endif ++static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, ++ ngx_http_request_t *r); + static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us); + static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); + static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, + void *data); +-static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, +- ngx_http_request_t *r); + static void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, + void *data, ngx_uint_t state); ++static ngx_int_t ngx_http_lua_balancer_create_keepalive_pool(lua_State *L, ++ ngx_log_t *log, uint32_t cpool_crc32, ngx_uint_t cpool_size, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool); ++static void ngx_http_lua_balancer_get_keepalive_pool(lua_State *L, ++ uint32_t cpool_crc32, ngx_http_lua_balancer_keepalive_pool_t **cpool); ++static void ngx_http_lua_balancer_free_keepalive_pool(ngx_log_t *log, ++ ngx_http_lua_balancer_keepalive_pool_t *cpool); ++static void ngx_http_lua_balancer_close(ngx_connection_t *c); ++static void ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev); ++static void ngx_http_lua_balancer_close_handler(ngx_event_t *ev); ++#if (NGX_HTTP_SSL) ++static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, ++ void *data); ++static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, ++ void *data); ++#endif ++ ++ ++#define ngx_http_lua_balancer_keepalive_is_enabled(bp) \ ++ (bp->keepalive) ++ ++#define ngx_http_lua_balancer_peer_set(bp) \ ++ (bp->sockaddr && bp->socklen) ++ ++ ++static char ngx_http_lua_balancer_keepalive_pools_table_key; + + + ngx_int_t +@@ -102,6 +158,61 @@ ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r, + } + + ++static ngx_int_t ++ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) ++{ ++ u_char *err_msg; ++ size_t len; ++ ngx_int_t rc; ++ ++ /* init nginx context in Lua VM */ ++ ngx_http_lua_set_req(L, r); ++ ++#ifndef OPENRESTY_LUAJIT ++ ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); ++ ++ /* {{{ make new env inheriting main thread's globals table */ ++ lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ ++ ngx_http_lua_get_globals_table(L); ++ lua_setfield(L, -2, "__index"); ++ lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ ++ /* }}} */ ++ ++ lua_setfenv(L, -2); /* set new running env for the code closure */ ++#endif /* OPENRESTY_LUAJIT */ ++ ++ lua_pushcfunction(L, ngx_http_lua_traceback); ++ lua_insert(L, 1); /* put it under chunk and args */ ++ ++ /* protected call user code */ ++ rc = lua_pcall(L, 0, 1, 1); ++ ++ lua_remove(L, 1); /* remove traceback function */ ++ ++ dd("rc == %d", (int) rc); ++ ++ if (rc != 0) { ++ /* error occurred when running loaded code */ ++ err_msg = (u_char *) lua_tolstring(L, -1, &len); ++ ++ if (err_msg == NULL) { ++ err_msg = (u_char *) "unknown reason"; ++ len = sizeof("unknown reason") - 1; ++ } ++ ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "failed to run balancer_by_lua*: %*s", len, err_msg); ++ ++ lua_settop(L, 0); /* clear remaining elems on stack */ ++ ++ return NGX_ERROR; ++ } ++ ++ lua_settop(L, 0); /* clear remaining elems on stack */ ++ return rc; ++} ++ ++ + char * + ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +@@ -125,16 +236,16 @@ char * + ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) + { +- u_char *cache_key = NULL; +- u_char *name; +- ngx_str_t *value; +- ngx_http_lua_srv_conf_t *lscf = conf; +- ++ u_char *cache_key = NULL; ++ u_char *name; ++ ngx_str_t *value; + ngx_http_upstream_srv_conf_t *uscf; ++ ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); + +- /* must specify a content handler */ ++ /* content handler setup */ ++ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } +@@ -178,11 +289,19 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + lscf->balancer.src_key = cache_key; + ++ /* balancer setup */ ++ + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + + if (uscf->peer.init_upstream) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "load balancing method redefined"); ++ ++ lscf->balancer.original_init_upstream = uscf->peer.init_upstream; ++ ++ } else { ++ lscf->balancer.original_init_upstream = ++ ngx_http_upstream_init_round_robin; + } + + uscf->peer.init_upstream = ngx_http_lua_balancer_init; +@@ -198,14 +317,18 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + + static ngx_int_t +-ngx_http_lua_balancer_init(ngx_conf_t *cf, +- ngx_http_upstream_srv_conf_t *us) ++ngx_http_lua_balancer_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) + { +- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { ++ ngx_http_lua_srv_conf_t *lscf; ++ ++ lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); ++ ++ if (lscf->balancer.original_init_upstream(cf, us) != NGX_OK) { + return NGX_ERROR; + } + +- /* this callback is called upon individual requests */ ++ lscf->balancer.original_init_peer = us->peer.init; ++ + us->peer.init = ngx_http_lua_balancer_init_peer; + + return NGX_OK; +@@ -216,33 +339,38 @@ static ngx_int_t + ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us) + { +- ngx_http_lua_srv_conf_t *bcf; ++ ngx_http_lua_srv_conf_t *lscf; + ngx_http_lua_balancer_peer_data_t *bp; + +- bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); +- if (bp == NULL) { ++ lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); ++ ++ if (lscf->balancer.original_init_peer(r, us) != NGX_OK) { + return NGX_ERROR; + } + +- r->upstream->peer.data = &bp->rrp; +- +- if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { ++ bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); ++ if (bp == NULL) { + return NGX_ERROR; + } + ++ bp->conf = lscf; ++ bp->request = r; ++ bp->data = r->upstream->peer.data; ++ bp->original_get_peer = r->upstream->peer.get; ++ bp->original_free_peer = r->upstream->peer.free; ++ ++ r->upstream->peer.data = bp; + r->upstream->peer.get = ngx_http_lua_balancer_get_peer; + r->upstream->peer.free = ngx_http_lua_balancer_free_peer; + + #if (NGX_HTTP_SSL) ++ bp->original_set_session = r->upstream->peer.set_session; ++ bp->original_save_session = r->upstream->peer.save_session; ++ + r->upstream->peer.set_session = ngx_http_lua_balancer_set_session; + r->upstream->peer.save_session = ngx_http_lua_balancer_save_session; + #endif + +- bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); +- +- bp->conf = bcf; +- bp->request = r; +- + return NGX_OK; + } + +@@ -250,25 +378,26 @@ ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + static ngx_int_t + ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + { +- lua_State *L; +- ngx_int_t rc; +- ngx_http_request_t *r; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_srv_conf_t *lscf; +- ngx_http_lua_main_conf_t *lmcf; +- ngx_http_lua_balancer_peer_data_t *bp = data; ++ lua_State *L; ++ ngx_int_t rc; ++ ngx_queue_t *q; ++ ngx_connection_t *c; ++ ngx_http_request_t *r; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_srv_conf_t *lscf; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ngx_http_lua_balancer_peer_data_t *bp = data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, +- "lua balancer peer, tries: %ui", pc->tries); +- +- lscf = bp->conf; ++ "lua balancer: get peer, tries: %ui", pc->tries); + + r = bp->request; ++ lscf = bp->conf; + + ngx_http_lua_assert(lscf->balancer.handler && r); + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); +- + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { +@@ -286,9 +415,15 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + + ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; + ++ bp->cpool = NULL; + bp->sockaddr = NULL; + bp->socklen = 0; + bp->more_tries = 0; ++ bp->cpool_crc32 = 0; ++ bp->cpool_size = 0; ++ bp->keepalive_requests = 0; ++ bp->keepalive_timeout = 0; ++ bp->keepalive = 0; + bp->total_tries++; + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +@@ -300,7 +435,6 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + lmcf->balancer_peer_data = bp; + + rc = lscf->balancer.handler(r, lscf, L); +- + if (rc == NGX_ERROR) { + return NGX_ERROR; + } +@@ -322,105 +456,414 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + } + } + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + pc->sockaddr = bp->sockaddr; + pc->socklen = bp->socklen; ++ pc->name = bp->host; + pc->cached = 0; + pc->connection = NULL; +- pc->name = bp->host; +- +- bp->rrp.peers->single = 0; + + if (bp->more_tries) { + r->upstream->peer.tries += bp->more_tries; + } + +- dd("tries: %d", (int) r->upstream->peer.tries); ++ if (ngx_http_lua_balancer_keepalive_is_enabled(bp)) { ++ ngx_http_lua_balancer_get_keepalive_pool(L, bp->cpool_crc32, ++ &bp->cpool); ++ ++ if (bp->cpool == NULL ++ && ngx_http_lua_balancer_create_keepalive_pool(L, pc->log, ++ bp->cpool_crc32, ++ bp->cpool_size, ++ &bp->cpool) ++ != NGX_OK) ++ { ++ return NGX_ERROR; ++ } ++ ++ ngx_http_lua_assert(bp->cpool); ++ ++ if (!ngx_queue_empty(&bp->cpool->cache)) { ++ q = ngx_queue_head(&bp->cpool->cache); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ c = item->connection; ++ ++ ngx_queue_remove(q); ++ ngx_queue_insert_head(&bp->cpool->free, q); ++ ++ c->idle = 0; ++ c->sent = 0; ++ c->log = pc->log; ++ c->read->log = pc->log; ++ c->write->log = pc->log; ++ c->pool->log = pc->log; ++ ++ if (c->read->timer_set) { ++ ngx_del_timer(c->read); ++ } ++ ++ pc->cached = 1; ++ pc->connection = c; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive reusing connection %p, " ++ "requests: %ui, cpool: %p", ++ c, c->requests, bp->cpool); ++ ++ return NGX_DONE; ++ } ++ ++ bp->cpool->connections++; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive no free connection, " ++ "cpool: %p", bp->cpool); ++ } + + return NGX_OK; + } + +- return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp); ++ return bp->original_get_peer(pc, bp->data); + } + + +-static ngx_int_t +-ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) ++static void ++ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, ++ ngx_uint_t state) + { +- u_char *err_msg; +- size_t len; +- ngx_int_t rc; ++ ngx_queue_t *q; ++ ngx_connection_t *c; ++ ngx_http_upstream_t *u; ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++ ngx_http_lua_balancer_peer_data_t *bp = data; + +- /* init nginx context in Lua VM */ +- ngx_http_lua_set_req(L, r); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: free peer, tries: %ui", pc->tries); + +-#ifndef OPENRESTY_LUAJIT +- ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); ++ u = bp->request->upstream; ++ c = pc->connection; + +- /* {{{ make new env inheriting main thread's globals table */ +- lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ +- ngx_http_lua_get_globals_table(L); +- lua_setfield(L, -2, "__index"); +- lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ +- /* }}} */ ++ if (ngx_http_lua_balancer_peer_set(bp)) { ++ bp->last_peer_state = (int) state; + +- lua_setfenv(L, -2); /* set new running env for the code closure */ +-#endif /* OPENRESTY_LUAJIT */ ++ if (pc->tries) { ++ pc->tries--; ++ } + +- lua_pushcfunction(L, ngx_http_lua_traceback); +- lua_insert(L, 1); /* put it under chunk and args */ ++ if (ngx_http_lua_balancer_keepalive_is_enabled(bp)) { ++ cpool = bp->cpool; + +- /* protected call user code */ +- rc = lua_pcall(L, 0, 1, 1); ++ if (state & NGX_PEER_FAILED ++ || c == NULL ++ || c->read->eof ++ || c->read->error ++ || c->read->timedout ++ || c->write->error ++ || c->write->timedout) ++ { ++ goto invalid; ++ } + +- lua_remove(L, 1); /* remove traceback function */ ++ if (bp->keepalive_requests ++ && c->requests >= bp->keepalive_requests) ++ { ++ goto invalid; ++ } + +- dd("rc == %d", (int) rc); ++ if (!u->keepalive) { ++ goto invalid; ++ } + +- if (rc != 0) { +- /* error occurred when running loaded code */ +- err_msg = (u_char *) lua_tolstring(L, -1, &len); ++ if (!u->request_body_sent) { ++ goto invalid; ++ } + +- if (err_msg == NULL) { +- err_msg = (u_char *) "unknown reason"; +- len = sizeof("unknown reason") - 1; ++ if (ngx_terminate || ngx_exiting) { ++ goto invalid; ++ } ++ ++ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ++ goto invalid; ++ } ++ ++ if (ngx_queue_empty(&cpool->free)) { ++ q = ngx_queue_last(&cpool->cache); ++ ngx_queue_remove(q); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ ++ ngx_http_lua_balancer_close(item->connection); ++ ++ } else { ++ q = ngx_queue_head(&cpool->free); ++ ngx_queue_remove(q); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ } ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive saving connection %p, " ++ "cpool: %p, connections: %ui", ++ c, cpool, cpool->connections); ++ ++ ngx_queue_insert_head(&cpool->cache, q); ++ ++ item->connection = c; ++ ++ pc->connection = NULL; ++ ++ if (bp->keepalive_timeout) { ++ c->read->delayed = 0; ++ ngx_add_timer(c->read, bp->keepalive_timeout); ++ ++ } else if (c->read->timer_set) { ++ ngx_del_timer(c->read); ++ } ++ ++ if (c->write->timer_set) { ++ ngx_del_timer(c->write); ++ } ++ ++ c->write->handler = ngx_http_lua_balancer_dummy_handler; ++ c->read->handler = ngx_http_lua_balancer_close_handler; ++ ++ c->data = item; ++ c->idle = 1; ++ c->log = ngx_cycle->log; ++ c->read->log = ngx_cycle->log; ++ c->write->log = ngx_cycle->log; ++ c->pool->log = ngx_cycle->log; ++ ++ if (c->read->ready) { ++ ngx_http_lua_balancer_close_handler(c->read); ++ } ++ ++ return; ++ ++invalid: ++ ++ cpool->connections--; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive not saving connection %p, " ++ "cpool: %p, connections: %ui", ++ c, cpool, cpool->connections); ++ ++ if (cpool->connections == 0) { ++ ngx_http_lua_balancer_free_keepalive_pool(pc->log, cpool); ++ } + } + +- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, +- "failed to run balancer_by_lua*: %*s", len, err_msg); ++ return; ++ } + +- lua_settop(L, 0); /* clear remaining elems on stack */ ++ bp->original_free_peer(pc, bp->data, state); ++} ++ ++ ++static ngx_int_t ++ngx_http_lua_balancer_create_keepalive_pool(lua_State *L, ngx_log_t *log, ++ uint32_t cpool_crc32, ngx_uint_t cpool_size, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool) ++{ ++ size_t size; ++ ngx_uint_t i; ++ ngx_http_lua_balancer_keepalive_pool_t *upool; ++ ngx_http_lua_balancer_keepalive_item_t *items; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ ngx_http_lua_assert(lua_istable(L, -1)); ++ ++ size = sizeof(ngx_http_lua_balancer_keepalive_pool_t) ++ + sizeof(ngx_http_lua_balancer_keepalive_item_t) * cpool_size; + ++ upool = lua_newuserdata(L, size); /* pools upool */ ++ if (upool == NULL) { + return NGX_ERROR; + } + +- lua_settop(L, 0); /* clear remaining elems on stack */ +- return rc; ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, ++ "lua balancer: keepalive create pool, crc32: %ui, " ++ "size: %ui", cpool_crc32, cpool_size); ++ ++ upool->lua_vm = L; ++ upool->crc32 = cpool_crc32; ++ upool->size = cpool_size; ++ upool->connections = 0; ++ ++ ngx_queue_init(&upool->cache); ++ ngx_queue_init(&upool->free); ++ ++ lua_rawseti(L, -2, cpool_crc32); /* pools */ ++ lua_pop(L, 1); /* orig stack */ ++ ++ items = (ngx_http_lua_balancer_keepalive_item_t *) (&upool->free + 1); ++ ++ ngx_http_lua_assert((void *) items == ngx_align_ptr(items, NGX_ALIGNMENT)); ++ ++ for (i = 0; i < cpool_size; i++) { ++ ngx_queue_insert_head(&upool->free, &items[i].queue); ++ items[i].cpool = upool; ++ } ++ ++ *cpool = upool; ++ ++ return NGX_OK; + } + + + static void +-ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, +- ngx_uint_t state) ++ngx_http_lua_balancer_get_keepalive_pool(lua_State *L, uint32_t cpool_crc32, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool) + { +- ngx_http_lua_balancer_peer_data_t *bp = data; ++ ngx_http_lua_balancer_keepalive_pool_t *upool; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* orig stack */ ++ ++ /* create upstream connection pools table */ ++ lua_createtable(L, 0, 0); /* pools */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_pushvalue(L, -2); /* pools pools_table_key pools */ ++ lua_rawset(L, LUA_REGISTRYINDEX); /* pools */ ++ } + +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, +- "lua balancer free peer, tries: %ui", pc->tries); ++ ngx_http_lua_assert(lua_istable(L, -1)); + +- if (bp->sockaddr && bp->socklen) { +- bp->last_peer_state = (int) state; ++ lua_rawgeti(L, -1, cpool_crc32); /* pools upool? */ ++ upool = lua_touserdata(L, -1); ++ lua_pop(L, 2); /* orig stack */ + +- if (pc->tries) { +- pc->tries--; ++ *cpool = upool; ++} ++ ++ ++static void ++ngx_http_lua_balancer_free_keepalive_pool(ngx_log_t *log, ++ ngx_http_lua_balancer_keepalive_pool_t *cpool) ++{ ++ lua_State *L; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, ++ "lua balancer: keepalive free pool %p, crc32: %ui", ++ cpool, cpool->crc32); ++ ++ ngx_http_lua_assert(cpool->connections == 0); ++ ++ L = cpool->lua_vm; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* orig stack */ ++ return; ++ } ++ ++ ngx_http_lua_assert(lua_istable(L, -1)); ++ ++ lua_pushnil(L); /* pools nil */ ++ lua_rawseti(L, -2, cpool->crc32); /* pools */ ++ lua_pop(L, 1); /* orig stack */ ++} ++ ++ ++static void ++ngx_http_lua_balancer_close(ngx_connection_t *c) ++{ ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ++ item = c->data; ++ ++#if (NGX_HTTP_SSL) ++ if (c->ssl) { ++ c->ssl->no_wait_shutdown = 1; ++ c->ssl->no_send_shutdown = 1; ++ ++ if (ngx_ssl_shutdown(c) == NGX_AGAIN) { ++ c->ssl->handler = ngx_http_lua_balancer_close; ++ return; ++ } ++ } ++#endif ++ ++ ngx_destroy_pool(c->pool); ++ ngx_close_connection(c); ++ ++ item->cpool->connections--; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "lua balancer: keepalive closing connection %p, cpool: %p, " ++ "connections: %ui", ++ c, item->cpool, item->cpool->connections); ++} ++ ++ ++static void ++ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev) ++{ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, ++ "lua balancer: dummy handler"); ++} ++ ++ ++static void ++ngx_http_lua_balancer_close_handler(ngx_event_t *ev) ++{ ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ++ int n; ++ char buf[1]; ++ ngx_connection_t *c; ++ ++ c = ev->data; ++ ++ if (c->close || c->read->timedout) { ++ goto close; ++ } ++ ++ n = recv(c->fd, buf, 1, MSG_PEEK); ++ ++ if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { ++ ev->ready = 0; ++ ++ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ++ goto close; + } + + return; + } + +- /* fallback */ ++close: ++ ++ item = c->data; ++ c->log = ev->log; ++ ++ ngx_http_lua_balancer_close(c); + +- ngx_http_upstream_free_round_robin_peer(pc, data, state); ++ ngx_queue_remove(&item->queue); ++ ngx_queue_insert_head(&item->cpool->free, &item->queue); ++ ++ if (item->cpool->connections == 0) { ++ ngx_http_lua_balancer_free_keepalive_pool(ev->log, item->cpool); ++ } + } + + +@@ -431,12 +874,12 @@ ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data) + { + ngx_http_lua_balancer_peer_data_t *bp = data; + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + /* TODO */ + return NGX_OK; + } + +- return ngx_http_upstream_set_round_robin_peer_session(pc, &bp->rrp); ++ return bp->original_set_session(pc, bp->data); + } + + +@@ -445,13 +888,12 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) + { + ngx_http_lua_balancer_peer_data_t *bp = data; + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + /* TODO */ + return; + } + +- ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp); +- return; ++ bp->original_save_session(pc, bp->data); + } + + #endif +@@ -459,14 +901,14 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) + + int + ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, +- const u_char *addr, size_t addr_len, int port, char **err) ++ const u_char *addr, size_t addr_len, int port, unsigned int cpool_crc32, ++ unsigned int cpool_size, char **err) + { +- ngx_url_t url; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- +- ngx_http_lua_main_conf_t *lmcf; +- ngx_http_lua_balancer_peer_data_t *bp; ++ ngx_url_t url; ++ ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { + *err = "no request found"; +@@ -536,6 +978,70 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ bp->cpool_crc32 = (uint32_t) cpool_crc32; ++ bp->cpool_size = (ngx_uint_t) cpool_size; ++ ++ return NGX_OK; ++} ++ ++ ++int ++ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, ++ unsigned long timeout, unsigned int max_requests, char **err) ++{ ++ ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_peer_data_t *bp; ++ ++ if (r == NULL) { ++ *err = "no request found"; ++ return NGX_ERROR; ++ } ++ ++ u = r->upstream; ++ ++ if (u == NULL) { ++ *err = "no upstream found"; ++ return NGX_ERROR; ++ } ++ ++ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); ++ if (ctx == NULL) { ++ *err = "no ctx found"; ++ return NGX_ERROR; ++ } ++ ++ if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { ++ *err = "API disabled in the current context"; ++ return NGX_ERROR; ++ } ++ ++ lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); ++ ++ /* we cannot read r->upstream->peer.data here directly because ++ * it could be overridden by other modules like ++ * ngx_http_upstream_keepalive_module. ++ */ ++ bp = lmcf->balancer_peer_data; ++ if (bp == NULL) { ++ *err = "no upstream peer data found"; ++ return NGX_ERROR; ++ } ++ ++ if (!ngx_http_lua_balancer_peer_set(bp)) { ++ *err = "no current peer set"; ++ return NGX_ERROR; ++ } ++ ++ if (!bp->cpool_crc32) { ++ bp->cpool_crc32 = ngx_crc32_long(bp->host->data, bp->host->len); ++ } ++ ++ bp->keepalive_timeout = (ngx_msec_t) timeout; ++ bp->keepalive_requests = (ngx_uint_t) max_requests; ++ bp->keepalive = 1; ++ + return NGX_OK; + } + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_common.h b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +index 781a2454..9ce6836a 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_common.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +@@ -295,6 +295,10 @@ union ngx_http_lua_srv_conf_u { + #endif + + struct { ++ ngx_http_upstream_init_pt original_init_upstream; ++ ngx_http_upstream_init_peer_pt original_init_peer; ++ uintptr_t data; ++ + ngx_http_lua_srv_conf_handler_pt handler; + ngx_str_t src; + u_char *src_key; +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_module.c b/ngx_lua-0.10.17/src/ngx_http_lua_module.c +index 9816d864..5d7cedfd 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_module.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_module.c +@@ -988,6 +988,9 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf) + * lscf->srv.ssl_session_fetch_src = { 0, NULL }; + * lscf->srv.ssl_session_fetch_src_key = NULL; + * ++ * lscf->balancer.original_init_upstream = NULL; ++ * lscf->balancer.original_init_peer = NULL; ++ * lscf->balancer.data = NULL; + * lscf->balancer.handler = NULL; + * lscf->balancer.src = { 0, NULL }; + * lscf->balancer.src_key = NULL; +-- +2.26.2 + + +From 4c5cb29a265b2f9524434322adf15d07deec6c7f Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:54 -0700 +Subject: [PATCH 2/3] feature: we now avoid the need for 'upstream' blocks to + define a stub 'server' directive when using 'balancer_by_lua*'. + +--- + src/ngx_http_lua_balancer.c | 42 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 0d403716..5c862d22 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -111,7 +111,8 @@ static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, + (bp->sockaddr && bp->socklen) + + +-static char ngx_http_lua_balancer_keepalive_pools_table_key; ++static char ngx_http_lua_balancer_keepalive_pools_table_key; ++static struct sockaddr *ngx_http_lua_balancer_default_server_sockaddr; + + + ngx_int_t +@@ -239,7 +240,9 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + u_char *cache_key = NULL; + u_char *name; + ngx_str_t *value; ++ ngx_url_t url; + ngx_http_upstream_srv_conf_t *uscf; ++ ngx_http_upstream_server_t *us; + ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); +@@ -293,6 +296,29 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + ++ if (uscf->servers->nelts == 0) { ++ us = ngx_array_push(uscf->servers); ++ if (us == NULL) { ++ return NGX_CONF_ERROR; ++ } ++ ++ ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); ++ ngx_memzero(&url, sizeof(ngx_url_t)); ++ ++ ngx_str_set(&url.url, "0.0.0.1"); ++ url.default_port = 80; ++ ++ if (ngx_parse_url(cf->pool, &url) != NGX_OK) { ++ return NGX_CONF_ERROR; ++ } ++ ++ us->name = url.url; ++ us->addrs = url.addrs; ++ us->naddrs = url.naddrs; ++ ++ ngx_http_lua_balancer_default_server_sockaddr = us->addrs[0].sockaddr; ++ } ++ + if (uscf->peer.init_upstream) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "load balancing method redefined"); +@@ -525,7 +551,19 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + return NGX_OK; + } + +- return bp->original_get_peer(pc, bp->data); ++ rc = bp->original_get_peer(pc, bp->data); ++ if (rc == NGX_ERROR) { ++ return rc; ++ } ++ ++ if (pc->sockaddr == ngx_http_lua_balancer_default_server_sockaddr) { ++ ngx_log_error(NGX_LOG_ERR, pc->log, 0, ++ "lua balancer: no peer set"); ++ ++ return NGX_ERROR; ++ } ++ ++ return rc; + } + + +-- +2.26.2 + + +From 941cd893573561574bc6a326d6306f1a30127293 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:58 -0700 +Subject: [PATCH 3/3] refactor: used a simpler way to stash the balancer peer + data. + +--- + src/ngx_http_lua_balancer.c | 91 +++++++++---------------------------- + src/ngx_http_lua_common.h | 7 --- + 2 files changed, 22 insertions(+), 76 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 5c862d22..3ea1f067 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -411,9 +411,9 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_srv_conf_t *lscf; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_keepalive_item_t *item; + ngx_http_lua_balancer_peer_data_t *bp = data; ++ void *pdata; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: get peer, tries: %ui", pc->tries); +@@ -452,15 +452,13 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + bp->keepalive = 0; + bp->total_tries++; + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* balancer_by_lua does not support yielding and +- * there cannot be any conflicts among concurrent requests, +- * thus it is safe to store the peer data in the main conf. +- */ +- lmcf->balancer_peer_data = bp; ++ pdata = r->upstream->peer.data; ++ r->upstream->peer.data = bp; + + rc = lscf->balancer.handler(r, lscf, L); ++ ++ r->upstream->peer.data = pdata; ++ + if (rc == NGX_ERROR) { + return NGX_ERROR; + } +@@ -945,7 +943,6 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + ngx_url_t url; + ngx_http_upstream_t *u; + ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -971,18 +968,6 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* we cannot read r->upstream->peer.data here directly because +- * it could be overridden by other modules like +- * ngx_http_upstream_keepalive_module. +- */ +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } +- + ngx_memzero(&url, sizeof(ngx_url_t)); + + url.url.data = ngx_palloc(r->pool, addr_len); +@@ -1006,6 +991,8 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; ++ + if (url.addrs && url.addrs[0].sockaddr) { + bp->sockaddr = url.addrs[0].sockaddr; + bp->socklen = url.addrs[0].socklen; +@@ -1029,7 +1016,6 @@ ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, + { + ngx_http_upstream_t *u; + ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -1055,17 +1041,7 @@ ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* we cannot read r->upstream->peer.data here directly because +- * it could be overridden by other modules like +- * ngx_http_upstream_keepalive_module. +- */ +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + if (!ngx_http_lua_balancer_peer_set(bp)) { + *err = "no current peer set"; +@@ -1089,14 +1065,13 @@ ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, long read_timeout, + char **err) + { +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; + + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + ngx_http_upstream_conf_t *ucf; +-#endif +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; ++#endif + + if (r == NULL) { + *err = "no request found"; +@@ -1121,15 +1096,9 @@ ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } +- + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; ++ + if (!bp->cloned_upstream_conf) { + /* we clone the upstream conf for the current request so that + * we do not affect other requests at all. */ +@@ -1184,12 +1153,10 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + int count, char **err) + { + #if (nginx_version >= 1007005) +- ngx_uint_t max_tries, total; ++ ngx_uint_t max_tries, total; + #endif +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- +- ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -1215,13 +1182,7 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + #if (nginx_version >= 1007005) + max_tries = r->upstream->conf->next_upstream_tries; +@@ -1247,12 +1208,10 @@ int + ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + int *status, char **err) + { +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- ngx_http_upstream_state_t *state; +- ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; ++ ngx_http_upstream_state_t *state; + ngx_http_lua_balancer_peer_data_t *bp; +- ngx_http_lua_main_conf_t *lmcf; + + if (r == NULL) { + *err = "no request found"; +@@ -1277,13 +1236,7 @@ ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + if (r->upstream_states && r->upstream_states->nelts > 1) { + state = r->upstream_states->elts; +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_common.h b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +index 9ce6836a..9a4342df 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_common.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +@@ -217,13 +217,6 @@ struct ngx_http_lua_main_conf_s { + ngx_http_lua_main_conf_handler_pt init_worker_handler; + ngx_str_t init_worker_src; + +- ngx_http_lua_balancer_peer_data_t *balancer_peer_data; +- /* neither yielding nor recursion is possible in +- * balancer_by_lua*, so there cannot be any races among +- * concurrent requests and it is safe to store the peer +- * data pointer in the main conf. +- */ +- + ngx_chain_t *body_filter_chain; + /* neither yielding nor recursion is possible in + * body_filter_by_lua*, so there cannot be any races among +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_03-upstream_recreate_request.patch b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_03-upstream_recreate_request.patch new file mode 100644 index 00000000..f7a7d9c2 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/ngx_lua-0.10.17_03-upstream_recreate_request.patch @@ -0,0 +1,59 @@ +From 200cf83dbd180bc015e3e1b5b4344abc665d096a Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 23 Jun 2020 17:33:09 -0700 +Subject: [PATCH] feature: added the + `ngx_http_lua_ffi_balancer_recreate_request` FFI function to allow recreation + of request buffer in balancer phase. + +--- + ngx_lua-0.10.17/src/ngx_http_lua_balancer.c | 39 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 3ea1f067..19a785e5 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -1250,4 +1250,43 @@ ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + } + + ++int ++ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r, ++ char **err) ++{ ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; ++ ++ if (r == NULL) { ++ *err = "no request found"; ++ return NGX_ERROR; ++ } ++ ++ u = r->upstream; ++ ++ if (u == NULL) { ++ *err = "no upstream found"; ++ return NGX_ERROR; ++ } ++ ++ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); ++ if (ctx == NULL) { ++ *err = "no ctx found"; ++ return NGX_ERROR; ++ } ++ ++ if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { ++ *err = "API disabled in the current context"; ++ return NGX_ERROR; ++ } ++ ++ /* u->create_request can not be NULL since we are in balancer phase */ ++ ngx_http_lua_assert(u->create_request != NULL); ++ ++ *err = NULL; ++ ++ return u->create_request(r); ++} ++ ++ + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch b/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch new file mode 100644 index 00000000..0b27a67e --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch @@ -0,0 +1,25 @@ +From a6afd31d32b31cf67afb13873deefb0c9d4e50a9 Mon Sep 17 00:00:00 2001 +From: James Callahan +Date: Tue, 11 Sep 2018 10:34:53 -0700 +Subject: [PATCH 4/9] inject req time api + +Signed-off-by: Aapo Talvensaari +--- + ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c b/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c +index 313a8f4..f47a574 100644 +--- a/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c ++++ b/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c +@@ -1955,6 +1955,7 @@ ngx_stream_lua_inject_req_api(ngx_log_t *log, lua_State *L) + lua_pushcfunction(L, ngx_stream_lua_req_socket); + lua_setfield(L, -2, "socket"); + ++ ngx_stream_lua_inject_req_time_api(L); + + lua_setfield(L, -2, "req"); + } +-- +2.19.1 + diff --git a/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_02-expose_request_struct.patch b/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_02-expose_request_struct.patch new file mode 100644 index 00000000..029150c3 --- /dev/null +++ b/openresty-patches/patches/1.17.8.1/ngx_stream_lua-0.0.8_02-expose_request_struct.patch @@ -0,0 +1,27 @@ +From 0acb7f5ad0fbc9ee037f0c5d689f98861fe9e49b Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 10 Dec 2019 11:51:53 -0800 +Subject: [PATCH] Sync with meta-lua-nginx-module + 1330009671cd86eaf045f9f2c5cda3727a94570f. + +--- + ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h b/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h +index 0e5a18f..040ef84 100644 +--- a/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h ++++ b/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h +@@ -21,6 +21,9 @@ + + + ++#include ++#include "../ngx_stream_lua_request.h" ++ + + #include + #include +-- +2.20.1 + From 64fca6bbd37ee9c8431af9e047b8d9a9b0918762 Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Mon, 13 Jul 2020 17:20:02 -0700 Subject: [PATCH 3/3] feat(openresty-patches) add patches for OpenResty 1.17.8.2 --- ....1-20200102_01-dyn-lightuserdata-map.patch | 207 +++ ...a-resty-core-0.1.19_01-cosocket-mtls.patch | 446 ++++++ ...ore-0.1.19_02-dyn_upstream_keepalive.patch | 231 +++ ...-0.1.19_03-upstream_recreate_request.patch | 55 + ...core-0.1.19_04-stream_req_start_time.patch | 183 +++ ...-resty-websocket-0.07_01-client-mtls.patch | 64 + ...am_client_certificate_and_ssl_verify.patch | 52 + ...tokens-from-special-responses-output.patch | 38 + ...x-1.17.8_03-stream_proxy_ssl_disable.patch | 33 + .../ngx_lua-0.10.17_01-cosocket-mtls.patch | 970 ++++++++++++ ...ua-0.10.17_02-dyn_upstream_keepalive.patch | 1320 +++++++++++++++++ ...0.10.17_03-upstream_recreate_request.patch | 59 + ...eam_lua-0.0.8_01-inject-req-time-api.patch | 25 + ...m_lua-0.0.8_02-expose_request_struct.patch | 27 + 14 files changed, 3710 insertions(+) create mode 100644 openresty-patches/patches/1.17.8.2/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch create mode 100644 openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_01-cosocket-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch create mode 100644 openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_03-upstream_recreate_request.patch create mode 100644 openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_04-stream_req_start_time.patch create mode 100644 openresty-patches/patches/1.17.8.2/lua-resty-websocket-0.07_01-client-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.2/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch create mode 100644 openresty-patches/patches/1.17.8.2/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch create mode 100644 openresty-patches/patches/1.17.8.2/nginx-1.17.8_03-stream_proxy_ssl_disable.patch create mode 100644 openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_01-cosocket-mtls.patch create mode 100644 openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch create mode 100644 openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_03-upstream_recreate_request.patch create mode 100644 openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch create mode 100644 openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_02-expose_request_struct.patch diff --git a/openresty-patches/patches/1.17.8.2/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch b/openresty-patches/patches/1.17.8.2/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch new file mode 100644 index 00000000..d5d95269 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/LuaJIT-2.1-20200102_01-dyn-lightuserdata-map.patch @@ -0,0 +1,207 @@ +From 22945d38da972613a171231ba16f7c759d4512a1 Mon Sep 17 00:00:00 2001 +From: Javier Guerra +Date: Tue, 13 Aug 2019 05:05:17 -0700 +Subject: [PATCH] Dynamic remapping of lightuserdata values + +To allow architectures with VA larger than 47 bits, splits the space in 8 sections, each of 2^LJ_LUV_SECT_SHIFT bytes +(2^45 on ARM64 (32TiB), VA is 48 bits). Since the lightuserdata value must have zeros on all bits above 47, only +sections [0..3] are valid. The table `luv_sect_map[]` must map any section used by the memory layout into a valid +section. It should also be a symetric mapping, so a repeat of the transformation returns the original value. + +The `luv_init_map()` function uses a sample of different types of pointers to determine with sections are actually +used, and constructs the required table. +--- + src/lj_api.c | 5 +-- + src/lj_arch.h | 1 + + src/lj_cconv.c | 2 +- + src/lj_obj.h | 15 +++++++++ + src/lj_state.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 105 insertions(+), 3 deletions(-) + +diff --git a/LuaJIT-2.1-20200102/src/lj_api.c b/LuaJIT-2.1-20200102/src/lj_api.c +index 9c4864d..0a3f778 100644 +--- a/LuaJIT-2.1-20200102/src/lj_api.c ++++ b/LuaJIT-2.1-20200102/src/lj_api.c +@@ -595,7 +595,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx) + if (tvisudata(o)) + return uddata(udataV(o)); + else if (tvislightud(o)) +- return lightudV(o); ++ return lightuvmap(lightudV(o)); + else + return NULL; + } +@@ -696,6 +696,7 @@ LUA_API void lua_pushboolean(lua_State *L, int b) + + LUA_API void lua_pushlightuserdata(lua_State *L, void *p) + { ++ p = lightuvmap(p); + setlightudV(L->top, checklightudptr(L, p)); + incr_top(L); + } +@@ -1138,7 +1139,7 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) + fn->c.f = func; + setfuncV(L, top++, fn); + if (LJ_FR2) setnilV(top++); +- setlightudV(top++, checklightudptr(L, ud)); ++ setlightudV(top++, checklightudptr(L, lightuvmap(ud))); + cframe_nres(L->cframe) = 1+0; /* Zero results. */ + L->top = top; + return top-1; /* Now call the newly allocated C function. */ +diff --git a/LuaJIT-2.1-20200102/src/lj_arch.h b/LuaJIT-2.1-20200102/src/lj_arch.h +index 8f6bc52..cf1c641 100644 +--- a/LuaJIT-2.1-20200102/src/lj_arch.h ++++ b/LuaJIT-2.1-20200102/src/lj_arch.h +@@ -237,6 +237,7 @@ + #define LJ_TARGET_MASKROT 1 + #define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */ + #define LJ_TARGET_GC64 1 ++#define LJ_LUV_SECT_SHIFT 45 + #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL + + #define LJ_ARCH_VERSION 80 +diff --git a/LuaJIT-2.1-20200102/src/lj_cconv.c b/LuaJIT-2.1-20200102/src/lj_cconv.c +index 13b8230..05eed3a 100644 +--- a/LuaJIT-2.1-20200102/src/lj_cconv.c ++++ b/LuaJIT-2.1-20200102/src/lj_cconv.c +@@ -611,7 +611,7 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, + if (ud->udtype == UDTYPE_IO_FILE) + tmpptr = *(void **)tmpptr; + } else if (tvislightud(o)) { +- tmpptr = lightudV(o); ++ tmpptr = lightuvmap(lightudV(o)); + } else if (tvisfunc(o)) { + void *p = lj_ccallback_new(cts, d, funcV(o)); + if (p) { +diff --git a/LuaJIT-2.1-20200102/src/lj_obj.h b/LuaJIT-2.1-20200102/src/lj_obj.h +index a89ea0d..77a157b 100644 +--- a/LuaJIT-2.1-20200102/src/lj_obj.h ++++ b/LuaJIT-2.1-20200102/src/lj_obj.h +@@ -830,6 +830,21 @@ typedef union GCobj { + #define setpriV(o, i) (setitype((o), (i))) + #endif + ++#ifdef LJ_LUV_SECT_SHIFT ++#define LJ_LUV_SECT_MASK (7UL << LJ_LUV_SECT_SHIFT) ++extern uint8_t luv_sect_map[8]; ++#endif ++ ++static LJ_AINLINE void *lightuvmap(void *p) ++{ ++#ifdef LJ_LUV_SECT_SHIFT ++ uintptr_t section = luv_sect_map[((uintptr_t)p >> LJ_LUV_SECT_SHIFT) & 7]; ++ p = (void *)(((uintptr_t)p & ~LJ_LUV_SECT_MASK) | (section << LJ_LUV_SECT_SHIFT)); ++#endif ++ return p; ++} ++ ++#include + static LJ_AINLINE void setlightudV(TValue *o, void *p) + { + #if LJ_GC64 +diff --git a/LuaJIT-2.1-20200102/src/lj_state.c b/LuaJIT-2.1-20200102/src/lj_state.c +index a0fba2a..1ab3097 100644 +--- a/LuaJIT-2.1-20200102/src/lj_state.c ++++ b/LuaJIT-2.1-20200102/src/lj_state.c +@@ -29,6 +29,90 @@ + #include "lj_alloc.h" + #include "luajit.h" + ++/* -- lightuserdata remapping --------------------------------------------- */ ++ ++#ifdef LJ_LUV_SECT_SHIFT ++ ++static char checked_layout = 0; ++ ++#define LJ_LUV_SECT_MASK (7UL << LJ_LUV_SECT_SHIFT) ++uint8_t luv_sect_map[8] = { ++ 0, 1, 7, 3, 4, 5, 6, 2, /* 111 <-> 010 */ ++}; ++ ++ ++static void luvmap_mark_need(void *p) ++{ ++ int index = ((uintptr_t)p >> LJ_LUV_SECT_SHIFT) & 7; ++ ++ luv_sect_map[index] = index < 4 ? index : 128; ++} ++ ++static void luvmap_fold(void) ++{ ++ int i, j; ++ ++ for (i = 0; i < 8; ++i) { ++ if (luv_sect_map[i] == 128) { /* needed but invalid */ ++ for (j = 3; j >= 0; --j) { ++ if (luv_sect_map[j] == 255) { /* found unused, swap */ ++ luv_sect_map[i] = j; ++ luv_sect_map[j] = i; ++ break; ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ if (luv_sect_map[i] == 128) ++ abort(); /* unfixed section */ ++ ++ if (luv_sect_map[i] == 255) ++ luv_sect_map[i] = i; ++ } ++} ++ ++static void luv_init_map() { ++ int i; ++ ++ if (checked_layout != 0) ++ return; ++ ++ for (i = 0; i < 8; ++i) ++ luv_sect_map[i] = 255; ++ ++ char unused_local = 0; ++ void *p = malloc(1); lua_assert(c != NULL); ++ ++ luvmap_mark_need(NULL); /* common use */ ++ luvmap_mark_need(&checked_layout); /* global space */ ++ luvmap_mark_need(&unused_local); /* stack space */ ++ luvmap_mark_need(&luv_init_map); /* function space */ ++ luvmap_mark_need(p); /* heap space */ ++ ++ /* some modules mask pointers before pushing. */ ++ /* mark them as needed too */ ++ #define luv_mask47(p) ((void *) ((uintptr_t) (p) & ((1UL << 47) - 1))) ++ ++ luvmap_mark_need(luv_mask47(&checked_layout)); ++ luvmap_mark_need(luv_mask47(&unused_local)); ++ luvmap_mark_need(luv_mask47(&luv_init_map)); ++ luvmap_mark_need(luv_mask47(p)); ++ ++ #undef luv_mask47 ++ ++ free(p); ++ ++ luvmap_fold(); ++ checked_layout = 1; ++} ++ ++#else ++#define luv_init_map() ++#endif ++ ++ + /* -- Stack handling ------------------------------------------------------ */ + + /* Stack sizes. */ +@@ -186,6 +270,7 @@ lua_State *lj_state_newstate(lua_Alloc f, void *ud) + LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) + #endif + { ++ luv_init_map(); + GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); + lua_State *L = &GG->L; + global_State *g = &GG->g; +-- +2.17.1 + diff --git a/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_01-cosocket-mtls.patch b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_01-cosocket-mtls.patch new file mode 100644 index 00000000..058768ed --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_01-cosocket-mtls.patch @@ -0,0 +1,446 @@ +From ddf9dac29e0dd8376e51b369710e42c948e9d959 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:41:56 -0700 +Subject: =?UTF-8?q?feature:=20implement=20the=20`tcpsock:tlshandshake`=20a?= + =?UTF-8?q?nd=20`tcpsock:sslhandshake`=0Afunctions=20using=20FFI.?= + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 172 ++++++++++++++++++++++++++++++++++ + 2 files changed, 173 insertions(+) + create mode 100644 lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +new file mode 100644 +index 0000000..fe81de5 +--- /dev/null ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -0,0 +1,172 @@ ++local ffi = require("ffi") ++local base = require("resty.core.base") ++ ++local C = ffi.C ++local ffi_string = ffi.string ++local ffi_gc = ffi.gc ++local FFI_ERROR = base.FFI_ERROR ++local FFI_DONE = base.FFI_DONE ++local FFI_OK = base.FFI_OK ++local FFI_AGAIN = base.FFI_AGAIN ++local get_request = base.get_request ++local error = error ++local assert = assert ++local getmetatable = getmetatable ++local type = type ++local select = select ++local co_yield = coroutine._yield ++local table_new = require("table.new") ++local table_clear = require("table.clear") ++ ++if not pcall(ffi.typeof, "ngx_ssl_session_t") then ++ ffi.cdef[[ ++ typedef struct SSL_SESSION ngx_ssl_session_t; ++ ]] ++end ++ ++ffi.cdef[[ ++typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; ++ ++int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ int enable_session_reuse, ngx_str_t *server_name, int verify, ++ int ocsp_status_req, char **errmsg); ++int ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ char **errmsg, int *openssl_error_code); ++void ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess); ++]] ++ ++ ++local SOCKET_CTX_INDEX = 1 ++ ++ ++local errmsg = base.get_errmsg_ptr() ++local session_ptr = ffi.new("ngx_ssl_session_t *[1]") ++local server_name_str = ffi.new("ngx_str_t[1]") ++local openssl_error_code = ffi.new("int[1]") ++local cached_options = table_new(0, 4) ++ ++ ++local function tlshandshake(self, options) ++ if not options then ++ table_clear(cached_options) ++ options = cached_options ++ ++ elseif type(options) ~= "table" then ++ error("bad options table type") ++ end ++ ++ local r = get_request() ++ ++ if not r then ++ error("no request found") ++ end ++ ++ local reused_session = options.reused_session ++ session_ptr[0] = type(reused_session) == "cdata" and reused_session or nil ++ ++ if options.server_name then ++ server_name_str[0].data = options.server_name ++ server_name_str[0].len = #options.server_name ++ ++ else ++ server_name_str[0].data = nil ++ server_name_str[0].len = 0 ++ end ++ ++ local rc = ++ C.ngx_http_lua_ffi_socket_tcp_tlshandshake(r, self[SOCKET_CTX_INDEX], ++ session_ptr[0], ++ reused_session ~= false, ++ server_name_str, ++ options.verify and 1 or 0, ++ options.ocsp_status_req ++ and 1 or 0, ++ errmsg) ++ ++::again:: ++ ++ if rc == FFI_ERROR then ++ if openssl_error_code[0] ~= 0 then ++ return nil, openssl_error_code[0] .. ": " .. ffi_string(errmsg[0]) ++ end ++ ++ return nil, ffi_string(errmsg[0]) ++ end ++ ++ if rc == FFI_DONE then ++ return options.reused_session ++ end ++ ++ if rc == FFI_OK then ++ if options.reused_session == false then ++ return true ++ end ++ ++ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, ++ self[SOCKET_CTX_INDEX], session_ptr, errmsg, openssl_error_code) ++ ++ assert(rc == FFI_OK) ++ ++ if session_ptr[0] == nil then ++ return session_ptr[0] ++ end ++ ++ return ffi_gc(session_ptr[0], C.ngx_http_lua_ffi_tls_free_session) ++ end ++ ++ assert(rc == FFI_AGAIN) ++ ++ co_yield() ++ ++ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, ++ self[SOCKET_CTX_INDEX], session_ptr, errmsg, openssl_error_code) ++ ++ assert(rc == FFI_OK or rc == FFI_ERROR) ++ ++ goto again ++end ++ ++ ++local function sslhandshake(self, reused_session, server_name, ssl_verify, ++ send_status_req, ...) ++ ++ local n = select("#", ...) ++ if not self or n > 1 then ++ error("ngx.socket sslhandshake: expecting 1 ~ 5 " ++ .. "arguments (including the object), but seen " .. n) ++ end ++ ++ cached_options.reused_session = reused_session ++ cached_options.server_name = server_name ++ cached_options.verify = ssl_verify ++ cached_options.ocsp_status_req = send_status_req ++ ++ local res, err = tlshandshake(self, cached_options) ++ table_clear(cached_options) ++ ++ return res, err ++end ++ ++ ++do ++ local old_socket_tcp = ngx.socket.tcp ++ ++ function ngx.socket.tcp() ++ local sock = old_socket_tcp() ++ local mt = getmetatable(sock) ++ ++ mt.tlshandshake = tlshandshake ++ mt.sslhandshake = sslhandshake ++ ++ ngx.socket.tcp = old_socket_tcp ++ ++ return sock ++ end ++end ++ ++ ++return { ++ version = base.version ++} +-- +2.20.1 + + +From 1b73826f746a9dd04f60c560d47e778fbec2c2d9 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:55:05 -0700 +Subject: change: better error when request context couldn't be found. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index fe81de5..e18f40e 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -8,6 +8,7 @@ local FFI_ERROR = base.FFI_ERROR + local FFI_DONE = base.FFI_DONE + local FFI_OK = base.FFI_OK + local FFI_AGAIN = base.FFI_AGAIN ++local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX + local get_request = base.get_request + local error = error + local assert = assert +@@ -85,6 +86,10 @@ local function tlshandshake(self, options) + and 1 or 0, + errmsg) + ++ if rc == FFI_NO_REQ_CTX then ++ error("no request ctx found", 2) ++ end ++ + ::again:: + + if rc == FFI_ERROR then +-- +2.20.1 + + +From 0fea325cd7d6ca479afbc8abbc297b4a046bc8c3 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:23:08 -0700 +Subject: cosocket: added client certificate support with TLS handshake. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index e18f40e..ed45c8a 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -19,23 +19,18 @@ local co_yield = coroutine._yield + local table_new = require("table.new") + local table_clear = require("table.clear") + +-if not pcall(ffi.typeof, "ngx_ssl_session_t") then +- ffi.cdef[[ +- typedef struct SSL_SESSION ngx_ssl_session_t; +- ]] +-end +- + ffi.cdef[[ + typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; + + int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ ngx_http_lua_socket_tcp_upstream_t *u, void *sess, + int enable_session_reuse, ngx_str_t *server_name, int verify, +- int ocsp_status_req, char **errmsg); ++ int ocsp_status_req, void *chain, void *pkey, ++ char **errmsg); + int ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ ngx_http_lua_socket_tcp_upstream_t *u, void **sess, + char **errmsg, int *openssl_error_code); +-void ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess); ++void ngx_http_lua_ffi_tls_free_session(void *sess); + ]] + + +@@ -43,7 +38,7 @@ local SOCKET_CTX_INDEX = 1 + + + local errmsg = base.get_errmsg_ptr() +-local session_ptr = ffi.new("ngx_ssl_session_t *[1]") ++local session_ptr = ffi.new("void *[1]") + local server_name_str = ffi.new("ngx_str_t[1]") + local openssl_error_code = ffi.new("int[1]") + local cached_options = table_new(0, 4) +@@ -76,6 +71,21 @@ local function tlshandshake(self, options) + server_name_str[0].len = 0 + end + ++ local client_cert = options.client_cert ++ local client_priv_key = options.client_priv_key ++ if client_cert then ++ if not client_priv_key then ++ error("client certificate supplied without " ++ .. "corresponding private key", 2) ++ end ++ ++ if type(client_cert) ~= "cdata" ++ or type(client_priv_key) ~= "cdata" ++ then ++ error("wrong type of client certificate or private key supplied", 2) ++ end ++ end ++ + local rc = + C.ngx_http_lua_ffi_socket_tcp_tlshandshake(r, self[SOCKET_CTX_INDEX], + session_ptr[0], +@@ -84,6 +94,8 @@ local function tlshandshake(self, options) + options.verify and 1 or 0, + options.ocsp_status_req + and 1 or 0, ++ client_cert, ++ client_priv_key, + errmsg) + + if rc == FFI_NO_REQ_CTX then +-- +2.20.1 + + +From 3ed719e95bc9a0fd1a768c6ead1ca0b8b777905a Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:29:56 -0700 +Subject: style: fixed long line. + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index ed45c8a..a867c73 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -20,7 +20,8 @@ local table_new = require("table.new") + local table_clear = require("table.clear") + + ffi.cdef[[ +-typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; ++typedef struct ngx_http_lua_socket_tcp_upstream_s ++ ngx_http_lua_socket_tcp_upstream_t; + + int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, void *sess, +-- +2.20.1 + + +From 036a7f9b431c7d00fb905533a8f57c7e93f8e0a2 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 24 Sep 2019 16:10:13 -0700 +Subject: =?UTF-8?q?fix:=20transparently=20propagate=20error=20message=20wh?= + =?UTF-8?q?en=20monkey=20patching=20TCP=0Asocket=20metatable.?= + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index a867c73..a4f4eee 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -14,6 +14,7 @@ local error = error + local assert = assert + local getmetatable = getmetatable + local type = type ++local pcall = pcall + local select = select + local co_yield = coroutine._yield + local table_new = require("table.new") +@@ -172,7 +173,11 @@ do + local old_socket_tcp = ngx.socket.tcp + + function ngx.socket.tcp() +- local sock = old_socket_tcp() ++ local ok, sock = pcall(old_socket_tcp) ++ if not ok then ++ error(sock, 2) ++ end ++ + local mt = getmetatable(sock) + + mt.tlshandshake = tlshandshake +-- +2.20.1 + + +From 75251e09f9950261ce7e587950907ff2982b2e51 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Mon, 28 Oct 2019 14:13:08 -0700 +Subject: load resty.core.socket_tcp to monkypatch the socket metatable + +--- + lua-resty-core-0.1.19/lib/resty/core.lua | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core.lua b/lua-resty-core-0.1.19/lib/resty/core.lua +index 57c9d17..7e8aca4 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core.lua +@@ -21,6 +21,7 @@ if subsystem == 'http' then + require "resty.core.worker" + require "resty.core.phase" + require "resty.core.ndk" ++ require "resty.core.socket_tcp" + end + + +-- +2.20.1 + + +From 8d4d81b2fbfac93b270ef70f6441f0d1c70d999e Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Thu, 5 Dec 2019 14:28:24 -0800 +Subject: [PATCH] do not change metatable to avoid conflicts with possible + other monkypatches on `ngx.socket.tcp` + +--- + lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +index a4f4eee..4cd2d77 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/socket_tcp.lua +@@ -12,7 +12,6 @@ local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX + local get_request = base.get_request + local error = error + local assert = assert +-local getmetatable = getmetatable + local type = type + local pcall = pcall + local select = select +@@ -178,12 +177,8 @@ do + error(sock, 2) + end + +- local mt = getmetatable(sock) +- +- mt.tlshandshake = tlshandshake +- mt.sslhandshake = sslhandshake +- +- ngx.socket.tcp = old_socket_tcp ++ sock.tlshandshake = tlshandshake ++ sock.sslhandshake = sslhandshake + + return sock + end +-- +2.20.1 + diff --git a/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch new file mode 100644 index 00000000..1f15f92e --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_02-dyn_upstream_keepalive.patch @@ -0,0 +1,231 @@ +From 37feb95041f183ae4fbafeebc47dc104995e6f27 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:44:33 -0700 +Subject: [PATCH] feature: implemented the 'balancer.enable_keepalive()' API. + +--- + lua-resty-core-0.1.19/lib/ngx/balancer.lua | 165 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 151 insertions(+), 14 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/ngx/balancer.lua b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +index d584639..614312f 100644 +--- a/lua-resty-core-0.1.19/lib/ngx/balancer.lua ++++ b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +@@ -3,6 +3,7 @@ + + local base = require "resty.core.base" + base.allows_subsystem('http', 'stream') ++require "resty.core.hash" + + + local ffi = require "ffi" +@@ -17,8 +18,10 @@ local error = error + local type = type + local tonumber = tonumber + local max = math.max ++local ngx_crc32_long = ngx.crc32_long + local subsystem = ngx.config.subsystem + local ngx_lua_ffi_balancer_set_current_peer ++local ngx_lua_ffi_balancer_enable_keepalive + local ngx_lua_ffi_balancer_set_more_tries + local ngx_lua_ffi_balancer_get_last_failure + local ngx_lua_ffi_balancer_set_timeouts -- used by both stream and http +@@ -27,7 +30,11 @@ local ngx_lua_ffi_balancer_set_timeouts -- used by both stream and http + if subsystem == 'http' then + ffi.cdef[[ + int ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, +- const unsigned char *addr, size_t addr_len, int port, char **err); ++ const unsigned char *addr, size_t addr_len, int port, ++ unsigned int cpool_crc32, unsigned int cpool_size, char **err); ++ ++ int ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, ++ unsigned long timeout, unsigned int max_requests, char **err); + + int ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + int count, char **err); +@@ -43,6 +50,9 @@ if subsystem == 'http' then + ngx_lua_ffi_balancer_set_current_peer = + C.ngx_http_lua_ffi_balancer_set_current_peer + ++ ngx_lua_ffi_balancer_enable_keepalive = ++ C.ngx_http_lua_ffi_balancer_enable_keepalive ++ + ngx_lua_ffi_balancer_set_more_tries = + C.ngx_http_lua_ffi_balancer_set_more_tries + +@@ -93,6 +103,11 @@ else + end + + ++local DEFAULT_KEEPALIVE_POOL_SIZE = 30 ++local DEFAULT_KEEPALIVE_IDLE_TIMEOUT = 60000 ++local DEFAULT_KEEPALIVE_MAX_REQUESTS = 100 ++ ++ + local peer_state_names = { + [1] = "keepalive", + [2] = "next", +@@ -103,25 +118,147 @@ local peer_state_names = { + local _M = { version = base.version } + + +-function _M.set_current_peer(addr, port) +- local r = get_request() +- if not r then +- error("no request found") ++if subsystem == "http" then ++ function _M.set_current_peer(addr, port, opts) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ local pool_crc32 ++ local pool_size ++ ++ if opts then ++ if type(opts) ~= "table" then ++ error("bad argument #3 to 'set_current_peer' " .. ++ "(table expected, got " .. type(opts) .. ")", 2) ++ end ++ ++ local pool = opts.pool ++ pool_size = opts.pool_size ++ ++ if pool then ++ if type(pool) ~= "string" then ++ error("bad option 'pool' to 'set_current_peer' " .. ++ "(string expected, got " .. type(pool) .. ")", 2) ++ end ++ ++ pool_crc32 = ngx_crc32_long(pool) ++ end ++ ++ if pool_size then ++ if type(pool_size) ~= "number" then ++ error("bad option 'pool_size' to 'set_current_peer' " .. ++ "(number expected, got " .. type(pool_size) .. ")", 2) ++ ++ elseif pool_size < 1 then ++ error("bad option 'pool_size' to 'set_current_peer' " .. ++ "(expected > 0)", 2) ++ end ++ end ++ end ++ ++ if not port then ++ port = 0 ++ ++ elseif type(port) ~= "number" then ++ port = tonumber(port) ++ end ++ ++ if not pool_crc32 then ++ pool_crc32 = 0 ++ end ++ ++ if not pool_size then ++ pool_size = DEFAULT_KEEPALIVE_POOL_SIZE ++ end ++ ++ local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, port, ++ pool_crc32, pool_size, ++ errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end + +- if not port then +- port = 0 +- elseif type(port) ~= "number" then +- port = tonumber(port) ++else ++ function _M.set_current_peer(addr, port, opts) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ if opts then ++ error("bad argument #3 to 'set_current_peer' ('opts' not yet " .. ++ "implemented in " .. subsystem .. " subsystem)", 2) ++ end ++ ++ if not port then ++ port = 0 ++ ++ elseif type(port) ~= "number" then ++ port = tonumber(port) ++ end ++ ++ local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, ++ port, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end ++end + +- local rc = ngx_lua_ffi_balancer_set_current_peer(r, addr, #addr, +- port, errmsg) +- if rc == FFI_OK then +- return true ++ ++if subsystem == "http" then ++ function _M.enable_keepalive(idle_timeout, max_requests) ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ if not idle_timeout then ++ idle_timeout = DEFAULT_KEEPALIVE_IDLE_TIMEOUT ++ ++ elseif type(idle_timeout) ~= "number" then ++ error("bad argument #1 to 'enable_keepalive' " .. ++ "(number expected, got " .. type(idle_timeout) .. ")", 2) ++ ++ elseif idle_timeout < 0 then ++ error("bad argument #1 to 'enable_keepalive' (expected >= 0)", 2) ++ ++ else ++ idle_timeout = idle_timeout * 1000 ++ end ++ ++ if not max_requests then ++ max_requests = DEFAULT_KEEPALIVE_MAX_REQUESTS ++ ++ elseif type(max_requests) ~= "number" then ++ error("bad argument #2 to 'enable_keepalive' " .. ++ "(number expected, got " .. type(max_requests) .. ")", 2) ++ ++ elseif max_requests < 0 then ++ error("bad argument #2 to 'enable_keepalive' (expected >= 0)", 2) ++ end ++ ++ local rc = ngx_lua_ffi_balancer_enable_keepalive(r, idle_timeout, ++ max_requests, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ return nil, ffi_str(errmsg[0]) + end + +- return nil, ffi_str(errmsg[0]) ++else ++ function _M.enable_keepalive() ++ error("'enable_keepalive' not yet implemented in " .. subsystem .. ++ " subsystem", 2) ++ end + end + + +-- +2.25.2 + diff --git a/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_03-upstream_recreate_request.patch b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_03-upstream_recreate_request.patch new file mode 100644 index 00000000..02f97617 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_03-upstream_recreate_request.patch @@ -0,0 +1,55 @@ +From daf26ee06cb4e276c96ea7e34a192f04d5fa7a22 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 23 Jun 2020 17:40:20 -0700 +Subject: [PATCH 1/2] feature: add the `balancer.recreate_request` function, + which allows user to recreate request buffer in balancer phase. + +This allows certain request parameters, such as headers (including +`Host` header) to be modified between balancer retries. +--- + lua-resty-core-0.1.19/lib/ngx/balancer.lua | 25 ++++++++++++++++++++++ + +diff --git a/lua-resty-core-0.1.19/lib/ngx/balancer.lua b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +index d584639..2bc16e1 100644 +--- a/lua-resty-core-0.1.19/lib/ngx/balancer.lua ++++ b/lua-resty-core-0.1.19/lib/ngx/balancer.lua +@@ -38,6 +38,10 @@ if subsystem == 'http' then + int ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, + long read_timeout, char **err); ++ ++ int ++ ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r, ++ char **err); + ]] + + ngx_lua_ffi_balancer_set_current_peer = +@@ -207,4 +211,25 @@ function _M.set_timeouts(connect_timeout, send_timeout, read_timeout) + end + + ++if subsystem == 'http' then ++ function _M.recreate_request() ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ local rc = C.ngx_http_lua_ffi_balancer_recreate_request(r, errmsg) ++ if rc == FFI_OK then ++ return true ++ end ++ ++ if errmsg[0] ~= nil then ++ return nil, ffi_str(errmsg[0]) ++ end ++ ++ return nil, "failed to recreate the upstream request" ++ end ++end ++ ++ + return _M +-- +2.20.1 + diff --git a/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_04-stream_req_start_time.patch b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_04-stream_req_start_time.patch new file mode 100644 index 00000000..8a4e6619 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/lua-resty-core-0.1.19_04-stream_req_start_time.patch @@ -0,0 +1,183 @@ +From 674ef93db9595694459777d928f0aee7f6822cd1 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Mon, 13 Jul 2020 15:41:10 -0700 +Subject: [PATCH] bugfix: added the missing 'ngx.req.start_time' to the stream + subsystem. + +The `ngx.req.start_time()` API is part of `request.lua` which is was +understandably not loaded for the stream subsystem. There existed no +tests for this API in the stream subsystem, so the removal of its +underlying CFunction resulted in `ngx.req.start_time` being `nil` with +no test cases to realize it. +--- + lib/resty/core.lua | 2 +- + lib/resty/core/request.lua | 48 +++++++++++++++++++++++++++----------- + lib/resty/core/utils.lua | 36 ++++++++++++++-------------- + 3 files changed, 55 insertions(+), 31 deletions(-) + +diff --git a/lua-resty-core-0.1.19/lib/resty/core.lua b/lua-resty-core-0.1.19/lib/resty/core.lua +index 54d9756..be287a9 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core.lua +@@ -12,10 +12,10 @@ require "resty.core.hash" + require "resty.core.uri" + require "resty.core.exit" + require "resty.core.base64" ++require "resty.core.request" + + + if subsystem == 'http' then +- require "resty.core.request" + require "resty.core.response" + require "resty.core.phase" + require "resty.core.ndk" +diff --git a/lua-resty-core-0.1.19/lib/resty/core/request.lua b/lua-resty-core-0.1.19/lib/resty/core/request.lua +index f912bfa..747b8c2 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/request.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/request.lua +@@ -3,10 +3,10 @@ + + local ffi = require 'ffi' + local base = require "resty.core.base" +-base.allows_subsystem("http") + local utils = require "resty.core.utils" + + ++local subsystem = ngx.config.subsystem + local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT + local FFI_DECLINED = base.FFI_DECLINED + local FFI_OK = base.FFI_OK +@@ -34,6 +34,40 @@ local _M = { + } + + ++local ngx_lua_ffi_req_start_time ++ ++ ++if subsystem == "stream" then ++ ffi.cdef[[ ++ double ngx_stream_lua_ffi_req_start_time(ngx_stream_lua_request_t *r); ++ ]] ++ ++ ngx_lua_ffi_req_start_time = C.ngx_stream_lua_ffi_req_start_time ++ ++elseif subsystem == "http" then ++ ffi.cdef[[ ++ double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r); ++ ]] ++ ++ ngx_lua_ffi_req_start_time = C.ngx_http_lua_ffi_req_start_time ++end ++ ++ ++function ngx.req.start_time() ++ local r = get_request() ++ if not r then ++ error("no request found") ++ end ++ ++ return tonumber(ngx_lua_ffi_req_start_time(r)) ++end ++ ++ ++if subsystem == "stream" then ++ return _M ++end ++ ++ + local errmsg = base.get_errmsg_ptr() + local ffi_str_type = ffi.typeof("ngx_http_lua_ffi_str_t*") + local ffi_str_size = ffi.sizeof("ngx_http_lua_ffi_str_t") +@@ -59,8 +93,6 @@ ffi.cdef[[ + int ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, + unsigned char *buf, ngx_http_lua_ffi_table_elt_t *out, int count); + +- double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r); +- + int ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r); + + int ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r, +@@ -222,16 +254,6 @@ function ngx.req.get_uri_args(max_args) + end + + +-function ngx.req.start_time() +- local r = get_request() +- if not r then +- error("no request found") +- end +- +- return tonumber(C.ngx_http_lua_ffi_req_start_time(r)) +-end +- +- + do + local methods = { + [0x0002] = "GET", +diff --git a/lua-resty-core-0.1.19/lib/resty/core/utils.lua b/lua-resty-core-0.1.19/lib/resty/core/utils.lua +index 398d7d5..98a0cac 100644 +--- a/lua-resty-core-0.1.19/lib/resty/core/utils.lua ++++ b/lua-resty-core-0.1.19/lib/resty/core/utils.lua +@@ -3,7 +3,6 @@ + + local ffi = require "ffi" + local base = require "resty.core.base" +-base.allows_subsystem("http") + + + local C = ffi.C +@@ -12,12 +11,7 @@ local ffi_copy = ffi.copy + local byte = string.byte + local str_find = string.find + local get_string_buf = base.get_string_buf +- +- +-ffi.cdef[[ +- void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len, +- const unsigned char find, const unsigned char replace); +-]] ++local subsystem = ngx.config.subsystem + + + local _M = { +@@ -25,19 +19,27 @@ local _M = { + } + + +-function _M.str_replace_char(str, find, replace) +- if not str_find(str, find, nil, true) then +- return str +- end ++if subsystem == "http" then ++ ffi.cdef[[ ++ void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len, ++ const unsigned char find, const unsigned char replace); ++ ]] ++ + +- local len = #str +- local buf = get_string_buf(len) +- ffi_copy(buf, str) ++ function _M.str_replace_char(str, find, replace) ++ if not str_find(str, find, nil, true) then ++ return str ++ end + +- C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), +- byte(replace)) ++ local len = #str ++ local buf = get_string_buf(len) ++ ffi_copy(buf, str) + +- return ffi_str(buf, len) ++ C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), ++ byte(replace)) ++ ++ return ffi_str(buf, len) ++ end + end + + +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.2/lua-resty-websocket-0.07_01-client-mtls.patch b/openresty-patches/patches/1.17.8.2/lua-resty-websocket-0.07_01-client-mtls.patch new file mode 100644 index 00000000..e2e629ed --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/lua-resty-websocket-0.07_01-client-mtls.patch @@ -0,0 +1,64 @@ +diff --git a/lua-resty-websocket-0.07/lib/resty/websocket/client.lua b/lua-resty-websocket-0.07/lib/resty/websocket/client.lua +index 13d4b99..47dc4c2 100644 +--- a/lua-resty-websocket-0.07/lib/resty/websocket/client.lua ++++ b/lua-resty-websocket-0.07/lib/resty/websocket/client.lua +@@ -98,7 +98,7 @@ function _M.connect(self, uri, opts) + path = "/" + end + +- local ssl_verify, proto_header, origin_header, sock_opts = false ++ local ssl_verify, proto_header, origin_header, sock_opts, tls_opts = false + + if opts then + local protos = opts.protocols +@@ -122,11 +122,37 @@ function _M.connect(self, uri, opts) + sock_opts = { pool = pool } + end + ++ local client_cert = opts.client_cert ++ local client_priv_key = opts.client_priv_key ++ ++ if client_cert then ++ assert(client_priv_key, ++ "client_priv_key must be provided with client_cert") ++ ++ tls_opts = { client_cert = client_cert, ++ client_priv_key = client_priv_key, } ++ end ++ + if opts.ssl_verify then + if not ssl_support then + return nil, "ngx_lua 0.9.11+ required for SSL sockets" + end +- ssl_verify = true ++ ++ tls_opts = tls_opts or {} ++ tls_opts.verify = true ++ end ++ ++ if opts.server_name then ++ if not ssl_support then ++ return nil, "ngx_lua 0.9.11+ required for SSL sockets" ++ end ++ ++ tls_opts = tls_opts or {} ++ tls_opts.server_name = opts.server_name ++ ++ elseif host then ++ tls_opts = tls_opts or {} ++ tls_opts.server_name = host + end + end + +@@ -144,9 +170,9 @@ function _M.connect(self, uri, opts) + if not ssl_support then + return nil, "ngx_lua 0.9.11+ required for SSL sockets" + end +- ok, err = sock:sslhandshake(false, host, ssl_verify) ++ ok, err = sock:tlshandshake(tls_opts) + if not ok then +- return nil, "ssl handshake failed: " .. err ++ return nil, "tls handshake failed: " .. err + end + end + diff --git a/openresty-patches/patches/1.17.8.2/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch new file mode 100644 index 00000000..2638aa85 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_01-upstream_client_certificate_and_ssl_verify.patch @@ -0,0 +1,52 @@ +diff --git a/nginx-1.17.8/src/http/ngx_http_upstream.c b/nginx-1.17.8/src/http/ngx_http_upstream.c +index 90710557..539a4db9 100644 +--- a/nginx-1.17.8/src/http/ngx_http_upstream.c ++++ b/nginx-1.17.8/src/http/ngx_http_upstream.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#if (NGX_HTTP_LUA_KONG) ++#include ++#endif + + + #if (NGX_HTTP_CACHE) +@@ -1691,7 +1691,14 @@ + c->sendfile = 0; + u->output.sendfile = 0; + ++ ++#if (NGX_HTTP_LUA_KONG) ++ if (u->conf->ssl_server_name ++ || ngx_http_lua_kong_get_upstream_ssl_verify(r, u->conf->ssl_verify)) ++ { ++#else + if (u->conf->ssl_server_name || u->conf->ssl_verify) { ++#endif + if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); +@@ -1719,6 +1722,10 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, + } + } + ++#if (NGX_HTTP_LUA_KONG) ++ ngx_http_lua_kong_set_upstream_ssl(r, c); ++#endif ++ + r->connection->log->action = "SSL handshaking to upstream"; + + rc = ngx_ssl_handshake(c); +@@ -1768,7 +1768,11 @@ + + if (c->ssl->handshaked) { + ++#if (NGX_HTTP_LUA_KONG) ++ if (ngx_http_lua_kong_get_upstream_ssl_verify(r, u->conf->ssl_verify)) { ++#else + if (u->conf->ssl_verify) { ++#endif + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { diff --git a/openresty-patches/patches/1.17.8.2/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch new file mode 100644 index 00000000..c6a8690d --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_02-remove-server-tokens-from-special-responses-output.patch @@ -0,0 +1,38 @@ +From 66f96c49ec4a222c4061e18aa8c3f8655b52327d Mon Sep 17 00:00:00 2001 +From: Aapo Talvensaari +Date: Fri, 16 Aug 2019 13:41:49 +0300 +Subject: [PATCH] remove server tokens from special responses output + +--- + nginx-1.17.8/src/http/ngx_http_special_response.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/nginx-1.17.8/src/http/ngx_http_special_response.c b/nginx-1.17.8/src/http/ngx_http_special_response.c +index 4b8bbf5..524cc7b 100644 +--- a/nginx-1.17.8/src/http/ngx_http_special_response.c ++++ b/nginx-1.17.8/src/http/ngx_http_special_response.c +@@ -19,21 +19,18 @@ static ngx_int_t ngx_http_send_refresh(ngx_http_request_t *r); + + + static u_char ngx_http_error_full_tail[] = +-"
" NGINX_VER "
" CRLF + "" CRLF + "" CRLF + ; + + + static u_char ngx_http_error_build_tail[] = +-"
" NGINX_VER_BUILD "
" CRLF + "" CRLF + "" CRLF + ; + + + static u_char ngx_http_error_tail[] = +-"
openresty
" CRLF + "" CRLF + "" CRLF + ; +-- +2.22.0 + diff --git a/openresty-patches/patches/1.17.8.2/nginx-1.17.8_03-stream_proxy_ssl_disable.patch b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_03-stream_proxy_ssl_disable.patch new file mode 100644 index 00000000..817296d0 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/nginx-1.17.8_03-stream_proxy_ssl_disable.patch @@ -0,0 +1,33 @@ +diff --git a/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c b/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c +index 09493135..fc8f8479 100644 +--- a/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c ++++ b/nginx-1.17.8/src/stream/ngx_stream_proxy_module.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#if (NGX_STREAM_LUA_KONG) ++#include ++#endif + + + typedef struct { +@@ -799,8 +802,18 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) + + #if (NGX_STREAM_SSL) + ++#if (NGX_STREAM_LUA_KONG) ++ ++ if (pc->type == SOCK_STREAM && pscf->ssl ++ && !ngx_stream_lua_kong_get_proxy_ssl_disable(s)) ++ { ++ ++#else ++ + if (pc->type == SOCK_STREAM && pscf->ssl) { + ++#endif ++ + if (u->proxy_protocol) { + if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { + return; diff --git a/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_01-cosocket-mtls.patch b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_01-cosocket-mtls.patch new file mode 100644 index 00000000..9aa58ba7 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_01-cosocket-mtls.patch @@ -0,0 +1,970 @@ +From 9bec4f8703054c91534570d6985e3a83843c8ac5 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:39:05 -0700 +Subject: [PATCH 1/5] cosocket: add function `tcpsock:tlshandshake`, retired + the Lua C API based `tcpsock:sslhandshake` implementation. + +--- + src/ngx_http_lua_socket_tcp.c | 387 +++++++++++++++------------------- + src/ngx_http_lua_socket_tcp.h | 3 + + 2 files changed, 177 insertions(+), 213 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 30a4e7b2..2551b5a7 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -23,6 +23,9 @@ static int ngx_http_lua_socket_tcp(lua_State *L); + static int ngx_http_lua_socket_tcp_connect(lua_State *L); + #if (NGX_HTTP_SSL) + static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L); ++static void ngx_http_lua_tls_handshake_handler(ngx_connection_t *c); ++static int ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); + #endif + static int ngx_http_lua_socket_tcp_receive(lua_State *L); + static int ngx_http_lua_socket_tcp_receiveany(lua_State *L); +@@ -152,12 +155,6 @@ static void + ngx_http_lua_socket_empty_resolve_handler(ngx_resolver_ctx_t *ctx); + static int ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L, ngx_uint_t ft_type); +-#if (NGX_HTTP_SSL) +-static int ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, +- ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); +-static void ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c); +-static int ngx_http_lua_ssl_free_session(lua_State *L); +-#endif + static void ngx_http_lua_socket_tcp_close_connection(ngx_connection_t *c); + + +@@ -309,13 +306,6 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) + lua_pushcfunction(L, ngx_http_lua_socket_tcp_connect); + lua_setfield(L, -2, "connect"); + +-#if (NGX_HTTP_SSL) +- +- lua_pushcfunction(L, ngx_http_lua_socket_tcp_sslhandshake); +- lua_setfield(L, -2, "sslhandshake"); +- +-#endif +- + lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); + lua_setfield(L, -2, "receive"); + +@@ -386,19 +376,6 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) + lua_setfield(L, -2, "__gc"); + lua_rawset(L, LUA_REGISTRYINDEX); + /* }}} */ +- +-#if (NGX_HTTP_SSL) +- +- /* {{{ssl session userdata metatable */ +- lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( +- ssl_session_metatable_key)); +- lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ +- lua_pushcfunction(L, ngx_http_lua_ssl_free_session); +- lua_setfield(L, -2, "__gc"); +- lua_rawset(L, LUA_REGISTRYINDEX); +- /* }}} */ +- +-#endif + } + + +@@ -1531,64 +1508,69 @@ ngx_http_lua_socket_conn_error_retval_handler(ngx_http_request_t *r, + + #if (NGX_HTTP_SSL) + +-static int +-ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) ++static const char * ++ngx_http_lua_socket_tcp_check_busy(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, unsigned int ops) + { +- int n, top; +- ngx_int_t rc; +- ngx_str_t name = ngx_null_string; +- ngx_connection_t *c; +- ngx_ssl_session_t **psession; +- ngx_http_request_t *r; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_co_ctx_t *coctx; +- +- ngx_http_lua_socket_tcp_upstream_t *u; +- +- /* Lua function arguments: self [,session] [,host] [,verify] +- [,send_status_req] */ ++ if (ops & SOCKET_OP_CONNECT && u->conn_waiting) { ++ return "socket busy connecting"; ++ } + +- n = lua_gettop(L); +- if (n < 1 || n > 5) { +- return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 5 " +- "arguments (including the object), but seen %d", n); ++ if (ops & SOCKET_OP_READ && u->read_waiting) { ++ return "socket busy reading"; + } + +- r = ngx_http_lua_get_req(L); +- if (r == NULL) { +- return luaL_error(L, "no request found"); ++ if (ops & SOCKET_OP_WRITE ++ && (u->write_waiting ++ || (u->raw_downstream ++ && (r->connection->buffered & NGX_HTTP_LOWLEVEL_BUFFERED)))) ++ { ++ return "socket busy writing"; + } + +- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "lua tcp socket ssl handshake"); ++ return NULL; ++} + +- luaL_checktype(L, 1, LUA_TTABLE); ++int ++ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, ++ int enable_session_reuse, ngx_str_t *server_name, int verify, ++ int ocsp_status_req, const char **errmsg) ++{ ++ ngx_int_t rc; ++ ngx_connection_t *c; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_co_ctx_t *coctx; ++ const char *busy_rc; + +- lua_rawgeti(L, 1, SOCKET_CTX_INDEX); +- u = lua_touserdata(L, -1); ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua tcp socket tls handshake"); + + if (u == NULL + || u->peer.connection == NULL + || u->read_closed + || u->write_closed) + { +- lua_pushnil(L); +- lua_pushliteral(L, "closed"); +- return 2; ++ *errmsg = "closed"; ++ return NGX_ERROR; + } + + if (u->request != r) { +- return luaL_error(L, "bad request"); ++ *errmsg = "bad request"; ++ return NGX_ERROR; + } + +- ngx_http_lua_socket_check_busy_connecting(r, u, L); +- ngx_http_lua_socket_check_busy_reading(r, u, L); +- ngx_http_lua_socket_check_busy_writing(r, u, L); ++ busy_rc = ngx_http_lua_socket_tcp_check_busy(r, u, SOCKET_OP_CONNECT ++ | SOCKET_OP_READ ++ | SOCKET_OP_WRITE); ++ if (busy_rc != NULL) { ++ *errmsg = busy_rc; ++ return NGX_ERROR; ++ } + + if (u->raw_downstream || u->body_downstream) { +- lua_pushnil(L); +- lua_pushliteral(L, "not supported for downstream"); +- return 2; ++ *errmsg = "not supported for downstream"; ++ return NGX_ERROR; + } + + c = u->peer.connection; +@@ -1596,122 +1578,96 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) + u->ssl_session_reuse = 1; + + if (c->ssl && c->ssl->handshaked) { +- switch (lua_type(L, 2)) { +- case LUA_TUSERDATA: +- lua_pushvalue(L, 2); +- break; ++ if (sess != NULL) { ++ return NGX_DONE; ++ } + +- case LUA_TBOOLEAN: +- if (!lua_toboolean(L, 2)) { +- /* avoid generating the ssl session */ +- lua_pushboolean(L, 1); +- break; +- } +- /* fall through */ ++ u->ssl_session_reuse = enable_session_reuse; + +- default: +- ngx_http_lua_ssl_handshake_retval_handler(r, u, L); +- break; +- } ++ (void) ngx_http_lua_tls_handshake_retval_handler(r, u, NULL); + +- return 1; ++ return NGX_OK; + } + + if (ngx_ssl_create_connection(u->conf->ssl, c, + NGX_SSL_BUFFER|NGX_SSL_CLIENT) + != NGX_OK) + { +- lua_pushnil(L); +- lua_pushliteral(L, "failed to create ssl connection"); +- return 2; ++ *errmsg = "failed to create ssl connection"; ++ return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { +- return luaL_error(L, "no ctx found"); ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "no ngx_lua ctx found while TLS handshaking"); ++ ++ ngx_http_lua_assert(NULL); ++ ++ *errmsg = "no ctx found"; ++ return NGX_ERROR; + } + + coctx = ctx->cur_co_ctx; + + c->sendfile = 0; + +- if (n >= 2) { +- if (lua_type(L, 2) == LUA_TBOOLEAN) { +- u->ssl_session_reuse = lua_toboolean(L, 2); +- +- } else { +- psession = lua_touserdata(L, 2); +- +- if (psession != NULL && *psession != NULL) { +- if (ngx_ssl_set_session(c, *psession) != NGX_OK) { +- lua_pushnil(L); +- lua_pushliteral(L, "lua ssl set session failed"); +- return 2; +- } +- +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua ssl set session: %p", *psession); +- } ++ if (sess != NULL) { ++ if (ngx_ssl_set_session(c, sess) != NGX_OK) { ++ *errmsg = "lua tls set session failed"; ++ return NGX_ERROR; + } + +- if (n >= 3) { +- name.data = (u_char *) lua_tolstring(L, 3, &name.len); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "lua tls set session: %p", sess); + +- if (name.data) { +- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "lua ssl server name: \"%*s\"", name.len, +- name.data); ++ } else { ++ u->ssl_session_reuse = enable_session_reuse; ++ } + +-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ++ if (server_name != NULL && server_name->data != NULL) { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua tls server name: \"%V\"", server_name); + +- if (SSL_set_tlsext_host_name(c->ssl->connection, +- (char *) name.data) +- == 0) +- { +- lua_pushnil(L); +- lua_pushliteral(L, "SSL_set_tlsext_host_name failed"); +- return 2; +- } ++#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ++ if (SSL_set_tlsext_host_name(c->ssl->connection, ++ (char *) server_name->data) ++ == 0) ++ { ++ *errmsg = "SSL_set_tlsext_host_name failed"; ++ return NGX_ERROR; ++ } + + #else +- +- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua socket SNI disabled because the current " +- "version of OpenSSL lacks the support"); +- ++ *errmsg = "OpenSSL has no SNI support"; ++ return NGX_ERROR; + #endif +- } ++ } + +- if (n >= 4) { +- u->ssl_verify = lua_toboolean(L, 4); ++ u->ssl_verify = verify; + +- if (n >= 5) { +- if (lua_toboolean(L, 5)) { ++ if (ocsp_status_req) { + #ifdef NGX_HTTP_LUA_USE_OCSP +- SSL_set_tlsext_status_type(c->ssl->connection, +- TLSEXT_STATUSTYPE_ocsp); ++ SSL_set_tlsext_status_type(c->ssl->connection, ++ TLSEXT_STATUSTYPE_ocsp); ++ + #else +- return luaL_error(L, "no OCSP support"); ++ *errmsg = "no OCSP support"; ++ return NGX_ERROR; + #endif +- } +- } +- } +- } + } + +- dd("found sni name: %.*s %p", (int) name.len, name.data, name.data); +- +- if (name.len == 0) { ++ if (server_name->len == 0) { + u->ssl_name.len = 0; + + } else { + if (u->ssl_name.data) { + /* buffer already allocated */ + +- if (u->ssl_name.len >= name.len) { ++ if (u->ssl_name.len >= server_name->len) { + /* reuse it */ +- ngx_memcpy(u->ssl_name.data, name.data, name.len); +- u->ssl_name.len = name.len; ++ ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ u->ssl_name.len = server_name->len; + + } else { + ngx_free(u->ssl_name.data); +@@ -1722,17 +1678,16 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) + + new_ssl_name: + +- u->ssl_name.data = ngx_alloc(name.len, ngx_cycle->log); ++ u->ssl_name.data = ngx_alloc(server_name->len, ngx_cycle->log); + if (u->ssl_name.data == NULL) { + u->ssl_name.len = 0; + +- lua_pushnil(L); +- lua_pushliteral(L, "no memory"); +- return 2; ++ *errmsg = "no memory"; ++ return NGX_ERROR; + } + +- ngx_memcpy(u->ssl_name.data, name.data, name.len); +- u->ssl_name.len = name.len; ++ ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ u->ssl_name.len = server_name->len; + } + } + +@@ -1746,7 +1701,8 @@ new_ssl_name: + + rc = ngx_ssl_handshake(c); + +- dd("ngx_ssl_handshake returned %d", (int) rc); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "ngx_ssl_handshake returned %d", rc); + + if (rc == NGX_AGAIN) { + if (c->write->timer_set) { +@@ -1756,13 +1712,13 @@ new_ssl_name: + ngx_add_timer(c->read, u->connect_timeout); + + u->conn_waiting = 1; +- u->write_prepare_retvals = ngx_http_lua_ssl_handshake_retval_handler; ++ u->write_prepare_retvals = ngx_http_lua_tls_handshake_retval_handler; + + ngx_http_lua_cleanup_pending_operation(coctx); + coctx->cleanup = ngx_http_lua_coctx_cleanup; + coctx->data = u; + +- c->ssl->handler = ngx_http_lua_ssl_handshake_handler; ++ c->ssl->handler = ngx_http_lua_tls_handshake_handler; + + if (ctx->entered_content_phase) { + r->write_event_handler = ngx_http_lua_content_wev_handler; +@@ -1771,21 +1727,25 @@ new_ssl_name: + r->write_event_handler = ngx_http_core_run_phases; + } + +- return lua_yield(L, 0); ++ return NGX_AGAIN; ++ } ++ ++ ngx_http_lua_tls_handshake_handler(c); ++ ++ if (rc == NGX_ERROR) { ++ *errmsg = u->error_ret; ++ ++ return NGX_ERROR; + } + +- top = lua_gettop(L); +- ngx_http_lua_ssl_handshake_handler(c); +- return lua_gettop(L) - top; ++ return NGX_OK; + } + + + static void +-ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) ++ngx_http_lua_tls_handshake_handler(ngx_connection_t *c) + { +- const char *err; + int waiting; +- lua_State *L; + ngx_int_t rc; + ngx_connection_t *dc; /* downstream connection */ + ngx_http_request_t *r; +@@ -1808,11 +1768,9 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + waiting = u->conn_waiting; + + dc = r->connection; +- L = u->write_co_ctx->co; + + if (c->read->timedout) { +- lua_pushnil(L); +- lua_pushliteral(L, "timeout"); ++ u->error_ret = "timeout"; + goto failed; + } + +@@ -1821,19 +1779,18 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + } + + if (c->ssl->handshaked) { +- + if (u->ssl_verify) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { +- lua_pushnil(L); +- err = lua_pushfstring(L, "%d: %s", (int) rc, +- X509_verify_cert_error_string(rc)); ++ u->error_ret = X509_verify_cert_error_string(rc); ++ u->openssl_error_code_ret = rc; + + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + if (llcf->log_socket_errors) { +- ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua ssl " +- "certificate verify error: (%s)", err); ++ ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua tls " ++ "certificate verify error: (%d: %s)", ++ rc, u->error_ret); + } + + goto failed; +@@ -1844,12 +1801,11 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + if (u->ssl_name.len + && ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) + { +- lua_pushnil(L); +- lua_pushliteral(L, "certificate host mismatch"); ++ u->error_ret = "certificate host mismatch"; + + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + if (llcf->log_socket_errors) { +- ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua ssl " ++ ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua tls " + "certificate does not match host \"%V\"", + &u->ssl_name); + } +@@ -1864,7 +1820,7 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + ngx_http_lua_socket_handle_conn_success(r, u); + + } else { +- (void) ngx_http_lua_ssl_handshake_retval_handler(r, u, L); ++ (void) ngx_http_lua_tls_handshake_retval_handler(r, u, NULL); + } + + if (waiting) { +@@ -1874,60 +1830,84 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c) + return; + } + +- lua_pushnil(L); +- lua_pushliteral(L, "handshake failed"); ++ u->error_ret = "handshake failed"; + + failed: + + if (waiting) { + u->write_prepare_retvals = +- ngx_http_lua_socket_conn_error_retval_handler; +- ngx_http_lua_socket_handle_conn_error(r, u, +- NGX_HTTP_LUA_SOCKET_FT_SSL); ++ ngx_http_lua_socket_conn_error_retval_handler; ++ ngx_http_lua_socket_handle_conn_error(r, u, NGX_HTTP_LUA_SOCKET_FT_SSL); + ngx_http_run_posted_requests(dc); + + } else { +- (void) ngx_http_lua_socket_conn_error_retval_handler(r, u, L); ++ u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_SSL; ++ ++ (void) ngx_http_lua_socket_conn_error_retval_handler(r, u, NULL); + } + } + + ++ ++int ++ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, ++ ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, ++ const char **errmsg, int *openssl_error_code) ++{ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "lua cosocket get TLS handshake result for upstream: %p", u); ++ ++ if (u->error_ret != NULL) { ++ *errmsg = u->error_ret; ++ *openssl_error_code = u->openssl_error_code_ret; ++ ++ return NGX_ERROR; ++ } ++ ++ *sess = u->ssl_session_ret; ++ ++ return NGX_OK; ++} ++ ++ + static int +-ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, ++ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L) + { + ngx_connection_t *c; +- ngx_ssl_session_t *ssl_session, **ud; ++ ngx_ssl_session_t *ssl_session; + + if (!u->ssl_session_reuse) { +- lua_pushboolean(L, 1); +- return 1; ++ return 0; + } + +- ud = lua_newuserdata(L, sizeof(ngx_ssl_session_t *)); +- + c = u->peer.connection; + + ssl_session = ngx_ssl_get_session(c); + if (ssl_session == NULL) { +- *ud = NULL; ++ u->ssl_session_ret = NULL; + + } else { +- *ud = ssl_session; ++ u->ssl_session_ret = ssl_session; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, +- "lua ssl save session: %p", ssl_session); +- +- /* set up the __gc metamethod */ +- lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( +- ssl_session_metatable_key)); +- lua_rawget(L, LUA_REGISTRYINDEX); +- lua_setmetatable(L, -2); ++ "lua tls save session: %p", ssl_session); + } + +- return 1; ++ return 0; + } + ++ ++void ++ngx_http_lua_ffi_tls_free_session(ngx_ssl_session_t *sess) ++{ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, ++ "lua tls free session: %p", sess); ++ ++ ngx_ssl_free_session(sess); ++} ++ ++ + #endif /* NGX_HTTP_SSL */ + + +@@ -1980,12 +1960,14 @@ ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r, + u_char errstr[NGX_MAX_ERROR_STR]; + u_char *p; + +- if (ft_type & (NGX_HTTP_LUA_SOCKET_FT_RESOLVER +- | NGX_HTTP_LUA_SOCKET_FT_SSL)) +- { ++ if (ft_type & NGX_HTTP_LUA_SOCKET_FT_RESOLVER) { + return 2; + } + ++ if (ft_type & NGX_HTTP_LUA_SOCKET_FT_SSL) { ++ return 0; ++ } ++ + lua_pushnil(L); + + if (ft_type & NGX_HTTP_LUA_SOCKET_FT_TIMEOUT) { +@@ -6058,27 +6040,6 @@ ngx_http_lua_coctx_cleanup(void *data) + } + + +-#if (NGX_HTTP_SSL) +- +-static int +-ngx_http_lua_ssl_free_session(lua_State *L) +-{ +- ngx_ssl_session_t **psession; +- +- psession = lua_touserdata(L, 1); +- if (psession && *psession != NULL) { +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, +- "lua ssl free session: %p", *psession); +- +- ngx_ssl_free_session(*psession); +- } +- +- return 0; +-} +- +-#endif /* NGX_HTTP_SSL */ +- +- + void + ngx_http_lua_cleanup_conn_pools(lua_State *L) + { +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h +index 091e4378..bb618702 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.h +@@ -114,6 +114,9 @@ struct ngx_http_lua_socket_tcp_upstream_s { + + #if (NGX_HTTP_SSL) + ngx_str_t ssl_name; ++ ngx_ssl_session_t *ssl_session_ret; ++ const char *error_ret; ++ int openssl_error_code_ret; + #endif + + unsigned ft_type:16; +-- +2.26.2 + + +From 958140f6113bc4ac33f0880682097f52682d0b81 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 16:54:32 -0700 +Subject: [PATCH 2/5] change: better error when request context couldn't be + found. + +--- + src/ngx_http_lua_socket_tcp.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 2551b5a7..8ae931bd 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1599,13 +1599,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { +- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, +- "no ngx_lua ctx found while TLS handshaking"); +- +- ngx_http_lua_assert(NULL); +- +- *errmsg = "no ctx found"; +- return NGX_ERROR; ++ return NGX_HTTP_LUA_FFI_NO_REQ_CTX; + } + + coctx = ctx->cur_co_ctx; +-- +2.26.2 + + +From 10bfa00f44a474d0c7667517d98243732c447612 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:24:07 -0700 +Subject: [PATCH 3/5] feature: TCP cosocket client certificate support. closes + #534 + +--- + src/ngx_http_lua_socket_tcp.c | 60 +++++++++++++++++++++++++++++++---- + 1 file changed, 54 insertions(+), 6 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index 8ae931bd..f49e609c 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -22,7 +22,6 @@ + static int ngx_http_lua_socket_tcp(lua_State *L); + static int ngx_http_lua_socket_tcp_connect(lua_State *L); + #if (NGX_HTTP_SSL) +-static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L); + static void ngx_http_lua_tls_handshake_handler(ngx_connection_t *c); + static int ngx_http_lua_tls_handshake_retval_handler(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); +@@ -213,9 +212,6 @@ static char ngx_http_lua_upstream_udata_metatable_key; + static char ngx_http_lua_downstream_udata_metatable_key; + static char ngx_http_lua_pool_udata_metatable_key; + static char ngx_http_lua_pattern_udata_metatable_key; +-#if (NGX_HTTP_SSL) +-static char ngx_http_lua_ssl_session_metatable_key; +-#endif + + + void +@@ -1535,13 +1531,16 @@ int + ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, + int enable_session_reuse, ngx_str_t *server_name, int verify, +- int ocsp_status_req, const char **errmsg) ++ int ocsp_status_req, STACK_OF(X509) *chain, EVP_PKEY *pkey, ++ const char **errmsg) + { +- ngx_int_t rc; ++ ngx_int_t rc, i; + ngx_connection_t *c; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_co_ctx_t *coctx; + const char *busy_rc; ++ ngx_ssl_conn_t *ssl_conn; ++ X509 *x509; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua tcp socket tls handshake"); +@@ -1597,6 +1596,8 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ ssl_conn = c->ssl->connection; ++ + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return NGX_HTTP_LUA_FFI_NO_REQ_CTX; +@@ -1619,6 +1620,53 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + u->ssl_session_reuse = enable_session_reuse; + } + ++ if (chain != NULL) { ++ ngx_http_lua_assert(pkey != NULL); /* ensured by resty.core */ ++ ++ if (sk_X509_num(chain) < 1) { ++ ERR_clear_error(); ++ *errmsg = "invalid client certificate chain"; ++ return NGX_ERROR; ++ } ++ ++ x509 = sk_X509_value(chain, 0); ++ if (x509 == NULL) { ++ ERR_clear_error(); ++ *errmsg = "lua tls fetch client certificate from chain failed"; ++ return NGX_ERROR; ++ } ++ ++ if (SSL_use_certificate(ssl_conn, x509) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua tls set client certificate failed"; ++ return NGX_ERROR; ++ } ++ ++ /* read rest of the chain */ ++ ++ for (i = 1; i < sk_X509_num(chain); i++) { ++ x509 = sk_X509_value(chain, i); ++ if (x509 == NULL) { ++ ERR_clear_error(); ++ *errmsg = "lua tls fetch client intermediate certificate " ++ "from chain failed"; ++ return NGX_ERROR; ++ } ++ ++ if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua tls set client intermediate certificate failed"; ++ return NGX_ERROR; ++ } ++ } ++ ++ if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { ++ ERR_clear_error(); ++ *errmsg = "lua ssl set client private key failed"; ++ return NGX_ERROR; ++ } ++ } ++ + if (server_name != NULL && server_name->data != NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua tls server name: \"%V\"", server_name); +-- +2.26.2 + + +From 87e157b594987a63d797fd74907c00c3ed69dc19 Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Wed, 18 Sep 2019 17:25:20 -0700 +Subject: [PATCH 4/5] style: style fixes. + +--- + src/ngx_http_lua_socket_tcp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index f49e609c..ce8132d3 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1708,7 +1708,8 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + if (u->ssl_name.len >= server_name->len) { + /* reuse it */ +- ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len); ++ ngx_memcpy(u->ssl_name.data, server_name->data, ++ server_name->len); + u->ssl_name.len = server_name->len; + + } else { +-- +2.26.2 + + +From f1d1b6352eb6d386593263e80ba3eab0ba710f59 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Mon, 6 Jan 2020 17:56:10 -0800 +Subject: [PATCH 5/5] cleanup + +--- + src/ngx_http_lua_socket_tcp.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +index ce8132d3..c4d8d269 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_socket_tcp.c +@@ -1527,6 +1527,7 @@ ngx_http_lua_socket_tcp_check_busy(ngx_http_request_t *r, + return NULL; + } + ++ + int + ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess, +@@ -1568,7 +1569,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + } + + if (u->raw_downstream || u->body_downstream) { +- *errmsg = "not supported for downstream"; ++ *errmsg = "not supported for downstream sockets"; + return NGX_ERROR; + } + +@@ -1609,7 +1610,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + + if (sess != NULL) { + if (ngx_ssl_set_session(c, sess) != NGX_OK) { +- *errmsg = "lua tls set session failed"; ++ *errmsg = "tls set session failed"; + return NGX_ERROR; + } + +@@ -1632,13 +1633,13 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + x509 = sk_X509_value(chain, 0); + if (x509 == NULL) { + ERR_clear_error(); +- *errmsg = "lua tls fetch client certificate from chain failed"; ++ *errmsg = "tls fetch client certificate from chain failed"; + return NGX_ERROR; + } + + if (SSL_use_certificate(ssl_conn, x509) == 0) { + ERR_clear_error(); +- *errmsg = "lua tls set client certificate failed"; ++ *errmsg = "tls set client certificate failed"; + return NGX_ERROR; + } + +@@ -1648,21 +1649,21 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + x509 = sk_X509_value(chain, i); + if (x509 == NULL) { + ERR_clear_error(); +- *errmsg = "lua tls fetch client intermediate certificate " +- "from chain failed"; ++ *errmsg = "tls fetch client intermediate certificate from " ++ "chain failed"; + return NGX_ERROR; + } + + if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { + ERR_clear_error(); +- *errmsg = "lua tls set client intermediate certificate failed"; ++ *errmsg = "tls set client intermediate certificate failed"; + return NGX_ERROR; + } + } + + if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { + ERR_clear_error(); +- *errmsg = "lua ssl set client private key failed"; ++ *errmsg = "tls set client private key failed"; + return NGX_ERROR; + } + } +@@ -1681,7 +1682,7 @@ ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r, + } + + #else +- *errmsg = "OpenSSL has no SNI support"; ++ *errmsg = "no TLS extension support"; + return NGX_ERROR; + #endif + } +@@ -1724,7 +1725,6 @@ new_ssl_name: + u->ssl_name.data = ngx_alloc(server_name->len, ngx_cycle->log); + if (u->ssl_name.data == NULL) { + u->ssl_name.len = 0; +- + *errmsg = "no memory"; + return NGX_ERROR; + } +@@ -1745,7 +1745,7 @@ new_ssl_name: + rc = ngx_ssl_handshake(c); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "ngx_ssl_handshake returned %d", rc); ++ "ngx_ssl_handshake returned: %d", rc); + + if (rc == NGX_AGAIN) { + if (c->write->timer_set) { +@@ -1777,7 +1777,6 @@ new_ssl_name: + + if (rc == NGX_ERROR) { + *errmsg = u->error_ret; +- + return NGX_ERROR; + } + +@@ -1891,7 +1890,6 @@ failed: + } + + +- + int + ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess, +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch new file mode 100644 index 00000000..165a9ab9 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_02-dyn_upstream_keepalive.patch @@ -0,0 +1,1320 @@ +From 2d12ac3e4045258b7a174b0505d92f63c26d82fc Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:44 -0700 +Subject: [PATCH 1/3] feature: implemented keepalive pooling in + 'balancer_by_lua*'. + +--- + src/ngx_http_lua_balancer.c | 738 ++++++++++++++++++++++++++++++------ + src/ngx_http_lua_common.h | 4 + + src/ngx_http_lua_module.c | 3 + + 3 files changed, 629 insertions(+), 116 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index f71a3e00..0d403716 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -16,46 +16,102 @@ + #include "ngx_http_lua_directive.h" + + ++typedef struct { ++ ngx_uint_t size; ++ ngx_uint_t connections; ++ ++ uint32_t crc32; ++ ++ lua_State *lua_vm; ++ ++ ngx_queue_t cache; ++ ngx_queue_t free; ++} ngx_http_lua_balancer_keepalive_pool_t; ++ ++ ++typedef struct { ++ ngx_queue_t queue; ++ ngx_connection_t *connection; ++ ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++} ngx_http_lua_balancer_keepalive_item_t; ++ ++ + struct ngx_http_lua_balancer_peer_data_s { +- /* the round robin data must be first */ +- ngx_http_upstream_rr_peer_data_t rrp; ++ ngx_uint_t cpool_size; ++ ngx_uint_t keepalive_requests; ++ ngx_msec_t keepalive_timeout; ++ ++ ngx_uint_t more_tries; ++ ngx_uint_t total_tries; + +- ngx_http_lua_srv_conf_t *conf; +- ngx_http_request_t *request; ++ int last_peer_state; + +- ngx_uint_t more_tries; +- ngx_uint_t total_tries; ++ uint32_t cpool_crc32; + +- struct sockaddr *sockaddr; +- socklen_t socklen; ++ void *data; + +- ngx_str_t *host; +- in_port_t port; ++ ngx_event_get_peer_pt original_get_peer; ++ ngx_event_free_peer_pt original_free_peer; + +- int last_peer_state; ++#if (NGX_HTTP_SSL) ++ ngx_event_set_peer_session_pt original_set_session; ++ ngx_event_save_peer_session_pt original_save_session; ++#endif ++ ++ ngx_http_request_t *request; ++ ngx_http_lua_srv_conf_t *conf; ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++ ++ ngx_str_t *host; ++ ++ struct sockaddr *sockaddr; ++ socklen_t socklen; ++ ++ unsigned keepalive:1; + + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) +- unsigned cloned_upstream_conf; /* :1 */ ++ unsigned cloned_upstream_conf:1; + #endif + }; + + +-#if (NGX_HTTP_SSL) +-static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, +- void *data); +-static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, +- void *data); +-#endif ++static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, ++ ngx_http_request_t *r); + static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us); + static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); + static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, + void *data); +-static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, +- ngx_http_request_t *r); + static void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, + void *data, ngx_uint_t state); ++static ngx_int_t ngx_http_lua_balancer_create_keepalive_pool(lua_State *L, ++ ngx_log_t *log, uint32_t cpool_crc32, ngx_uint_t cpool_size, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool); ++static void ngx_http_lua_balancer_get_keepalive_pool(lua_State *L, ++ uint32_t cpool_crc32, ngx_http_lua_balancer_keepalive_pool_t **cpool); ++static void ngx_http_lua_balancer_free_keepalive_pool(ngx_log_t *log, ++ ngx_http_lua_balancer_keepalive_pool_t *cpool); ++static void ngx_http_lua_balancer_close(ngx_connection_t *c); ++static void ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev); ++static void ngx_http_lua_balancer_close_handler(ngx_event_t *ev); ++#if (NGX_HTTP_SSL) ++static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, ++ void *data); ++static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, ++ void *data); ++#endif ++ ++ ++#define ngx_http_lua_balancer_keepalive_is_enabled(bp) \ ++ (bp->keepalive) ++ ++#define ngx_http_lua_balancer_peer_set(bp) \ ++ (bp->sockaddr && bp->socklen) ++ ++ ++static char ngx_http_lua_balancer_keepalive_pools_table_key; + + + ngx_int_t +@@ -102,6 +158,61 @@ ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r, + } + + ++static ngx_int_t ++ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) ++{ ++ u_char *err_msg; ++ size_t len; ++ ngx_int_t rc; ++ ++ /* init nginx context in Lua VM */ ++ ngx_http_lua_set_req(L, r); ++ ++#ifndef OPENRESTY_LUAJIT ++ ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); ++ ++ /* {{{ make new env inheriting main thread's globals table */ ++ lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ ++ ngx_http_lua_get_globals_table(L); ++ lua_setfield(L, -2, "__index"); ++ lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ ++ /* }}} */ ++ ++ lua_setfenv(L, -2); /* set new running env for the code closure */ ++#endif /* OPENRESTY_LUAJIT */ ++ ++ lua_pushcfunction(L, ngx_http_lua_traceback); ++ lua_insert(L, 1); /* put it under chunk and args */ ++ ++ /* protected call user code */ ++ rc = lua_pcall(L, 0, 1, 1); ++ ++ lua_remove(L, 1); /* remove traceback function */ ++ ++ dd("rc == %d", (int) rc); ++ ++ if (rc != 0) { ++ /* error occurred when running loaded code */ ++ err_msg = (u_char *) lua_tolstring(L, -1, &len); ++ ++ if (err_msg == NULL) { ++ err_msg = (u_char *) "unknown reason"; ++ len = sizeof("unknown reason") - 1; ++ } ++ ++ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ++ "failed to run balancer_by_lua*: %*s", len, err_msg); ++ ++ lua_settop(L, 0); /* clear remaining elems on stack */ ++ ++ return NGX_ERROR; ++ } ++ ++ lua_settop(L, 0); /* clear remaining elems on stack */ ++ return rc; ++} ++ ++ + char * + ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +@@ -125,16 +236,16 @@ char * + ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) + { +- u_char *cache_key = NULL; +- u_char *name; +- ngx_str_t *value; +- ngx_http_lua_srv_conf_t *lscf = conf; +- ++ u_char *cache_key = NULL; ++ u_char *name; ++ ngx_str_t *value; + ngx_http_upstream_srv_conf_t *uscf; ++ ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); + +- /* must specify a content handler */ ++ /* content handler setup */ ++ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } +@@ -178,11 +289,19 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + lscf->balancer.src_key = cache_key; + ++ /* balancer setup */ ++ + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + + if (uscf->peer.init_upstream) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "load balancing method redefined"); ++ ++ lscf->balancer.original_init_upstream = uscf->peer.init_upstream; ++ ++ } else { ++ lscf->balancer.original_init_upstream = ++ ngx_http_upstream_init_round_robin; + } + + uscf->peer.init_upstream = ngx_http_lua_balancer_init; +@@ -198,14 +317,18 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + + static ngx_int_t +-ngx_http_lua_balancer_init(ngx_conf_t *cf, +- ngx_http_upstream_srv_conf_t *us) ++ngx_http_lua_balancer_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) + { +- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { ++ ngx_http_lua_srv_conf_t *lscf; ++ ++ lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); ++ ++ if (lscf->balancer.original_init_upstream(cf, us) != NGX_OK) { + return NGX_ERROR; + } + +- /* this callback is called upon individual requests */ ++ lscf->balancer.original_init_peer = us->peer.init; ++ + us->peer.init = ngx_http_lua_balancer_init_peer; + + return NGX_OK; +@@ -216,33 +339,38 @@ static ngx_int_t + ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us) + { +- ngx_http_lua_srv_conf_t *bcf; ++ ngx_http_lua_srv_conf_t *lscf; + ngx_http_lua_balancer_peer_data_t *bp; + +- bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); +- if (bp == NULL) { ++ lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); ++ ++ if (lscf->balancer.original_init_peer(r, us) != NGX_OK) { + return NGX_ERROR; + } + +- r->upstream->peer.data = &bp->rrp; +- +- if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { ++ bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); ++ if (bp == NULL) { + return NGX_ERROR; + } + ++ bp->conf = lscf; ++ bp->request = r; ++ bp->data = r->upstream->peer.data; ++ bp->original_get_peer = r->upstream->peer.get; ++ bp->original_free_peer = r->upstream->peer.free; ++ ++ r->upstream->peer.data = bp; + r->upstream->peer.get = ngx_http_lua_balancer_get_peer; + r->upstream->peer.free = ngx_http_lua_balancer_free_peer; + + #if (NGX_HTTP_SSL) ++ bp->original_set_session = r->upstream->peer.set_session; ++ bp->original_save_session = r->upstream->peer.save_session; ++ + r->upstream->peer.set_session = ngx_http_lua_balancer_set_session; + r->upstream->peer.save_session = ngx_http_lua_balancer_save_session; + #endif + +- bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); +- +- bp->conf = bcf; +- bp->request = r; +- + return NGX_OK; + } + +@@ -250,25 +378,26 @@ ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + static ngx_int_t + ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + { +- lua_State *L; +- ngx_int_t rc; +- ngx_http_request_t *r; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_srv_conf_t *lscf; +- ngx_http_lua_main_conf_t *lmcf; +- ngx_http_lua_balancer_peer_data_t *bp = data; ++ lua_State *L; ++ ngx_int_t rc; ++ ngx_queue_t *q; ++ ngx_connection_t *c; ++ ngx_http_request_t *r; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_srv_conf_t *lscf; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ngx_http_lua_balancer_peer_data_t *bp = data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, +- "lua balancer peer, tries: %ui", pc->tries); +- +- lscf = bp->conf; ++ "lua balancer: get peer, tries: %ui", pc->tries); + + r = bp->request; ++ lscf = bp->conf; + + ngx_http_lua_assert(lscf->balancer.handler && r); + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); +- + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { +@@ -286,9 +415,15 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + + ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; + ++ bp->cpool = NULL; + bp->sockaddr = NULL; + bp->socklen = 0; + bp->more_tries = 0; ++ bp->cpool_crc32 = 0; ++ bp->cpool_size = 0; ++ bp->keepalive_requests = 0; ++ bp->keepalive_timeout = 0; ++ bp->keepalive = 0; + bp->total_tries++; + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +@@ -300,7 +435,6 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + lmcf->balancer_peer_data = bp; + + rc = lscf->balancer.handler(r, lscf, L); +- + if (rc == NGX_ERROR) { + return NGX_ERROR; + } +@@ -322,105 +456,414 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + } + } + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + pc->sockaddr = bp->sockaddr; + pc->socklen = bp->socklen; ++ pc->name = bp->host; + pc->cached = 0; + pc->connection = NULL; +- pc->name = bp->host; +- +- bp->rrp.peers->single = 0; + + if (bp->more_tries) { + r->upstream->peer.tries += bp->more_tries; + } + +- dd("tries: %d", (int) r->upstream->peer.tries); ++ if (ngx_http_lua_balancer_keepalive_is_enabled(bp)) { ++ ngx_http_lua_balancer_get_keepalive_pool(L, bp->cpool_crc32, ++ &bp->cpool); ++ ++ if (bp->cpool == NULL ++ && ngx_http_lua_balancer_create_keepalive_pool(L, pc->log, ++ bp->cpool_crc32, ++ bp->cpool_size, ++ &bp->cpool) ++ != NGX_OK) ++ { ++ return NGX_ERROR; ++ } ++ ++ ngx_http_lua_assert(bp->cpool); ++ ++ if (!ngx_queue_empty(&bp->cpool->cache)) { ++ q = ngx_queue_head(&bp->cpool->cache); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ c = item->connection; ++ ++ ngx_queue_remove(q); ++ ngx_queue_insert_head(&bp->cpool->free, q); ++ ++ c->idle = 0; ++ c->sent = 0; ++ c->log = pc->log; ++ c->read->log = pc->log; ++ c->write->log = pc->log; ++ c->pool->log = pc->log; ++ ++ if (c->read->timer_set) { ++ ngx_del_timer(c->read); ++ } ++ ++ pc->cached = 1; ++ pc->connection = c; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive reusing connection %p, " ++ "requests: %ui, cpool: %p", ++ c, c->requests, bp->cpool); ++ ++ return NGX_DONE; ++ } ++ ++ bp->cpool->connections++; ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive no free connection, " ++ "cpool: %p", bp->cpool); ++ } + + return NGX_OK; + } + +- return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp); ++ return bp->original_get_peer(pc, bp->data); + } + + +-static ngx_int_t +-ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) ++static void ++ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, ++ ngx_uint_t state) + { +- u_char *err_msg; +- size_t len; +- ngx_int_t rc; ++ ngx_queue_t *q; ++ ngx_connection_t *c; ++ ngx_http_upstream_t *u; ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ngx_http_lua_balancer_keepalive_pool_t *cpool; ++ ngx_http_lua_balancer_peer_data_t *bp = data; + +- /* init nginx context in Lua VM */ +- ngx_http_lua_set_req(L, r); ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: free peer, tries: %ui", pc->tries); + +-#ifndef OPENRESTY_LUAJIT +- ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); ++ u = bp->request->upstream; ++ c = pc->connection; + +- /* {{{ make new env inheriting main thread's globals table */ +- lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ +- ngx_http_lua_get_globals_table(L); +- lua_setfield(L, -2, "__index"); +- lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ +- /* }}} */ ++ if (ngx_http_lua_balancer_peer_set(bp)) { ++ bp->last_peer_state = (int) state; + +- lua_setfenv(L, -2); /* set new running env for the code closure */ +-#endif /* OPENRESTY_LUAJIT */ ++ if (pc->tries) { ++ pc->tries--; ++ } + +- lua_pushcfunction(L, ngx_http_lua_traceback); +- lua_insert(L, 1); /* put it under chunk and args */ ++ if (ngx_http_lua_balancer_keepalive_is_enabled(bp)) { ++ cpool = bp->cpool; + +- /* protected call user code */ +- rc = lua_pcall(L, 0, 1, 1); ++ if (state & NGX_PEER_FAILED ++ || c == NULL ++ || c->read->eof ++ || c->read->error ++ || c->read->timedout ++ || c->write->error ++ || c->write->timedout) ++ { ++ goto invalid; ++ } + +- lua_remove(L, 1); /* remove traceback function */ ++ if (bp->keepalive_requests ++ && c->requests >= bp->keepalive_requests) ++ { ++ goto invalid; ++ } + +- dd("rc == %d", (int) rc); ++ if (!u->keepalive) { ++ goto invalid; ++ } + +- if (rc != 0) { +- /* error occurred when running loaded code */ +- err_msg = (u_char *) lua_tolstring(L, -1, &len); ++ if (!u->request_body_sent) { ++ goto invalid; ++ } + +- if (err_msg == NULL) { +- err_msg = (u_char *) "unknown reason"; +- len = sizeof("unknown reason") - 1; ++ if (ngx_terminate || ngx_exiting) { ++ goto invalid; ++ } ++ ++ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ++ goto invalid; ++ } ++ ++ if (ngx_queue_empty(&cpool->free)) { ++ q = ngx_queue_last(&cpool->cache); ++ ngx_queue_remove(q); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ ++ ngx_http_lua_balancer_close(item->connection); ++ ++ } else { ++ q = ngx_queue_head(&cpool->free); ++ ngx_queue_remove(q); ++ ++ item = ngx_queue_data(q, ngx_http_lua_balancer_keepalive_item_t, ++ queue); ++ } ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive saving connection %p, " ++ "cpool: %p, connections: %ui", ++ c, cpool, cpool->connections); ++ ++ ngx_queue_insert_head(&cpool->cache, q); ++ ++ item->connection = c; ++ ++ pc->connection = NULL; ++ ++ if (bp->keepalive_timeout) { ++ c->read->delayed = 0; ++ ngx_add_timer(c->read, bp->keepalive_timeout); ++ ++ } else if (c->read->timer_set) { ++ ngx_del_timer(c->read); ++ } ++ ++ if (c->write->timer_set) { ++ ngx_del_timer(c->write); ++ } ++ ++ c->write->handler = ngx_http_lua_balancer_dummy_handler; ++ c->read->handler = ngx_http_lua_balancer_close_handler; ++ ++ c->data = item; ++ c->idle = 1; ++ c->log = ngx_cycle->log; ++ c->read->log = ngx_cycle->log; ++ c->write->log = ngx_cycle->log; ++ c->pool->log = ngx_cycle->log; ++ ++ if (c->read->ready) { ++ ngx_http_lua_balancer_close_handler(c->read); ++ } ++ ++ return; ++ ++invalid: ++ ++ cpool->connections--; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "lua balancer: keepalive not saving connection %p, " ++ "cpool: %p, connections: %ui", ++ c, cpool, cpool->connections); ++ ++ if (cpool->connections == 0) { ++ ngx_http_lua_balancer_free_keepalive_pool(pc->log, cpool); ++ } + } + +- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, +- "failed to run balancer_by_lua*: %*s", len, err_msg); ++ return; ++ } + +- lua_settop(L, 0); /* clear remaining elems on stack */ ++ bp->original_free_peer(pc, bp->data, state); ++} ++ ++ ++static ngx_int_t ++ngx_http_lua_balancer_create_keepalive_pool(lua_State *L, ngx_log_t *log, ++ uint32_t cpool_crc32, ngx_uint_t cpool_size, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool) ++{ ++ size_t size; ++ ngx_uint_t i; ++ ngx_http_lua_balancer_keepalive_pool_t *upool; ++ ngx_http_lua_balancer_keepalive_item_t *items; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ ngx_http_lua_assert(lua_istable(L, -1)); ++ ++ size = sizeof(ngx_http_lua_balancer_keepalive_pool_t) ++ + sizeof(ngx_http_lua_balancer_keepalive_item_t) * cpool_size; + ++ upool = lua_newuserdata(L, size); /* pools upool */ ++ if (upool == NULL) { + return NGX_ERROR; + } + +- lua_settop(L, 0); /* clear remaining elems on stack */ +- return rc; ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, ++ "lua balancer: keepalive create pool, crc32: %ui, " ++ "size: %ui", cpool_crc32, cpool_size); ++ ++ upool->lua_vm = L; ++ upool->crc32 = cpool_crc32; ++ upool->size = cpool_size; ++ upool->connections = 0; ++ ++ ngx_queue_init(&upool->cache); ++ ngx_queue_init(&upool->free); ++ ++ lua_rawseti(L, -2, cpool_crc32); /* pools */ ++ lua_pop(L, 1); /* orig stack */ ++ ++ items = (ngx_http_lua_balancer_keepalive_item_t *) (&upool->free + 1); ++ ++ ngx_http_lua_assert((void *) items == ngx_align_ptr(items, NGX_ALIGNMENT)); ++ ++ for (i = 0; i < cpool_size; i++) { ++ ngx_queue_insert_head(&upool->free, &items[i].queue); ++ items[i].cpool = upool; ++ } ++ ++ *cpool = upool; ++ ++ return NGX_OK; + } + + + static void +-ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, +- ngx_uint_t state) ++ngx_http_lua_balancer_get_keepalive_pool(lua_State *L, uint32_t cpool_crc32, ++ ngx_http_lua_balancer_keepalive_pool_t **cpool) + { +- ngx_http_lua_balancer_peer_data_t *bp = data; ++ ngx_http_lua_balancer_keepalive_pool_t *upool; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* orig stack */ ++ ++ /* create upstream connection pools table */ ++ lua_createtable(L, 0, 0); /* pools */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_pushvalue(L, -2); /* pools pools_table_key pools */ ++ lua_rawset(L, LUA_REGISTRYINDEX); /* pools */ ++ } + +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, +- "lua balancer free peer, tries: %ui", pc->tries); ++ ngx_http_lua_assert(lua_istable(L, -1)); + +- if (bp->sockaddr && bp->socklen) { +- bp->last_peer_state = (int) state; ++ lua_rawgeti(L, -1, cpool_crc32); /* pools upool? */ ++ upool = lua_touserdata(L, -1); ++ lua_pop(L, 2); /* orig stack */ + +- if (pc->tries) { +- pc->tries--; ++ *cpool = upool; ++} ++ ++ ++static void ++ngx_http_lua_balancer_free_keepalive_pool(ngx_log_t *log, ++ ngx_http_lua_balancer_keepalive_pool_t *cpool) ++{ ++ lua_State *L; ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, ++ "lua balancer: keepalive free pool %p, crc32: %ui", ++ cpool, cpool->crc32); ++ ++ ngx_http_lua_assert(cpool->connections == 0); ++ ++ L = cpool->lua_vm; ++ ++ /* get upstream connection pools table */ ++ lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( ++ balancer_keepalive_pools_table_key)); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* pools? */ ++ ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* orig stack */ ++ return; ++ } ++ ++ ngx_http_lua_assert(lua_istable(L, -1)); ++ ++ lua_pushnil(L); /* pools nil */ ++ lua_rawseti(L, -2, cpool->crc32); /* pools */ ++ lua_pop(L, 1); /* orig stack */ ++} ++ ++ ++static void ++ngx_http_lua_balancer_close(ngx_connection_t *c) ++{ ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ++ item = c->data; ++ ++#if (NGX_HTTP_SSL) ++ if (c->ssl) { ++ c->ssl->no_wait_shutdown = 1; ++ c->ssl->no_send_shutdown = 1; ++ ++ if (ngx_ssl_shutdown(c) == NGX_AGAIN) { ++ c->ssl->handler = ngx_http_lua_balancer_close; ++ return; ++ } ++ } ++#endif ++ ++ ngx_destroy_pool(c->pool); ++ ngx_close_connection(c); ++ ++ item->cpool->connections--; ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "lua balancer: keepalive closing connection %p, cpool: %p, " ++ "connections: %ui", ++ c, item->cpool, item->cpool->connections); ++} ++ ++ ++static void ++ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev) ++{ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, ++ "lua balancer: dummy handler"); ++} ++ ++ ++static void ++ngx_http_lua_balancer_close_handler(ngx_event_t *ev) ++{ ++ ngx_http_lua_balancer_keepalive_item_t *item; ++ ++ int n; ++ char buf[1]; ++ ngx_connection_t *c; ++ ++ c = ev->data; ++ ++ if (c->close || c->read->timedout) { ++ goto close; ++ } ++ ++ n = recv(c->fd, buf, 1, MSG_PEEK); ++ ++ if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { ++ ev->ready = 0; ++ ++ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ++ goto close; + } + + return; + } + +- /* fallback */ ++close: ++ ++ item = c->data; ++ c->log = ev->log; ++ ++ ngx_http_lua_balancer_close(c); + +- ngx_http_upstream_free_round_robin_peer(pc, data, state); ++ ngx_queue_remove(&item->queue); ++ ngx_queue_insert_head(&item->cpool->free, &item->queue); ++ ++ if (item->cpool->connections == 0) { ++ ngx_http_lua_balancer_free_keepalive_pool(ev->log, item->cpool); ++ } + } + + +@@ -431,12 +874,12 @@ ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data) + { + ngx_http_lua_balancer_peer_data_t *bp = data; + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + /* TODO */ + return NGX_OK; + } + +- return ngx_http_upstream_set_round_robin_peer_session(pc, &bp->rrp); ++ return bp->original_set_session(pc, bp->data); + } + + +@@ -445,13 +888,12 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) + { + ngx_http_lua_balancer_peer_data_t *bp = data; + +- if (bp->sockaddr && bp->socklen) { ++ if (ngx_http_lua_balancer_peer_set(bp)) { + /* TODO */ + return; + } + +- ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp); +- return; ++ bp->original_save_session(pc, bp->data); + } + + #endif +@@ -459,14 +901,14 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) + + int + ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, +- const u_char *addr, size_t addr_len, int port, char **err) ++ const u_char *addr, size_t addr_len, int port, unsigned int cpool_crc32, ++ unsigned int cpool_size, char **err) + { +- ngx_url_t url; +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- +- ngx_http_lua_main_conf_t *lmcf; +- ngx_http_lua_balancer_peer_data_t *bp; ++ ngx_url_t url; ++ ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { + *err = "no request found"; +@@ -536,6 +978,70 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ bp->cpool_crc32 = (uint32_t) cpool_crc32; ++ bp->cpool_size = (ngx_uint_t) cpool_size; ++ ++ return NGX_OK; ++} ++ ++ ++int ++ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, ++ unsigned long timeout, unsigned int max_requests, char **err) ++{ ++ ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_balancer_peer_data_t *bp; ++ ++ if (r == NULL) { ++ *err = "no request found"; ++ return NGX_ERROR; ++ } ++ ++ u = r->upstream; ++ ++ if (u == NULL) { ++ *err = "no upstream found"; ++ return NGX_ERROR; ++ } ++ ++ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); ++ if (ctx == NULL) { ++ *err = "no ctx found"; ++ return NGX_ERROR; ++ } ++ ++ if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { ++ *err = "API disabled in the current context"; ++ return NGX_ERROR; ++ } ++ ++ lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); ++ ++ /* we cannot read r->upstream->peer.data here directly because ++ * it could be overridden by other modules like ++ * ngx_http_upstream_keepalive_module. ++ */ ++ bp = lmcf->balancer_peer_data; ++ if (bp == NULL) { ++ *err = "no upstream peer data found"; ++ return NGX_ERROR; ++ } ++ ++ if (!ngx_http_lua_balancer_peer_set(bp)) { ++ *err = "no current peer set"; ++ return NGX_ERROR; ++ } ++ ++ if (!bp->cpool_crc32) { ++ bp->cpool_crc32 = ngx_crc32_long(bp->host->data, bp->host->len); ++ } ++ ++ bp->keepalive_timeout = (ngx_msec_t) timeout; ++ bp->keepalive_requests = (ngx_uint_t) max_requests; ++ bp->keepalive = 1; ++ + return NGX_OK; + } + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_common.h b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +index 781a2454..9ce6836a 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_common.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +@@ -295,6 +295,10 @@ union ngx_http_lua_srv_conf_u { + #endif + + struct { ++ ngx_http_upstream_init_pt original_init_upstream; ++ ngx_http_upstream_init_peer_pt original_init_peer; ++ uintptr_t data; ++ + ngx_http_lua_srv_conf_handler_pt handler; + ngx_str_t src; + u_char *src_key; +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_module.c b/ngx_lua-0.10.17/src/ngx_http_lua_module.c +index 9816d864..5d7cedfd 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_module.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_module.c +@@ -988,6 +988,9 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf) + * lscf->srv.ssl_session_fetch_src = { 0, NULL }; + * lscf->srv.ssl_session_fetch_src_key = NULL; + * ++ * lscf->balancer.original_init_upstream = NULL; ++ * lscf->balancer.original_init_peer = NULL; ++ * lscf->balancer.data = NULL; + * lscf->balancer.handler = NULL; + * lscf->balancer.src = { 0, NULL }; + * lscf->balancer.src_key = NULL; +-- +2.26.2 + + +From 4c5cb29a265b2f9524434322adf15d07deec6c7f Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:54 -0700 +Subject: [PATCH 2/3] feature: we now avoid the need for 'upstream' blocks to + define a stub 'server' directive when using 'balancer_by_lua*'. + +--- + src/ngx_http_lua_balancer.c | 42 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 0d403716..5c862d22 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -111,7 +111,8 @@ static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, + (bp->sockaddr && bp->socklen) + + +-static char ngx_http_lua_balancer_keepalive_pools_table_key; ++static char ngx_http_lua_balancer_keepalive_pools_table_key; ++static struct sockaddr *ngx_http_lua_balancer_default_server_sockaddr; + + + ngx_int_t +@@ -239,7 +240,9 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + u_char *cache_key = NULL; + u_char *name; + ngx_str_t *value; ++ ngx_url_t url; + ngx_http_upstream_srv_conf_t *uscf; ++ ngx_http_upstream_server_t *us; + ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); +@@ -293,6 +296,29 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + ++ if (uscf->servers->nelts == 0) { ++ us = ngx_array_push(uscf->servers); ++ if (us == NULL) { ++ return NGX_CONF_ERROR; ++ } ++ ++ ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); ++ ngx_memzero(&url, sizeof(ngx_url_t)); ++ ++ ngx_str_set(&url.url, "0.0.0.1"); ++ url.default_port = 80; ++ ++ if (ngx_parse_url(cf->pool, &url) != NGX_OK) { ++ return NGX_CONF_ERROR; ++ } ++ ++ us->name = url.url; ++ us->addrs = url.addrs; ++ us->naddrs = url.naddrs; ++ ++ ngx_http_lua_balancer_default_server_sockaddr = us->addrs[0].sockaddr; ++ } ++ + if (uscf->peer.init_upstream) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "load balancing method redefined"); +@@ -525,7 +551,19 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + return NGX_OK; + } + +- return bp->original_get_peer(pc, bp->data); ++ rc = bp->original_get_peer(pc, bp->data); ++ if (rc == NGX_ERROR) { ++ return rc; ++ } ++ ++ if (pc->sockaddr == ngx_http_lua_balancer_default_server_sockaddr) { ++ ngx_log_error(NGX_LOG_ERR, pc->log, 0, ++ "lua balancer: no peer set"); ++ ++ return NGX_ERROR; ++ } ++ ++ return rc; + } + + +-- +2.26.2 + + +From 941cd893573561574bc6a326d6306f1a30127293 Mon Sep 17 00:00:00 2001 +From: Thibault Charbonnier +Date: Tue, 17 Sep 2019 11:43:58 -0700 +Subject: [PATCH 3/3] refactor: used a simpler way to stash the balancer peer + data. + +--- + src/ngx_http_lua_balancer.c | 91 +++++++++---------------------------- + src/ngx_http_lua_common.h | 7 --- + 2 files changed, 22 insertions(+), 76 deletions(-) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 5c862d22..3ea1f067 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -411,9 +411,9 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_srv_conf_t *lscf; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_keepalive_item_t *item; + ngx_http_lua_balancer_peer_data_t *bp = data; ++ void *pdata; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: get peer, tries: %ui", pc->tries); +@@ -452,15 +452,13 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) + bp->keepalive = 0; + bp->total_tries++; + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* balancer_by_lua does not support yielding and +- * there cannot be any conflicts among concurrent requests, +- * thus it is safe to store the peer data in the main conf. +- */ +- lmcf->balancer_peer_data = bp; ++ pdata = r->upstream->peer.data; ++ r->upstream->peer.data = bp; + + rc = lscf->balancer.handler(r, lscf, L); ++ ++ r->upstream->peer.data = pdata; ++ + if (rc == NGX_ERROR) { + return NGX_ERROR; + } +@@ -945,7 +943,6 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + ngx_url_t url; + ngx_http_upstream_t *u; + ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -971,18 +968,6 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* we cannot read r->upstream->peer.data here directly because +- * it could be overridden by other modules like +- * ngx_http_upstream_keepalive_module. +- */ +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } +- + ngx_memzero(&url, sizeof(ngx_url_t)); + + url.url.data = ngx_palloc(r->pool, addr_len); +@@ -1006,6 +991,8 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + return NGX_ERROR; + } + ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; ++ + if (url.addrs && url.addrs[0].sockaddr) { + bp->sockaddr = url.addrs[0].sockaddr; + bp->socklen = url.addrs[0].socklen; +@@ -1029,7 +1016,6 @@ ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, + { + ngx_http_upstream_t *u; + ngx_http_lua_ctx_t *ctx; +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -1055,17 +1041,7 @@ ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- /* we cannot read r->upstream->peer.data here directly because +- * it could be overridden by other modules like +- * ngx_http_upstream_keepalive_module. +- */ +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + if (!ngx_http_lua_balancer_peer_set(bp)) { + *err = "no current peer set"; +@@ -1089,14 +1065,13 @@ ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, long read_timeout, + char **err) + { +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; + + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + ngx_http_upstream_conf_t *ucf; +-#endif +- ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; ++#endif + + if (r == NULL) { + *err = "no request found"; +@@ -1121,15 +1096,9 @@ ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } +- + #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; ++ + if (!bp->cloned_upstream_conf) { + /* we clone the upstream conf for the current request so that + * we do not affect other requests at all. */ +@@ -1184,12 +1153,10 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + int count, char **err) + { + #if (nginx_version >= 1007005) +- ngx_uint_t max_tries, total; ++ ngx_uint_t max_tries, total; + #endif +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- +- ngx_http_lua_main_conf_t *lmcf; ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { +@@ -1215,13 +1182,7 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + #if (nginx_version >= 1007005) + max_tries = r->upstream->conf->next_upstream_tries; +@@ -1247,12 +1208,10 @@ int + ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + int *status, char **err) + { +- ngx_http_lua_ctx_t *ctx; +- ngx_http_upstream_t *u; +- ngx_http_upstream_state_t *state; +- ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; ++ ngx_http_upstream_state_t *state; + ngx_http_lua_balancer_peer_data_t *bp; +- ngx_http_lua_main_conf_t *lmcf; + + if (r == NULL) { + *err = "no request found"; +@@ -1277,13 +1236,7 @@ ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + return NGX_ERROR; + } + +- lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +- +- bp = lmcf->balancer_peer_data; +- if (bp == NULL) { +- *err = "no upstream peer data found"; +- return NGX_ERROR; +- } ++ bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + if (r->upstream_states && r->upstream_states->nelts > 1) { + state = r->upstream_states->elts; +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_common.h b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +index 9ce6836a..9a4342df 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_common.h ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_common.h +@@ -217,13 +217,6 @@ struct ngx_http_lua_main_conf_s { + ngx_http_lua_main_conf_handler_pt init_worker_handler; + ngx_str_t init_worker_src; + +- ngx_http_lua_balancer_peer_data_t *balancer_peer_data; +- /* neither yielding nor recursion is possible in +- * balancer_by_lua*, so there cannot be any races among +- * concurrent requests and it is safe to store the peer +- * data pointer in the main conf. +- */ +- + ngx_chain_t *body_filter_chain; + /* neither yielding nor recursion is possible in + * body_filter_by_lua*, so there cannot be any races among +-- +2.26.2 + diff --git a/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_03-upstream_recreate_request.patch b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_03-upstream_recreate_request.patch new file mode 100644 index 00000000..f7a7d9c2 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/ngx_lua-0.10.17_03-upstream_recreate_request.patch @@ -0,0 +1,59 @@ +From 200cf83dbd180bc015e3e1b5b4344abc665d096a Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 23 Jun 2020 17:33:09 -0700 +Subject: [PATCH] feature: added the + `ngx_http_lua_ffi_balancer_recreate_request` FFI function to allow recreation + of request buffer in balancer phase. + +--- + ngx_lua-0.10.17/src/ngx_http_lua_balancer.c | 39 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +index 3ea1f067..19a785e5 100644 +--- a/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c ++++ b/ngx_lua-0.10.17/src/ngx_http_lua_balancer.c +@@ -1250,4 +1250,43 @@ ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + } + + ++int ++ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r, ++ char **err) ++{ ++ ngx_http_lua_ctx_t *ctx; ++ ngx_http_upstream_t *u; ++ ++ if (r == NULL) { ++ *err = "no request found"; ++ return NGX_ERROR; ++ } ++ ++ u = r->upstream; ++ ++ if (u == NULL) { ++ *err = "no upstream found"; ++ return NGX_ERROR; ++ } ++ ++ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); ++ if (ctx == NULL) { ++ *err = "no ctx found"; ++ return NGX_ERROR; ++ } ++ ++ if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { ++ *err = "API disabled in the current context"; ++ return NGX_ERROR; ++ } ++ ++ /* u->create_request can not be NULL since we are in balancer phase */ ++ ngx_http_lua_assert(u->create_request != NULL); ++ ++ *err = NULL; ++ ++ return u->create_request(r); ++} ++ ++ + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch b/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch new file mode 100644 index 00000000..0b27a67e --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_01-inject-req-time-api.patch @@ -0,0 +1,25 @@ +From a6afd31d32b31cf67afb13873deefb0c9d4e50a9 Mon Sep 17 00:00:00 2001 +From: James Callahan +Date: Tue, 11 Sep 2018 10:34:53 -0700 +Subject: [PATCH 4/9] inject req time api + +Signed-off-by: Aapo Talvensaari +--- + ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c b/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c +index 313a8f4..f47a574 100644 +--- a/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c ++++ b/ngx_stream_lua-0.0.8/src/ngx_stream_lua_util.c +@@ -1955,6 +1955,7 @@ ngx_stream_lua_inject_req_api(ngx_log_t *log, lua_State *L) + lua_pushcfunction(L, ngx_stream_lua_req_socket); + lua_setfield(L, -2, "socket"); + ++ ngx_stream_lua_inject_req_time_api(L); + + lua_setfield(L, -2, "req"); + } +-- +2.19.1 + diff --git a/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_02-expose_request_struct.patch b/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_02-expose_request_struct.patch new file mode 100644 index 00000000..029150c3 --- /dev/null +++ b/openresty-patches/patches/1.17.8.2/ngx_stream_lua-0.0.8_02-expose_request_struct.patch @@ -0,0 +1,27 @@ +From 0acb7f5ad0fbc9ee037f0c5d689f98861fe9e49b Mon Sep 17 00:00:00 2001 +From: Datong Sun +Date: Tue, 10 Dec 2019 11:51:53 -0800 +Subject: [PATCH] Sync with meta-lua-nginx-module + 1330009671cd86eaf045f9f2c5cda3727a94570f. + +--- + ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h b/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h +index 0e5a18f..040ef84 100644 +--- a/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h ++++ b/ngx_stream_lua-0.0.8/src/api/ngx_stream_lua_api.h +@@ -21,6 +21,9 @@ + + + ++#include ++#include "../ngx_stream_lua_request.h" ++ + + #include + #include +-- +2.20.1 +