From 9201820097ef333e967f72450dc18ea727c30e2e Mon Sep 17 00:00:00 2001 From: dzwdz Date: Wed, 24 Aug 2022 00:22:48 +0200 Subject: user/netstack: TCP outgoing I got on IRC! --- src/user/app/netstack/fs.c | 19 +++++++++++++++++++ src/user/app/netstack/proto.h | 5 +++++ src/user/app/netstack/tcp.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c index b50e778..f4d9625 100644 --- a/src/user/app/netstack/fs.c +++ b/src/user/app/netstack/fs.c @@ -185,6 +185,25 @@ static void fs_open(handle_t reqh, char *path) { 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) { diff --git a/src/user/app/netstack/proto.h b/src/user/app/netstack/proto.h index 738f09e..30ff864 100644 --- a/src/user/app/netstack/proto.h +++ b/src/user/app/netstack/proto.h @@ -95,6 +95,11 @@ void tcp_listen( void (*on_recv)(void *carg), void (*on_close)(void *carg), void *carg); +struct tcp_conn *tcpc_new( + struct tcp t, + void (*on_recv)(void *carg), + void (*on_close)(void *carg), + void *carg); size_t tcpc_tryread(struct tcp_conn *, void *buf, size_t len); void tcpc_send(struct tcp_conn *, const void *buf, size_t len); void tcpc_close(struct tcp_conn *); diff --git a/src/user/app/netstack/tcp.c b/src/user/app/netstack/tcp.c index a1b0759..9e6e3bb 100644 --- a/src/user/app/netstack/tcp.c +++ b/src/user/app/netstack/tcp.c @@ -31,7 +31,9 @@ enum { enum tcp_state { LISTEN, + SYN_SENT, SYN_RCVD, + ESTABILISHED, LAST_ACK, CLOSED, }; @@ -93,6 +95,7 @@ void tcp_listen( void *carg) { struct tcp_conn *c = malloc(sizeof *c); + memset(c, 0, sizeof *c); c->lport = port; c->lip = state.ip; c->state = LISTEN; @@ -104,6 +107,35 @@ void tcp_listen( c->rx = (ring_t){malloc(4096), 4096, 0, 0}; conns_append(c); } +struct tcp_conn *tcpc_new( + struct tcp t, + void (*on_recv)(void *carg), + void (*on_close)(void *carg), + void *carg) +{ + struct tcp_conn *c = malloc(sizeof *c); + memset(c, 0, sizeof *c); + c->lip = t.ip.src ? t.ip.src : state.ip; + c->rip = t.ip.dst; + c->lport = t.src ? t.src : 50002; // TODO randomize source ports + c->rport = t.dst; + if (arpcache_get(c->rip, &c->rmac) < 0) { + // TODO make arp request, wait for reply + eprintf("not in ARP cache, unimplemented"); + free(c); + return NULL; + } + + c->state = SYN_SENT; + c->on_recv = on_recv; + c->on_close = on_close; + c->carg = carg; + c->rx = (ring_t){malloc(4096), 4096, 0, 0}; + conns_append(c); + + tcpc_sendraw(c, FlagSYN, NULL, 0); + return c; +} size_t tcpc_tryread(struct tcp_conn *c, void *buf, size_t len) { if (!buf) return ring_used(&c->rx); return ring_get(&c->rx, buf, len); @@ -163,6 +195,17 @@ void tcp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) { if (iter->rip == ip.src && iter->rport == srcport) { // TODO doesn't handle seq/ack overflows + if (iter->state == SYN_SENT) { + if (flags & FlagSYN) { + iter->state = ESTABILISHED; + iter->lack = seq + 1; + tcpc_sendraw(iter, FlagACK, NULL, 0); + return; + } else { + // TODO resend syn? + return; + } + } if (flags & FlagACK) { if (iter->rack < acknum) iter->rack = acknum; -- cgit v1.2.3