Compare commits
11 Commits
c304133224
...
f022a1b08f
| Author | SHA1 | Date |
|---|---|---|
|
|
f022a1b08f | |
|
|
b3bbfaeff0 | |
|
|
679a3d4209 | |
|
|
a0211d88e7 | |
|
|
e216fc7798 | |
|
|
c648ea12f2 | |
|
|
2e59373a1e | |
|
|
a51a81b6cd | |
|
|
9809f87010 | |
|
|
8794122c2d | |
|
|
8fb2270ecf |
|
|
@ -126,14 +126,16 @@ namespace BAN
|
|||
Variant(Variant&& other)
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
other.clear();
|
||||
}
|
||||
|
||||
Variant(const Variant& other)
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -157,12 +159,13 @@ namespace BAN
|
|||
|
||||
Variant& operator=(Variant&& other)
|
||||
{
|
||||
if (m_index == other.m_index)
|
||||
if (m_index == other.m_index && m_index != invalid_index())
|
||||
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||
else
|
||||
{
|
||||
clear();
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
m_index = other.m_index;
|
||||
}
|
||||
other.clear();
|
||||
|
|
@ -171,12 +174,13 @@ namespace BAN
|
|||
|
||||
Variant& operator=(const Variant& other)
|
||||
{
|
||||
if (m_index == other.m_index)
|
||||
if (m_index == other.m_index && m_index != invalid_index())
|
||||
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||
else
|
||||
{
|
||||
clear();
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
m_index = other.m_index;
|
||||
}
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ namespace Kernel
|
|||
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
|
||||
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<void> getsockopt(int level, int option, void* value, socklen_t* value_len);
|
||||
BAN::ErrorOr<void> setsockopt(int level, int option, const void* value, socklen_t value_len);
|
||||
|
||||
// General API
|
||||
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
|
||||
|
|
@ -161,6 +163,8 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// General API
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <kernel/FS/Socket.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/OpenFileDescriptorSet.h>
|
||||
|
||||
namespace Kernel
|
||||
|
|
@ -32,6 +31,8 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override;
|
||||
virtual bool can_write_impl() const override;
|
||||
|
|
@ -69,9 +70,10 @@ namespace Kernel
|
|||
size_t size;
|
||||
BAN::Vector<FDWrapper> fds;
|
||||
BAN::Optional<struct ucred> ucred;
|
||||
BAN::WeakPtr<UnixDomainSocket> sender;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<void> add_packet(const msghdr&, PacketInfo&&);
|
||||
BAN::ErrorOr<size_t> add_packet(const msghdr&, PacketInfo&&, bool dont_block);
|
||||
|
||||
private:
|
||||
const Socket::Type m_socket_type;
|
||||
|
|
@ -81,10 +83,14 @@ namespace Kernel
|
|||
|
||||
BAN::CircularQueue<PacketInfo, 512> m_packet_infos;
|
||||
size_t m_packet_size_total { 0 };
|
||||
size_t m_packet_buffer_tail { 0 };
|
||||
BAN::UniqPtr<VirtualRange> m_packet_buffer;
|
||||
Mutex m_packet_lock;
|
||||
mutable Mutex m_packet_lock;
|
||||
ThreadBlocker m_packet_thread_blocker;
|
||||
|
||||
BAN::Atomic<size_t> m_sndbuf { 0 };
|
||||
BAN::Atomic<size_t> m_bytes_sent { 0 };
|
||||
|
||||
friend class BAN::RefPtr<UnixDomainSocket>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -222,6 +222,22 @@ namespace Kernel
|
|||
return getpeername_impl(address, address_len);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::getsockopt(int level, int option, void* value, socklen_t* value_len)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
return getsockopt_impl(level, option, value, value_len);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::setsockopt(int level, int option, const void* value, socklen_t value_len)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
return setsockopt_impl(level, option, value, value_len);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
|
|
|||
|
|
@ -170,8 +170,8 @@ namespace Kernel
|
|||
SpinLockGuard _(m_bound_socket_lock);
|
||||
|
||||
if (bind_address.sin_port == 0)
|
||||
bind_address.sin_port = TRY(find_free_port());
|
||||
const uint16_t port = BAN::host_to_network_endian(bind_address.sin_port);
|
||||
bind_address.sin_port = BAN::host_to_network_endian(TRY(find_free_port()));
|
||||
const uint16_t port = BAN::network_endian_to_host(bind_address.sin_port);
|
||||
|
||||
if (m_bound_sockets.contains(port))
|
||||
return BAN::Error::from_errno(EADDRINUSE);
|
||||
|
|
|
|||
|
|
@ -245,10 +245,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> TCPSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
|
@ -264,6 +261,8 @@ namespace Kernel
|
|||
{
|
||||
if (m_state != State::Established)
|
||||
return return_with_maybe_zero();
|
||||
if (flags & MSG_DONTWAIT)
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
}
|
||||
|
||||
|
|
@ -297,6 +296,34 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||
{
|
||||
if (level != SOL_SOCKET)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
int result;
|
||||
switch (option)
|
||||
{
|
||||
case SO_ERROR:
|
||||
result = 0;
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
result = m_send_window.scaled_size();
|
||||
break;
|
||||
case SO_RCVBUF:
|
||||
result = m_recv_window.buffer->size();
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
|
||||
memcpy(value, &result, len);
|
||||
*value_len = sizeof(int);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
|
|
@ -436,7 +463,7 @@ namespace Kernel
|
|||
};
|
||||
auto interface = MUST(this->interface(reinterpret_cast<const sockaddr*>(&target), sizeof(target)));
|
||||
|
||||
add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, interface->payload_mtu() - m_network_layer.header_size());
|
||||
add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, interface->payload_mtu() - m_network_layer.header_size() - protocol_header_size());
|
||||
|
||||
if (m_connection_info->has_window_scale)
|
||||
add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift);
|
||||
|
|
|
|||
|
|
@ -162,10 +162,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> UDPSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
|
@ -213,6 +210,34 @@ namespace Kernel
|
|||
return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||
{
|
||||
if (level != SOL_SOCKET)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
int result;
|
||||
switch (option)
|
||||
{
|
||||
case SO_ERROR:
|
||||
result = 0;
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
result = m_packet_buffer->size();
|
||||
break;
|
||||
case SO_RCVBUF:
|
||||
result = m_packet_buffer->size();
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
|
||||
memcpy(value, &result, len);
|
||||
*value_len = sizeof(int);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Kernel
|
|||
static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets;
|
||||
static Mutex s_bound_socket_lock;
|
||||
|
||||
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
|
||||
static constexpr size_t s_packet_buffer_size = 0x10000;
|
||||
|
||||
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
|
|
@ -45,8 +45,6 @@ namespace Kernel
|
|||
return BAN::StringView { sockaddr_un.sun_path, length };
|
||||
}
|
||||
|
||||
// FIXME: why is this using spinlocks instead of mutexes??
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
|
||||
{
|
||||
auto socket = TRY(BAN::RefPtr<UnixDomainSocket>::create(socket_type, info));
|
||||
|
|
@ -64,6 +62,7 @@ namespace Kernel
|
|||
UnixDomainSocket::UnixDomainSocket(Socket::Type socket_type, const Socket::Info& info)
|
||||
: Socket(info)
|
||||
, m_socket_type(socket_type)
|
||||
, m_sndbuf(s_packet_buffer_size)
|
||||
{
|
||||
switch (socket_type)
|
||||
{
|
||||
|
|
@ -289,28 +288,56 @@ namespace Kernel
|
|||
case Socket::Type::SEQPACKET:
|
||||
case Socket::Type::DGRAM:
|
||||
return false;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::add_packet(const msghdr& packet, PacketInfo&& packet_info)
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::add_packet(const msghdr& packet, PacketInfo&& packet_info, bool dont_block)
|
||||
{
|
||||
LockGuard _(m_packet_lock);
|
||||
|
||||
while (m_packet_infos.full() || m_packet_size_total + packet_info.size > s_packet_buffer_size)
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
|
||||
const auto has_space =
|
||||
[&]() -> bool
|
||||
{
|
||||
if (m_packet_infos.full())
|
||||
return false;
|
||||
if (is_streaming())
|
||||
return m_packet_size_total < m_packet_buffer->size();
|
||||
return m_packet_size_total + packet_info.size <= m_packet_buffer->size();
|
||||
};
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr() + m_packet_size_total);
|
||||
|
||||
size_t offset = 0;
|
||||
for (int i = 0; i < packet.msg_iovlen; i++)
|
||||
while (!has_space())
|
||||
{
|
||||
memcpy(packet_buffer + offset, packet.msg_iov[i].iov_base, packet.msg_iov[i].iov_len);
|
||||
offset += packet.msg_iov[i].iov_len;
|
||||
if (dont_block)
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
|
||||
}
|
||||
|
||||
ASSERT(offset == packet_info.size);
|
||||
if (auto available = m_packet_buffer->size() - m_packet_size_total; available < packet_info.size)
|
||||
{
|
||||
ASSERT(is_streaming());
|
||||
packet_info.size = available;
|
||||
}
|
||||
|
||||
uint8_t* packet_buffer_base_u8 = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
|
||||
size_t bytes_copied = 0;
|
||||
for (int i = 0; i < packet.msg_iovlen && bytes_copied < packet_info.size; i++)
|
||||
{
|
||||
const uint8_t* iov_base_u8 = static_cast<const uint8_t*>(packet.msg_iov[i].iov_base);
|
||||
|
||||
const size_t to_copy = BAN::Math::min(packet.msg_iov[i].iov_len, packet_info.size - bytes_copied);
|
||||
|
||||
const size_t copy_offset = (m_packet_buffer_tail + m_packet_size_total + bytes_copied) % m_packet_buffer->size();
|
||||
const size_t before_wrap = BAN::Math::min(to_copy, m_packet_buffer->size() - copy_offset);
|
||||
memcpy(packet_buffer_base_u8 + copy_offset, iov_base_u8, before_wrap);
|
||||
if (const size_t after_wrap = to_copy - before_wrap)
|
||||
memcpy(packet_buffer_base_u8, iov_base_u8 + before_wrap, after_wrap);
|
||||
|
||||
bytes_copied += to_copy;
|
||||
}
|
||||
|
||||
ASSERT(bytes_copied == packet_info.size);
|
||||
m_packet_size_total += packet_info.size;
|
||||
m_packet_infos.emplace(BAN::move(packet_info));
|
||||
|
||||
|
|
@ -318,7 +345,7 @@ namespace Kernel
|
|||
|
||||
epoll_notify(EPOLLIN);
|
||||
|
||||
return {};
|
||||
return bytes_copied;
|
||||
}
|
||||
|
||||
bool UnixDomainSocket::can_read_impl() const
|
||||
|
|
@ -334,24 +361,13 @@ namespace Kernel
|
|||
return false;
|
||||
}
|
||||
|
||||
LockGuard _(m_packet_lock);
|
||||
return m_packet_size_total > 0;
|
||||
}
|
||||
|
||||
bool UnixDomainSocket::can_write_impl() const
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
auto connection = connection_info.connection.lock();
|
||||
if (!connection)
|
||||
return false;
|
||||
if (connection->m_packet_infos.full())
|
||||
return false;
|
||||
if (connection->m_packet_size_total >= s_packet_buffer_size)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_bytes_sent < m_sndbuf;
|
||||
}
|
||||
|
||||
bool UnixDomainSocket::has_hungup_impl() const
|
||||
|
|
@ -375,6 +391,7 @@ namespace Kernel
|
|||
}
|
||||
|
||||
LockGuard _(m_packet_lock);
|
||||
|
||||
while (m_packet_size_total == 0)
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
|
|
@ -395,7 +412,7 @@ namespace Kernel
|
|||
cheader->cmsg_len = message.msg_controllen;
|
||||
size_t cheader_len = 0;
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
uint8_t* packet_buffer_base_u8 = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
|
||||
message.msg_flags = 0;
|
||||
|
||||
|
|
@ -469,7 +486,12 @@ namespace Kernel
|
|||
uint8_t* iov_base = static_cast<uint8_t*>(iov.iov_base);
|
||||
|
||||
const size_t nrecv = BAN::Math::min<size_t>(iov.iov_len - iov_offset, packet_info.size - packet_received);
|
||||
memcpy(iov_base + iov_offset, packet_buffer + packet_received, nrecv);
|
||||
|
||||
const size_t copy_offset = (m_packet_buffer_tail + packet_received) % m_packet_buffer->size();
|
||||
const size_t before_wrap = BAN::Math::min<size_t>(nrecv, m_packet_buffer->size() - copy_offset);
|
||||
memcpy(iov_base + iov_offset, packet_buffer_base_u8 + copy_offset, before_wrap);
|
||||
if (const size_t after_wrap = nrecv - before_wrap)
|
||||
memcpy(iov_base + iov_offset + before_wrap, packet_buffer_base_u8, after_wrap);
|
||||
|
||||
packet_received += nrecv;
|
||||
|
||||
|
|
@ -490,12 +512,17 @@ namespace Kernel
|
|||
if (packet_info.size == 0)
|
||||
m_packet_infos.pop();
|
||||
|
||||
// FIXME: get rid of this memmove :)
|
||||
memmove(packet_buffer, packet_buffer + to_discard, m_packet_size_total - to_discard);
|
||||
m_packet_buffer_tail = (m_packet_buffer_tail + to_discard) % m_packet_buffer->size();
|
||||
m_packet_size_total -= to_discard;
|
||||
|
||||
total_recv += packet_received;
|
||||
|
||||
if (auto sender = packet_info.sender.lock())
|
||||
{
|
||||
sender->m_bytes_sent -= to_discard;
|
||||
sender->epoll_notify(EPOLLOUT);
|
||||
}
|
||||
|
||||
// on linux ancillary data is a barrier on stream sockets, lets do the same
|
||||
if (!is_streaming() || had_ancillary_data)
|
||||
break;
|
||||
|
|
@ -505,17 +532,12 @@ namespace Kernel
|
|||
|
||||
m_packet_thread_blocker.unblock();
|
||||
|
||||
epoll_notify(EPOLLOUT);
|
||||
|
||||
return total_recv;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
if (flags & ~(MSG_NOSIGNAL | MSG_DONTWAIT))
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
|
@ -529,13 +551,14 @@ namespace Kernel
|
|||
return result;
|
||||
}();
|
||||
|
||||
if (total_message_size > s_packet_buffer_size)
|
||||
return BAN::Error::from_errno(ENOBUFS);
|
||||
if (!is_streaming() && total_message_size > m_packet_buffer->size())
|
||||
return BAN::Error::from_errno(EMSGSIZE);
|
||||
|
||||
PacketInfo packet_info {
|
||||
.size = total_message_size,
|
||||
.fds = {},
|
||||
.ucred = {},
|
||||
.size = total_message_size,
|
||||
.fds = {},
|
||||
.ucred = {},
|
||||
.sender = TRY(get_weak_ptr()),
|
||||
};
|
||||
|
||||
for (const auto* header = CMSG_FIRSTHDR(&message); header; header = CMSG_NXTHDR(&message, header))
|
||||
|
|
@ -608,8 +631,9 @@ namespace Kernel
|
|||
auto target = connection_info.connection.lock();
|
||||
if (!target)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
TRY(target->add_packet(message, BAN::move(packet_info)));
|
||||
return total_message_size;
|
||||
const size_t bytes_sent = TRY(target->add_packet(message, BAN::move(packet_info), flags & MSG_DONTWAIT));
|
||||
m_bytes_sent += bytes_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -626,7 +650,7 @@ namespace Kernel
|
|||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
absolute_path,
|
||||
O_RDWR
|
||||
O_WRONLY
|
||||
)).inode;
|
||||
}
|
||||
else
|
||||
|
|
@ -652,9 +676,11 @@ namespace Kernel
|
|||
|
||||
if (!target)
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
TRY(target->add_packet(message, BAN::move(packet_info)));
|
||||
|
||||
return total_message_size;
|
||||
if (target->m_socket_type != m_socket_type)
|
||||
return BAN::Error::from_errno(EPROTOTYPE);
|
||||
const auto bytes_sent = TRY(target->add_packet(message, BAN::move(packet_info), flags & MSG_DONTWAIT));
|
||||
m_bytes_sent += bytes_sent;
|
||||
return bytes_sent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -678,4 +704,58 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||
{
|
||||
if (level != SOL_SOCKET)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
int result;
|
||||
switch (option)
|
||||
{
|
||||
case SO_ERROR:
|
||||
result = 0;
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
result = m_sndbuf;
|
||||
break;
|
||||
case SO_RCVBUF:
|
||||
result = m_packet_buffer->size();
|
||||
break;
|
||||
default:
|
||||
dwarnln("getsockopt(SOL_SOCKET, {})", option);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
|
||||
memcpy(value, &result, len);
|
||||
*value_len = sizeof(int);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
|
||||
{
|
||||
if (level != SOL_SOCKET)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case SO_SNDBUF:
|
||||
{
|
||||
if (value_len != sizeof(int))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
const int new_sndbuf = *static_cast<const int*>(value);
|
||||
if (new_sndbuf < 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
m_sndbuf = new_sndbuf;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dwarnln("setsockopt(SOL_SOCKET, {})", option);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -795,7 +795,7 @@ namespace Kernel
|
|||
|
||||
LockGuard _(inode->m_mutex);
|
||||
if (is_nonblock && !inode->can_read())
|
||||
return BAN::Error::from_errno(EWOULDBLOCK);
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
return inode->recvmsg(message, flags);
|
||||
}
|
||||
|
||||
|
|
@ -817,12 +817,13 @@ namespace Kernel
|
|||
LockGuard _(inode->m_mutex);
|
||||
if (inode->has_hungup())
|
||||
{
|
||||
Thread::current().add_signal(SIGPIPE, {});
|
||||
if (!(flags & MSG_NOSIGNAL))
|
||||
Thread::current().add_signal(SIGPIPE, {});
|
||||
return BAN::Error::from_errno(EPIPE);
|
||||
}
|
||||
if (is_nonblock && !inode->can_write())
|
||||
return BAN::Error::from_errno(EWOULDBLOCK);
|
||||
return inode->sendmsg(message, flags);
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||
|
|
|
|||
|
|
@ -1674,20 +1674,13 @@ namespace Kernel
|
|||
if (!inode->mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
|
||||
switch (option_name)
|
||||
{
|
||||
case SO_ERROR:
|
||||
{
|
||||
option_len = BAN::Math::min<socklen_t>(option_len, sizeof(int));
|
||||
const int zero { 0 };
|
||||
TRY(write_to_user(user_option_value, &zero, option_len));
|
||||
TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, true));
|
||||
BAN::ScopeGuard _([buffer] { buffer->unpin(); });
|
||||
|
||||
dwarnln("getsockopt(SOL_SOCKET, {})", option_name);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
TRY(inode->getsockopt(level, option_name, user_option_value, &option_len));
|
||||
TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_setsockopt(int socket, int level, int option_name, const void* user_option_value, socklen_t option_len)
|
||||
|
|
@ -1705,10 +1698,12 @@ namespace Kernel
|
|||
if (!inode->mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
|
||||
(void)user_option_value;
|
||||
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, false));
|
||||
BAN::ScopeGuard _([buffer] { buffer->unpin(); });
|
||||
|
||||
dwarnln("setsockopt(SOL_SOCKET, {})", option_name);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
TRY(inode->setsockopt(level, option_name, user_option_value, option_len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_accept(int socket, sockaddr* address, socklen_t* address_len, int flags)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ typedef struct
|
|||
{
|
||||
short flags;
|
||||
pid_t pgroup;
|
||||
sched_param schedparam;
|
||||
struct sched_param schedparam;
|
||||
int schedpolicy;
|
||||
sigset_t sigdefault;
|
||||
sigset_t sigmask;
|
||||
|
|
|
|||
|
|
@ -123,14 +123,15 @@ struct linger
|
|||
|
||||
#define SOMAXCONN 4096
|
||||
|
||||
#define MSG_CTRUNC 0x01
|
||||
#define MSG_DONTROUTE 0x02
|
||||
#define MSG_EOR 0x04
|
||||
#define MSG_OOB 0x08
|
||||
#define MSG_NOSIGNAL 0x10
|
||||
#define MSG_PEEK 0x20
|
||||
#define MSG_TRUNC 0x40
|
||||
#define MSG_WAITALL 0x80
|
||||
#define MSG_CTRUNC 0x001
|
||||
#define MSG_DONTROUTE 0x002
|
||||
#define MSG_EOR 0x004
|
||||
#define MSG_OOB 0x008
|
||||
#define MSG_NOSIGNAL 0x010
|
||||
#define MSG_PEEK 0x020
|
||||
#define MSG_TRUNC 0x040
|
||||
#define MSG_WAITALL 0x080
|
||||
#define MSG_DONTWAIT 0x100
|
||||
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_INET 1
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
|
|||
if (ret <= 0)
|
||||
return result;
|
||||
nread += ret;
|
||||
result += ret;
|
||||
}
|
||||
result += nread;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -44,8 +45,9 @@ ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
|
|||
if (ret <= 0)
|
||||
return result;
|
||||
nwrite += ret;
|
||||
result += ret;
|
||||
}
|
||||
result += nwrite;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ namespace LibGUI
|
|||
void fill_rect(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t color);
|
||||
void fill(uint32_t color) { return fill_rect(0, 0, width(), height(), color); }
|
||||
|
||||
void clear_rect(int32_t x, int32_t y, uint32_t width, uint32_t height) { fill_rect(x, y, width, height, m_bg_color); }
|
||||
void clear() { return clear_rect(0, 0, width(), height()); }
|
||||
|
||||
void copy_texture(const Texture& texture, int32_t x, int32_t y, uint32_t sub_x = 0, uint32_t sub_y = 0, uint32_t width = -1, uint32_t height = -1);
|
||||
|
||||
void draw_character(uint32_t codepoint, const LibFont::Font& font, int32_t x, int32_t y, uint32_t color);
|
||||
|
|
|
|||
|
|
@ -373,8 +373,6 @@ static void handle_copy_relocation(const LoadedElf& elf, const RelocT& reloc)
|
|||
reinterpret_cast<void*>(src_elf->base + src_sym->st_value),
|
||||
symbol.st_size
|
||||
);
|
||||
|
||||
src_sym->st_value = (elf.base + reloc.r_offset) - src_elf->base;
|
||||
}
|
||||
|
||||
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
|
||||
|
|
@ -927,6 +925,8 @@ static bool can_load_elf(int fd, const ElfNativeFileHeader& file_header, uintptr
|
|||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Don't map read-only sections as writable with DT_TEXTREL.
|
||||
// Instead mprotect the areas writable during relocation.
|
||||
static void load_program_header(const ElfNativeProgramHeader& program_header, int fd, bool needs_writable)
|
||||
{
|
||||
if (program_header.p_type != PT_LOAD)
|
||||
|
|
@ -966,7 +966,7 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
|
|||
mmap_args.flags = MAP_PRIVATE | MAP_FIXED;
|
||||
mmap_args.len = file_backed_size;
|
||||
mmap_args.off = program_header.p_offset;
|
||||
mmap_args.prot = prot | PROT_WRITE;
|
||||
mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0);
|
||||
|
||||
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(program_header.p_vaddr))
|
||||
print_error_and_exit("could not load program header", ret);
|
||||
|
|
@ -1002,12 +1002,13 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
|
|||
0x00,
|
||||
program_header.p_memsz - program_header.p_filesz
|
||||
);
|
||||
}
|
||||
|
||||
if (!(prot & PROT_WRITE) && !needs_writable)
|
||||
{
|
||||
// FIXME: Implement mprotect so PROT_WRITE can be removed
|
||||
//syscall(SYS_MPROTECT, start_vaddr, length, prot);
|
||||
if (!(prot & PROT_WRITE) && !needs_writable)
|
||||
{
|
||||
if (auto ret = syscall(SYS_MPROTECT, program_header.p_vaddr + file_backed_size, program_header.p_memsz - file_backed_size, prot))
|
||||
print_error_and_exit("failed to remove PROT_WRITE from mapped", ret);
|
||||
print(STDDBG_FILENO, "dropped PROT_WRITE :nekocatwoah:");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,12 @@ BAN::ErrorOr<void> Execute::execute_command(const PipedCommand& piped_command)
|
|||
}
|
||||
);
|
||||
|
||||
if (piped_command.commands[i].arguments.empty())
|
||||
{
|
||||
child_codes[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int fd_in = last_pipe_rd;
|
||||
const int fd_out = new_pipe[1];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue