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/memtracker.cpp
|
||||||
src/misc/digest.cpp
|
src/misc/digest.cpp
|
||||||
src/misc/base64.cpp
|
src/misc/base64.cpp
|
||||||
|
src/misc/net.cpp
|
||||||
|
|
||||||
src/lock/rw_mutex.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)
|
#add_executable(SQLTest ${SOURCE_FILES} ${HEADER_FILES} test/SQLTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
|
||||||
#target_link_libraries(SQLTest ${TEST_LIBRARIES})
|
#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)
|
target_link_libraries(SQL2Test sqlite3)
|
||||||
|
|
||||||
add_executable(ChannelTest ${SOURCE_FILES} ${HEADER_FILES} test/ChannelTest.cpp src/log/LogSinks.cpp src/log/LogSinks.h)
|
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
92
src/misc/net.cpp
Normal 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
|
@ -4,6 +4,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
@ -18,19 +19,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace net {
|
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];
|
char buffer[INET6_ADDRSTRLEN];
|
||||||
if(!inet_ntop(AF_INET6, (void*) &address, buffer, INET6_ADDRSTRLEN)) return "";
|
if(!inet_ntop(AF_INET6, (void*) &address, buffer, INET6_ADDRSTRLEN)) return "";
|
||||||
return std::string(buffer);
|
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];
|
char buffer[INET_ADDRSTRLEN];
|
||||||
if(!inet_ntop(AF_INET, (void*) &address, buffer, INET_ADDRSTRLEN)) return "";
|
if(!inet_ntop(AF_INET, (void*) &address, buffer, INET_ADDRSTRLEN)) return "";
|
||||||
return std::string(buffer);
|
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) {
|
switch(address.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return to_string(((sockaddr_in*) &address)->sin_addr) + (port ? ":" + std::to_string(htons(((sockaddr_in*) &address)->sin_port)) : "");
|
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) {
|
switch(address.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return htons(((sockaddr_in*) &address)->sin_port);
|
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) {
|
switch (address.ss_family) {
|
||||||
case AF_INET: return sizeof(sockaddr_in);
|
case AF_INET: return sizeof(sockaddr_in);
|
||||||
case AF_INET6: return sizeof(sockaddr_in6);
|
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 != 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;
|
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) {
|
else if(a.ss_family == AF_INET6) {
|
||||||
@ -73,7 +74,7 @@ namespace net {
|
|||||||
return false;
|
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 != b.ss_family) return false;
|
||||||
if(a.ss_family == AF_INET) {
|
if(a.ss_family == AF_INET) {
|
||||||
auto address_a = ((sockaddr_in*) &a)->sin_addr.s_addr;
|
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{};
|
sockaddr_in6 sa{};
|
||||||
return inet_pton(AF_INET6, str.c_str(), &(sa.sin6_addr)) != 0;
|
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{};
|
sockaddr_in sa{};
|
||||||
return inet_pton(AF_INET, str.c_str(), &(sa.sin_addr)) != 0;
|
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) {
|
if(storage.ss_family == AF_INET) {
|
||||||
auto data = (sockaddr_in*) &storage;
|
auto data = (sockaddr_in*) &storage;
|
||||||
return data->sin_addr.s_addr == 0;
|
return data->sin_addr.s_addr == 0;
|
||||||
@ -165,7 +166,7 @@ namespace net {
|
|||||||
return false;
|
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)) {
|
if(is_ipv4(address)) {
|
||||||
sockaddr_in s{};
|
sockaddr_in s{};
|
||||||
s.sin_port = 0;
|
s.sin_port = 0;
|
||||||
@ -210,51 +211,18 @@ namespace net {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace helpers {
|
[[nodiscard]] std::vector<std::tuple<std::string, sockaddr_storage, std::string>> resolve_bindings(const std::string& bindings, uint16_t port);
|
||||||
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) {
|
enum struct binding_result {
|
||||||
std::deque<std::string> result{};
|
ADDRESS_FREE,
|
||||||
size_t found, index = 0;
|
ADDRESS_USED,
|
||||||
do {
|
INTERNAL_ERROR
|
||||||
found = message.find(delimiter, index);
|
};
|
||||||
result.push_back(message.substr(index, found - index));
|
|
||||||
index = found + 1;
|
|
||||||
} while(index != 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::vector<std::tuple<std::string, sockaddr_storage, std::string>> resolve_bindings(const std::string& bindings, uint16_t port) {
|
enum struct binding_type {
|
||||||
auto binding_list = helpers::split(bindings, ',');
|
TCP,
|
||||||
std::vector<std::tuple<std::string, sockaddr_storage, std::string>> result;
|
UDP
|
||||||
result.reserve(binding_list.size());
|
};
|
||||||
|
|
||||||
for(auto& address : binding_list) {
|
[[nodiscard]] binding_result address_available(const sockaddr_storage& address, binding_type type);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -175,8 +175,11 @@ struct A {
|
|||||||
~A() = default;
|
~A() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <set>
|
#include <netinet/in.h>
|
||||||
|
#include <src/misc/net.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
#if 0
|
||||||
std::set<int> elements{};
|
std::set<int> elements{};
|
||||||
if(!elements.empty()) {
|
if(!elements.empty()) {
|
||||||
auto it = elements.begin();
|
auto it = elements.begin();
|
||||||
@ -186,4 +189,12 @@ int main() {
|
|||||||
const auto diff = last_element - now;
|
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
Block a user