From d3076a3e1664c6a6e7c0d4cf24ac4335bb0a3899 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 17 Jan 2015 23:33:59 +0100 Subject: cNetwork: Split cNetworkSingleton to a separate file. --- src/OSSupport/NetworkSingleton.cpp | 281 +++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 src/OSSupport/NetworkSingleton.cpp (limited to 'src/OSSupport/NetworkSingleton.cpp') diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp new file mode 100644 index 000000000..552abad64 --- /dev/null +++ b/src/OSSupport/NetworkSingleton.cpp @@ -0,0 +1,281 @@ + +// NetworkSingleton.cpp + +// Implements the cNetworkSingleton class representing the storage for global data pertaining to network API +// such as a list of all connections, all listening sockets and the LibEvent dispatch thread. + +#include "Globals.h" +#include "NetworkSingleton.h" +#include +#include +#include +#include +#include + + + + + +//////////////////////////////////////////////////////////////////////////////// +// Class definitions: + +/** Holds information about an in-progress Hostname-to-IP 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 cHostnameLookupPtr; +typedef std::vector 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 cIPLookupPtr; +typedef std::vector cIPLookupPtrs; + + + + + +cNetworkSingleton::cNetworkSingleton(void) +{ + // Windows: initialize networking: + #ifdef _WIN32 + WSADATA wsaData; + memset(&wsaData, 0, sizeof(wsaData)); + int res = WSAStartup (MAKEWORD(2, 2), &wsaData); + if (res != 0) + { + int err = WSAGetLastError(); + LOGWARNING("WSAStartup failed: %d, WSAGLE = %d (%s)", res, err, evutil_socket_error_to_string(err)); + exit(1); + } + #endif // _WIN32 + + // Initialize LibEvent logging: + event_set_log_callback(LogCallback); + + // Initialize threading: + #if defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED) + evthread_use_windows_threads(); + #elif defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) + evthread_use_pthreads(); + #else + #error No threading implemented for EVTHREAD + #endif + + // Create the main event_base: + m_EventBase = event_base_new(); + if (m_EventBase == nullptr) + { + LOGERROR("Failed to initialize LibEvent. The server will now terminate."); + abort(); + } + + // Create the DNS lookup helper: + m_DNSBase = evdns_base_new(m_EventBase, 1); + if (m_DNSBase == nullptr) + { + LOGERROR("Failed to initialize LibEvent's DNS subsystem. The server will now terminate."); + abort(); + } + + // Create the event loop thread: + std::thread EventLoopThread(RunEventLoop, this); + EventLoopThread.detach(); +} + + + + + +cNetworkSingleton & cNetworkSingleton::Get(void) +{ + static cNetworkSingleton Instance; + return Instance; +} + + + + + +bool cNetworkSingleton::HostnameToIP( + const AString & a_Hostname, + cNetwork::cResolveNameCallbacksPtr a_Callbacks +) +{ + try + { + cCSLock Lock(m_CS); + m_HostnameLookups.push_back(std::make_shared(a_Hostname, a_Callbacks)); + } + catch (...) + { + return false; + } + return true; +} + + + + +bool cNetworkSingleton::IPToHostName( + const AString & a_IP, + cNetwork::cResolveNameCallbacksPtr a_Callbacks +) +{ + try + { + cCSLock Lock(m_CS); + m_IPLookups.push_back(std::make_shared(a_IP, a_Callbacks)); + } + catch (...) + { + return false; + } + return true; +} + + + + +void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) +{ + switch (a_Severity) + { + case _EVENT_LOG_DEBUG: LOGD ("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_MSG: LOG ("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_WARN: LOGWARNING("LibEvent: %s", a_Msg); break; + case _EVENT_LOG_ERR: LOGERROR ("LibEvent: %s", a_Msg); break; + default: + { + LOGWARNING("LibEvent: Unknown log severity (%d): %s", a_Severity, a_Msg); + break; + } + } +} + + + + + +void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) +{ + event_base_loop(a_Self->m_EventBase, EVLOOP_NO_EXIT_ON_EMPTY); +} + + + + + +void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup) +{ + cCSLock Lock(m_CS); + 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[] +} + + + + + +void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) +{ + cCSLock Lock(m_CS); + 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_IPLookups[] +} + + + + + +void cNetworkSingleton::AddLink(cTCPLinkImplPtr a_Link) +{ + cCSLock Lock(m_CS); + m_Connections.push_back(a_Link); +} + + + + + +void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link) +{ + cCSLock Lock(m_CS); + for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) + { + if (itr->get() == a_Link) + { + m_Connections.erase(itr); + return; + } + } // for itr - m_Connections[] +} + + + + + +void cNetworkSingleton::AddServer(cServerHandleImplPtr a_Server) +{ + cCSLock Lock(m_CS); + m_Servers.push_back(a_Server); +} + + + + + +void cNetworkSingleton::RemoveServer(const cServerHandleImpl * a_Server) +{ + cCSLock Lock(m_CS); + for (auto itr = m_Servers.begin(), end = m_Servers.end(); itr != end; ++itr) + { + if (itr->get() == a_Server) + { + m_Servers.erase(itr); + return; + } + } // for itr - m_Servers[] +} + + + + -- cgit v1.2.3 From c0cb787c101725a649d26de68fca2632c82830ba Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 18 Jan 2015 11:57:16 +0100 Subject: cNetwork: Split the main cpp file into several files. --- src/OSSupport/NetworkSingleton.cpp | 51 +++++--------------------------------- 1 file changed, 6 insertions(+), 45 deletions(-) (limited to 'src/OSSupport/NetworkSingleton.cpp') diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp index 552abad64..c9d9b1d81 100644 --- a/src/OSSupport/NetworkSingleton.cpp +++ b/src/OSSupport/NetworkSingleton.cpp @@ -11,51 +11,8 @@ #include #include #include - - - - - -//////////////////////////////////////////////////////////////////////////////// -// Class definitions: - -/** Holds information about an in-progress Hostname-to-IP 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 cHostnameLookupPtr; -typedef std::vector 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 cIPLookupPtr; -typedef std::vector cIPLookupPtrs; +#include "IPLookup.h" +#include "HostnameLookup.h" @@ -130,6 +87,8 @@ bool cNetworkSingleton::HostnameToIP( { try { + // TODO: This has a race condition with possible memory leak: + // If a lookup finishes immediately, the constructor calls the removal before this addition cCSLock Lock(m_CS); m_HostnameLookups.push_back(std::make_shared(a_Hostname, a_Callbacks)); } @@ -150,6 +109,8 @@ bool cNetworkSingleton::IPToHostName( { try { + // TODO: This has a race condition with possible memory leak: + // If a lookup finishes immediately, the constructor calls the removal before this addition cCSLock Lock(m_CS); m_IPLookups.push_back(std::make_shared(a_IP, a_Callbacks)); } -- cgit v1.2.3 From d4682463a1d503c349ac95e275b11d67d402268c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 18 Jan 2015 12:35:02 +0100 Subject: cNetwork: Fixed race conditions with lookups; proper shutdown. --- src/OSSupport/NetworkSingleton.cpp | 77 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 38 deletions(-) (limited to 'src/OSSupport/NetworkSingleton.cpp') diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp index c9d9b1d81..8c38fb4eb 100644 --- a/src/OSSupport/NetworkSingleton.cpp +++ b/src/OSSupport/NetworkSingleton.cpp @@ -70,60 +70,40 @@ cNetworkSingleton::cNetworkSingleton(void) -cNetworkSingleton & cNetworkSingleton::Get(void) +cNetworkSingleton::~cNetworkSingleton() { - static cNetworkSingleton Instance; - return Instance; -} - + // Wait for the LibEvent event loop to terminate: + event_base_loopbreak(m_EventBase); + m_EventLoopTerminated.Wait(); - - - -bool cNetworkSingleton::HostnameToIP( - const AString & a_Hostname, - cNetwork::cResolveNameCallbacksPtr a_Callbacks -) -{ - try + // Remove all objects: { - // TODO: This has a race condition with possible memory leak: - // If a lookup finishes immediately, the constructor calls the removal before this addition cCSLock Lock(m_CS); - m_HostnameLookups.push_back(std::make_shared(a_Hostname, a_Callbacks)); + m_Connections.clear(); + m_Servers.clear(); + m_HostnameLookups.clear(); + m_IPLookups.clear(); } - catch (...) - { - return false; - } - return true; + + // Free the underlying LibEvent objects: + evdns_base_free(m_DNSBase, true); + event_base_free(m_EventBase); } -bool cNetworkSingleton::IPToHostName( - const AString & a_IP, - cNetwork::cResolveNameCallbacksPtr a_Callbacks -) + +cNetworkSingleton & cNetworkSingleton::Get(void) { - try - { - // TODO: This has a race condition with possible memory leak: - // If a lookup finishes immediately, the constructor calls the removal before this addition - cCSLock Lock(m_CS); - m_IPLookups.push_back(std::make_shared(a_IP, a_Callbacks)); - } - catch (...) - { - return false; - } - return true; + static cNetworkSingleton Instance; + return Instance; } + void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) { switch (a_Severity) @@ -147,6 +127,17 @@ void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) { event_base_loop(a_Self->m_EventBase, EVLOOP_NO_EXIT_ON_EMPTY); + a_Self->m_EventLoopTerminated.Set(); +} + + + + + +void cNetworkSingleton::AddHostnameLookup(cHostnameLookupPtr a_HostnameLookup) +{ + cCSLock Lock(m_CS); + m_HostnameLookups.push_back(a_HostnameLookup); } @@ -170,6 +161,16 @@ void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameL +void cNetworkSingleton::AddIPLookup(cIPLookupPtr a_IPLookup) +{ + cCSLock Lock(m_CS); + m_IPLookups.push_back(a_IPLookup); +} + + + + + void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) { cCSLock Lock(m_CS); -- cgit v1.2.3 From 10cfa61fbc5d0720f4e4864f50f1298937327348 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 23 Jan 2015 23:01:18 +0100 Subject: cNetwork: Added self pointers to keep objects alive for callbacks. Ref.: http://forum.mc-server.org/showthread.php?tid=1700&pid=17947#pid17947 --- src/OSSupport/NetworkSingleton.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/OSSupport/NetworkSingleton.cpp') diff --git a/src/OSSupport/NetworkSingleton.cpp b/src/OSSupport/NetworkSingleton.cpp index 8c38fb4eb..92f0604cd 100644 --- a/src/OSSupport/NetworkSingleton.cpp +++ b/src/OSSupport/NetworkSingleton.cpp @@ -88,6 +88,8 @@ cNetworkSingleton::~cNetworkSingleton() // Free the underlying LibEvent objects: evdns_base_free(m_DNSBase, true); event_base_free(m_EventBase); + + libevent_global_shutdown(); } -- cgit v1.2.3