From 534f9a3d92700deea20217fbc642acaa65d15b37 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 12 Jan 2024 22:05:19 +0100 Subject: [PATCH] Added missing class. Also found a bit newer socket implementation. --- sfw/core/inet_address.cpp | 297 ++++++++++++++++++++++++++++++++++++++ sfw/core/inet_address.h | 96 ++++++++++++ sfw/core/socket.cpp | 16 +- sfw/core/socket.h | 4 +- 4 files changed, 403 insertions(+), 10 deletions(-) create mode 100755 sfw/core/inet_address.cpp create mode 100755 sfw/core/inet_address.h diff --git a/sfw/core/inet_address.cpp b/sfw/core/inet_address.cpp new file mode 100755 index 0000000..0281e24 --- /dev/null +++ b/sfw/core/inet_address.cpp @@ -0,0 +1,297 @@ +//Based on: + +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) + +#include "inet_address.h" + +#include + +#ifdef _WIN32 + +#ifdef __GNUC__ + #define GCCWIN + // Mingw / gcc on windows + // #define _WIN32_WINNT 0x0501 + #include + #include + + extern "C" { + WINSOCK_API_LINKAGE INT WSAAPI inet_pton( INT Family, PCSTR pszAddrString, PVOID pAddrBuf); + WINSOCK_API_LINKAGE PCSTR WSAAPI inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize); + } +#else + // Windows... + #include + #include + #include +#endif + +struct in6__addruint +{ + union + { + u_char Byte[16]; + u_short Word[8]; + uint32_t __s6_addr32[4]; + } uext; +}; +#else +#include // memset +#include +#include +#endif + +// INADDR_ANY use (type)value casting. +static const in_addr_t kInaddrAny = INADDR_ANY; +static const in_addr_t kInaddrLoopback = INADDR_ANY; + +// /* Structure describing an Internet socket address. */ +// struct sock_addrin { +// sa_family_t sin_family; /* address family: AF_INET */ +// uint16_t sin_port; /* port in network byte order */ +// struct in_addr sin_addr; /* internet address */ +// }; + +// /* Internet address. */ +// typedef uint32_t in_addr_t; +// struct in_addr { +// in_addr_t s_addr; /* address in network byte order */ +// }; + +// struct sockaddr_in6 { +// sa_family_t sin6_family; /* address family: AF_INET6 */ +// uint16_t sin6_port; /* port in network byte order */ +// uint32_t sin6_flowinfo; /* IPv6 flow information */ +// struct in6_addr sin6_addr; /* IPv6 address */ +// uint32_t sin6_scope_id; /* IPv6 scope-id */ +// }; + +/* +#ifdef __linux__ +#if !(__GNUC_PREREQ(4, 6)) +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif +#endif +*/ + +String InetAddress::to_ip_port() const +{ + char buf[64] = ""; + uint16_t port = ntohs(_addr.sin_port); + snprintf(buf, sizeof(buf), ":%u", port); + + return to_ip() + String(buf); +} + +bool InetAddress::is_intranet_ip() const +{ + if (_addr.sin_family == AF_INET) + { + uint32_t ip_addr = ntohl(_addr.sin_addr.s_addr); + if ((ip_addr >= 0x0A000000 && ip_addr <= 0x0AFFFFFF) || + (ip_addr >= 0xAC100000 && ip_addr <= 0xAC1FFFFF) || + (ip_addr >= 0xC0A80000 && ip_addr <= 0xC0A8FFFF) || + ip_addr == 0x7f000001) + + { + return true; + } + } + else + { + auto addrP = ip6_net_endian(); + // Loopback ip + if (*addrP == 0 && *(addrP + 1) == 0 && *(addrP + 2) == 0 && + ntohl(*(addrP + 3)) == 1) + return true; + // Privated ip is prefixed by FEC0::/10 or FE80::/10, need testing + auto i32 = (ntohl(*addrP) & 0xffc00000); + if (i32 == 0xfec00000 || i32 == 0xfe800000) + return true; + if (*addrP == 0 && *(addrP + 1) == 0 && ntohl(*(addrP + 2)) == 0xffff) + { + // the IPv6 version of an IPv4 IP address + uint32_t ip_addr = ntohl(*(addrP + 3)); + if ((ip_addr >= 0x0A000000 && ip_addr <= 0x0AFFFFFF) || + (ip_addr >= 0xAC100000 && ip_addr <= 0xAC1FFFFF) || + (ip_addr >= 0xC0A80000 && ip_addr <= 0xC0A8FFFF) || + ip_addr == 0x7f000001) + + { + return true; + } + } + } + return false; +} + +bool InetAddress::is_loopback_ip() const +{ + if (!is_ip_v6()) + { + uint32_t ip_addr = ntohl(_addr.sin_addr.s_addr); + if (ip_addr == 0x7f000001) + { + return true; + } + } + else + { + auto addrP = ip6_net_endian(); + if (*addrP == 0 && *(addrP + 1) == 0 && *(addrP + 2) == 0 && + ntohl(*(addrP + 3)) == 1) + return true; + // the IPv6 version of an IPv4 loopback address + if (*addrP == 0 && *(addrP + 1) == 0 && ntohl(*(addrP + 2)) == 0xffff && + ntohl(*(addrP + 3)) == 0x7f000001) + return true; + } + return false; +} + +const struct sockaddr *InetAddress::get_sock_addr() const +{ + return static_cast((void *)(&_addr6)); +} + +void InetAddress::set_sock_addr_inet6(const struct sockaddr_in6 &addr6) +{ + _addr6 = addr6; + _is_ip_v6 = (_addr6.sin6_family == AF_INET6); + _is_unspecified = false; +} + +sa_family_t InetAddress::family() const +{ + return _addr.sin_family; +} + +String InetAddress::to_ip() const +{ + char buf[64]; + if (_addr.sin_family == AF_INET) + { +#if defined GCCWIN || (_MSC_VER && _MSC_VER >= 1900) + ::inet_ntop(AF_INET, (PVOID)&_addr.sin_addr, buf, sizeof(buf)); +#else + ::inet_ntop(AF_INET, &_addr.sin_addr, buf, sizeof(buf)); +#endif + } + else if (_addr.sin_family == AF_INET6) + { +#if defined GCCWIN || (_MSC_VER && _MSC_VER >= 1900) + ::inet_ntop(AF_INET6, (PVOID)&_addr6.sin6_addr, buf, sizeof(buf)); +#else + ::inet_ntop(AF_INET6, &_addr6.sin6_addr, buf, sizeof(buf)); +#endif + } + + return buf; +} + +uint32_t InetAddress::ip_net_endian() const +{ + // assert(family() == AF_INET); + return _addr.sin_addr.s_addr; +} + +const uint32_t *InetAddress::ip6_net_endian() const +{ +// assert(family() == AF_INET6); +#if defined __linux__ || defined __HAIKU__ + return _addr6.sin6_addr.s6_addr32; +#elif defined _WIN32 + // TODO is this OK ? + const struct in6__addruint *_addrtemp = + reinterpret_cast(&_addr6.sin6_addr); + return (*_addrtemp).uext.__s6_addr32; +#else + return _addr6.sin6_addr.__u6_addr.__u6_addr32; +#endif +} + +uint16_t InetAddress::port_net_endian() const +{ + return _addr.sin_port; +} + +void InetAddress::set_port_net_endian(uint16_t port) +{ + _addr.sin_port = port; +} + +inline bool InetAddress::is_unspecified() const +{ + return _is_unspecified; +} + +uint16_t InetAddress::to_port() const +{ + return ntohs(port_net_endian()); +} + +bool InetAddress::is_ip_v6() const +{ + return _is_ip_v6; +} + +InetAddress::InetAddress(uint16_t port, bool loopbackOnly, bool ipv6) + : _is_ip_v6(ipv6) +{ + if (ipv6) + { + memset(&_addr6, 0, sizeof(_addr6)); + _addr6.sin6_family = AF_INET6; + + in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any; + + _addr6.sin6_addr = ip; + _addr6.sin6_port = htons(port); + } + else + { + memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + + in_addr_t ip = loopbackOnly ? kInaddrLoopback : kInaddrAny; + + _addr.sin_addr.s_addr = htonl(ip); + _addr.sin_port = htons(port); + } + _is_unspecified = false; +} + +InetAddress::InetAddress(const String &ip, uint16_t port, bool ipv6) + : _is_ip_v6(ipv6) +{ + if (ipv6) + { + memset(&_addr6, 0, sizeof(_addr6)); + _addr6.sin6_family = AF_INET6; + _addr6.sin6_port = htons(port); + + if (::inet_pton(AF_INET6, ip.c_str(), &_addr6.sin6_addr) <= 0) + { + return; + } + } + else + { + memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + _addr.sin_port = htons(port); + + if (::inet_pton(AF_INET, ip.c_str(), &_addr.sin_addr) <= 0) + { + return; + } + } + _is_unspecified = false; +} + diff --git a/sfw/core/inet_address.h b/sfw/core/inet_address.h new file mode 100755 index 0000000..b82838f --- /dev/null +++ b/sfw/core/inet_address.h @@ -0,0 +1,96 @@ +//Based on: + +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) +// +// This is a public header file, it must only include public header files. + +// Taken from Muduo and modified +// Copyright 2016, Tao An. All rights reserved. +// https://github.com/an-tao/trantor +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#ifndef INET_ADDRESS_H +#define INET_ADDRESS_H + +//On windows link to ws2_32 + +#include + +#ifdef _WIN32 +#include +using sa_family_t = unsigned short; +using in_addr_t = uint32_t; +using uint16_t = unsigned short; +#else +#include +#include +#include +#endif +#include "core/string.h" +#include +#include + +class InetAddress +{ + public: + + sa_family_t family() const; + + String to_ip() const; + String to_ip_port() const; + + uint16_t to_port() const; + + bool is_ip_v6() const; + bool is_intranet_ip() const; + bool is_loopback_ip() const; + + const struct sockaddr *get_sock_addr() const; + + void set_sock_addr_inet6(const struct sockaddr_in6 &addr6); + + uint32_t ip_net_endian() const; + const uint32_t *ip6_net_endian() const; + + uint16_t port_net_endian() const; + + void set_port_net_endian(uint16_t port); + + inline bool is_unspecified() const; + + InetAddress(uint16_t port = 0, bool loopbackOnly = false, bool ipv6 = false); + InetAddress(const String &ip, uint16_t port, bool ipv6 = false); + + explicit InetAddress(const struct sockaddr_in &addr) + : _addr(addr), _is_unspecified(false) + { + } + + explicit InetAddress(const struct sockaddr_in6 &addr) + : _addr6(addr), _is_ip_v6(true), _is_unspecified(false) + { + } + + + private: + union + { + struct sockaddr_in _addr; + struct sockaddr_in6 _addr6; + }; + + bool _is_ip_v6 {false}; + bool _is_unspecified {true}; +}; + +#endif diff --git a/sfw/core/socket.cpp b/sfw/core/socket.cpp index 8db2181..31a1db5 100755 --- a/sfw/core/socket.cpp +++ b/sfw/core/socket.cpp @@ -144,8 +144,8 @@ void Socket::bind_address(const InetAddress &address) if (ret != 0) { - LOG_ERR("Bind address failed:"); - LOG_ERR(address.to_ip_port()); + RLOG_ERR("Bind address failed:"); + RLOG_ERR(address.to_ip_port()); #ifdef _WIN32 exit(WSAGetLastError()); @@ -162,7 +162,7 @@ void Socket::listen() int ret = ::listen(_socket, SOMAXCONN); if (ret < 0) { - LOG_ERR("listen failed"); + RLOG_ERR("listen failed"); exit(1); } @@ -200,7 +200,7 @@ void Socket::close_write() if (::shutdown(_socket, SD_SEND) < 0) #endif { - LOG_ERR("sockets::shutdownwrite"); + RLOG_ERR("sockets::shutdownwrite"); } } @@ -255,12 +255,12 @@ void Socket::set_reuse_port(bool on) if (ret < 0 && on) { - LOG_ERR("SO_REUSEPORT failed."); + RLOG_ERR("SO_REUSEPORT failed."); } #else if (on) { - LOG_ERR("SO_REUSEPORT is not supported."); + RLOG_ERR("SO_REUSEPORT is not supported."); } #endif } @@ -283,7 +283,7 @@ struct sockaddr_in6 Socket::get_local_addr() if (::getsockname(_socket, static_cast((void *)(&localaddr)), &addrlen) < 0) { - LOG_ERR("sockets::getLocalAddr"); + RLOG_ERR("sockets::getLocalAddr"); } return localaddr; @@ -297,7 +297,7 @@ struct sockaddr_in6 Socket::get_peer_addr() if (::getpeername(_socket, static_cast((void *)(&peeraddr)), &addrlen) < 0) { - LOG_ERR("sockets::getPeerAddr"); + RLOG_ERR("sockets::getPeerAddr"); } return peeraddr; diff --git a/sfw/core/socket.h b/sfw/core/socket.h index 6ff40c7..4d360c7 100755 --- a/sfw/core/socket.h +++ b/sfw/core/socket.h @@ -17,8 +17,8 @@ * */ -#include "error_macros.h" -#include +#include "core/error_macros.h" +#include "core/string.h" #ifndef _WIN32 #include