1
0

cNetwork: Implemented IP-to-hostname lookup.

This commit is contained in:
Mattes D 2015-01-11 12:59:07 +01:00
parent fde44cba08
commit 251c96952b
2 changed files with 130 additions and 11 deletions

View File

@ -123,7 +123,7 @@ public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Class definitions: // Class definitions:
/** Holds information about an in-progress hostname lookup. */ /** Holds information about an in-progress Hostname-to-IP lookup. */
class cHostnameLookup class cHostnameLookup
{ {
/** The callbacks to call for resolved names / errors. */ /** The callbacks to call for resolved names / errors. */
@ -144,6 +144,27 @@ typedef std::vector<cHostnameLookupPtr> cHostnameLookupPtrs;
/** Holds information about an in-progress IP-to-Hostname lookup. */
class cIPLookup
{
/** The callbacks to call for resolved names / errors. */
cNetwork::cResolveNameCallbacksPtr m_Callbacks;
/** The IP that was queried (needed for the callbacks). */
AString m_IP;
static void Callback(int a_Result, char a_Type, int a_Count, int a_Ttl, void * a_Addresses, void * a_Self);
public:
cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks);
};
typedef SharedPtr<cIPLookup> cIPLookupPtr;
typedef std::vector<cIPLookupPtr> cIPLookupPtrs;
/** 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
@ -236,6 +257,7 @@ typedef std::vector<cServerHandleImplPtr> cServerHandleImplPtrs;
class cNetworkSingleton class cNetworkSingleton
{ {
friend class cHostnameLookup; // Needs access to m_DNSBase friend class cHostnameLookup; // Needs access to m_DNSBase
friend class cIPLookup; // Needs access to m_DNSBase
friend class cTCPLinkImpl; // Needs access to m_EventBase and m_DNSBase friend class cTCPLinkImpl; // Needs access to m_EventBase and m_DNSBase
public: public:
@ -305,6 +327,9 @@ protected:
/** Container for all pending hostname lookups. */ /** Container for all pending hostname lookups. */
cHostnameLookupPtrs m_HostnameLookups; cHostnameLookupPtrs m_HostnameLookups;
/** Container for all pending IP lookups. */
cIPLookupPtrs m_IPLookups;
/** Initializes the LibEvent internals. */ /** Initializes the LibEvent internals. */
cNetworkSingleton(void); cNetworkSingleton(void);
@ -315,8 +340,13 @@ 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. */ /** Removes the specified hostname lookup from m_HostnameLookups.
void RemoveHostnameLookup(cHostnameLookup * a_HostnameLookup); Used by the underlying lookup implementation when the lookup is finished. */
void RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup);
/** Removes the specified IP lookup from m_IPLookups.
Used by the underlying lookup implementation when the lookup is finished. */
void RemoveIPLookup(const cIPLookup * a_IPLookup);
}; };
@ -343,7 +373,7 @@ cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveN
void cHostnameLookup::Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, void * a_Self) void cHostnameLookup::Callback(int a_ErrCode, evutil_addrinfo * a_Addr, void * a_Self)
{ {
// Get the Self class: // Get the Self class:
cHostnameLookup * Self = reinterpret_cast<cHostnameLookup *>(a_Self); cHostnameLookup * Self = reinterpret_cast<cHostnameLookup *>(a_Self);
@ -359,6 +389,7 @@ void cHostnameLookup::Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, v
// Call the success handler for each entry received: // Call the success handler for each entry received:
bool HasResolved = false; bool HasResolved = false;
evutil_addrinfo * OrigAddr = a_Addr;
for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next) for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next)
{ {
char IP[128]; char IP[128];
@ -395,6 +426,7 @@ void cHostnameLookup::Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, v
{ {
Self->m_Callbacks->OnFinished(); Self->m_Callbacks->OnFinished();
} }
evutil_freeaddrinfo(OrigAddr);
cNetworkSingleton::Get().RemoveHostnameLookup(Self); cNetworkSingleton::Get().RemoveHostnameLookup(Self);
} }
@ -402,6 +434,57 @@ void cHostnameLookup::Callback(int a_ErrCode, struct evutil_addrinfo * a_Addr, v
////////////////////////////////////////////////////////////////////////////////
// cIPLookup:
cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks):
m_Callbacks(a_Callbacks),
m_IP(a_IP)
{
sockaddr_storage sa;
int salen = static_cast<int>(sizeof(sa));
evutil_parse_sockaddr_port(a_IP.c_str(), reinterpret_cast<sockaddr *>(&sa), &salen);
switch (sa.ss_family)
{
case AF_INET:
{
sockaddr_in * sa4 = reinterpret_cast<sockaddr_in *>(&sa);
evdns_base_resolve_reverse(cNetworkSingleton::Get().m_DNSBase, &(sa4->sin_addr), 0, Callback, this);
}
case AF_INET6:
{
}
}
}
void cIPLookup::Callback(int a_Result, char a_Type, int a_Count, int a_Ttl, void * a_Addresses, void * a_Self)
{
// Get the Self class:
cIPLookup * Self = reinterpret_cast<cIPLookup *>(a_Self);
ASSERT(Self != nullptr);
if ((a_Result != 0) || (a_Addresses == nullptr))
{
// An error has occurred, notify the error callback:
Self->m_Callbacks->OnError(a_Result);
}
else
{
// Call the success handler::
Self->m_Callbacks->OnNameResolved(*(reinterpret_cast<char **>(a_Addresses)), Self->m_IP);
Self->m_Callbacks->OnFinished();
}
cNetworkSingleton::Get().RemoveIPLookup(Self);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// cTCPLinkImpl: // cTCPLinkImpl:
@ -842,9 +925,15 @@ bool cNetworkSingleton::IPToHostName(
cNetwork::cResolveNameCallbacksPtr a_Callbacks cNetwork::cResolveNameCallbacksPtr a_Callbacks
) )
{ {
// TODO try
ASSERT(!"Not implemented yet!"); {
return false; m_IPLookups.push_back(std::make_shared<cIPLookup>(a_IP, a_Callbacks));
}
catch (...)
{
return false;
}
return true;
} }
@ -878,7 +967,8 @@ void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self)
void cNetworkSingleton::RemoveHostnameLookup(cHostnameLookup * a_HostnameLookup)
void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup)
{ {
for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr) for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr)
{ {
@ -893,3 +983,19 @@ void cNetworkSingleton::RemoveHostnameLookup(cHostnameLookup * a_HostnameLookup)
void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup)
{
for (auto itr = m_IPLookups.begin(), end = m_IPLookups.end(); itr != end; ++itr)
{
if (itr->get() == a_IPLookup)
{
m_IPLookups.erase(itr);
return;
}
} // for itr - m_HostnameLookups[]
}

View File

@ -25,7 +25,7 @@ class cFinishLookupCallbacks:
virtual void OnError(int a_ErrorCode) override virtual void OnError(int a_ErrorCode) override
{ {
LOGD("Error %d while performing lookup!", a_ErrorCode); LOGD("Error %d while performing lookup!", a_ErrorCode);
abort(); exit(a_ErrorCode);
} }
virtual void OnFinished(void) override virtual void OnFinished(void) override
@ -49,15 +49,28 @@ int main()
{ {
cEvent evtFinish; cEvent evtFinish;
// Look up google.com (has multiple IP addresses):
LOGD("Network test: Looking up google.com"); LOGD("Network test: Looking up google.com");
if (!cNetwork::HostnameToIP("google.com", std::make_shared<cFinishLookupCallbacks>(evtFinish))) if (!cNetwork::HostnameToIP("google.com", std::make_shared<cFinishLookupCallbacks>(evtFinish)))
{ {
LOGWARNING("Cannot resolve google.com"); LOGWARNING("Cannot resolve google.com to IP");
abort(); abort();
} }
LOGD("Name lookup has been successfully queued"); LOGD("Name lookup has been successfully queued");
evtFinish.Wait(); evtFinish.Wait();
LOGD("Lookup finished.");
// 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)))
{
LOGWARNING("Cannot resolve 8.8.8.8 to name");
abort();
}
LOGD("IP lookup has been successfully queued");
evtFinish.Wait();
LOGD("IP lookup finished.");
LOGD("Network test finished"); LOGD("Network test finished");
return 0; return 0;
} }