Add OnServerListen hook to configure listen() (#459)

This commit is contained in:
Paul Kulchenko 2022-07-08 07:17:25 -07:00 committed by GitHub
parent 11ac8f11a9
commit a18044c504
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 6 deletions

View file

@ -501,7 +501,7 @@ HOOKS
OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
If this function is defined it'll be called from the main process
each time redbean accepts a new client connection. If it returns
true then redbean will close the connection without calling fork.
`true`, redbean will close the connection without calling fork.
OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
If this function is defined it'll be called from the main process
@ -517,6 +517,12 @@ HOOKS
each time redbean reaps a child connection process using wait4().
This won't be called in uniprocess mode.
OnServerListen(socketdescriptor:int,serverip:int,serverport:int) → bool
If this function is defined it'll be called from the main process
before redbean starts listening on a port. This hook can be used
to modify socket configuration to set `SO_REUSEPORT`, for example.
If it returns `true`, redbean will not listen to that ip/port.
OnServerStart()
If this function is defined it'll be called from the main process
right before the main event loop starts.

View file

@ -1080,8 +1080,8 @@ static bool LuaEvalFile(const char *path) {
}
static bool LuaOnClientConnection(void) {
bool dropit = false;
#ifndef STATIC
bool dropit;
uint32_t ip, serverip;
uint16_t port, serverport;
lua_State *L = GL;
@ -1096,14 +1096,11 @@ static bool LuaOnClientConnection(void) {
dropit = lua_toboolean(L, -1);
} else {
LogLuaError("OnClientConnection", lua_tostring(L, -1));
dropit = false;
}
lua_pop(L, 1); // pop result or error
AssertLuaStackIsAt(L, 0);
return dropit;
#else
return false;
#endif
return dropit;
}
static void LuaOnProcessCreate(int pid) {
@ -1127,6 +1124,25 @@ static void LuaOnProcessCreate(int pid) {
#endif
}
static bool LuaOnServerListen(int fd, uint32_t ip, uint16_t port) {
bool nouse = false;
#ifndef STATIC
lua_State *L = GL;
lua_getglobal(L, "OnServerListen");
lua_pushinteger(L, fd);
lua_pushinteger(L, ip);
lua_pushinteger(L, port);
if (LuaCallWithTrace(L, 3, 1, NULL) == LUA_OK) {
nouse = lua_toboolean(L, -1);
} else {
LogLuaError("OnServerListen", lua_tostring(L, -1));
}
lua_pop(L, 1); // pop result or error
AssertLuaStackIsAt(L, 0);
#endif
return nouse;
}
static void LuaOnProcessDestroy(int pid) {
#ifndef STATIC
lua_State *L = GL;
@ -6913,6 +6929,7 @@ static void Listen(void) {
char ipbuf[16];
size_t i, j, n;
uint32_t ip, port, addrsize, *ifs, *ifp;
bool hasonserverlisten = IsHookDefined("OnServerListen");
if (!ports.n) {
ProgramPort(8080);
}
@ -6939,6 +6956,12 @@ static void Listen(void) {
IPPROTO_TCP, true, &timeout)) == -1) {
DIEF("(srvr) socket: %m");
}
if (hasonserverlisten &&
LuaOnServerListen(servers.p[n].fd, ips.p[i], ports.p[j])) {
n--; // skip this server instance
continue;
}
if (bind(servers.p[n].fd, &servers.p[n].addr,
sizeof(servers.p[n].addr)) == -1) {
DIEF("(srvr) bind error: %m: %hhu.%hhu.%hhu.%hhu:%hu", ips.p[i] >> 24,