ladybird/Kernel/Socket.cpp
Andreas Kling d5f515cf6c Kernel: Give each FileDescriptor a chance to co-open sockets.
Track how many fds are open for a socket's Accepted and Connected roles.
This allows fork() to clone a socket fd without a subsequent close() walking
all over the parent process's fd.
2019-02-17 11:00:35 +01:00

64 lines
1.4 KiB
C++

#include <Kernel/Socket.h>
#include <Kernel/LocalSocket.h>
#include <Kernel/UnixTypes.h>
#include <Kernel/Process.h>
#include <LibC/errno_numbers.h>
RetainPtr<Socket> Socket::create(int domain, int type, int protocol, int& error)
{
(void)protocol;
switch (domain) {
case AF_LOCAL:
return LocalSocket::create(type & SOCK_TYPE_MASK);
default:
error = EAFNOSUPPORT;
return nullptr;
}
}
Socket::Socket(int domain, int type, int protocol)
: m_domain(domain)
, m_type(type)
, m_protocol(protocol)
{
m_origin_pid = current->pid();
}
Socket::~Socket()
{
}
bool Socket::listen(int backlog, int& error)
{
LOCKER(m_lock);
if (m_type != SOCK_STREAM) {
error = -EOPNOTSUPP;
return false;
}
m_backlog = backlog;
kprintf("Socket{%p} listening with backlog=%d\n", this, m_backlog);
return true;
}
RetainPtr<Socket> Socket::accept()
{
LOCKER(m_lock);
if (m_pending.is_empty())
return nullptr;
auto client = m_pending.take_first();
ASSERT(!client->is_connected());
client->m_connected = true;
m_clients.append(client.copy_ref());
return client;
}
bool Socket::queue_connection_from(Socket& peer, int& error)
{
LOCKER(m_lock);
if (m_pending.size() >= m_backlog) {
error = -ECONNREFUSED;
return false;
}
m_pending.append(peer);
return true;
}