summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--CMake/AddDependencies.cmake1
m---------lib/asio0
-rw-r--r--src/Bindings/ManualBindings_Network.cpp4
-rw-r--r--src/Globals.h2
-rw-r--r--src/OSSupport/HostnameLookup.cpp121
-rw-r--r--src/OSSupport/HostnameLookup.h21
-rw-r--r--src/OSSupport/IPLookup.cpp4
-rw-r--r--src/OSSupport/Network.h2
-rw-r--r--src/OSSupport/NetworkSingleton.cpp10
-rw-r--r--src/OSSupport/NetworkSingleton.h10
-rw-r--r--src/OSSupport/TCPLinkImpl.cpp2
-rw-r--r--src/OSSupport/UDPEndpointImpl.cpp3
-rw-r--r--tests/Network/CMakeLists.txt2
-rw-r--r--tests/Network/NameLookup.cpp4
15 files changed, 85 insertions, 104 deletions
diff --git a/.gitmodules b/.gitmodules
index e167fe6d5..57f3c9779 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -66,3 +66,6 @@
[submodule "Tools/BlockTypePaletteGenerator/lib/lunajson"]
path = Tools/BlockTypePaletteGenerator/lib/lunajson
url = https://github.com/grafi-tt/lunajson.git
+[submodule "lib/asio"]
+ path = lib/asio
+ url = https://github.com/chriskohlhoff/asio
diff --git a/CMake/AddDependencies.cmake b/CMake/AddDependencies.cmake
index 971a338cc..795940009 100644
--- a/CMake/AddDependencies.cmake
+++ b/CMake/AddDependencies.cmake
@@ -49,6 +49,7 @@ function(link_dependencies TARGET)
# Add required includes:
target_include_directories(
${TARGET} SYSTEM PRIVATE
+ lib/asio/asio/include
lib/mbedtls/include
lib/TCLAP/include
lib # TODO fix files including zlib/x instead of x
diff --git a/lib/asio b/lib/asio
new file mode 160000
+Subproject efff0de89920eb66afead00dfd8bb8cf588ccee
diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp
index 4a7dd2367..fb60e4e0a 100644
--- a/src/Bindings/ManualBindings_Network.cpp
+++ b/src/Bindings/ManualBindings_Network.cpp
@@ -169,7 +169,7 @@ static int tolua_cNetwork_HostnameToIP(lua_State * L)
ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
// Try to look up:
- bool res = cNetwork::HostnameToIP(host, std::make_shared<cLuaNameLookup>(host, std::move(callbacks)));
+ bool res = cNetwork::HostnameToIP(host, std::make_unique<cLuaNameLookup>(host, std::move(callbacks)));
S.Push(res);
return 1;
}
@@ -205,7 +205,7 @@ static int tolua_cNetwork_IPToHostname(lua_State * L)
ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false
// Try to look up:
- bool res = cNetwork::IPToHostName(ip, std::make_shared<cLuaNameLookup>(ip, std::move(callbacks)));
+ bool res = cNetwork::IPToHostName(ip, std::make_unique<cLuaNameLookup>(ip, std::move(callbacks)));
S.Push(res);
return 1;
}
diff --git a/src/Globals.h b/src/Globals.h
index 114991129..2523a4304 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -57,7 +57,7 @@
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_CLIENTBLOCK new(_CLIENT_BLOCK, __FILE__, __LINE__)
- #define new DEBUG_CLIENTBLOCK
+ // #define new DEBUG_CLIENTBLOCK
// For some reason this works magically - each "new X" gets replaced as "new(_CLIENT_BLOCK, "file", line) X"
// The CRT has a definition for this operator new that stores the debugging info for leak-finding later.
#endif
diff --git a/src/OSSupport/HostnameLookup.cpp b/src/OSSupport/HostnameLookup.cpp
index d86430d83..ee9610f63 100644
--- a/src/OSSupport/HostnameLookup.cpp
+++ b/src/OSSupport/HostnameLookup.cpp
@@ -15,104 +15,85 @@
////////////////////////////////////////////////////////////////////////////////
// cHostnameLookup:
-cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks):
- m_Callbacks(std::move(a_Callbacks)),
- m_Hostname(a_Hostname)
+void cHostnameLookup::Lookup(
+ const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks)
{
-}
-
-
-
-
-
-void cHostnameLookup::Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks)
-{
- // Cannot use std::make_shared here, constructor is not accessible
- cHostnameLookupPtr Lookup{ new cHostnameLookup(a_Hostname, std::move(a_Callbacks)) };
+ // Note the Lookup object is owned solely by this lambda which is destroyed
+ // after it runs
+ cNetworkSingleton::Get().GetLookupThread().async_resolve(
+ a_Hostname, "",
+ [Callbacks = std::move(a_Callbacks)](const auto & a_Error, const auto & a_Results)
+ {
+ // If an error has occurred, notify the error callback:
+ if (a_Error)
+ {
+ Callbacks->OnError(a_Error.value(), a_Error.message());
+ return;
+ }
- // Note the Lookup object is owned solely by this lambda which is destroyed after it runs
- cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]()
- {
- // Start the lookup:
- addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_CANONNAME;
-
- addrinfo * Result;
- int ErrCode = getaddrinfo(Lookup->m_Hostname.c_str(), nullptr, &hints, &Result);
-
- Lookup->Callback(ErrCode, Result);
- });
+ Callback(*Callbacks.get(), a_Results);
+ }
+ );
}
-void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr)
+void cHostnameLookup::Callback(cNetwork::cResolveNameCallbacks & a_Callbacks, const asio::ip::tcp::resolver::results_type & a_Addr)
{
- // If an error has occurred, notify the error callback:
- if (a_ErrCode != 0)
- {
- m_Callbacks->OnError(a_ErrCode, ErrorString(a_ErrCode));
- return;
- }
-
// Call the success handler for each entry received:
bool HasResolved = false;
- addrinfo * OrigAddr = a_Addr;
- for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next)
+
+ for (const auto & Addr : a_Addr)
{
- char IP[128];
- switch (a_Addr->ai_family)
+ const auto & Endpoint = Addr.endpoint();
+ const auto & Address = Endpoint.address();
+ const auto & Hostname = Addr.host_name();
+
+ if (Address.is_v4())
{
- case AF_INET: // IPv4
+ const auto sin =
+ reinterpret_cast<const sockaddr_in *>(Endpoint.data());
+ if (!a_Callbacks.OnNameResolvedV4(Hostname, sin))
{
- sockaddr_in * sin = reinterpret_cast<sockaddr_in *>(a_Addr->ai_addr);
- if (!m_Callbacks->OnNameResolvedV4(m_Hostname, sin))
- {
- // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address:
- HasResolved = true;
- continue;
- }
- evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP));
- break;
+ // Callback indicated that the IP shouldn't be serialized to
+ // a string, just continue with the next address:
+ HasResolved = true;
+ continue;
}
- case AF_INET6: // IPv6
- {
- sockaddr_in6 * sin = reinterpret_cast<sockaddr_in6 *>(a_Addr->ai_addr);
- if (!m_Callbacks->OnNameResolvedV6(m_Hostname, sin))
- {
- // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address:
- HasResolved = true;
- continue;
- }
- evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP));
- break;
- }
- default:
+ }
+ else if (Address.is_v6())
+ {
+ const auto sin =
+ reinterpret_cast<const sockaddr_in6 *>(Endpoint.data());
+ if (!a_Callbacks.OnNameResolvedV6(Hostname, sin))
{
- // Unknown address family, handle as if this entry wasn't received
- continue; // for (a_Addr)
+ // Callback indicated that the IP shouldn't be serialized to
+ // a string, just continue with the next address:
+ HasResolved = true;
+ continue;
}
}
- m_Callbacks->OnNameResolved(m_Hostname, IP);
+ else
+ {
+ // Unknown address family, handle as if this entry wasn't
+ // received
+ continue; // for (a_Addr)
+ }
+ a_Callbacks.OnNameResolved(Hostname, Address.to_string());
HasResolved = true;
} // for (a_Addr)
// If only unsupported families were reported, call the Error handler:
if (!HasResolved)
{
- m_Callbacks->OnError(EAI_NONAME, ErrorString(EAI_NONAME));
+ a_Callbacks.OnError(EAI_NONAME, ErrorString(EAI_NONAME));
}
else
{
- m_Callbacks->OnFinished();
+ a_Callbacks.OnFinished();
}
- freeaddrinfo(OrigAddr);
}
diff --git a/src/OSSupport/HostnameLookup.h b/src/OSSupport/HostnameLookup.h
index 9189ef021..337100063 100644
--- a/src/OSSupport/HostnameLookup.h
+++ b/src/OSSupport/HostnameLookup.h
@@ -12,6 +12,7 @@
#pragma once
#include "Network.h"
+#include <asio/ip/tcp.hpp>
@@ -24,23 +25,7 @@ public:
/** Creates a lookup object and schedules the lookup. */
static void Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks);
-protected:
+private:
- /** Creates the lookup object. Doesn't start the lookup yet. */
- cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks);
-
- /** The callbacks to call for resolved names / errors. */
- cNetwork::cResolveNameCallbacksPtr m_Callbacks;
-
- /** The hostname that was queried (needed for the callbacks). */
- AString m_Hostname;
-
- void Callback(int a_ErrCode, struct addrinfo * a_Addr);
+ static void Callback(cNetwork::cResolveNameCallbacks & a_Callbacks, const asio::ip::tcp::resolver::results_type & a_Addr);
};
-typedef std::shared_ptr<cHostnameLookup> cHostnameLookupPtr;
-typedef std::vector<cHostnameLookupPtr> cHostnameLookupPtrs;
-
-
-
-
-
diff --git a/src/OSSupport/IPLookup.cpp b/src/OSSupport/IPLookup.cpp
index f730110b9..066573a72 100644
--- a/src/OSSupport/IPLookup.cpp
+++ b/src/OSSupport/IPLookup.cpp
@@ -32,7 +32,7 @@ void cIPLookup::Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr
cIPLookupPtr Lookup{ new cIPLookup(a_IP, std::move(a_Callbacks)) }; // Cannot use std::make_shared here, constructor is not accessible
// Note the Lookup object is owned solely by this lambda which is destroyed after it runs
- cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]()
+ /* cNetworkSingleton::Get().GetLookupThread().ScheduleLookup( */[=]()
{
sockaddr_storage sa;
int salen = sizeof(sa);
@@ -58,7 +58,7 @@ void cIPLookup::Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr
0
);
Lookup->Callback(ErrCode, Hostname);
- });
+ }();
}
diff --git a/src/OSSupport/Network.h b/src/OSSupport/Network.h
index 8e3f20025..e6432cd15 100644
--- a/src/OSSupport/Network.h
+++ b/src/OSSupport/Network.h
@@ -297,7 +297,7 @@ public:
Only called if there was no error reported. */
virtual void OnFinished(void) = 0;
};
- typedef std::shared_ptr<cResolveNameCallbacks> cResolveNameCallbacksPtr;
+ typedef std::unique_ptr<cResolveNameCallbacks> cResolveNameCallbacksPtr;
/** Queues a TCP connection to be made to the specified host.
diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp
index e022f4fec..54842f358 100644
--- a/src/OSSupport/NetworkSingleton.cpp
+++ b/src/OSSupport/NetworkSingleton.cpp
@@ -16,7 +16,8 @@
cNetworkSingleton::cNetworkSingleton() :
- m_HasTerminated(true)
+ m_HasTerminated(true),
+ m_Resolver(m_Context)
{
}
@@ -47,7 +48,9 @@ cNetworkSingleton & cNetworkSingleton::Get(void)
void cNetworkSingleton::Initialise(void)
{
// Start the lookup thread
- m_LookupThread.Start();
+ m_Context.restart();
+ m_Context.get_executor().on_work_started();
+ m_LookupThread = std::thread([this] { m_Context.run(); });
// Windows: initialize networking:
#ifdef _WIN32
@@ -100,7 +103,8 @@ void cNetworkSingleton::Terminate(void)
ASSERT(!m_HasTerminated);
// Wait for the lookup thread to stop
- m_LookupThread.Stop();
+ m_Context.get_executor().on_work_finished();
+ m_LookupThread.join();
// Wait for the LibEvent event loop to terminate:
event_base_loopbreak(m_EventBase);
diff --git a/src/OSSupport/NetworkSingleton.h b/src/OSSupport/NetworkSingleton.h
index 2a2d0cef3..31347f4c1 100644
--- a/src/OSSupport/NetworkSingleton.h
+++ b/src/OSSupport/NetworkSingleton.h
@@ -14,6 +14,8 @@
#pragma once
#include <event2/event.h>
+#include <asio/ip/tcp.hpp>
+#include <asio/io_context.hpp>
#include "NetworkLookup.h"
#include "CriticalSection.h"
#include "Event.h"
@@ -57,7 +59,7 @@ public:
event_base * GetEventBase(void) { return m_EventBase; }
/** Returns the thread used to perform hostname and IP lookups */
- cNetworkLookup & GetLookupThread() { return m_LookupThread; }
+ asio::ip::tcp::resolver & GetLookupThread() { return m_Resolver; }
/** Adds the specified link to m_Connections.
Used by the underlying link implementation when a new link is created. */
@@ -100,7 +102,11 @@ protected:
cEvent m_StartupEvent;
/** The thread on which hostname and ip address lookup is performed. */
- cNetworkLookup m_LookupThread;
+ std::thread m_LookupThread;
+
+ asio::io_context m_Context;
+
+ asio::ip::tcp::resolver m_Resolver;
/** Converts LibEvent-generated log events into log messages in MCS log. */
diff --git a/src/OSSupport/TCPLinkImpl.cpp b/src/OSSupport/TCPLinkImpl.cpp
index c93a1879d..6b8c7f677 100644
--- a/src/OSSupport/TCPLinkImpl.cpp
+++ b/src/OSSupport/TCPLinkImpl.cpp
@@ -138,7 +138,7 @@ cTCPLinkImplPtr cTCPLinkImpl::Connect(const AString & a_Host, UInt16 a_Port, cTC
};
// Schedule the host query
- cNetwork::HostnameToIP(a_Host, std::make_shared<cHostnameCallback>(res, a_Port));
+ cNetwork::HostnameToIP(a_Host, std::make_unique<cHostnameCallback>(res, a_Port));
return res;
}
diff --git a/src/OSSupport/UDPEndpointImpl.cpp b/src/OSSupport/UDPEndpointImpl.cpp
index 3f04dd4f5..14066a058 100644
--- a/src/OSSupport/UDPEndpointImpl.cpp
+++ b/src/OSSupport/UDPEndpointImpl.cpp
@@ -270,8 +270,7 @@ bool cUDPEndpointImpl::Send(const AString & a_Payload, const AString & a_Host, U
if (evutil_parse_sockaddr_port(a_Host.c_str(), reinterpret_cast<sockaddr *>(&sa), &salen) != 0)
{
// a_Host is a hostname, we need to do a lookup first:
- auto queue = std::make_shared<cUDPSendAfterLookup>(a_Payload, a_Port, m_MainSock, m_SecondarySock, m_IsMainSockIPv6);
- return cNetwork::HostnameToIP(a_Host, queue);
+ return cNetwork::HostnameToIP(a_Host, std::make_unique<cUDPSendAfterLookup>(a_Payload, a_Port, m_MainSock, m_SecondarySock, m_IsMainSockIPv6));
}
// a_Host is an IP address and has been parsed into "sa"
diff --git a/tests/Network/CMakeLists.txt b/tests/Network/CMakeLists.txt
index 8bbe6294d..00d5e2f21 100644
--- a/tests/Network/CMakeLists.txt
+++ b/tests/Network/CMakeLists.txt
@@ -55,6 +55,8 @@ add_library(Network
${Network_HDRS}
)
+target_include_directories(Network SYSTEM PUBLIC ${CMAKE_SOURCE_DIR}/lib/asio/asio/include)
+
target_link_libraries(Network event_core event_extra fmt::fmt mbedtls)
if(NOT WIN32)
target_link_libraries(Network event_pthreads Threads::Threads)
diff --git a/tests/Network/NameLookup.cpp b/tests/Network/NameLookup.cpp
index 2904a0199..1ae6c3bbc 100644
--- a/tests/Network/NameLookup.cpp
+++ b/tests/Network/NameLookup.cpp
@@ -52,7 +52,7 @@ static void DoTest(void)
// Look up google.com (has multiple IP addresses):
LOGD("Network test: Looking up google.com");
- if (!cNetwork::HostnameToIP("google.com", std::make_shared<cFinishLookupCallbacks>(evtFinish)))
+ if (!cNetwork::HostnameToIP("google.com", std::make_unique<cFinishLookupCallbacks>(evtFinish)))
{
LOGWARNING("Cannot resolve google.com to IP");
abort();
@@ -63,7 +63,7 @@ static void DoTest(void)
// Look up 8.8.8.8 (Google free DNS):
LOGD("Network test: Looking up IP 8.8.8.8");
- if (!cNetwork::IPToHostName("8.8.8.8", std::make_shared<cFinishLookupCallbacks>(evtFinish)))
+ if (!cNetwork::IPToHostName("8.8.8.8", std::make_unique<cFinishLookupCallbacks>(evtFinish)))
{
LOGWARNING("Cannot resolve 8.8.8.8 to name");
abort();