[mod_magnet] lighty.server.* table w/ new function

(experimental)

(new interfaces are unstable and may change)
master
Glenn Strauss 9 months ago
parent 1118a8af61
commit beb029d6e2

@ -195,6 +195,7 @@ struct server {
pid_t pid;
int stdin_fd;
const buffer *default_server_tag;
char **argv;
#ifdef HAVE_PCRE2_H
void *match_data; /*(shared and reused)*/

@ -9,6 +9,7 @@
#include "buffer.h"
#include "chunk.h"
#include "ck.h"
#include "h2.h"
#include "http_chunk.h"
#include "http_etag.h"
#include "http_header.h"
@ -2290,6 +2291,118 @@ magnet_request_table (lua_State * const L, request_st ** const rr)
lua_setmetatable(L, -2); /* tie the metatable to r (sp -= 1) */
}
static int
magnet_request_iter (lua_State *L)
{
/* upvalue 1: (connection *) in linked list
* upvalue 2: index into h2con->r[]
* upvalue 3: request userdata
* upvalue 4: request table (references r in userdata) */
connection *con = lua_touserdata(L, lua_upvalueindex(1));
/* skip over HTTP/2 connections with no active requests */
while (con && con->h2 && 0 == con->h2->rused)
con = con->next;
if (NULL == con)
return 0;
/* set (request_st *)r */
int32_t i = -1;
if (con->h2) {
/* get index into h2con->r[] */
i = lua_tointeger(L, lua_upvalueindex(2));
/* set (request_st *)r in userdata */
if (-1 == i)
*(request_st **)lua_touserdata(L,lua_upvalueindex(3))=&con->request;
else
*(request_st **)lua_touserdata(L,lua_upvalueindex(3))=con->h2->r[i];
/* step to next index into h2con->r[] */
if ((uint32_t)++i == con->h2->rused)
i = -1;
lua_pushinteger(L, i);
lua_replace(L, lua_upvalueindex(2));
}
else {
/* set (request_st *) in userdata */
*(request_st **)lua_touserdata(L, lua_upvalueindex(3)) = &con->request;
}
if (-1 == i) {
/* step to next connection */
con = con->next;
lua_pushlightuserdata(L, con);
lua_replace(L, lua_upvalueindex(1));
}
/* return request object (which references (request_st *)r in userdata) */
lua_pushvalue(L, lua_upvalueindex(4));
return 1;
}
static int
magnet_irequests (lua_State *L)
{
/* NB: iterator request object *is invalid* outside of iteration
* For efficiency, r is stored in userdata as upvalue to iteration
* and is invalid (and may be cleaned up) outside of iterator loop.
* A C pointer into userdata is stored in iterator request object methods.
* The iterator request object is *reused* for each iteration loop and the
* upvalue to the userdata is changed each iteration to point to next r.
* The iterator request object *must not* be saved for use outside
* the iteration loop. Extract data that must be saved and store data
* in a persistent object if data is to be used outside iterator loop.
* (Were it desirable to produce a persistent request object for use outside
* the iteration loop, a future enhancement would be to add a method such
* as lighty.server.irequests_clone(r) which creates a new request object
* pointing into a new userdata, and saving that new userdata in the new
* request object table as '_r_userdata')
* NB: iterator request objects should generally be treated read-only.
* Modifications may in some cases be unsafe and cause lighttpd to crash. */
request_st *r = magnet_get_request(L);
lua_pushlightuserdata(L, r->con->srv->conns);
lua_pushinteger(L, -1);
request_st ** const r_userdata =
(request_st **)lua_newuserdata0(L, sizeof(request_st *));
magnet_request_table(L, r_userdata);
lua_pushcclosure(L, magnet_request_iter, 4);
return 1;
}
static int
magnet_server_stats_get (lua_State *L)
{
size_t klen;
const char * const k = luaL_checklstring(L, 2, &klen);
const request_st * const r = magnet_get_request(L);
const server * const srv = r->con->srv;
switch (klen) {
case 6:
if (0 == memcmp(k, "uptime", 6)) {
lua_pushinteger(L, (lua_Integer)(log_epoch_secs - srv->startup_ts));
return 1;
}
break;
case 7:
if (0 == memcmp(k, "version", 7)) {
lua_pushlstring(L, BUF_PTR_LEN(srv->default_server_tag));
return 1;
}
break;
case 12:
/*(could calculate from irequests: ++count on remote-addr/port change)*/
if (0 == memcmp(k, "clients_open", 12)) {
lua_pushinteger(L, (lua_Integer)
(srv->srvconf.max_conns - srv->lim_conns));
return 1;
}
break;
default:
break;
}
return luaL_error(L, "server.stats['%s'] invalid", k);
}
__attribute_cold__
static void
magnet_req_header_metatable (lua_State * const L)
@ -2422,6 +2535,40 @@ magnet_plugin_stats_table (lua_State * const L)
lua_setmetatable(L, -2); /* (sp -= 1) */
}
__attribute_cold__
static void
magnet_server_stats_table (lua_State * const L)
{
lua_createtable(L, 0, 0); /* {} (sp += 1) */
lua_createtable(L, 0, 3); /* metatable for stats (sp += 1) */
lua_pushcfunction(L, magnet_server_stats_get); /* (sp += 1) */
lua_setfield(L, -2, "__index"); /* (sp -= 1) */
lua_pushcfunction(L, magnet_newindex_readonly); /* (sp += 1) */
lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
lua_pushboolean(L, 0); /* (sp += 1) */
lua_setfield(L, -2, "__metatable"); /* protect metatable (sp -= 1) */
lua_setmetatable(L, -2); /* (sp -= 1) */
}
__attribute_cold__
static void
magnet_server_table (lua_State * const L)
{
lua_createtable(L, 0, 3); /* {} (sp += 1) */
lua_pushcfunction(L, magnet_irequests); /* (sp += 1) */
lua_setfield(L, -2, "irequests"); /* iterate over requests (sp -= 1) */
magnet_plugin_stats_table(L); /* (sp += 1) */
lua_setfield(L, -2, "plugin_stats"); /* (sp -= 1) */
magnet_server_stats_table(L); /* (sp += 1) */
lua_setfield(L, -2, "stats"); /* (sp -= 1) */
lua_createtable(L, 0, 2); /* metatable for server table (sp += 1) */
lua_pushcfunction(L, magnet_newindex_readonly); /* (sp += 1) */
lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
lua_pushboolean(L, 0); /* (sp += 1) */
lua_setfield(L, -2, "__metatable"); /* protect metatable (sp -= 1) */
lua_setmetatable(L, -2); /* tie the metatable to server (sp -= 1) */
}
__attribute_cold__
static void
magnet_script_setup_global_state (lua_State * const L)
@ -2459,6 +2606,7 @@ magnet_init_lighty_table (lua_State * const L, request_st **rr)
*
* lighty.r.* HTTP request object methods
* lighty.c.* lighttpd C methods callable from lua
* lighty.server.* lighttpd server object methods
*
* (older interface)
*
@ -2481,6 +2629,9 @@ magnet_init_lighty_table (lua_State * const L, request_st **rr)
magnet_request_table(L, rr); /* lighty.r (sp += 1) */
lua_setfield(L, -2, "r"); /* lighty.r = {} (sp -= 1) */
magnet_server_table(L); /* lighty.server (sp += 1) */
lua_setfield(L, -2, "server"); /* server = {} (sp -= 1) */
/* compatibility with previous mod_magnet interfaces in top of lighty.* */
lua_getfield(L, -1, "r"); /* (sp += 1) */
/* alias lighty.request -> lighty.r.req_header */
@ -2494,12 +2645,16 @@ magnet_init_lighty_table (lua_State * const L, request_st **rr)
lua_setfield(L, -3, "req_env"); /* req_env = {} (sp -= 1) */
lua_pop(L, 1); /* (sp -= 1) */
magnet_plugin_stats_table(L); /* (sp += 1) */
lua_setfield(L, -2, "status"); /* status = {} (sp -= 1) */
/* alias lighty.server.stats -> lighty.status */
lua_getfield(L, -1, "server"); /* (sp += 1) */
lua_getfield(L, -1, "plugin_stats"); /* (sp += 1) */
lua_setfield(L, -3, "status"); /* status = {} (sp -= 1) */
lua_pop(L, 1); /* (sp -= 1) */
lua_pushinteger(L, MAGNET_RESTART_REQUEST);
lua_setfield(L, -2, "RESTART_REQUEST");
/* alias lighty.c.stat -> lighty.stat */
lua_pushcfunction(L, magnet_stat); /* (sp += 1) */
lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */

@ -328,6 +328,7 @@ static server *server_init(void) {
srv->loadavg[1] = 0.0;
srv->loadavg[2] = 0.0;
srv->stdin_fd = -1;
srv->default_server_tag = &default_server_tag;
log_con_jqueue = (connection *)(uintptr_t)&log_con_jqueue;/*(sentinel)*/

Loading…
Cancel
Save