summaryrefslogtreecommitdiff
path: root/kernel/socket.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-07-08 21:37:15 +0200
committerAnton Kling <anton@kling.gg>2024-07-08 21:37:15 +0200
commite49d2a9fa5a485c33a250ce843d44fc6dedea8b5 (patch)
tree4be00773adca0b6c59da6d07602338ff538a7199 /kernel/socket.c
parent35292a486c2b44862cac6887441d6fa18148b249 (diff)
Kernel/Net: Don't use kmalloc to create send buffers
Current method is also really bad since it uses multiple copies when it should instead just copy to the send buffer of the network card directly. But I have other things that I want to prioritize first.
Diffstat (limited to 'kernel/socket.c')
-rw-r--r--kernel/socket.c69
1 files changed, 56 insertions, 13 deletions
diff --git a/kernel/socket.c b/kernel/socket.c
index fbccac5..cc5a645 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -48,12 +48,30 @@ void tcp_remove_connection(struct TcpConnection *con) {
}
if (c == con) {
relist_remove(&open_tcp_connections, i);
+ ringbuffer_free(&c->incoming_buffer);
+ ringbuffer_free(&c->outgoing_buffer);
kfree(con);
break;
}
}
}
+int num_open_connections(void) {
+ int f = 0;
+ for (int i = 0;; i++) {
+ struct TcpConnection *c;
+ int end;
+ if (!relist_get(&open_tcp_connections, i, (void **)&c, &end)) {
+ if (end) {
+ break;
+ }
+ continue;
+ }
+ f++;
+ }
+ return f;
+}
+
struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
ipv4_t dst_ip, u16 dst_port) {
for (int i = 0;; i++) {
@@ -74,7 +92,11 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
if (c->incoming_port == dst_port) {
struct TcpConnection *new_connection =
kmalloc(sizeof(struct TcpConnection));
- memcpy(new_connection, c, sizeof(struct TcpConnection));
+ new_connection->incoming_port = c->incoming_port;
+ new_connection->incoming_ip = c->incoming_ip;
+
+ new_connection->no_delay = c->no_delay;
+
new_connection->outgoing_port = src_port;
new_connection->outgoing_ip = src_ip.d;
new_connection->state = TCP_STATE_LISTEN;
@@ -94,10 +116,7 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
new_connection->snd_wnd = 0;
new_connection->sent_ack = 0;
- new_connection->snd_wnd =
- ringbuffer_unused(&new_connection->outgoing_buffer);
- u32 index;
- assert(relist_add(&open_tcp_connections, new_connection, &index));
+ assert(relist_add(&open_tcp_connections, new_connection, NULL));
assert(relist_add(&c->incoming_connections, new_connection, NULL));
return new_connection;
}
@@ -137,9 +156,24 @@ void tcp_flush_buffers(void) {
}
continue;
}
+ if (TCP_STATE_TIME_WAIT == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
+ if (TCP_STATE_FIN_WAIT2 == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
if (TCP_STATE_CLOSED == c->state) {
continue;
}
+ if (TCP_STATE_ESTABLISHED != c->state) {
+ continue;
+ }
tcp_sync_buffer(c);
}
}
@@ -233,9 +267,12 @@ void tcp_strip_connection(struct TcpConnection *con) {
void tcp_close(vfs_fd_t *fd) {
struct TcpConnection *con = fd->inode->internal_object;
+ if (TCP_STATE_CLOSED == con->state) {
+ return;
+ }
assert(con);
- tcp_sync_buffer(con);
if (TCP_STATE_ESTABLISHED == con->state) {
+ tcp_sync_buffer(con);
tcp_strip_connection(con);
}
tcp_close_connection(con);
@@ -256,12 +293,16 @@ int tcp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
int tcp_has_data(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
+ if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
+ }
return !(ringbuffer_isempty(&con->incoming_buffer));
}
int tcp_can_write(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
return 0;
}
if (con->no_delay) {
@@ -271,6 +312,11 @@ int tcp_can_write(vfs_inode_t *inode) {
(0 != tcp_can_send(con));
}
+int tcp_is_open(vfs_inode_t *inode) {
+ struct TcpConnection *con = inode->internal_object;
+ return (TCP_STATE_ESTABLISHED == con->state);
+}
+
int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
(void)offset;
struct TcpConnection *con = fd->inode->internal_object;
@@ -462,6 +508,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->_is_open = tcp_is_open;
fd->inode->write = tcp_write;
fd->inode->read = tcp_read;
fd->inode->close = tcp_close;
@@ -535,12 +582,6 @@ int uds_open(const char *path) {
return fd[0];
}
-int tcp_listen_has_data(vfs_inode_t *inode) {
- const SOCKET *s = (SOCKET *)inode->internal_object;
- const struct TcpListen *tcp_listen = s->object;
- return !stack_isempty(&tcp_listen->incoming_connections);
-}
-
int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
(void)address;
(void)address_len;
@@ -587,6 +628,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
NULL /*create_file*/, tcp_read, tcp_write, tcp_close /*close*/,
NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/,
NULL /*stat*/, NULL /*send_signal*/, NULL /*connect*/);
+ inode->_is_open = tcp_is_open;
assert(inode);
return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
}
@@ -618,7 +660,7 @@ struct TcpConnection *tcp_get_incoming_connection(struct TcpConnection *con,
if (!c) {
continue;
}
- if (TCP_STATE_ESTABLISHED == c->state) {
+ if (TCP_STATE_LISTEN != c->state) {
if (remove) {
assert(relist_remove(&con->incoming_connections, i));
}
@@ -739,6 +781,7 @@ int tcp_create_fd(int is_nonblock) {
kfree(con);
return -ENOMEM;
}
+ inode->_is_open = tcp_is_open;
int fd = vfs_create_fd(O_RDWR | (is_nonblock ? O_NONBLOCK : 0), 0,
0 /*is_tty*/, inode, NULL);
if (fd < 0) {