diff options
author | Anton Kling <anton@kling.gg> | 2024-04-29 18:00:20 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-04-29 18:00:20 +0200 |
commit | 7d2ab3a71f4bda9d8ee997764d98b29e13a902c5 (patch) | |
tree | 6dcdc7a674a8047a2dba3e95d3be91b4e3161bd5 /kernel | |
parent | d60fa1fc01e600c4a163bbe82fab3f1986cb1476 (diff) |
Kernel/Socket: Move sockets back to being file descriptors
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/cpu/isr.s | 2 | ||||
-rw-r--r-- | kernel/cpu/syscall.c | 91 | ||||
-rw-r--r-- | kernel/drivers/keyboard.c | 2 | ||||
-rw-r--r-- | kernel/fs/vfs.c | 2 | ||||
-rw-r--r-- | kernel/includes/syscalls.h | 5 | ||||
-rw-r--r-- | kernel/init/kernel.c | 2 | ||||
-rw-r--r-- | kernel/lib/ringbuffer.c | 17 | ||||
-rw-r--r-- | kernel/lib/ringbuffer.h | 3 | ||||
-rw-r--r-- | kernel/lib/stack.c | 4 | ||||
-rw-r--r-- | kernel/lib/stack.h | 1 | ||||
-rw-r--r-- | kernel/network/tcp.c | 14 | ||||
-rw-r--r-- | kernel/network/tcp.h | 2 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 31 | ||||
-rw-r--r-- | kernel/sched/scheduler.h | 3 | ||||
-rw-r--r-- | kernel/socket.c | 384 | ||||
-rw-r--r-- | kernel/socket.h | 19 |
17 files changed, 334 insertions, 250 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 240f7df..149b1bc 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,6 +1,6 @@ CC="i686-sb-gcc" AS="i686-sb-as" -OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o queue.o syscalls/queue.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o lib/relist.o +OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/fstat.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o syscalls/munmap.o syscalls/open_process.o syscalls/lseek.o lib/ringbuffer.o lib/relist.o CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL LDFLAGS= INCLUDE=-I./includes/ -I../include/ -I./libc/include/ diff --git a/kernel/cpu/isr.s b/kernel/cpu/isr.s index 819b22b..9fca13c 100644 --- a/kernel/cpu/isr.s +++ b/kernel/cpu/isr.s @@ -32,7 +32,7 @@ ISR_NOERRCODE 9 ISR_NOERRCODE 10 ISR_NOERRCODE 11 ISR_NOERRCODE 12 -ISR_NOERRCODE 13 +ISR_ERRCODE 13 ISR_ERRCODE 14 ISR_NOERRCODE 15 ISR_NOERRCODE 16 diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c index 3765a84..84faa16 100644 --- a/kernel/cpu/syscall.c +++ b/kernel/cpu/syscall.c @@ -140,49 +140,64 @@ int syscall_openpty(SYS_OPENPTY_PARAMS *args) { args->winp); } -u32 syscall_tcp_connect(u32 ip, u16 port, int *error) { - // TODO: Make sure error is a user address - return tcp_connect_ipv4(ip, port, error); -} - -int syscall_tcp_write(u32 socket, const u8 *buffer, u32 len, u64 *out) { - // TODO: Make sure out is a user address - return tcp_write(socket, buffer, len, out); -} - -int syscall_tcp_read(u32 socket, u8 *buffer, u32 buffer_size, u64 *out) { - // TODO: Make sure out is a user address - return tcp_read(socket, buffer, buffer_size, out); +int syscall_connect(int sockfd, const struct sockaddr *addr, + socklen_t addrlen) { + return connect(sockfd, addr, addrlen); } int (*syscall_functions[])() = { - (void(*))syscall_open, (void(*))syscall_mread, - (void(*))syscall_write, (void(*))syscall_pread, - (void(*))syscall_pwrite, (void(*))syscall_fork, - (void(*))syscall_exec, (void(*))syscall_getpid, - (void(*))syscall_exit, (void(*))syscall_wait, - (void(*))syscall_brk, (void(*))syscall_sbrk, - (void(*))syscall_pipe, (void(*))syscall_dup2, - (void(*))syscall_close, (void(*))syscall_openpty, - (void(*))syscall_poll, (void(*))syscall_mmap, - (void(*))syscall_accept, (void(*))syscall_bind, - (void(*))syscall_socket, (void(*))syscall_shm_open, - (void(*))syscall_ftruncate, (void(*))syscall_fstat, - (void(*))syscall_msleep, (void(*))syscall_uptime, - (void(*))syscall_mkdir, (void(*))syscall_recvfrom, - (void(*))syscall_sendto, (void(*))syscall_kill, - (void(*))syscall_sigaction, (void(*))syscall_chdir, - (void(*))syscall_getcwd, (void(*))syscall_isatty, - (void(*))syscall_randomfill, (void(*))syscall_outw, - (void(*))syscall_inl, (void(*))syscall_outl, - (void(*))syscall_map_frames, (void(*))syscall_virtual_to_physical, - (void(*))syscall_install_irq, (void(*))syscall_tmp_handle_packet, - (void(*))syscall_tcp_connect, (void(*))syscall_tcp_write, - (void(*))syscall_tcp_read, - (void(*))syscall_queue_create, (void(*))syscall_queue_add, - (void(*))syscall_queue_wait, (void(*))syscall_munmap, + (void(*))syscall_open, + (void(*))syscall_mread, + (void(*))syscall_write, + (void(*))syscall_pread, + (void(*))syscall_pwrite, + (void(*))syscall_fork, + (void(*))syscall_exec, + (void(*))syscall_getpid, + (void(*))syscall_exit, + (void(*))syscall_wait, + (void(*))syscall_brk, + (void(*))syscall_sbrk, + (void(*))syscall_pipe, + (void(*))syscall_dup2, + (void(*))syscall_close, + (void(*))syscall_openpty, + (void(*))syscall_poll, + (void(*))syscall_mmap, + (void(*))syscall_accept, + (void(*))syscall_bind, + (void(*))syscall_socket, + (void(*))syscall_shm_open, + (void(*))syscall_ftruncate, + (void(*))syscall_fstat, + (void(*))syscall_msleep, + (void(*))syscall_uptime, + (void(*))syscall_mkdir, + (void(*))syscall_recvfrom, + (void(*))syscall_sendto, + (void(*))syscall_kill, + (void(*))syscall_sigaction, + (void(*))syscall_chdir, + (void(*))syscall_getcwd, + (void(*))syscall_isatty, + (void(*))syscall_randomfill, + (void(*))syscall_outw, + (void(*))syscall_inl, + (void(*))syscall_outl, + (void(*))syscall_map_frames, + (void(*))syscall_virtual_to_physical, + (void(*))syscall_install_irq, + (void(*))syscall_tmp_handle_packet, + (void(*))NULL, + (void(*))NULL, + (void(*))NULL, + (void(*))NULL, + (void(*))NULL, + (void(*))NULL, + (void(*))syscall_munmap, (void(*))syscall_open_process, (void(*))syscall_lseek, + (void(*))syscall_connect, }; void int_syscall(reg_t *r); diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index 770c8c5..a120788 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -5,9 +5,9 @@ #include <fs/devfs.h> #include <fs/fifo.h> #include <fs/vfs.h> +#include <lib/ringbuffer.h> #include <sched/scheduler.h> #include <typedefs.h> -#include <lib/ringbuffer.h> #define PS2_REG_DATA 0x60 #define PS2_REG_STATUS 0x64 diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 9312c2a..cd3f854 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -340,7 +340,7 @@ int vfs_pmread(int fd, void *buf, u64 count, int blocking, u64 offset) { return -EBADF; } int rc = raw_vfs_pread(vfs_fd, buf, count, offset); - if (-EAGAIN == rc && count > 0) { + if ((-EAGAIN == rc || -EWOULDBLOCK == rc) && count > 0) { if (!(vfs_fd->flags & O_NONBLOCK) && blocking) { struct pollfd fds; do { diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h index 6945c21..2fabb2b 100644 --- a/kernel/includes/syscalls.h +++ b/kernel/includes/syscalls.h @@ -1,5 +1,4 @@ #include <fs/vfs.h> -#include <queue.h> #include <signal.h> #include <socket.h> #include <stddef.h> @@ -13,10 +12,6 @@ u32 syscall_inl(u16 port); void syscall_outl(u16 port, u32 l); int syscall_open_process(int pid); -int syscall_queue_create(u32 *id); -int syscall_queue_add(u32 queue_id, struct event *ev, u32 size); -int syscall_queue_wait(u32 queue_id); - int syscall_ipc_register_endpoint(u32 endpoint); int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid); int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length); diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c index 2b96359..0a2243d 100644 --- a/kernel/init/kernel.c +++ b/kernel/init/kernel.c @@ -85,6 +85,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr, install_keyboard(); klog("PS2 Keyboard driver installed", LOG_SUCCESS); +global_socket_init(); + vfs_mount("/dev", devfs_mount()); assert(ahci_init()); vfs_inode_t *ext2_mount_point = ext2_mount(); diff --git a/kernel/lib/ringbuffer.c b/kernel/lib/ringbuffer.c index 66dd17e..9caf555 100644 --- a/kernel/lib/ringbuffer.c +++ b/kernel/lib/ringbuffer.c @@ -16,6 +16,23 @@ int ringbuffer_init(struct ringbuffer *rb, u32 buffer_size) { return 1; } +u32 ringbuffer_used(const struct ringbuffer *rb) { + if (rb->write_ptr < rb->read_ptr) { + u32 c = rb->buffer_size - rb->read_ptr; + c += rb->write_ptr; + return c; + } + return rb->write_ptr - rb->read_ptr; +} + +u32 ringbuffer_capacity(const struct ringbuffer *rb) { + return rb->buffer_size - 1; +} + +u32 ringbuffer_unused(const struct ringbuffer *rb) { + return ringbuffer_capacity(rb) - ringbuffer_used(rb); +} + u32 ringbuffer_write(struct ringbuffer *rb, const u8 *buffer, u32 len) { const u32 orig_len = len; for (; len > 0;) { diff --git a/kernel/lib/ringbuffer.h b/kernel/lib/ringbuffer.h index 3ebc507..d6e699a 100644 --- a/kernel/lib/ringbuffer.h +++ b/kernel/lib/ringbuffer.h @@ -14,6 +14,9 @@ u32 ringbuffer_write(struct ringbuffer *rb, const u8 *buffer, u32 len); u32 ringbuffer_read(struct ringbuffer *rb, u8 *buffer, u32 len); int ringbuffer_isempty(const struct ringbuffer *rb); void ringbuffer_free(struct ringbuffer *rb); +u32 ringbuffer_used(const struct ringbuffer *rb); +u32 ringbuffer_capacity(const struct ringbuffer *rb); +u32 ringbuffer_unused(const struct ringbuffer *rb); #ifdef KERNEL_TEST void ringbuffer_test(void); #endif // KERNEL_TEST diff --git a/kernel/lib/stack.c b/kernel/lib/stack.c index 7283b35..7c44193 100644 --- a/kernel/lib/stack.c +++ b/kernel/lib/stack.c @@ -7,6 +7,10 @@ void stack_init(struct stack *s) { s->head = NULL; } +int stack_isempty(const struct stack *s) { + return (NULL == s->head); +} + // 1 = Success // 0 = Failure int stack_push(struct stack *s, void *data) { diff --git a/kernel/lib/stack.h b/kernel/lib/stack.h index f47fe66..09fff66 100644 --- a/kernel/lib/stack.h +++ b/kernel/lib/stack.h @@ -13,6 +13,7 @@ struct stack { }; void stack_init(struct stack *s); +int stack_isempty(const struct stack *s); int stack_push(struct stack *s, void *data); void *stack_pop(struct stack *s); #endif diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c index 8740a63..39b8d7c 100644 --- a/kernel/network/tcp.c +++ b/kernel/network/tcp.c @@ -121,6 +121,10 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) { send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, send_buffer, send_len); } +void tcp_close_connection(struct TcpConnection *con) { + tcp_send_empty_payload(con, FIN | ACK); +} + void tcp_send_ack(struct TcpConnection *con) { tcp_send_empty_payload(con, ACK); } @@ -170,7 +174,6 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) { u8 flags = header->flags; u16 src_port = htons(n_src_port); - (void)src_port; u16 dst_port = htons(n_dst_port); u32 seq_num = htonl(n_seq_num); u32 ack_num = htonl(n_ack_num); @@ -182,10 +185,12 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) { assert(con); con->ack = seq_num + 1; tcp_send_empty_payload(con, SYN | ACK); + con->seq++; return; } - struct TcpConnection *incoming_connection = tcp_find_connection(dst_port); + struct TcpConnection *incoming_connection = + tcp_find_connection(src_ip, src_port, dst_port); if (!incoming_connection) { kprintf("unable to find open port for incoming connection\n"); } @@ -214,8 +219,8 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) { 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->buffer, tcp_payload, - tcp_payload_length); + 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); @@ -224,6 +229,7 @@ void handle_tcp(ipv4_t src_ip, const u8 *payload, u32 payload_length) { incoming_connection->ack++; 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 diff --git a/kernel/network/tcp.h b/kernel/network/tcp.h index 0c53535..1e292b3 100644 --- a/kernel/network/tcp.h +++ b/kernel/network/tcp.h @@ -5,4 +5,4 @@ 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 tcp_close_connection(struct INCOMING_TCP_CONNECTION *s); +void tcp_close_connection(struct TcpConnection *con); diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c index 639dd05..9a241ac 100644 --- a/kernel/sched/scheduler.c +++ b/kernel/sched/scheduler.c @@ -7,7 +7,6 @@ #include <errno.h> #include <fs/vfs.h> #include <interrupts.h> -#include <queue.h> #include <signal.h> // FIXME: Use the process_t struct instead or keep this contained in it. @@ -160,11 +159,6 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) { list_init(&r->write_list); list_init(&r->disconnect_list); - list_init(&r->tcp_sockets); - list_init(&r->tcp_listen); - - list_init(&r->event_queue); - if (esp) { esp -= 4; insert_eip_on_stack(r->cr3->physical_address, esp, eip); @@ -209,9 +203,6 @@ void free_process(process_t *p) { list_free(&p->read_list); list_free(&p->write_list); list_free(&p->disconnect_list); - list_free(&p->tcp_sockets); - list_free(&p->tcp_listen); - list_free(&p->event_queue); relist_free(&p->file_descriptors); kfree(p->tcb); @@ -428,28 +419,6 @@ int is_halted(process_t *process) { } } - int queue_block = 1; - int wait_empty = 1; - for (int i = 0;; i++) { - struct event_queue *q; - if (!list_get(&process->event_queue, i, (void **)&q)) { - break; - } - int is_empty; - int rc = queue_should_block(q, &is_empty); - if (is_empty) { - wait_empty = 0; - continue; - } - if (0 == rc) { - queue_block = 0; - } - } - if (!queue_block && !wait_empty) { - kprintf("skip because queue_wait has data\n"); - return 0; - } - int fd_empty; if (isset_fdhalt(process, &fd_empty) && !fd_empty) { return 1; diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h index feb6aa5..7a8bf0c 100644 --- a/kernel/sched/scheduler.h +++ b/kernel/sched/scheduler.h @@ -68,9 +68,6 @@ struct Process { struct list write_list; struct list disconnect_list; - struct list tcp_sockets; - struct list tcp_listen; - struct list event_queue; struct stack restore_context_stack; diff --git a/kernel/socket.c b/kernel/socket.c index e0c3f35..fbc0648 100644 --- a/kernel/socket.c +++ b/kernel/socket.c @@ -9,6 +9,14 @@ #include <sched/scheduler.h> #include <socket.h> +struct list open_tcp_connections; +struct list open_tcp_listen; + +void global_socket_init(void) { + list_init(&open_tcp_connections); + list_init(&open_tcp_listen); +} + OPEN_UNIX_SOCKET *un_sockets[100] = {0}; void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4) { @@ -18,44 +26,29 @@ void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4) { ip->a[3] = i4; } -struct TcpConnection *tcp_find_connection(u16 port) { - process_t *p = current_task; - p = p->next; - for (int i = 0; i < 100; i++, p = p->next) { - if (!p) { - p = ready_queue; +struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port, + u16 dst_port) { + (void)src_ip; + for (int i = 0;; i++) { + struct TcpConnection *c; + if (!list_get(&open_tcp_connections, i, (void **)&c)) { + break; } - struct list *connections = &p->tcp_sockets; - for (int i = 0;; i++) { - struct TcpConnection *c; - if (!list_get(connections, i, (void **)&c)) { - break; - } - if (c->incoming_port == port) { - return c; - } + if (c->incoming_port == dst_port && c->outgoing_port == src_port) { + return c; } } return NULL; } struct TcpListen *tcp_find_listen(u16 port) { - process_t *p = current_task; - process_t *s = p; - p = p->next; - for (; p != s; p = p->next) { - if (!p) { - p = ready_queue; + for (int i = 0;; i++) { + struct TcpListen *c; + if (!list_get(&open_tcp_listen, i, (void **)&c)) { + break; } - struct list *listen_list = &p->tcp_listen; - for (int i = 0;; i++) { - struct TcpListen *c; - if (!list_get(listen_list, i, (void **)&c)) { - break; - } - if (c->port == port) { - return c; - } + if (c->port == port) { + return c; } } return NULL; @@ -71,134 +64,125 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port, struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection)); int connection_id; - struct list *connections = ¤t_task->tcp_sockets; - list_add(connections, con, &connection_id); + list_add(&open_tcp_connections, con, &connection_id); 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->incoming_ip = dst_ip; + con->incoming_port = dst_port; - ringbuffer_init(&con->buffer, 8192); - stack_push(&listen->incoming_connections, (void *)connection_id); + ringbuffer_init(&con->incoming_buffer, 8192); + ringbuffer_init(&con->outgoing_buffer, 8192); + stack_push(&listen->incoming_connections, con); return con; } -u32 tcp_listen_ipv4(u32 ip, u16 port, int *error) { - *error = 0; +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. + } + + struct ringbuffer *rb = &con->outgoing_buffer; + u32 send_buffer_len = ringbuffer_used(rb); + if (0 == 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; +} + +void tcp_close(vfs_fd_t *fd) { + struct TcpConnection *con = fd->inode->internal_object; - struct TcpListen *listener = kcalloc(1, sizeof(struct TcpListen)); - listener->ip = ip; - listener->port = port; - stack_init(&listener->incoming_connections); + tcp_sync_buffer(fd); - struct list *listen_list = ¤t_task->tcp_listen; - int index; - list_add(listen_list, listener, &index); - return index; + tcp_close_connection(con); } -struct TcpConnection *tcp_get_connection(u32 socket, process_t *p) { - if (!p) { - p = current_task; +int tcp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) { + struct TcpConnection *con = fd->inode->internal_object; + assert(con); + if (con->dead) { + return -EBADF; // TODO: Check if this is correct. } - const struct list *connections = &p->tcp_sockets; - struct TcpConnection *con; - if (!list_get(connections, socket, (void **)&con)) { - return NULL; + + u32 rc = ringbuffer_read(&con->incoming_buffer, buffer, len); + if (0 == rc && len > 0) { + return -EWOULDBLOCK; } - return con; + return rc; } -u32 tcp_accept(u32 listen_socket, int *error) { - *error = 0; - struct list *listen_list = ¤t_task->tcp_listen; - struct TcpListen *l; - if (!list_get(listen_list, listen_socket, (void **)&l)) { - *error = 1; - return 0; +int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) { + (void)offset; + struct TcpConnection *con = fd->inode->internal_object; + assert(con); + if (con->dead) { + return -EBADF; // TODO: Check if this is correct. } - 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? - } + + struct ringbuffer *rb = &con->outgoing_buffer; + if (ringbuffer_unused(rb) < len) { + tcp_sync_buffer(fd); + send_tcp_packet(con, buffer, len); + len = 0; + } else { + assert(ringbuffer_write(rb, buffer, len) == len); } - ASSERT_NOT_REACHED; + return len; +} + +int tcp_has_data(vfs_inode_t *inode) { + struct TcpConnection *con = inode->internal_object; + return !(ringbuffer_isempty(&con->incoming_buffer)); } -u32 tcp_connect_ipv4(u32 ip, u16 port, int *error) { - struct list *connections = ¤t_task->tcp_sockets; - *error = 0; +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + vfs_fd_t *fd = get_vfs_fd(sockfd, NULL); + assert(fd); + + if (fd->inode->internal_object) { + return -EISCONN; + } + assert(AF_INET == addr->sa_family); + const struct sockaddr_in *in_addr = (const struct sockaddr_in *)addr; struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection)); - int index; - list_add(connections, con, &index); + if (!con) { + return -ENOMEM; + } con->incoming_port = 1337; // TODO - con->outgoing_ip = ip; - con->outgoing_port = port; + con->outgoing_ip = in_addr->sin_addr.s_addr; + con->outgoing_port = in_addr->sin_port; - ringbuffer_init(&con->buffer, 8192); + ringbuffer_init(&con->incoming_buffer, 8192); + ringbuffer_init(&con->outgoing_buffer, 8192); + list_add(&open_tcp_connections, con, NULL); tcp_send_syn(con); for (;;) { tcp_wait_reply(con); if (con->dead) { // Port is probably closed - *error = 1; - return 0; + return -ECONNREFUSED; } if (0 != con->handshake_state) { break; } } - return index; -} - -int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out) { - if (out) { - *out = 0; - } - struct TcpConnection *con = tcp_get_connection(socket, NULL); - if (!con) { - return 0; - } - if (con->dead) { - return 0; - } - - send_tcp_packet(con, buffer, len); - if (out) { - *out = len; - } - return 1; -} - -int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out) { - if (out) { - *out = 0; - } - struct TcpConnection *con = tcp_get_connection(socket, NULL); - if (!con) { - return 0; - } - if (con->dead) { - return 0; - } - - u32 len = ringbuffer_read(&con->buffer, buffer, buffer_size); - if (out) { - *out = len; - } - return 1; -} - -void tcp_close(u32 socket) { - assert(NULL); + fd->inode->_has_data = tcp_has_data; + fd->inode->write = tcp_write; + fd->inode->read = tcp_read; + fd->inode->close = tcp_close; + fd->inode->internal_object = con; + return 0; } int uds_open(const char *path) { @@ -238,6 +222,12 @@ 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; @@ -245,25 +235,50 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) { assert(fd_ptr); vfs_inode_t *inode = fd_ptr->inode; SOCKET *s = (SOCKET *)inode->internal_object; + if (AF_UNIX == s->domain) { + for (; NULL == s->incoming_fd;) { + // Wait until we have gotten a connection + struct pollfd fds[1]; + fds[0].fd = socket; + fds[0].events = POLLIN; + fds[0].revents = 0; + poll(fds, 1, 0); + } - for (; NULL == s->incoming_fd;) { - // Wait until we have gotten a connection - struct pollfd fds[1]; - fds[0].fd = socket; - fds[0].events = POLLIN; - fds[0].revents = 0; - poll(fds, 1, 0); + int index; + assert(relist_add(¤t_task->file_descriptors, s->incoming_fd, &index)); + assert(1 <= s->incoming_fd->reference_count); + s->incoming_fd = NULL; + return index; } - - int index; - assert(relist_add(¤t_task->file_descriptors, s->incoming_fd, &index)); - assert(1 <= s->incoming_fd->reference_count); - s->incoming_fd = NULL; - // for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);) - // ; - // s->ptr_fifo_fd->inode->has_data = 0; - - return index; + if (AF_INET == s->domain) { + struct TcpListen *tcp_listen = s->object; + assert(tcp_listen); + if (stack_isempty(&tcp_listen->incoming_connections)) { + if (fd_ptr->flags & O_NONBLOCK) { + return -EWOULDBLOCK; + } + struct pollfd fds[1]; + fds[0].fd = socket; + fds[0].events = POLLIN; + fds[0].revents = 0; + poll(fds, 1, 0); + } + struct TcpConnection *connection = + 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, 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*/, + NULL /*send_signal*/); + assert(inode); + return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL); + } + ASSERT_NOT_REACHED; + return 0; } int bind_has_data(vfs_inode_t *inode) { @@ -286,6 +301,9 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { if (!inode) { return -EBADF; } + if (FS_TYPE_UNIX_SOCKET != inode->type) { + return -ENOTSOCK; + } SOCKET *s = (SOCKET *)inode->internal_object; if (AF_UNIX == s->domain) { struct sockaddr_un *un = (struct sockaddr_un *)addr; @@ -310,8 +328,25 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { devfs_add_file(us->path, NULL, NULL, NULL, NULL, bind_can_write, FS_TYPE_UNIX_SOCKET); return 0; + } else if (AF_INET == s->domain) { + struct sockaddr_in *in = (struct sockaddr_in *)addr; + + struct TcpListen *tcp_listen = kmalloc(sizeof(struct TcpListen)); + if (!tcp_listen) { + return -ENOMEM; + } + tcp_listen->ip = in->sin_addr.s_addr; + tcp_listen->port = ntohs(in->sin_port); + stack_init(&tcp_listen->incoming_connections); + + s->object = tcp_listen; + + inode->_has_data = tcp_listen_has_data; + + list_add(&open_tcp_listen, tcp_listen, NULL); + return 0; } - return 0; + ASSERT_NOT_REACHED; } int socket_has_data(vfs_inode_t *inode) { @@ -342,29 +377,68 @@ void socket_close(vfs_fd_t *fd) { } int socket(int domain, int type, int protocol) { + int rc = 0; + vfs_inode_t *inode = NULL; + SOCKET *new_socket = NULL; if (!(AF_UNIX == domain || AF_INET == domain)) { - return -EINVAL; + rc = -EINVAL; + goto socket_error; } - SOCKET *new_socket = kmalloc(sizeof(SOCKET)); - vfs_inode_t *inode = vfs_create_inode( - 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, bind_has_data, socket_can_write, - 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/, - NULL /*open*/, NULL /*create_file*/, socket_read, socket_write, - socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/, - NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/); - - vfs_fd_t *fd; - int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd); - + new_socket = kmalloc(sizeof(SOCKET)); + if (!new_socket) { + rc = -ENOMEM; + goto socket_error; + } new_socket->domain = domain; new_socket->type = type; new_socket->protocol = protocol; new_socket->path = NULL; new_socket->incoming_fd = NULL; + if (AF_UNIX == domain) { + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, bind_has_data, socket_can_write, + 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/, + NULL /*open*/, NULL /*create_file*/, socket_read, socket_write, + socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/, + NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/); + if (!inode) { + rc = -ENOMEM; + goto socket_error; + } + + vfs_fd_t *fd; + int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd); + if (n < 0) { + rc = n; + goto socket_error; + } - new_socket->fifo_file = create_fifo_object(); + new_socket->fifo_file = create_fifo_object(); - new_socket->ptr_socket_fd = fd; - return n; + new_socket->ptr_socket_fd = fd; + return n; + } + if (AF_INET == domain) { + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, NULL, always_can_write, 1, + new_socket, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, NULL, + NULL, NULL /*close*/, NULL /*create_directory*/, NULL /*get_vm_object*/, + NULL /*truncate*/, NULL /*stat*/, NULL /*send_signal*/); + if (!inode) { + rc = -ENOMEM; + goto socket_error; + } + int n = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL); + if (n < 0) { + rc = n; + goto socket_error; + } + return n; + } + ASSERT_NOT_REACHED; +socket_error: + kfree(inode); + kfree(new_socket); + return rc; } diff --git a/kernel/socket.h b/kernel/socket.h index ad505b8..b542c87 100644 --- a/kernel/socket.h +++ b/kernel/socket.h @@ -20,13 +20,6 @@ #define MSG_WAITALL 1 void gen_ipv4(ipv4_t *ip, u8 i1, u8 i2, u8 i3, u8 i4); -u32 tcp_connect_ipv4(u32 ip, u16 port, int *error); - -u32 tcp_listen_ipv4(u32 ip, u16 port, int *error); -u32 tcp_accept(u32 listen_socket, int *error); - -int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out); -int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out); struct TcpListen { u32 ip; @@ -37,11 +30,13 @@ struct TcpListen { struct TcpConnection { int dead; u16 incoming_port; + u32 incoming_ip; u32 outgoing_ip; u16 outgoing_port; int unhandled_packet; - struct ringbuffer buffer; + struct ringbuffer incoming_buffer; + struct ringbuffer outgoing_buffer; u32 seq; u32 ack; @@ -53,7 +48,8 @@ struct TcpConnection *tcp_get_connection(u32 socket, process_t *p); struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port, u32 dst_ip, u16 dst_port); -struct TcpConnection *tcp_find_connection(u16 port); +struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port, + u16 dst_port); typedef struct { vfs_fd_t *ptr_socket_fd; @@ -67,6 +63,8 @@ typedef struct { // UNIX socket char *path; vfs_fd_t *incoming_fd; + + void *object; } SOCKET; typedef struct { @@ -115,4 +113,7 @@ struct INCOMING_TCP_CONNECTION * handle_incoming_tcp_connection(u8 ip[4], u16 n_port, u16 dst_port); struct INCOMING_TCP_CONNECTION *get_incoming_tcp_connection(u8 ip[4], u16 n_port); +int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +void global_socket_init(void); +u16 tcp_get_free_port(void); #endif |