diff options
author | dzwdz | 2023-08-14 18:51:07 +0200 |
---|---|---|
committer | dzwdz | 2023-08-14 18:51:07 +0200 |
commit | 642b5fb0007b64c77d186fcb018d571152ee1d47 (patch) | |
tree | 1c466461f3602d306be309a053edae558ef2568e /src/user/app/netstack/fs.c | |
parent | 8050069c57b729c18c19b1a03ab6e4bf63b4735e (diff) |
reorganization: first steps
Diffstat (limited to 'src/user/app/netstack/fs.c')
-rw-r--r-- | src/user/app/netstack/fs.c | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c deleted file mode 100644 index 6d51c35..0000000 --- a/src/user/app/netstack/fs.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * path format: - * /net/raw - * raw ethernet frames (read-write) - * /net/arp - * ARP cache (currently read-only) - * /net/connect/0.0.0.0/1.2.3.4/udp/53 - * connect from 0.0.0.0 (any ip) to 1.2.3.4 on udp port 53 - * /net/listen/0.0.0.0/{tcp,udp}/53 - * waits for a connection to any ip on udp port 53 - * open() returns once a connection to ip 0.0.0.0 on udp port 53 is received - */ -#include "proto.h" -#include "util.h" -#include <camellia/flags.h> -#include <camellia/syscalls.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -enum handle_type { - H_ETHER, - H_TCP, - H_UDP, - H_ARP, -}; - -struct strqueue { - struct strqueue *next; - size_t len; - char buf[]; -}; - -struct handle { - enum handle_type type; - struct { - struct udp_conn *c; - struct strqueue *rx, *rxlast; - } udp; - struct { - struct tcp_conn *c; - size_t readcap; - } tcp; - bool dead; - hid_t reqh; -}; - - -static void tcp_listen_callback(struct tcp_conn *c, void *arg) { - struct handle *h = arg; - h->tcp.c = c; - _sys_fs_respond(h->reqh, h, 0, 0); - h->reqh = -1; -} - -/* also called from recv_enqueue. yes, it's a mess */ -static void tcp_recv_callback(void *arg) { - struct handle *h = arg; - char buf[1024]; - if (h->reqh >= 0) { - if (h->tcp.readcap > sizeof buf) - h->tcp.readcap = sizeof buf; - size_t len = tcpc_tryread(h->tcp.c, buf, h->tcp.readcap); - if (len > 0) { - _sys_fs_respond(h->reqh, buf, len, 0); - h->reqh = -1; - } - } -} - -static void tcp_close_callback(void *arg) { - struct handle *h = arg; - h->dead = true; - if (h->reqh >= 0) { - _sys_fs_respond(h->reqh, NULL, -ECONNRESET, 0); - h->reqh = -1; - return; - } -} - -static void udp_listen_callback(struct udp_conn *c, void *arg) { - struct handle *h = arg; - h->udp.c = c; - _sys_fs_respond(h->reqh, h, 0, 0); - h->reqh = -1; -} - -static void udp_recv_callback(const void *buf, size_t len, void *arg) { - struct handle *h = arg; - if (h->reqh >= 0) { - _sys_fs_respond(h->reqh, buf, len, 0); - h->reqh = -1; - return; - } - struct strqueue *sq = malloc(sizeof(*sq) + len); - sq->next = NULL; - sq->len = len; - memcpy(sq->buf, buf, len); - if (h->udp.rx) { - h->udp.rxlast->next = sq; - h->udp.rxlast = sq; - } else { - h->udp.rx = sq; - h->udp.rxlast = sq; - } -} - -static void recv_enqueue(struct handle *h, hid_t reqh, size_t readcap) { - if (h->reqh > 0) { - // TODO queue - _sys_fs_respond(reqh, NULL, -1, 0); - return; - } - if (h->type == H_UDP && h->udp.rx) { - _sys_fs_respond(reqh, h->udp.rx->buf, h->udp.rx->len, 0); - h->udp.rx = h->udp.rx->next; - free(h->udp.rx); - return; - } - h->reqh = reqh; - if (h->type == H_TCP) { - h->tcp.readcap = readcap; - tcp_recv_callback(h); - } -} - -static void fs_open(hid_t reqh, char *path, int flags) { -#define respond(buf, val) do{ _sys_fs_respond(reqh, buf, val, 0); return; }while(0) - struct handle *h; - if (*path != '/') respond(NULL, -1); - path++; - - if (strcmp(path, "raw") == 0) { - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_ETHER; - respond(h, 0); - } else if (strcmp(path, "arp") == 0) { - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_ARP; - respond(h, 0); - } - - /* everything below ends up sending packets */ - if (!OPEN_WRITEABLE(flags)) - respond(NULL, -EACCES); - - char *save; - const char *verb, *proto, *port_s; - uint32_t srcip, dstip; - - verb = strtok_r(path, "/", &save); - if (!verb) respond(NULL, -1); - - if (ip_parse(strtok_r(NULL, "/", &save), &srcip) < 0) - respond(NULL, -1); - if (srcip != 0) { - eprintf("unimplemented"); - respond(NULL, -1); - } - - if (strcmp(verb, "listen") == 0) { - proto = strtok_r(NULL, "/", &save); - if (!proto) respond(NULL, -1); - if (strcmp(proto, "udp") == 0) { - port_s = strtok_r(NULL, "/", &save); - if (port_s) { - uint16_t port = strtol(port_s, NULL, 0); - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_UDP; - h->reqh = reqh; - udp_listen(port, udp_listen_callback, udp_recv_callback, h); - return; - } - } - if (strcmp(proto, "tcp") == 0) { - port_s = strtok_r(NULL, "/", &save); - if (port_s) { - uint16_t port = strtol(port_s, NULL, 0); - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_TCP; - h->reqh = reqh; - tcp_listen(port, tcp_listen_callback, tcp_recv_callback, tcp_close_callback, h); - return; - } - } - } else if (strcmp(verb, "connect") == 0) { - if (ip_parse(strtok_r(NULL, "/", &save), &dstip) < 0) - respond(NULL, -1); - proto = strtok_r(NULL, "/", &save); - if (!proto) respond(NULL, -1); - if (strcmp(proto, "tcp") == 0) { - port_s = strtok_r(NULL, "/", &save); - if (port_s) { - uint16_t port = strtol(port_s, NULL, 0); - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_TCP; - h->tcp.c = tcpc_new((struct tcp){ - .dst = port, - .ip.dst = dstip, - }, tcp_recv_callback, tcp_close_callback, h); - if (h->tcp.c) { - respond(h, 0); - } else { - free(h); - respond(NULL, -1); - } - } - } - if (strcmp(proto, "udp") == 0) { - port_s = strtok_r(NULL, "/", &save); - if (port_s) { - uint16_t port = strtol(port_s, NULL, 0); - h = malloc(sizeof *h); - memset(h, 0, sizeof *h); - h->type = H_UDP; - h->udp.c = udpc_new((struct udp){ - .dst = port, - .ip.dst = dstip, - }, udp_recv_callback, h); - if (h->udp.c) { - respond(h, 0); - } else { - free(h); - respond(NULL, -1); - } - } - } - } - respond(NULL, -1); -#undef respond -} - -void fs_thread(void *arg) { (void)arg; - const size_t buflen = 4096; - char *buf = malloc(buflen); - for (;;) { - struct ufs_request res; - hid_t reqh = _sys_fs_wait(buf, buflen, &res); - if (reqh < 0) break; - struct handle *h = res.id; - long ret; - switch (res.op) { - case VFSOP_OPEN: - if (res.len < buflen) { - buf[res.len] = '\0'; - fs_open(reqh, buf, res.flags); - } else { - _sys_fs_respond(reqh, NULL, -1, 0); - } - break; - case VFSOP_READ: - if (h->dead) { - _sys_fs_respond(reqh, NULL, -ECONNRESET, 0); - break; - } - switch (h->type) { - case H_ETHER: { - struct ethq *qe; - qe = malloc(sizeof *qe); - qe->h = reqh; - qe->next = ether_queue; - ether_queue = qe; - break;} - case H_TCP: - case H_UDP: - recv_enqueue(h, reqh, res.capacity); - break; - case H_ARP: - arp_fsread(reqh, res.offset); - break; - default: - _sys_fs_respond(reqh, NULL, -1, 0); - } - break; - case VFSOP_WRITE: - if (h->dead) { - _sys_fs_respond(reqh, NULL, -ECONNRESET, 0); - break; - } - switch (h->type) { - case H_ETHER: - ret = _sys_write(state.raw_h, buf, res.len, 0, 0); - _sys_fs_respond(reqh, NULL, ret, 0); - break; - case H_TCP: - tcpc_send(h->tcp.c, buf, res.len); - _sys_fs_respond(reqh, NULL, res.len, 0); - break; - case H_UDP: - udpc_send(h->udp.c, buf, res.len); - _sys_fs_respond(reqh, NULL, res.len, 0); - break; - case H_ARP: - _sys_fs_respond(reqh, NULL, arp_fswrite(buf, res.len, res.offset), 0); - break; - default: - _sys_fs_respond(reqh, NULL, -1, 0); - } - break; - case VFSOP_CLOSE: - // TODO remove entries in queue - // TODO why does close even have _sys_fs_respond? - if (h->type == H_TCP) tcpc_close(h->tcp.c); - if (h->type == H_UDP) udpc_close(h->udp.c); - free(h); - _sys_fs_respond(reqh, NULL, -1, 0); - break; - default: - _sys_fs_respond(reqh, NULL, -1, 0); - break; - } - } - free(buf); -} |