mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 10:07:40 +00:00
Kernel: Move socket role tracking to the Socket class itself
This is more logical and allows us to solve the problem of non-blocking TCP sockets getting stuck in SocketRole::None. The only complication is that a single LocalSocket may be shared between two file descriptions (on the connect and accept sides), and should have two different roles depending from which side you look at it. To deal with it, Socket::role() is made a virtual method that accepts a file description, and LocalSocket internally tracks which FileDescription is the which one and returns a correct role.
This commit is contained in:
parent
d46c3b0b5b
commit
43ce6c5474
11 changed files with 103 additions and 95 deletions
|
@ -22,17 +22,16 @@ NonnullRefPtr<FileDescription> FileDescription::create(Custody& custody)
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<FileDescription> FileDescription::create(File& file, SocketRole role)
|
NonnullRefPtr<FileDescription> FileDescription::create(File& file)
|
||||||
{
|
{
|
||||||
return adopt(*new FileDescription(file, role));
|
return adopt(*new FileDescription(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDescription::FileDescription(File& file, SocketRole role)
|
FileDescription::FileDescription(File& file)
|
||||||
: m_file(file)
|
: m_file(file)
|
||||||
{
|
{
|
||||||
if (file.is_inode())
|
if (file.is_inode())
|
||||||
m_inode = static_cast<InodeFile&>(file).inode();
|
m_inode = static_cast<InodeFile&>(file).inode();
|
||||||
set_socket_role(role);
|
|
||||||
if (is_socket())
|
if (is_socket())
|
||||||
socket()->attach(*this);
|
socket()->attach(*this);
|
||||||
}
|
}
|
||||||
|
@ -47,15 +46,6 @@ FileDescription::~FileDescription()
|
||||||
m_inode = nullptr;
|
m_inode = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDescription::set_socket_role(SocketRole role)
|
|
||||||
{
|
|
||||||
if (role == m_socket_role)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ASSERT(is_socket());
|
|
||||||
m_socket_role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
KResult FileDescription::fstat(stat& buffer)
|
KResult FileDescription::fstat(stat& buffer)
|
||||||
{
|
{
|
||||||
ASSERT(!is_fifo());
|
ASSERT(!is_fifo());
|
||||||
|
|
|
@ -23,7 +23,7 @@ class SharedMemory;
|
||||||
class FileDescription : public RefCounted<FileDescription> {
|
class FileDescription : public RefCounted<FileDescription> {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<FileDescription> create(Custody&);
|
static NonnullRefPtr<FileDescription> create(Custody&);
|
||||||
static NonnullRefPtr<FileDescription> create(File&, SocketRole = SocketRole::None);
|
static NonnullRefPtr<FileDescription> create(File&);
|
||||||
~FileDescription();
|
~FileDescription();
|
||||||
|
|
||||||
int close();
|
int close();
|
||||||
|
@ -93,9 +93,6 @@ public:
|
||||||
|
|
||||||
void set_original_inode(Badge<VFS>, NonnullRefPtr<Inode>&& inode) { m_inode = move(inode); }
|
void set_original_inode(Badge<VFS>, NonnullRefPtr<Inode>&& inode) { m_inode = move(inode); }
|
||||||
|
|
||||||
SocketRole socket_role() const { return m_socket_role; }
|
|
||||||
void set_socket_role(SocketRole);
|
|
||||||
|
|
||||||
KResult truncate(off_t);
|
KResult truncate(off_t);
|
||||||
|
|
||||||
off_t offset() const { return m_current_offset; }
|
off_t offset() const { return m_current_offset; }
|
||||||
|
@ -104,7 +101,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class VFS;
|
friend class VFS;
|
||||||
FileDescription(File&, SocketRole = SocketRole::None);
|
explicit FileDescription(File&);
|
||||||
FileDescription(FIFO&, FIFO::Direction);
|
FileDescription(FIFO&, FIFO::Direction);
|
||||||
|
|
||||||
RefPtr<Custody> m_custody;
|
RefPtr<Custody> m_custody;
|
||||||
|
@ -119,6 +116,5 @@ private:
|
||||||
|
|
||||||
bool m_is_blocking { true };
|
bool m_is_blocking { true };
|
||||||
bool m_should_append { false };
|
bool m_should_append { false };
|
||||||
SocketRole m_socket_role { SocketRole::None };
|
|
||||||
FIFO::Direction m_fifo_direction { FIFO::Direction::Neither };
|
FIFO::Direction m_fifo_direction { FIFO::Direction::Neither };
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,6 +108,8 @@ KResult IPv4Socket::connect(FileDescription& description, const sockaddr* addres
|
||||||
return KResult(-EINVAL);
|
return KResult(-EINVAL);
|
||||||
if (address->sa_family != AF_INET)
|
if (address->sa_family != AF_INET)
|
||||||
return KResult(-EINVAL);
|
return KResult(-EINVAL);
|
||||||
|
if (m_role == Role::Connected)
|
||||||
|
return KResult(-EISCONN);
|
||||||
|
|
||||||
auto& ia = *(const sockaddr_in*)address;
|
auto& ia = *(const sockaddr_in*)address;
|
||||||
m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr);
|
m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr);
|
||||||
|
@ -124,9 +126,9 @@ void IPv4Socket::detach(FileDescription&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPv4Socket::can_read(FileDescription& description) const
|
bool IPv4Socket::can_read(FileDescription&) const
|
||||||
{
|
{
|
||||||
if (description.socket_role() == SocketRole::Listener)
|
if (m_role == Role::Listener)
|
||||||
return can_accept();
|
return can_accept();
|
||||||
if (protocol_is_disconnected())
|
if (protocol_is_disconnected())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -99,23 +99,35 @@ KResult LocalSocket::connect(FileDescription& description, const sockaddr* addre
|
||||||
|
|
||||||
m_address = local_address;
|
m_address = local_address;
|
||||||
|
|
||||||
|
ASSERT(m_connect_side_fd == &description);
|
||||||
|
m_connect_side_role = Role::Connecting;
|
||||||
|
|
||||||
auto peer = m_file->inode()->socket();
|
auto peer = m_file->inode()->socket();
|
||||||
auto result = peer->queue_connection_from(*this);
|
auto result = peer->queue_connection_from(*this);
|
||||||
if (result.is_error())
|
if (result.is_error()) {
|
||||||
|
m_connect_side_role = Role::None;
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_connected())
|
if (is_connected()) {
|
||||||
|
m_connect_side_role = Role::Connected;
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
if (current->block<Thread::ConnectBlocker>(description) == Thread::BlockResult::InterruptedBySignal)
|
if (current->block<Thread::ConnectBlocker>(description) == Thread::BlockResult::InterruptedBySignal) {
|
||||||
|
m_connect_side_role = Role::None;
|
||||||
return KResult(-EINTR);
|
return KResult(-EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_LOCAL_SOCKET
|
#ifdef DEBUG_LOCAL_SOCKET
|
||||||
kprintf("%s(%u) LocalSocket{%p} connect(%s) status is %s\n", current->process().name().characters(), current->pid(), this, safe_address, to_string(setup_state()));
|
kprintf("%s(%u) LocalSocket{%p} connect(%s) status is %s\n", current->process().name().characters(), current->pid(), this, safe_address, to_string(setup_state()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!is_connected())
|
if (!is_connected()) {
|
||||||
|
m_connect_side_role = Role::None;
|
||||||
return KResult(-ECONNREFUSED);
|
return KResult(-ECONNREFUSED);
|
||||||
|
}
|
||||||
|
m_connect_side_role = Role::Connected;
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +137,7 @@ KResult LocalSocket::listen(int backlog)
|
||||||
if (type() != SOCK_STREAM)
|
if (type() != SOCK_STREAM)
|
||||||
return KResult(-EOPNOTSUPP);
|
return KResult(-EOPNOTSUPP);
|
||||||
set_backlog(backlog);
|
set_backlog(backlog);
|
||||||
|
m_connect_side_role = m_role = Role::Listener;
|
||||||
kprintf("LocalSocket{%p} listening with backlog=%d\n", this, backlog);
|
kprintf("LocalSocket{%p} listening with backlog=%d\n", this, backlog);
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
@ -132,68 +145,53 @@ KResult LocalSocket::listen(int backlog)
|
||||||
void LocalSocket::attach(FileDescription& description)
|
void LocalSocket::attach(FileDescription& description)
|
||||||
{
|
{
|
||||||
ASSERT(!m_accept_side_fd_open);
|
ASSERT(!m_accept_side_fd_open);
|
||||||
switch (description.socket_role()) {
|
if (m_connect_side_role == Role::None) {
|
||||||
case SocketRole::None:
|
ASSERT(m_connect_side_fd == nullptr);
|
||||||
ASSERT(!m_connect_side_fd_open);
|
m_connect_side_fd = &description;
|
||||||
m_connect_side_fd_open = true;
|
} else {
|
||||||
break;
|
ASSERT(m_connect_side_fd != &description);
|
||||||
case SocketRole::Accepted:
|
|
||||||
m_accept_side_fd_open = true;
|
m_accept_side_fd_open = true;
|
||||||
break;
|
|
||||||
case SocketRole::Connected:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSocket::detach(FileDescription& description)
|
void LocalSocket::detach(FileDescription& description)
|
||||||
{
|
{
|
||||||
switch (description.socket_role()) {
|
if (m_connect_side_fd == &description) {
|
||||||
case SocketRole::None:
|
m_connect_side_fd = nullptr;
|
||||||
ASSERT(!m_accept_side_fd_open);
|
} else {
|
||||||
ASSERT(m_connect_side_fd_open);
|
|
||||||
m_connect_side_fd_open = false;
|
|
||||||
break;
|
|
||||||
case SocketRole::Accepted:
|
|
||||||
ASSERT(m_accept_side_fd_open);
|
ASSERT(m_accept_side_fd_open);
|
||||||
m_accept_side_fd_open = false;
|
m_accept_side_fd_open = false;
|
||||||
break;
|
|
||||||
case SocketRole::Connected:
|
|
||||||
ASSERT(m_connect_side_fd_open);
|
|
||||||
m_connect_side_fd_open = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocalSocket::can_read(FileDescription& description) const
|
bool LocalSocket::can_read(FileDescription& description) const
|
||||||
{
|
{
|
||||||
auto role = description.socket_role();
|
auto role = this->role(description);
|
||||||
if (role == SocketRole::Listener)
|
if (role == Role::Listener)
|
||||||
return can_accept();
|
return can_accept();
|
||||||
if (role == SocketRole::Accepted)
|
if (role == Role::Accepted)
|
||||||
return !has_attached_peer(description) || !m_for_server.is_empty();
|
return !has_attached_peer(description) || !m_for_server.is_empty();
|
||||||
if (role == SocketRole::Connected)
|
if (role == Role::Connected)
|
||||||
return !has_attached_peer(description) || !m_for_client.is_empty();
|
return !has_attached_peer(description) || !m_for_client.is_empty();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocalSocket::has_attached_peer(const FileDescription& description) const
|
bool LocalSocket::has_attached_peer(const FileDescription& description) const
|
||||||
{
|
{
|
||||||
if (description.socket_role() == SocketRole::Accepted)
|
auto role = this->role(description);
|
||||||
return m_connect_side_fd_open;
|
if (role == Role::Accepted)
|
||||||
if (description.socket_role() == SocketRole::Connected)
|
return m_connect_side_fd != nullptr;
|
||||||
|
if (role == Role::Connected)
|
||||||
return m_accept_side_fd_open;
|
return m_accept_side_fd_open;
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocalSocket::can_write(FileDescription& description) const
|
bool LocalSocket::can_write(FileDescription& description) const
|
||||||
{
|
{
|
||||||
if (description.socket_role() == SocketRole::Accepted)
|
auto role = this->role(description);
|
||||||
|
if (role == Role::Accepted)
|
||||||
return !has_attached_peer(description) || m_for_client.bytes_in_write_buffer() < 16384;
|
return !has_attached_peer(description) || m_for_client.bytes_in_write_buffer() < 16384;
|
||||||
if (description.socket_role() == SocketRole::Connected)
|
if (role == Role::Connected)
|
||||||
return !has_attached_peer(description) || m_for_server.bytes_in_write_buffer() < 16384;
|
return !has_attached_peer(description) || m_for_server.bytes_in_write_buffer() < 16384;
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -202,24 +200,25 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size
|
||||||
{
|
{
|
||||||
if (!has_attached_peer(description))
|
if (!has_attached_peer(description))
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
if (description.socket_role() == SocketRole::Accepted)
|
auto role = this->role(description);
|
||||||
|
if (role == Role::Accepted)
|
||||||
return m_for_client.write((const u8*)data, data_size);
|
return m_for_client.write((const u8*)data, data_size);
|
||||||
if (description.socket_role() == SocketRole::Connected)
|
if (role == Role::Connected)
|
||||||
return m_for_server.write((const u8*)data, data_size);
|
return m_for_server.write((const u8*)data, data_size);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
|
ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
|
||||||
{
|
{
|
||||||
auto role = description.socket_role();
|
auto role = this->role(description);
|
||||||
if (role == SocketRole::Accepted) {
|
if (role == Role::Accepted) {
|
||||||
if (!description.is_blocking()) {
|
if (!description.is_blocking()) {
|
||||||
if (m_for_server.is_empty())
|
if (m_for_server.is_empty())
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
return m_for_server.read((u8*)buffer, buffer_size);
|
return m_for_server.read((u8*)buffer, buffer_size);
|
||||||
}
|
}
|
||||||
if (role == SocketRole::Connected) {
|
if (role == Role::Connected) {
|
||||||
if (!description.is_blocking()) {
|
if (!description.is_blocking()) {
|
||||||
if (m_for_client.is_empty())
|
if (m_for_client.is_empty())
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
|
@ -28,11 +28,25 @@ private:
|
||||||
virtual bool is_local() const override { return true; }
|
virtual bool is_local() const override { return true; }
|
||||||
bool has_attached_peer(const FileDescription&) const;
|
bool has_attached_peer(const FileDescription&) const;
|
||||||
|
|
||||||
|
// An open socket file on the filesystem.
|
||||||
RefPtr<FileDescription> m_file;
|
RefPtr<FileDescription> m_file;
|
||||||
|
|
||||||
|
// A single LocalSocket is shared between two file descriptions
|
||||||
|
// on the connect side and the accept side; so we need to store
|
||||||
|
// an additional role for the connect side and differentiate
|
||||||
|
// between them.
|
||||||
|
Role m_connect_side_role { Role::None };
|
||||||
|
FileDescription* m_connect_side_fd { nullptr };
|
||||||
|
|
||||||
|
virtual Role role(const FileDescription& description) const override
|
||||||
|
{
|
||||||
|
if (m_connect_side_fd == &description)
|
||||||
|
return m_connect_side_role;
|
||||||
|
return m_role;
|
||||||
|
}
|
||||||
|
|
||||||
bool m_bound { false };
|
bool m_bound { false };
|
||||||
bool m_accept_side_fd_open { false };
|
bool m_accept_side_fd_open { false };
|
||||||
bool m_connect_side_fd_open { false };
|
|
||||||
sockaddr_un m_address;
|
sockaddr_un m_address;
|
||||||
|
|
||||||
DoubleBuffer m_for_client;
|
DoubleBuffer m_for_client;
|
||||||
|
|
|
@ -48,6 +48,7 @@ KResult Socket::listen(int backlog)
|
||||||
if (m_type != SOCK_STREAM)
|
if (m_type != SOCK_STREAM)
|
||||||
return KResult(-EOPNOTSUPP);
|
return KResult(-EOPNOTSUPP);
|
||||||
m_backlog = backlog;
|
m_backlog = backlog;
|
||||||
|
m_role = Role::Listener;
|
||||||
kprintf("Socket{%p} listening with backlog=%d\n", this, m_backlog);
|
kprintf("Socket{%p} listening with backlog=%d\n", this, m_backlog);
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +65,7 @@ RefPtr<Socket> Socket::accept()
|
||||||
ASSERT(!client->is_connected());
|
ASSERT(!client->is_connected());
|
||||||
client->set_setup_state(SetupState::Completed);
|
client->set_setup_state(SetupState::Completed);
|
||||||
client->m_connected = true;
|
client->m_connected = true;
|
||||||
|
client->m_role = Role::Accepted;
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,14 +148,14 @@ void Socket::load_send_deadline()
|
||||||
m_send_deadline.tv_usec %= 1000000;
|
m_send_deadline.tv_usec %= 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* to_string(SocketRole role)
|
static const char* to_string(Socket::Role role)
|
||||||
{
|
{
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case SocketRole::Listener:
|
case Socket::Role::Listener:
|
||||||
return "Listener";
|
return "Listener";
|
||||||
case SocketRole::Accepted:
|
case Socket::Role::Accepted:
|
||||||
return "Accepted";
|
return "Accepted";
|
||||||
case SocketRole::Connected:
|
case Socket::Role::Connected:
|
||||||
return "Connected";
|
return "Connected";
|
||||||
default:
|
default:
|
||||||
return "None";
|
return "None";
|
||||||
|
@ -162,7 +164,7 @@ static const char* to_string(SocketRole role)
|
||||||
|
|
||||||
String Socket::absolute_path(const FileDescription& description) const
|
String Socket::absolute_path(const FileDescription& description) const
|
||||||
{
|
{
|
||||||
return String::format("socket:%x (role: %s)", this, ::to_string(description.socket_role()));
|
return String::format("socket:%x (role: %s)", this, ::to_string(role(description)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Socket::read(FileDescription& description, u8* buffer, ssize_t size)
|
ssize_t Socket::read(FileDescription& description, u8* buffer, ssize_t size)
|
||||||
|
|
|
@ -9,13 +9,6 @@
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
#include <Kernel/UnixTypes.h>
|
#include <Kernel/UnixTypes.h>
|
||||||
|
|
||||||
enum class SocketRole : u8 {
|
|
||||||
None,
|
|
||||||
Listener,
|
|
||||||
Accepted,
|
|
||||||
Connected,
|
|
||||||
Connecting
|
|
||||||
};
|
|
||||||
enum class ShouldBlock {
|
enum class ShouldBlock {
|
||||||
No = 0,
|
No = 0,
|
||||||
Yes = 1
|
Yes = 1
|
||||||
|
@ -38,6 +31,14 @@ public:
|
||||||
Completed, // the setup process is complete, but not necessarily successful
|
Completed, // the setup process is complete, but not necessarily successful
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Role : u8 {
|
||||||
|
None,
|
||||||
|
Listener,
|
||||||
|
Accepted,
|
||||||
|
Connected,
|
||||||
|
Connecting
|
||||||
|
};
|
||||||
|
|
||||||
static const char* to_string(SetupState setup_state)
|
static const char* to_string(SetupState setup_state)
|
||||||
{
|
{
|
||||||
switch (setup_state) {
|
switch (setup_state) {
|
||||||
|
@ -55,6 +56,8 @@ public:
|
||||||
SetupState setup_state() const { return m_setup_state; }
|
SetupState setup_state() const { return m_setup_state; }
|
||||||
void set_setup_state(SetupState setup_state);
|
void set_setup_state(SetupState setup_state);
|
||||||
|
|
||||||
|
virtual Role role(const FileDescription&) const { return m_role; }
|
||||||
|
|
||||||
bool is_connected() const { return m_connected; }
|
bool is_connected() const { return m_connected; }
|
||||||
void set_connected(bool connected) { m_connected = connected; }
|
void set_connected(bool connected) { m_connected = connected; }
|
||||||
|
|
||||||
|
@ -101,6 +104,8 @@ protected:
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "Socket"; }
|
virtual const char* class_name() const override { return "Socket"; }
|
||||||
|
|
||||||
|
Role m_role { Role::None };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_socket() const final { return true; }
|
virtual bool is_socket() const final { return true; }
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ void TCPSocket::set_state(State new_state)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_state = new_state;
|
m_state = new_state;
|
||||||
|
|
||||||
|
if (new_state == State::Established && m_direction == Direction::Outgoing)
|
||||||
|
m_role = Role::Connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>& TCPSocket::sockets_by_tuple()
|
Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>& TCPSocket::sockets_by_tuple()
|
||||||
|
@ -268,14 +271,17 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh
|
||||||
set_setup_state(SetupState::InProgress);
|
set_setup_state(SetupState::InProgress);
|
||||||
send_tcp_packet(TCPFlags::SYN);
|
send_tcp_packet(TCPFlags::SYN);
|
||||||
m_state = State::SynSent;
|
m_state = State::SynSent;
|
||||||
|
m_role = Role::Connecting;
|
||||||
m_direction = Direction::Outgoing;
|
m_direction = Direction::Outgoing;
|
||||||
|
|
||||||
if (should_block == ShouldBlock::Yes) {
|
if (should_block == ShouldBlock::Yes) {
|
||||||
if (current->block<Thread::ConnectBlocker>(description) == Thread::BlockResult::InterruptedBySignal)
|
if (current->block<Thread::ConnectBlocker>(description) == Thread::BlockResult::InterruptedBySignal)
|
||||||
return KResult(-EINTR);
|
return KResult(-EINTR);
|
||||||
ASSERT(setup_state() == SetupState::Completed);
|
ASSERT(setup_state() == SetupState::Completed);
|
||||||
if (has_error())
|
if (has_error()) {
|
||||||
|
m_role = Role::None;
|
||||||
return KResult(-ECONNREFUSED);
|
return KResult(-ECONNREFUSED);
|
||||||
|
}
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,12 @@ int UDPSocket::protocol_send(const void* data, int data_length)
|
||||||
return data_length;
|
return data_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResult UDPSocket::protocol_connect(FileDescription&, ShouldBlock)
|
||||||
|
{
|
||||||
|
m_role = Role::Connected;
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
int UDPSocket::protocol_allocate_local_port()
|
int UDPSocket::protocol_allocate_local_port()
|
||||||
{
|
{
|
||||||
static const u16 first_ephemeral_port = 32768;
|
static const u16 first_ephemeral_port = 32768;
|
||||||
|
|
|
@ -17,7 +17,7 @@ private:
|
||||||
|
|
||||||
virtual int protocol_receive(const KBuffer&, void* buffer, size_t buffer_size, int flags) override;
|
virtual int protocol_receive(const KBuffer&, void* buffer, size_t buffer_size, int flags) override;
|
||||||
virtual int protocol_send(const void*, int) override;
|
virtual int protocol_send(const void*, int) override;
|
||||||
virtual KResult protocol_connect(FileDescription&, ShouldBlock) override { return KSuccess; }
|
virtual KResult protocol_connect(FileDescription&, ShouldBlock) override;
|
||||||
virtual int protocol_allocate_local_port() override;
|
virtual int protocol_allocate_local_port() override;
|
||||||
virtual KResult protocol_bind() override;
|
virtual KResult protocol_bind() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2134,11 +2134,7 @@ int Process::sys$listen(int sockfd, int backlog)
|
||||||
if (!description->is_socket())
|
if (!description->is_socket())
|
||||||
return -ENOTSOCK;
|
return -ENOTSOCK;
|
||||||
auto& socket = *description->socket();
|
auto& socket = *description->socket();
|
||||||
auto result = socket.listen(backlog);
|
return socket.listen(backlog);
|
||||||
if (result.is_error())
|
|
||||||
return result;
|
|
||||||
description->set_socket_role(SocketRole::Listener);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* address_size)
|
int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* address_size)
|
||||||
|
@ -2168,7 +2164,7 @@ int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* a
|
||||||
ASSERT(accepted_socket);
|
ASSERT(accepted_socket);
|
||||||
bool success = accepted_socket->get_peer_address(address, address_size);
|
bool success = accepted_socket->get_peer_address(address, address_size);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
auto accepted_socket_description = FileDescription::create(*accepted_socket, SocketRole::Accepted);
|
auto accepted_socket_description = FileDescription::create(*accepted_socket);
|
||||||
// NOTE: The accepted socket inherits fd flags from the accepting socket.
|
// NOTE: The accepted socket inherits fd flags from the accepting socket.
|
||||||
// I'm not sure if this matches other systems but it makes sense to me.
|
// I'm not sure if this matches other systems but it makes sense to me.
|
||||||
accepted_socket_description->set_blocking(accepting_socket_description->is_blocking());
|
accepted_socket_description->set_blocking(accepting_socket_description->is_blocking());
|
||||||
|
@ -2188,17 +2184,9 @@ int Process::sys$connect(int sockfd, const sockaddr* address, socklen_t address_
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
if (!description->is_socket())
|
if (!description->is_socket())
|
||||||
return -ENOTSOCK;
|
return -ENOTSOCK;
|
||||||
if (description->socket_role() == SocketRole::Connected)
|
|
||||||
return -EISCONN;
|
|
||||||
auto& socket = *description->socket();
|
auto& socket = *description->socket();
|
||||||
description->set_socket_role(SocketRole::Connecting);
|
return socket.connect(*description, address, address_size, description->is_blocking() ? ShouldBlock::Yes : ShouldBlock::No);
|
||||||
auto result = socket.connect(*description, address, address_size, description->is_blocking() ? ShouldBlock::Yes : ShouldBlock::No);
|
|
||||||
if (result.is_error()) {
|
|
||||||
description->set_socket_role(SocketRole::None);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
description->set_socket_role(SocketRole::Connected);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Process::sys$sendto(const Syscall::SC_sendto_params* params)
|
ssize_t Process::sys$sendto(const Syscall::SC_sendto_params* params)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue