URI: 
       webext: Process full messages - surf - surf browser, a WebKit based browser
  HTML git clone git://git.suckless.org/surf
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 9ef79bf7106496c736ba613c51d2fd5af9d873a8
   DIR parent d5f45bffe0c3a54344f61662b4b643e168539251
  HTML Author: Quentin Rameau <quinq@fifth.space>
       Date:   Sun, 24 Mar 2024 15:24:22 +0100
       
       webext: Process full messages
       
       Piped messages would not always be fully sent in a single read.
       Do a bit of message reassembly.
       
       Diffstat:
         M webext-surf.c                       |      90 ++++++++++++++++++++++---------
       
       1 file changed, 64 insertions(+), 26 deletions(-)
       ---
   DIR diff --git 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;
        }