diff --git a/other/websocket.c b/other/websocket.c index 5160bc7..1ad2c70 100644 --- a/other/websocket.c +++ b/other/websocket.c @@ -740,6 +740,47 @@ void start_server() { printf("Waiting for connections on %s:%d\n", settings.listen_host, settings.listen_port); + + + if (settings.single_shot) { + clilen = sizeof(cli_addr); + pipe_error = 0; + pid = 0; + csock = accept(lsock, + (struct sockaddr *) &cli_addr, + &clilen); + if (csock < 0) { + error("ERROR on accept"); + goto CLEANUP; + } + handler_msg("got client connection from %s\n", + inet_ntoa(cli_addr.sin_addr)); + + + ws_ctx = do_handshake(csock); + if (ws_ctx == NULL) { + handler_msg("No connection after handshake\n"); + goto CLEANUP; + } + + settings.handler(ws_ctx); + if (pipe_error) { + handler_emsg("Closing due to SIGPIPE\n"); + } + + CLEANUP: + if (ws_ctx) { + ws_socket_free(ws_ctx); + free_ws_ctx(ws_ctx); + } else { + shutdown(csock, SHUT_RDWR); + close(csock); + } + handler_msg("handler exit\n"); + exit(0); + } + + while (1) { clilen = sizeof(cli_addr); pipe_error = 0; @@ -754,24 +795,25 @@ void start_server() { handler_msg("got client connection from %s\n", inet_ntoa(cli_addr.sin_addr)); - handler_msg("forking handler process\n"); - pid = fork(); + handler_msg("forking handler process\n"); - if (pid == 0) { // handler process - ws_ctx = do_handshake(csock); - if (ws_ctx == NULL) { - handler_msg("No connection after handshake\n"); - break; // Child process exits - } + pid = fork(); - settings.handler(ws_ctx); - if (pipe_error) { - handler_emsg("Closing due to SIGPIPE\n"); - } - break; // Child process exits - } else { // parent process - settings.handler_id += 1; - } + if (pid == 0) { // handler process + ws_ctx = do_handshake(csock); + if (ws_ctx == NULL) { + handler_msg("No connection after handshake\n"); + break; // Child process exits + } + + settings.handler(ws_ctx); + if (pipe_error) { + handler_emsg("Closing due to SIGPIPE\n"); + } + break; // Child process exits + } else { // parent process + settings.handler_id += 1; + } } if (pid == 0) { if (ws_ctx) { diff --git a/other/websocket.h b/other/websocket.h index 8062da7..3af8a5d 100644 --- a/other/websocket.h +++ b/other/websocket.h @@ -61,6 +61,7 @@ typedef struct { char *key; int ssl_only; int daemon; + int single_shot; } settings_t; diff --git a/other/websockify.c b/other/websockify.c index f8e6bcb..daddeb6 100644 --- a/other/websockify.c +++ b/other/websockify.c @@ -35,6 +35,7 @@ char USAGE[] = "Usage: [options] " \ "[source_addr:]source_port target_addr:target_port\n\n" \ " --verbose|-v verbose messages and per frame traffic\n" \ " --daemon|-D become a daemon (background process)\n" \ + " --single-shot|-S Only accept one connect, then exit when it's gone\n" \ " --cert CERT SSL certificate file\n" \ " --key KEY SSL key file (if separate from cert)\n" \ " --ssl-only disallow non-encrypted connections"; @@ -273,12 +274,13 @@ void proxy_handler(ws_ctx_t *ws_ctx) { int main(int argc, char *argv[]) { int fd, c, option_index = 0; - static int ssl_only = 0, daemon = 0, verbose = 0; + static int ssl_only = 0, daemon = 0, verbose = 0, single_shot = 0; char *found; static struct option long_options[] = { {"verbose", no_argument, &verbose, 'v'}, {"ssl-only", no_argument, &ssl_only, 1 }, {"daemon", no_argument, &daemon, 'D'}, + {"single-shot",no_argument, &single_shot,'S'}, /* ---- */ {"cert", required_argument, 0, 'c'}, {"key", required_argument, 0, 'k'}, @@ -293,7 +295,7 @@ int main(int argc, char *argv[]) settings.key = ""; while (1) { - c = getopt_long (argc, argv, "vDc:k:", + c = getopt_long (argc, argv, "vDSc:k:", long_options, &option_index); /* Detect the end */ @@ -310,6 +312,9 @@ int main(int argc, char *argv[]) case 'D': daemon = 1; break; + case 'S': + single_shot = 1; + break; case 'c': settings.cert = realpath(optarg, NULL); if (! settings.cert) { @@ -329,6 +334,7 @@ int main(int argc, char *argv[]) settings.verbose = verbose; settings.ssl_only = ssl_only; settings.daemon = daemon; + settings.single_shot = single_shot; if ((argc-optind) != 2) { usage("Invalid number of arguments\n");