diff --git a/.gitignore b/.gitignore index ae4497fd5..95f31267b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ nginx ctags tags a.lua +t/shdict.t mockeagain.so diff --git a/lib/ngx/ssl.lua b/lib/ngx/ssl.lua index 336cbb841..fc870208b 100644 --- a/lib/ngx/ssl.lua +++ b/lib/ngx/ssl.lua @@ -6,9 +6,11 @@ base.allows_subsystem('http', 'stream') local ffi = require "ffi" +local bit = require "bit" local C = ffi.C local ffi_str = ffi.string local ffi_gc = ffi.gc +local bor = bit.bor local get_request = base.get_request local error = error local tonumber = tonumber @@ -19,7 +21,12 @@ local FFI_DECLINED = base.FFI_DECLINED local FFI_OK = base.FFI_OK local subsystem = ngx.config.subsystem - +local ngx_lua_ffi_ssl_client_server_name +local ngx_lua_ffi_ssl_set_ciphers +local ngx_lua_ffi_ssl_set_protocols +local ngx_http_lua_ffi_ssl_client_server_name +local ngx_http_lua_ffi_ssl_set_protocols +local ngx_http_lua_ffi_ssl_set_ciphers local ngx_lua_ffi_ssl_set_der_certificate local ngx_lua_ffi_ssl_clear_certs local ngx_lua_ffi_ssl_set_der_private_key @@ -39,6 +46,15 @@ local ngx_lua_ffi_free_priv_key if subsystem == 'http' then ffi.cdef[[ + int ngx_http_lua_ffi_ssl_client_server_name(ngx_http_request_t *r, + char **name, size_t *namelen, char **err); + + int ngx_http_lua_ffi_ssl_set_protocols(ngx_http_request_t *r, + int protocols, char **err); + + int ngx_http_lua_ffi_ssl_set_ciphers(void *r, + const unsigned char *cdata, char **err); + int ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r, const char *data, size_t len, char **err); @@ -80,6 +96,10 @@ if subsystem == 'http' then void ngx_http_lua_ffi_free_priv_key(void *cdata); ]] + ngx_lua_ffi_ssl_client_server_name = + C.ngx_http_lua_ffi_ssl_client_server_name + ngx_lua_ffi_ssl_set_ciphers = C.ngx_http_lua_ffi_ssl_set_ciphers + ngx_lua_ffi_ssl_set_protocols = C.ngx_http_lua_ffi_ssl_set_protocols ngx_lua_ffi_ssl_set_der_certificate = C.ngx_http_lua_ffi_ssl_set_der_certificate ngx_lua_ffi_ssl_clear_certs = C.ngx_http_lua_ffi_ssl_clear_certs @@ -169,6 +189,80 @@ local charpp = ffi.new("char*[1]") local intp = ffi.new("int[1]") +function _M.client_server_name() + if subsystem ~= 'http' then + error("no support stream") + end + + local r = get_request() + if not r then + error("no request found") + end + + local sizep = get_size_ptr() + + local rc = ngx_lua_ffi_ssl_client_server_name(r, charpp, sizep, errmsg) + if rc == FFI_OK then + return ffi_str(charpp[0], sizep[0]) + end + + return nil, ffi_str(errmsg[0]) +end + +do + local protocal_flags = { + ["SSLv2"] = 0x0002, + ["SSLv3"] = 0x0004, + ["TLSv1"] = 0x0008, + ["TLSv1.1"] = 0x0010, + ["TLSv1.2"] = 0x0020, + ["TLSv1.3"] = 0x0040, + }; + + function _M.set_protocols(ops) + if subsystem ~= 'http' then + error("no support stream") + end + + local r = get_request() + if not r then + error("no request found") + end + + local protocols = 0 + for _, op in ipairs(ops) do + protocols = bor(protocols, protocal_flags[op]) + end + + local rc = ngx_lua_ffi_ssl_set_protocols(r, protocols, errmsg) + if rc == FFI_OK then + return true + end + + return nil, ffi_str(errmsg[0]) + end +end + + +function _M.set_ciphers(ciphers) + if subsystem ~= 'http' then + error("no support stream") + end + + local r = get_request() + if not r then + error("no request found") + end + + local rc = ngx_lua_ffi_ssl_set_ciphers(r, ciphers, errmsg) + if rc == FFI_OK then + return true + end + + return nil, ffi_str(errmsg[0]) +end + + function _M.clear_certs() local r = get_request() if not r then @@ -241,6 +335,27 @@ function _M.raw_server_addr() return nil, nil, ffi_str(errmsg[0]) end +function _M.raw_client_addr() + local r = getfenv(0).__ngx_req + if not r then + return error("no request found") + end + + local sizep = get_size_ptr() + + local rc = C.ngx_http_lua_ffi_ssl_raw_client_addr(r, charpp, sizep, + intp, errmsg) + if rc == FFI_OK then + local typ = addr_types[intp[0]] + if not typ then + return nil, nil, "unknown address type: " .. intp[0] + end + return ffi_str(charpp[0], sizep[0]), typ + end + + return nil, nil, ffi_str(errmsg[0]) +end + function _M.server_name() local r = get_request() @@ -351,6 +466,10 @@ end function _M.set_cert(cert) + if cert == nil then + return nil, "certificate invalid" + end + local r = get_request() if not r then error("no request found") @@ -366,6 +485,10 @@ end function _M.set_priv_key(priv_key) + if priv_key == nil then + return nil, "private key invalid" + end + local r = get_request() if not r then error("no request found") diff --git a/lib/resty/core/phase.lua b/lib/resty/core/phase.lua index d30a53491..0fb620145 100644 --- a/lib/resty/core/phase.lua +++ b/lib/resty/core/phase.lua @@ -28,6 +28,7 @@ local context_names = { [0x0400] = "ssl_cert", [0x0800] = "ssl_session_store", [0x1000] = "ssl_session_fetch", + [0x2000] = "ssl_client_hello", } diff --git a/lib/resty/core/response.lua b/lib/resty/core/response.lua index 56bc18087..5f8230deb 100644 --- a/lib/resty/core/response.lua +++ b/lib/resty/core/response.lua @@ -42,6 +42,18 @@ ffi.cdef[[ const unsigned char *key, size_t key_len, unsigned char *key_buf, ngx_http_lua_ffi_str_t *values, int max_nvalues, char **errmsg); + + unsigned int + ngx_http_lua_ffi_bytes_sent(ngx_http_request_t *r); + + unsigned int + ngx_http_lua_ffi_bytes_buffered(ngx_http_request_t *r); + + unsigned int + ngx_http_lua_ffi_con_nbusy(ngx_http_request_t *r); + + unsigned int + ngx_http_lua_ffi_con_bytes_busy(ngx_http_request_t *r); ]] @@ -119,6 +131,41 @@ end _M.set_resp_header = set_resp_header +function _M.bytes_sent() + local r = get_request() + if not r then + error("no request found") + end + + return C.ngx_http_lua_ffi_bytes_sent(r) +end + +function _M.bytes_buffered() + local r = get_request() + if not r then + error("no request found") + end + + return C.ngx_http_lua_ffi_bytes_buffered(r) +end + +function _M.con_bytes_busy() + local r = get_request() + if not r then + error("no request found") + end + + return C.ngx_http_lua_ffi_con_bytes_busy(r) +end + +function _M.con_nbusy() + local r = get_request() + if not r then + error("no request found") + end + + return C.ngx_http_lua_ffi_con_nbusy(r) +end local function get_resp_header(tb, key) local r = get_request() diff --git a/lib/resty/core/shdict.lua b/lib/resty/core/shdict.lua index af91689f1..fadc2115a 100644 --- a/lib/resty/core/shdict.lua +++ b/lib/resty/core/shdict.lua @@ -40,7 +40,7 @@ int ngx_http_lua_ffi_shdict_get(void *zone, const unsigned char *key, int get_stale, int *is_stale, char **errmsg); int ngx_http_lua_ffi_shdict_incr(void *zone, const unsigned char *key, - size_t key_len, double *value, char **err, int has_init, + size_t key_len, double *value, int exptime, char **err, int has_init, double init, long init_ttl, int *forcible); int ngx_http_lua_ffi_shdict_store(void *zone, int op, @@ -431,7 +431,7 @@ local function shdict_get_stale(zone, key) end -local function shdict_incr(zone, key, value, init, init_ttl) +local function shdict_incr(zone, key, value, exptime, init, init_ttl) zone = check_zone(zone) if key == nil then @@ -450,10 +450,13 @@ local function shdict_incr(zone, key, value, init, init_ttl) return nil, "key too long" end + value = value or 1 if type(value) ~= "number" then value = tonumber(value) end num_value[0] = value + + exptime = exptime or -1 if init then local typ = type(init) @@ -488,7 +491,7 @@ local function shdict_incr(zone, key, value, init, init_ttl) init_ttl = 0 end - local rc = ngx_lua_ffi_shdict_incr(zone, key, key_len, num_value, + local rc = ngx_lua_ffi_shdict_incr(zone, key, key_len, num_value, exptime, errmsg, init and 1 or 0, init or 0, init_ttl * 1000, forcible) diff --git a/t/shdict.t b/t/shdict.t index edd88a8b1..3cf35494d 100644 --- a/t/shdict.t +++ b/t/shdict.t @@ -890,6 +890,21 @@ stitch +<<<<<<< HEAD + +=== TEST 27: incr key expire +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua ' + local val, flags + local dogs = ngx.shared.dogs + local value, err = dogs:incr(nil, 32, 10) + if not ok then + ngx.say("failed to incr: ", err) + end + '; +======= === TEST 28: incr, value is not number --- config location = /t { @@ -927,7 +942,7 @@ cannot convert 'nil' to 'double' ngx.say("failed to incr: ", err) end - local value, err, forcible = dogs:incr("foo", 10, 10) + local value, err, forcible = dogs:incr("foo", 10, nil, 10) if not value then ngx.say("failed to incr: ", err) return @@ -939,6 +954,13 @@ cannot convert 'nil' to 'double' --- request GET /t --- response_body +<<<<<<< HEAD +failed to incr: nil key +--- no_error_log +[error] +[alert] +[crit] +======= failed to incr: not found incr ok, value: 20, forcible: false --- no_error_log @@ -954,7 +976,7 @@ incr ok, value: 20, forcible: false content_by_lua_block { local val, flags local dogs = ngx.shared.dogs - local value, err = dogs:incr("foo", 10, "bar") + local value, err = dogs:incr("foo", 10, nil, "bar") if not ok then ngx.say("failed to incr: ", err) end