[melbourne-pug] Spawn new process to handle inbound websocket connection

Andrew Stuart andrew.stuart at supercoders.com.au
Thu Jul 26 02:11:05 EDT 2018


Thanks to Tim and Rory and Ben Finney who all chipped in with ideas.

Just to follow through, here’s the solution I put together in the end.  It spawns a netcat process in response to a POST request (Python 3.6). I managed to avoid implementing a queueing system and lots of file juggling.  It’s just plain TCP sockets, not websockets.  

Send this to get a new netcat process spawned on a port:
curl -X POST -H "Content-Type: text/plain" --data ‘example data'  localhost:8000


from http.server import HTTPServer, BaseHTTPRequestHandler
import socket
import os
import io

host = '0.0.0.0'
port = 8000

def find_free_port():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('', 0))
        return s.getsockname()[1]

def spawn_netcat(port):
    command = "/bin/nc"
    params = f"nc -l {port}"
    spawnDaemon(command, params.split())

def spawnDaemon(path_to_executable, params):

    # Do first fork
    pid = os.fork()
    if (pid != 0):
        os.waitid(os.P_PID, pid, os.WEXITED)
        return
        
    # Decouple from parent environment
    os.chdir("/opt")
    os.setsid()
    os.umask(0)

    # Do second fork
    pid = os.fork()
    if (pid != 0):
        os._exit(0)

    # exec this process into netcat.....
    os.execv(path_to_executable, params)

class Server(BaseHTTPRequestHandler):

    def do_POST(self):
        netcat_listen_port = find_free_port()
        spawn_netcat(netcat_listen_port)
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        response = io.BytesIO()
        response.write(str(netcat_listen_port).encode())
        self.wfile.write(response.getvalue())

if __name__ == "__main__":
    httpd = HTTPServer((host, port), Server)
    httpd.serve_forever()








More information about the melbourne-pug mailing list