summaryrefslogtreecommitdiff
path: root/kernel/socket.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-02-28 21:47:49 +0100
committerAnton Kling <anton@kling.gg>2024-02-28 21:47:49 +0100
commite6c8f7298b40757a410d9df6319824c4f0d70351 (patch)
treeb90ee0eba9a45c7551d9f23b6e66620ff0ea5b66 /kernel/socket.c
parent4536dc81b4be9a62328826455664cd6d696df8fb (diff)
TCP/UDP: Start rewrite of network sockets
Having sockets be file descriptors seems like a bad idea so I trying to make UDP and TCP sockets be more independent and not be abstracted away as much.
Diffstat (limited to 'kernel/socket.c')
-rw-r--r--kernel/socket.c270
1 files changed, 131 insertions, 139 deletions
diff --git a/kernel/socket.c b/kernel/socket.c
index 0f960f5..9cb8763 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -10,162 +10,172 @@
// FIXME: Make these more dynamic
OPEN_UNIX_SOCKET *un_sockets[100] = {0};
-OPEN_INET_SOCKET *inet_sockets[100] = {0};
-struct INCOMING_TCP_CONNECTION tcp_connections[100] = {0};
+struct TcpConnection *tcp_sockets[100];
+struct TcpListen *tcp_listen[100];
-int tcp_socket_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
- struct INCOMING_TCP_CONNECTION *s =
- (struct INCOMING_TCP_CONNECTION *)fd->inode->internal_object;
- if (s->connection_closed) {
- return -EBADF;
- }
-
- if (buffered_write(&s->buffer, buffer, len)) {
- return len;
- }
-
- // Use the current buffered input
- if (s->buffer.buffer_usage > 0) {
- send_tcp_packet(s, s->buffer.data, s->buffer.buffer_usage);
- buffered_clear(&s->buffer);
+u32 gen_ipv4(u8 i1, u8 i2, u8 i3, u8 i4) {
+ return i4 << (32 - 8) | i3 << (32 - 16) | i2 << (32 - 24) | i1 << (32 - 32);
+}
- // Try to add to the buffer again. If it fails just send the whole
- // thing immediatley.
- if (buffered_write(&s->buffer, buffer, len)) {
- return len;
+struct TcpConnection *tcp_find_connection(u16 port) {
+ for (int i = 0; i < 100; i++) {
+ if (port == tcp_sockets[i]->incoming_port) {
+ return tcp_sockets[i];
}
}
- send_tcp_packet(s, buffer, len);
- return len;
+ return NULL;
}
+struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
+ u32 dst_ip, u16 dst_port) {
+ u32 i = 0;
+ for (; i < 100; i++) {
+ if (!tcp_listen[i]) {
+ continue;
+ }
+ if (dst_port == tcp_listen[i]->port) {
+ break;
+ }
+ }
+ if (!tcp_listen[i] || dst_port != tcp_listen[i]->port) {
+ return NULL;
+ }
+ struct TcpListen *listen = tcp_listen[i];
+ u32 listen_id = i;
-int tcp_socket_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
- struct INCOMING_TCP_CONNECTION *s =
- (struct INCOMING_TCP_CONNECTION *)fd->inode->internal_object;
- if (s->connection_closed) {
- return -EBADF;
+ i = 0;
+ for (; i < 100; i++) {
+ if (!tcp_sockets[i]) {
+ break;
+ }
+ }
+ if (tcp_sockets[i]) {
+ return NULL;
}
- return fifo_object_read(buffer, offset, len, s->data_file);
+ tcp_sockets[i] = kcalloc(1, sizeof(struct TcpConnection));
+ struct TcpConnection *con = tcp_sockets[i];
+ u32 con_id = i;
+ con->outgoing_ip = src_ip;
+ con->outgoing_port = src_port;
+ // con->incoming_ip = dst_ip;
+ con->incoming_port = dst_port; // FIXME: Should be different for each
+ // connection
+
+ con->data_file = create_fifo_object();
+ kprintf("pushing the connection\n");
+ kprintf("listen_id: %x\n", listen_id);
+ stack_push(&listen->incoming_connections, (void *)con_id);
+ kprintf("listen->incoming_connections->head: %x\n",
+ (&listen->incoming_connections)->head);
+ kprintf("root: %x\n", &listen->incoming_connections);
+ return con;
}
-void tcp_socket_close(vfs_fd_t *fd) {
- struct INCOMING_TCP_CONNECTION *s =
- (struct INCOMING_TCP_CONNECTION *)fd->inode->internal_object;
-
- // Flush the remaining buffer
- if (s->buffer.buffer_usage > 0) {
- send_tcp_packet(s, s->buffer.data, s->buffer.buffer_usage);
+u32 tcp_listen_ipv4(u32 ip, u16 port, int *error) {
+ *error = 0;
+ u32 i = 0;
+ for (; i < 100; i++) {
+ if (!tcp_listen[i]) {
+ break;
+ }
}
- buffered_free(&s->buffer);
-
- if (s->connection_closed) {
- s->is_used = 0;
- return;
+ if (tcp_listen[i]) {
+ *error = 1;
+ return 0;
}
- s->requesting_connection_close = 1;
- tcp_close_connection(s);
- s->is_used = 0;
+
+ tcp_listen[i] = kcalloc(1, sizeof(struct TcpListen));
+ tcp_listen[i]->ip = ip;
+ tcp_listen[i]->port = port;
+ stack_init(&tcp_listen[i]->incoming_connections);
+ return i;
}
-struct INCOMING_TCP_CONNECTION *get_incoming_tcp_connection(u8 ip[4],
- u16 n_port) {
- for (int i = 0; i < 100; i++) {
- if (0 != memcmp(tcp_connections[i].ip, ip, sizeof(u8[4]))) {
- continue;
- }
- if (n_port != tcp_connections[i].n_port) {
- continue;
+u32 tcp_accept(u32 listen_socket, int *error) {
+ *error = 0;
+ struct TcpListen *l = tcp_listen[listen_socket];
+ if (NULL == l) {
+ *error = 1;
+ return 0;
+ }
+ for (;;) {
+ // TODO: halt the process
+ if (NULL != l->incoming_connections.head) {
+ void *out = stack_pop(&l->incoming_connections);
+ return (u32)out; // TODO: Should a pointer store a u32?
}
- return &tcp_connections[i];
}
- return NULL;
+ ASSERT_NOT_REACHED;
}
-struct INCOMING_TCP_CONNECTION *
-handle_incoming_tcp_connection(u8 ip[4], u16 n_port, u16 dst_port) {
- OPEN_INET_SOCKET *in = find_open_tcp_port(htons(dst_port));
- if (!in) {
- kprintf("TCP SYN to unopened port: %d\n", dst_port);
- return NULL;
- }
-
- int i;
- for (i = 0; i < 100; i++) {
- if (!tcp_connections[i].is_used) {
+u32 tcp_connect_ipv4(u32 ip, u16 port, int *error) {
+ *error = 0;
+ u32 i = 0;
+ for (; i < 100; i++) {
+ if (!tcp_sockets[i]) {
break;
}
}
+ if (tcp_sockets[i]) {
+ *error = 1;
+ return 0;
+ }
- tcp_connections[i].is_used = 1;
- memcpy(tcp_connections[i].ip, ip, sizeof(u8[4]));
- tcp_connections[i].n_port = n_port;
- tcp_connections[i].dst_port = dst_port;
- tcp_connections[i].data_file = create_fifo_object();
-
- buffered_init(&tcp_connections[i].buffer, 0x2000);
+ tcp_sockets[i] = kcalloc(1, sizeof(struct TcpConnection));
+ struct TcpConnection *con = tcp_sockets[i];
- SOCKET *s = in->s;
+ con->incoming_port = 1337; // TODO
+ con->outgoing_ip = ip;
+ con->outgoing_port = port;
- vfs_inode_t *inode = vfs_create_inode(
- 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, 0 /*has_data*/, 1 /*can_write*/,
- 1 /*is_open*/, &tcp_connections[i], 0 /*file_size*/, NULL /*open*/,
- NULL /*create_file*/, tcp_socket_read, tcp_socket_write, tcp_socket_close,
- NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/,
- NULL /*stat*/);
+ con->data_file = create_fifo_object();
- tcp_connections[i].has_data_ptr = &inode->has_data;
+ tcp_send_syn(con);
- vfs_fd_t *fd;
- int n = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, &fd);
+ for (;;) {
+ tcp_wait_reply(con);
+ if (con->dead) { // Port is probably closed
+ *error = 1;
+ return 0;
+ }
+ if (0 != con->handshake_state) {
+ break;
+ }
+ }
- fd->reference_count++;
- s->incoming_fd = fd;
+ return i;
+}
- // Shitty way of telling the accepting socket we have a incoming
- // connection.
- char c = 'i';
- fifo_object_write((u8 *)&c, 1, 0, s->fifo_file);
- s->ptr_socket_fd->inode->has_data = 1;
+int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out) {
+ struct TcpConnection *con = tcp_sockets[socket];
+ if (con->dead) {
+ *out = 0;
+ return 0;
+ }
- vfs_close(n); // Closes the file descriptor in the current process.
- // But it does not get freed since the reference count
- // is still over zero.
- fd->reference_count--;
- return &tcp_connections[i];
+ send_tcp_packet(con, buffer, len);
+ *out = len;
+ return 1;
}
-OPEN_INET_SOCKET *find_open_tcp_port(u16 port) {
- for (int i = 0; i < 100; i++) {
- if (!inet_sockets[i]) {
- continue;
- }
- if (inet_sockets[i]->port != port) {
- continue;
- }
- if (inet_sockets[i]->s->type != SOCK_STREAM) {
- continue;
- }
- return inet_sockets[i];
+int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out) {
+ struct TcpConnection *con = tcp_sockets[socket];
+ if (con->dead) {
+ *out = 0;
+ return 0;
}
- return NULL;
-}
-OPEN_INET_SOCKET *find_open_udp_port(u16 port) {
- for (int i = 0; i < 100; i++) {
- if (!inet_sockets[i]) {
- continue;
- }
- if (inet_sockets[i]->port != port) {
- continue;
- }
- if (inet_sockets[i]->s->type != SOCK_DGRAM) {
- continue;
- }
- return inet_sockets[i];
+ int rc = 0;
+ for (; rc <= 0;) {
+ rc = fifo_object_read(buffer, 0, buffer_size, con->data_file);
}
- return NULL;
+ *out = rc;
+ return 1;
+}
+
+void tcp_close(u32 socket) {
+ assert(NULL);
}
int uds_open(const char *path) {
@@ -268,24 +278,6 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
devfs_add_file(us->path, NULL, NULL, NULL, 1, 1, FS_TYPE_UNIX_SOCKET);
return 0;
}
- if (AF_INET == s->domain) {
- struct sockaddr_in *in = (struct sockaddr_in *)addr;
- assert(in->sin_family == AF_INET); // FIXME: Figure out error value
- OPEN_INET_SOCKET *inet;
- int i = 0;
- for (; i < 100; i++) {
- if (!inet_sockets[i]) {
- break;
- }
- }
-
- inet = inet_sockets[i] = kmalloc(sizeof(OPEN_INET_SOCKET));
- inet->address = in->sin_addr.s_addr;
- inet->port = in->sin_port;
- inet->s = s;
- s->child = inet;
- return 0;
- }
return 0;
}