]> prime8.dev >> repos - ttyd.git/commitdiff
libwebsockets: hande fragmented messages, fixes #9
authorShuanglei Tao <tsl0922@gmail.com>
Sat, 1 Oct 2016 12:32:40 +0000 (20:32 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Sat, 1 Oct 2016 12:34:45 +0000 (20:34 +0800)
src/protocol.c
src/server.c
src/server.h

index 680a77f190f0a4c2dcb3562d4c52c4e98fe76246..13077c9d78cd9568ac7929d9addd0dfba27fbb22 100644 (file)
@@ -82,6 +82,10 @@ tty_client_destroy(struct tty_client *client) {
     lwsl_notice("process exited with code %d, pid: %d\n", status, client->pid);
     close(client->pty);
 
+    // free the buffer
+    if (client->buffer != NULL)
+        t_free(client->buffer);
+
     // remove from clients list
     pthread_mutex_lock(&server->lock);
     LIST_REMOVE(client, list);
@@ -152,7 +156,6 @@ int
 callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
              void *user, void *in, size_t len) {
     struct tty_client *client = (struct tty_client *) user;
-    char *data;
     struct winsize *size;
 
     switch (reason) {
@@ -161,6 +164,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
             client->initialized = false;
             client->authenticated = false;
             client->wsi = wsi;
+            client->buffer = NULL;
             lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi),
                                    client->hostname, sizeof(client->hostname),
                                    client->address, sizeof(client->address));
@@ -222,8 +226,18 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
             break;
 
         case LWS_CALLBACK_RECEIVE:
-            data = (char *) in;
-            char command = data[0];
+            if (client->buffer == NULL) {
+                client->buffer = t_malloc(len + 1);
+                client->len = len;
+                memcpy(client->buffer, in, len);
+            } else {
+                client->buffer = t_realloc(client->buffer, client->len + len + 1);
+                memcpy(client->buffer + client->len, in, len);
+                client->len += len;
+            }
+            client->buffer[client->len] = '\0';
+
+            const char command = client->buffer[0];
 
             // check auth
             if (server->credential != NULL && !client->authenticated && command != JSON_DATA) {
@@ -231,9 +245,14 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
                 return -1;
             }
 
+            // check if there are more fragmented messages
+            if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
+                return 0;
+            }
+
             switch (command) {
                 case INPUT:
-                    if (write(client->pty, data + 1, len - 1) < len - 1) {
+                    if (write(client->pty, client->buffer + 1, client->len - 1) < client->len - 1) {
                         lwsl_err("write INPUT to pty\n");
                         return -1;
                     }
@@ -248,7 +267,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
                     }
                     break;
                 case RESIZE_TERMINAL:
-                    size = parse_window_size(data + 1);
+                    size = parse_window_size(client->buffer + 1);
                     if (size != NULL) {
                         if (ioctl(client->pty, TIOCSWINSZ, size) == -1) {
                             lwsl_err("ioctl TIOCSWINSZ: %d (%s)\n", errno, strerror(errno));
@@ -260,7 +279,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
                     if (server->credential == NULL)
                         break;
                     {
-                        json_object *obj = json_tokener_parse(data);
+                        json_object *obj = json_tokener_parse(client->buffer);
                         struct json_object *o = NULL;
                         if (json_object_object_get_ex(obj, "AuthToken", &o)) {
                             const char *token = json_object_get_string(o);
@@ -276,6 +295,11 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
                     lwsl_notice("unknown message type: %c\n", command);
                     break;
             }
+
+            if (client->buffer != NULL) {
+                t_free(client->buffer);
+                client->buffer = NULL;
+            }
             break;
 
         case LWS_CALLBACK_CLOSED:
index 300b3a6df6b100c0ab53ffe594f911e1b2430e02..faffd680d55791864df8c56a547000940e7b5595 100644 (file)
@@ -9,7 +9,7 @@ struct tty_server *server;
 // websocket protocols
 static const struct lws_protocols protocols[] = {
         {"http-only", callback_http, 0,                         0},
-        {"tty",       callback_tty,  sizeof(struct tty_client), 128},
+        {"tty",       callback_tty,  sizeof(struct tty_client), 0},
         {NULL, NULL,                 0,                         0}
 };
 
index 1acb41b3b9f996407a56d397c663cea32156b94a..2e914518a3420a4701eb313fe36dabb9639e458b 100644 (file)
@@ -50,6 +50,8 @@ struct tty_client {
     char address[50];
 
     struct lws *wsi;
+    char *buffer;
+    size_t len;
     int pid;
     int pty;
     pthread_t thread;