/* * Copyright (C) 2008-2015 TrinityCore * * 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 . */ #ifndef SocketMgr_h__ #define SocketMgr_h__ #include "AsyncAcceptor.h" #include "Config.h" #include "Errors.h" #include "NetworkThread.h" #include #include using boost::asio::ip::tcp; template class SocketMgr { public: virtual ~SocketMgr() { delete _acceptor; delete[] _threads; } virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) { _threadCount = sConfigMgr->GetIntDefault("Network.Threads", 1); if (_threadCount <= 0) { TC_LOG_ERROR("misc", "Network.Threads is wrong in your config file"); return false; } try { _acceptor = new AsyncAcceptor(service, bindIp, port); } catch (boost::system::system_error const& err) { TC_LOG_ERROR("network", "Exception caught in SocketMgr.StartNetwork (%s:%u): %s", bindIp.c_str(), port, err.what()); return false; } _threads = CreateThreads(); ASSERT(_threads); for (int32 i = 0; i < _threadCount; ++i) _threads[i].Start(); return true; } virtual void StopNetwork() { if (_threadCount != 0) for (int32 i = 0; i < _threadCount; ++i) _threads[i].Stop(); Wait(); } void Wait() { if (_threadCount != 0) for (int32 i = 0; i < _threadCount; ++i) _threads[i].Wait(); } virtual void OnSocketOpen(tcp::socket&& sock) { size_t min = 0; for (int32 i = 1; i < _threadCount; ++i) if (_threads[i].GetConnectionCount() < _threads[min].GetConnectionCount()) min = i; try { std::shared_ptr newSocket = std::make_shared(std::move(sock)); newSocket->Start(); _threads[min].AddSocket(newSocket); } catch (boost::system::system_error const& err) { TC_LOG_WARN("network", "Failed to retrieve client's remote address %s", err.what()); } } int32 GetNetworkThreadCount() const { return _threadCount; } protected: SocketMgr() : _acceptor(nullptr), _threads(nullptr), _threadCount(1) { } virtual NetworkThread* CreateThreads() const = 0; AsyncAcceptor* _acceptor; NetworkThread* _threads; int32 _threadCount; }; #endif // SocketMgr_h__