Corium 1.1.0
High-Performance Zero-Heap C++20 MPSC Application Runtime
Loading...
Searching...
No Matches
DomainSocket.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <cstddef>
10#include <cstring>
11#include <string>
12#include <utility>
13
14#if defined(_WIN32) || defined(_WIN64)
15#ifndef NOMINMAX
16#define NOMINMAX
17#endif
18#ifndef WIN32_LEAN_AND_MEAN
19#define WIN32_LEAN_AND_MEAN
20#endif
21#include <windows.h>
22#include <winsock2.h>
23#include <afunix.h>
24#define CORIUM_HAS_POSIX_SOCKETS 0
25#elif __has_include(<sys/socket.h>) && __has_include(<sys/un.h>) && __has_include(<unistd.h>) && __has_include(<fcntl.h>)
26#include <fcntl.h>
27#include <sys/socket.h>
28#include <sys/un.h>
29#include <unistd.h>
30#define CORIUM_HAS_POSIX_SOCKETS 1
31#else
32#define CORIUM_HAS_POSIX_SOCKETS 0
33#endif
34
35namespace corium::ipc {
36
40public:
41 DomainSocket() noexcept = default;
42
44 {
45 close();
46 }
47
48 DomainSocket(const DomainSocket&) = delete;
50
51 DomainSocket(DomainSocket&& other) noexcept
52 : _fd(other._fd),
53 _boundPath(std::move(other._boundPath)),
54 _isBound(other._isBound)
55 {
56 other._fd = -1;
57 other._isBound = false;
58 }
59
61 {
62 if (this != &other) {
63 close();
64 _fd = other._fd;
65 _boundPath = std::move(other._boundPath);
66 _isBound = other._isBound;
67 other._fd = -1;
68 other._isBound = false;
69 }
70 return *this;
71 }
72
76 bool bind(const std::string& socketPath) noexcept
77 {
78 close();
79
80#if CORIUM_HAS_POSIX_SOCKETS
81 ::unlink(socketPath.c_str());
82
83 _fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
84 if (_fd < 0) {
85 return false;
86 }
87
88 struct sockaddr_un addr{};
89 addr.sun_family = AF_UNIX;
90 std::strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
91
92 if (::bind(_fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) != 0) {
93 ::close(_fd);
94 _fd = -1;
95 return false;
96 }
97
98 _boundPath = socketPath;
99 _isBound = true;
100 return true;
101#else
102 (void)socketPath;
103 return false;
104#endif
105 }
106
111 bool connect(const std::string& socketPath, const std::string& clientPath = "") noexcept
112 {
113 close();
114
115#if CORIUM_HAS_POSIX_SOCKETS
116 _fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
117 if (_fd < 0) {
118 return false;
119 }
120
121 if (!clientPath.empty()) {
122 ::unlink(clientPath.c_str());
123 struct sockaddr_un localAddr{};
124 localAddr.sun_family = AF_UNIX;
125 std::strncpy(localAddr.sun_path, clientPath.c_str(), sizeof(localAddr.sun_path) - 1);
126
127 if (::bind(_fd, reinterpret_cast<struct sockaddr*>(&localAddr), sizeof(localAddr)) != 0) {
128 ::close(_fd);
129 _fd = -1;
130 return false;
131 }
132 _boundPath = clientPath;
133 _isBound = true;
134 }
135
136 struct sockaddr_un remoteAddr{};
137 remoteAddr.sun_family = AF_UNIX;
138 std::strncpy(remoteAddr.sun_path, socketPath.c_str(), sizeof(remoteAddr.sun_path) - 1);
139
140 if (::connect(_fd, reinterpret_cast<struct sockaddr*>(&remoteAddr), sizeof(remoteAddr)) != 0) {
141 close();
142 return false;
143 }
144 return true;
145#else
146 (void)socketPath;
147 (void)clientPath;
148 return false;
149#endif
150 }
151
153 void setNonBlocking(bool nonBlocking) noexcept
154 {
155#if CORIUM_HAS_POSIX_SOCKETS
156 if (_fd >= 0) {
157 int flags = ::fcntl(_fd, F_GETFL, 0);
158 if (flags >= 0) {
159 if (nonBlocking) {
160 flags |= O_NONBLOCK;
161 } else {
162 flags &= ~O_NONBLOCK;
163 }
164 ::fcntl(_fd, F_SETFL, flags);
165 }
166 }
167#else
168 (void)nonBlocking;
169#endif
170 }
171
176 int send(const void* buffer, std::size_t length) noexcept
177 {
178#if CORIUM_HAS_POSIX_SOCKETS
179 if (_fd < 0) return -1;
180 return static_cast<int>(::send(_fd, buffer, length, 0));
181#else
182 (void)buffer;
183 (void)length;
184 return -1;
185#endif
186 }
187
192 int receive(void* buffer, std::size_t maxLength) noexcept
193 {
194#if CORIUM_HAS_POSIX_SOCKETS
195 if (_fd < 0) return -1;
196 return static_cast<int>(::recv(_fd, buffer, maxLength, 0));
197#else
198 (void)buffer;
199 (void)maxLength;
200 return -1;
201#endif
202 }
203
205 void close() noexcept
206 {
207#if CORIUM_HAS_POSIX_SOCKETS
208 if (_fd >= 0) {
209 ::close(_fd);
210 _fd = -1;
211 }
212 if (_isBound && !_boundPath.empty()) {
213 ::unlink(_boundPath.c_str());
214 _isBound = false;
215 _boundPath.clear();
216 }
217#endif
218 }
219
221 [[nodiscard]] bool isOpen() const noexcept { return _fd >= 0; }
222
224 [[nodiscard]] int nativeHandle() const noexcept { return _fd; }
225
226private:
227 int _fd{-1};
228 std::string _boundPath;
229 bool _isBound{false};
230};
231
232} // namespace corium::ipc
Low-level RAII abstraction for UNIX Domain Datagram Sockets (AF_UNIX / SOCK_DGRAM)....
Definition DomainSocket.hpp:39
void setNonBlocking(bool nonBlocking) noexcept
Set socket non-blocking mode.
Definition DomainSocket.hpp:153
bool connect(const std::string &socketPath, const std::string &clientPath="") noexcept
Connect to a destination socket as a client.
Definition DomainSocket.hpp:111
DomainSocket() noexcept=default
void close() noexcept
Close socket and unlink bound file if server.
Definition DomainSocket.hpp:205
DomainSocket(DomainSocket &&other) noexcept
Definition DomainSocket.hpp:51
int nativeHandle() const noexcept
Access underlying OS file descriptor.
Definition DomainSocket.hpp:224
DomainSocket & operator=(DomainSocket &&other) noexcept
Definition DomainSocket.hpp:60
bool bind(const std::string &socketPath) noexcept
Bind socket to a filesystem path as a receiving server.
Definition DomainSocket.hpp:76
int send(const void *buffer, std::size_t length) noexcept
Send datagram packet over the connected socket.
Definition DomainSocket.hpp:176
bool isOpen() const noexcept
Check if socket descriptor is open.
Definition DomainSocket.hpp:221
int receive(void *buffer, std::size_t maxLength) noexcept
Receive datagram packet from socket.
Definition DomainSocket.hpp:192
DomainSocket(const DomainSocket &)=delete
DomainSocket & operator=(const DomainSocket &)=delete
Definition DomainSocket.hpp:35