From 155cce4e52a27be0dd0b770ad858f1708bbc313d Mon Sep 17 00:00:00 2001 From: "lj2007331@gmail.com" Date: Sat, 15 May 2021 20:16:26 +0800 Subject: [PATCH] [feat] Update resty --- resty/core.lua | 3 +- resty/core/base.lua | 14 ++--- resty/core/ctx.lua | 73 +++++++++++++++++------- resty/core/phase.lua | 1 + resty/core/regex.lua | 21 +++++-- resty/core/request.lua | 48 +++++++++++----- resty/core/socket.lua | 124 +++++++++++++++++++++++++++++++++++++++++ resty/core/utils.lua | 40 ++++++------- 8 files changed, 259 insertions(+), 65 deletions(-) create mode 100644 resty/core/socket.lua diff --git a/resty/core.lua b/resty/core.lua index 54d9756..5472230 100644 --- a/resty/core.lua +++ b/resty/core.lua @@ -12,13 +12,14 @@ 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" + require "resty.core.socket" end diff --git a/resty/core/base.lua b/resty/core/base.lua index 96ce881..880c50f 100644 --- a/resty/core/base.lua +++ b/resty/core/base.lua @@ -19,22 +19,22 @@ if subsystem == 'http' then local ngx_lua_v = ngx.config.ngx_lua_version if not ngx.config or not ngx.config.ngx_lua_version - or (ngx_lua_v ~= 10019 and ngx_lua_v ~= 10020) + or (ngx_lua_v ~= 10018 and ngx_lua_v ~= 10019) then - error("ngx_http_lua_module 0.10.19 or 0.10.20 required") + error("ngx_http_lua_module 0.10.18 or 0.10.19 required") end elseif subsystem == 'stream' then if not ngx.config or not ngx.config.ngx_lua_version - or ngx.config.ngx_lua_version ~= 8 + or ngx.config.ngx_lua_version ~= 9 then - error("ngx_stream_lua_module 0.0.8 required") + error("ngx_stream_lua_module 0.0.9 required") end else - error("ngx_http_lua_module 0.10.16 or " - .. "ngx_stream_lua_module 0.0.8 required") + error("ngx_http_lua_module 0.10.18 or " + .. "ngx_stream_lua_module 0.0.9 required") end @@ -133,7 +133,7 @@ local c_buf_type = ffi.typeof("char[?]") local _M = new_tab(0, 18) -_M.version = "0.1.19" +_M.version = "0.1.21" _M.new_tab = new_tab _M.clear_tab = clear_tab diff --git a/resty/core/ctx.lua b/resty/core/ctx.lua index 0683aaa..61b391a 100644 --- a/resty/core/ctx.lua +++ b/resty/core/ctx.lua @@ -17,6 +17,7 @@ local get_request = base.get_request local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX local FFI_OK = base.FFI_OK local error = error +local setmetatable = setmetatable local subsystem = ngx.config.subsystem @@ -26,7 +27,8 @@ local ngx_lua_ffi_set_ctx_ref if subsystem == "http" then ffi.cdef[[ - int ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r); + int ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r, int *in_ssl_phase, + int *ssl_ctx_ref); int ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref); ]] @@ -35,7 +37,8 @@ if subsystem == "http" then elseif subsystem == "stream" then ffi.cdef[[ - int ngx_stream_lua_ffi_get_ctx_ref(ngx_stream_lua_request_t *r); + int ngx_stream_lua_ffi_get_ctx_ref(ngx_stream_lua_request_t *r, + int *in_ssl_phase, int *ssl_ctx_ref); int ngx_stream_lua_ffi_set_ctx_ref(ngx_stream_lua_request_t *r, int ref); ]] @@ -49,28 +52,56 @@ local _M = { } -local function get_ctx_table() - local r = get_request() +local get_ctx_table +do + local in_ssl_phase = ffi.new("int[1]") + local ssl_ctx_ref = ffi.new("int[1]") - if not r then - error("no request found") - end + function get_ctx_table() + local r = get_request() - local ctx_ref = ngx_lua_ffi_get_ctx_ref(r) - if ctx_ref == FFI_NO_REQ_CTX then - error("no request ctx found") - end - - local ctxs = registry.ngx_lua_ctx_tables - if ctx_ref < 0 then - local ctx = new_tab(0, 4) - ctx_ref = ref_in_table(ctxs, ctx) - if ngx_lua_ffi_set_ctx_ref(r, ctx_ref) ~= FFI_OK then - return nil + if not r then + error("no request found") end - return ctx + + local ctx_ref = ngx_lua_ffi_get_ctx_ref(r, in_ssl_phase, ssl_ctx_ref) + if ctx_ref == FFI_NO_REQ_CTX then + error("no request ctx found") + end + + local ctxs = registry.ngx_lua_ctx_tables + if ctx_ref < 0 then + local ctx + + ctx_ref = ssl_ctx_ref[0] + if ctx_ref > 0 and ctxs[ctx_ref] then + if in_ssl_phase[0] ~= 0 then + return ctxs[ctx_ref] + end + + ctx = new_tab(0, 4) + ctx = setmetatable(ctx, ctxs[ctx_ref]) + + else + if in_ssl_phase[0] ~= 0 then + ctx = new_tab(1, 4) + -- to avoid creating another table, we assume the users + -- won't overwrite the `__index` key + ctx.__index = ctx + + else + ctx = new_tab(0, 4) + end + end + + ctx_ref = ref_in_table(ctxs, ctx) + if ngx_lua_ffi_set_ctx_ref(r, ctx_ref) ~= FFI_OK then + return nil + end + return ctx + end + return ctxs[ctx_ref] end - return ctxs[ctx_ref] end register_getter("ctx", get_ctx_table) @@ -82,7 +113,7 @@ local function set_ctx_table(ctx) error("no request found") end - local ctx_ref = ngx_lua_ffi_get_ctx_ref(r) + local ctx_ref = ngx_lua_ffi_get_ctx_ref(r, nil, nil) if ctx_ref == FFI_NO_REQ_CTX then error("no request ctx found") end diff --git a/resty/core/phase.lua b/resty/core/phase.lua index d30a534..331752a 100644 --- a/resty/core/phase.lua +++ b/resty/core/phase.lua @@ -28,6 +28,7 @@ local context_names = { [0x0400] = "ssl_cert", [0x0800] = "ssl_session_store", [0x1000] = "ssl_session_fetch", + [0x2000] = "exit_worker", } diff --git a/resty/core/regex.lua b/resty/core/regex.lua index 6de764f..6a14416 100644 --- a/resty/core/regex.lua +++ b/resty/core/regex.lua @@ -48,14 +48,27 @@ local _M = { ngx.re = new_tab(0, 5) -ffi.cdef[[ - const char *pcre_version(void); -]] +local pcre_ver_fn +if subsystem == 'http' then + ffi.cdef[[ + const char *ngx_http_lua_ffi_pcre_version(void); + ]] + pcre_ver_fn = C.ngx_http_lua_ffi_pcre_version + +elseif subsystem == 'stream' then + ffi.cdef[[ + const char *ngx_stream_lua_ffi_pcre_version(void); + ]] + pcre_ver_fn = C.ngx_stream_lua_ffi_pcre_version + +else + error("unsupported subsystem: " .. tostring(subsystem)) +end local pcre_ver -if not pcall(function() pcre_ver = ffi_string(C.pcre_version()) end) then +if not pcall(function() pcre_ver = ffi_string(pcre_ver_fn()) end) then setmetatable(ngx.re, { __index = function(_, key) error("no support for 'ngx.re." .. key .. "': OpenResty was " .. diff --git a/resty/core/request.lua b/resty/core/request.lua index f912bfa..747b8c2 100644 --- a/resty/core/request.lua +++ b/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/resty/core/socket.lua b/resty/core/socket.lua new file mode 100644 index 0000000..1a504ec --- /dev/null +++ b/resty/core/socket.lua @@ -0,0 +1,124 @@ +local base = require "resty.core.base" +base.allows_subsystem('http') +local debug = require 'debug' +local ffi = require 'ffi' + + +local error = error +local tonumber = tonumber +local registry = debug.getregistry() +local ffi_new = ffi.new +local ffi_string = ffi.string +local C = ffi.C +local get_string_buf = base.get_string_buf +local get_size_ptr = base.get_size_ptr +local tostring = tostring + + +local option_index = { + ["keepalive"] = 1, + ["reuseaddr"] = 2, + ["tcp-nodelay"] = 3, + ["sndbuf"] = 4, + ["rcvbuf"] = 5, +} + + +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_getoption(ngx_http_lua_socket_tcp_upstream_t *u, + int opt, int *val, unsigned char *err, size_t *errlen); + +int +ngx_http_lua_ffi_socket_tcp_setoption(ngx_http_lua_socket_tcp_upstream_t *u, + int opt, int val, unsigned char *err, size_t *errlen); +]] + + +local output_value_buf = ffi_new("int[1]") +local FFI_OK = base.FFI_OK +local SOCKET_CTX_INDEX = 1 +local ERR_BUF_SIZE = 4096 + + +local function get_tcp_socket(cosocket) + local tcp_socket = cosocket[SOCKET_CTX_INDEX] + if not tcp_socket then + error("socket is never created nor connected") + end + + return tcp_socket +end + + +local function getoption(cosocket, option) + local tcp_socket = get_tcp_socket(cosocket) + + if option == nil then + return nil, 'missing the "option" argument' + end + + if option_index[option] == nil then + return nil, "unsupported option " .. tostring(option) + end + + local err = get_string_buf(ERR_BUF_SIZE) + local errlen = get_size_ptr() + errlen[0] = ERR_BUF_SIZE + + local rc = C.ngx_http_lua_ffi_socket_tcp_getoption(tcp_socket, + option_index[option], + output_value_buf, + err, + errlen) + if rc ~= FFI_OK then + return nil, ffi_string(err, errlen[0]) + end + + return tonumber(output_value_buf[0]) +end + + +local function setoption(cosocket, option, value) + local tcp_socket = get_tcp_socket(cosocket) + + if option == nil then + return nil, 'missing the "option" argument' + end + + if value == nil then + return nil, 'missing the "value" argument' + end + + if option_index[option] == nil then + return nil, "unsupported option " .. tostring(option) + end + + local err = get_string_buf(ERR_BUF_SIZE) + local errlen = get_size_ptr() + errlen[0] = ERR_BUF_SIZE + + local rc = C.ngx_http_lua_ffi_socket_tcp_setoption(tcp_socket, + option_index[option], + value, + err, + errlen) + if rc ~= FFI_OK then + return nil, ffi_string(err, errlen[0]) + end + + return true +end + + +do + local method_table = registry.__tcp_cosocket_mt + method_table.getoption = getoption + method_table.setoption = setoption +end + + +return { version = base.version } diff --git a/resty/core/utils.lua b/resty/core/utils.lua index 398d7d5..fda074a 100644 --- a/resty/core/utils.lua +++ b/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 +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); + ]] + + + function _M.str_replace_char(str, find, replace) + if not str_find(str, find, nil, true) then + return str + end + + local len = #str + local buf = get_string_buf(len) + ffi_copy(buf, str, len) + + C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), + byte(replace)) + + return ffi_str(buf, len) end - - local len = #str - local buf = get_string_buf(len) - ffi_copy(buf, str) - - C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find), - byte(replace)) - - return ffi_str(buf, len) end