From: Shuanglei Tao Date: Sat, 18 Aug 2018 09:07:41 +0000 (+0800) Subject: libwebsockets 3.0 support X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=0f97a694465df94f93609adb6ebae05e94554d2e;p=ttyd.git libwebsockets 3.0 support --- diff --git a/src/http.c b/src/http.c index 522ecf0..42478e2 100644 --- a/src/http.c +++ b/src/http.c @@ -52,6 +52,7 @@ check_auth(struct lws *wsi) { int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { + struct pss_http *pss = (struct pss_http *) user; unsigned char buffer[4096 + LWS_PRE], *p, *end; char buf[256], name[100], rip[50]; @@ -60,9 +61,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi // only GET method is allowed if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) || len < 1) { lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL); - goto try_to_reuse; + return 0; } + lws_snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in); lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip)); lwsl_notice("HTTP %s - %s (%s)\n", (char *) in, rip, name); @@ -70,7 +72,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi case 0: break; case -1: - goto try_to_reuse; + return 0; case 1: default: return 1; @@ -79,7 +81,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi p = buffer + LWS_PRE; end = p + sizeof(buffer) - LWS_PRE; - if (!strncmp((const char *) in, "/auth_token.js", 14)) { + if (strncmp(pss->path, "/auth_token.js", 14) == 0) { size_t n = server->credential != NULL ? sprintf(buf, "var tty_auth_token = '%s';", server->credential) : 0; if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) @@ -95,15 +97,17 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi return 1; if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) return 1; - if (n > 0 && lws_write_http(wsi, buf, n) < 0) { - return 1; + if (n > 0) { + pss->buffer = strdup(buf); + pss->len = n; + lws_callback_on_writable(wsi); } - goto try_to_reuse; + return 0; } - if (strncmp((const char *) in, "/", 1) != 0) { + if (strcmp(pss->path, "/") != 0) { lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); - goto try_to_reuse; + return 0; } const char* content_type = "text/html"; @@ -123,10 +127,22 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) return 1; - if (lws_write_http(wsi, index_html, index_html_len) < 0) + pss->buffer = (char *) index_html; + pss->len = index_html_len; + lws_callback_on_writable(wsi); + return 0; + } + break; + case LWS_CALLBACK_HTTP_WRITEABLE: + if (pss->len > 0) { + int n = lws_write_http(wsi, pss->buffer, pss->len); + if (strncmp(pss->path, "/", 1) != 0) + free(pss->buffer); + if (n < pss->len) return 1; - goto try_to_reuse; } + if (lws_http_transaction_completed(wsi)) + return -1; break; case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if (!len || (SSL_get_verify_result((SSL *) in) != X509_V_OK)) { @@ -142,11 +158,4 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi } return 0; - - /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */ - try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; } diff --git a/src/protocol.c b/src/protocol.c index 21074d5..1968b80 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -26,31 +26,37 @@ #include "server.h" #include "utils.h" +// initial message list +char initial_cmds[] = { + SET_WINDOW_TITLE, + SET_RECONNECT, + SET_PREFERENCES +}; + int -send_initial_message(struct lws *wsi) { - unsigned char message[LWS_PRE + 256]; +send_initial_message(struct lws *wsi, int index) { + unsigned char message[LWS_PRE + 1 + 4096]; unsigned char *p = &message[LWS_PRE]; - int n; - - char hostname[128]; - gethostname(hostname, sizeof(hostname) - 1); - - // window title - n = sprintf((char *) p, "%c%s (%s)", SET_WINDOW_TITLE, server->command, hostname); - if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) { - return -1; - } - // reconnect time - n = sprintf((char *) p, "%c%d", SET_RECONNECT, server->reconnect); - if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) { - return -1; - } - // client preferences - n = sprintf((char *) p, "%c%s", SET_PREFERENCES, server->prefs_json); - if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) { - return -1; + char buffer[128]; + int n = 0; + + char cmd = initial_cmds[index]; + switch(cmd) { + case SET_WINDOW_TITLE: + gethostname(buffer, sizeof(buffer) - 1); + n = sprintf((char *) p, "%c%s (%s)", cmd, server->command, buffer); + break; + case SET_RECONNECT: + n = sprintf((char *) p, "%c%d", cmd, server->reconnect); + break; + case SET_PREFERENCES: + n = sprintf((char *) p, "%c%s", cmd, server->prefs_json); + break; + default: + break; } - return 0; + + return lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY); } bool @@ -228,7 +234,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, lwsl_warn("refuse to serve WS client due to the --max-clients option.\n"); return 1; } - if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 || strcmp(buf, WS_PATH)) { + if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 || strcmp(buf, WS_PATH) != 0) { lwsl_warn("refuse to serve WS client for illegal ws path: %s\n", buf); return 1; } @@ -242,6 +248,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_ESTABLISHED: client->running = false; client->initialized = false; + client->initial_cmd_index = 0; client->authenticated = false; client->wsi = wsi; client->buffer = NULL; @@ -263,13 +270,18 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_SERVER_WRITEABLE: if (!client->initialized) { - if (send_initial_message(wsi) < 0) { + if (client->initial_cmd_index == sizeof(initial_cmds)) { + client->initialized = true; + break; + } + if (send_initial_message(wsi, client->initial_cmd_index) < 0) { tty_client_remove(client); lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0); return -1; } - client->initialized = true; - break; + client->initial_cmd_index++; + lws_callback_on_writable(wsi); + return 0; } if (client->state != STATE_READY) break; diff --git a/src/server.c b/src/server.c index b8d0a3b..d3fc2d0 100644 --- a/src/server.c +++ b/src/server.c @@ -27,7 +27,7 @@ struct tty_server *server; // websocket protocols static const struct lws_protocols protocols[] = { - {"http-only", callback_http, 0, 0}, + {"http-only", callback_http, sizeof(struct pss_http), 0}, {"tty", callback_tty, sizeof(struct tty_client), 0}, {NULL, NULL, 0, 0} }; diff --git a/src/server.h b/src/server.h index 5e61d2a..cc73b91 100644 --- a/src/server.h +++ b/src/server.h @@ -29,6 +29,7 @@ enum pty_state { struct tty_client { bool running; bool initialized; + int initial_cmd_index; bool authenticated; char hostname[100]; char address[50]; @@ -49,6 +50,12 @@ struct tty_client { LIST_ENTRY(tty_client) list; }; +struct pss_http { + char path[128]; + char *buffer; + size_t len; +}; + struct tty_server { LIST_HEAD(client, tty_client) clients; // client list int client_count; // client count