Luna/libos/src/LocalServer.cpp

88 lines
2.2 KiB
C++
Raw Normal View History

#include <errno.h>
#include <fcntl.h>
#include <os/FileSystem.h>
#include <os/LocalServer.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
namespace os
{
Result<SharedPtr<LocalServer>> LocalServer::create(StringView path, bool blocking)
{
auto server = TRY(make_shared<LocalServer>());
(void)os::FileSystem::remove(path); // We explicitly ignore any error here, either it doesn't exist (which is
// fine), or it cannot be removed, which will make bind() fail later.
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) return err(errno);
struct sockaddr_un un;
un.sun_family = AF_UNIX;
strncpy(un.sun_path, path.chars(), sizeof(un.sun_path));
if (bind(sockfd, (struct sockaddr*)&un, sizeof(un)) < 0)
{
close(sockfd);
return err(errno);
}
if (!blocking) { fcntl(sockfd, F_SETFL, O_NONBLOCK); }
server->m_blocking = blocking;
fcntl(sockfd, F_SETFD, FD_CLOEXEC);
server->m_fd = sockfd;
return server;
}
Result<void> LocalServer::listen(int backlog)
{
if (::listen(m_fd, backlog) < 0) return err(errno);
return {};
}
Result<SharedPtr<LocalServer::Client>> LocalServer::accept()
{
int fd = ::accept(m_fd, nullptr, nullptr);
if (fd < 0) return err(errno);
if (!m_blocking) fcntl(fd, F_SETFL, O_NONBLOCK);
return make_shared<Client>(fd);
}
LocalServer::~LocalServer()
{
close(m_fd);
}
LocalServer::Client::Client(int fd) : m_fd(fd)
{
}
LocalServer::Client::~Client()
{
if (m_fd >= 0) close(m_fd);
}
Result<usize> LocalServer::Client::recv(u8* buf, usize length)
{
ssize_t nread = read(m_fd, buf, length);
if (nread < 0) return err(errno);
return nread;
}
Result<usize> LocalServer::Client::send(const u8* buf, usize length)
{
ssize_t nwrite = write(m_fd, buf, length);
if (nwrite < 0) return err(errno);
return nwrite;
}
void LocalServer::Client::disconnect()
{
close(m_fd);
m_fd = -1;
}
}