commit 9ef79bf7106496c736ba613c51d2fd5af9d873a8
Author:     Quentin Rameau <[email protected]>
AuthorDate: Sun Mar 24 15:24:22 2024 +0100
Commit:     Quentin Rameau <[email protected]>
CommitDate: Sun Mar 24 15:27:20 2024 +0100

    webext: Process full messages
    
    Piped messages would not always be fully sent in a single read.
    Do a bit of message reassembly.

diff --git a/webext-surf.c b/webext-surf.c
index 230c71b..7063fa7 100644
--- a/webext-surf.c
+++ b/webext-surf.c
@@ -19,61 +19,99 @@
 static WebKitWebExtension *webext;
 static int sock;
 
-static gboolean
-readsock(GIOChannel *s, GIOCondition c, gpointer unused)
+/*
+ * Return:
+ * 0 No data processed: need more data
+ * > 0 Amount of data processed or discarded
+ */
+static size_t
+evalmsg(char *msg, size_t sz)
 {
-       static char js[48], msg[MSGBUFSZ];
+       char js[48];
        WebKitWebPage *page;
        JSCContext *jsc;
        JSCValue *jsv;
-       GError *gerr = NULL;
-       gsize msgsz;
-
-       if (g_io_channel_read_chars(s, msg, sizeof(msg), &msgsz, &gerr) !=
-           G_IO_STATUS_NORMAL) {
-               if (gerr) {
-                       fprintf(stderr, "webext: error reading socket: %s\n",
-                               gerr->message);
-                       g_error_free(gerr);
-               }
-               return TRUE;
-       }
-
-       if (msgsz < 2) {
-               fprintf(stderr, "webext: readsock: message too short: %lu\n",
-                       msgsz);
-               return TRUE;
-       }
 
        if (!(page = webkit_web_extension_get_page(webext, msg[0])))
-               return TRUE;
+               return sz;
+
+       if (sz < 2)
+               return 0;
 
        jsc = webkit_frame_get_js_context(webkit_web_page_get_main_frame(page));
        jsv = NULL;
 
        switch (msg[1]) {
        case 'h':
-               if (msgsz != 3)
-                       return TRUE;
+               if (sz < 3) {
+                       sz = 0;
+                       break;
+               }
+               sz = 3;
                snprintf(js, sizeof(js),
                         "window.scrollBy(window.innerWidth/100*%hhd,0);",
                         msg[2]);
                jsv = jsc_context_evaluate(jsc, js, -1);
                break;
        case 'v':
-               if (msgsz != 3)
-                       return TRUE;
+               if (sz < 3) {
+                       sz = 0;
+                       break;
+               }
+               sz = 3;
                snprintf(js, sizeof(js),
                         "window.scrollBy(0,window.innerHeight/100*%hhd);",
                         msg[2]);
                jsv = jsc_context_evaluate(jsc, js, -1);
                break;
+       default:
+               fprintf(stderr, "%s:%d:evalmsg: unknown cmd(%zu): '%#x'\n",
+                       __FILE__, __LINE__, sz, msg[1]);
        }
 
        g_object_unref(jsc);
        if (jsv)
                g_object_unref(jsv);
 
+       return sz;
+}
+
+static gboolean
+readsock(GIOChannel *s, GIOCondition c, gpointer unused)
+{
+       static char msg[MSGBUFSZ];
+       static size_t msgoff;
+       GError *gerr = NULL;
+       size_t sz;
+       gsize rsz;
+
+       if (g_io_channel_read_chars(s, msg+msgoff, sizeof(msg)-msgoff, &rsz, 
&gerr) !=
+           G_IO_STATUS_NORMAL) {
+               if (gerr) {
+                       fprintf(stderr, "webext: error reading socket: %s\n",
+                               gerr->message);
+                       g_error_free(gerr);
+               }
+               return TRUE;
+       }
+       if (msgoff >= sizeof(msg)) {
+               fprintf(stderr, "%s:%d:%s: msgoff: %zu", __FILE__, __LINE__, 
__func__, msgoff);
+               return FALSE;
+       }
+
+       for (rsz += msgoff; rsz; rsz -= sz) {
+               sz = evalmsg(msg, rsz);
+               if (sz == 0) {
+                       /* need more data */
+                       break;
+               }
+               if (sz != rsz) {
+                       /* continue processing message */
+                       memmove(msg, msg+sz, rsz-sz);
+               }
+       }
+       msgoff = rsz;
+
        return TRUE;
 }
 

Reply via email to