summaryrefslogtreecommitdiff
path: root/src/user
diff options
context:
space:
mode:
authordzwdz2022-08-24 00:22:48 +0200
committerdzwdz2022-08-24 00:22:48 +0200
commit9201820097ef333e967f72450dc18ea727c30e2e (patch)
treedf048f2dd99627ff2be35fc2717203001cd5d97e /src/user
parent49e2767cad2fd366b4edc56077103403e4e59d71 (diff)
user/netstack: TCP outgoing
I got on IRC!
Diffstat (limited to 'src/user')
-rw-r--r--src/user/app/netstack/fs.c19
-rw-r--r--src/user/app/netstack/proto.h5
-rw-r--r--src/user/app/netstack/tcp.c43
3 files changed, 67 insertions, 0 deletions
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;