1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
//
// Created by cheesekun on 2/28/22.
//
#include <filesystem>
#include <stdexcept>
#include <cassert>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "UnixSocket.hpp"
ssize_t UnixSocketBase::read(void *buffer, size_t size) {
return ::read(descriptor(), buffer, size);
}
ssize_t UnixSocketBase::write(const void *buffer, size_t size) {
return ::write(descriptor(), buffer, size);
}
void UnixSocketBase::close() {
::close(descriptor());
}
UnixSocketConnection::UnixSocketConnection(FD descriptor, sockaddr_un clientAddress) :
_descriptor(descriptor),
_clientAddress(clientAddress)
{
}
FD UnixSocketConnection::descriptor() {
return _descriptor;
}
UnixSocket::UnixSocket(const std::string path):
_path(path),
_descriptor(createSocket())
{
}
void UnixSocket::bind() {
if (std::filesystem::exists(_path)) {
if (!std::filesystem::is_socket(_path)) {
// TODO: file exists, but not socket
throw std::runtime_error("");
}
std::filesystem::remove(_path);
}
sockaddr_un address = {};
address.sun_family = AF_UNIX;
std::strncpy(address.sun_path, _path.c_str(), _path.size());
int retval = ::bind(_descriptor, (sockaddr *) &address, sizeof(address));
if (retval == -1) {
throw SystemCallException(errno, "bind");
}
}
void UnixSocket::listen() {
int retval = ::listen(_descriptor, 0);
if (retval == -1) {
throw SystemCallException(errno, "listen");
}
}
UnixSocketConnection UnixSocket::accept() {
socklen_t addressLength = 0;
sockaddr_un clientAddress = {};
FD client = ::accept(_descriptor, (sockaddr *) &clientAddress, &addressLength);
if (client == -1) {
throw SystemCallException(errno, "accept");
}
// assert(addressLength == sizeof(clientAddress));
return UnixSocketConnection(client, clientAddress);
}
void UnixSocket::connect() {
sockaddr_un address = {};
address.sun_family = AF_UNIX;
std::strncpy(address.sun_path, _path.c_str(), _path.size());
address.sun_len = _path.size();
int retval = ::connect(_descriptor, (sockaddr *) &address, sizeof(address));
if (retval < 0) {
throw SystemCallException(errno, "connect");
}
}
FD UnixSocket::descriptor() {
return _descriptor;
}
FD UnixSocket::createSocket() {
FD descriptor = socket(AF_UNIX, SOCK_STREAM, 0);
if (descriptor < 0) {
throw SystemCallException(errno, "socket");
}
// size_t recvBufferSize = 256000;
// setsockopt(descriptor, SOL_SOCKET, SO_RCVBUF, &recvBufferSize, sizeof(recvBufferSize));
// size_t sendBufferSize = 256000;
// setsockopt(descriptor, SOL_SOCKET, SO_SNDBUF, &sendBufferSize, sizeof(sendBufferSize));
return descriptor;
}
|