summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-11 13:33:01 +0200
committerAnton Kling <anton@kling.gg>2024-06-11 15:18:40 +0200
commitabf9cf5bec2712465400417cc8232fee2d1cce28 (patch)
tree3e43f9cc8e194aa20de6e2e5a1916a10ced69f44 /kernel
parentb118759096ef08bfcc003933059de46a7a964ad7 (diff)
TCP stuff
Diffstat (limited to 'kernel')
-rw-r--r--kernel/lib/relist.c7
-rw-r--r--kernel/lib/relist.h1
-rw-r--r--kernel/network/ethernet.c2
-rw-r--r--kernel/network/ipv4.c8
-rw-r--r--kernel/network/tcp.c269
-rw-r--r--kernel/network/tcp.h7
-rw-r--r--kernel/network/udp.c3
-rw-r--r--kernel/network/udp.h2
-rw-r--r--kernel/socket.c37
-rw-r--r--kernel/socket.h6
10 files changed, 253 insertions, 89 deletions
diff --git a/kernel/lib/relist.c b/kernel/lib/relist.c
index 01af884..2e45429 100644
--- a/kernel/lib/relist.c
+++ b/kernel/lib/relist.c
@@ -5,6 +5,7 @@
#include <string.h>
void relist_init(struct relist *list) {
+ list->num_entries = 0;
list->bitmap_capacity = 1;
list->bitmap = kcalloc(sizeof(u64), list->bitmap_capacity);
if (!list->bitmap) {
@@ -28,6 +29,7 @@ relist_init_error:
}
void relist_reset(struct relist *list) {
+ list->num_entries = 0;
memset(list->bitmap, 0, list->bitmap_capacity * sizeof(u64));
}
@@ -43,12 +45,14 @@ int relist_clone(struct relist *in, struct relist *out) {
kfree(out->bitmap);
goto relist_clone_error;
}
+ out->num_entries = in->num_entries;
memcpy(out->bitmap, in->bitmap, sizeof(u64) * out->bitmap_capacity);
memcpy(out->entries, in->entries,
sizeof(void *) * sizeof(u64) * 8 * out->bitmap_capacity);
return 1;
relist_clone_error:
+ out->num_entries = 0;
out->bitmap_capacity = 0;
out->entries = NULL;
out->bitmap = NULL;
@@ -100,6 +104,7 @@ int relist_add(struct relist *list, void *value, u32 *index) {
if (index) {
*index = entry;
}
+ list->num_entries++;
list->bitmap[entry / 64] |= ((u64)1 << (entry % 64));
return 1;
}
@@ -114,6 +119,7 @@ int relist_remove(struct relist *list, u32 index) {
assert(0);
return 0;
}
+ list->num_entries--;
list->bitmap[index / 64] &= ~((u64)1 << (index % 64));
return 1;
}
@@ -148,6 +154,7 @@ int relist_get(const struct relist *list, u32 index, void **out, int *end) {
}
void relist_free(struct relist *list) {
+ list->num_entries = 0;
list->bitmap_capacity = 0;
kfree(list->entries);
kfree(list->bitmap);
diff --git a/kernel/lib/relist.h b/kernel/lib/relist.h
index 734e5dc..409032d 100644
--- a/kernel/lib/relist.h
+++ b/kernel/lib/relist.h
@@ -5,6 +5,7 @@
struct relist {
void **entries;
u32 bitmap_capacity;
+ u32 num_entries;
u64 *bitmap;
};
diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c
index cf2e047..1bda07f 100644
--- a/kernel/network/ethernet.c
+++ b/kernel/network/ethernet.c
@@ -62,7 +62,7 @@ void handle_ethernet(const u8 *packet, u64 packet_length) {
handle_ipv4(payload, packet_length - sizeof(struct ETHERNET_HEADER) - 4);
break;
default:
- kprintf("Can't handle ethernet type\n");
+ kprintf("Can't handle ethernet type 0x%x\n", type);
break;
}
}
diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c
index 4fe3799..cceee8e 100644
--- a/kernel/network/ipv4.c
+++ b/kernel/network/ipv4.c
@@ -84,15 +84,17 @@ void handle_ipv4(const u8 *payload, u32 packet_length) {
assert(ipv4_total_length <= packet_length);
ipv4_t src_ip;
- memcpy(&src_ip, payload + 12, sizeof(u8[4]));
+ memcpy(&src_ip.d, payload + 12, sizeof(u8[4]));
+ ipv4_t dst_ip;
+ memcpy(&dst_ip.d, payload + 16, sizeof(u8[4]));
u8 protocol = *(payload + 9);
switch (protocol) {
case 0x6:
- handle_tcp(src_ip, payload + 20, ipv4_total_length - 20);
+ handle_tcp(src_ip, dst_ip, payload + 20, ipv4_total_length - 20);
break;
case 0x11:
- handle_udp(src_ip, payload + 20, ipv4_total_length - 20);
+ handle_udp(src_ip, dst_ip, payload + 20, ipv4_total_length - 20);
break;
default:
kprintf("Protocol given in IPv4 header not handeld: %x\n", protocol);
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index aeabbf2..fc8d97c 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -1,10 +1,13 @@
#include <assert.h>
#include <cpu/arch_inst.h>
#include <drivers/pit.h>
+#include <fs/vfs.h>
+#include <math.h>
#include <network/arp.h>
#include <network/bytes.h>
#include <network/ipv4.h>
#include <network/udp.h>
+#include <random.h>
#define CWR (1 << 7)
#define ECE (1 << 6)
@@ -15,6 +18,8 @@
#define SYN (1 << 1)
#define FIN (1 << 0)
+#define MSS 536
+
// FIXME: This should be dynamic
#define WINDOW_SIZE 4096
@@ -73,28 +78,82 @@ u16 tcp_checksum(u16 *buffer, int size) {
return (u16)(~cksum);
}
-void tcp_calculate_checksum(ipv4_t src_ip, u32 dst_ip, const u8 *payload,
- u16 payload_length, struct TCP_HEADER *header) {
- struct PSEUDO_TCP_HEADER ps;
- memset(&ps, 0, sizeof(ps));
- memcpy(&ps.src_addr, &src_ip.d, sizeof(u32));
- memcpy(&ps.dst_addr, &dst_ip, sizeof(u32));
- ps.protocol = 6;
- ps.tcp_length = htons(20 + payload_length);
- ps.src_port = header->src_port;
- ps.dst_port = header->dst_port;
- ps.seq_num = header->seq_num;
- ps.ack_num = header->ack_num;
- ps.data_offset = header->data_offset;
- ps.reserved = header->reserved;
- ps.flags = header->flags;
- ps.window_size = header->window_size;
- ps.urgent_pointer = header->urgent_pointer;
- int buffer_length = sizeof(ps) + payload_length;
+u16 tcp_calculate_checksum(ipv4_t src_ip, u32 dst_ip, const u8 *payload,
+ u16 payload_length, const struct TCP_HEADER *header,
+ int total) {
+ if (total < header->data_offset + payload_length) {
+ return 0;
+ }
+
+ int pseudo = sizeof(u32) * 2 + sizeof(u16) + sizeof(u8) * 2;
+
+ int buffer_length =
+ pseudo + header->data_offset * sizeof(u32) + payload_length;
u8 buffer[buffer_length];
- memcpy(buffer, &ps, sizeof(ps));
- memcpy(buffer + sizeof(ps), payload, payload_length);
- header->checksum = tcp_checksum((u16 *)buffer, buffer_length);
+ u8 *ptr = buffer;
+ memcpy(ptr, &src_ip.d, sizeof(u32));
+ ptr += sizeof(u32);
+ memcpy(ptr, &dst_ip, sizeof(u32));
+ ptr += sizeof(u32);
+ *ptr = 0;
+ ptr += sizeof(u8);
+ *ptr = 6;
+ ptr += sizeof(u8);
+ *(u16 *)ptr = htons(header->data_offset * sizeof(u32) + payload_length);
+ ptr += sizeof(u16);
+ memcpy(ptr, header, header->data_offset * sizeof(u32));
+ memset(ptr + 16, 0, sizeof(u16)); // set checksum to zero
+ ptr += header->data_offset * sizeof(u32);
+ memcpy(ptr, payload, payload_length);
+
+ return tcp_checksum((u16 *)buffer, buffer_length);
+}
+
+struct TcpPacket {
+ u32 time;
+ u32 seq_num;
+ u16 payload_length;
+ u8 *buffer;
+ u16 length;
+};
+
+static void tcp_send(struct TcpConnection *con, u8 *buffer, u16 length,
+ u32 seq_num, u32 payload_length) {
+ if (payload_length > 0) {
+ struct TcpPacket *packet = kmalloc(sizeof(struct TcpPacket));
+ assert(packet);
+ packet->time = pit_num_ms();
+ packet->seq_num = seq_num;
+ packet->buffer = buffer;
+ packet->length = length;
+ packet->payload_length = payload_length;
+
+ assert(relist_add(&con->inflight, packet, NULL));
+ }
+ send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, buffer, length);
+}
+
+void tcp_resend_packets(struct TcpConnection *con) {
+ if (con->inflight.num_entries > 0) {
+ for (u32 i = 0;; i++) {
+ struct TcpPacket *packet;
+ int end;
+ if (!relist_get(&con->inflight, i, (void *)&packet, &end)) {
+ if (end) {
+ break;
+ }
+ continue;
+ }
+ if (packet->time + 200 > pit_num_ms()) {
+ continue;
+ }
+ // resend the packet
+ relist_remove(&con->inflight, i);
+ tcp_send(con, packet->buffer, packet->length, packet->seq_num,
+ packet->payload_length);
+ kfree(packet);
+ }
+ }
}
void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
@@ -111,14 +170,15 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
u8 payload[0];
u16 payload_length = 0;
- tcp_calculate_checksum(ip_address, con->outgoing_ip, (const u8 *)payload,
- payload_length, &header);
+ header.checksum = tcp_calculate_checksum(
+ ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
+ &header, sizeof(struct TCP_HEADER) + payload_length);
int send_len = sizeof(header) + payload_length;
- u8 send_buffer[send_len];
+ u8 *send_buffer = kmalloc(send_len);
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
- send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, send_buffer, send_len);
+ tcp_send(con, send_buffer, send_len, con->seq, 0);
}
void tcp_close_connection(struct TcpConnection *con) {
@@ -134,12 +194,30 @@ void tcp_send_syn(struct TcpConnection *con) {
con->seq++;
}
-void send_tcp_packet(struct TcpConnection *con, const u8 *payload,
- u16 payload_length) {
- if (payload_length > 1500 - 20 - sizeof(struct TCP_HEADER)) {
- send_tcp_packet(con, payload, 1500 - 20 - sizeof(struct TCP_HEADER));
- payload_length -= 1500 - 20 - sizeof(struct TCP_HEADER);
- payload += 1500 - 20 - sizeof(struct TCP_HEADER);
+int tcp_can_send(struct TcpConnection *con, u16 payload_length) {
+ if (con->inflight.num_entries > 2) {
+ tcp_resend_packets(con);
+ return 0;
+ }
+ if (con->seq - con->seq_ack + payload_length > con->current_window_size) {
+ tcp_resend_packets(con);
+ return 0;
+ }
+ return 1;
+}
+
+int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
+ u16 payload_length) {
+ if (!tcp_can_send(con, payload_length)) {
+ return 0;
+ }
+
+ if (payload_length > MSS) {
+ if (0 == send_tcp_packet(con, payload, MSS)) {
+ return 0;
+ }
+ payload_length -= MSS;
+ payload += MSS;
return send_tcp_packet(con, payload, payload_length);
}
struct TCP_HEADER header = {0};
@@ -152,24 +230,37 @@ void send_tcp_packet(struct TcpConnection *con, const u8 *payload,
header.flags = PSH | ACK;
header.window_size = htons(WINDOW_SIZE);
header.urgent_pointer = 0;
- tcp_calculate_checksum(ip_address, con->outgoing_ip, (const u8 *)payload,
- payload_length, &header);
+ header.checksum = tcp_calculate_checksum(
+ ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
+ &header, sizeof(struct TCP_HEADER) + payload_length);
int send_len = sizeof(header) + payload_length;
- u8 send_buffer[send_len];
+ u8 *send_buffer = kmalloc(send_len);
+ assert(send_buffer);
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
- send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, send_buffer, send_len);
+
+ tcp_send(con, send_buffer, send_len, con->seq, payload_length);
con->seq += payload_length;
+ return 1;
}
-void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
+void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload,
+ u32 payload_length) {
const struct TCP_HEADER *header = (const struct TCP_HEADER *)payload;
- (void)header;
+ u16 tcp_payload_length = payload_length - header->data_offset * sizeof(u32);
+ const u8 *tcp_payload = payload + header->data_offset * sizeof(u32);
+ u16 checksum =
+ tcp_calculate_checksum(src_ip, dst_ip.d, tcp_payload, tcp_payload_length,
+ header, payload_length);
+ if (header->checksum != checksum) {
+ return;
+ }
u16 n_src_port = header->src_port;
u16 n_dst_port = header->dst_port;
u32 n_seq_num = header->seq_num;
u32 n_ack_num = header->ack_num;
+ u32 n_window_size = header->window_size;
u8 flags = header->flags;
@@ -177,14 +268,18 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
u16 dst_port = htons(n_dst_port);
u32 seq_num = htonl(n_seq_num);
u32 ack_num = htonl(n_ack_num);
+ u16 window_size = htons(n_window_size);
+
(void)ack_num;
if (SYN == flags) {
struct TcpConnection *con =
internal_tcp_incoming(src_ip.d, src_port, 0, dst_port);
- if(!con) {
+ if (!con) {
return;
}
+ con->window_size = window_size;
+ con->current_window_size = MSS;
con->ack = seq_num + 1;
tcp_send_empty_payload(con, SYN | ACK);
con->seq++;
@@ -195,49 +290,75 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) {
tcp_find_connection(src_ip, src_port, dst_port);
if (!incoming_connection) {
kprintf("unable to find open port for incoming connection\n");
+ return;
+ }
+ incoming_connection->window_size = window_size;
+ incoming_connection->unhandled_packet = 1;
+ if (0 != (flags & RST)) {
+ klog("Requested port is closed", LOG_NOTE);
+ incoming_connection->dead = 1;
+ return;
}
- if (incoming_connection) {
- incoming_connection->unhandled_packet = 1;
- if (0 != (flags & RST)) {
- klog("Requested port is closed", LOG_NOTE);
- incoming_connection->dead = 1;
+ if (ACK == flags) {
+ if (0 == incoming_connection->handshake_state) {
+ // Then it is probably a response to the SYN|ACK we sent.
+ incoming_connection->handshake_state = 1;
return;
}
- if (ACK == flags) {
- if (0 == incoming_connection->handshake_state) {
- // Then it is probably a response to the SYN|ACK we sent.
- incoming_connection->handshake_state = 1;
- return;
+ }
+ if ((SYN | ACK) == flags) {
+ assert(0 == incoming_connection->handshake_state);
+ incoming_connection->handshake_state = 1;
+ incoming_connection->ack = seq_num + 1;
+ tcp_send_ack(incoming_connection);
+ return;
+ }
+ if (ACK & flags) {
+ incoming_connection->seq_ack = ack_num;
+ if (incoming_connection->inflight.num_entries > 0) {
+ for (u32 i = 0;; i++) {
+ struct TcpPacket *packet;
+ int end;
+ if (!relist_get(&incoming_connection->inflight, i, (void *)&packet,
+ &end)) {
+ if (end) {
+ break;
+ }
+ continue;
+ }
+ if (packet->seq_num + packet->payload_length != ack_num) {
+ continue;
+ }
+ relist_remove(&incoming_connection->inflight, i);
+ kfree(packet->buffer);
+ kfree(packet);
+ break;
}
}
- if ((SYN | ACK) == flags) {
- assert(0 == incoming_connection->handshake_state);
- incoming_connection->handshake_state = 1;
-
- incoming_connection->ack = seq_num + 1;
-
- tcp_send_ack(incoming_connection);
- }
- u16 tcp_payload_length = payload_length - header->data_offset * sizeof(u32);
- if (tcp_payload_length > 0) {
- const u8 *tcp_payload = payload + header->data_offset * sizeof(u32);
- u32 len = ringbuffer_write(&incoming_connection->incoming_buffer,
- tcp_payload, tcp_payload_length);
- assert(len == tcp_payload_length);
- incoming_connection->ack += len;
- tcp_send_ack(incoming_connection);
+ tcp_resend_packets(incoming_connection);
+ if (0 == incoming_connection->inflight.num_entries) {
+ u32 rest = incoming_connection->window_size -
+ incoming_connection->current_window_size;
+ if (rest > 0) {
+ incoming_connection->current_window_size += min(rest, MSS);
+ }
}
- if (0 != (flags & FIN)) {
- incoming_connection->ack++;
+ }
+ if (tcp_payload_length > 0) {
+ u32 len = ringbuffer_write(&incoming_connection->incoming_buffer,
+ tcp_payload, tcp_payload_length);
+ assert(len == tcp_payload_length);
+ incoming_connection->ack += len;
+ tcp_send_ack(incoming_connection);
+ }
+ if (0 != (flags & FIN)) {
+ incoming_connection->ack++;
- tcp_send_empty_payload(incoming_connection, FIN | ACK);
- incoming_connection->seq++;
+ tcp_send_empty_payload(incoming_connection, FIN | ACK);
+ incoming_connection->seq++;
- incoming_connection->dead = 1; // FIXME: It should wait for a ACK
- // of the FIN before the connection
- // is closed.
- }
- } else {
- return;
+ incoming_connection->dead = 1; // FIXME: It should wait for a ACK
+ // of the FIN before the connection
+ // is closed.
}
}
diff --git a/kernel/network/tcp.h b/kernel/network/tcp.h
index 1e292b3..836a148 100644
--- a/kernel/network/tcp.h
+++ b/kernel/network/tcp.h
@@ -2,7 +2,8 @@
#include <typedefs.h>
void tcp_send_syn(struct TcpConnection *con);
void tcp_wait_reply(struct TcpConnection *con);
-void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length);
-void send_tcp_packet(struct TcpConnection *con, const u8 *payload,
- u16 payload_length);
+void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload, u32 payload_length);
+int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
+ u16 payload_length);
void tcp_close_connection(struct TcpConnection *con);
+int tcp_can_send(struct TcpConnection *con, u16 payload_length);
diff --git a/kernel/network/udp.c b/kernel/network/udp.c
index 724c97a..0c8d6e9 100644
--- a/kernel/network/udp.c
+++ b/kernel/network/udp.c
@@ -24,7 +24,8 @@ void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst,
kfree(packet);
}
-void handle_udp(ipv4_t src_ip, const u8 *payload, u32 packet_length) {
+void handle_udp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload, u32 packet_length) {
+ (void)dst_ip;
if (packet_length < sizeof(u16[4])) {
return;
}
diff --git a/kernel/network/udp.h b/kernel/network/udp.h
index bcf31bc..af532ec 100644
--- a/kernel/network/udp.h
+++ b/kernel/network/udp.h
@@ -1,6 +1,6 @@
#include <socket.h>
#include <typedefs.h>
-void handle_udp(ipv4_t src_ip, const u8 *payload, u32 packet_length);
+void handle_udp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload, u32 packet_length);
void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst,
const u8 *payload, u16 payload_length);
diff --git a/kernel/socket.c b/kernel/socket.c
index fa37efd..8b6e12d 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -89,6 +89,7 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
int connection_id;
list_add(&open_tcp_connections, con, &connection_id);
+ con->current_window_size = 536;
con->outgoing_ip = src_ip;
con->outgoing_port = src_port;
con->incoming_ip = dst_ip;
@@ -97,6 +98,7 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
ringbuffer_init(&con->incoming_buffer, 8192);
ringbuffer_init(&con->outgoing_buffer, 8192);
+ relist_init(&con->inflight);
stack_push(&listen->incoming_connections, con);
return con;
}
@@ -105,7 +107,7 @@ int tcp_sync_buffer(vfs_fd_t *fd) {
struct TcpConnection *con = fd->inode->internal_object;
assert(con);
if (con->dead) {
- return -EBADF; // TODO: Check if this is correct.
+ return 0;
}
struct ringbuffer *rb = &con->outgoing_buffer;
@@ -113,11 +115,16 @@ int tcp_sync_buffer(vfs_fd_t *fd) {
if (0 == send_buffer_len) {
return 0;
}
+
+ if (!tcp_can_send(con, send_buffer_len)) {
+ return 0;
+ }
+
char *send_buffer = kmalloc(send_buffer_len);
assert(ringbuffer_read(rb, send_buffer, send_buffer_len) == send_buffer_len);
send_tcp_packet(con, send_buffer, send_buffer_len);
kfree(send_buffer);
- return 0;
+ return 1;
}
void tcp_close(vfs_fd_t *fd) {
@@ -151,14 +158,20 @@ int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
}
if (con->no_delay) {
- send_tcp_packet(con, buffer, len);
+ if (!send_tcp_packet(con, buffer, len)) {
+ return -EWOULDBLOCK;
+ }
return len;
}
struct ringbuffer *rb = &con->outgoing_buffer;
if (ringbuffer_unused(rb) < len) {
- tcp_sync_buffer(fd);
- send_tcp_packet(con, buffer, len);
+ if (!tcp_sync_buffer(fd)) {
+ return -EWOULDBLOCK;
+ }
+ if (!send_tcp_packet(con, buffer, len)) {
+ return -EWOULDBLOCK;
+ }
len = 0;
} else {
assert(ringbuffer_write(rb, buffer, len) == len);
@@ -171,6 +184,15 @@ int tcp_has_data(vfs_inode_t *inode) {
return !(ringbuffer_isempty(&con->incoming_buffer));
}
+int tcp_can_write(vfs_inode_t *inode) {
+ struct TcpConnection *con = inode->internal_object;
+ if (con->no_delay) {
+ return tcp_can_send(con, 256);
+ }
+ return (ringbuffer_unused(&con->outgoing_buffer) > 0) ||
+ (tcp_can_send(con, 250));
+}
+
int udp_recvfrom(vfs_fd_t *fd, void *buffer, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen) {
struct UdpConnection *con = fd->inode->internal_object;
@@ -289,10 +311,12 @@ int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
con->incoming_port = 1337; // TODO
con->outgoing_ip = in_addr->sin_addr.s_addr;
con->outgoing_port = ntohs(in_addr->sin_port);
+ con->current_window_size = 536;
ringbuffer_init(&con->incoming_buffer, 8192);
ringbuffer_init(&con->outgoing_buffer, 8192);
list_add(&open_tcp_connections, con, NULL);
+ relist_init(&con->inflight);
tcp_send_syn(con);
@@ -307,6 +331,7 @@ int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
}
fd->inode->_has_data = tcp_has_data;
+ fd->inode->_can_write = tcp_can_write;
fd->inode->write = tcp_write;
fd->inode->read = tcp_read;
fd->inode->close = tcp_close;
@@ -426,7 +451,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
stack_pop(&tcp_listen->incoming_connections);
assert(connection);
vfs_inode_t *inode = vfs_create_inode(
- 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, tcp_has_data, always_can_write, 1,
+ 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, tcp_has_data, tcp_can_write, 1,
connection, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
tcp_read, tcp_write, tcp_close /*close*/, NULL /*create_directory*/,
NULL /*get_vm_object*/, NULL /*truncate*/, NULL /*stat*/,
diff --git a/kernel/socket.h b/kernel/socket.h
index ef5863d..f41e9a1 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -5,6 +5,7 @@ typedef int socklen_t;
#include <fs/fifo.h>
#include <fs/vfs.h>
#include <lib/buffered_write.h>
+#include <lib/relist.h>
#include <lib/ringbuffer.h>
#include <lib/stack.h>
#include <stddef.h>
@@ -51,9 +52,14 @@ struct TcpConnection {
struct ringbuffer incoming_buffer;
struct ringbuffer outgoing_buffer;
+ struct relist inflight;
+
int no_delay;
+ u32 current_window_size;
+ u32 window_size;
u32 seq;
+ u32 seq_ack;
u32 ack;
int handshake_state;