-
Notifications
You must be signed in to change notification settings - Fork 7
/
UnixSocket.cpp
134 lines (103 loc) · 2.93 KB
/
UnixSocket.cpp
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
123
124
125
126
127
128
129
130
131
132
133
134
//
// 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 <fcntl.h>
#include <poll.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);
}
pollfd UnixSocketBase::poll(short events, int timeout) {
pollfd pollFd = {
descriptor(),
events,
0
};
if (::poll(&pollFd, 1, timeout) < 0) {
throw SystemCallException(errno, "poll");
}
return pollFd;
}
int UnixSocketBase::fcntl(int cmd, int arg) {
return ::fcntl(descriptor(), cmd, arg);
}
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");
}
return descriptor;
}