diff options
-rw-r--r-- | kernel/drivers/rtl8139.c | 1 | ||||
-rw-r--r-- | kernel/fs/vfs.c | 10 | ||||
-rw-r--r-- | kernel/fs/vfs.h | 1 | ||||
-rw-r--r-- | kernel/init/kernel.c | 1 | ||||
-rw-r--r-- | kernel/kmalloc.c | 2 | ||||
-rw-r--r-- | kernel/network/ethernet.c | 14 | ||||
-rw-r--r-- | kernel/network/ipv4.c | 5 | ||||
-rw-r--r-- | kernel/network/tcp.c | 17 | ||||
-rw-r--r-- | kernel/queue.c | 9 | ||||
-rw-r--r-- | kernel/queue.h | 1 | ||||
-rw-r--r-- | kernel/socket.c | 69 | ||||
-rw-r--r-- | kernel/socket.h | 1 |
12 files changed, 91 insertions, 40 deletions
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c index 98d3f22..669cb6c 100644 --- a/kernel/drivers/rtl8139.c +++ b/kernel/drivers/rtl8139.c @@ -68,6 +68,7 @@ void handle_packet(void) { (!packet_header.data.ROK); if (error) { + klog(LOG_ERROR, "RTL8139 packet error"); current_packet_read = 0; outb(rtl8139.gen.base_mem_io + 0x37, 0x4); outb(rtl8139.gen.base_mem_io + 0x37, 0x4 | 0x8); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 65be4aa..d76e56c 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -41,7 +41,7 @@ vfs_inode_t *vfs_create_inode( int (*send_signal)(vfs_fd_t *fd, int signal), int (*connect)(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen)) { - vfs_inode_t *r = kmalloc(sizeof(inode_t)); + vfs_inode_t *r = kcalloc(1, sizeof(inode_t)); r->inode_num = inode_num; r->type = type; r->_has_data = has_data; @@ -325,14 +325,6 @@ int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset) { } int vfs_pread(int fd, void *buf, u64 count, u64 offset) { - if (fd >= 100) { - kprintf("EBADF : %x\n", fd); - return -EBADF; - } - if (fd < 0) { - kprintf("EBADF : %x\n", fd); - return -EBADF; - } vfs_fd_t *vfs_fd = get_vfs_fd(fd, NULL); if (!vfs_fd) { return -EBADF; diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index a39982d..640cfbb 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -48,6 +48,7 @@ struct vfs_inode { int type; int (*_has_data)(vfs_inode_t *iinode); int (*_can_write)(vfs_inode_t *iinode); + int (*_is_open)(vfs_inode_t *iinode); u8 is_open; int internal_object_type; void *internal_object; diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c index 61e863b..2e569cb 100644 --- a/kernel/init/kernel.c +++ b/kernel/init/kernel.c @@ -13,6 +13,7 @@ #include <drivers/rtl8139.h> #include <drivers/serial.h> #include <drivers/vbe.h> +#include <fcntl.h> #include <fs/devfs.h> #include <fs/ext2.h> #include <fs/shm.h> diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c index b4a7f54..f5188cc 100644 --- a/kernel/kmalloc.c +++ b/kernel/kmalloc.c @@ -7,7 +7,7 @@ #include <mmu.h> #include <random.h> #include <stdint.h> -#define NEW_ALLOC_SIZE 0x5000 +#define NEW_ALLOC_SIZE 0x40000 // #define KMALLOC_DEBUG diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c index 7b1de7f..dbd1b6d 100644 --- a/kernel/network/ethernet.c +++ b/kernel/network/ethernet.c @@ -68,14 +68,14 @@ void handle_ethernet(const u8 *packet, u64 packet_length) { } } +u8 ethernet_buffer[0x1000]; void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload, u64 payload_length) { - // FIXME: Janky allocation, do this better u64 buffer_size = sizeof(struct EthernetHeader) + payload_length + sizeof(u32); - u8 *buffer = kmalloc(buffer_size); - memset(buffer, 0, buffer_size); - u8 *buffer_start = buffer; + assert(buffer_size < 0x1000); + memset(ethernet_buffer, 0, buffer_size); + u8 *buffer = ethernet_buffer; struct EthernetHeader *eth_header = (struct EthernetHeader *)buffer; buffer += sizeof(struct EthernetHeader); memcpy(buffer, payload, payload_length); @@ -84,8 +84,8 @@ void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload, memcpy(eth_header->mac_dst, mac_dst, sizeof(u8[6])); get_mac_address(eth_header->mac_src); eth_header->type = htons(type); - *(u32 *)(buffer) = htonl(crc32((const char *)buffer_start, buffer_size - 4)); + *(u32 *)(buffer) = + htonl(crc32((const char *)ethernet_buffer, buffer_size - 4)); - rtl8139_send_data(buffer_start, buffer_size); - kfree(buffer_start); + rtl8139_send_data(ethernet_buffer, buffer_size); } diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c index 69ceef7..6074141 100644 --- a/kernel/network/ipv4.c +++ b/kernel/network/ipv4.c @@ -26,6 +26,7 @@ static u16 ip_checksum(const u16 *data, u16 length) { return htons(~acc); } +u8 ipv4_buffer[0x1000]; void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) { u16 header[10]; header[0] = (4 /*version*/ << 4) | (5 /*IHL*/); @@ -46,7 +47,8 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) { header[5] = ip_checksum(header, 20); u16 packet_length = length + 20; - u8 *packet = kmalloc(packet_length); + assert(packet_length < sizeof(ipv4_buffer)); + u8 *packet = ipv4_buffer; memcpy(packet, header, 20); memcpy(packet + 20, payload, length); @@ -54,7 +56,6 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) { for (; !get_mac_from_ip(ip, mac);) ; send_ethernet_packet(mac, 0x0800, packet, packet_length); - kfree(packet); } void handle_ipv4(const u8 *payload, u32 packet_length) { diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c index 8a56dd1..8717250 100644 --- a/kernel/network/tcp.c +++ b/kernel/network/tcp.c @@ -87,6 +87,7 @@ static void tcp_send(struct TcpConnection *con, u8 *buffer, u16 length, send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, buffer, length); } +u8 tcp_buffer[0x1000]; void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) { struct TcpHeader header; memset(&header, 0, sizeof(header)); @@ -110,8 +111,10 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) { header.checksum = tcp_calculate_checksum( ip_address, con->outgoing_ip, (const u8 *)payload, payload_length, &header, sizeof(struct TcpHeader) + payload_length); - int send_len = sizeof(header) + payload_length; - u8 *send_buffer = kmalloc(send_len); + u32 send_len = sizeof(header) + payload_length; + + assert(send_len < sizeof(tcp_buffer)); + u8 *send_buffer = tcp_buffer; memcpy(send_buffer, &header, sizeof(header)); memcpy(send_buffer + sizeof(header), payload, payload_length); @@ -133,13 +136,15 @@ void tcp_close_connection(struct TcpConnection *con) { if (TCP_STATE_CLOSE_WAIT == con->state) { tcp_send_empty_payload(con, FIN); con->state = TCP_STATE_LAST_ACK; + tcp_destroy_connection(con); // Client does not appear to respond + // with last ack? return; } if (TCP_STATE_ESTABLISHED == con->state) { // FIXME: // Book says it should be FIN but observed network traffic says it // should be FIN|ACK? - tcp_send_empty_payload(con, FIN | ACK); + tcp_send_empty_payload(con, FIN); con->state = TCP_STATE_FIN_WAIT1; return; } @@ -189,9 +194,9 @@ int send_tcp_packet(struct TcpConnection *con, const u8 *payload, header.checksum = tcp_calculate_checksum( ip_address, con->outgoing_ip, (const u8 *)payload, payload_length, &header, sizeof(struct TcpHeader) + payload_length); - int send_len = sizeof(header) + payload_length; - u8 *send_buffer = kmalloc(send_len); - assert(send_buffer); + u32 send_len = sizeof(header) + payload_length; + assert(send_len < sizeof(tcp_buffer)); + u8 *send_buffer = tcp_buffer; memcpy(send_buffer, &header, sizeof(header)); memcpy(send_buffer + sizeof(header), payload, payload_length); diff --git a/kernel/queue.c b/kernel/queue.c index 6d4209d..e1b2943 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -43,6 +43,13 @@ int queue_get_entries(struct queue_list *list, struct queue_entry *events, } } } + if (QUEUE_WAIT_CLOSE & entry->listen) { + if (ptr->inode->_is_open) { + if (!ptr->inode->_is_open(ptr->inode)) { + should_add = 1; + } + } + } if (should_add) { if (events) { memcpy(events + rc, entry, sizeof(struct queue_entry)); @@ -130,7 +137,7 @@ int queue_mod_entries(int fd, int flag, struct queue_entry *entries, } for (int j = 0; j < num_entries; j++) { if (entry->fd == entries[j].fd) { - relist_remove(&list->entries, i); + assert(relist_remove(&list->entries, i)); kfree(entry); break; } diff --git a/kernel/queue.h b/kernel/queue.h index 0885f16..4a9cd17 100644 --- a/kernel/queue.h +++ b/kernel/queue.h @@ -4,6 +4,7 @@ #define QUEUE_WAIT_READ (1 << 0) #define QUEUE_WAIT_WRITE (1 << 1) +#define QUEUE_WAIT_CLOSE (1 << 2) #define QUEUE_MOD_ADD 0 #define QUEUE_MOD_CHANGE 1 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) { diff --git a/kernel/socket.h b/kernel/socket.h index 35074a1..efe0104 100644 --- a/kernel/socket.h +++ b/kernel/socket.h @@ -40,7 +40,6 @@ struct UdpConnection { }; struct TcpConnection { - int state; u16 incoming_port; |