Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarNetImpl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarNetImpl.hpp')
-rw-r--r--source/core/StarNetImpl.hpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/source/core/StarNetImpl.hpp b/source/core/StarNetImpl.hpp
new file mode 100644
index 0000000..80d75da
--- /dev/null
+++ b/source/core/StarNetImpl.hpp
@@ -0,0 +1,157 @@
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stdio.h>
+#else
+#ifdef STAR_SYSTEM_FREEBSD
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#endif
+
+#include "StarHostAddress.hpp"
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#endif
+
+namespace Star {
+
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+struct WindowsSocketInitializer {
+ WindowsSocketInitializer() {
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
+ fatalError("WSAStartup failed", false);
+ };
+};
+static WindowsSocketInitializer g_windowsSocketInitializer;
+#endif
+
+inline String netErrorString() {
+#ifdef STAR_SYSTEM_WINDOWS
+ LPVOID lpMsgBuf = NULL;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ WSAGetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR)&lpMsgBuf,
+ 0,
+ NULL);
+
+ String result = String((char*)lpMsgBuf);
+
+ if (lpMsgBuf != NULL)
+ LocalFree(lpMsgBuf);
+
+ return result;
+#else
+ return strf("%s - %s", errno, strerror(errno));
+#endif
+}
+
+inline bool netErrorConnectionReset() {
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+ return WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAENETRESET;
+#else
+ return errno == ECONNRESET || errno == ETIMEDOUT;
+#endif
+}
+
+inline bool netErrorInterrupt() {
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+ return WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+ return errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK;
+#endif
+}
+
+inline void setAddressFromNative(HostAddressWithPort& addressWithPort, NetworkMode mode, struct sockaddr_storage* sockAddr) {
+ switch (mode) {
+ case NetworkMode::IPv4: {
+ struct sockaddr_in* addr4 = (struct sockaddr_in*)sockAddr;
+ addressWithPort = HostAddressWithPort(mode, (uint8_t*)&(addr4->sin_addr.s_addr), ntohs(addr4->sin_port));
+ break;
+ }
+ case NetworkMode::IPv6: {
+ struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sockAddr;
+ addressWithPort = HostAddressWithPort(mode, (uint8_t*)&addr6->sin6_addr.s6_addr, ntohs(addr6->sin6_port));
+ break;
+ }
+ default:
+ throw NetworkException("Invalid network mode for setAddressFromNative");
+ }
+}
+
+inline void setNativeFromAddress(HostAddressWithPort const& addressWithPort, struct sockaddr_storage* sockAddr, socklen_t* sockAddrLen) {
+ switch (addressWithPort.address().mode()) {
+ case NetworkMode::IPv4: {
+ struct sockaddr_in* addr4 = (struct sockaddr_in*)sockAddr;
+ *sockAddrLen = sizeof(*addr4);
+
+ memset(addr4, 0, *sockAddrLen);
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = htons(addressWithPort.port());
+ memcpy(((char*)&addr4->sin_addr.s_addr), addressWithPort.address().bytes(), addressWithPort.address().size());
+
+ break;
+ }
+ case NetworkMode::IPv6: {
+ struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sockAddr;
+ *sockAddrLen = sizeof(*addr6);
+
+ memset(addr6, 0, *sockAddrLen);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = htons(addressWithPort.port());
+ memcpy(((char*)&addr6->sin6_addr.s6_addr), addressWithPort.address().bytes(), addressWithPort.address().size());
+ break;
+ }
+ default:
+ throw NetworkException("Invalid network mode for setNativeFromAddress");
+ }
+}
+
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+inline bool invalidSocketDescriptor(SOCKET socket) {
+ return socket == INVALID_SOCKET;
+}
+#else
+inline bool invalidSocketDescriptor(int socket) {
+ return socket < 0;
+}
+#endif
+
+struct SocketImpl {
+ SocketImpl() {
+ socketDesc = 0;
+ }
+
+ void setSockOpt(int level, int optname, const void* optval, socklen_t len) {
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+ int ret = ::setsockopt(socketDesc, level, optname, (const char*)optval, len);
+#else
+ int ret = ::setsockopt(socketDesc, level, optname, optval, len);
+#endif
+ if (ret < 0)
+ throw NetworkException(strf("setSockOpt failed to set %d, %d: %s", level, optname, netErrorString()));
+ }
+
+#ifdef STAR_SYSTEM_FAMILY_WINDOWS
+ SOCKET socketDesc;
+#else
+ int socketDesc;
+#endif
+};
+
+}