summaryrefslogtreecommitdiff
path: root/src/user/app/netstack/tcp.c
diff options
context:
space:
mode:
authordzwdz2022-08-24 00:22:48 +0200
committerdzwdz2022-08-24 00:22:48 +0200
commit9201820097ef333e967f72450dc18ea727c30e2e (patch)
treedf048f2dd99627ff2be35fc2717203001cd5d97e /src/user/app/netstack/tcp.c
parent49e2767cad2fd366b4edc56077103403e4e59d71 (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.c43
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;