Kernel: Make nonblocking sockets unblocking :)
This commit is contained in:
parent
c9132d984b
commit
15045cc486
|
@ -169,6 +169,7 @@ namespace Kernel
|
|||
private:
|
||||
BAN::WeakPtr<SharedFileData> m_shared_region;
|
||||
friend class FileBackedRegion;
|
||||
friend class OpenFileDescriptorSet;
|
||||
friend class SharedFileData;
|
||||
friend class TTY;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
||||
|
||||
BAN::ErrorOr<size_t> recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<size_t> sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len);
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||
BAN::ErrorOr<BAN::StringView> path_of(int) const;
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
||||
|
|
|
@ -226,51 +226,33 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> 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<size_t>(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<size_t>(message.size(), m_send_window.buffer->size() - m_send_window.data_size);
|
||||
|
||||
{
|
||||
auto* buffer = reinterpret_cast<uint8_t*>(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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <kernel/FS/Pipe.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Networking/NetworkManager.h>
|
||||
#include <kernel/OpenFileDescriptorSet.h>
|
||||
|
||||
|
@ -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<size_t> 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<size_t> 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<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||
{
|
||||
TRY(validate_fd(fd));
|
||||
|
|
|
@ -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<const uint8_t*>(arguments->message), arguments->length };
|
||||
return TRY(inode->sendto(message, arguments->dest_addr, arguments->dest_len));
|
||||
auto message = BAN::ConstByteSpan(static_cast<const uint8_t*>(arguments->message), arguments->length);
|
||||
return TRY(m_open_file_descriptors.sendto(arguments->socket, message, arguments->dest_addr, arguments->dest_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> 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<uint8_t*>(arguments->buffer), arguments->length };
|
||||
return TRY(inode->recvfrom(buffer, arguments->address, arguments->address_len));
|
||||
auto message = BAN::ByteSpan(static_cast<uint8_t*>(arguments->buffer), arguments->length);
|
||||
return TRY(m_open_file_descriptors.recvfrom(arguments->socket, message, arguments->address, arguments->address_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_ioctl(int fildes, int request, void* arg)
|
||||
|
|
Loading…
Reference in New Issue