Updated to 1.4.13 ;)
This commit is contained in:
parent
16c2272fe4
commit
c31cc9d0ee
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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";
|
||||
}
|
Loading…
Reference in New Issue