From b2cda1d68ca6de2c372cf132af536a726a7a80ee Mon Sep 17 00:00:00 2001 From: Shuanglei Tao Date: Tue, 10 Aug 2021 22:20:56 +0800 Subject: [PATCH] drop libwebsockets < 3.2.0 support --- .clang-format | 7 +- .github/workflows/backend.yml | 2 +- CMakeLists.txt | 13 +-- src/http.c | 16 +-- src/protocol.c | 42 +++----- src/pty.c | 55 +++++----- src/pty.h | 6 +- src/server.c | 195 +++++++++++++--------------------- src/server.h | 2 +- src/utils.c | 144 ++++++++++++------------- 10 files changed, 194 insertions(+), 288 deletions(-) diff --git a/.clang-format b/.clang-format index f23b895..938dda8 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,6 @@ -BasedOnStyle: Google +BasedOnStyle: Google Language: Cpp -ColumnLimit: 100 +ColumnLimit: 120 +IndentWidth: 2 +TabWidth: 2 +UseTab: Never \ No newline at end of file diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 5d0a5fb..7d917ac 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - lws-version: [4.2.1, 3.2.3, 2.4.2] + lws-version: [4.2.1, 3.2.3] steps: - name: Install packages run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 0da04ee..f1ffd5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,18 +51,7 @@ if(JSON-C_FOUND) endif() find_package(ZLIB REQUIRED) -find_package(Libwebsockets 1.7.0 QUIET) - -if(NOT Libwebsockets_FOUND) # for libwebsockets-dev on ubuntu 16.04 - find_path(LIBWEBSOCKETS_INCLUDE_DIR NAMES libwebsockets.h) - find_library(LIBWEBSOCKETS_LIBRARY NAMES websockets) - find_package_handle_standard_args(LIBWEBSOCKETS REQUIRED_VARS LIBWEBSOCKETS_LIBRARY LIBWEBSOCKETS_INCLUDE_DIR) - mark_as_advanced(LIBWEBSOCKETS_INCLUDE_DIR LIBWEBSOCKETS_LIBRARY) - if(LIBWEBSOCKETS_FOUND) - SET(LIBWEBSOCKETS_INCLUDE_DIRS "${LIBWEBSOCKETS_INCLUDE_DIR}") - SET(LIBWEBSOCKETS_LIBRARIES "${LIBWEBSOCKETS_LIBRARY}") - endif() -endif() +find_package(Libwebsockets 3.2.0 REQUIRED) set(INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} ${LIBWEBSOCKETS_INCLUDE_DIRS} ${JSON-C_INCLUDE_DIRS} ${LIBUV_INCLUDE_DIRS}) set(LINK_LIBS ${ZLIB_LIBRARIES} ${LIBWEBSOCKETS_LIBRARIES} ${JSON-C_LIBRARIES} ${LIBUV_LIBRARIES}) diff --git a/src/http.c b/src/http.c index e537863..f144297 100644 --- a/src/http.c +++ b/src/http.c @@ -6,10 +6,6 @@ #include "server.h" #include "utils.h" -#if LWS_LIBRARY_VERSION_MAJOR < 2 -#define HTTP_STATUS_FOUND 302 -#endif - enum { AUTH_OK, AUTH_FAIL, AUTH_ERROR }; static char *html_cache = NULL; @@ -21,7 +17,7 @@ static int check_auth(struct lws *wsi, struct pss_http *pss) { char buf[256]; int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION); if (len >= 7 && strstr(buf, "Basic ")) { - if (!strcmp(buf +6, server->credential)) return AUTH_OK; + if (!strcmp(buf + 6, server->credential)) return AUTH_OK; } unsigned char buffer[1024 + LWS_PRE], *p, *end; @@ -89,12 +85,7 @@ static void pss_buffer_free(struct pss_http *pss) { static void access_log(struct lws *wsi, const char *path) { char rip[50]; -#if LWS_LIBRARY_VERSION_NUMBER >= 2004000 lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip)); -#else - char name[100]; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip)); -#endif lwsl_notice("HTTP %s - %s\n", path, rip); } @@ -186,14 +177,9 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) return 1; -#if LWS_LIBRARY_VERSION_MAJOR < 2 - if (lws_write_http(wsi, output, output_len) < 0) return 1; - goto try_to_reuse; -#else pss->buffer = pss->ptr = output; pss->len = output_len; lws_callback_on_writable(wsi); -#endif } break; diff --git a/src/protocol.c b/src/protocol.c index 43dc441..5324655 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,10 +1,10 @@ #include +#include +#include #include #include #include #include -#include -#include #include "pty.h" #include "server.h" @@ -35,16 +35,14 @@ static int send_initial_message(struct lws *wsi, int index) { return lws_write(wsi, p, (size_t)n, LWS_WRITE_BINARY); } -static json_object* parse_window_size(const char *buf, size_t len, uint16_t *cols, uint16_t *rows) { +static json_object *parse_window_size(const char *buf, size_t len, uint16_t *cols, uint16_t *rows) { json_tokener *tok = json_tokener_new(); json_object *obj = json_tokener_parse_ex(tok, buf, len); struct json_object *o = NULL; - if (json_object_object_get_ex(obj, "columns", &o)) - *cols = (uint16_t) json_object_get_int(o); - if (json_object_object_get_ex(obj, "rows", &o)) - *rows = (uint16_t) json_object_get_int(o); - + if (json_object_object_get_ex(obj, "columns", &o)) *cols = (uint16_t)json_object_get_int(o); + if (json_object_object_get_ex(obj, "rows", &o)) *rows = (uint16_t)json_object_get_int(o); + json_tokener_free(tok); return obj; } @@ -52,7 +50,7 @@ static json_object* parse_window_size(const char *buf, size_t len, uint16_t *col static bool check_host_origin(struct lws *wsi) { char buf[256]; memset(buf, 0, sizeof(buf)); - int len = lws_hdr_copy(wsi, buf, (int) sizeof(buf), WSI_TOKEN_ORIGIN); + int len = lws_hdr_copy(wsi, buf, (int)sizeof(buf), WSI_TOKEN_ORIGIN); if (len <= 0) { return false; } @@ -68,23 +66,23 @@ static bool check_host_origin(struct lws *wsi) { char host_buf[256]; memset(host_buf, 0, sizeof(host_buf)); - len = lws_hdr_copy(wsi, host_buf, (int) sizeof(host_buf), WSI_TOKEN_HOST); + len = lws_hdr_copy(wsi, host_buf, (int)sizeof(host_buf), WSI_TOKEN_HOST); return len > 0 && strcasecmp(buf, host_buf) == 0; } static void process_read_cb(void *ctx, pty_buf_t *buf, bool eof) { - struct pss_tty *pss = (struct pss_tty *) ctx; + struct pss_tty *pss = (struct pss_tty *)ctx; if (eof && !process_running(pss->process)) pss->lws_close_status = pss->process->exit_code == 0 ? 1000 : 1006; else pss->pty_buf = buf; - + lws_callback_on_writable(pss->wsi); } static void process_exit_cb(void *ctx, pty_process *process) { - struct pss_tty *pss = (struct pss_tty *) ctx; + struct pss_tty *pss = (struct pss_tty *)ctx; pss->process = NULL; if (process->killed) { lwsl_notice("process killed with signal %d, pid: %d\n", process->exit_signal, process->pid); @@ -107,7 +105,7 @@ static bool spawn_process(struct pss_tty *pss, uint16_t columns, uint16_t rows) } argv[n] = NULL; - pty_process *process = process_init((void *) pss, server->loop, argv); + pty_process *process = process_init((void *)pss, server->loop, argv); if (columns > 0) process->columns = columns; if (rows > 0) process->rows = rows; strncpy(process->term, server->terminal_type, sizeof(process->term)); @@ -126,13 +124,13 @@ static bool spawn_process(struct pss_tty *pss, uint16_t columns, uint16_t rows) static void wsi_output(struct lws *wsi, pty_buf_t *buf) { if (buf == NULL) return; char *message = xmalloc(LWS_PRE + 1 + buf->len); - char *ptr= message + LWS_PRE; + char *ptr = message + LWS_PRE; *ptr = OUTPUT; memcpy(ptr + 1, buf->base, buf->len); size_t n = buf->len + 1; - if (lws_write(wsi, (unsigned char *) ptr, n, LWS_WRITE_BINARY) < n) { + if (lws_write(wsi, (unsigned char *)ptr, n, LWS_WRITE_BINARY) < n) { lwsl_err("write OUTPUT to WS\n"); } @@ -157,7 +155,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, } if (server->credential != NULL) { n = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION); - if (n < 7 || !strstr(buf, "Basic ") || strcmp(buf +6, server->credential)) return 1; + if (n < 7 || !strstr(buf, "Basic ") || strcmp(buf + 6, server->credential)) return 1; } n = lws_hdr_copy(wsi, pss->path, sizeof(pss->path), WSI_TOKEN_GET_URI); @@ -195,13 +193,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, server->client_count++; -#if LWS_LIBRARY_VERSION_NUMBER >= 2004000 lws_get_peer_simple(lws_get_network_wsi(wsi), pss->address, sizeof(pss->address)); -#else - char name[100]; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), pss->address, - sizeof(pss->address)); -#endif lwsl_notice("WS %s - %s, clients: %d\n", pss->path, pss->address, server->client_count); break; @@ -269,8 +261,8 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, } break; case RESIZE_TERMINAL: - json_object_put(parse_window_size(pss->buffer + 1, pss->len - 1, - &pss->process->columns, &pss->process->rows)); + json_object_put(parse_window_size(pss->buffer + 1, pss->len - 1, &pss->process->columns, + &pss->process->rows)); pty_resize(pss->process); break; case PAUSE: diff --git a/src/pty.c b/src/pty.c index 1a9d17f..97acad9 100644 --- a/src/pty.c +++ b/src/pty.c @@ -32,9 +32,7 @@ static void alloc_cb(uv_handle_t *unused, size_t suggested_size, uv_buf_t *buf) buf->len = suggested_size; } -static void close_cb(uv_handle_t *handle) { - free(handle); -} +static void close_cb(uv_handle_t *handle) { free(handle); } pty_buf_t *pty_buf_init(char *base, size_t len) { pty_buf_t *buf = xmalloc(sizeof(pty_buf_t)); @@ -65,7 +63,7 @@ done: } static void write_cb(uv_write_t *req, int unused) { - pty_buf_t *buf = (pty_buf_t *)req->data; + pty_buf_t *buf = (pty_buf_t *) req->data; pty_buf_free(buf); free(req); } @@ -152,10 +150,10 @@ bool pty_resize(pty_process *process) { if (process == NULL) return false; if (process->columns <= 0 || process->rows <= 0) return false; #ifdef _WIN32 - COORD size = { (int16_t) process->columns, (int16_t) process->rows }; + COORD size = {(int16_t) process->columns, (int16_t) process->rows}; return pResizePseudoConsole(process->pty, size) == S_OK; #else - struct winsize size = { process->rows, process->columns, 0, 0 }; + struct winsize size = {process->rows, process->columns, 0, 0}; return ioctl(process->pty, TIOCSWINSZ, &size) == 0; #endif } @@ -180,15 +178,12 @@ bool conpty_init() { static struct { char *name; FARPROC *ptr; - } conpty_entry[] = { - { "CreatePseudoConsole", (FARPROC *)&pCreatePseudoConsole }, - { "ResizePseudoConsole", (FARPROC *)&pResizePseudoConsole }, - { "ClosePseudoConsole", (FARPROC *)&pClosePseudoConsole }, - { NULL, NULL } - }; - for (int i = 0; - conpty_entry[i].name != NULL && conpty_entry[i].ptr != NULL; i++) { - if (uv_dlsym(&kernel, conpty_entry[i].name, (void **)conpty_entry[i].ptr)) { + } conpty_entry[] = {{"CreatePseudoConsole", (FARPROC *) &pCreatePseudoConsole}, + {"ResizePseudoConsole", (FARPROC *) &pResizePseudoConsole}, + {"ClosePseudoConsole", (FARPROC *) &pClosePseudoConsole}, + {NULL, NULL}}; + for (int i = 0; conpty_entry[i].name != NULL && conpty_entry[i].ptr != NULL; i++) { + if (uv_dlsym(&kernel, conpty_entry[i].name, (void **) conpty_entry[i].ptr)) { uv_dlclose(&kernel); return false; } @@ -212,7 +207,7 @@ static WCHAR *join_args(char **argv) { int len = MultiByteToWideChar(CP_UTF8, 0, args, -1, NULL, 0); if (len <= 0) goto failed; - WCHAR *ws = (WCHAR*) xmalloc(len * sizeof(WCHAR)); + WCHAR *ws = (WCHAR *) xmalloc(len * sizeof(WCHAR)); if (len != MultiByteToWideChar(CP_UTF8, 0, args, -1, ws, len)) { free(ws); goto failed; @@ -228,7 +223,7 @@ static bool conpty_setup(HPCON *hnd, COORD size, STARTUPINFOEXW *si_ex, char **i static int count = 0; char buf[256]; HPCON pty = INVALID_HANDLE_VALUE; - SECURITY_ATTRIBUTES sa = { 0 }; + SECURITY_ATTRIBUTES sa = {0}; HANDLE in_pipe = INVALID_HANDLE_VALUE; HANDLE out_pipe = INVALID_HANDLE_VALUE; const DWORD open_mode = PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE; @@ -260,14 +255,14 @@ static bool conpty_setup(HPCON *hnd, COORD size, STARTUPINFOEXW *si_ex, char **i si_ex->StartupInfo.hStdInput = NULL; si_ex->StartupInfo.hStdOutput = NULL; size_t bytes_required; - InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required); + InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required); si_ex->lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST) xmalloc(bytes_required); if (!InitializeProcThreadAttributeList(si_ex->lpAttributeList, 1, 0, &bytes_required)) { print_error("InitializeProcThreadAttributeList"); goto failed; } - if (!UpdateProcThreadAttribute(si_ex->lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, - pty, sizeof(HPCON), NULL, NULL)) { + if (!UpdateProcThreadAttribute(si_ex->lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, pty, sizeof(HPCON), + NULL, NULL)) { print_error("UpdateProcThreadAttribute"); goto failed; } @@ -288,9 +283,7 @@ done: return ret; } -static void connect_cb(uv_connect_t *req, int status) { - free(req); -} +static void connect_cb(uv_connect_t *req, int status) { free(req); } static void CALLBACK conpty_exit(void *context, BOOLEAN unused) { pty_process *process = (pty_process *) context; @@ -316,7 +309,7 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) { char *in_name = NULL; char *out_name = NULL; DWORD flags = EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT; - COORD size = { (int16_t) process->columns, (int16_t) process->rows }; + COORD size = {(int16_t) process->columns, (int16_t) process->rows}; if (!conpty_setup(&process->pty, size, &process->si, &in_name, &out_name)) return 1; @@ -329,8 +322,8 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) { uv_connect_t *out_req = xmalloc(sizeof(uv_connect_t)); uv_pipe_connect(in_req, io->in, in_name, connect_cb); uv_pipe_connect(out_req, io->out, out_name, connect_cb); - - PROCESS_INFORMATION pi = { 0 }; + + PROCESS_INFORMATION pi = {0}; cmdline = join_args(process->argv); if (cmdline == NULL) goto cleanup; @@ -351,7 +344,7 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) { process->async.data = process; uv_async_init(process->loop, &process->async, async_cb); - if(!RegisterWaitForSingleObject(&process->wait, pi.hProcess, conpty_exit, process, INFINITE, WT_EXECUTEONLYONCE)) { + if (!RegisterWaitForSingleObject(&process->wait, pi.hProcess, conpty_exit, process, INFINITE, WT_EXECUTEONLYONCE)) { print_error("RegisterWaitForSingleObject"); pty_io_free(io); goto cleanup; @@ -380,7 +373,7 @@ static bool fd_duplicate(int fd, uv_pipe_t *pipe) { if (!fd_set_cloexec(fd_dup)) return false; int status = uv_pipe_open(pipe, fd_dup); - if(status) close(fd_dup); + if (status) close(fd_dup); return status == 0; } @@ -419,7 +412,7 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) { uv_disable_stdio_inheritance(); int master, pid; - struct winsize size = { process->rows, process->columns, 0, 0 }; + struct winsize size = {process->rows, process->columns, 0, 0}; pid = forkpty(&master, NULL, NULL, &size); if (pid < 0) { status = -errno; @@ -439,12 +432,12 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) { status = -errno; goto error; } - if(fcntl(master, F_SETFD, flags | O_NONBLOCK) == -1) { + if (fcntl(master, F_SETFD, flags | O_NONBLOCK) == -1) { status = -errno; goto error; } if (!fd_set_cloexec(master)) { - status=-errno; + status = -errno; goto error; } diff --git a/src/pty.h b/src/pty.h index 51ff97b..f891315 100644 --- a/src/pty.h +++ b/src/pty.h @@ -7,10 +7,10 @@ #ifdef _WIN32 #ifndef HPCON -# define HPCON VOID * +#define HPCON VOID * #endif #ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE -# define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016 +#define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016 #endif bool conpty_init(); @@ -51,7 +51,7 @@ struct pty_process_ { uv_thread_t tid; #endif char **argv; - + uv_loop_t *loop; uv_async_t async; pty_io_t *io; diff --git a/src/server.c b/src/server.c index c60eb3d..f1af441 100644 --- a/src/server.c +++ b/src/server.c @@ -22,68 +22,63 @@ struct lws_context *context; struct server *server; struct endpoints endpoints = {"/ws", "/", "/token", ""}; -extern int callback_http(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len); -extern int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len); +extern int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); +extern int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); // websocket protocols -static const struct lws_protocols protocols[] = { - {"http-only", callback_http, sizeof(struct pss_http), 0}, - {"tty", callback_tty, sizeof(struct pss_tty), 0}, - {NULL, NULL, 0, 0}}; +static const struct lws_protocols protocols[] = {{"http-only", callback_http, sizeof(struct pss_http), 0}, + {"tty", callback_tty, sizeof(struct pss_tty), 0}, + {NULL, NULL, 0, 0}}; #ifndef LWS_WITHOUT_EXTENSIONS // websocket extensions static const struct lws_extension extensions[] = { - {"permessage-deflate", lws_extension_callback_pm_deflate, - "permessage-deflate"}, + {"permessage-deflate", lws_extension_callback_pm_deflate, "permessage-deflate"}, {"deflate-frame", lws_extension_callback_pm_deflate, "deflate_frame"}, {NULL, NULL, NULL}}; #endif #if LWS_LIBRARY_VERSION_NUMBER >= 4000000 -static const uint32_t backoff_ms[] = { 1000, 2000, 3000, 4000, 5000 }; +static const uint32_t backoff_ms[] = {1000, 2000, 3000, 4000, 5000}; static lws_retry_bo_t retry = { - .retry_ms_table = backoff_ms, - .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), - .conceal_count = LWS_ARRAY_SIZE(backoff_ms), - .secs_since_valid_ping = 5, - .secs_since_valid_hangup = 10, - .jitter_percent = 0, - }; + .retry_ms_table = backoff_ms, + .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), + .conceal_count = LWS_ARRAY_SIZE(backoff_ms), + .secs_since_valid_ping = 5, + .secs_since_valid_hangup = 10, + .jitter_percent = 0, +}; #endif // command line options -static const struct option options[] = { - {"port", required_argument, NULL, 'p'}, - {"interface", required_argument, NULL, 'i'}, - {"credential", required_argument, NULL, 'c'}, - {"uid", required_argument, NULL, 'u'}, - {"gid", required_argument, NULL, 'g'}, - {"signal", required_argument, NULL, 's'}, - {"index", required_argument, NULL, 'I'}, - {"base-path", required_argument, NULL, 'b'}, +static const struct option options[] = {{"port", required_argument, NULL, 'p'}, + {"interface", required_argument, NULL, 'i'}, + {"credential", required_argument, NULL, 'c'}, + {"uid", required_argument, NULL, 'u'}, + {"gid", required_argument, NULL, 'g'}, + {"signal", required_argument, NULL, 's'}, + {"index", required_argument, NULL, 'I'}, + {"base-path", required_argument, NULL, 'b'}, #if LWS_LIBRARY_VERSION_NUMBER >= 4000000 - {"ping-interval", required_argument, NULL, 'P'}, + {"ping-interval", required_argument, NULL, 'P'}, #endif - {"ipv6", no_argument, NULL, '6'}, - {"ssl", no_argument, NULL, 'S'}, - {"ssl-cert", required_argument, NULL, 'C'}, - {"ssl-key", required_argument, NULL, 'K'}, - {"ssl-ca", required_argument, NULL, 'A'}, - {"url-arg", no_argument, NULL, 'a'}, - {"readonly", no_argument, NULL, 'R'}, - {"terminal-type", required_argument, NULL, 'T'}, - {"client-option", required_argument, NULL, 't'}, - {"check-origin", no_argument, NULL, 'O'}, - {"max-clients", required_argument, NULL, 'm'}, - {"once", no_argument, NULL, 'o'}, - {"browser", no_argument, NULL, 'B'}, - {"debug", required_argument, NULL, 'd'}, - {"version", no_argument, NULL, 'v'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, 0, 0}}; + {"ipv6", no_argument, NULL, '6'}, + {"ssl", no_argument, NULL, 'S'}, + {"ssl-cert", required_argument, NULL, 'C'}, + {"ssl-key", required_argument, NULL, 'K'}, + {"ssl-ca", required_argument, NULL, 'A'}, + {"url-arg", no_argument, NULL, 'a'}, + {"readonly", no_argument, NULL, 'R'}, + {"terminal-type", required_argument, NULL, 'T'}, + {"client-option", required_argument, NULL, 't'}, + {"check-origin", no_argument, NULL, 'O'}, + {"max-clients", required_argument, NULL, 'm'}, + {"once", no_argument, NULL, 'o'}, + {"browser", no_argument, NULL, 'B'}, + {"debug", required_argument, NULL, 'd'}, + {"version", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, 0, 0}}; #if LWS_LIBRARY_VERSION_NUMBER < 4000000 static const char *opt_string = "p:i:c:u:g:s:I:b:6aSC:K:A:Rt:T:Om:oBd:vh"; @@ -167,7 +162,7 @@ static struct server *server_new(int argc, char **argv, int start) { char *ptr = ts->command; for (int i = 0; i < cmd_argc; i++) { size_t len = strlen(ts->argv[i]); - ptr = memcpy (ptr, ts->argv[i], len + 1) + len; + ptr = memcpy(ptr, ts->argv[i], len + 1) + len; if (i != cmd_argc - 1) { *ptr++ = ' '; } @@ -186,18 +181,22 @@ static void server_free(struct server *ts) { if (ts->index != NULL) free(ts->index); free(ts->command); free(ts->prefs_json); + int i = 0; do { free(ts->argv[i++]); } while (ts->argv[i] != NULL); free(ts->argv); + if (strlen(ts->socket_path) > 0) { struct stat st; if (!stat(ts->socket_path, &st)) { unlink(ts->socket_path); } } + uv_loop_close(ts->loop); + free(ts->loop); free(ts); } @@ -209,8 +208,7 @@ static void signal_cb(uv_signal_t *watcher, int signum) { case SIGINT: case SIGTERM: get_sig_name(watcher->signum, sig_name, sizeof(sig_name)); - lwsl_notice("received signal: %s (%d), exiting...\n", sig_name, - watcher->signum); + lwsl_notice("received signal: %s (%d), exiting...\n", sig_name, watcher->signum); break; default: signal(SIGABRT, SIG_DFL); @@ -219,14 +217,11 @@ static void signal_cb(uv_signal_t *watcher, int signum) { if (force_exit) exit(EXIT_FAILURE); force_exit = true; + lws_cancel_service(context); -#if LWS_LIBRARY_VERSION_MAJOR >= 3 uv_stop(server->loop); + lwsl_notice("send ^C to force exit.\n"); -#else - lws_libuv_stop(context); - exit(EXIT_SUCCESS); -#endif } static int parse_int(char *name, char *str) { @@ -237,7 +232,7 @@ static int parse_int(char *name, char *str) { fprintf(stderr, "ttyd: invalid value for %s: %s\n", name, str); exit(EXIT_FAILURE); } - return (int) val; + return (int)val; } static int calc_command_start(int argc, char **argv) { @@ -300,8 +295,7 @@ int main(int argc, char **argv) { info.gid = -1; info.uid = -1; info.max_http_header_pool = 16; - info.options = LWS_SERVER_OPTION_LIBUV | LWS_SERVER_OPTION_VALIDATE_UTF8 | - LWS_SERVER_OPTION_DISABLE_IPV6; + info.options = LWS_SERVER_OPTION_LIBUV | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_DISABLE_IPV6; #ifndef LWS_WITHOUT_EXTENSIONS info.extensions = extensions; #endif @@ -394,13 +388,11 @@ int main(int argc, char **argv) { } struct stat st; if (stat(server->index, &st) == -1) { - fprintf(stderr, "Can not stat index.html: %s, error: %s\n", - server->index, strerror(errno)); + fprintf(stderr, "Can not stat index.html: %s, error: %s\n", server->index, strerror(errno)); return -1; } if (S_ISDIR(st.st_mode)) { - fprintf(stderr, "Invalid index.html path: %s, is it a dir?\n", - server->index); + fprintf(stderr, "Invalid index.html path: %s, is it a dir?\n", server->index); return -1; } break; @@ -417,18 +409,16 @@ int main(int argc, char **argv) { #undef sc } break; #if LWS_LIBRARY_VERSION_NUMBER >= 4000000 - case 'P': - { - int interval = parse_int("ping-interval", optarg); - if (interval <= 0) { - fprintf(stderr, "ttyd: invalid ping interval: %s\n", optarg); - return -1; - } - retry.secs_since_valid_ping = interval; - retry.secs_since_valid_hangup = interval + 7; - info.retry_and_idle_policy = &retry; + case 'P': { + int interval = parse_int("ping-interval", optarg); + if (interval <= 0) { + fprintf(stderr, "ttyd: invalid ping interval: %s\n", optarg); + return -1; } - break; + retry.secs_since_valid_ping = interval; + retry.secs_since_valid_hangup = interval + 7; + info.retry_and_idle_policy = &retry; + } break; #endif case '6': info.options &= ~(LWS_SERVER_OPTION_DISABLE_IPV6); @@ -451,8 +441,7 @@ int main(int argc, char **argv) { break; #endif case 'T': - strncpy(server->terminal_type, optarg, - sizeof(server->terminal_type) - 1); + strncpy(server->terminal_type, optarg, sizeof(server->terminal_type) - 1); server->terminal_type[sizeof(server->terminal_type) - 1] = '\0'; break; case '?': @@ -463,22 +452,16 @@ int main(int argc, char **argv) { char *option = optarg; char *key = strsep(&option, "="); if (key == NULL) { - fprintf(stderr, - "ttyd: invalid client option: %s, format: key=value\n", - optarg); + fprintf(stderr, "ttyd: invalid client option: %s, format: key=value\n", optarg); return -1; } char *value = strsep(&option, "="); if (value == NULL) { - fprintf(stderr, - "ttyd: invalid client option: %s, format: key=value\n", - optarg); + fprintf(stderr, "ttyd: invalid client option: %s, format: key=value\n", optarg); return -1; } struct json_object *obj = json_tokener_parse(value); - json_object_object_add( - client_prefs, key, - obj != NULL ? obj : json_object_new_string(value)); + json_object_object_add(client_prefs, key, obj != NULL ? obj : json_object_new_string(value)); } break; default: @@ -496,13 +479,11 @@ int main(int argc, char **argv) { lws_set_log_level(debug_level, NULL); -#if LWS_LIBRARY_VERSION_MAJOR >= 2 char server_hdr[128] = ""; - sprintf(server_hdr, "ttyd/%s (libwebsockets/%s)", TTYD_VERSION, - LWS_LIBRARY_VERSION); + sprintf(server_hdr, "ttyd/%s (libwebsockets/%s)", TTYD_VERSION, LWS_LIBRARY_VERSION); info.server_string = server_hdr; -#endif -#if LWS_LIBRARY_VERSION_NUMBER >= 2001000 && LWS_LIBRARY_VERSION_NUMBER < 4000000 + +#if LWS_LIBRARY_VERSION_NUMBER < 4000000 info.ws_ping_pong_interval = 5; #endif @@ -511,11 +492,10 @@ int main(int argc, char **argv) { if (endswith(info.iface, ".sock") || endswith(info.iface, ".socket")) { #if defined(LWS_USE_UNIX_SOCK) || defined(LWS_WITH_UNIX_SOCK) info.options |= LWS_SERVER_OPTION_UNIX_SOCK; - info.port = 0; // warmcat/libwebsockets#1985 + info.port = 0; // warmcat/libwebsockets#1985 strncpy(server->socket_path, info.iface, sizeof(server->socket_path) - 1); #else - fprintf(stderr, - "libwebsockets is not compiled with UNIX domain socket support"); + fprintf(stderr, "libwebsockets is not compiled with UNIX domain socket support"); return -1; #endif } @@ -529,17 +509,13 @@ int main(int argc, char **argv) { info.ssl_ca_filepath = ca_path; info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; } -#if LWS_LIBRARY_VERSION_MAJOR >= 2 info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS; -#endif } #endif - lwsl_notice("ttyd %s (libwebsockets %s)\n", TTYD_VERSION, - LWS_LIBRARY_VERSION); + lwsl_notice("ttyd %s (libwebsockets %s)\n", TTYD_VERSION, LWS_LIBRARY_VERSION); lwsl_notice("tty configuration:\n"); - if (server->credential != NULL) - lwsl_notice(" credential: %s\n", server->credential); + if (server->credential != NULL) lwsl_notice(" credential: %s\n", server->credential); lwsl_notice(" start command: %s\n", server->command); lwsl_notice(" close signal: %s (%d)\n", server->sig_name, server->sig_code); lwsl_notice(" terminal type: %s\n", server->terminal_type); @@ -553,19 +529,14 @@ int main(int argc, char **argv) { if (server->check_origin) lwsl_notice(" check origin: true\n"); if (server->url_arg) lwsl_notice(" allow url arg: true\n"); if (server->readonly) lwsl_notice(" readonly: true\n"); - if (server->max_clients > 0) - lwsl_notice(" max clients: %d\n", server->max_clients); + if (server->max_clients > 0) lwsl_notice(" max clients: %d\n", server->max_clients); if (server->once) lwsl_notice(" once: true\n"); - if (server->index != NULL) { - lwsl_notice(" custom index.html: %s\n", server->index); - } + if (server->index != NULL) lwsl_notice(" custom index.html: %s\n", server->index); -#if LWS_LIBRARY_VERSION_MAJOR >= 3 void *foreign_loops[1]; foreign_loops[0] = server->loop; info.foreign_loops = foreign_loops; info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS; -#endif context = lws_create_context(&info); if (context == NULL) { @@ -573,16 +544,12 @@ int main(int argc, char **argv) { return 1; } -#if LWS_LIBRARY_VERSION_MAJOR >= 3 struct lws_vhost *vhost = lws_create_vhost(context, &info); if (vhost == NULL) { lwsl_err("libwebsockets vhost creation failed\n"); return 1; } int port = lws_get_vhost_listen_port(vhost); -#else - int port = info.port; -#endif lwsl_notice(" Listening on port: %d\n", port); if (browser) { @@ -591,8 +558,7 @@ int main(int argc, char **argv) { open_uri(url); } -#if LWS_LIBRARY_VERSION_MAJOR >= 3 - #define sig_count 2 +#define sig_count 2 int sig_nums[] = {SIGINT, SIGTERM}; uv_signal_t signals[sig_count]; for (int i = 0; i < sig_count; i++) { @@ -605,16 +571,7 @@ int main(int argc, char **argv) { for (int i = 0; i < sig_count; i++) { uv_signal_stop(&signals[i]); } - #undef sig_count -#else -#if LWS_LIBRARY_VERSION_MAJOR < 2 - lws_uv_initloop(context, server->loop, signal_cb, 0); -#else - lws_uv_sigint_cfg(context, 1, signal_cb); - lws_uv_initloop(context, server->loop, 0); -#endif - lws_libuv_run(context, 0); -#endif +#undef sig_count lws_context_destroy(context); diff --git a/src/server.h b/src/server.h index 8fc5dde..5f369ae 100644 --- a/src/server.h +++ b/src/server.h @@ -72,5 +72,5 @@ struct server { char socket_path[255]; // UNIX domain socket path char terminal_type[30]; // terminal type to report - uv_loop_t *loop; // the libuv event loop + uv_loop_t *loop; // the libuv event loop }; diff --git a/src/utils.c b/src/utils.c index ed31643..e3f9b39 100644 --- a/src/utils.c +++ b/src/utils.c @@ -8,10 +8,9 @@ #if defined(__linux__) && !defined(__ANDROID__) const char *sys_signame[NSIG] = { - "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "UNUSED", "FPE", - "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", - "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", - "PROF", "WINCH", "IO", "PWR", "SYS", NULL}; + "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "UNUSED", "FPE", "KILL", "USR1", + "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", + "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "SYS", NULL}; #endif #if defined(_WIN32) || defined(__CYGWIN__) @@ -19,10 +18,9 @@ const char *sys_signame[NSIG] = { #undef NSIG #define NSIG 33 const char *sys_signame[NSIG] = { - "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "EMT", "FPE", - "KILL", "BUS", "SEGV", "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", - "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", "XFSZ", "VTALRM", - "PROF", "WINCH", "PWR", "USR1", "USR2", NULL}; + "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "EMT", "FPE", "KILL", "BUS", + "SEGV", "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", + "TTOU", "IO", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "PWR", "USR1", "USR2", NULL}; #endif void *xmalloc(size_t size) { @@ -54,8 +52,7 @@ bool endswith(const char *str, const char *suffix) { } int get_sig_name(int sig, char *buf, size_t len) { - int n = - snprintf(buf, len, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown"); + int n = snprintf(buf, len, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown"); uppercase(buf); return n; } @@ -63,8 +60,7 @@ int get_sig_name(int sig, char *buf, size_t len) { int get_sig(const char *sig_name) { for (int sig = 1; sig < NSIG; sig++) { const char *name = sys_signame[sig]; - if (name != NULL && (strcasecmp(name, sig_name) == 0 || - strcasecmp(name, sig_name + 3) == 0)) + if (name != NULL && (strcasecmp(name, sig_name) == 0 || strcasecmp(name, sig_name + 3) == 0)) return sig; } return atoi(sig_name); @@ -76,7 +72,7 @@ int open_uri(char *uri) { sprintf(command, "open %s > /dev/null 2>&1", uri); return system(command); #elif defined(_WIN32) || defined(__CYGWIN__) - return ShellExecute(0, 0, uri, 0, 0, SW_SHOW) > (HINSTANCE) 32 ? 0 : 1; + return ShellExecute(0, 0, uri, 0, 0, SW_SHOW) > (HINSTANCE)32 ? 0 : 1; #else // check if X server is running if (system("xset -q > /dev/null 2>&1")) return 1; @@ -89,81 +85,71 @@ int open_uri(char *uri) { #ifdef _WIN32 char *strsep(char **sp, char *sep) { char *p, *s; - if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL); + if (sp == NULL || *sp == NULL || **sp == '\0') return (NULL); s = *sp; p = s + strcspn(s, sep); if (*p != '\0') *p++ = '\0'; *sp = p; - return(s); + return s; } const char *quote_arg(const char *arg) { - int len = 0, n = 0; - int force_quotes = 0; - char *q, *d; - const char *p = arg; - if (!*p) force_quotes = 1; - while (*p) { - if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'') - force_quotes = 1; - else if (*p == '"') - n++; - else if (*p == '\\') { - int count = 0; - while (*p == '\\') { - count++; - p++; - len++; - } - if (*p == '"' || !*p) - n += count*2 + 1; - continue; - } - len++; - p++; - } - if (!force_quotes && n == 0) - return arg; + int len = 0, n = 0; + int force_quotes = 0; + char *q, *d; + const char *p = arg; + if (!*p) force_quotes = 1; + while (*p) { + if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'') + force_quotes = 1; + else if (*p == '"') + n++; + else if (*p == '\\') { + int count = 0; + while (*p == '\\') { + count++; + p++; + len++; + } + if (*p == '"' || !*p) n += count * 2 + 1; + continue; + } + len++; + p++; + } + if (!force_quotes && n == 0) return arg; - d = q = xmalloc(len + n + 3); - *d++ = '"'; - while (*arg) { - if (*arg == '"') - *d++ = '\\'; - else if (*arg == '\\') { - int count = 0; - while (*arg == '\\') { - count++; - *d++ = *arg++; - } - if (*arg == '"' || !*arg) { - while (count-- > 0) - *d++ = '\\'; - if (!*arg) - break; - *d++ = '\\'; - } - } - *d++ = *arg++; - } - *d++ = '"'; - *d++ = '\0'; - return q; + d = q = xmalloc(len + n + 3); + *d++ = '"'; + while (*arg) { + if (*arg == '"') + *d++ = '\\'; + else if (*arg == '\\') { + int count = 0; + while (*arg == '\\') { + count++; + *d++ = *arg++; + } + if (*arg == '"' || !*arg) { + while (count-- > 0) *d++ = '\\'; + if (!*arg) break; + *d++ = '\\'; + } + } + *d++ = *arg++; + } + *d++ = '"'; + *d++ = '\0'; + return q; } -void print_error(char *func) { - LPVOID buffer; - DWORD dw = GetLastError(); - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &buffer, - 0, NULL ); - wprintf(L"== %s failed with error %d: %s", func, dw, buffer); - LocalFree(buffer); +void print_error(char *func) { + LPVOID buffer; + DWORD dw = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buffer, 0, NULL); + wprintf(L"== %s failed with error %d: %s", func, dw, buffer); + LocalFree(buffer); } #endif -- 2.43.4