Updated to 1.4.13 ;)

This commit is contained in:
WolverinDEV 2020-04-16 14:05:56 +02:00
parent 16c2272fe4
commit c31cc9d0ee
4 changed files with 129 additions and 57 deletions

View File

@ -94,6 +94,7 @@ set(SOURCE_FILES
src/misc/memtracker.cpp
src/misc/digest.cpp
src/misc/base64.cpp
src/misc/net.cpp
src/lock/rw_mutex.cpp
@ -278,7 +279,7 @@ if(BUILD_TESTS)
#add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
#target_link_libraries(SQLTest ${TEST_LIBRARIES})
add_executable(SQL2Test test/SQL2Test.cpp src/Variable.cpp)
add_executable(SQL2Test test/SQL2Test.cpp src/Variable.cpp src/misc/net.cpp)
target_link_libraries(SQL2Test sqlite3)
add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)

92
src/misc/net.cpp Normal file
View File

@ -0,0 +1,92 @@
//
// Created by WolverinDEV on 16/04/2020.
//
#ifndef WIN32
#include <unistd.h>
#include <fcntl.h>
#endif
#include "./net.h"
namespace helpers {
inline void strip(std::string& message) {
while(!message.empty()) {
if(message[0] == ' ')
message = message.substr(1);
else if(message[message.length() - 1] == ' ')
message = message.substr(0, message.length() - 1);
else break;
}
}
inline std::deque<std::string> split(const std::string& message, char delimiter) {
std::deque<std::string> result{};
size_t found, index = 0;
do {
found = message.find(delimiter, index);
result.push_back(message.substr(index, found - index));
index = found + 1;
} while(index != 0);
return result;
}
}
std::vector<std::tuple<std::string, sockaddr_storage, std::string>> net::resolve_bindings(const std::string& bindings, uint16_t port) {
auto binding_list = helpers::split(bindings, ',');
std::vector<std::tuple<std::string, sockaddr_storage, std::string>> result;
result.reserve(binding_list.size());
for(auto& address : binding_list) {
helpers::strip(address);
sockaddr_storage element{};
memset(&element, 0, sizeof(element));
if(!resolve_address(address, element)) {
result.emplace_back(address, element, "address resolve failed");
continue;
}
if(element.ss_family == AF_INET) {
((sockaddr_in*) &element)->sin_port = htons(port);
} else if(element.ss_family == AF_INET6) {
((sockaddr_in6*) &element)->sin6_port = htons(port);
}
result.emplace_back(address, element, "");
}
return result;
}
#ifndef WIN32
net::binding_result net::address_available(const sockaddr_storage& address, binding_type type) {
int file_descriptor{0};
net::binding_result result{binding_result::INTERNAL_ERROR};
int disable{0}, enable{1};
file_descriptor = socket(address.ss_family, type == binding_type::TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
if(file_descriptor <= 0)
goto cleanup_exit;
fcntl(file_descriptor, F_SETFD, FD_CLOEXEC); /* just to ensure */
setsockopt(file_descriptor, SOL_SOCKET, SO_REUSEADDR, &disable, sizeof(int));
setsockopt(file_descriptor, SOL_SOCKET, SO_REUSEPORT, &disable, sizeof(int));
if(type == binding_type::UDP && address.ss_family == AF_INET6)
setsockopt(file_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int));
if(::bind(file_descriptor, (const sockaddr*) &address, net::address_size(address)) != 0) {
result = binding_result::ADDRESS_USED;
} else {
result = binding_result::ADDRESS_FREE;
}
if(type == binding_type::TCP) {
if(::listen(file_descriptor, 1) != 0)
result = binding_result::ADDRESS_USED;
}
cleanup_exit:
if(file_descriptor > 0)
::close(file_descriptor);
return result;
}
#endif

View File

