#include #include #include #include #include #include #include namespace os { Result> LocalServer::create(StringView path, bool blocking) { auto server = TRY(make_shared()); (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 LocalServer::listen(int backlog) { if (::listen(m_fd, backlog) < 0) return err(errno); return {}; } Result> 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(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 LocalServer::Client::recv(u8* buf, usize length) { ssize_t nread = read(m_fd, buf, length); if (nread < 0) return err(errno); return nread; } Result 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; } }