From 9cb56dabb676391a9382731347e8d2b07b9437a5 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Sun, 7 Apr 2024 13:25:49 +0200 Subject: big cleanup --- sites/pmikkelsen.com/_files/websocket-webfs.patch | 565 ---------------------- 1 file changed, 565 deletions(-) delete mode 100644 sites/pmikkelsen.com/_files/websocket-webfs.patch (limited to 'sites/pmikkelsen.com/_files/websocket-webfs.patch') diff --git a/sites/pmikkelsen.com/_files/websocket-webfs.patch b/sites/pmikkelsen.com/_files/websocket-webfs.patch deleted file mode 100644 index 77c44b0..0000000 --- a/sites/pmikkelsen.com/_files/websocket-webfs.patch +++ /dev/null @@ -1,565 +0,0 @@ -From 424bcc25db6c3de73678fe43d44e4b408cd0434d -From: Peter Mikkelsen -Date: Wed, 23 Jun 2021 15:44:24 +0000 -Subject: [PATCH] Initial buggy version of adding websocket support to webfs - - -It can create connections but doesn't handle errors very well yet. ---- -diff ce73821f3575921e24f839b21c7be60520a9dc42 424bcc25db6c3de73678fe43d44e4b408cd0434d ---- a/sys/src/cmd/webfs/fns.h Mon Jun 21 17:38:11 2021 -+++ b/sys/src/cmd/webfs/fns.h Wed Jun 23 17:44:24 2021 -@@ -41,3 +41,6 @@ - int authenticate(Url *u, Url *ru, char *method, char *s); - void flushauth(Url *u, char *t); - void http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost); -+ -+/* websocket */ -+void websocket(int fd, Buq *qbody, Buq *qpost); ---- a/sys/src/cmd/webfs/fs.c Mon Jun 21 17:38:11 2021 -+++ b/sys/src/cmd/webfs/fs.c Wed Jun 23 17:44:24 2021 -@@ -4,6 +4,7 @@ - #include - #include - #include <9p.h> -+#include - - #include "dat.h" - #include "fns.h" -@@ -19,10 +20,12 @@ - Url *baseurl; - Url *url; - Key *hdr; -+ int wantwebsocket; - - int obody; /* body opend */ - int cbody; /* body closed */ - Buq *qbody; -+ Buq *websocketin; /* websocket input */ - }; - - struct Webfid -@@ -121,6 +124,8 @@ - - buclose(cl->qbody, 0); - bufree(cl->qbody); -+ buclose(cl->websocketin, 0); -+ bufree(cl->websocketin); - - while(k = cl->hdr){ - cl->hdr = k->next; -@@ -384,6 +389,25 @@ - if(cl->qbody == nil){ - char *m; - -+ if(f->level == Qbody && (!strcmp(cl->url->scheme, "ws") || !strcmp(cl->url->scheme, "wss"))){ -+ cl->wantwebsocket = 1; -+ cl->websocketin = bualloc(64*1024); -+ if(!lookkey(cl->hdr, "Upgrade")) -+ cl->hdr = addkey(cl->hdr, "Upgrade", "websocket"); -+ if(!lookkey(cl->hdr, "Connection")) -+ cl->hdr = addkey(cl->hdr, "Connection", "upgrade"); -+ if(!lookkey(cl->hdr, "Sec-WebSocket-Version")) -+ cl->hdr = addkey(cl->hdr, "Sec-WebSocket-Version", "13"); -+ if(!lookkey(cl->hdr, "Sec-WebSocket-Key")){ -+ uchar nonce[16]; -+ char *b64nonce; -+ genrandom(nonce, 16); -+ b64nonce = smprint("%.*[", 16, nonce); -+ cl->hdr = addkey(cl->hdr, "Sec-WebSocket-Key", b64nonce); -+ free(b64nonce); -+ } -+ } -+ - if(cl->url == nil){ - respond(r, "no url set"); - return; -@@ -413,7 +437,7 @@ - if(agent && !lookkey(cl->hdr, "User-Agent")) - cl->hdr = addkey(cl->hdr, "User-Agent", agent); - -- http(m, cl->url, cl->hdr, cl->qbody, f->buq); -+ http(m, cl->url, cl->hdr, cl->qbody, cl->wantwebsocket ? cl->websocketin : f->buq); - cl->request[0] = 0; - cl->url = nil; - cl->hdr = nil; -@@ -683,6 +707,11 @@ - case Qpost: - bureq(f->buq, r); - return; -+ case Qbody: -+ if(f->client->wantwebsocket){ -+ bureq(f->client->websocketin, r); -+ return; -+ } - } - respond(r, "not implemented"); - } ---- a/sys/src/cmd/webfs/http.c Mon Jun 21 17:38:11 2021 -+++ b/sys/src/cmd/webfs/http.c Wed Jun 23 17:44:24 2021 -@@ -131,7 +131,7 @@ - if(strcmp(proxy->scheme, "https") == 0) - fd = tlswrap(fd, proxy->host); - } else { -- if(strcmp(u->scheme, "https") == 0) -+ if(strcmp(u->scheme, "https") == 0 || strcmp(u->scheme, "wss") == 0) - fd = tlswrap(fd, u->host); - } - if(fd < 0){ -@@ -520,7 +520,7 @@ - void - http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost) - { -- int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody, badauth; -+ int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody, badauth, wantwebsocket; - char *s, *x, buf[8192+2], status[256], method[16], *host; - vlong length, offset; - Url ru, tu, *nu; -@@ -549,8 +549,13 @@ - break; - } - -+ if(!strcmp(u->scheme, "ws") || !strcmp(u->scheme, "wss")) -+ wantwebsocket = 1; -+ else -+ wantwebsocket = 0; -+ - notify(catch); -- if(qpost){ -+ if(qpost && !wantwebsocket){ - /* file for spooling the postbody if we need to restart the request */ - snprint(buf, sizeof(buf), "/tmp/http.%d.%d.post", getppid(), getpid()); - fd = create(buf, OEXCL|ORDWR|ORCLOSE, 0600); -@@ -565,7 +570,7 @@ - badauth = 0; - for(try = 0; try < 12; try++){ - strcpy(status, "0 No status"); -- if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https"))){ -+ if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https") && strcmp(u->scheme, "ws") && strcmp(u->scheme, "wss"))){ - werrstr("bad url scheme"); - break; - } -@@ -591,7 +596,7 @@ - - length = 0; - chunked = 0; -- if(qpost){ -+ if(qpost && !wantwebsocket){ - /* have to read it to temp file to figure out the length */ - if(fd >= 0 && needlength && lookkey(shdr, "Content-Length") == nil){ - seek(fd, 0, 2); -@@ -700,7 +705,7 @@ - goto Retry; - } - -- if(qpost && !h->tunnel){ -+ if(qpost && !h->tunnel && !wantwebsocket){ - h->cancel = 0; - if((pid = rfork(RFMEM|RFPROC)) <= 0){ - int ifd; -@@ -802,8 +807,42 @@ - goto Status; - } - goto Error; -- case 100: /* Continue */ - case 101: /* Switching Protocols */ -+ if(wantwebsocket){ -+ int ok = 1; -+ char *wskey = lookkey(shdr, "Sec-WebSocket-Key"); -+ -+ k = getkey(rhdr, "Upgrade"); -+ if(k == nil || cistrcmp(k->val, "websocket") != 0) -+ ok = 0; -+ -+ k = getkey(rhdr, "Connection"); -+ if(k == nil && cistrcmp(k->val, "upgrade") != 0) -+ ok = 0; -+ -+ k = getkey(rhdr, "Sec-WebSocket-Accept"); -+ if(k == nil || wskey == nil) -+ ok = 0; -+ else{ -+ uchar digest[SHA1dlen]; -+ char *str = smprint("%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", wskey); -+ -+ sha1((uchar*)str, strlen(str), digest, nil); -+ char *val = smprint("%.*[", SHA1dlen, digest); -+ if(strcmp(val, k->val) != 0) -+ ok = 0; -+ free(str); -+ free(val); -+ } -+ -+ if(ok){ -+ qbody->url = u; u = nil; -+ qbody->hdr = rhdr; rhdr = nil; -+ websocket(h->fd, qbody, qpost); -+ } -+ goto Error; -+ } -+ case 100: /* Continue */ - case 102: /* Processing */ - case 103: /* Early Hints */ - while(k = rhdr){ ---- a/sys/src/cmd/webfs/mkfile Mon Jun 21 17:38:11 2021 -+++ b/sys/src/cmd/webfs/mkfile Wed Jun 23 17:44:24 2021 -@@ -3,6 +3,6 @@ - TARG=webfs - - HFILES=fns.h dat.h --OFILES=sub.$O url.$O buq.$O http.$O fs.$O -+OFILES=sub.$O url.$O buq.$O http.$O websocket.$O fs.$O - - -+#include -+#include -+#include -+#include <9p.h> -+#include -+ -+#include "dat.h" -+#include "fns.h" -+ -+typedef struct Frame Frame; -+typedef struct Message Message; -+ -+struct Frame -+{ -+ int final; -+ int opcode; -+ int masked; -+ uchar maskkey[4]; -+ uvlong length; -+ uchar *data; -+ -+ Frame *next; /* Chain frames in a message together */ -+}; -+ -+struct Message -+{ -+ int type; -+ uvlong length; -+ uchar *data; -+}; -+ -+enum { -+ ContinueFrame = 0x0, -+ TextFrame = 0x1, -+ BinaryFrame = 0x2, -+ CloseFrame = 0x8, -+ PingFrame = 0x9, -+ PongFrame = 0xA, -+}; -+ -+void writemessage(int, Message *); -+ -+void -+maskframe(Frame *f) -+{ -+ uvlong i; -+ for(i = 0; i < f->length; i++) -+ f->data[i] = f->data[i] ^ f->maskkey[i%4]; -+} -+ -+Frame * -+readframe(int fd) -+{ -+ Frame *f = malloc(sizeof(Frame)); -+ long n; -+ int offset; -+ uchar len; -+ -+ uchar buf[4096]; -+ -+Again: -+ offset = 0; -+ n = read(fd, buf, 2); -+ if(n != 2) -+ goto Error; -+ -+ f->final = (buf[offset] >> 7) & 0x1; -+ /* ignore rsv1, rsv2, rsv3 */ -+ f->opcode = buf[offset] & 0x0F; -+ offset++; -+ -+ f->masked = (buf[offset] >> 7) & 0x1; -+ len = buf[offset] & 0x7F; -+ offset++; -+ -+ if(len <= 125) -+ f->length = len; -+ else if(len == 126){ -+ n = read(fd, buf+offset, 2); -+ if(n != 2) -+ goto Error; -+ -+ f->length = buf[offset++] << 8; -+ f->length |= buf[offset++]; -+ }else if(len == 127){ -+ n = read(fd, buf+offset, 8); -+ if(n != 8) -+ goto Error; -+ f->length = (uvlong)buf[offset++] << 56; -+ f->length |= (uvlong)buf[offset++] << 48; -+ f->length |= (uvlong)buf[offset++] << 40; -+ f->length |= (uvlong)buf[offset++] << 32; -+ f->length |= buf[offset++] << 24; -+ f->length |= buf[offset++] << 16; -+ f->length |= buf[offset++] << 8; -+ f->length |= buf[offset++]; -+ } -+ -+ if(f->masked){ -+ n = read(fd, buf+offset, 4); -+ if(n != 4) -+ goto Error; -+ -+ f->maskkey[0] = buf[offset++]; -+ f->maskkey[1] = buf[offset++]; -+ f->maskkey[2] = buf[offset++]; -+ f->maskkey[3] = buf[offset]; -+ } -+ -+ f->data = malloc(f->length); -+ readn(fd, f->data, f->length); -+ if(f->masked) -+ maskframe(f); -+ -+ if(f->opcode == PingFrame){ -+ Message *m = malloc(sizeof(Message)); -+ m->type = PongFrame; -+ m->length = f->length; -+ m->data = f->data; -+ writemessage(fd, m); /* SHOULD LOCK */ -+ free(m); -+ free(f->data); -+ goto Again; -+ } -+ -+ return f; -+Error: -+ exits("Readframe failed"); -+ return nil; -+} -+ -+Message * -+framestomessage(Frame *frames) -+{ -+ Message *m = malloc(sizeof(Message)); -+ uvlong length = 0; -+ uvlong offset = 0; -+ -+ Frame *f; -+ for(f = frames; f != nil; f = f->next) -+ length += f->length; -+ -+ m->type = frames->opcode; -+ m->length = length; -+ m->data = malloc(length); -+ for(f = frames; f != nil; f = f->next){ -+ memcpy(m->data + offset, f->data, f->length); -+ offset += f->length; -+ } -+ -+ return m; -+} -+ -+Message * -+readmsg(int fd) -+{ -+ Frame *frames = readframe(fd); -+ Frame *last = frames; -+ Message *m; -+ -+ while(!last->final){ -+ last->next = readframe(fd); -+ last = last->next; -+ } -+ last->next = nil; -+ -+ m = framestomessage(frames); -+ while(frames){ -+ Frame *f = frames->next; -+ free(frames->data); -+ free(frames); -+ frames = f; -+ } -+ return m; -+} -+ -+void -+writeframe(int fd, Frame *f) -+{ -+ uchar *buf; -+ uvlong totsize = 0; -+ uvlong offset = 0; -+ int lenbytes = 0; -+ -+ totsize += 2; /* Always there */ -+ if(f->length == 126) -+ lenbytes = 2; -+ else if(f->length == 127) -+ lenbytes = 8; -+ totsize += lenbytes; -+ -+ if(f->masked) -+ totsize += 4; -+ -+ totsize += f->length; -+ -+ buf = malloc(totsize); -+ -+ buf[offset] = f->final << 7; -+ buf[offset++] |= f->opcode; -+ buf[offset] = f->masked << 7; -+ -+ if(lenbytes == 0) -+ buf[offset++] |= f->length; -+ else if(lenbytes == 2) -+ buf[offset++] |= 126; -+ else if(lenbytes == 8) -+ buf[offset++] |= 127; -+ -+ if(lenbytes == 2){ -+ buf[offset++] = 0xFF & (f->length >> 8); -+ buf[offset++] = 0xFF & f->length; -+ }else if(lenbytes == 8){ -+ buf[offset++] = 0xFF & (f->length >> 56); -+ buf[offset++] = 0xFF & (f->length >> 48); -+ buf[offset++] = 0xFF & (f->length >> 40); -+ buf[offset++] = 0xFF & (f->length >> 32); -+ buf[offset++] = 0xFF & (f->length >> 24); -+ buf[offset++] = 0xFF & (f->length >> 16); -+ buf[offset++] = 0xFF & (f->length >> 8); -+ buf[offset++] = 0xFF & f->length; -+ } -+ -+ if(f->masked){ -+ buf[offset++] = f->maskkey[0]; -+ buf[offset++] = f->maskkey[1]; -+ buf[offset++] = f->maskkey[2]; -+ buf[offset++] = f->maskkey[3]; -+ } -+ -+ memcpy(buf + offset, f->data, f->length); -+ write(fd, buf, totsize); -+} -+ -+void -+writemessage(int fd, Message *m) -+{ -+ /* Could split up the message into frames but not right now. */ -+ -+ Frame *f = malloc(sizeof(Frame)); -+ f->final = 1; -+ f->opcode = m->type; -+ f->masked = 1; -+ genrandom(f->maskkey, 4); -+ f->length = m->length; -+ f->data = malloc(f->length); -+ memcpy(f->data, m->data, f->length); -+ maskframe(f); -+ f->next = nil; -+ -+ writeframe(fd, f); -+ free(f->data); -+ free(f); -+} -+ -+void -+websocketrecv(int fd, Buq *qbody) -+{ -+ /* -+ * Plan: Read frames and when we have a whole message do: -+ * 1) If control, act on it -+ * 2) If data, format as text and buwrite it -+ */ -+ while(1){ -+ Message *m = readmsg(fd); -+ //print("Received message type=%d length=%ulld\n", m->type, m->length); -+ -+ if(m->type == TextFrame || m->type == BinaryFrame){ -+ char *header; -+ if(m->type == TextFrame) -+ header = smprint("t %0.20ulld", m->length); -+ else -+ header = smprint("b %0.20ulld", m->length); -+ buwrite(qbody, header, 22); -+ buwrite(qbody, m->data, m->length); -+ } -+ free(m->data); -+ free(m); -+ } -+} -+ -+void -+websocketsend(int fd, Buq *qpost) -+{ -+ /* buread messages and pack them up in frames and send them */ -+ char buf[64]; -+ long n; -+ Message *m; -+ while(1){ -+ n = buread(qpost, buf, 22); -+ if(n != 22){ -+ buclose(qpost, "Header short"); -+ return; -+ } -+ buf[n] = 0; -+ -+ m = malloc(sizeof(Message)); -+ if(buf[0] == 't') -+ m->type = TextFrame; -+ else if(buf[0] == 'b') -+ m->type = BinaryFrame; -+ -+ char *ret; -+ m->length = strtoull(buf+2, &ret, 10); -+ if(ret != buf+22){ -+ buclose(qpost, "Header format wrong"); -+ return; -+ } -+ -+ m->data = malloc(m->length); -+ n = 0; -+ while(n < m->length){ -+ uvlong missing = m->length - n; -+ n += buread(qpost, m->data + n, (missing < 8192) ? missing : 8192); -+ } -+ -+ writemessage(fd, m); -+ free(m->data); -+ free(m); -+ } -+} -+ -+void -+websocket(int fd, Buq *qbody, Buq *qpost) -+{ -+ buwrite(qbody, "websocket ready\n", 16); -+ switch(rfork(RFPROC|RFMEM)){ -+ default: -+ websocketrecv(fd, qbody); -+ break; -+ case 0: -+ websocketsend(fd, qpost); -+ goto End; -+ case -1: -+ buclose(qbody, "can't fork"); -+ bufree(qbody); -+ buclose(qpost, "can't fork"); -+ bufree(qpost); -+ break; -+ } -+End: -+ close(fd); -+ buclose(qbody, nil); -+ bufree(qbody); -+ buclose(qpost, nil); -+ bufree(qpost); -+ exits(nil); -+} -- cgit v1.2.3