@ -4,6 +4,7 @@
#include <cstring>
#include <deque>
#include <vector>
#include <tuple>
#ifdef WIN32
#include <WS2tcpip.h>
@ -18,19 +19,19 @@
#endif
namespace net {
inline std::string to_string(const in6_addr& address) {
[[nodiscard]] inline std::string to_string(const in6_addr& address) {
char buffer[INET6_ADDRSTRLEN];
if(!inet_ntop(AF_INET6, (void*) &address, buffer, INET6_ADDRSTRLEN)) return "";
return std::string(buffer);
}
inline std::string to_string(const in_addr& address) {
[[nodiscard]] inline std::string to_string(const in_addr& address) {
char buffer[INET_ADDRSTRLEN];
if(!inet_ntop(AF_INET, (void*) &address, buffer, INET_ADDRSTRLEN)) return "";
return std::string(buffer);
}
inline std::string to_string(const sockaddr_storage& address, bool port = true) {
[[nodiscard]] inline std::string to_string(const sockaddr_storage& address, bool port = true) {
switch(address.ss_family) {
case AF_INET:
return to_string(((sockaddr_in*) &address)->sin_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in*) &address)->sin_port)) : "");
@ -41,7 +42,7 @@ namespace net {
}
}
inline uint16_t port(const sockaddr_storage& address) {
[[nodiscard]] inline uint16_t port(const sockaddr_storage& address) {
switch(address.ss_family) {
case AF_INET:
return htons(((sockaddr_in*) &address)->sin_port);
@ -52,7 +53,7 @@ namespace net {
}
}
inline socklen_t address_size(const sockaddr_storage& address) {
[[nodiscard]] inline socklen_t address_size(const sockaddr_storage& address) {
switch (address.ss_family) {
case AF_INET: return sizeof(sockaddr_in);
case AF_INET6: return sizeof(sockaddr_in6);
@ -60,7 +61,7 @@ namespace net {
}
}
inline bool address_equal(const sockaddr_storage& a, const sockaddr_storage& b) {
[[nodiscard]] inline bool address_equal(const sockaddr_storage& a, const sockaddr_storage& b) {
if(a.ss_family != b.ss_family) return false;
if(a.ss_family == AF_INET) return ((sockaddr_in*) &a)->sin_addr.s_addr == ((sockaddr_in*) &b)->sin_addr.s_addr;
else if(a.ss_family == AF_INET6) {
@ -73,7 +74,7 @@ namespace net {
return false;
}
inline bool address_equal_ranged(const sockaddr_storage& a, const sockaddr_storage& b, uint8_t range) {
[[nodiscard]] inline bool address_equal_ranged(const sockaddr_storage& a, const sockaddr_storage& b, uint8_t range) {
if(a.ss_family != b.ss_family) return false;
if(a.ss_family == AF_INET) {
auto address_a = ((sockaddr_in*) &a)->sin_addr.s_addr;
@ -130,17 +131,17 @@ namespace net {
}
inline bool is_ipv6(const std::string& str) {
[[nodiscard]] inline bool is_ipv6(const std::string& str) {
sockaddr_in6 sa{};
return inet_pton(AF_INET6, str.c_str(), &(sa.sin6_addr)) != 0;
}
inline bool is_ipv4(const std::string& str) {
[[nodiscard]] inline bool is_ipv4(const std::string& str) {
sockaddr_in sa{};
return inet_pton(AF_INET, str.c_str(), &(sa.sin_addr)) != 0;
}
inline bool is_anybind(sockaddr_storage& storage) {
[[nodiscard]] inline bool is_anybind(sockaddr_storage& storage) {
if(storage.ss_family == AF_INET) {
auto data = (sockaddr_in*) &storage;
return data->sin_addr.s_addr == 0;
@ -165,7 +166,7 @@ namespace net {
return false;
}
inline bool resolve_address(const std::string& address, sockaddr_storage& result) {
[[nodiscard]] inline bool resolve_address(const std::string& address, sockaddr_storage& result) {
if(is_ipv4(address)) {
sockaddr_in s{};
s.sin_port = 0;
@ -210,51 +211,18 @@ namespace net {
return false;
}
namespace helpers {
inline void strip(std::string& message) {
while(!message.empty()) {
if(message[0] == ' ')
message = message.substr(1);
else if(message[message.length() - 1] == ' ')
message = message.substr(0, message.length() - 1);
else break;
}
}
[[nodiscard]] std::vector<std::tuple<std::string, sockaddr_storage, std::string>> resolve_bindings(const std::string& bindings, uint16_t port);
inline std::deque<std::string> split(const std::string& message, char delimiter) {
std::deque<std::string> result{};
size_t found, index = 0;
do {
found = message.find(delimiter, index);
result.push_back(message.substr(index, found - index));
index = found + 1;
} while(index != 0);
return result;
}
}
enum struct binding_result {
ADDRESS_FREE,
ADDRESS_USED,
INTERNAL_ERROR
};
inline std::vector<std::tuple<std::string, sockaddr_storage, std::string>> resolve_bindings(const std::string& bindings, uint16_t port) {
auto binding_list = helpers::split(bindings, ',');
std::vector<std::tuple<std::string, sockaddr_storage, std::string>> result;
result.reserve(binding_list.size());
enum struct binding_type {
TCP,
UDP
};
for(auto& address : binding_list) {
helpers::strip(address);
sockaddr_storage element{};
memset(&element, 0, sizeof(element));
if(!resolve_address(address, element)) {
result.emplace_back(address, element, "address resolve failed");
continue;
}
if(element.ss_family == AF_INET) {
((sockaddr_in*) &element)->sin_port = htons(port);
} else if(element.ss_family == AF_INET6) {
((sockaddr_in6*) &element)->sin6_port = htons(port);
}
result.emplace_back(address, element, "");
}
return result;
}
[[nodiscard]] binding_result address_available(const sockaddr_storage& address, binding_type type);
}

View File

@ -175,8 +175,11 @@ struct A {
~A() = default;
};
#include <set>
#include <netinet/in.h>
#include <src/misc/net.h>
int main() {
#if 0
std::set<int> elements{};
if(!elements.empty()) {
auto it = elements.begin();
@ -186,4 +189,12 @@ int main() {
const auto diff = last_element - now;
}
}
#endif
sockaddr_in addr{};
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(9987);
std::cout << "Result: " << (int) net::address_available(*(sockaddr_storage*) &addr, net::binding_type::TCP) << "\n";
std::cout << strerror(errno) << "\n";
}