summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-09-08 05:32:40 +0000
committerLaurent Bercot <ska@appnovation.com>2023-09-08 05:32:40 +0000
commit9efa646c7fb520747804acdc829b3cccea0dce63 (patch)
tree8b98fc5da073f75d6ceea7bee433bb1f056843f5
parent9f03a9a73f35b998ea5d923dcdcea087e5712858 (diff)
downloads6-networking-9efa646c7fb520747804acdc829b3cccea0dce63.tar.xz
New versions of s6-tcpserver4d and s6-tcpserver6d
- both now use posix_spawn when available - s6-tcpserver4d uses avltree for logarithmic lookups - s6-tcpserver6d still has the linear lookup - the point was to benchmark linear vs logarithmic, but the fork() overhead overshadowed everything - now with fork() out of the way, I'm going back to benchmarks Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--package/deps.mak5
-rw-r--r--src/conn-tools/deps-exe/s6-tcpserver4d1
-rw-r--r--src/conn-tools/deps-exe/s6-tcpserver6d1
-rw-r--r--src/conn-tools/s6-tcpserver4d.c245
-rw-r--r--src/conn-tools/s6-tcpserver6d.c69
5 files changed, 166 insertions, 155 deletions
diff --git a/package/deps.mak b/package/deps.mak
index 4227dd5..0ba4787 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -20,6 +20,7 @@ src/conn-tools/s6-tcpserver4d.o src/conn-tools/s6-tcpserver4d.lo: src/conn-tools
src/conn-tools/s6-tcpserver6-socketbinder.o src/conn-tools/s6-tcpserver6-socketbinder.lo: src/conn-tools/s6-tcpserver6-socketbinder.c
src/conn-tools/s6-tcpserver6.o src/conn-tools/s6-tcpserver6.lo: src/conn-tools/s6-tcpserver6.c src/include/s6-networking/config.h
src/conn-tools/s6-tcpserver6d.o src/conn-tools/s6-tcpserver6d.lo: src/conn-tools/s6-tcpserver6d.c
+src/conn-tools/tcpserverd_spawn.o src/conn-tools/tcpserverd_spawn.lo: src/conn-tools/tcpserverd_spawn.c src/conn-tools/tcpserverd-internal.h
src/libs6net/s6net_ident_client.o src/libs6net/s6net_ident_client.lo: src/libs6net/s6net_ident_client.c src/include/s6-networking/ident.h
src/libs6net/s6net_ident_error.o src/libs6net/s6net_ident_error.lo: src/libs6net/s6net_ident_error.c src/include/s6-networking/ident.h
src/libs6net/s6net_ident_reply_get.o src/libs6net/s6net_ident_reply_get.lo: src/libs6net/s6net_ident_reply_get.c src/include/s6-networking/ident.h
@@ -127,13 +128,13 @@ s6-tcpserver4: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
s6-tcpserver4: src/conn-tools/s6-tcpserver4.o
s6-tcpserver4-socketbinder: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
s6-tcpserver4-socketbinder: src/conn-tools/s6-tcpserver4-socketbinder.o
-s6-tcpserver4d: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
+s6-tcpserver4d: EXTRA_LIBS := -ls6 -lskarnet ${SOCKET_LIB}
s6-tcpserver4d: src/conn-tools/s6-tcpserver4d.o
s6-tcpserver6: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
s6-tcpserver6: src/conn-tools/s6-tcpserver6.o
s6-tcpserver6-socketbinder: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
s6-tcpserver6-socketbinder: src/conn-tools/s6-tcpserver6-socketbinder.o
-s6-tcpserver6d: EXTRA_LIBS := -lskarnet ${SOCKET_LIB}
+s6-tcpserver6d: EXTRA_LIBS := -ls6 -lskarnet ${SOCKET_LIB}
s6-tcpserver6d: src/conn-tools/s6-tcpserver6d.o
ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
libs6net.a.xyzzy: src/libs6net/s6net_ident_client.o src/libs6net/s6net_ident_reply_get.o src/libs6net/s6net_ident_reply_parse.o src/libs6net/s6net_ident_error.o
diff --git a/src/conn-tools/deps-exe/s6-tcpserver4d b/src/conn-tools/deps-exe/s6-tcpserver4d
index 19869b2..062999f 100644
--- a/src/conn-tools/deps-exe/s6-tcpserver4d
+++ b/src/conn-tools/deps-exe/s6-tcpserver4d
@@ -1,2 +1,3 @@
+-ls6
-lskarnet
${SOCKET_LIB}
diff --git a/src/conn-tools/deps-exe/s6-tcpserver6d b/src/conn-tools/deps-exe/s6-tcpserver6d
index 19869b2..062999f 100644
--- a/src/conn-tools/deps-exe/s6-tcpserver6d
+++ b/src/conn-tools/deps-exe/s6-tcpserver6d
@@ -1,2 +1,3 @@
+-ls6
-lskarnet
${SOCKET_LIB}
diff --git a/src/conn-tools/s6-tcpserver4d.c b/src/conn-tools/s6-tcpserver4d.c
index 4c1edf2..8dd6614 100644
--- a/src/conn-tools/s6-tcpserver4d.c
+++ b/src/conn-tools/s6-tcpserver4d.c
@@ -9,9 +9,11 @@
#include <fcntl.h>
#include <signal.h>
-#include <skalibs/gccattributes.h>
-#include <skalibs/allreadwrite.h>
+#include <skalibs/posixplz.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
#include <skalibs/types.h>
+#include <skalibs/allreadwrite.h>
#include <skalibs/sgetopt.h>
#include <skalibs/strerr.h>
#include <skalibs/fmtscan.h>
@@ -22,33 +24,38 @@
#include <skalibs/selfpipe.h>
#include <skalibs/iopause.h>
#include <skalibs/socket.h>
-#include <skalibs/exec.h>
+#include <skalibs/genset.h>
+#include <skalibs/avltreen.h>
+
+#include <s6/ucspiserver.h>
-#define ABSOLUTE_MAXCONN 1000
+#define ABSOLUTE_MAXCONN 16384
#define USAGE "s6-tcpserver4d [ -v verbosity ] [ -1 ] [ -c maxconn ] [ -C localmaxconn ] prog..."
-typedef struct pidip_s pidip_t, *pidip_t_ref ;
-struct pidip_s
+typedef struct pidi_s pidi, *pidi_ref ;
+struct pidi_s
{
- pid_t left ;
- uint32_t right ;
+ pid_t pid ;
+ uint32_t i ;
} ;
-static unsigned int maxconn = 40 ;
-static unsigned int localmaxconn = 40 ;
-static unsigned int verbosity = 1 ;
+static uint32_t maxconn = 40 ;
+static uint32_t localmaxconn = 40 ;
+static uint32_t verbosity = 1 ;
static int cont = 1 ;
-static pidip_t *pidip = 0 ;
-static unsigned int numconn = 0 ;
-static diuint32 *ipnum = 0 ;
-static unsigned int iplen = 0 ;
-static char fmtmaxconn[UINT_FMT+1] = "/" ;
-static char fmtlocalmaxconn[UINT_FMT+1] = "/" ;
+static genset *pidis ;
+#define PIDI(i) genset_p(pidi, pidis, (i))
+#define numconn genset_n(pidis)
+static genset *ipnums ;
+#define IPNUM(i) genset_p(diuint32, ipnums, (i))
+static avltreen *by_ip ;
+static avltreen *by_pid ;
+static char fmtmaxconn[UINT32_FMT+1] = "/" ;
+static char fmtlocalmaxconn[UINT32_FMT+1] = "/" ;
- /* Utility functions */
static inline void dieusage ()
{
@@ -60,25 +67,33 @@ static inline void X (void)
strerr_dief1x(101, "internal inconsistency. Please submit a bug-report.") ;
}
-
- /* Lookup primitives */
-
-static inline unsigned int lookup_pid (pid_t pid)
+static void *bypid_dtok (uint32_t d, void *aux)
{
- unsigned int i = 0 ;
- for (; i < numconn ; i++) if (pid == pidip[i].left) break ;
- return i ;
+ genset *g = aux ;
+ return &genset_p(pidi, g, d)->pid ;
}
-static inline unsigned int lookup_ip (uint32_t ip)
+static int bypid_cmp (void const *a, void const *b, void *aux)
{
- unsigned int i = 0 ;
- for (; i < iplen ; i++) if (ip == ipnum[i].left) break ;
- return i ;
+ (void)aux ;
+ pid_t aa = *(pid_t const *)a ;
+ pid_t bb = *(pid_t const *)b ;
+ return aa < bb ? -1 : aa > bb ;
}
+static void *byip_dtok (uint32_t d, void *aux)
+{
+ genset *g = aux ;
+ return &genset_p(diuint32, g, d)->left ;
+}
- /* Logging */
+static int byip_cmp (void const *a, void const *b, void *aux)
+{
+ (void)aux ;
+ uint32_t aa = *(uint32_t const *)a ;
+ uint32_t bb = *(uint32_t const *)b ;
+ return aa < bb ? -1 : aa > bb ;
+}
static inline void log_start (void)
{
@@ -97,28 +112,28 @@ static void log_status (void)
strerr_warni3x("status: ", fmt, fmtmaxconn) ;
}
-static inline void log_deny (uint32_t ip, uint16_t port, unsigned int num)
+static inline void log_deny (uint32_t ip, uint16_t port, uint32_t num)
{
char fmtip[UINT32_FMT] ;
char fmtport[UINT16_FMT] ;
- char fmtnum[UINT_FMT] ;
+ char fmtnum[UINT32_FMT] ;
fmtip[ip4_fmtu32(fmtip, ip)] = 0 ;
fmtport[uint16_fmt(fmtport, port)] = 0 ;
- fmtnum[uint_fmt(fmtnum, num)] = 0 ;
+ fmtnum[uint32_fmt(fmtnum, num)] = 0 ;
strerr_warni7sys("deny ", fmtip, ":", fmtport, " count ", fmtnum, fmtlocalmaxconn) ;
}
-static inline void log_accept (pid_t pid, uint32_t ip, uint16_t port, unsigned int num)
+static inline void log_accept (pid_t pid, uint32_t ip, uint16_t port, uint32_t num)
{
char fmtipport[IP4_FMT + UINT16_FMT + 1] ;
char fmtpid[PID_FMT] ;
- char fmtnum[UINT_FMT] ;
+ char fmtnum[UINT32_FMT] ;
size_t n ;
n = ip4_fmtu32(fmtipport, ip) ;
fmtipport[n++] = ':' ;
n += uint16_fmt(fmtipport + n, port) ;
fmtipport[n] = 0 ;
- fmtnum[uint_fmt(fmtnum, num)] = 0 ;
+ fmtnum[uint32_fmt(fmtnum, num)] = 0 ;
fmtpid[pid_fmt(fmtpid, pid)] = 0 ;
strerr_warni7x("allow ", fmtipport, " pid ", fmtpid, " count ", fmtnum, fmtlocalmaxconn) ;
}
@@ -134,37 +149,42 @@ static inline void log_close (pid_t pid, uint32_t ip, int w)
strerr_warni6x("end pid ", fmtpid, " ip ", fmtip, WIFSIGNALED(w) ? " signal " : " exitcode ", fmtw) ;
}
-
- /* Signal handling */
+static int killthem_iter (void *data, void *aux)
+{
+ kill(((pidi *)data)->pid, *(int *)aux) ;
+ return 1 ;
+}
static void killthem (int sig)
{
- unsigned int i = 0 ;
- for (; i < numconn ; i++) kill(pidip[i].left, sig) ;
+ genset_iter(pidis, &killthem_iter, &sig) ;
}
static inline void wait_children (void)
{
for (;;)
{
- unsigned int i ;
- int w ;
- pid_t pid = wait_nohang(&w) ;
+ uint32_t d ;
+ int wstat ;
+ pid_t pid = wait_nohang(&wstat) ;
if (pid < 0)
if (errno != ECHILD) strerr_diefu1sys(111, "wait_nohang") ;
else break ;
else if (!pid) break ;
- i = lookup_pid(pid) ;
- if (i < numconn) /* it's one of ours ! */
+ if (avltreen_search(by_pid, &pid, &d))
{
- uint32_t ip = pidip[i].right ;
- unsigned int j = lookup_ip(ip) ;
- if (j >= iplen) X() ;
- if (!--ipnum[j].right) ipnum[j] = ipnum[--iplen] ;
- pidip[i] = pidip[--numconn] ;
+ uint32_t i = PIDI(d)->i ;
+ uint32_t ip = IPNUM(i)->left ;
+ avltreen_delete(by_pid, &pid) ;
+ genset_delete(pidis, d) ;
+ if (!--IPNUM(i)->right)
+ {
+ avltreen_delete(by_ip, &ip) ;
+ genset_delete(ipnums, i) ;
+ }
if (verbosity >= 2)
{
- log_close(pid, ip, w) ;
+ log_close(pid, ip, wstat) ;
log_status() ;
}
}
@@ -214,73 +234,63 @@ static inline void handle_signals (void)
}
}
-
- /* New connection handling */
-
-static inline void run_child (int, uint32_t, uint16_t, unsigned int, char const *const *) gccattr_noreturn ;
-static inline void run_child (int s, uint32_t ip, uint16_t port, unsigned int num, char const *const *argv)
-{
- char fmt[74] ;
- size_t n = 0 ;
- PROG = "s6-tcpserver4d (child)" ;
- if ((fd_move(1, s) < 0) || (fd_copy(0, 1) < 0))
- strerr_diefu1sys(111, "move fds") ;
- memcpy(fmt+n, "PROTO=TCP\0TCPREMOTEIP=", 22) ; n += 22 ;
- n += ip4_fmtu32(fmt+n, ip) ; fmt[n++] = 0 ;
- memcpy(fmt+n, "TCPREMOTEPORT=", 14) ; n += 14 ;
- n += uint16_fmt(fmt+n, port) ; fmt[n++] = 0 ;
- memcpy(fmt+n, "TCPCONNNUM=", 11) ; n += 11 ;
- n += uint_fmt(fmt+n, num) ; fmt[n++] = 0 ;
- xmexec_n(argv, fmt, n, 4) ;
-}
-
-static inline void new_connection (int s, uint32_t ip, uint16_t port, char const *const *argv)
+static inline void new_connection (int s, uint32_t ip, uint16_t port, char const *const *argv, char const *const *envp, size_t envlen)
{
- unsigned int i = lookup_ip(ip) ;
- unsigned int num = (i < iplen) ? ipnum[i].right : 0 ;
+ size_t m = 0 ;
pid_t pid ;
+ uint32_t d ;
+ uint32_t num = 0 ;
+ char fmt[47 + IP4_FMT + UINT16_FMT + UINT_FMT] ;
+
+ if (avltreen_search(by_ip, &ip, &d)) num = IPNUM(d)->right ;
if (num >= localmaxconn)
{
log_deny(ip, port, num) ;
return ;
}
- pid = fork() ;
- if (pid < 0)
+
+ memcpy(fmt + m, "PROTO=TCP\0TCPREMOTEIP=", 22) ; m += 22 ;
+ m += ip4_fmtu32(fmt + m, ip) ;
+ fmt[m++] = 0 ;
+ memcpy(fmt + m, "TCPREMOTEPORT=", 14) ; m += 14 ;
+ m += uint16_fmt(fmt + m, port) ; fmt[m++] = 0 ;
+ memcpy(fmt + m, "TCPCONNNUM=", 11) ; m += 11 ;
+ m += uint_fmt(fmt + m, num) ; fmt[m++] = 0 ;
+
+ pid = s6_ucspiserver_spawn(s, argv, envp, envlen, fmt, m, 4) ;
+ if (!pid)
{
- if (verbosity) strerr_warnwu1sys("fork") ;
+ if (verbosity) strerr_warnwu2sys("spawn ", argv[0]) ;
return ;
}
- else if (!pid)
- {
- selfpipe_finish() ;
- run_child(s, ip, port, num+1, argv) ;
- }
- if (i < iplen) ipnum[i].right = num + 1 ;
+ if (num) IPNUM(d)->right++ ;
else
{
- ipnum[iplen].left = ip ;
- ipnum[iplen++].right = 1 ;
+ d = genset_new(ipnums) ;
+ IPNUM(d)->left = ip ;
+ IPNUM(d)->right = 1 ;
+ avltreen_insert(by_ip, d) ;
}
- pidip[numconn].left = pid ;
- pidip[numconn++].right = ip ;
+
+ num = genset_new(pidis) ;
+ PIDI(num)->pid = pid ;
+ PIDI(num)->i = d ;
+ avltreen_insert(by_pid, num) ;
if (verbosity >= 2)
{
- log_accept(pid, ip, port, ipnum[i].right) ;
+ log_accept(pid, ip, port, IPNUM(d)->right) ;
log_status() ;
}
}
-
- /* And the main */
-
int main (int argc, char const *const *argv)
{
iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 0, .events = IOPAUSE_READ | IOPAUSE_EXCEPT } } ;
+ int flag1 = 0 ;
PROG = "s6-tcpserver4d" ;
{
subgetopt l = SUBGETOPT_ZERO ;
- int flag1 = 0 ;
for (;;)
{
int opt = subgetopt_r(argc, argv, "1c:C:v:", &l) ;
@@ -288,9 +298,9 @@ int main (int argc, char const *const *argv)
switch (opt)
{
case '1' : flag1 = 1 ; break ;
- case 'c' : if (!uint0_scan(l.arg, &maxconn)) dieusage() ; break ;
- case 'C' : if (!uint0_scan(l.arg, &localmaxconn)) dieusage() ; break ;
- case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
+ case 'c' : if (!uint320_scan(l.arg, &maxconn)) dieusage() ; break ;
+ case 'C' : if (!uint320_scan(l.arg, &localmaxconn)) dieusage() ; break ;
+ case 'v' : if (!uint320_scan(l.arg, &verbosity)) dieusage() ; break ;
default : dieusage() ;
}
}
@@ -301,7 +311,8 @@ int main (int argc, char const *const *argv)
if (fstat(0, &st) < 0) strerr_diefu1sys(111, "fstat stdin") ;
if (!S_ISSOCK(st.st_mode)) strerr_dief1x(100, "stdin is not a socket") ;
}
- if (coe(0) < 0) strerr_diefu1sys(111, "make socket close-on-exec") ;
+ if (coe(0) == -1 || ndelay_on(0) == -1)
+ strerr_diefu1sys(111, "set socket flags") ;
if (flag1)
{
if (fcntl(1, F_GETFD) < 0)
@@ -325,13 +336,40 @@ int main (int argc, char const *const *argv)
sigaddset(&set, SIGABRT) ;
if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ;
}
- fmtlocalmaxconn[1+uint_fmt(fmtlocalmaxconn+1, localmaxconn)] = 0 ;
+ fmtlocalmaxconn[1+uint32_fmt(fmtlocalmaxconn+1, localmaxconn)] = 0 ;
+ }
+
+ {
+ diuint32 ipnum_storage[maxconn] ;
+ uint32_t ipnum_freelist[maxconn] ;
+ avlnode byip_storage[maxconn] ;
+ uint32_t byip_freelist[maxconn] ;
+ pidi pidi_storage[maxconn] ;
+ uint32_t pidi_freelist[maxconn] ;
+ avlnode bypid_storage[maxconn] ;
+ uint32_t bypid_freelist[maxconn] ;
+ genset ipnum_info ;
+ genset pidi_info ;
+ avltreen byip_info ;
+ avltreen bypid_info ;
+ size_t envlen = env_len((char const *const *)environ) ;
+
+ GENSET_init(&ipnum_info, diuint32, ipnum_storage, ipnum_freelist, maxconn) ;
+ GENSET_init(&pidi_info, pidi, pidi_storage, pidi_freelist, maxconn) ;
+ avltreen_init(&byip_info, byip_storage, byip_freelist, maxconn, &byip_dtok, &byip_cmp, &ipnum_info) ;
+ avltreen_init(&bypid_info, bypid_storage, bypid_freelist, maxconn, &bypid_dtok, &bypid_cmp, &pidi_info) ;
+ ipnums = &ipnum_info ;
+ pidis = &pidi_info ;
+ by_ip = &byip_info ;
+ by_pid = &bypid_info ;
+
if (verbosity >= 2)
{
- fmtmaxconn[1+uint_fmt(fmtmaxconn+1, maxconn)] = 0 ;
+ fmtmaxconn[1+uint32_fmt(fmtmaxconn+1, maxconn)] = 0 ;
log_start() ;
log_status() ;
}
+
if (flag1)
{
uint16_t port ;
@@ -345,14 +383,9 @@ int main (int argc, char const *const *argv)
else m = uint16_fmt(fmtport, port) ;
fmtport[m++] = '\n' ;
allwrite(1, fmtport, m) ;
- fd_close(1) ;
+ close(1) ;
}
- }
- {
- pidip_t pidip_inyostack[maxconn] ;
- diuint32 ipnum_inyostack[maxconn] ;
- pidip = pidip_inyostack ; ipnum = ipnum_inyostack ;
while (cont)
{
if (iopause_g(x, 1 + (numconn < maxconn), 0) < 0) strerr_diefu1sys(111, "iopause") ;
@@ -366,7 +399,7 @@ int main (int argc, char const *const *argv)
char packedip[4] ;
uint16_t port ;
int fd = socket_accept4(x[1].fd, packedip, &port) ;
- if (fd < 0)
+ if (fd == -1)
{
if (verbosity) strerr_warnwu1sys("accept") ;
}
@@ -374,7 +407,7 @@ int main (int argc, char const *const *argv)
{
uint32_t ip ;
uint32_unpack_big(packedip, &ip) ;
- new_connection(fd, ip, port, argv) ;
+ new_connection(fd, ip, port, argv, (char const *const *)environ, envlen) ;
fd_close(fd) ;
}
}
diff --git a/src/conn-tools/s6-tcpserver6d.c b/src/conn-tools/s6-tcpserver6d.c
index b345d72..e3c66bd 100644
--- a/src/conn-tools/s6-tcpserver6d.c
+++ b/src/conn-tools/s6-tcpserver6d.c
@@ -9,7 +9,7 @@
#include <fcntl.h>
#include <signal.h>
-#include <skalibs/gccattributes.h>
+#include <skalibs/posixplz.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/types.h>
#include <skalibs/sgetopt.h>
@@ -21,9 +21,10 @@
#include <skalibs/selfpipe.h>
#include <skalibs/iopause.h>
#include <skalibs/socket.h>
-#include <skalibs/exec.h>
-#define ABSOLUTE_MAXCONN 1000
+#include <s6/ucspiserver.h>
+
+#define ABSOLUTE_MAXCONN 16384
#define USAGE "s6-tcpserver6d [ -v verbosity ] [ -1 ] [ -c maxconn ] [ -C localmaxconn ] prog..."
@@ -53,9 +54,6 @@ static unsigned int iplen = 0 ;
static char fmtmaxconn[UINT_FMT+1] = "/" ;
static char fmtlocalmaxconn[UINT_FMT+1] = "/" ;
-
- /* Utility functions */
-
static inline void dieusage ()
{
strerr_dieusage(100, USAGE) ;
@@ -66,9 +64,6 @@ static inline void X (void)
strerr_dief1x(101, "internal inconsistency. Please submit a bug-report.") ;
}
-
- /* Lookup primitives */
-
static inline unsigned int lookup_pid (pid_t pid)
{
unsigned int i = 0 ;
@@ -83,9 +78,6 @@ static inline unsigned int lookup_ip (char const *ip)
return i ;
}
-
- /* Logging */
-
static inline void log_start (void)
{
strerr_warni1x("starting") ;
@@ -140,9 +132,6 @@ static inline void log_close (pid_t pid, char const *ip, int w)
strerr_warni6x("end pid ", fmtpid, " ip ", fmtip, WIFSIGNALED(w) ? " signal " : " exitcode ", fmtw) ;
}
-
- /* Signal handling */
-
static void killthem (int sig)
{
unsigned int i = 0 ;
@@ -220,47 +209,33 @@ static inline void handle_signals (void)
}
}
-
- /* New connection handling */
-
-static inline void run_child (int, char const *, uint16_t, unsigned int, char const *const *) gccattr_noreturn ;
-static inline void run_child (int s, char const *ip, uint16_t port, unsigned int num, char const *const *argv)
-{
- char fmt[98] ;
- size_t n = 0 ;
- PROG = "s6-tcpserver6d (child)" ;
- if ((fd_move(1, s) < 0) || (fd_copy(0, 1) < 0))
- strerr_diefu1sys(111, "move fds") ;
- memcpy(fmt+n, "PROTO=TCP\0TCPREMOTEIP=", 22) ; n += 22 ;
- n += ip6_fmt(fmt+n, ip) ; fmt[n++] = 0 ;
- memcpy(fmt+n, "TCPREMOTEPORT=", 14) ; n += 14 ;
- n += uint16_fmt(fmt+n, port) ; fmt[n++] = 0 ;
- memcpy(fmt+n, "TCPCONNNUM=", 11) ; n += 11 ;
- n += uint_fmt(fmt+n, num) ; fmt[n++] = 0 ;
- xmexec_n(argv, fmt, n, 4) ;
-}
-
-static inline void new_connection (int s, char const *ip, uint16_t port, char const *const *argv)
+static inline void new_connection (int s, char const *ip, uint16_t port, char const *const *argv, char const *const *envp, size_t envlen)
{
+ pid_t pid ;
unsigned int i = lookup_ip(ip) ;
unsigned int num = (i < iplen) ? ipnum[i].num : 0 ;
- pid_t pid ;
+ size_t m = 0 ;
+ char fmt[47 + IP6_FMT + UINT16_FMT + UINT_FMT] ;
+
if (num >= localmaxconn)
{
log_deny(ip, port, num) ;
return ;
}
- pid = fork() ;
- if (pid < 0)
+
+ memcpy(fmt + m, "PROTO=TCP\0TCPREMOTEIP=", 22) ; m += 22 ;
+ m += ip6_fmt(fmt + m, ip) ; fmt[m++] = 0 ;
+ memcpy(fmt + m, "TCPREMOTEPORT=", 14) ; m += 14 ;
+ m += uint16_fmt(fmt + m, port) ; fmt[m++] = 0 ;
+ memcpy(fmt + m, "TCPCONNNUM=", 11) ; m += 11 ;
+ m += uint_fmt(fmt + m, num) ; fmt[m++] = 0 ;
+
+ pid = s6_ucspiserver_spawn(s, argv, envp, envlen, fmt, m, 4) ;
+ if (!pid)
{
- if (verbosity) strerr_warnwu1sys("fork") ;
+ if (verbosity) strerr_warnwu2sys("spawn ", argv[0]) ;
return ;
}
- else if (!pid)
- {
- selfpipe_finish() ;
- run_child(s, ip, port, num+1, argv) ;
- }
if (i < iplen) ipnum[i].num = num + 1 ;
else
@@ -277,7 +252,6 @@ static inline void new_connection (int s, char const *ip, uint16_t port, char co
}
}
-
int main (int argc, char const *const *argv)
{
iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 0, .events = IOPAUSE_READ | IOPAUSE_EXCEPT } } ;
@@ -356,6 +330,7 @@ int main (int argc, char const *const *argv)
{
pidip_t pidip_inyostack[maxconn] ;
ipnum_t ipnum_inyostack[maxconn] ;
+ size_t envlen = env_len((char const *const *)environ) ;
pidip = pidip_inyostack ; ipnum = ipnum_inyostack ;
while (cont)
@@ -379,7 +354,7 @@ int main (int argc, char const *const *argv)
}
else
{
- new_connection(fd, ip, port, argv) ;
+ new_connection(fd, ip, port, argv, (char const *const *)environ, envlen) ;
fd_close(fd) ;
}
}