surf

surf browser, a WebKit based browser
git clone git://git.suckless.org/surf
Log | Files | Refs | README | LICENSE

commit 9ef79bf7106496c736ba613c51d2fd5af9d873a8
parent d5f45bffe0c3a54344f61662b4b643e168539251
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:
Mwebext-surf.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 64 insertions(+), 26 deletions(-)

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; }