Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Socket.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Common/CompilerMacrosExport.h"
5#include "../Common/PlatformMacrosType.h"
6#ifndef SC_EXPORT_LIBRARY_SOCKET
7#define SC_EXPORT_LIBRARY_SOCKET 0
8#endif
9#define SC_SOCKET_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_SOCKET)
10
11#include "../Common/AlignedStorage.h"
12#include "../Common/Assert.h"
13#include "../Common/Result.h"
14#include "../Common/StringSpan.h"
15#include "../Common/UniqueHandle.h"
16
17namespace SC
18{
19SC_DECLARE_ASSERT_PROVIDER(SocketAssert, SC_SOCKET_EXPORT);
20
21#define SC_SOCKET_ASSERT_RELEASE(e) SC_ASSERT_PROVIDER_RELEASE(SC::SocketAssert, e)
22#define SC_SOCKET_ASSERT_DEBUG(e) SC_ASSERT_PROVIDER_DEBUG(SC::SocketAssert, e)
23#define SC_SOCKET_TRUST_RESULT(expression) SC_SOCKET_ASSERT_RELEASE(expression)
24
27
28namespace detail
29{
30
32#if SC_PLATFORM_WINDOWS
33
34struct SC_SOCKET_EXPORT SocketDescriptorDefinition
35{
36 using Handle = size_t; // SOCKET
37 static Result releaseHandle(Handle& handle);
38
39 static constexpr Handle Invalid = ~static_cast<Handle>(0); // INVALID_SOCKET
40};
41
42#else
43
44struct SC_SOCKET_EXPORT SocketDescriptorDefinition
45{
46 using Handle = int; // fd
47 static Result releaseHandle(Handle& handle);
48
49 static constexpr Handle Invalid = -1; // invalid fd
50};
51
52#endif
53} // namespace detail
54
56struct SC_SOCKET_EXPORT SocketFlags
57{
60 {
62 Blocking
63 };
64
67 {
69 Inheritable
70 };
71
74 {
77 AddressFamilyUnix
78 };
79
82 {
84 SocketDgram
85 };
86
94
97 {
98 ShutdownBoth
99 };
100
101 private:
102 friend struct SocketDescriptor;
103 friend struct SocketAddress;
104 friend struct SocketIPAddressInternal;
105 [[nodiscard]] static AddressFamily AddressFamilyFromInt(int value);
106 [[nodiscard]] static unsigned char toNative(AddressFamily family);
107
108 [[nodiscard]] static int toNative(SocketType family);
109 [[nodiscard]] static int toNative(ProtocolType family);
110};
111
116struct SC_SOCKET_EXPORT SocketIPAddress
117{
119 static constexpr int MAX_ASCII_STRING_LENGTH = 46;
120
122 using AsciiBuffer = char[MAX_ASCII_STRING_LENGTH];
123
126 SocketIPAddress(SocketFlags::AddressFamily addressFamily = SocketFlags::AddressFamilyIPV4);
127
131
134 [[nodiscard]] uint16_t getPort() const;
135
140 Result fromAddressPort(StringSpan interfaceAddress, uint16_t port);
141
143 [[nodiscard]] uint32_t sizeOfHandle() const;
144
146 [[nodiscard]] bool isValid() const;
147
152 [[nodiscard]] bool toString(Span<char> inputSpan, StringSpan& outputSpan) const;
153
155 AlignedStorage<28> handle = {};
156
157 private:
158 friend struct SocketServer;
159 friend struct SocketClient;
160
161 struct Internal;
162};
163
167struct SC_SOCKET_EXPORT SocketAddress
168{
169 enum class UnixNamespace
170 {
171 Unnamed,
172 Pathname,
173 Abstract
174 };
175
176 SocketAddress() = default;
177 SocketAddress(const SocketIPAddress& ipAddress);
178
180 Result fromUnixPath(StringSpan path);
181
184 Result fromUnixAbstractName(Span<const char> name);
185
186 [[nodiscard]] SocketFlags::AddressFamily getAddressFamily() const;
187 [[nodiscard]] uint32_t sizeOfHandle() const;
188 [[nodiscard]] bool isValid() const;
189
191 Result getIPAddress(SocketIPAddress& output) const;
192
194 Result getUnixName(Span<const char>& output, UnixNamespace& unixNamespace) const;
195
197 AlignedStorage<128> handle = {};
198 uint32_t nativeSize = 0;
199};
200
206struct SC_SOCKET_EXPORT SocketDescriptor : public UniqueHandle<detail::SocketDescriptorDefinition>
207{
215 Result create(SocketFlags::AddressFamily addressFamily,
216 SocketFlags::SocketType socketType = SocketFlags::SocketStream,
217 SocketFlags::ProtocolType protocol = SocketFlags::ProtocolTcp,
218 SocketFlags::BlockingType blocking = SocketFlags::Blocking,
219 SocketFlags::InheritableType inheritable = SocketFlags::NonInheritable);
220
224 Result isInheritable(bool& value) const;
225
229 Result setInheritable(bool value);
230
234 Result setBlocking(bool value);
235
239 Result getAddressFamily(SocketFlags::AddressFamily& addressFamily) const;
240
245
249 Result setTcpNoDelay(bool tcpNoDelay);
250
254 Result setBroadcast(bool enableBroadcast);
255
260 Result joinMulticastGroup(const SocketIPAddress& multicastAddress, const SocketIPAddress& interfaceAddress);
261
266 Result leaveMulticastGroup(const SocketIPAddress& multicastAddress, const SocketIPAddress& interfaceAddress);
267
272 Result setMulticastLoopback(SocketFlags::AddressFamily addressFamily, bool enableLoopback);
273
278 Result setMulticastHops(SocketFlags::AddressFamily addressFamily, int hops);
279
283 Result setMulticastOutboundInterface(const SocketIPAddress& interfaceAddress);
284
290 Result sendTo(Span<const char> data, const SocketAddress& destination);
291
293 Result sendTo(Span<const char> data, const SocketIPAddress& destination);
294
303 Result receiveFrom(Span<char> buffer, Span<char>& receivedData, SocketAddress& sourceAddress);
304
306 Result receiveFrom(Span<char> buffer, Span<char>& receivedData, SocketIPAddress& sourceAddress);
307};
308
313struct SC_SOCKET_EXPORT SocketServer
314{
315 enum class BindReuseAddress : uint8_t
316 {
317 Disabled,
318 Enabled,
319 };
320
321 enum class BindStatus : uint8_t
322 {
323 None,
324 AddressInUse,
325 };
326
329 SocketServer(SocketDescriptor& socket) : socket(socket) {}
330
333 Result close();
334
340 Result bind(const SocketAddress& nativeAddress, BindReuseAddress reuseAddress = BindReuseAddress::Enabled,
341 BindStatus* outStatus = nullptr);
342
344 Result bind(SocketIPAddress nativeAddress, BindReuseAddress reuseAddress = BindReuseAddress::Enabled,
345 BindStatus* outStatus = nullptr);
346
351 Result listen(uint32_t numberOfWaitingConnections);
352
357 Result accept(SocketFlags::AddressFamily addressFamily, SocketDescriptor& newClient);
358
360 Result accept(SocketDescriptor& newClient, SocketAddress* peerAddress = nullptr);
361
362 private:
363 SocketDescriptor& socket;
364};
365
376struct SC_SOCKET_EXPORT SocketClient
377{
380 SocketClient(const SocketDescriptor& socket) : socket(socket) {}
381
387 Result connect(StringSpan address, uint16_t port);
388
392 Result connect(SocketIPAddress ipAddress);
393
395 Result connect(const SocketAddress& address);
396
400 Result write(Span<const char> data);
401
406 Result read(Span<char> data, Span<char>& readData);
407
413 Result readWithTimeout(Span<char> data, Span<char>& readData, int64_t timeout);
414
415 private:
416 const SocketDescriptor& socket;
417};
418
423struct SC_SOCKET_EXPORT SocketDNS
424{
432 [[nodiscard]] static Result resolveDNS(StringSpan host, Span<char>& ipAddress);
433};
434
436struct SC_SOCKET_EXPORT SocketNetworking
437{
439 static void initNetworking();
440
442 static void shutdownNetworking();
443
446 [[nodiscard]] static bool isNetworkingInited();
447
448 private:
449 struct Internal;
450};
451
453} // namespace SC
Family-neutral native socket address.
Definition Socket.h:168
Result getIPAddress(SocketIPAddress &output) const
Extracts an IP address when this address contains IPv4 or IPv6.
Result fromUnixAbstractName(Span< const char > name)
Builds a Linux abstract-namespace Unix-domain address.
Result fromUnixPath(StringSpan path)
Builds a filesystem-named Unix-domain address.
Result getUnixName(Span< const char > &output, UnixNamespace &unixNamespace) const
Returns a view into the inline Unix-domain name storage.
Use a SocketDescriptor as a client (example a TCP or UDP socket client).
Definition Socket.h:377
Result read(Span< char > data, Span< char > &readData)
Read bytes from this socket blocking until they're actually received.
SocketClient(const SocketDescriptor &socket)
Constructs this SocketClient from a SocketDescriptor (already created with SocketDescriptor::create)
Definition Socket.h:380
Result connect(StringSpan address, uint16_t port)
Connect to a given address and port combination.
Result connect(SocketIPAddress ipAddress)
Connect to a given address and port combination.
Result readWithTimeout(Span< char > data, Span< char > &readData, int64_t timeout)
Read bytes from this socket blocking until they're actually received or timeout occurs.
Result write(Span< const char > data)
Writes bytes to this socket.
Result connect(const SocketAddress &address)
Connect to a family-neutral socket address.
Synchronous DNS Resolution.
Definition Socket.h:424
static Result resolveDNS(StringSpan host, Span< char > &ipAddress)
Resolve an host string to an ip address (blocking until DNS response arrives)
Low-level OS socket handle.
Definition Socket.h:207
Result setMulticastHops(SocketFlags::AddressFamily addressFamily, int hops)
Specifies the default TTL or hop limit for outgoing multicast datagrams.
Result receiveFrom(Span< char > buffer, Span< char > &receivedData, SocketIPAddress &sourceAddress)
IP-address compatibility overload for receiveFrom.
Result shutdown(SocketFlags::ShutdownType shutdownType)
Shuts down the socket for reading, writing, or both.
Result setTcpNoDelay(bool tcpNoDelay)
Disables Nagle's algorithm for low-latency communication.
Result setBroadcast(bool enableBroadcast)
Enables or disables broadcast on this socket (for UDP)
Result setMulticastOutboundInterface(const SocketIPAddress &interfaceAddress)
Specifies the default local network interface for outgoing multicast datagrams.
Result isInheritable(bool &value) const
Check if socket is inheritable by child processes.
Result setBlocking(bool value)
Changes the blocking flag for this socket (if IO reads / writes should be blocking or not)
Result leaveMulticastGroup(const SocketIPAddress &multicastAddress, const SocketIPAddress &interfaceAddress)
Leaves a previously joined IPv4 or IPv6 multicast group on a specific interface.
Result setMulticastLoopback(SocketFlags::AddressFamily addressFamily, bool enableLoopback)
Controls whether multicast traffic is sent back to the local host.
Result setInheritable(bool value)
Changes the inheritable flag for this socket.
Result joinMulticastGroup(const SocketIPAddress &multicastAddress, const SocketIPAddress &interfaceAddress)
Joins an IPv4 or IPv6 multicast group on a specific interface.
Result create(SocketFlags::AddressFamily addressFamily, SocketFlags::SocketType socketType=SocketFlags::SocketStream, SocketFlags::ProtocolType protocol=SocketFlags::ProtocolTcp, SocketFlags::BlockingType blocking=SocketFlags::Blocking, SocketFlags::InheritableType inheritable=SocketFlags::NonInheritable)
Creates a new SocketDescriptor Descriptor of given family, type, protocol.
Result receiveFrom(Span< char > buffer, Span< char > &receivedData, SocketAddress &sourceAddress)
Receives a datagram, reporting its source address.
Result getAddressFamily(SocketFlags::AddressFamily &addressFamily) const
Get the address family of this socket.
Result sendTo(Span< const char > data, const SocketIPAddress &destination)
IP-address compatibility overload for sendTo.
Result sendTo(Span< const char > data, const SocketAddress &destination)
Sends a datagram to the given destination address.
Flags for SocketDescriptor (Blocking / Inheritable, IPVx, SocketType)
Definition Socket.h:57
SocketType
Sets the socket type to datagram or stream.
Definition Socket.h:82
@ SocketStream
Streaming socket (for TCP and Unix-domain streams)
Definition Socket.h:83
AddressFamily
Sets the socket address family.
Definition Socket.h:74
@ AddressFamilyIPV6
IP Address is IPV6.
Definition Socket.h:76
@ AddressFamilyIPV4
IP Address is IPV4.
Definition Socket.h:75
InheritableType
Sets the socket inheritable behaviour for child processes.
Definition Socket.h:67
@ NonInheritable
SocketDescriptor will not be inherited by child processes.
Definition Socket.h:68
ShutdownType
Sets the type of shutdown to perform.
Definition Socket.h:97
BlockingType
Sets the socket as blocking / nonblocking mode.
Definition Socket.h:60
@ NonBlocking
SocketDescriptor is in non-blocking mode.
Definition Socket.h:61
ProtocolType
Sets the socket protocol type.
Definition Socket.h:89
@ ProtocolUdp
The protocol is UDP.
Definition Socket.h:91
@ ProtocolDefault
Use the default protocol for the address family and socket type.
Definition Socket.h:92
@ ProtocolTcp
The protocol is TCP.
Definition Socket.h:90
Native representation of an IP Address.
Definition Socket.h:117
bool toString(Span< char > inputSpan, StringSpan &outputSpan) const
Returns the text representation of this SocketIPAddress.
uint16_t getPort() const
Get port of this ip address.
char[MAX_ASCII_STRING_LENGTH] AsciiBuffer
Buffer for storing the ASCII representation of an IP Address.
Definition Socket.h:122
Result fromAddressPort(StringSpan interfaceAddress, uint16_t port)
Builds this SocketIPAddress parsing given address string and port.
SocketFlags::AddressFamily getAddressFamily() const
Get Address family of this ip address (IPV4 or IPV6)
uint32_t sizeOfHandle() const
Size of the native IP Address representation.
SocketIPAddress(SocketFlags::AddressFamily addressFamily=SocketFlags::AddressFamilyIPV4)
Constructs an ip address from a given family (IPV4 or IPV6)
bool isValid() const
Checks if this is a valid IPV4 or IPV6 address.
Networking globals initialization (Winsock2 WSAStartup)
Definition Socket.h:437
static void initNetworking()
Initializes Winsock2 on Windows (WSAStartup)
static void shutdownNetworking()
Shutdowns Winsock2 on Windows (WSAStartup)
static bool isNetworkingInited()
Check if initNetworking has been previously called.
Use a SocketDescriptor as a Server (example TCP or UDP Socket Server).
Definition Socket.h:314
Result listen(uint32_t numberOfWaitingConnections)
Start listening for incoming connections at a specific address / port combination (after bind)
SocketServer(SocketDescriptor &socket)
Build a SocketServer from a SocketDescriptor (already created with SocketDescriptor::create)
Definition Socket.h:329
Result accept(SocketDescriptor &newClient, SocketAddress *peerAddress=nullptr)
Accepts a new client and optionally reports its peer address.
Result bind(SocketIPAddress nativeAddress, BindReuseAddress reuseAddress=BindReuseAddress::Enabled, BindStatus *outStatus=nullptr)
IP-address compatibility overload for bind.
Result close()
Calls SocketDescriptor::close.
Result bind(const SocketAddress &nativeAddress, BindReuseAddress reuseAddress=BindReuseAddress::Enabled, BindStatus *outStatus=nullptr)
Binds this socket to an address.
Result accept(SocketFlags::AddressFamily addressFamily, SocketDescriptor &newClient)
Accepts a new client, blocking while waiting for it.