From 4ca75894c16ea3be1e4c19a7469f1595c18b2f63 Mon Sep 17 00:00:00 2001
From: Omar Rizwan <omar.rizwan@gmail.com>
Date: Sun, 11 Nov 2018 05:32:44 -0800
Subject: WebSocket communication seems to work.

---
 fs/hello.c | 182 +++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 128 insertions(+), 54 deletions(-)

(limited to 'fs/hello.c')

diff --git a/fs/hello.c b/fs/hello.c
index d136cf8..2d5db9c 100644
--- a/fs/hello.c
+++ b/fs/hello.c
@@ -10,6 +10,8 @@
 #define WBY_USE_ASSERT
 #include "mmx/web.h"
 
+#include "cJSON/cJSON.h"
+#include "cJSON/cJSON.c"
 
 #define MAX_WSCONN 8
 struct server_state {
@@ -19,6 +21,15 @@ struct server_state {
     int conn_count;
 };
 
+struct wby_server server;
+struct wby_con *con;
+
+typedef struct response_readdir_t {
+  char **names;
+  size_t num_names;
+} response_readdir_t;
+
+response_readdir_t *response;
 
 static const char  *file_path      = "/hello.txt";
 static const char   file_content[] = "Hello World!\n";
@@ -61,6 +72,32 @@ hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
     if (strcmp(path, "/") != 0) /* We only recognize the root directory. */
         return -ENOENT;
 
+    // send [READDIR, path] to the websocket handler
+    {
+      char *msg;
+      {
+        cJSON *req = cJSON_CreateObject();
+        cJSON_AddStringToObject(req, "op", "readdir");
+        cJSON_AddStringToObject(req, "path", path);
+
+        msg = cJSON_Print(req);
+        printf("%s\n", msg);
+
+        cJSON_Delete(req);
+      }
+
+      wby_frame_begin(con, WBY_WSOP_TEXT_FRAME);
+      wby_write(con, msg, strlen(msg));
+      wby_frame_end(con);
+
+      free(msg);
+    }
+
+    response = NULL;
+    do {
+        wby_update(&server);
+    } while (response == NULL);
+
     filler(buf, ".", NULL, 0);           /* Current directory (.)  */
     filler(buf, "..", NULL, 0);          /* Parent directory (..)  */
     filler(buf, file_path + 1, NULL, 0); /* The only file we have. */
@@ -96,83 +133,120 @@ static struct fuse_operations hello_filesystem_operations = {
 static int
 dispatch(struct wby_con *connection, void *userdata)
 {
+    return 1;
+}
+
+static int
+websocket_connect(struct wby_con *connection, void *userdata)
+{
+    /* Allow websocket upgrades on /wstest */
     struct server_state *state = (struct server_state*)userdata;
-    if (!strcmp("/foo", connection->request.uri)) {
-        wby_response_begin(connection, 200, 14, NULL, 0);
-        wby_write(connection, "Hello, world!\n", 14);
-        wby_response_end(connection);
-        return 0;
-    } else if (!strcmp("/bar", connection->request.uri)) {
-        wby_response_begin(connection, 200, -1, NULL, 0);
-        wby_write(connection, "Hello, world!\n", 14);
-        wby_write(connection, "Hello, world?\n", 14);
-        wby_response_end(connection);
+    /* connection bound userdata */
+    connection->user_data = NULL;
+    if (0 == strcmp(connection->request.uri, "/") && state->conn_count < MAX_WSCONN)
         return 0;
-    } else if (!strcmp("/quit", connection->request.uri)) {
-        wby_response_begin(connection, 200, -1, NULL, 0);
-        wby_write(connection, "Goodbye, cruel world\n", 22);
-        wby_response_end(connection);
-        state->quit = 1;
-        return 0;
-    } else return 1;
+    else return 1;
+}
+
+static void
+websocket_connected(struct wby_con *connection, void *userdata)
+{
+    struct server_state *state = (struct server_state*)userdata;
+    printf("WebSocket connected\n");
+    con = connection;
+}
+
+static int
+websocket_frame(struct wby_con *connection, const struct wby_frame *frame, void *userdata)
+{
+    int i = 0;
+    printf("WebSocket frame incoming\n");
+    printf("  Frame OpCode: %d\n", frame->opcode);
+    printf("  Final frame?: %s\n", (frame->flags & WBY_WSF_FIN) ? "yes" : "no");
+    printf("  Masked?     : %s\n", (frame->flags & WBY_WSF_MASKED) ? "yes" : "no");
+    printf("  Data Length : %d\n", (int) frame->payload_length);
+    while (i < frame->payload_length) {
+        unsigned char buffer[16];
+        int remain = frame->payload_length - i;
+        size_t read_size = remain > (int) sizeof buffer ? sizeof buffer : (size_t) remain;
+        size_t k;
+
+        printf("%08x ", (int) i);
+        if (0 != wby_read(connection, buffer, read_size))
+            break;
+        for (k = 0; k < read_size; ++k)
+            printf("%02x ", buffer[k]);
+        for (k = read_size; k < 16; ++k)
+            printf("   ");
+        printf(" | ");
+        for (k = 0; k < read_size; ++k)
+            printf("%c", isprint(buffer[k]) ? buffer[k] : '?');
+        printf("\n");
+        i += (int)read_size;
+    }
+    return 0;
+}
+
+static void
+websocket_closed(struct wby_con *connection, void *userdata)
+{
+    int i;
+    struct server_state *state = (struct server_state*)userdata;
+    printf("WebSocket closed\n");
+    for (i = 0; i < state->conn_count; i++) {
+        if (state->conn[i] == connection) {
+            int remain = state->conn_count - i;
+            memmove(state->conn + i, state->conn + i + 1, (size_t)remain * sizeof(struct wby_con*));
+            --state->conn_count;
+            break;
+        }
+    }
+}
+
+static void
+test_log(const char* text)
+{
+    printf("[debug] %s\n", text);
 }
 
 int
 main(int argc, char **argv)
 {
-      void *memory = NULL;
+  void *memory = NULL;
     wby_size needed_memory = 0;
     struct server_state state;
-    struct wby_server server;
 
     struct wby_config config;
     memset(&config, 0, sizeof config);
     config.userdata = &state;
     config.address = "127.0.0.1";
     config.port = 8888;
-    config.connection_max = 4;
+    config.connection_max = 1;
     config.request_buffer_size = 2048;
     config.io_buffer_size = 8192;
-    /* config.log = test_log; */
+    config.log = test_log;
     config.dispatch = dispatch;
-    /* config.ws_connect = websocket_connect; */
-    /* config.ws_connected = websocket_connected; */
-    /* config.ws_frame = websocket_frame; */
-    /* config.ws_closed = websocket_closed; */
-
-#if defined(_WIN32)
-    {WORD wsa_version = MAKEWORD(2,2);
-    WSADATA wsa_data;
-    if (WSAStartup(wsa_version, &wsa_data)) {
-        fprintf(stderr, "WSAStartup failed\n");
-        return 1;
-    }}
-#endif
-
+    config.ws_connect = websocket_connect;
+    config.ws_connected = websocket_connected;
+    config.ws_frame = websocket_frame;
+    config.ws_closed = websocket_closed;
+    
     wby_init(&server, &config, &needed_memory);
     memory = calloc(needed_memory, 1);
     wby_start(&server, memory);
 
     memset(&state, 0, sizeof state);
-    while (!state.quit) {
-        int i = 0;
+
+    printf("Awaiting WebSocket connection from Chrome extension.\n");
+    while (con == NULL) {
         wby_update(&server);
-        /* Push some test data over websockets */
-        if (!(state.frame_counter & 0x7f)) {
-            for (i = 0; i < state.conn_count; ++i) {
-                wby_frame_begin(state.conn[i], WBY_WSOP_TEXT_FRAME);
-                wby_write(state.conn[i], "Hello world over websockets!\n", 29);
-                wby_frame_end(state.conn[i]);
-            }
-        }
-        /* sleep_for(30); */
-        ++state.frame_counter;
     }
-    wby_stop(&server);
-    free(memory);
-#if defined(_WIN32)
-    WSACleanup();
-#endif
-    return 0;
-  // return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
+    return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
+/*     wby_stop(&server); */
+/*     free(memory); */
+/* #if defined(_WIN32) */
+/*     WSACleanup(); */
+/* #endif */
+/*     return 0; */
+  // 
 }
-- 
cgit v1.2.3