diff options
author | Shauren <shauren.trinity@gmail.com> | 2018-01-06 01:21:59 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2018-01-06 01:21:59 +0100 |
commit | dfd2660a85e4f0891c63009ee8425b2796586409 (patch) | |
tree | 26704dff3840402765ada5e6e4549a48b95ed82b /src | |
parent | 76577ddc3ca4edd5943777443d9cf5a4c5314e10 (diff) |
Core/Misc: Added compatibility layer for boost 1.66 and future std:: networking stuff
* Based on work done by @dimiandre in PR #21173
Closes #21171
Closes #21173
Diffstat (limited to 'src')
32 files changed, 469 insertions, 187 deletions
diff --git a/src/common/Utilities/AsioHacksFwd.h b/src/common/Asio/AsioHacksFwd.h index 113e41ac585..457f53f39b1 100644 --- a/src/common/Utilities/AsioHacksFwd.h +++ b/src/common/Asio/AsioHacksFwd.h @@ -18,6 +18,11 @@ #ifndef AsioHacksFwd_h__ #define AsioHacksFwd_h__ +#include <boost/version.hpp> + +/** + Collection of forward declarations to improve compile time + */ namespace boost { namespace posix_time @@ -27,6 +32,9 @@ namespace boost namespace asio { + template <typename Time> + struct time_traits; + namespace ip { class address; @@ -37,19 +45,22 @@ namespace boost class basic_endpoint; typedef basic_endpoint<tcp> tcp_endpoint; + } - template <typename InternetProtocol> - class resolver_service; - - template <typename InternetProtocol, typename ResolverService> - class basic_resolver; +#if BOOST_VERSION >= 106600 + template <typename Time, typename TimeTraits> + class basic_deadline_timer; - typedef basic_resolver<tcp, resolver_service<tcp>> tcp_resolver; - } + typedef basic_deadline_timer<posix_time::ptime, time_traits<posix_time::ptime>> deadline_timer; - template <typename Time> - struct time_traits; + namespace ip + { + template <typename InternetProtocol> + class basic_resolver; + typedef basic_resolver<tcp> tcp_resolver; + } +#else template <typename TimeType, typename TimeTraits> class deadline_timer_service; @@ -57,12 +68,27 @@ namespace boost class basic_deadline_timer; typedef basic_deadline_timer<posix_time::ptime, time_traits<posix_time::ptime>, deadline_timer_service<posix_time::ptime, time_traits<posix_time::ptime>>> deadline_timer; + + namespace ip + { + template <typename InternetProtocol> + class resolver_service; + + template <typename InternetProtocol, typename ResolverService> + class basic_resolver; + + typedef basic_resolver<tcp, resolver_service<tcp>> tcp_resolver; + } +#endif } } namespace Trinity { - class AsioStrand; + namespace Asio + { + class Strand; + } } #endif // AsioHacksFwd_h__ diff --git a/src/common/Asio/IoContext.h b/src/common/Asio/IoContext.h new file mode 100644 index 00000000000..50411b76957 --- /dev/null +++ b/src/common/Asio/IoContext.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IoContext_h__ +#define IoContext_h__ + +#include <boost/version.hpp> + +#if BOOST_VERSION >= 106600 +#include <boost/asio/io_context.hpp> +#include <boost/asio/post.hpp> +#define IoContextBaseNamespace boost::asio +#define IoContextBase io_context +#else +#include <boost/asio/io_service.hpp> +#define IoContextBaseNamespace boost::asio +#define IoContextBase io_service +#endif + +namespace Trinity +{ + namespace Asio + { + class IoContext : public IoContextBaseNamespace::IoContextBase + { + using IoContextBaseNamespace::IoContextBase::IoContextBase; + }; + + template<typename T> + inline decltype(auto) post(IoContextBaseNamespace::IoContextBase& ioContext, T&& t) + { +#if BOOST_VERSION >= 106600 + return boost::asio::post(ioContext, std::forward<T>(t)); +#else + return ioContext.post(std::forward<T>(t)); +#endif + } + + template<typename T> + inline decltype(auto) get_io_context(T&& ioObject) + { +#if BOOST_VERSION >= 106600 + return ioObject.get_executor().context(); +#else + return ioObject.get_io_service(); +#endif + } + } +} + +#endif // IoContext_h__ diff --git a/src/common/Asio/IpAddress.h b/src/common/Asio/IpAddress.h new file mode 100644 index 00000000000..a4994012036 --- /dev/null +++ b/src/common/Asio/IpAddress.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IpAddress_h__ +#define IpAddress_h__ + +#include "Define.h" +#include <boost/asio/ip/address.hpp> + +namespace Trinity +{ + namespace Net + { +#if BOOST_VERSION >= 106600 + using boost::asio::ip::make_address; + using boost::asio::ip::make_address_v4; + inline uint32 address_to_uint(boost::asio::ip::address_v4 const& address) { return address.to_uint(); } +#else + inline boost::asio::ip::address make_address(char const* str) { return boost::asio::ip::address::from_string(str); } + inline boost::asio::ip::address make_address(char const* str, boost::system::error_code& ec) { return boost::asio::ip::address::from_string(str, ec); } + inline boost::asio::ip::address make_address(std::string const& str) { return boost::asio::ip::address::from_string(str); } + inline boost::asio::ip::address make_address(std::string const& str, boost::system::error_code& ec) { return boost::asio::ip::address::from_string(str, ec); } + inline boost::asio::ip::address_v4 make_address_v4(char const* str) { return boost::asio::ip::address_v4::from_string(str); } + inline boost::asio::ip::address_v4 make_address_v4(char const* str, boost::system::error_code& ec) { return boost::asio::ip::address_v4::from_string(str, ec); } + inline boost::asio::ip::address_v4 make_address_v4(std::string const& str) { return boost::asio::ip::address_v4::from_string(str); } + inline boost::asio::ip::address_v4 make_address_v4(std::string const& str, boost::system::error_code& ec) { return boost::asio::ip::address_v4::from_string(str, ec); } + inline uint32 address_to_uint(boost::asio::ip::address_v4 const& address) { return address.to_ulong(); } +#endif + } +} + +#endif // IpAddress_h__ diff --git a/src/common/Asio/IpNetwork.h b/src/common/Asio/IpNetwork.h new file mode 100644 index 00000000000..bdd3c1dc683 --- /dev/null +++ b/src/common/Asio/IpNetwork.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IpNetwork_h__ +#define IpNetwork_h__ + +#include "Define.h" +#include "IpAddress.h" +#include <boost/version.hpp> +#if BOOST_VERSION >= 106600 +#include <boost/asio/ip/network_v4.hpp> +#include <boost/asio/ip/network_v6.hpp> +#endif + +namespace Trinity +{ + namespace Net + { + inline bool IsInNetwork(boost::asio::ip::address_v4 const& networkAddress, boost::asio::ip::address_v4 const& mask, boost::asio::ip::address_v4 const& clientAddress) + { +#if BOOST_VERSION >= 106600 + boost::asio::ip::network_v4 network = boost::asio::ip::make_network_v4(networkAddress, mask); + boost::asio::ip::address_v4_range hosts = network.hosts(); + return hosts.find(clientAddress) != hosts.end(); +#else + return (clientAddress.to_ulong() & mask.to_ulong()) == (networkAddress.to_ulong() & mask.to_ulong()); +#endif + } + + inline boost::asio::ip::address_v4 GetDefaultNetmaskV4(boost::asio::ip::address_v4 const& networkAddress) + { + if ((address_to_uint(networkAddress) & 0x80000000) == 0) + return boost::asio::ip::address_v4(0xFF000000); + if ((address_to_uint(networkAddress) & 0xC0000000) == 0x80000000) + return boost::asio::ip::address_v4(0xFFFF0000); + if ((address_to_uint(networkAddress) & 0xE0000000) == 0xC0000000) + return boost::asio::ip::address_v4(0xFFFFFF00); + return boost::asio::ip::address_v4(0xFFFFFFFF); + } + + inline bool IsInNetwork(boost::asio::ip::address_v6 const& networkAddress, uint16 prefixLength, boost::asio::ip::address_v6 const& clientAddress) + { +#if BOOST_VERSION >= 106600 + boost::asio::ip::network_v6 network = boost::asio::ip::make_network_v6(networkAddress, prefixLength); + boost::asio::ip::address_v6_range hosts = network.hosts(); + return hosts.find(clientAddress) != hosts.end(); +#else + (void)networkAddress; + (void)prefixLength; + (void)clientAddress; + return false; +#endif + } + } +} + +#endif // IpNetwork_h__ diff --git a/src/common/Asio/Resolver.h b/src/common/Asio/Resolver.h new file mode 100644 index 00000000000..5106421ee5e --- /dev/null +++ b/src/common/Asio/Resolver.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Resolver_h__ +#define Resolver_h__ + +#include "Optional.h" +#include <boost/asio/ip/tcp.hpp> +#include <string> + +namespace Trinity +{ + namespace Net + { + inline Optional<boost::asio::ip::tcp::endpoint> Resolve(boost::asio::ip::tcp::resolver& resolver, boost::asio::ip::tcp const& protocol, + std::string const& host, std::string const& service) + { + boost::system::error_code ec; +#if BOOST_VERSION >= 106600 + boost::asio::ip::tcp::resolver::results_type results = resolver.resolve(protocol, host, service, ec); + if (results.empty() || ec) + return {}; + + return results.begin()->endpoint(); +#else + boost::asio::ip::tcp::resolver::query query(std::move(protocol), std::move(host), std::move(service)); + boost::asio::ip::tcp::resolver::iterator itr = resolver.resolve(query, ec); + boost::asio::ip::tcp::resolver::iterator end; + if (itr == end || ec) + return {}; + + return itr->endpoint(); +#endif + } + } +} + +#endif // Resolver_h__ diff --git a/src/common/Utilities/AsioHacksImpl.h b/src/common/Asio/Strand.h index 458c6f76c2b..2b69c02f7bd 100644 --- a/src/common/Utilities/AsioHacksImpl.h +++ b/src/common/Asio/Strand.h @@ -15,18 +15,39 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef AsioHacksImpl_h__ -#define AsioHacksImpl_h__ +#ifndef Strand_h__ +#define Strand_h__ +#include "IoContext.h" #include <boost/asio/strand.hpp> +#if BOOST_VERSION >= 106600 +#include <boost/asio/bind_executor.hpp> +#endif + namespace Trinity { - class AsioStrand : public boost::asio::io_service::strand + namespace Asio { - public: - AsioStrand(boost::asio::io_service& io_service) : boost::asio::io_service::strand(io_service) { } - }; + /** + Hack to make it possible to forward declare strand (which is a inner class) + */ + class Strand : public IoContextBaseNamespace::IoContextBase::strand + { + public: + Strand(IoContext& ioContext) : IoContextBaseNamespace::IoContextBase::strand(ioContext) { } + }; + +#if BOOST_VERSION >= 106600 + using boost::asio::bind_executor; +#else + template<typename T> + inline decltype(auto) bind_executor(Strand& strand, T&& t) + { + return strand.wrap(std::forward<T>(t)); + } +#endif + } } -#endif // AsioHacksImpl_h__ +#endif // Strand_h__ diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index de9caf08581..3ce0307a96b 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -19,18 +19,18 @@ #include "Log.h" #include "AppenderConsole.h" #include "AppenderFile.h" -#include "AsioHacksImpl.h" #include "Common.h" #include "Config.h" #include "Errors.h" #include "Logger.h" #include "LogMessage.h" #include "LogOperation.h" +#include "Strand.h" #include "Util.h" #include <chrono> #include <sstream> -Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioService(nullptr), _strand(nullptr) +Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioContext(nullptr), _strand(nullptr) { m_logsTimestamp = "_" + GetTimestampStr(); RegisterAppender<AppenderConsole>(); @@ -228,11 +228,10 @@ void Log::write(std::unique_ptr<LogMessage>&& msg) const { Logger const* logger = GetLoggerByType(msg->type); - if (_ioService) + if (_ioContext) { - auto logOperation = std::make_shared<LogOperation>(logger, std::move(msg)); - - _ioService->post(_strand->wrap([logOperation](){ logOperation->call(); })); + std::shared_ptr<LogOperation> logOperation = std::make_shared<LogOperation>(logger, std::move(msg)); + Trinity::Asio::post(*_ioContext, Trinity::Asio::bind_executor(*_strand, [logOperation]() { logOperation->call(); })); } else logger->write(msg.get()); @@ -367,12 +366,12 @@ Log* Log::instance() return &instance; } -void Log::Initialize(boost::asio::io_service* ioService) +void Log::Initialize(Trinity::Asio::IoContext* ioContext) { - if (ioService) + if (ioContext) { - _ioService = ioService; - _strand = new Trinity::AsioStrand(*ioService); + _ioContext = ioContext; + _strand = new Trinity::Asio::Strand(*ioContext); } LoadFromConfig(); @@ -382,7 +381,7 @@ void Log::SetSynchronous() { delete _strand; _strand = nullptr; - _ioService = nullptr; + _ioContext = nullptr; } void Log::LoadFromConfig() diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index 7d70c1ea254..010ef62ce68 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -31,11 +31,11 @@ class Appender; class Logger; struct LogMessage; -namespace boost +namespace Trinity { - namespace asio + namespace Asio { - class io_service; + class IoContext; } } @@ -62,7 +62,7 @@ class TC_COMMON_API Log public: static Log* instance(); - void Initialize(boost::asio::io_service* ioService); + void Initialize(Trinity::Asio::IoContext* ioContext); void SetSynchronous(); // Not threadsafe - should only be called from main() after all threads are joined void LoadFromConfig(); void Close(); @@ -122,8 +122,8 @@ class TC_COMMON_API Log std::string m_logsDir; std::string m_logsTimestamp; - boost::asio::io_service* _ioService; - Trinity::AsioStrand* _strand; + Trinity::Asio::IoContext* _ioContext; + Trinity::Asio::Strand* _strand; }; #define sLog Log::instance() diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp index dd564b695f7..cd30f2e4b08 100644 --- a/src/common/Metric/Metric.cpp +++ b/src/common/Metric/Metric.cpp @@ -16,21 +16,21 @@ */ #include "Metric.h" -#include "AsioHacksImpl.h" #include "Common.h" #include "Config.h" #include "Log.h" +#include "Strand.h" #include "Util.h" #include <boost/algorithm/string/replace.hpp> #include <boost/asio/deadline_timer.hpp> #include <boost/asio/ip/tcp.hpp> -void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger) +void Metric::Initialize(std::string const& realmName, Trinity::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger) { _dataStream = Trinity::make_unique<boost::asio::ip::tcp::iostream>(); _realmName = FormatInfluxDBTagValue(realmName); - _batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); - _overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); + _batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioContext); + _overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioContext); _overallStatusLogger = overallStatusLogger; LoadFromConfigs(); } @@ -215,8 +215,8 @@ void Metric::ScheduleSend() void Metric::ForceSend() { - // Send what's queued only if io_service is stopped (so only on shutdown) - if (_enabled && _batchTimer->get_io_service().stopped()) + // Send what's queued only if IoContext is stopped (so only on shutdown) + if (_enabled && Trinity::Asio::get_io_context(*_batchTimer).stopped()) SendBatch(); } diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h index 1e1f8cf8e48..ae61b5f35d5 100644 --- a/src/common/Metric/Metric.h +++ b/src/common/Metric/Metric.h @@ -27,11 +27,11 @@ #include <memory> #include <string> -namespace boost +namespace Trinity { - namespace asio + namespace Asio { - class io_service; + class IoContext; } } @@ -95,7 +95,7 @@ public: ~Metric(); static Metric* instance(); - void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger); + void Initialize(std::string const& realmName, Trinity::Asio::IoContext& ioContext, std::function<void()> overallStatusLogger); void LoadFromConfigs(); void Update(); diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index b316db31bfd..f34989c8546 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -18,7 +18,7 @@ #include "Util.h" #include "Common.h" -#include <boost/asio/ip/address.hpp> +#include "IpAddress.h" #include <utf8.h> #include <algorithm> #include <sstream> @@ -216,7 +216,7 @@ bool IsIPAddress(char const* ipaddress) return false; boost::system::error_code error; - boost::asio::ip::address::from_string(ipaddress, error); + Trinity::Net::make_address(ipaddress, error); return !error; } diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index caf9326fbd6..05fef45f918 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -64,12 +64,12 @@ char serviceDescription[] = "TrinityCore Battle.net emulator authentication serv */ int m_ServiceStatus = -1; -void ServiceStatusWatcher(std::weak_ptr<boost::asio::deadline_timer> serviceStatusWatchTimerRef, std::weak_ptr<boost::asio::io_service> ioServiceRef, boost::system::error_code const& error); +void ServiceStatusWatcher(std::weak_ptr<boost::asio::deadline_timer> serviceStatusWatchTimerRef, std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error); #endif bool StartDB(); void StopDB(); -void SignalHandler(std::weak_ptr<boost::asio::io_service> ioServiceRef, boost::system::error_code const& error, int signalNumber); +void SignalHandler(std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error, int signalNumber); void KeepDatabaseAliveHandler(std::weak_ptr<boost::asio::deadline_timer> dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const& error); void BanExpiryHandler(std::weak_ptr<boost::asio::deadline_timer> banExpiryCheckTimerRef, int32 banExpiryCheckInterval, boost::system::error_code const& error); variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService); @@ -153,7 +153,7 @@ int main(int argc, char** argv) std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); }); - std::shared_ptr<boost::asio::io_service> ioService = std::make_shared<boost::asio::io_service>(); + std::shared_ptr<Trinity::Asio::IoContext> ioContext = std::make_shared<Trinity::Asio::IoContext>(); // Start the listening port (acceptor) for auth connections int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); @@ -163,7 +163,7 @@ int main(int argc, char** argv) return 1; } - if (!sLoginService.Start(ioService.get())) + if (!sLoginService.Start(ioContext.get())) { TC_LOG_ERROR("server.bnetserver", "Failed to initialize login service"); return 1; @@ -172,13 +172,13 @@ int main(int argc, char** argv) std::shared_ptr<void> sLoginServiceHandle(nullptr, [](void*) { sLoginService.Stop(); }); // Get the list of realms for the server - sRealmList->Initialize(*ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); + sRealmList->Initialize(*ioContext, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); std::shared_ptr<void> sRealmListHandle(nullptr, [](void*) { sRealmList->Close(); }); std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); - if (!sSessionMgr.StartNetwork(*ioService, bindIp, bnport)) + if (!sSessionMgr.StartNetwork(*ioContext, bindIp, bnport)) { TC_LOG_ERROR("server.bnetserver", "Failed to initialize network"); return 1; @@ -187,23 +187,23 @@ int main(int argc, char** argv) std::shared_ptr<void> sSessionMgrHandle(nullptr, [](void*) { sSessionMgr.StopNetwork(); }); // Set signal handlers - boost::asio::signal_set signals(*ioService, SIGINT, SIGTERM); + boost::asio::signal_set signals(*ioContext, SIGINT, SIGTERM); #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS signals.add(SIGBREAK); #endif - signals.async_wait(std::bind(&SignalHandler, std::weak_ptr<boost::asio::io_service>(ioService), std::placeholders::_1, std::placeholders::_2)); + signals.async_wait(std::bind(&SignalHandler, std::weak_ptr<Trinity::Asio::IoContext>(ioContext), std::placeholders::_1, std::placeholders::_2)); // Set process priority according to configuration settings SetProcessPriority("server.bnetserver", sConfigMgr->GetIntDefault(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetBoolDefault(CONFIG_HIGH_PRIORITY, false)); // Enabled a timed callback for handling the database keep alive ping int32 dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30); - std::shared_ptr<boost::asio::deadline_timer> dbPingTimer = std::make_shared<boost::asio::deadline_timer>(*ioService); + std::shared_ptr<boost::asio::deadline_timer> dbPingTimer = std::make_shared<boost::asio::deadline_timer>(*ioContext); dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval)); dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, std::weak_ptr<boost::asio::deadline_timer>(dbPingTimer), dbPingInterval, std::placeholders::_1)); int32 banExpiryCheckInterval = sConfigMgr->GetIntDefault("BanExpiryCheckInterval", 60); - std::shared_ptr<boost::asio::deadline_timer> banExpiryCheckTimer = std::make_shared<boost::asio::deadline_timer>(*ioService); + std::shared_ptr<boost::asio::deadline_timer> banExpiryCheckTimer = std::make_shared<boost::asio::deadline_timer>(*ioContext); banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(banExpiryCheckInterval)); banExpiryCheckTimer->async_wait(std::bind(&BanExpiryHandler, std::weak_ptr<boost::asio::deadline_timer>(banExpiryCheckTimer), banExpiryCheckInterval, std::placeholders::_1)); @@ -211,17 +211,17 @@ int main(int argc, char** argv) std::shared_ptr<boost::asio::deadline_timer> serviceStatusWatchTimer; if (m_ServiceStatus != -1) { - serviceStatusWatchTimer = std::make_shared<boost::asio::deadline_timer>(*ioService); + serviceStatusWatchTimer = std::make_shared<boost::asio::deadline_timer>(*ioContext); serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1)); serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher, std::weak_ptr<boost::asio::deadline_timer>(serviceStatusWatchTimer), - std::weak_ptr<boost::asio::io_service>(ioService), + std::weak_ptr<Trinity::Asio::IoContext>(ioContext), std::placeholders::_1)); } #endif // Start the io service worker loop - ioService->run(); + ioContext->run(); banExpiryCheckTimer->cancel(); dbPingTimer->cancel(); @@ -258,11 +258,11 @@ void StopDB() MySQL::Library_End(); } -void SignalHandler(std::weak_ptr<boost::asio::io_service> ioServiceRef, boost::system::error_code const& error, int /*signalNumber*/) +void SignalHandler(std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error, int /*signalNumber*/) { if (!error) - if (std::shared_ptr<boost::asio::io_service> ioService = ioServiceRef.lock()) - ioService->stop(); + if (std::shared_ptr<Trinity::Asio::IoContext> ioContext = ioContextRef.lock()) + ioContext->stop(); } void KeepDatabaseAliveHandler(std::weak_ptr<boost::asio::deadline_timer> dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const& error) @@ -297,20 +297,20 @@ void BanExpiryHandler(std::weak_ptr<boost::asio::deadline_timer> banExpiryCheckT } #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -void ServiceStatusWatcher(std::weak_ptr<boost::asio::deadline_timer> serviceStatusWatchTimerRef, std::weak_ptr<boost::asio::io_service> ioServiceRef, boost::system::error_code const& error) +void ServiceStatusWatcher(std::weak_ptr<boost::asio::deadline_timer> serviceStatusWatchTimerRef, std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error) { if (!error) { - if (std::shared_ptr<boost::asio::io_service> ioService = ioServiceRef.lock()) + if (std::shared_ptr<Trinity::Asio::IoContext> ioContext = ioContextRef.lock()) { if (m_ServiceStatus == 0) { - ioService->stop(); + ioContext->stop(); } else if (std::shared_ptr<boost::asio::deadline_timer> serviceStatusWatchTimer = serviceStatusWatchTimerRef.lock()) { serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1)); - serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher, serviceStatusWatchTimerRef, ioService, std::placeholders::_1)); + serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher, serviceStatusWatchTimerRef, ioContext, std::placeholders::_1)); } } } diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp index 20ca3f1431d..e256c9f10a5 100644 --- a/src/server/bnetserver/REST/LoginRESTService.cpp +++ b/src/server/bnetserver/REST/LoginRESTService.cpp @@ -19,8 +19,10 @@ #include "Configuration/Config.h" #include "DatabaseEnv.h" #include "Errors.h" +#include "IpNetwork.h" #include "ProtobufJSON.h" #include "Realm.h" +#include "Resolver.h" #include "SessionManager.h" #include "SHA1.h" #include "SHA256.h" @@ -69,9 +71,9 @@ int32 handle_post_plugin(soap* soapClient) return sLoginService.HandleHttpRequest(soapClient, "POST", sLoginService._postHandlers); } -bool LoginRESTService::Start(boost::asio::io_service* ioService) +bool LoginRESTService::Start(Trinity::Asio::IoContext* ioContext) { - _ioService = ioService; + _ioContext = ioContext; _bindIP = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); _port = sConfigMgr->GetIntDefault("LoginREST.Port", 8081); if (_port < 0 || _port > 0xFFFF) @@ -81,30 +83,28 @@ bool LoginRESTService::Start(boost::asio::io_service* ioService) } boost::system::error_code ec; - boost::asio::ip::tcp::resolver resolver(*ioService); - boost::asio::ip::tcp::resolver::iterator end; + boost::asio::ip::tcp::resolver resolver(*ioContext); std::string configuredAddress = sConfigMgr->GetStringDefault("LoginREST.ExternalAddress", "127.0.0.1"); - boost::asio::ip::tcp::resolver::query externalAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); - boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec); - if (endPoint == end || ec) + Optional<boost::asio::ip::tcp::endpoint> externalAddress = Trinity::Net::Resolve(resolver, boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); + if (!externalAddress) { TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str()); return false; } - _externalAddress = endPoint->endpoint(); + _externalAddress = *externalAddress; configuredAddress = sConfigMgr->GetStringDefault("LoginREST.LocalAddress", "127.0.0.1"); - boost::asio::ip::tcp::resolver::query localAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); - endPoint = resolver.resolve(localAddressQuery, ec); - if (endPoint == end || ec) + Optional<boost::asio::ip::tcp::endpoint> localAddress = Trinity::Net::Resolve(resolver, boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); + if (!localAddress) { - TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str()); + TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.LocalAddress %s", configuredAddress.c_str()); return false; } - _localAddress = endPoint->endpoint(); + _localAddress = *localAddress; + _localNetmask = Trinity::Net::GetDefaultNetmaskV4(_localAddress.address().to_v4()); // set up form inputs Battlenet::JSON::Login::FormInput* input; @@ -145,8 +145,7 @@ boost::asio::ip::tcp::endpoint const& LoginRESTService::GetAddressForClient(boos else if (_localAddress.address().is_loopback()) return _externalAddress; - boost::asio::ip::address_v4 netmask = boost::asio::ip::address_v4::netmask(_localAddress.address().to_v4()); - if ((netmask.to_ulong() & address.to_v4().to_ulong()) == (netmask.to_ulong() & _localAddress.address().to_v4().to_ulong())) + if (Trinity::Net::IsInNetwork(_localAddress.address().to_v4(), _localNetmask, address.to_v4())) return _localAddress; return _externalAddress; @@ -205,7 +204,7 @@ void LoginRESTService::Run() TC_LOG_DEBUG("server.rest", "Accepted connection from IP=%s", boost::asio::ip::address_v4(soapClient->GetClient()->ip).to_string().c_str()); - _ioService->post([soapClient]() + Trinity::Asio::post(*_ioContext, [soapClient]() { soapClient->GetClient()->user = (void*)&soapClient; // this allows us to make a copy of pointer inside GET/POST handlers to increment reference count soap_begin(soapClient->GetClient()); @@ -295,7 +294,7 @@ int32 LoginRESTService::HandleGetGameAccounts(std::shared_ptr<AsyncRequest> requ SendResponse(request->GetClient(), response); }))); - _ioService->post([this, request]() { HandleAsyncRequest(request); }); + Trinity::Asio::post(*_ioContext, [this, request]() { HandleAsyncRequest(request); }); return SOAP_OK; } @@ -436,7 +435,7 @@ int32 LoginRESTService::HandlePostLogin(std::shared_ptr<AsyncRequest> request) sLoginService.SendResponse(request->GetClient(), loginResult); }))); - _ioService->post([this, request]() { HandleAsyncRequest(request); }); + Trinity::Asio::post(*_ioContext, [this, request]() { HandleAsyncRequest(request); }); return SOAP_OK; } @@ -476,7 +475,7 @@ int32 LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<AsyncReques SendResponse(request->GetClient(), loginRefreshResult); }))); - _ioService->post([this, request]() { HandleAsyncRequest(request); }); + Trinity::Asio::post(*_ioContext, [this, request]() { HandleAsyncRequest(request); }); return SOAP_OK; } @@ -494,7 +493,7 @@ void LoginRESTService::HandleAsyncRequest(std::shared_ptr<AsyncRequest> request) { if (!request->InvokeIfReady()) { - _ioService->post([this, request]() { HandleAsyncRequest(request); }); + Trinity::Asio::post(*_ioContext, [this, request]() { HandleAsyncRequest(request); }); } else if (request->GetResponseStatus()) { diff --git a/src/server/bnetserver/REST/LoginRESTService.h b/src/server/bnetserver/REST/LoginRESTService.h index 78253732264..6cc0e60b3c3 100644 --- a/src/server/bnetserver/REST/LoginRESTService.h +++ b/src/server/bnetserver/REST/LoginRESTService.h @@ -19,11 +19,11 @@ #define LoginRESTService_h__ #include "Define.h" +#include "IoContext.h" +#include "IpAddress.h" #include "Login.pb.h" #include "Session.h" -#include <boost/asio/io_service.hpp> #include <boost/asio/ip/tcp.hpp> -#include <boost/asio/ip/address.hpp> #include <atomic> #include <thread> @@ -40,11 +40,11 @@ enum class BanMode class LoginRESTService { public: - LoginRESTService() : _ioService(nullptr), _stopped(false), _port(0), _loginTicketDuration(0) { } + LoginRESTService() : _ioContext(nullptr), _stopped(false), _port(0), _loginTicketDuration(0) { } static LoginRESTService& Instance(); - bool Start(boost::asio::io_service* ioService); + bool Start(Trinity::Asio::IoContext* ioContext); void Stop(); boost::asio::ip::tcp::endpoint const& GetAddressForClient(boost::asio::ip::address const& address) const; @@ -96,7 +96,7 @@ private: char const* ContentType; }; - boost::asio::io_service* _ioService; + Trinity::Asio::IoContext* _ioContext; std::thread _thread; std::atomic<bool> _stopped; Battlenet::JSON::Login::FormInputs _formInputs; @@ -104,6 +104,7 @@ private: int32 _port; boost::asio::ip::tcp::endpoint _externalAddress; boost::asio::ip::tcp::endpoint _localAddress; + boost::asio::ip::address_v4 _localNetmask; uint32 _loginTicketDuration; HttpMethodHandlerMap _getHandlers; diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp index 92b4e9f7735..25abb0c5d6f 100644 --- a/src/server/bnetserver/Server/SessionManager.cpp +++ b/src/server/bnetserver/Server/SessionManager.cpp @@ -17,9 +17,9 @@ #include "SessionManager.h" -bool Battlenet::SessionManager::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount) +bool Battlenet::SessionManager::StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount) { - if (!BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount)) + if (!BaseSocketMgr::StartNetwork(ioContext, bindIp, port, threadCount)) return false; _acceptor->SetSocketFactory(std::bind(&BaseSocketMgr::GetSocketForAccept, this)); diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h index 7d4f35cb65c..3dcd3386f56 100644 --- a/src/server/bnetserver/Server/SessionManager.h +++ b/src/server/bnetserver/Server/SessionManager.h @@ -30,7 +30,7 @@ namespace Battlenet public: static SessionManager& Instance(); - bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount = 1) override; + bool StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount = 1) override; protected: NetworkThread<Session>* CreateThreads() const override; diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp index 1a00728ffcd..dd2b98656ba 100644 --- a/src/server/game/Server/Protocol/PacketLog.cpp +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -17,11 +17,11 @@ #include "PacketLog.h" #include "Config.h" +#include "IpAddress.h" #include "Realm.h" #include "Timer.h" #include "World.h" #include "WorldPacket.h" -#include <boost/asio/ip/address.hpp> #pragma pack(push, 1) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 958e48240aa..08357f8bc4d 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -33,6 +33,7 @@ #include "Group.h" #include "Guild.h" #include "GuildMgr.h" +#include "IpAddress.h" #include "Map.h" #include "Metric.h" #include "MiscPackets.h" @@ -708,7 +709,7 @@ void WorldSession::Handle_EarlyProccess(WorldPacket& recvPacket) void WorldSession::SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial) { boost::system::error_code ignored_error; - boost::asio::ip::address instanceAddress = realm.GetAddressForClient(boost::asio::ip::address::from_string(GetRemoteAddress(), ignored_error)); + boost::asio::ip::address instanceAddress = realm.GetAddressForClient(Trinity::Net::make_address(GetRemoteAddress(), ignored_error)); _instanceConnectKey.Fields.AccountId = GetAccountId(); _instanceConnectKey.Fields.ConnectionType = CONNECTION_TYPE_INSTANCE; diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 23c99f7133e..b83742a3346 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -133,7 +133,7 @@ void WorldSocket::CheckIpCallback(PreparedQueryResult result) initializer.Write(ServerConnectionInitialize.c_str(), ServerConnectionInitialize.length()); initializer.Write("\n", 1); - // - io_service.run thread, safe. + // - IoContext.run thread, safe. QueuePacket(std::move(initializer)); } diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp index 7cf67a7a590..216d68d695a 100644 --- a/src/server/game/Server/WorldSocketMgr.cpp +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -58,11 +58,11 @@ WorldSocketMgr& WorldSocketMgr::Instance() return instance; } -bool WorldSocketMgr::StartWorldNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, uint16 instancePort, int threadCount) +bool WorldSocketMgr::StartWorldNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, uint16 instancePort, int threadCount) { _tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true); - int const max_connections = boost::asio::socket_base::max_connections; + int const max_connections = TRINITY_MAX_LISTEN_CONNECTIONS; TC_LOG_DEBUG("misc", "Max allowed socket connections %d", max_connections); // -1 means use default @@ -76,13 +76,13 @@ bool WorldSocketMgr::StartWorldNetwork(boost::asio::io_service& service, std::st return false; } - if (!BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount)) + if (!BaseSocketMgr::StartNetwork(ioContext, bindIp, port, threadCount)) return false; AsyncAcceptor* instanceAcceptor = nullptr; try { - instanceAcceptor = new AsyncAcceptor(service, bindIp, instancePort); + instanceAcceptor = new AsyncAcceptor(ioContext, bindIp, instancePort); } catch (boost::system::system_error const& err) { diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h index b8a1ee77c53..efc04595d15 100644 --- a/src/server/game/Server/WorldSocketMgr.h +++ b/src/server/game/Server/WorldSocketMgr.h @@ -40,7 +40,7 @@ public: static WorldSocketMgr& Instance(); /// Start network, listen at address:port . - bool StartWorldNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, uint16 instancePort, int networkThreads); + bool StartWorldNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, uint16 instancePort, int networkThreads); /// Stops all network threads, It will wait for all running threads . void StopNetwork() override; @@ -56,9 +56,9 @@ protected: private: // private, must not be called directly - bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount) override + bool StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount) override { - return BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount); + return BaseSocketMgr::StartNetwork(ioContext, bindIp, port, threadCount); } AsyncAcceptor* _instanceAcceptor; diff --git a/src/server/game/Services/WorldserverService.cpp b/src/server/game/Services/WorldserverService.cpp index 3121a0f1f34..f6fd36dc328 100644 --- a/src/server/game/Services/WorldserverService.cpp +++ b/src/server/game/Services/WorldserverService.cpp @@ -17,13 +17,13 @@ #include "WorldserverService.h" #include "BattlenetRpcErrorCodes.h" +#include "IpAddress.h" #include "Log.h" #include "ProtobufJSON.h" #include "Realm.h" #include "RealmList.h" #include "RealmList.pb.h" #include "World.h" -#include <boost/asio/ip/address.hpp> #include <zlib.h> Battlenet::GameUtilitiesService::GameUtilitiesService(WorldSession* session) : BaseService(session) @@ -101,7 +101,7 @@ uint32 Battlenet::GameUtilitiesService::HandleRealmJoinRequest(std::unordered_ma { auto realmAddress = params.find("Param_RealmAddress"); if (realmAddress != params.end()) - return sRealmList->JoinRealm(uint32(realmAddress->second->uint_value()), realm.Build, boost::asio::ip::address::from_string(_session->GetRemoteAddress()), _session->GetRealmListSecret(), + return sRealmList->JoinRealm(uint32(realmAddress->second->uint_value()), realm.Build, Trinity::Net::make_address(_session->GetRemoteAddress()), _session->GetRealmListSecret(), _session->GetSessionDbcLocale(), _session->GetOS(), _session->GetAccountName(), response); return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET; diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 70886e948e1..e4bb6a4494b 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -25,13 +25,13 @@ EndScriptData */ #include "AccountMgr.h" #include "Chat.h" #include "DatabaseEnv.h" +#include "IpAddress.h" #include "Language.h" #include "Log.h" #include "Player.h" #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" -#include <boost/asio/ip/address_v4.hpp> class account_commandscript : public CommandScript { @@ -291,7 +291,7 @@ public: if (param == "on") { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); - uint32 ip = boost::asio::ip::address_v4::from_string(handler->GetSession()->GetRemoteAddress()).to_ulong(); + uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(handler->GetSession()->GetRemoteAddress())); EndianConvertReverse(ip); stmt->setUInt32(0, ip); PreparedQueryResult result = LoginDatabase.Query(stmt); diff --git a/src/server/scripts/Commands/cs_battlenet_account.cpp b/src/server/scripts/Commands/cs_battlenet_account.cpp index da560ca3242..93713d23182 100644 --- a/src/server/scripts/Commands/cs_battlenet_account.cpp +++ b/src/server/scripts/Commands/cs_battlenet_account.cpp @@ -20,13 +20,13 @@ #include "BigNumber.h" #include "Chat.h" #include "DatabaseEnv.h" +#include "IpAddress.h" #include "Language.h" #include "Log.h" #include "Player.h" #include "ScriptMgr.h" #include "Util.h" #include "WorldSession.h" -#include <boost/asio/ip/address_v4.hpp> class battlenet_account_commandscript : public CommandScript { @@ -144,7 +144,7 @@ public: if (param == "on") { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); - uint32 ip = boost::asio::ip::address_v4::from_string(handler->GetSession()->GetRemoteAddress()).to_ulong(); + uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(handler->GetSession()->GetRemoteAddress())); EndianConvertReverse(ip); stmt->setUInt32(0, ip); PreparedQueryResult result = LoginDatabase.Query(stmt); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 4f7d34d01ac..a14ddcf1be8 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -26,6 +26,7 @@ #include "Group.h" #include "GroupMgr.h" #include "InstanceSaveMgr.h" +#include "IpAddress.h" #include "Item.h" #include "Language.h" #include "LFG.h" @@ -50,7 +51,6 @@ #include "WeatherMgr.h" #include "World.h" #include "WorldSession.h" -#include <boost/asio/ip/address_v4.hpp> // temporary hack until database includes are sorted out (don't want to pull in Windows.h everywhere from mysql.h) #ifdef GetClassName @@ -1781,7 +1781,7 @@ public: lastIp = fields[4].GetString(); lastLogin = fields[5].GetString(); - uint32 ip = boost::asio::ip::address_v4::from_string(lastIp).to_ulong();; + uint32 ip = Trinity::Net::address_to_uint(Trinity::Net::make_address_v4(lastIp)); EndianConvertReverse(ip); // If ip2nation table is populated, it displays the country diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index cea7c8abd99..254d9336dc4 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -18,22 +18,29 @@ #ifndef __ASYNCACCEPT_H_ #define __ASYNCACCEPT_H_ +#include "IoContext.h" +#include "IpAddress.h" #include "Log.h" #include <boost/asio/ip/tcp.hpp> -#include <boost/asio/ip/address.hpp> #include <functional> #include <atomic> using boost::asio::ip::tcp; +#if BOOST_VERSION >= 106600 +#define TRINITY_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_listen_connections +#else +#define TRINITY_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_connections +#endif + class AsyncAcceptor { public: typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex); - AsyncAcceptor(boost::asio::io_service& ioService, std::string const& bindIp, uint16 port) : - _acceptor(ioService), _endpoint(boost::asio::ip::address::from_string(bindIp), port), - _socket(ioService), _closed(false), _socketFactory(std::bind(&AsyncAcceptor::DefeaultSocketFactory, this)) + AsyncAcceptor(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port) : + _acceptor(ioContext), _endpoint(Trinity::Net::make_address(bindIp), port), + _socket(ioContext), _closed(false), _socketFactory(std::bind(&AsyncAcceptor::DefeaultSocketFactory, this)) { } @@ -84,7 +91,7 @@ public: return false; } - _acceptor.listen(boost::asio::socket_base::max_connections, errorCode); + _acceptor.listen(TRINITY_MAX_LISTEN_CONNECTIONS, errorCode); if (errorCode) { TC_LOG_INFO("network", "Failed to start listening on %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str()); diff --git a/src/server/shared/Networking/NetworkThread.h b/src/server/shared/Networking/NetworkThread.h index e384e1515ae..2f032a20247 100644 --- a/src/server/shared/Networking/NetworkThread.h +++ b/src/server/shared/Networking/NetworkThread.h @@ -20,6 +20,7 @@ #include "Define.h" #include "Errors.h" +#include "IoContext.h" #include "Log.h" #include "Timer.h" #include <boost/asio/ip/tcp.hpp> @@ -37,8 +38,8 @@ template<class SocketType> class NetworkThread { public: - NetworkThread() : _connections(0), _stopped(false), _thread(nullptr), _io_service(1), - _acceptSocket(_io_service), _updateTimer(_io_service) + NetworkThread() : _connections(0), _stopped(false), _thread(nullptr), _ioContext(1), + _acceptSocket(_ioContext), _updateTimer(_ioContext) { } @@ -55,7 +56,7 @@ public: void Stop() { _stopped = true; - _io_service.stop(); + _ioContext.stop(); } bool Start() @@ -123,7 +124,7 @@ protected: _updateTimer.expires_from_now(boost::posix_time::milliseconds(10)); _updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this)); - _io_service.run(); + _ioContext.run(); TC_LOG_DEBUG("misc", "Network Thread exits"); _newSockets.clear(); @@ -170,7 +171,7 @@ private: std::mutex _newSocketsLock; SocketContainer _newSockets; - boost::asio::io_service _io_service; + Trinity::Asio::IoContext _ioContext; tcp::socket _acceptSocket; boost::asio::deadline_timer _updateTimer; }; diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h index 585aad409c0..1fc0ef88e44 100644 --- a/src/server/shared/Networking/SocketMgr.h +++ b/src/server/shared/Networking/SocketMgr.h @@ -35,14 +35,14 @@ public: ASSERT(!_threads && !_acceptor && !_threadCount, "StopNetwork must be called prior to SocketMgr destruction"); } - virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount) + virtual bool StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount) { ASSERT(threadCount > 0); AsyncAcceptor* acceptor = nullptr; try { - acceptor = new AsyncAcceptor(service, bindIp, port); + acceptor = new AsyncAcceptor(ioContext, bindIp, port); } catch (boost::system::system_error const& err) { diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp index 7b98f51bf35..6f9d216bcd4 100644 --- a/src/server/shared/Realm/Realm.cpp +++ b/src/server/shared/Realm/Realm.cpp @@ -16,8 +16,9 @@ */ #include "Realm.h" +#include "IpAddress.h" +#include "IpNetwork.h" #include "StringFormat.h" -#include <boost/asio/ip/address.hpp> #include <algorithm> #include <cctype> @@ -47,12 +48,8 @@ boost::asio::ip::address Realm::GetAddressForClient(boost::asio::ip::address con } else { - if (clientAddr.is_v4() && - (clientAddr.to_v4().to_ulong() & LocalSubnetMask->to_v4().to_ulong()) == - (LocalAddress->to_v4().to_ulong() & LocalSubnetMask->to_v4().to_ulong())) - { + if (clientAddr.is_v4() && Trinity::Net::IsInNetwork(LocalAddress->to_v4(), LocalSubnetMask->to_v4(), clientAddr.to_v4())) realmIp = *LocalAddress; - } else realmIp = *ExternalAddress; } diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index 84449fae116..d94be106ac5 100644 --- a/src/server/shared/Realm/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -21,8 +21,10 @@ #include "BigNumber.h" #include "DatabaseEnv.h" #include "Errors.h" +#include "IoContext.h" #include "Log.h" #include "ProtobufJSON.h" +#include "Resolver.h" #include "Util.h" #include "game_utilities_service.pb.h" #include "RealmList.pb.h" @@ -48,11 +50,11 @@ RealmList* RealmList::Instance() } // Load the realm list from the database -void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) +void RealmList::Initialize(Trinity::Asio::IoContext& ioContext, uint32 updateInterval) { _updateInterval = updateInterval; - _updateTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); - _resolver = Trinity::make_unique<boost::asio::ip::tcp::resolver>(ioService); + _updateTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioContext); + _resolver = Trinity::make_unique<boost::asio::ip::tcp::resolver>(ioContext); // Get the content of the realmlist table in the database UpdateRealms(boost::system::error_code()); @@ -64,7 +66,7 @@ void RealmList::Close() } void RealmList::UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name, - boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, + boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population) { @@ -78,11 +80,11 @@ void RealmList::UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint realm.AllowedSecurityLevel = allowedSecurityLevel; realm.PopulationLevel = population; if (!realm.ExternalAddress || *realm.ExternalAddress != address) - realm.ExternalAddress = Trinity::make_unique<boost::asio::ip::address>(address); + realm.ExternalAddress = Trinity::make_unique<boost::asio::ip::address>(std::move(address)); if (!realm.LocalAddress || *realm.LocalAddress != localAddr) - realm.LocalAddress = Trinity::make_unique<boost::asio::ip::address>(localAddr); + realm.LocalAddress = Trinity::make_unique<boost::asio::ip::address>(std::move(localAddr)); if (!realm.LocalSubnetMask || *realm.LocalSubnetMask != localSubmask) - realm.LocalSubnetMask = Trinity::make_unique<boost::asio::ip::address>(localSubmask); + realm.LocalSubnetMask = Trinity::make_unique<boost::asio::ip::address>(std::move(localSubmask)); realm.Port = port; } @@ -110,43 +112,34 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) { try { - boost::asio::ip::tcp::resolver::iterator end; - Field* fields = result->Fetch(); uint32 realmId = fields[0].GetUInt32(); std::string name = fields[1].GetString(); - boost::asio::ip::tcp::resolver::query externalAddressQuery(boost::asio::ip::tcp::v4(), fields[2].GetString(), ""); + std::string externalAddressString = fields[2].GetString(); + std::string localAddressString = fields[3].GetString(); + std::string localSubmaskString = fields[4].GetString(); - boost::system::error_code ec; - boost::asio::ip::tcp::resolver::iterator endPoint = _resolver->resolve(externalAddressQuery, ec); - if (endPoint == end || ec) + Optional<boost::asio::ip::tcp::endpoint> externalAddress = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), externalAddressString, ""); + if (!externalAddress) { - TC_LOG_ERROR("realmlist", "Could not resolve address %s for realm \"%s\" id %u", fields[2].GetString().c_str(), name.c_str(), realmId); + TC_LOG_ERROR("realmlist", "Could not resolve address %s for realm \"%s\" id %u", externalAddressString.c_str(), name.c_str(), realmId); continue; } - boost::asio::ip::address externalAddress = endPoint->endpoint().address(); - - boost::asio::ip::tcp::resolver::query localAddressQuery(boost::asio::ip::tcp::v4(), fields[3].GetString(), ""); - endPoint = _resolver->resolve(localAddressQuery, ec); - if (endPoint == end || ec) + Optional<boost::asio::ip::tcp::endpoint> localAddress = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), localAddressString, ""); + if (!localAddress) { - TC_LOG_ERROR("realmlist", "Could not resolve localAddress %s for realm \"%s\" id %u", fields[3].GetString().c_str(), name.c_str(), realmId); + TC_LOG_ERROR("realmlist", "Could not resolve localAddress %s for realm \"%s\" id %u", localAddressString.c_str(), name.c_str(), realmId); continue; } - boost::asio::ip::address localAddress = endPoint->endpoint().address(); - - boost::asio::ip::tcp::resolver::query localSubmaskQuery(boost::asio::ip::tcp::v4(), fields[4].GetString(), ""); - endPoint = _resolver->resolve(localSubmaskQuery, ec); - if (endPoint == end || ec) + Optional<boost::asio::ip::tcp::endpoint> localSubmask = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), localSubmaskString, ""); + if (!localSubmask) { - TC_LOG_ERROR("realmlist", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", fields[4].GetString().c_str(), name.c_str(), realmId); + TC_LOG_ERROR("realmlist", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", localSubmaskString.c_str(), name.c_str(), realmId); continue; } - boost::asio::ip::address localSubmask = endPoint->endpoint().address(); - uint16 port = fields[5].GetUInt16(); uint8 icon = fields[6].GetUInt8(); if (icon == REALM_TYPE_FFA_PVP) @@ -163,15 +156,15 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) Battlenet::RealmHandle id{ region, battlegroup, realmId }; - UpdateRealm(newRealms[id], id, build, name, externalAddress, localAddress, localSubmask, port, icon, + UpdateRealm(newRealms[id], id, build, name, externalAddress->address(), localAddress->address(), localSubmask->address(), port, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); newSubRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString()); if (!existingRealms.count(id)) - TC_LOG_INFO("realmlist", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + TC_LOG_INFO("realmlist", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port); else - TC_LOG_DEBUG("realmlist", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + TC_LOG_DEBUG("realmlist", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port); existingRealms.erase(id); } diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h index 9f3b93e3d08..ac8983c283a 100644 --- a/src/server/shared/Realm/RealmList.h +++ b/src/server/shared/Realm/RealmList.h @@ -38,11 +38,6 @@ namespace boost { class shared_mutex; - namespace asio - { - class io_service; - } - namespace system { class error_code; @@ -72,6 +67,14 @@ namespace JSON } } +namespace Trinity +{ + namespace Asio + { + class IoContext; + } +} + /// Storage object for the list of realms on the server class TC_SHARED_API RealmList { @@ -82,7 +85,7 @@ public: ~RealmList(); - void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); + void Initialize(Trinity::Asio::IoContext& ioContext, uint32 updateInterval); void Close(); Realm const* GetRealm(Battlenet::RealmHandle const& id) const; @@ -99,7 +102,7 @@ private: void UpdateRealms(boost::system::error_code const& error); void UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name, - boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, + boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); std::unique_ptr<boost::shared_mutex> _realmsMutex; diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index f65e1f79a10..46e06109b09 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -32,6 +32,7 @@ #include "DatabaseLoader.h" #include "GitRevision.h" #include "InstanceSaveMgr.h" +#include "IoContext.h" #include "MapManager.h" #include "Metric.h" #include "MySQLThreading.h" @@ -50,7 +51,6 @@ #include "WorldSocketMgr.h" #include <openssl/opensslv.h> #include <openssl/crypto.h> -#include <boost/asio/io_service.hpp> #include <boost/asio/deadline_timer.hpp> #include <boost/asio/signal_set.hpp> #include <boost/filesystem/operations.hpp> @@ -85,8 +85,8 @@ int m_ServiceStatus = -1; class FreezeDetector { public: - FreezeDetector(boost::asio::io_service& ioService, uint32 maxCoreStuckTime) - : _timer(ioService), _worldLoopCounter(0), _lastChangeMsTime(0), _maxCoreStuckTimeInMs(maxCoreStuckTime) { } + FreezeDetector(Trinity::Asio::IoContext& ioContext, uint32 maxCoreStuckTime) + : _timer(ioContext), _worldLoopCounter(0), _lastChangeMsTime(0), _maxCoreStuckTimeInMs(maxCoreStuckTime) { } static void Start(std::shared_ptr<FreezeDetector> const& freezeDetector) { @@ -104,7 +104,7 @@ private: }; void SignalHandler(boost::system::error_code const& error, int signalNumber); -AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService); +AsyncAcceptor* StartRaSocketAcceptor(Trinity::Asio::IoContext& ioContext); bool StartDB(); void StopDB(); void WorldUpdateLoop(); @@ -148,11 +148,11 @@ extern int main(int argc, char** argv) return 1; } - std::shared_ptr<boost::asio::io_service> ioService = std::make_shared<boost::asio::io_service>(); + std::shared_ptr<Trinity::Asio::IoContext> ioContext = std::make_shared<Trinity::Asio::IoContext>(); sLog->RegisterAppender<AppenderDB>(); - // If logs are supposed to be handled async then we need to pass the io_service into the Log singleton - sLog->Initialize(sConfigMgr->GetBoolDefault("Log.Async.Enable", false) ? ioService.get() : nullptr); + // If logs are supposed to be handled async then we need to pass the IoContext into the Log singleton + sLog->Initialize(sConfigMgr->GetBoolDefault("Log.Async.Enable", false) ? ioContext.get() : nullptr); Trinity::Banner::Show("worldserver-daemon", [](char const* text) @@ -189,8 +189,8 @@ extern int main(int argc, char** argv) } } - // Set signal handlers (this must be done before starting io_service threads, because otherwise they would unblock and exit) - boost::asio::signal_set signals(*ioService, SIGINT, SIGTERM); + // Set signal handlers (this must be done before starting IoContext threads, because otherwise they would unblock and exit) + boost::asio::signal_set signals(*ioContext, SIGINT, SIGTERM); #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS signals.add(SIGBREAK); #endif @@ -198,9 +198,9 @@ extern int main(int argc, char** argv) // Start the Boost based thread pool int numThreads = sConfigMgr->GetIntDefault("ThreadPool", 1); - std::shared_ptr<std::vector<std::thread>> threadPool(new std::vector<std::thread>(), [ioService](std::vector<std::thread>* del) + std::shared_ptr<std::vector<std::thread>> threadPool(new std::vector<std::thread>(), [ioContext](std::vector<std::thread>* del) { - ioService->stop(); + ioContext->stop(); for (std::thread& thr : *del) thr.join(); @@ -211,7 +211,7 @@ extern int main(int argc, char** argv) numThreads = 1; for (int i = 0; i < numThreads; ++i) - threadPool->push_back(std::thread([ioService]() { ioService->run(); })); + threadPool->push_back(std::thread([ioContext]() { ioContext->run(); })); // Set process priority according to configuration settings SetProcessPriority("server.worldserver", sConfigMgr->GetIntDefault(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetBoolDefault(CONFIG_HIGH_PRIORITY, false)); @@ -225,13 +225,13 @@ extern int main(int argc, char** argv) // Set server offline (not connectable) LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm); - sRealmList->Initialize(*ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); + sRealmList->Initialize(*ioContext, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); std::shared_ptr<void> sRealmListHandle(nullptr, [](void*) { sRealmList->Close(); }); LoadRealmInfo(); - sMetric->Initialize(realm.Name, *ioService, []() + sMetric->Initialize(realm.Name, *ioContext, []() { TC_METRIC_VALUE("online_players", sWorld->GetPlayerCount()); }); @@ -267,7 +267,7 @@ extern int main(int argc, char** argv) // Start the Remote Access port (acceptor) if enabled std::unique_ptr<AsyncAcceptor> raAcceptor; if (sConfigMgr->GetBoolDefault("Ra.Enable", false)) - raAcceptor.reset(StartRaSocketAcceptor(*ioService)); + raAcceptor.reset(StartRaSocketAcceptor(*ioContext)); // Start soap serving thread if enabled std::shared_ptr<std::thread> soapThread; @@ -294,7 +294,7 @@ extern int main(int argc, char** argv) return 1; } - if (!sWorldSocketMgr.StartWorldNetwork(*ioService, worldListener, worldPort, instancePort, networkThreads)) + if (!sWorldSocketMgr.StartWorldNetwork(*ioContext, worldListener, worldPort, instancePort, networkThreads)) { TC_LOG_ERROR("server.worldserver", "Failed to initialize network"); return 1; @@ -331,7 +331,7 @@ extern int main(int argc, char** argv) std::shared_ptr<FreezeDetector> freezeDetector; if (int coreStuckTime = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0)) { - freezeDetector = std::make_shared<FreezeDetector>(*ioService, coreStuckTime * 1000); + freezeDetector = std::make_shared<FreezeDetector>(*ioContext, coreStuckTime * 1000); FreezeDetector::Start(freezeDetector); TC_LOG_INFO("server.worldserver", "Starting up anti-freeze thread (%u seconds max stuck time)...", coreStuckTime); } @@ -500,12 +500,12 @@ void FreezeDetector::Handler(std::weak_ptr<FreezeDetector> freezeDetectorRef, bo } } -AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService) +AsyncAcceptor* StartRaSocketAcceptor(Trinity::Asio::IoContext& ioContext) { uint16 raPort = uint16(sConfigMgr->GetIntDefault("Ra.Port", 3443)); std::string raListener = sConfigMgr->GetStringDefault("Ra.IP", "0.0.0.0"); - AsyncAcceptor* acceptor = new AsyncAcceptor(ioService, raListener, raPort); + AsyncAcceptor* acceptor = new AsyncAcceptor(ioContext, raListener, raPort); if (!acceptor->Bind()) { TC_LOG_ERROR("server.worldserver", "Failed to bind RA socket acceptor"); |