diff options
author | dzwdz | 2022-08-24 00:22:48 +0200 |
---|---|---|
committer | dzwdz | 2022-08-24 00:22:48 +0200 |
commit | 9201820097ef333e967f72450dc18ea727c30e2e (patch) | |
tree | df048f2dd99627ff2be35fc2717203001cd5d97e /src/user/app/netstack/tcp.c | |
parent | 49e2767cad2fd366b4edc56077103403e4e59d71 (diff) |
user/netstack: TCP outgoing
I got on IRC!
Diffstat (limited to 'src/user/app/netstack/tcp.c')
-rw-r--r-- | src/user/app/netstack/tcp.c | 43 |
1 files changed, 43 insertions, 0 deletions
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; |