The UCSPI-TCP way
There are toolsets other than netcat. Here are how to use a few of them. They all presume the existence of a service script that runs your func, whatever that may be:
#!/bin/sh
while read -r MESSAGE
do
echo 1>&2 "${TCPREMOTEIP}" "${TCPREMOTEPORT}" rx "${MESSAGE}"
func
done
The TCPREMOTEIP and TCPREMOTEPORT environment variables are defined by the UCSPI-TCP protocol.
The script is spawned as an individual process per TCP connection using the various toolsets. In what follows, the tools are shown as used within a short script. Such a script, conventionally named run, is how one would run them under a daemontools-family service manager. They can of course be invoked directly.
Bernstein ucspi-tcp
With Daniel J. Bernstein's ucspi-tcp, tcpserver spawns the service script:
#!/bin/sh -e
exec tcpserver -v -P -R -H -l 0 0.0.0.0 7777 ./service
There are IPv6-capable enhanced versions of Bernstein ucspi-tcp. With Erwin Hoffman's, tcpserver attempts to handle both IPv4 and IPv6 in one (if the operating system supports this, a few do not) and spawns the service script:
#!/bin/sh -e
exec tcpserver -v -P -R -H -l 0 ::0 7777 ./service
Bercot s6-networking, s6, and execline
With Laurent Bercot's s6-networking, s6-tcpserver4 and s6-tcpserver6 handle IPv4 and IPv6 separately, and spawn the service script:
#!/command/execlineb
s6-tcpserver4 -v 0.0.0.0 7777
./service
#!/command/execlineb
s6-tcpserver6 -v ::0 7777
./service
One can build up more complex servers by interposing tools such as s6-tcpserver-access and s6-applyuidgid in the chain immediately before ./service.
nosh UCSPI tools
With the nosh toolset, tcp-socket-listen listens on the TCP socket, again handling IPv4 and IPv6 simulataneously if the operating system supports doing so, and chains to tcp-socket-accept which in turn spawns the service script:
#!/bin/nosh
tcp-socket-listen --combine4and6 :: 7777
tcp-socket-accept --verbose --localname 0
./service
Or one runs two separate processes, on operating systems such as OpenBSD:
#!/bin/nosh
tcp-socket-listen 0.0.0.0 7777
tcp-socket-accept --verbose --localname 0
./service
#!/bin/nosh
tcp-socket-listen :: 7777
tcp-socket-accept --verbose --localname ::
./service
One can build up more complex servers by interposing tools such as ucspi-socket-rules-check and setuidgid in the chain.
#!/bin/nosh
tcp-socket-listen --combine4and6 :: 7777
setuidgid unprivileged-user
tcp-socket-accept --verbose --localname 0
ucspi-socket-rules-check --verbose
./service
Pape ipsvd
With Gerrit Pape's ipsvd, tcpsvd spawns the service script:
#!/bin/sh -e
exec tcpsvd -v 0.0.0.0 7777 ./service
UCSPI-UDP
The common service script can handle when standard input is a stream socket. But you didn't specify TCP explicitly.
Although some of the aforementioned toolkits can be used to build UDP servers in similar fashion to how one can use them to build TCP servers (c.f. udp-socket-listen in nosh), it's tricky to build the actual service program with shell script, as the shell's builtins do not necessarily cope well when standard input is a datagram socket.
Further reading
- Protocol:
- toolsets:
- Daniel J. Bernstein. ucspi-tcp. cr.yp.to.
- s6-networking. Laurent Bercot. skarnet.org.
- s6. Laurent Bercot. skarnet.org.
- Jonathan de Boyne Pollard (2016). nosh. Softwares.
- ipsvd. Gerrit Pape. smarden.org.
- reference manuals: