mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Kernel: More work on sockets. Fleshing out connect().
This commit is contained in:
parent
b12ab1270a
commit
b20a7aca61
Notes:
sideshowbarker
2024-07-19 15:43:02 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/b20a7aca612
7 changed files with 90 additions and 4 deletions
|
@ -4,6 +4,7 @@
|
|||
#include <LibC/errno_numbers.h>
|
||||
#include "FileSystem.h"
|
||||
#include "MemoryManager.h"
|
||||
#include <Kernel/LocalSocket.h>
|
||||
|
||||
static dword s_lastFileSystemID;
|
||||
static HashMap<dword, FS*>* s_fs_map;
|
||||
|
@ -152,3 +153,17 @@ void Inode::set_vmo(VMObject& vmo)
|
|||
{
|
||||
m_vmo = vmo.make_weak_ptr();
|
||||
}
|
||||
|
||||
bool Inode::bind_socket(LocalSocket& socket)
|
||||
{
|
||||
ASSERT(!m_socket);
|
||||
m_socket = socket;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Inode::unbind_socket()
|
||||
{
|
||||
ASSERT(m_socket);
|
||||
m_socket = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ static const dword mepoch = 476763780;
|
|||
|
||||
class Inode;
|
||||
class FileDescriptor;
|
||||
class LocalSocket;
|
||||
class VMObject;
|
||||
|
||||
class FS : public Retainable<FS> {
|
||||
|
@ -92,6 +93,11 @@ public:
|
|||
virtual size_t directory_entry_count() const = 0;
|
||||
virtual bool chmod(mode_t, int& error) = 0;
|
||||
|
||||
LocalSocket* socket() { return m_socket.ptr(); }
|
||||
const LocalSocket* socket() const { return m_socket.ptr(); }
|
||||
bool bind_socket(LocalSocket&);
|
||||
bool unbind_socket();
|
||||
|
||||
bool is_metadata_dirty() const { return m_metadata_dirty; }
|
||||
|
||||
virtual int set_atime(time_t);
|
||||
|
@ -120,6 +126,7 @@ private:
|
|||
FS& m_fs;
|
||||
unsigned m_index { 0 };
|
||||
WeakPtr<VMObject> m_vmo;
|
||||
RetainPtr<LocalSocket> m_socket;
|
||||
bool m_metadata_dirty { false };
|
||||
};
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ bool LocalSocket::get_address(sockaddr* address, socklen_t* address_size)
|
|||
|
||||
bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& error)
|
||||
{
|
||||
ASSERT(!m_connected);
|
||||
if (address_size != sizeof(sockaddr_un)) {
|
||||
error = -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (address->sa_family != AF_LOCAL) {
|
||||
error = -EINVAL;
|
||||
return false;
|
||||
|
@ -51,10 +51,46 @@ bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& err
|
|||
if (!m_file) {
|
||||
if (error == -EEXIST)
|
||||
error = -EADDRINUSE;
|
||||
return error;
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT(m_file->inode());
|
||||
m_file->inode()->bind_socket(*this);
|
||||
|
||||
m_address = local_address;
|
||||
m_bound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
RetainPtr<Socket> LocalSocket::connect(const sockaddr* address, socklen_t address_size, int& error)
|
||||
{
|
||||
ASSERT(!m_bound);
|
||||
if (address_size != sizeof(sockaddr_un)) {
|
||||
error = -EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
if (address->sa_family != AF_LOCAL) {
|
||||
error = -EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
|
||||
char safe_address[sizeof(local_address.sun_path) + 1];
|
||||
memcpy(safe_address, local_address.sun_path, sizeof(local_address.sun_path));
|
||||
|
||||
kprintf("%s(%u) LocalSocket{%p} connect(%s)\n", current->name().characters(), current->pid(), safe_address);
|
||||
|
||||
m_file = VFS::the().open(safe_address, error, 0, 0, *current->cwd_inode());
|
||||
if (!m_file) {
|
||||
error = -ECONNREFUSED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASSERT(m_file->inode());
|
||||
ASSERT(m_file->inode()->socket());
|
||||
|
||||
m_peer = m_file->inode()->socket();
|
||||
m_address = local_address;
|
||||
m_connected = true;
|
||||
return m_peer;
|
||||
}
|
||||
|
|
|
@ -11,14 +11,18 @@ public:
|
|||
virtual ~LocalSocket() override;
|
||||
|
||||
virtual bool bind(const sockaddr*, socklen_t, int& error) override;
|
||||
virtual RetainPtr<Socket> connect(const sockaddr*, socklen_t, int& error) override;
|
||||
virtual bool get_address(sockaddr*, socklen_t*) override;
|
||||
|
||||
private:
|
||||
explicit LocalSocket(int type);
|
||||
virtual bool is_local() const override { return true; }
|
||||
|
||||
RetainPtr<FileDescriptor> m_file;
|
||||
RetainPtr<LocalSocket> m_peer;
|
||||
|
||||
bool m_bound { false };
|
||||
bool m_connected { false };
|
||||
sockaddr_un m_address;
|
||||
|
||||
DoubleBuffer m_for_client;
|
||||
|
|
|
@ -2329,7 +2329,28 @@ int Process::sys$accept(int sockfd, sockaddr* address, socklen_t* address_size)
|
|||
return fd;
|
||||
}
|
||||
|
||||
int Process::sys$connect(int sockfd, const sockaddr*, socklen_t)
|
||||
int Process::sys$connect(int sockfd, const sockaddr* address, socklen_t address_size)
|
||||
{
|
||||
return -ENOTIMPL;
|
||||
if (!validate_read(address, address_size))
|
||||
return -EFAULT;
|
||||
if (number_of_open_file_descriptors() >= m_max_open_file_descriptors)
|
||||
return -EMFILE;
|
||||
int fd = 0;
|
||||
for (; fd < (int)m_max_open_file_descriptors; ++fd) {
|
||||
if (!m_fds[fd])
|
||||
break;
|
||||
}
|
||||
auto* descriptor = file_descriptor(sockfd);
|
||||
if (!descriptor)
|
||||
return -EBADF;
|
||||
if (!descriptor->is_socket())
|
||||
return -ENOTSOCK;
|
||||
auto& socket = *descriptor->socket();
|
||||
int error;
|
||||
auto server = socket.connect(address, address_size, error);
|
||||
if (!server)
|
||||
return error;
|
||||
auto server_descriptor = FileDescriptor::create(move(server), SocketRole::Connected);
|
||||
m_fds[fd].set(move(server_descriptor));
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ public:
|
|||
bool listen(int backlog, int& error);
|
||||
|
||||
virtual bool bind(const sockaddr*, socklen_t, int& error) = 0;
|
||||
virtual RetainPtr<Socket> connect(const sockaddr*, socklen_t, int& error) = 0;
|
||||
virtual bool get_address(sockaddr*, socklen_t*) = 0;
|
||||
virtual bool is_local() const { return false; }
|
||||
|
||||
protected:
|
||||
Socket(int domain, int type, int protocol);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
__ERROR(EADDRINUSE, "Address in use") \
|
||||
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
|
||||
__ERROR(ENOTEMPTY, "Directory not empty") \
|
||||
__ERROR(ECONNREFUSED, "Connection refused") \
|
||||
|
||||
|
||||
enum __errno_values {
|
||||
|
|
Loading…
Reference in a new issue