diff options
| author | Shauren <shauren.trinity@gmail.com> | 2014-09-12 20:26:46 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2014-09-12 20:26:46 +0200 |
| commit | 7f2cdfd166d99efdd308f0b4d195a6b972092dd9 (patch) | |
| tree | 8871e168077155d8daabca787b223940f8774af9 /src/server/game | |
| parent | be8111b0a21308e78435e9bc20bbbb2804d51c78 (diff) | |
| parent | 6dff6b74256748f182ad65634a1ab16c5989d40e (diff) | |
Merge branch 'master' of https://github.com/TrinityCore/TrinityCore into 4.3.4
Conflicts:
src/server/authserver/Main.cpp
src/server/authserver/Server/AuthSession.cpp
src/server/authserver/Server/AuthSession.h
src/server/game/Server/WorldSocket.cpp
src/server/game/Server/WorldSocket.h
src/server/scripts/World/npcs_special.cpp
Diffstat (limited to 'src/server/game')
| -rw-r--r-- | src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h | 2 | ||||
| -rw-r--r-- | src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 7 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Groups/Group.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Groups/Group.h | 14 | ||||
| -rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 24 | ||||
| -rw-r--r-- | src/server/game/Loot/LootMgr.cpp | 7 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 141 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.h | 76 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocketMgr.cpp | 115 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocketMgr.h | 66 |
13 files changed, 337 insertions, 127 deletions
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h index 9c9a39cf567..df930367878 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h @@ -72,7 +72,7 @@ class AuctionBotBuyer : public AuctionBotAgent { public: AuctionBotBuyer(); - ~AuctionBotBuyer() override; + ~AuctionBotBuyer(); bool Initialize() override; bool Update(AuctionHouseType houseType) override; diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h index 014fe23f71a..42677a52f49 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h @@ -118,7 +118,7 @@ public: typedef std::vector<uint32> ItemPool; AuctionBotSeller(); - ~AuctionBotSeller() override; + ~AuctionBotSeller(); bool Initialize() override; bool Update(AuctionHouseType houseType) override; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ee8fee198bf..bab96b15292 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3878,7 +3878,8 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent if (!pSkill) continue; - if (_spell_idx->second->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->id)) + ///@todo: confirm if rogues start with lockpicking skill at level 1 but only receive the spell to use it at level 16 + if ((_spell_idx->second->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->id)) || (pSkill->id == SKILL_LOCKPICKING && _spell_idx->second->max_value == 0)) LearnDefaultSkill(pSkill->id, 0); } } @@ -17943,6 +17944,7 @@ bool Player::isAllowedToLoot(const Creature* creature) switch (thisGroup->GetLootMethod()) { + case MASTER_LOOT: case FREE_FOR_ALL: return true; case ROUND_ROBIN: @@ -17952,7 +17954,6 @@ bool Player::isAllowedToLoot(const Creature* creature) return true; return loot->hasItemFor(this); - case MASTER_LOOT: case GROUP_LOOT: case NEED_BEFORE_GREED: // may only loot if the player is the loot roundrobin player @@ -23664,6 +23665,8 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) skillValue = std::min(std::max<uint16>({ 1, uint16((getLevel() - 1) * 5) }), maxValue); else if (skillId == SKILL_FIST_WEAPONS) skillValue = std::max<uint16>(1, GetSkillValue(SKILL_UNARMED)); + else if (skillId == SKILL_LOCKPICKING) + skillValue = std::max<uint16>(1, GetSkillValue(SKILL_LOCKPICKING)); SetSkill(skillId, 0, skillValue, maxValue); break; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f6615d67c99..6f37f74b607 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -14108,7 +14108,8 @@ void Unit::SetFeared(bool apply) } if (Player* player = ToPlayer()) - player->SetClientControl(this, !apply); + if(!player->HasUnitState(UNIT_STATE_POSSESSED)) + player->SetClientControl(this, !apply); } void Unit::SetConfused(bool apply) @@ -14130,7 +14131,8 @@ void Unit::SetConfused(bool apply) } if (Player* player = ToPlayer()) - player->SetClientControl(this, !apply); + if (!player->HasUnitState(UNIT_STATE_POSSESSED)) + player->SetClientControl(this, !apply); } bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* aurApp) diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 638cc19784a..fd89ed80429 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -226,7 +226,7 @@ void Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, void Group::ConvertToLFG() { - m_groupType = GroupType(m_groupType | GROUPTYPE_LFG | GROUPTYPE_UNK1); + m_groupType = GroupType(m_groupType | GROUPTYPE_LFG | GROUPTYPE_LFG_RESTRICTED); m_lootMethod = NEED_BEFORE_GREED; if (!isBGGroup() && !isBFGroup()) { diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 4559c5841ae..84e3a5454cd 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -82,13 +82,15 @@ enum GroupMemberAssignment enum GroupType { - GROUPTYPE_NORMAL = 0x00, - GROUPTYPE_BG = 0x01, - GROUPTYPE_RAID = 0x02, - GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask - GROUPTYPE_UNK1 = 0x04, - GROUPTYPE_LFG = 0x08 + GROUPTYPE_NORMAL = 0x00, + GROUPTYPE_BG = 0x01, + GROUPTYPE_RAID = 0x02, + GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask + GROUPTYPE_LFG_RESTRICTED = 0x04, // Script_HasLFGRestrictions() + GROUPTYPE_LFG = 0x08, // 0x10, leave/change group?, I saw this flag when leaving group and after leaving BG while in group + // GROUPTYPE_ONE_PERSON_PARTY = 0x20, 4.x Script_IsOnePersonParty() + // GROUPTYPE_EVERYONE_ASSISTANT = 0x40 4.x Script_IsEveryoneAssistant() }; enum GroupUpdateFlags diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index cfb7df6c34e..ac18a10c9a9 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -310,10 +310,14 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) - _player->AddQuestAndCheckCompletion(nextQuest, object); - - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); + // Only send the quest to the player if the conditions are met + if (_player->CanTakeQuest(nextQuest, true)) + { + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) + _player->AddQuestAndCheckCompletion(nextQuest, object); + + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); + } } _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); @@ -334,10 +338,14 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) - _player->AddQuestAndCheckCompletion(nextQuest, object); - - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); + // Only send the quest to the player if the conditions are met + if (_player->CanTakeQuest(nextQuest, true)) + { + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) + _player->AddQuestAndCheckCompletion(nextQuest, object); + + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); + } } _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 60475382d5e..26d348737ab 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -902,8 +902,13 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) slot_type = LOOT_SLOT_TYPE_ROLL_ONGOING; break; case MASTER_PERMISSION: - slot_type = LOOT_SLOT_TYPE_MASTER; + { + if (lv.viewer->GetGroup() && lv.viewer->GetGroup()->GetMasterLooterGuid() == lv.viewer->GetGUID()) + slot_type = LOOT_SLOT_TYPE_MASTER; + else + slot_type = LOOT_SLOT_TYPE_LOCKED; break; + } case RESTRICTED_PERMISSION: slot_type = LOOT_SLOT_TYPE_LOCKED; break; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index feef22c8a21..6d0ea9ea7a4 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -268,7 +268,7 @@ void WorldSession::SendPacket(WorldPacket* packet, bool forced /*= false*/) sScriptMgr->OnPacketSend(this, *packet); - m_Socket->AsyncWrite(*packet); + m_Socket->SendPacket(*packet); } /// Add an incoming packet to the queue diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 9a7b212da04..6cf406f21fa 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -32,19 +32,24 @@ std::string const WorldSocket::ServerConnectionInitialize("WORLD OF WARCRAFT CON std::string const WorldSocket::ClientConnectionInitialize("WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER"); -WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket), sizeof(ClientPktHeader)), - _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _initialized(false) + +WorldSocket::WorldSocket(tcp::socket&& socket) + : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _initialized(false) { + _headerBuffer.Resize(sizeof(ClientPktHeader)); } void WorldSocket::Start() { - sScriptMgr->OnSocketOpen(shared_from_this()); + AsyncRead(); - AsyncReadData(ClientConnectionInitialize.length() + 2 /*sizeof(ClientPktHeader::size)*/ + 1 /*null terminator*/); + MessageBuffer initializer; + ServerPktHeader header(ServerConnectionInitialize.size(), 0); + initializer.Write(header.header, header.getHeaderLength() - 2); + initializer.Write((void*)ServerConnectionInitialize.c_str(), ServerConnectionInitialize.length()); - _writeQueue.emplace(ServerConnectionInitialize); - AsyncWrite(_writeQueue.front()); + std::unique_lock<std::mutex> dummy(_writeLock, std::defer_lock); + QueuePacket(std::move(initializer), dummy); } void WorldSocket::HandleSendAuthSession() @@ -60,14 +65,69 @@ void WorldSocket::HandleSendAuthSession() packet << uint32(_authSeed); packet << uint8(1); - AsyncWrite(packet); + SendPacket(packet); +} + +void WorldSocket::ReadHandler() +{ + if (!IsOpen()) + return; + + MessageBuffer& packet = GetReadBuffer(); + while (packet.GetActiveSize() > 0) + { + if (_headerBuffer.GetRemainingSpace() > 0) + { + // need to receive the header + std::size_t readHeaderSize = std::min(packet.GetActiveSize(), _headerBuffer.GetRemainingSpace()); + _headerBuffer.Write(packet.GetReadPointer(), readHeaderSize); + packet.ReadCompleted(readHeaderSize); + + if (_headerBuffer.GetRemainingSpace() > 0) + { + // Couldn't receive the whole header this time. + ASSERT(packet.GetActiveSize() == 0); + break; + } + + // We just received nice new header + if (!ReadHeaderHandler()) + return; + } + + // We have full read header, now check the data payload + if (_packetBuffer.GetRemainingSpace() > 0) + { + // need more data in the payload + std::size_t readDataSize = std::min(packet.GetActiveSize(), _packetBuffer.GetRemainingSpace()); + _packetBuffer.Write(packet.GetReadPointer(), readDataSize); + packet.ReadCompleted(readDataSize); + + if (_packetBuffer.GetRemainingSpace() > 0) + { + // Couldn't receive the whole data this time. + ASSERT(packet.GetActiveSize() == 0); + break; + } + } + + // just received fresh new payload + if (!ReadDataHandler()) + return; + + _headerBuffer.Reset(); + } + + AsyncRead(); } -void WorldSocket::ReadHeaderHandler() +bool WorldSocket::ReadHeaderHandler() { - _authCrypt.DecryptRecv(GetHeaderBuffer(), sizeof(ClientPktHeader)); + ASSERT(_headerBuffer.GetActiveSize() == sizeof(ClientPktHeader)); + + _authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), sizeof(ClientPktHeader)); - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetHeaderBuffer()); + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); EndianConvertReverse(header->size); EndianConvert(header->cmd); @@ -81,26 +141,28 @@ void WorldSocket::ReadHeaderHandler() } else TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)", - GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd); + GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd); CloseSocket(); - return; + return false; } - AsyncReadData(header->size - sizeof(header->cmd)); + header->size -= sizeof(header->cmd); + _packetBuffer.Resize(header->size); + return true; } -void WorldSocket::ReadDataHandler() +bool WorldSocket::ReadDataHandler() { if (_initialized) { - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetHeaderBuffer()); + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); Opcodes opcode = PacketFilter::DropHighBytes(Opcodes(header->cmd)); std::string opcodeName = GetOpcodeNameForLogging(opcode); - WorldPacket packet(opcode, MoveData()); + WorldPacket packet(opcode, std::move(_packetBuffer)); if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort()); @@ -129,7 +191,7 @@ void WorldSocket::ReadDataHandler() packet.rfinish(); // contains uint32 disconnectReason; TC_LOG_DEBUG("network", "%s", opcodeName.c_str()); sScriptMgr->OnPacketReceive(_worldSession, packet); - return; + return true; case CMSG_ENABLE_NAGLE: { TC_LOG_DEBUG("network", "%s", opcodeName.c_str()); @@ -144,7 +206,7 @@ void WorldSocket::ReadDataHandler() { TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); CloseSocket(); - return; + return false; } // Our Idle timer will reset on any non PING opcodes. @@ -159,23 +221,23 @@ void WorldSocket::ReadDataHandler() } else { - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetDataBuffer()); + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); - std::string initializer(reinterpret_cast<char const*>(header) + sizeof(header->size)); + std::string initializer(reinterpret_cast<char const*>(_packetBuffer.GetReadPointer()), header->size); if (initializer != ClientConnectionInitialize) { CloseSocket(); - return; + return false; } _initialized = true; HandleSendAuthSession(); } - AsyncReadHeader(); + return true; } -void WorldSocket::AsyncWrite(WorldPacket& packet) +void WorldSocket::SendPacket(WorldPacket& packet) { if (!IsOpen()) return; @@ -190,15 +252,27 @@ void WorldSocket::AsyncWrite(WorldPacket& packet) ServerPktHeader header(packet.size() + 2, packet.GetOpcode()); - std::lock_guard<std::mutex> guard(_writeLock); + std::unique_lock<std::mutex> guard(_writeLock); - bool needsWriteStart = _writeQueue.empty(); _authCrypt.EncryptSend(header.header, header.getHeaderLength()); - _writeQueue.emplace(header, packet); +#ifndef BOOST_ASIO_HAS_IOCP + if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= header.getHeaderLength() + packet.size()) + { + _writeBuffer.Write(header.header, header.getHeaderLength()); + if (!packet.empty()) + _writeBuffer.Write(packet.contents(), packet.size()); + } + else +#endif + { + MessageBuffer buffer(header.getHeaderLength() + packet.size()); + buffer.Write(header.header, header.getHeaderLength()); + if (!packet.empty()) + buffer.Write(packet.contents(), packet.size()); - if (needsWriteStart) - AsyncWrite(_writeQueue.front()); + QueuePacket(std::move(buffer), guard); + } } void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) @@ -480,7 +554,7 @@ void WorldSocket::SendAuthResponseError(uint8 code) packet.WriteBit(0); // has account info packet << uint8(code); - AsyncWrite(packet); + SendPacket(packet); } void WorldSocket::HandlePing(WorldPacket& recvPacket) @@ -541,12 +615,5 @@ void WorldSocket::HandlePing(WorldPacket& recvPacket) WorldPacket packet(SMSG_PONG, 4); packet << ping; - return AsyncWrite(packet); -} - -void WorldSocket::CloseSocket() -{ - sScriptMgr->OnSocketClose(shared_from_this()); - - Socket::CloseSocket(); + return SendPacket(packet); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 9e5f785d939..6ba76584909 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -19,16 +19,6 @@ #ifndef __WORLDSOCKET_H__ #define __WORLDSOCKET_H__ -// Forward declare buffer function here - Socket.h must know about it -struct WorldPacketBuffer; -namespace boost -{ - namespace asio - { - WorldPacketBuffer const& buffer(WorldPacketBuffer const& buf); - } -} - #include "Common.h" #include "WorldPacketCrypt.h" #include "ServerPktHeader.h" @@ -54,58 +44,8 @@ struct ClientPktHeader #pragma pack(pop) -struct WorldPacketBuffer -{ - typedef boost::asio::const_buffer value_type; - - typedef boost::asio::const_buffer const* const_iterator; - - WorldPacketBuffer(ServerPktHeader header, WorldPacket const& packet) : _header(header), _packet(packet), _bufferCount(0) - { - _buffers[_bufferCount++] = boost::asio::const_buffer(_header.header, _header.getHeaderLength()); - if (!_packet.empty()) - _buffers[_bufferCount++] = boost::asio::const_buffer(_packet.contents(), _packet.size()); - } - - WorldPacketBuffer(std::string const& str) : _header(str.length() + 1 /*null terminator*/, 0), _packet(), _bufferCount(0) - { - _buffers[_bufferCount++] = boost::asio::const_buffer(_header.header, _header.getHeaderLength() - 2 /*sizeof(opcode)*/); - if (!str.empty()) - _buffers[_bufferCount++] = boost::asio::const_buffer(str.c_str(), _header.size); - } - - const_iterator begin() const - { - return _buffers; - } - - const_iterator end() const - { - return _buffers + _bufferCount; - } - -private: - boost::asio::const_buffer _buffers[2]; - ServerPktHeader _header; - WorldPacket _packet; - uint32 _bufferCount; -}; - -namespace boost -{ - namespace asio - { - inline WorldPacketBuffer const& buffer(WorldPacketBuffer const& buf) - { - return buf; - } - } -} - -class WorldSocket : public Socket<WorldSocket, WorldPacketBuffer> +class WorldSocket : public Socket<WorldSocket> { - typedef Socket<WorldSocket, WorldPacketBuffer> Base; - static std::string const ServerConnectionInitialize; static std::string const ClientConnectionInitialize; @@ -118,14 +58,12 @@ public: void Start() override; - void CloseSocket() override; - - using Base::AsyncWrite; - void AsyncWrite(WorldPacket& packet); + void SendPacket(WorldPacket& packet); protected: - void ReadHeaderHandler() override; - void ReadDataHandler() override; + void ReadHandler() override; + bool ReadHeaderHandler(); + bool ReadDataHandler(); private: void HandleSendAuthSession(); @@ -141,6 +79,10 @@ private: uint32 _OverSpeedPings; WorldSession* _worldSession; + + MessageBuffer _headerBuffer; + MessageBuffer _packetBuffer; + bool _initialized; }; diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp new file mode 100644 index 00000000000..21f62fa265c --- /dev/null +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +#include "Config.h" +#include "NetworkThread.h" +#include "ScriptMgr.h" +#include "WorldSocket.h" +#include "WorldSocketMgr.h" +#include <boost/system/error_code.hpp> + +static void OnSocketAccept(tcp::socket&& sock) +{ + sWorldSocketMgr.OnSocketOpen(std::forward<tcp::socket>(sock)); +} + +class WorldSocketThread : public NetworkThread<WorldSocket> +{ +public: + void SocketAdded(std::shared_ptr<WorldSocket> sock) override + { + sScriptMgr->OnSocketOpen(sock); + } + + void SocketRemoved(std::shared_ptr<WorldSocket> sock) override + { + sScriptMgr->OnSocketClose(sock); + } +}; + +WorldSocketMgr::WorldSocketMgr() : BaseSocketMgr(), _socketSendBufferSize(-1), m_SockOutUBuff(65536), _tcpNoDelay(true) +{ +} + +bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) +{ + _tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true); + + TC_LOG_DEBUG("misc", "Max allowed socket connections %d", boost::asio::socket_base::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); + + _acceptor->AsyncAcceptManaged(&OnSocketAccept); + + sScriptMgr->OnNetworkStart(); + return true; +} + +void WorldSocketMgr::StopNetwork() +{ + BaseSocketMgr::StopNetwork(); + + sScriptMgr->OnNetworkStop(); +} + +void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock) +{ + // 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<size_t> (m_SockOutUBuff); + + BaseSocketMgr::OnSocketOpen(std::forward<tcp::socket>(sock)); +} + +NetworkThread<WorldSocket>* WorldSocketMgr::CreateThreads() const +{ + return new WorldSocketThread[GetNetworkThreadCount()]; +} diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h new file mode 100644 index 00000000000..92a28d0c135 --- /dev/null +++ b/src/server/game/Server/WorldSocketMgr.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +/** \addtogroup u2w User to World Communication + * @{ + * \file WorldSocketMgr.h + * \author Derex <derex101@gmail.com> + */ + +#ifndef __WORLDSOCKETMGR_H +#define __WORLDSOCKETMGR_H + +#include "SocketMgr.h" + +class WorldSocket; + +/// Manages all sockets connected to peers and network threads +class WorldSocketMgr : public SocketMgr<WorldSocket> +{ + typedef SocketMgr<WorldSocket> BaseSocketMgr; + +public: + static WorldSocketMgr& Instance() + { + static WorldSocketMgr instance; + return instance; + } + + /// Start network, listen at address:port . + bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override; + + /// Stops all network threads, It will wait for all running threads . + void StopNetwork() override; + + void OnSocketOpen(tcp::socket&& sock) override; + +protected: + WorldSocketMgr(); + + NetworkThread<WorldSocket>* CreateThreads() const override; + +private: + int32 _socketSendBufferSize; + int32 m_SockOutUBuff; + bool _tcpNoDelay; +}; + +#define sWorldSocketMgr WorldSocketMgr::Instance() + +#endif +/// @} |
