cNetwork: Implemented HostnameToIP lookups.
This commit is contained in:
parent
c7335255ac
commit
fde44cba08
@ -123,6 +123,27 @@ public:
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Class definitions:
|
// Class definitions:
|
||||||
|
|
||||||
|
/** Holds information about an in-progress hostname lookup. */
|
||||||
|
class cHostnameLookup
|
||||||
|
{
|
||||||
|
/** The callbacks to call for resolved names / errors. */
|
||||||
|
cNetwork::cResolveNameCallbacksPtr m_Callbacks;
|
||||||
|
|
||||||
|
/** The hostname that was queried (needed for the callbacks). */
|
||||||
|
AString m_Hostname;
|
||||||
|
|
||||||
|
static void Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, void * a_Self);
|
||||||
|
|
||||||
|
public:
|
||||||
|
cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks);
|
||||||
|
};
|
||||||
|
typedef SharedPtr<cHostnameLookup> cHostnameLookupPtr;
|
||||||
|
typedef std::vector<cHostnameLookupPtr> cHostnameLookupPtrs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Implements the cTCPLink details so that it can represent the single connection between two endpoints. */
|
/** Implements the cTCPLink details so that it can represent the single connection between two endpoints. */
|
||||||
class cTCPLinkImpl:
|
class cTCPLinkImpl:
|
||||||
public cTCPLink
|
public cTCPLink
|
||||||
@ -214,7 +235,8 @@ typedef std::vector<cServerHandleImplPtr> cServerHandleImplPtrs;
|
|||||||
|
|
||||||
class cNetworkSingleton
|
class cNetworkSingleton
|
||||||
{
|
{
|
||||||
friend class cTCPLinkImpl;
|
friend class cHostnameLookup; // Needs access to m_DNSBase
|
||||||
|
friend class cTCPLinkImpl; // Needs access to m_EventBase and m_DNSBase
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Returns the singleton instance of this class */
|
/** Returns the singleton instance of this class */
|
||||||
@ -280,6 +302,9 @@ protected:
|
|||||||
/** Container for all servers that are currently active. */
|
/** Container for all servers that are currently active. */
|
||||||
cServerHandleImplPtrs m_Servers;
|
cServerHandleImplPtrs m_Servers;
|
||||||
|
|
||||||
|
/** Container for all pending hostname lookups. */
|
||||||
|
cHostnameLookupPtrs m_HostnameLookups;
|
||||||
|
|
||||||
|
|
||||||
/** Initializes the LibEvent internals. */
|
/** Initializes the LibEvent internals. */
|
||||||
cNetworkSingleton(void);
|
cNetworkSingleton(void);
|
||||||
@ -289,12 +314,94 @@ protected:
|
|||||||
|
|
||||||
/** Implements the thread that runs LibEvent's event dispatcher loop. */
|
/** Implements the thread that runs LibEvent's event dispatcher loop. */
|
||||||
static void RunEventLoop(cNetworkSingleton * a_Self);
|
static void RunEventLoop(cNetworkSingleton * a_Self);
|
||||||
|
|
||||||
|
/** Removes the specified hostname lookup from m_HostnameLookups. */
|
||||||
|
void RemoveHostnameLookup(cHostnameLookup * a_HostnameLookup);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cHostnameLookup:
|
||||||
|
|
||||||
|
cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks):
|
||||||
|
m_Callbacks(a_Callbacks),
|
||||||
|
m_Hostname(a_Hostname)
|
||||||
|
{
|
||||||
|
evutil_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 = EVUTIL_AI_CANONNAME;
|
||||||
|
evdns_getaddrinfo(cNetworkSingleton::Get().m_DNSBase, a_Hostname.c_str(), nullptr, &hints, Callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHostnameLookup::Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, void * a_Self)
|
||||||
|
{
|
||||||
|
// Get the Self class:
|
||||||
|
cHostnameLookup * Self = reinterpret_cast<cHostnameLookup *>(a_Self);
|
||||||
|
ASSERT(Self != nullptr);
|
||||||
|
|
||||||
|
// If an error has occurred, notify the error callback:
|
||||||
|
if (a_ErrCode != 0)
|
||||||
|
{
|
||||||
|
Self->m_Callbacks->OnError(a_ErrCode);
|
||||||
|
cNetworkSingleton::Get().RemoveHostnameLookup(Self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the success handler for each entry received:
|
||||||
|
bool HasResolved = false;
|
||||||
|
for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next)
|
||||||
|
{
|
||||||
|
char IP[128];
|
||||||
|
switch (a_Addr->ai_family)
|
||||||
|
{
|
||||||
|
case AF_INET: // IPv4
|
||||||
|
{
|
||||||
|
sockaddr_in * sin = reinterpret_cast<sockaddr_in *>(a_Addr->ai_addr);
|
||||||
|
evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AF_INET6: // IPv6
|
||||||
|
{
|
||||||
|
sockaddr_in6 * sin = reinterpret_cast<sockaddr_in6 *>(a_Addr->ai_addr);
|
||||||
|
evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Unknown address family, handle as error
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self->m_Callbacks->OnNameResolved(Self->m_Hostname, IP);
|
||||||
|
HasResolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If only unsupported families were reported, call the Error handler:
|
||||||
|
if (!HasResolved)
|
||||||
|
{
|
||||||
|
Self->m_Callbacks->OnError(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Self->m_Callbacks->OnFinished();
|
||||||
|
}
|
||||||
|
cNetworkSingleton::Get().RemoveHostnameLookup(Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cTCPLinkImpl:
|
// cTCPLinkImpl:
|
||||||
|
|
||||||
@ -716,9 +823,15 @@ bool cNetworkSingleton::HostnameToIP(
|
|||||||
cNetwork::cResolveNameCallbacksPtr a_Callbacks
|
cNetwork::cResolveNameCallbacksPtr a_Callbacks
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// TODO
|
try
|
||||||
ASSERT(!"Not implemented yet!");
|
{
|
||||||
return false;
|
m_HostnameLookups.push_back(std::make_shared<cHostnameLookup>(a_Hostname, a_Callbacks));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -765,3 +878,18 @@ void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cNetworkSingleton::RemoveHostnameLookup(cHostnameLookup * a_HostnameLookup)
|
||||||
|
{
|
||||||
|
for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (itr->get() == a_HostnameLookup)
|
||||||
|
{
|
||||||
|
m_HostnameLookups.erase(itr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // for itr - m_HostnameLookups[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,11 +148,18 @@ public:
|
|||||||
// Force a virtual destructor for all descendants:
|
// Force a virtual destructor for all descendants:
|
||||||
virtual ~cResolveNameCallbacks() {}
|
virtual ~cResolveNameCallbacks() {}
|
||||||
|
|
||||||
/** Called when the hostname is successfully resolved into an IP address. */
|
/** Called when the hostname is successfully resolved into an IP address.
|
||||||
|
May be called multiple times if an address resolves to multiple addresses.
|
||||||
|
a_IP may be either an IPv4 or an IPv6 address with their proper formatting. */
|
||||||
virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) = 0;
|
virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) = 0;
|
||||||
|
|
||||||
/** Called when an error is encountered while resolving. */
|
/** Called when an error is encountered while resolving.
|
||||||
|
If an error is reported, the OnFinished() callback is not called. */
|
||||||
virtual void OnError(int a_ErrorCode) = 0;
|
virtual void OnError(int a_ErrorCode) = 0;
|
||||||
|
|
||||||
|
/** Called when all the addresses resolved have been reported via the OnNameResolved() callback.
|
||||||
|
Only called if there was no error reported. */
|
||||||
|
virtual void OnFinished(void) = 0;
|
||||||
};
|
};
|
||||||
typedef SharedPtr<cResolveNameCallbacks> cResolveNameCallbacksPtr;
|
typedef SharedPtr<cResolveNameCallbacks> cResolveNameCallbacksPtr;
|
||||||
|
|
||||||
|
@ -8,7 +8,16 @@ include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include)
|
|||||||
add_definitions(-DTEST_GLOBALS=1)
|
add_definitions(-DTEST_GLOBALS=1)
|
||||||
add_library(Network ${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp)
|
add_library(Network ${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp)
|
||||||
target_link_libraries(Network event_core event_extra)
|
target_link_libraries(Network event_core event_extra)
|
||||||
|
if (MSVC)
|
||||||
|
target_link_libraries(Network ws2_32.lib)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(Google-exe Google.cpp)
|
add_executable(Google-exe Google.cpp)
|
||||||
target_link_libraries(Google-exe Network)
|
target_link_libraries(Google-exe Network)
|
||||||
add_test(NAME Google-test COMMAND Google-exe)
|
add_test(NAME Google-test COMMAND Google-exe)
|
||||||
|
|
||||||
|
add_executable(EchoServer EchoServer.cpp)
|
||||||
|
target_link_libraries(EchoServer Network)
|
||||||
|
|
||||||
|
add_executable(NameLookup NameLookup.cpp)
|
||||||
|
target_link_libraries(NameLookup Network)
|
||||||
|
19
tests/Network/EchoServer.cpp
Normal file
19
tests/Network/EchoServer.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
// EchoServer.cpp
|
||||||
|
|
||||||
|
// Implements an Echo server using the LibEvent-based cNetwork API, as a test of that API
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
|||||||
|
|
||||||
|
// Google.cpp
|
||||||
|
|
||||||
|
// Implements a HTTP download of the google's front page using the LibEvent-based cNetwork API
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include "OSSupport/Event.h"
|
#include "OSSupport/Event.h"
|
||||||
|
|
||||||
#include "OSSupport/Network.h"
|
#include "OSSupport/Network.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Connect callbacks that send a HTTP GET request for google.com when connected. */
|
/** Connect callbacks that send a HTTP GET request for google.com when connected. */
|
||||||
class cHTTPConnectCallbacks:
|
class cHTTPConnectCallbacks:
|
||||||
public cNetwork::cConnectCallbacks
|
public cNetwork::cConnectCallbacks
|
||||||
@ -35,6 +41,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** cTCPLink callbacks that dump everything it received to the log. */
|
/** cTCPLink callbacks that dump everything it received to the log. */
|
||||||
class cDumpCallbacks:
|
class cDumpCallbacks:
|
||||||
public cTCPLink::cCallbacks
|
public cTCPLink::cCallbacks
|
||||||
@ -69,7 +78,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
cEvent evtFinish;
|
cEvent evtFinish;
|
||||||
|
|
||||||
LOGD("Network test: Connecting to google.com:80, reading front page via HTTP.");
|
LOGD("Network test: Connecting to google.com:80, reading front page via HTTP.");
|
||||||
@ -83,3 +96,7 @@ int main() {
|
|||||||
evtFinish.Wait();
|
evtFinish.Wait();
|
||||||
LOGD("Network test finished");
|
LOGD("Network test finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
67
tests/Network/NameLookup.cpp
Normal file
67
tests/Network/NameLookup.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
// NameLookup.cpp
|
||||||
|
|
||||||
|
// Implements a DNS name lookup using the LibEvent-based cNetwork API
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include <thread>
|
||||||
|
#include "OSSupport/Event.h"
|
||||||
|
#include "OSSupport/Network.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cFinishLookupCallbacks:
|
||||||
|
public cNetwork::cResolveNameCallbacks
|
||||||
|
{
|
||||||
|
cEvent & m_Event;
|
||||||
|
|
||||||
|
virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override
|
||||||
|
{
|
||||||
|
LOGD("%s resolves to IP %s", a_Name.c_str(), a_IP.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnError(int a_ErrorCode) override
|
||||||
|
{
|
||||||
|
LOGD("Error %d while performing lookup!", a_ErrorCode);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnFinished(void) override
|
||||||
|
{
|
||||||
|
LOGD("Resolving finished.");
|
||||||
|
m_Event.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
cFinishLookupCallbacks(cEvent & a_Event):
|
||||||
|
m_Event(a_Event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cEvent evtFinish;
|
||||||
|
|
||||||
|
LOGD("Network test: Looking up google.com");
|
||||||
|
if (!cNetwork::HostnameToIP("google.com", std::make_shared<cFinishLookupCallbacks>(evtFinish)))
|
||||||
|
{
|
||||||
|
LOGWARNING("Cannot resolve google.com");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
LOGD("Name lookup has been successfully queued");
|
||||||
|
|
||||||
|
evtFinish.Wait();
|
||||||
|
LOGD("Network test finished");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user