summaryrefslogtreecommitdiff
path: root/src/user/app/netstack/fs.c
diff options
context:
space:
mode:
authordzwdz2023-08-14 18:51:07 +0200
committerdzwdz2023-08-14 18:51:07 +0200
commit642b5fb0007b64c77d186fcb018d571152ee1d47 (patch)
tree1c466461f3602d306be309a053edae558ef2568e /src/user/app/netstack/fs.c
parent8050069c57b729c18c19b1a03ab6e4bf63b4735e (diff)
reorganization: first steps
Diffstat (limited to 'src/user/app/netstack/fs.c')
-rw-r--r--src/user/app/netstack/fs.c320
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);
-}