1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-25 16:25:08 +00:00

Kernel: More work on sockets. Fleshing out connect().

This commit is contained in:
Andreas Kling 2019-02-14 15:55:19 +01:00
parent b12ab1270a
commit b20a7aca61
7 changed files with 90 additions and 4 deletions

View file

@ -4,6 +4,7 @@
#include <LibC/errno_numbers.h> #include <LibC/errno_numbers.h>
#include "FileSystem.h" #include "FileSystem.h"
#include "MemoryManager.h" #include "MemoryManager.h"
#include <Kernel/LocalSocket.h>
static dword s_lastFileSystemID; static dword s_lastFileSystemID;
static HashMap<dword, FS*>* s_fs_map; static HashMap<dword, FS*>* s_fs_map;
@ -152,3 +153,17 @@ void Inode::set_vmo(VMObject& vmo)
{ {
m_vmo = vmo.make_weak_ptr(); 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;
}

View file

@ -20,6 +20,7 @@ static const dword mepoch = 476763780;
class Inode; class Inode;
class FileDescriptor; class FileDescriptor;
class LocalSocket;
class VMObject; class VMObject;
class FS : public Retainable<FS> { class FS : public Retainable<FS> {
@ -92,6 +93,11 @@ public:
virtual size_t directory_entry_count() const = 0; virtual size_t directory_entry_count() const = 0;
virtual bool chmod(mode_t, int& error) = 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; } bool is_metadata_dirty() const { return m_metadata_dirty; }
virtual int set_atime(time_t); virtual int set_atime(time_t);
@ -120,6 +126,7 @@ private:
FS& m_fs; FS& m_fs;
unsigned m_index { 0 }; unsigned m_index { 0 };
WeakPtr<VMObject> m_vmo; WeakPtr<VMObject> m_vmo;
RetainPtr<LocalSocket> m_socket;
bool m_metadata_dirty { false }; bool m_metadata_dirty { false };
}; };

View file

@ -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) bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& error)
{ {
ASSERT(!m_connected);
if (address_size != sizeof(sockaddr_un)) { if (address_size != sizeof(sockaddr_un)) {
error = -EINVAL; error = -EINVAL;
return false; return false;
} }
if (address->sa_family != AF_LOCAL) { if (address->sa_family != AF_LOCAL) {
error = -EINVAL; error = -EINVAL;
return false; return false;
@ -51,10 +51,46 @@ bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& err
if (!m_file) { if (!m_file) {
if (error == -EEXIST) if (error == -EEXIST)
error = -EADDRINUSE; error = -EADDRINUSE;
return error; return false;
} }
ASSERT(m_file->inode());
m_file->inode()->bind_socket(*this);
m_address = local_address; m_address = local_address;
m_bound = true; m_bound = true;
return 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;
}

View file

@ -11,14 +11,18 @@ public:
virtual ~LocalSocket() override; virtual ~LocalSocket() override;
virtual bool bind(const sockaddr*, socklen_t, int& error) 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; virtual bool get_address(sockaddr*, socklen_t*) override;
private: private:
explicit LocalSocket(int type); explicit LocalSocket(int type);
virtual bool is_local() const override { return true; }
RetainPtr<FileDescriptor> m_file; RetainPtr<FileDescriptor> m_file;
RetainPtr<LocalSocket> m_peer;
bool m_bound { false }; bool m_bound { false };
bool m_connected { false };
sockaddr_un m_address; sockaddr_un m_address;
DoubleBuffer m_for_client; DoubleBuffer m_for_client;

View file

@ -2329,7 +2329,28 @@ int Process::sys$accept(int sockfd, sockaddr* address, socklen_t* address_size)
return fd; 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;
} }

View file

@ -23,7 +23,9 @@ public:
bool listen(int backlog, int& error); bool listen(int backlog, int& error);
virtual bool bind(const sockaddr*, socklen_t, int& error) = 0; 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 get_address(sockaddr*, socklen_t*) = 0;
virtual bool is_local() const { return false; }
protected: protected:
Socket(int domain, int type, int protocol); Socket(int domain, int type, int protocol);

View file

@ -46,6 +46,7 @@
__ERROR(EADDRINUSE, "Address in use") \ __ERROR(EADDRINUSE, "Address in use") \
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \ __ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
__ERROR(ENOTEMPTY, "Directory not empty") \ __ERROR(ENOTEMPTY, "Directory not empty") \
__ERROR(ECONNREFUSED, "Connection refused") \
enum __errno_values { enum __errno_values {