Kernel: Rewrite Sockets to not be TmpInodes
TmpInodes just caused issues because TmpFS kept them alive. There was really no reason for sockets to even be stored inside a TmpFS...
This commit is contained in:
@@ -68,18 +68,12 @@ namespace Kernel
|
||||
header.checksum = calculate_internet_checksum(BAN::ConstByteSpan::from(header), {});
|
||||
}
|
||||
|
||||
void IPv4Layer::unbind_socket(BAN::RefPtr<NetworkSocket> socket, uint16_t port)
|
||||
void IPv4Layer::unbind_socket(uint16_t port)
|
||||
{
|
||||
{
|
||||
SpinLockGuard _(m_bound_socket_lock);
|
||||
auto it = m_bound_sockets.find(port);
|
||||
if (it != m_bound_sockets.end())
|
||||
{
|
||||
ASSERT(it->value.lock() == socket);
|
||||
m_bound_sockets.remove(it);
|
||||
}
|
||||
}
|
||||
NetworkManager::get().TmpFileSystem::remove_from_cache(socket);
|
||||
SpinLockGuard _(m_bound_socket_lock);
|
||||
auto it = m_bound_sockets.find(port);
|
||||
ASSERT(it != m_bound_sockets.end());
|
||||
m_bound_sockets.remove(it);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> IPv4Layer::bind_socket_to_unused(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len)
|
||||
|
||||
@@ -19,11 +19,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> NetworkManager::initialize()
|
||||
{
|
||||
ASSERT(!s_instance);
|
||||
NetworkManager* manager_ptr = new NetworkManager();
|
||||
if (manager_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto manager = BAN::UniqPtr<NetworkManager>::adopt(manager_ptr);
|
||||
TRY(manager->TmpFileSystem::initialize(0777, 0, 0));
|
||||
auto manager = TRY(BAN::UniqPtr<NetworkManager>::create());
|
||||
manager->m_ipv4_layer = TRY(IPv4Layer::create());
|
||||
s_instance = BAN::move(manager);
|
||||
return {};
|
||||
@@ -35,10 +31,6 @@ namespace Kernel
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
NetworkManager::NetworkManager()
|
||||
: TmpFileSystem(128)
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> NetworkManager::add_interface(PCI::Device& pci_device)
|
||||
{
|
||||
BAN::RefPtr<NetworkInterface> interface;
|
||||
@@ -72,21 +64,21 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<TmpInode>> NetworkManager::create_socket(SocketDomain domain, SocketType type, mode_t mode, uid_t uid, gid_t gid)
|
||||
BAN::ErrorOr<BAN::RefPtr<Socket>> NetworkManager::create_socket(Socket::Domain domain, Socket::Type type, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
switch (domain)
|
||||
{
|
||||
case SocketDomain::INET:
|
||||
case Socket::Domain::INET:
|
||||
switch (type)
|
||||
{
|
||||
case SocketType::DGRAM:
|
||||
case SocketType::STREAM:
|
||||
case Socket::Type::DGRAM:
|
||||
case Socket::Type::STREAM:
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(EPROTOTYPE);
|
||||
}
|
||||
break;
|
||||
case SocketDomain::UNIX:
|
||||
case Socket::Domain::UNIX:
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
@@ -95,30 +87,28 @@ namespace Kernel
|
||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||
mode |= Inode::Mode::IFSOCK;
|
||||
|
||||
auto inode_info = create_inode_info(mode, uid, gid);
|
||||
ino_t ino = TRY(allocate_inode(inode_info));
|
||||
|
||||
BAN::RefPtr<TmpInode> socket;
|
||||
auto socket_info = Socket::Info { .mode = mode, .uid = uid, .gid = gid };
|
||||
BAN::RefPtr<Socket> socket;
|
||||
switch (domain)
|
||||
{
|
||||
case SocketDomain::INET:
|
||||
case Socket::Domain::INET:
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SocketType::DGRAM:
|
||||
socket = TRY(UDPSocket::create(*m_ipv4_layer, ino, inode_info));
|
||||
case Socket::Type::DGRAM:
|
||||
socket = TRY(UDPSocket::create(*m_ipv4_layer, socket_info));
|
||||
break;
|
||||
case SocketType::STREAM:
|
||||
socket = TRY(TCPSocket::create(*m_ipv4_layer, ino, inode_info));
|
||||
case Socket::Type::STREAM:
|
||||
socket = TRY(TCPSocket::create(*m_ipv4_layer, socket_info));
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SocketDomain::UNIX:
|
||||
case Socket::Domain::UNIX:
|
||||
{
|
||||
socket = TRY(UnixDomainSocket::create(type, ino, inode_info));
|
||||
socket = TRY(UnixDomainSocket::create(type, socket_info));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
NetworkSocket::NetworkSocket(NetworkLayer& network_layer, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(NetworkManager::get(), ino, inode_info)
|
||||
NetworkSocket::NetworkSocket(NetworkLayer& network_layer, const Socket::Info& info)
|
||||
: Socket(info)
|
||||
, m_network_layer(network_layer)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace Kernel
|
||||
static constexpr size_t s_window_buffer_size = 15 * PAGE_SIZE;
|
||||
static_assert(s_window_buffer_size <= UINT16_MAX);
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, const Info& info)
|
||||
{
|
||||
auto socket = TRY(BAN::RefPtr<TCPSocket>::create(network_layer, ino, inode_info));
|
||||
auto socket = TRY(BAN::RefPtr<TCPSocket>::create(network_layer, info));
|
||||
socket->m_recv_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||
PageTable::kernel(),
|
||||
KERNEL_OFFSET,
|
||||
@@ -48,11 +48,13 @@ namespace Kernel
|
||||
reinterpret_cast<TCPSocket*>(socket_ptr)->process_task();
|
||||
}, socket.ptr()
|
||||
);
|
||||
// hack to keep socket alive until its process starts
|
||||
socket->ref();
|
||||
return socket;
|
||||
}
|
||||
|
||||
TCPSocket::TCPSocket(NetworkLayer& network_layer, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
: NetworkSocket(network_layer, ino, inode_info)
|
||||
TCPSocket::TCPSocket(NetworkLayer& network_layer, const Info& info)
|
||||
: NetworkSocket(network_layer, info)
|
||||
{
|
||||
m_send_window.start_seq = Random::get_u32() & 0x7FFFFFFF;
|
||||
m_send_window.current_seq = m_send_window.start_seq;
|
||||
@@ -89,7 +91,7 @@ namespace Kernel
|
||||
|
||||
BAN::RefPtr<TCPSocket> return_inode;
|
||||
{
|
||||
auto return_inode_tmp = TRY(NetworkManager::get().create_socket(m_network_layer.domain(), SocketType::STREAM, mode().mode & ~Mode::TYPE_MASK, uid(), gid()));
|
||||
auto return_inode_tmp = TRY(NetworkManager::get().create_socket(m_network_layer.domain(), Socket::Type::STREAM, mode().mode & ~Mode::TYPE_MASK, uid(), gid()));
|
||||
return_inode = static_cast<TCPSocket*>(return_inode_tmp.ptr());
|
||||
}
|
||||
|
||||
@@ -605,13 +607,9 @@ namespace Kernel
|
||||
// NOTE: Only listen socket can unbind the socket as
|
||||
// listen socket is always alive to redirect packets
|
||||
if (!m_listen_parent)
|
||||
m_network_layer.unbind_socket(this, m_port);
|
||||
m_network_layer.unbind_socket(m_port);
|
||||
else
|
||||
{
|
||||
m_listen_parent->remove_listen_child(this);
|
||||
// Listen children are not actually bound, so they have to be manually removed
|
||||
NetworkManager::get().TmpFileSystem::remove_from_cache(this);
|
||||
}
|
||||
m_interface = nullptr;
|
||||
m_port = PORT_NONE;
|
||||
dprintln_if(DEBUG_TCP, "Socket unbound");
|
||||
@@ -643,6 +641,7 @@ namespace Kernel
|
||||
static constexpr uint32_t retransmit_timeout_ms = 1000;
|
||||
|
||||
BAN::RefPtr<TCPSocket> keep_alive { this };
|
||||
this->unref();
|
||||
|
||||
while (m_process)
|
||||
{
|
||||
@@ -657,8 +656,8 @@ namespace Kernel
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is the last instance (one instance in network manager and another keep_alive)
|
||||
if (ref_count() == 2)
|
||||
// This is the last instance
|
||||
if (ref_count() == 1)
|
||||
{
|
||||
if (m_state == State::Listen)
|
||||
{
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<UDPSocket>> UDPSocket::create(NetworkLayer& network_layer, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
BAN::ErrorOr<BAN::RefPtr<UDPSocket>> UDPSocket::create(NetworkLayer& network_layer, const Socket::Info& info)
|
||||
{
|
||||
auto socket = TRY(BAN::RefPtr<UDPSocket>::create(network_layer, ino, inode_info));
|
||||
auto socket = TRY(BAN::RefPtr<UDPSocket>::create(network_layer, info));
|
||||
socket->m_packet_buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||
PageTable::kernel(),
|
||||
KERNEL_OFFSET,
|
||||
@@ -19,14 +19,14 @@ namespace Kernel
|
||||
return socket;
|
||||
}
|
||||
|
||||
UDPSocket::UDPSocket(NetworkLayer& network_layer, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
: NetworkSocket(network_layer, ino, inode_info)
|
||||
UDPSocket::UDPSocket(NetworkLayer& network_layer, const Socket::Info& info)
|
||||
: NetworkSocket(network_layer, info)
|
||||
{ }
|
||||
|
||||
UDPSocket::~UDPSocket()
|
||||
{
|
||||
if (is_bound())
|
||||
m_network_layer.unbind_socket(this, m_port);
|
||||
m_network_layer.unbind_socket(m_port);
|
||||
m_port = PORT_NONE;
|
||||
m_interface = nullptr;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace Kernel
|
||||
|
||||
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(SocketType socket_type, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
|
||||
{
|
||||
auto socket = TRY(BAN::RefPtr<UnixDomainSocket>::create(socket_type, ino, inode_info));
|
||||
auto socket = TRY(BAN::RefPtr<UnixDomainSocket>::create(socket_type, info));
|
||||
socket->m_packet_buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||
PageTable::kernel(),
|
||||
KERNEL_OFFSET,
|
||||
@@ -29,17 +29,17 @@ namespace Kernel
|
||||
return socket;
|
||||
}
|
||||
|
||||
UnixDomainSocket::UnixDomainSocket(SocketType socket_type, ino_t ino, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(NetworkManager::get(), ino, inode_info)
|
||||
UnixDomainSocket::UnixDomainSocket(Socket::Type socket_type, const Socket::Info& info)
|
||||
: Socket(info)
|
||||
, m_socket_type(socket_type)
|
||||
{
|
||||
switch (socket_type)
|
||||
{
|
||||
case SocketType::STREAM:
|
||||
case SocketType::SEQPACKET:
|
||||
case Socket::Type::STREAM:
|
||||
case Socket::Type::SEQPACKET:
|
||||
m_info.emplace<ConnectionInfo>();
|
||||
break;
|
||||
case SocketType::DGRAM:
|
||||
case Socket::Type::DGRAM:
|
||||
m_info.emplace<ConnectionlessInfo>();
|
||||
break;
|
||||
default:
|
||||
@@ -55,7 +55,6 @@ namespace Kernel
|
||||
auto it = s_bound_sockets.find(m_bound_path);
|
||||
if (it != s_bound_sockets.end())
|
||||
s_bound_sockets.remove(it);
|
||||
m_bound_path.clear();
|
||||
}
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
@@ -63,7 +62,6 @@ namespace Kernel
|
||||
if (auto connection = connection_info.connection.lock(); connection && connection->m_info.has<ConnectionInfo>())
|
||||
connection->m_info.get<ConnectionInfo>().target_closed = true;
|
||||
}
|
||||
m_info.clear();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> UnixDomainSocket::accept_impl(sockaddr* address, socklen_t* address_len)
|
||||
@@ -89,7 +87,7 @@ namespace Kernel
|
||||
BAN::RefPtr<UnixDomainSocket> return_inode;
|
||||
|
||||
{
|
||||
auto return_inode_tmp = TRY(NetworkManager::get().create_socket(SocketDomain::UNIX, m_socket_type, mode().mode & ~Mode::TYPE_MASK, uid(), gid()));
|
||||
auto return_inode_tmp = TRY(NetworkManager::get().create_socket(Socket::Domain::UNIX, m_socket_type, mode().mode & ~Mode::TYPE_MASK, uid(), gid()));
|
||||
return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr());
|
||||
}
|
||||
|
||||
@@ -227,10 +225,10 @@ namespace Kernel
|
||||
{
|
||||
switch (m_socket_type)
|
||||
{
|
||||
case SocketType::STREAM:
|
||||
case Socket::Type::STREAM:
|
||||
return true;
|
||||
case SocketType::SEQPACKET:
|
||||
case SocketType::DGRAM:
|
||||
case Socket::Type::SEQPACKET:
|
||||
case Socket::Type::DGRAM:
|
||||
return false;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
@@ -97,38 +97,38 @@ namespace Kernel
|
||||
{
|
||||
bool valid_protocol = true;
|
||||
|
||||
SocketDomain sock_domain;
|
||||
Socket::Domain sock_domain;
|
||||
switch (domain)
|
||||
{
|
||||
case AF_INET:
|
||||
sock_domain = SocketDomain::INET;
|
||||
sock_domain = Socket::Domain::INET;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sock_domain = SocketDomain::INET6;
|
||||
sock_domain = Socket::Domain::INET6;
|
||||
break;
|
||||
case AF_UNIX:
|
||||
sock_domain = SocketDomain::UNIX;
|
||||
sock_domain = Socket::Domain::UNIX;
|
||||
valid_protocol = false;
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(EPROTOTYPE);
|
||||
}
|
||||
|
||||
SocketType sock_type;
|
||||
Socket::Type sock_type;
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM:
|
||||
sock_type = SocketType::STREAM;
|
||||
sock_type = Socket::Type::STREAM;
|
||||
if (protocol != IPPROTO_TCP)
|
||||
valid_protocol = false;
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
sock_type = SocketType::DGRAM;
|
||||
sock_type = Socket::Type::DGRAM;
|
||||
if (protocol != IPPROTO_UDP)
|
||||
valid_protocol = false;
|
||||
break;
|
||||
case SOCK_SEQPACKET:
|
||||
sock_type = SocketType::SEQPACKET;
|
||||
sock_type = Socket::Type::SEQPACKET;
|
||||
valid_protocol = false;
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user