/* * Copyright (C) 2008-2017 TrinityCore * Copyright (C) 2005-2008 MaNGOS * * 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 . */ #include "Config.h" #include "NetworkThread.h" #include "ScriptMgr.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" #include static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex) { sWorldSocketMgr.OnSocketOpen(std::forward(sock), threadIndex); } class WorldSocketThread : public NetworkThread { public: void SocketAdded(std::shared_ptr sock) override { sScriptMgr->OnSocketOpen(sock); } void SocketRemoved(std::shared_ptr sock) override { sScriptMgr->OnSocketClose(sock); } }; WorldSocketMgr::WorldSocketMgr() : BaseSocketMgr(), _instanceAcceptor(nullptr), _socketSendBufferSize(-1), m_SockOutUBuff(65536), _tcpNoDelay(true) { } WorldSocketMgr::~WorldSocketMgr() { ASSERT(!_instanceAcceptor, "StopNetwork must be called prior to WorldSocketMgr destruction"); } WorldSocketMgr& WorldSocketMgr::Instance() { static WorldSocketMgr instance; return instance; } bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount) { _tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true); int const max_connections = boost::asio::socket_base::max_connections; TC_LOG_DEBUG("misc", "Max allowed socket connections %d", max_connections); // -1 means use default _socketSendBufferSize = sConfigMgr->GetIntDefault("Network.OutKBuff", -1); m_SockOutUBuff = sConfigMgr->GetIntDefault("Network.OutUBuff", 65536); if (m_SockOutUBuff <= 0) { TC_LOG_ERROR("misc", "Network.OutUBuff is wrong in your config file"); return false; } BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount); _instanceAcceptor = new AsyncAcceptor(service, bindIp, uint16(sWorld->getIntConfig(CONFIG_PORT_INSTANCE))); _acceptor->SetSocketFactory(std::bind(&BaseSocketMgr::GetSocketForAccept, this)); _instanceAcceptor->SetSocketFactory(std::bind(&BaseSocketMgr::GetSocketForAccept, this)); _acceptor->AsyncAcceptWithCallback<&OnSocketAccept>(); _instanceAcceptor->AsyncAcceptWithCallback<&OnSocketAccept>(); sScriptMgr->OnNetworkStart(); return true; } void WorldSocketMgr::StopNetwork() { _instanceAcceptor->Close(); BaseSocketMgr::StopNetwork(); delete _instanceAcceptor; _instanceAcceptor = nullptr; sScriptMgr->OnNetworkStop(); } void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock, uint32 threadIndex) { // set some options here if (_socketSendBufferSize >= 0) { boost::system::error_code err; sock.set_option(boost::asio::socket_base::send_buffer_size(_socketSendBufferSize), err); if (err && err != boost::system::errc::not_supported) { TC_LOG_ERROR("misc", "WorldSocketMgr::OnSocketOpen sock.set_option(boost::asio::socket_base::send_buffer_size) err = %s", err.message().c_str()); return; } } // Set TCP_NODELAY. if (_tcpNoDelay) { boost::system::error_code err; sock.set_option(boost::asio::ip::tcp::no_delay(true), err); if (err) { TC_LOG_ERROR("misc", "WorldSocketMgr::OnSocketOpen sock.set_option(boost::asio::ip::tcp::no_delay) err = %s", err.message().c_str()); return; } } //sock->m_OutBufferSize = static_cast (m_SockOutUBuff); BaseSocketMgr::OnSocketOpen(std::forward(sock), threadIndex); } NetworkThread* WorldSocketMgr::CreateThreads() const { return new WorldSocketThread[GetNetworkThreadCount()]; }