From fbd3a6690c40d6d6681a1ef010006c4783d999bd Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Sun, 24 Mar 2024 15:24:22 +0100 Subject: webext: Process full messages Piped messages would not always be fully sent in a single read. Do a bit of message reassembly. --- webext-surf.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 26 deletions(-) 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; } -- cgit v1.2.3