From 15045cc4864ddfccf8db4e8dcb7725211ea05db0 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 5 Apr 2025 18:42:02 +0300 Subject: [PATCH] Kernel: Make nonblocking sockets unblocking :) --- kernel/include/kernel/FS/Inode.h | 1 + kernel/include/kernel/OpenFileDescriptorSet.h | 3 ++ kernel/kernel/Networking/TCPSocket.cpp | 36 ++++---------- kernel/kernel/OpenFileDescriptorSet.cpp | 48 +++++++++++++++++-- kernel/kernel/Process.cpp | 24 ++-------- 5 files changed, 62 insertions(+), 50 deletions(-) diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index abfd1a19..0504334d 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -169,6 +169,7 @@ namespace Kernel private: BAN::WeakPtr m_shared_region; friend class FileBackedRegion; + friend class OpenFileDescriptorSet; friend class SharedFileData; friend class TTY; }; diff --git a/kernel/include/kernel/OpenFileDescriptorSet.h b/kernel/include/kernel/OpenFileDescriptorSet.h index 9bc33399..29e22406 100644 --- a/kernel/include/kernel/OpenFileDescriptorSet.h +++ b/kernel/include/kernel/OpenFileDescriptorSet.h @@ -47,6 +47,9 @@ namespace Kernel BAN::ErrorOr read_dir_entries(int fd, struct dirent* list, size_t list_len); + BAN::ErrorOr recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len); + BAN::ErrorOr sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len); + BAN::ErrorOr file_of(int) const; BAN::ErrorOr path_of(int) const; BAN::ErrorOr> inode_of(int); diff --git a/kernel/kernel/Networking/TCPSocket.cpp b/kernel/kernel/Networking/TCPSocket.cpp index 78b6835d..036c3f75 100644 --- a/kernel/kernel/Networking/TCPSocket.cpp +++ b/kernel/kernel/Networking/TCPSocket.cpp @@ -226,51 +226,33 @@ namespace Kernel BAN::ErrorOr TCPSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) { + (void)address; + (void)address_len; + if (address) return BAN::Error::from_errno(EISCONN); if (!m_has_connected) return BAN::Error::from_errno(ENOTCONN); - if (message.size() > m_send_window.buffer->size()) - { - size_t nsent = 0; - while (nsent < message.size()) - { - const size_t to_send = BAN::Math::min(message.size() - nsent, m_send_window.buffer->size()); - TRY(sendto_impl(message.slice(nsent, to_send), address, address_len)); - nsent += to_send; - } - return nsent; - } - - while (true) + while (m_send_window.data_size == m_send_window.buffer->size()) { if (m_state != State::Established) return return_with_maybe_zero(); - if (m_send_window.data_size + message.size() <= m_send_window.buffer->size()) - break; LockFreeGuard free(m_mutex); TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); } + const size_t to_send = BAN::Math::min(message.size(), m_send_window.buffer->size() - m_send_window.data_size); + { auto* buffer = reinterpret_cast(m_send_window.buffer->vaddr()); - memcpy(buffer + m_send_window.data_size, message.data(), message.size()); - m_send_window.data_size += message.size(); + memcpy(buffer + m_send_window.data_size, message.data(), to_send); + m_send_window.data_size += to_send; } - const uint32_t target_ack = m_send_window.start_seq + m_send_window.data_size; m_thread_blocker.unblock(); - while (m_send_window.current_ack < target_ack) - { - if (m_state != State::Established) - return return_with_maybe_zero(); - LockFreeGuard free(m_mutex); - TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); - } - - return message.size(); + return to_send; } bool TCPSocket::can_read_impl() const diff --git a/kernel/kernel/OpenFileDescriptorSet.cpp b/kernel/kernel/OpenFileDescriptorSet.cpp index d246148a..5653eac2 100644 --- a/kernel/kernel/OpenFileDescriptorSet.cpp +++ b/kernel/kernel/OpenFileDescriptorSet.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -298,11 +299,13 @@ namespace Kernel { TRY(validate_fd(fd)); auto& open_file = m_open_files[fd]; + if (open_file.inode()->mode().ifsock()) + return recvfrom(fd, buffer, nullptr, nullptr); if (!(open_file.status_flags() & O_RDONLY)) return BAN::Error::from_errno(EBADF); if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_read()) return 0; - size_t nread = TRY(open_file.inode()->read(open_file.offset(), buffer)); + const size_t nread = TRY(open_file.inode()->read(open_file.offset(), buffer)); open_file.offset() += nread; return nread; } @@ -311,13 +314,15 @@ namespace Kernel { TRY(validate_fd(fd)); auto& open_file = m_open_files[fd]; + if (open_file.inode()->mode().ifsock()) + return sendto(fd, buffer, nullptr, 0); if (!(open_file.status_flags() & O_WRONLY)) return BAN::Error::from_errno(EBADF); if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_write()) - return 0; + return BAN::Error::from_errno(EWOULDBLOCK); if (open_file.status_flags() & O_APPEND) open_file.offset() = open_file.inode()->size(); - size_t nwrite = TRY(open_file.inode()->write(open_file.offset(), buffer)); + const size_t nwrite = TRY(open_file.inode()->write(open_file.offset(), buffer)); open_file.offset() += nwrite; return nwrite; } @@ -340,6 +345,43 @@ namespace Kernel } } + BAN::ErrorOr OpenFileDescriptorSet::recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) + { + TRY(validate_fd(fd)); + auto& open_file = m_open_files[fd]; + if (!open_file.inode()->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + LockGuard _(open_file.inode()->m_mutex); + if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_read()) + return BAN::Error::from_errno(EWOULDBLOCK); + return open_file.inode()->recvfrom(buffer, address, address_len); + } + + BAN::ErrorOr OpenFileDescriptorSet::sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len) + { + TRY(validate_fd(fd)); + auto& open_file = m_open_files[fd]; + if (!open_file.inode()->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_write()) + return BAN::Error::from_errno(EWOULDBLOCK); + + LockGuard _(open_file.inode()->m_mutex); + + size_t total_sent = 0; + while (total_sent < buffer.size()) + { + if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_write()) + return total_sent; + const size_t nsend = TRY(open_file.inode()->sendto(buffer.slice(total_sent), address, address_len)); + if (nsend == 0) + return 0; + total_sent += nsend; + } + + return total_sent; + } + BAN::ErrorOr OpenFileDescriptorSet::file_of(int fd) const { TRY(validate_fd(fd)); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 302322d7..f6f95f54 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1321,16 +1321,8 @@ namespace Kernel TRY(validate_pointer_access(arguments->message, arguments->length, false)); TRY(validate_pointer_access(arguments->dest_addr, arguments->dest_len, false)); - auto inode = TRY(m_open_file_descriptors.inode_of(arguments->socket)); - if (!inode->mode().ifsock()) - return BAN::Error::from_errno(ENOTSOCK); - - const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket)); - if ((status_flags & O_NONBLOCK) && !inode->can_write()) - return BAN::Error::from_errno(EAGAIN); - - BAN::ConstByteSpan message { reinterpret_cast(arguments->message), arguments->length }; - return TRY(inode->sendto(message, arguments->dest_addr, arguments->dest_len)); + auto message = BAN::ConstByteSpan(static_cast(arguments->message), arguments->length); + return TRY(m_open_file_descriptors.sendto(arguments->socket, message, arguments->dest_addr, arguments->dest_len)); } BAN::ErrorOr Process::sys_recvfrom(sys_recvfrom_t* arguments) @@ -1349,16 +1341,8 @@ namespace Kernel TRY(validate_pointer_access(arguments->address, *arguments->address_len, true)); } - auto inode = TRY(m_open_file_descriptors.inode_of(arguments->socket)); - if (!inode->mode().ifsock()) - return BAN::Error::from_errno(ENOTSOCK); - - const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket)); - if ((status_flags & O_NONBLOCK) && !inode->can_read()) - return BAN::Error::from_errno(EAGAIN); - - BAN::ByteSpan buffer { reinterpret_cast(arguments->buffer), arguments->length }; - return TRY(inode->recvfrom(buffer, arguments->address, arguments->address_len)); + auto message = BAN::ByteSpan(static_cast(arguments->buffer), arguments->length); + return TRY(m_open_file_descriptors.recvfrom(arguments->socket, message, arguments->address, arguments->address_len)); } BAN::ErrorOr Process::sys_ioctl(int fildes, int request, void* arg)