]> prime8.dev >> repos - ttyd.git/commitdiff
libwebsockets 3.0 support
authorShuanglei Tao <tsl0922@gmail.com>
Sat, 18 Aug 2018 09:07:41 +0000 (17:07 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Sat, 18 Aug 2018 09:07:41 +0000 (17:07 +0800)
src/http.c
src/protocol.c
src/server.c
src/server.h

index 522ecf03da4f1e2a5967d529b055f6f010bb8a16..42478e2bc18a0228072fdaccc74e6568465738c8 100644 (file)
@@ -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;
 }
index 21074d53bebf19c3ecee8839bddcf3628827f1fe..1968b80c6bda83130dd49fe54d49b286a1a578cb 100644 (file)
 #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;
index b8d0a3be6853f7f9889d188132a8389f099f1055..d3fc2d0e64475692ec323c091412d156c6850520 100644 (file)
@@ -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}
 };
index 5e61d2a2136bb23c646efe3be22ad9748316d7a0..cc73b91c430444bde509f561be62b4258e9efbc9 100644 (file)
@@ -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