diff options
Diffstat (limited to 'src')
29 files changed, 244 insertions, 125 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index b2fb516804f..efffbda2e91 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -18,7 +18,6 @@ #include "AuthSession.h" #include "Log.h" -#include "ByteBuffer.h" #include "AuthCodes.h" #include "Database/DatabaseEnv.h" #include "SHA1.h" @@ -173,19 +172,16 @@ void AuthSession::ReadDataHandler(boost::system::error_code error, size_t transf CloseSocket(); } -void AuthSession::AsyncWrite(ByteBuffer const& packet) +void AuthSession::AsyncWrite(ByteBuffer& packet) { - std::vector<uint8> data(packet.size()); - std::memcpy(data.data(), packet.contents(), packet.size()); - std::lock_guard<std::mutex> guard(_writeLock); bool needsWriteStart = _writeQueue.empty(); - _writeQueue.push(std::move(data)); + _writeQueue.push(std::move(packet)); if (needsWriteStart) - AsyncWrite(_writeQueue.front()); + Base::AsyncWrite(_writeQueue.front()); } bool AuthSession::HandleLogonChallenge() diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index eedffb86ff8..14129d76fd8 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -20,6 +20,7 @@ #define __AUTHSESSION_H__ #include "Common.h" +#include "ByteBuffer.h" #include "Socket.h" #include "BigNumber.h" #include <memory> @@ -28,10 +29,10 @@ using boost::asio::ip::tcp; struct AuthHandler; -class ByteBuffer; -class AuthSession : public Socket<AuthSession> +class AuthSession : public Socket<AuthSession, ByteBuffer> { + typedef Socket<AuthSession, ByteBuffer> Base; public: static std::unordered_map<uint8, AuthHandler> InitHandlers(); @@ -47,8 +48,8 @@ public: AsyncReadHeader(); } - using Socket<AuthSession>::AsyncWrite; - void AsyncWrite(ByteBuffer const& packet); + using Base::AsyncWrite; + void AsyncWrite(ByteBuffer& packet); protected: void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; diff --git a/src/server/authserver/Server/BattlenetBitStream.h b/src/server/authserver/Server/BattlenetBitStream.h index 86bf5549380..90f883856a3 100644 --- a/src/server/authserver/Server/BattlenetBitStream.h +++ b/src/server/authserver/Server/BattlenetBitStream.h @@ -234,4 +234,15 @@ namespace Battlenet bool BitStream::Read<bool>(uint32 bitCount); } +namespace boost +{ + namespace asio + { + inline const_buffers_1 buffer(Battlenet::BitStream const& stream) + { + return buffer(stream.GetBuffer(), stream.GetSize()); + } + } +} + #endif // __BATTLENETBITSTREAM_H__ diff --git a/src/server/authserver/Server/BattlenetSession.h b/src/server/authserver/Server/BattlenetSession.h index 4c1614cb839..705aa468a4c 100644 --- a/src/server/authserver/Server/BattlenetSession.h +++ b/src/server/authserver/Server/BattlenetSession.h @@ -20,6 +20,7 @@ #include "BattlenetPackets.h" #include "BattlenetPacketCrypt.h" +#include "Socket.h" #include "BigNumber.h" #include <memory> #include <boost/asio/ip/tcp.hpp> diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index e47a23d467c..64116b8f8c1 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -642,7 +642,7 @@ void CalendarMgr::SendCalendarCommandResult(uint64 guid, CalendarError err, char } } -void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket packet, CalendarEvent const& calendarEvent) +void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket& packet, CalendarEvent const& calendarEvent) { // Send packet to all guild members if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement()) diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h index 3dadcbdf645..cd527a7373e 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -330,7 +330,7 @@ class CalendarMgr void SendCalendarClearPendingAction(uint64 guid); void SendCalendarCommandResult(uint64 guid, CalendarError err, char const* param = NULL); - void SendPacketToAllEventRelatives(WorldPacket packet, CalendarEvent const& calendarEvent); + void SendPacketToAllEventRelatives(WorldPacket& packet, CalendarEvent const& calendarEvent); }; #define sCalendarMgr CalendarMgr::instance() diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 13d725dbbe2..51087e0f966 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -712,7 +712,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons if (iter == data_map.end()) { - std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData(player->GetMapId()))); + std::pair<UpdateDataMapType::iterator, bool> p = data_map.emplace(player, UpdateData(player->GetMapId())); ASSERT(p.second); iter = p.first; } diff --git a/src/server/game/Entities/Object/Updates/UpdateData.h b/src/server/game/Entities/Object/Updates/UpdateData.h index 1deccfa237b..e0666a1a717 100644 --- a/src/server/game/Entities/Object/Updates/UpdateData.h +++ b/src/server/game/Entities/Object/Updates/UpdateData.h @@ -55,6 +55,11 @@ class UpdateData { public: UpdateData(uint16 map); + UpdateData(UpdateData&& right) : m_map(right.m_map), m_blockCount(right.m_blockCount), + m_outOfRangeGUIDs(std::move(right.m_outOfRangeGUIDs)), + m_data(std::move(right.m_data)) + { + } void AddOutOfRangeGUID(std::set<uint64>& guids); void AddOutOfRangeGUID(uint64 guid); @@ -70,6 +75,9 @@ class UpdateData uint32 m_blockCount; std::set<uint64> m_outOfRangeGUIDs; ByteBuffer m_data; + + UpdateData(UpdateData const& right) = delete; + UpdateData& operator=(UpdateData const& right) = delete; }; #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2a3b903513e..f096170c46d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2118,7 +2118,11 @@ void Unit::SendMeleeAttackStop(Unit* victim) { WorldPacket data(SMSG_ATTACKSTOP, (8+8+4)); data.append(GetPackGUID()); - data.append(victim ? victim->GetPackGUID() : 0); + if (victim) + data.append(victim->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); //! Can also take the value 0x01, which seems related to updating rotation SendMessageToSet(&data, true); TC_LOG_DEBUG("entities.unit", "WORLD: Sent SMSG_ATTACKSTOP"); diff --git a/src/server/game/Handlers/CombatHandler.cpp b/src/server/game/Handlers/CombatHandler.cpp index 47ffc2578bd..e4d749d9ab0 100644 --- a/src/server/game/Handlers/CombatHandler.cpp +++ b/src/server/game/Handlers/CombatHandler.cpp @@ -93,7 +93,11 @@ void WorldSession::SendAttackStop(Unit const* enemy) { WorldPacket data(SMSG_ATTACKSTOP, (8+8+4)); // we guess size data.append(GetPlayer()->GetPackGUID()); - data.append(enemy ? enemy->GetPackGUID() : 0); // must be packed guid + if (enemy) + data.append(enemy->GetPackGUID()); + else + data << uint8(0); + data << uint32(0); // unk, can be 1 also SendPacket(&data); } diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp index 97d5ea8310e..a6e63d196c2 100644 --- a/src/server/game/Handlers/GuildHandler.cpp +++ b/src/server/game/Handlers/GuildHandler.cpp @@ -746,7 +746,7 @@ void WorldSession::HandleAutoDeclineGuildInvites(WorldPacket& recvPacket) uint8 enable; recvPacket >> enable; - GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_AUTO_DECLINE_GUILD, enable); + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_AUTO_DECLINE_GUILD, enable != 0); } void WorldSession::HandleGuildRewardsQueryOpcode(WorldPacket& recvPacket) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c69f7863ef6..75301da32ed 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2705,7 +2705,7 @@ uint32 Map::GetPlayersCountExceptGMs() const return count; } -void Map::SendToPlayers(WorldPacket const* data) const +void Map::SendToPlayers(WorldPacket* data) const { for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) itr->GetSource()->GetSession()->SendPacket(data); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index c676a5c5ce0..c194f4dccd7 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -423,7 +423,7 @@ class Map : public GridRefManager<NGridType> void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); } void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); } - void SendToPlayers(WorldPacket const* data) const; + void SendToPlayers(WorldPacket* data) const; typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 78c6c98cb59..e1a15fa52b5 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -60,12 +60,12 @@ namespace Movement { MoveSpline& move_spline = *unit->movespline; - bool transport = unit->GetTransGUID(); + bool transport = unit->GetTransGUID() != 0; Location real_position; // there is a big chance that current position is unknown if current state is not finalized, need compute it // this also allows calculate spline position and update map position in much greater intervals // Don't compute for transport movement if the unit is in a motion between two transports - if (!move_spline.Finalized() && move_spline.onTransport == (unit->GetTransGUID() != 0)) + if (!move_spline.Finalized() && move_spline.onTransport == transport) real_position = move_spline.ComputePosition(); else { @@ -138,7 +138,7 @@ namespace Movement if (move_spline.Finalized()) return; - bool transport = unit->GetTransGUID(); + bool transport = unit->GetTransGUID() != 0; Location loc; if (move_spline.onTransport == transport) loc = move_spline.ComputePosition(); @@ -178,7 +178,7 @@ namespace Movement { args.splineId = splineIdGen.NewId(); // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes - args.TransformForTransport = unit->GetTransGUID(); + args.TransformForTransport = unit->GetTransGUID() != 0; // mix existing state into new args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); args.flags.flying = unit->m_movementInfo.HasMovementFlag(MovementFlags(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY)); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index e437875d57a..6d0be13c35e 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -414,25 +414,37 @@ void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> socket, bool wasNew) FOREACH_SCRIPT(ServerScript)->OnSocketClose(socket, wasNew); } -void ScriptMgr::OnPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket packet) +void ScriptMgr::OnPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet) { ASSERT(socket); - FOREACH_SCRIPT(ServerScript)->OnPacketReceive(socket, packet); + if (SCR_REG_LST(ServerScript).empty()) + return; + + WorldPacket copy(packet); + FOREACH_SCRIPT(ServerScript)->OnPacketReceive(socket, copy); } -void ScriptMgr::OnPacketSend(std::shared_ptr<WorldSocket> socket, WorldPacket packet) +void ScriptMgr::OnPacketSend(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet) { ASSERT(socket); - FOREACH_SCRIPT(ServerScript)->OnPacketSend(socket, packet); + if (SCR_REG_LST(ServerScript).empty()) + return; + + WorldPacket copy(packet); + FOREACH_SCRIPT(ServerScript)->OnPacketSend(socket, copy); } -void ScriptMgr::OnUnknownPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket packet) +void ScriptMgr::OnUnknownPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet) { ASSERT(socket); - FOREACH_SCRIPT(ServerScript)->OnUnknownPacketReceive(socket, packet); + if (SCR_REG_LST(ServerScript).empty()) + return; + + WorldPacket copy(packet); + FOREACH_SCRIPT(ServerScript)->OnUnknownPacketReceive(socket, copy); } void ScriptMgr::OnOpenStateChange(bool open) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index bc58519fde4..104410a1345 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -909,9 +909,9 @@ class ScriptMgr void OnNetworkStop(); void OnSocketOpen(std::shared_ptr<WorldSocket> socket); void OnSocketClose(std::shared_ptr<WorldSocket> socket, bool wasNew); - void OnPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket packet); - void OnPacketSend(std::shared_ptr<WorldSocket> socket, WorldPacket packet); - void OnUnknownPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket packet); + void OnPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet); + void OnPacketSend(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet); + void OnUnknownPacketReceive(std::shared_ptr<WorldSocket> socket, WorldPacket const& packet); public: /* WorldScript */ diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h index e2498e64f0a..3e812621b48 100644 --- a/src/server/game/Server/WorldPacket.h +++ b/src/server/game/Server/WorldPacket.h @@ -33,15 +33,28 @@ class WorldPacket : public ByteBuffer { } - WorldPacket(Opcodes opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) + explicit WorldPacket(Opcodes opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } + + WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode) + { + } + + WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode) { } - // copy constructor - WorldPacket(WorldPacket const& packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) + + WorldPacket& operator=(WorldPacket const& right) { + if (this != &right) + { + m_opcode = right.m_opcode; + ByteBuffer::operator =(right); + } + + return *this; } - void Initialize(Opcodes opcode, size_t newres = 200) + void Initialize(Opcodes opcode, size_t newres=200) { clear(); _storage.reserve(newres); @@ -58,5 +71,5 @@ class WorldPacket : public ByteBuffer void Compress(void* dst, uint32 *dst_size, const void* src, int src_size); z_stream_s* _compressionStream; }; -#endif +#endif diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 46411b35522..227555c1dfa 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -206,7 +206,7 @@ uint32 WorldSession::GetGuidLow() const } /// Send a packet to the client -void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/) +void WorldSession::SendPacket(WorldPacket* packet, bool forced /*= false*/) { if (!m_Socket) return; @@ -350,7 +350,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) } else if (_player->IsInWorld()) { - sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnPacketReceive(m_Socket, *packet); (this->*opHandle->Handler)(*packet); LogUnprocessedTail(packet); } @@ -363,7 +363,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) else { // not expected _player or must checked in packet hanlder - sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnPacketReceive(m_Socket, *packet); (this->*opHandle->Handler)(*packet); LogUnprocessedTail(packet); } @@ -375,7 +375,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world"); else { - sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnPacketReceive(m_Socket, *packet); (this->*opHandle->Handler)(*packet); LogUnprocessedTail(packet); } @@ -393,7 +393,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (packet->GetOpcode() == CMSG_CHAR_ENUM) m_playerRecentlyLogout = false; - sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnPacketReceive(m_Socket, *packet); (this->*opHandle->Handler)(*packet); LogUnprocessedTail(packet); break; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 96a66bf2421..bd159475c37 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -185,7 +185,7 @@ class CharacterCreateInfo protected: CharacterCreateInfo(std::string const& name, uint8 race, uint8 cclass, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId, WorldPacket& data) : Name(name), Race(race), Class(cclass), Gender(gender), Skin(skin), Face(face), HairStyle(hairStyle), HairColor(hairColor), FacialHair(facialHair), - OutfitId(outfitId), Data(data), CharCount(0) + OutfitId(outfitId), Data(std::move(data)), CharCount(0) { } /// User specified variables @@ -227,7 +227,7 @@ class WorldSession void SendAddonsInfo(); bool IsAddonRegistered(const std::string& prefix) const; - void SendPacket(WorldPacket const* packet, bool forced = false); + void SendPacket(WorldPacket* packet, bool forced = false); void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3); void SendNotification(uint32 string_id, ...); void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName *declinedName); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 48c12f84870..46a1bf8f16d 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -18,7 +18,6 @@ #include <memory> #include "WorldSocket.h" -#include "ServerPktHeader.h" #include "BigNumber.h" #include "Opcodes.h" #include "ScriptMgr.h" @@ -175,35 +174,24 @@ void WorldSocket::ReadDataHandler(boost::system::error_code error, size_t transf CloseSocket(); } -void WorldSocket::AsyncWrite(WorldPacket const& packet) +void WorldSocket::AsyncWrite(WorldPacket& packet) { if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(packet, SERVER_TO_CLIENT); - WorldPacket const* pkt = &packet; - WorldPacket buff; // Empty buffer used in case packet should be compressed if (_worldSession && packet.size() > 0x400) - { - buff.Compress(_worldSession->GetCompressionStream(), pkt); - pkt = &buff; - } - - TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(pkt->GetOpcode()).c_str()); - - ServerPktHeader header(pkt->size() + 2, pkt->GetOpcode()); + packet.Compress(_worldSession->GetCompressionStream()); - std::vector<uint8> data(header.getHeaderLength() + pkt->size()); - std::memcpy(data.data(), header.header, header.getHeaderLength()); + TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str()); - if (!pkt->empty()) - std::memcpy(&data[header.getHeaderLength()], pkt->contents(), pkt->size()); + ServerPktHeader header(packet.size() + 2, packet.GetOpcode()); std::lock_guard<std::mutex> guard(_writeLock); bool needsWriteStart = _writeQueue.empty(); - _authCrypt.EncryptSend(data.data(), header.getHeaderLength()); + _authCrypt.EncryptSend(header.header, header.getHeaderLength()); - _writeQueue.push(std::move(data)); + _writeQueue.emplace(header, std::move(packet)); if (needsWriteStart) AsyncWrite(_writeQueue.front()); diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index ca50b46efb0..4e1cbe743fd 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -19,14 +19,26 @@ #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" #include "Socket.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" #include <chrono> #include <boost/asio/ip/tcp.hpp> +#include <boost/asio/buffer.hpp> using boost::asio::ip::tcp; @@ -40,8 +52,50 @@ struct ClientPktHeader #pragma pack(pop) -class WorldSocket : public Socket<WorldSocket> +struct WorldPacketBuffer { + typedef boost::asio::const_buffer value_type; + + typedef boost::asio::const_buffer const* const_iterator; + + WorldPacketBuffer(ServerPktHeader header, WorldPacket&& packet) : _header(header), _packet(std::move(packet)) + { + _buffers[0] = boost::asio::const_buffer(_header.header, _header.getHeaderLength()); + if (!_packet.empty()) + _buffers[1] = boost::asio::const_buffer(_packet.contents(), _packet.size()); + } + + const_iterator begin() const + { + return _buffers; + } + + const_iterator end() const + { + return _buffers + (_packet.empty() ? 1 : 2); + } + +private: + boost::asio::const_buffer _buffers[2]; + ServerPktHeader _header; + WorldPacket _packet; +}; + +namespace boost +{ + namespace asio + { + inline WorldPacketBuffer const& buffer(WorldPacketBuffer const& buf) + { + return buf; + } + } +} + +class WorldSocket : public Socket<WorldSocket, WorldPacketBuffer> +{ + typedef Socket<WorldSocket, WorldPacketBuffer> Base; + public: WorldSocket(tcp::socket&& socket); @@ -50,8 +104,8 @@ public: void Start() override; - void AsyncWrite(WorldPacket const& packet); - using Socket<WorldSocket>::AsyncWrite; + using Base::AsyncWrite; + void AsyncWrite(WorldPacket& packet); protected: void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp index e444d6793e6..81f81fda4c4 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp @@ -112,26 +112,6 @@ public: (*itr)->DespawnOrUnsummon(); } - void SendWeather(WeatherState weather, float grade) const - { - WorldPacket data(SMSG_WEATHER, 9); - data << uint32(weather); - data << float(grade); - data << uint8(0); - SendPacketToPlayers(&data); - } - - // Send packet to all players in Tomb of the Earthrager - void SendPacketToPlayers(WorldPacket const* data) const - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.isEmpty()) - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (Player* player = itr->GetSource()) - if (player->GetAreaId() == AREA_TOMB_OF_THE_EARTHRAGER) - player->GetSession()->SendPacket(data); - } - void Reset() override { _summonDeaths = 0; @@ -153,7 +133,7 @@ public: me->AttackStop(); DoCast(me, SPELL_SANDSTORM); - SendWeather(WEATHER_STATE_LIGHT_SANDSTORM, 1.0f); + me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_LIGHT_SANDSTORM, 1.0f); events.ScheduleEvent(EVENT_PTAH_EXPLODE, 6000, 0, PHASE_DISPERSE); events.ScheduleEvent(EVENT_QUICKSAND, 10000, 0, PHASE_DISPERSE); @@ -185,7 +165,7 @@ public: ++_summonDeaths; if (_summonDeaths == 11) // All summons died { - SendWeather(WEATHER_STATE_FOG, 0.0f); + me->GetMap()->SetZoneWeather(AREA_TOMB_OF_THE_EARTHRAGER, WEATHER_STATE_FOG, 0.0f); me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION); events.SetPhase(PHASE_NORMAL); events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL); diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h index b4022baaadc..9c05ed49c05 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h @@ -100,7 +100,7 @@ enum GameObjects enum Misc { - AREA_TOMB_OF_THE_EARTHRAGER = 5610, + AREA_TOMB_OF_THE_EARTHRAGER = 4945, ACHIEV_VAULT_OF_LIGHTS_EVENT = 24212, // Faster Than The Speed Of Light SPELL_VAULT_OF_LIGHTS_CREDIT = 94067, // Not in DBC }; diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 676418c27a7..9c3ec180b0a 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 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 @@ -26,12 +25,13 @@ #include <queue> #include <memory> #include <functional> +#include <type_traits> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/write.hpp> using boost::asio::ip::tcp; -template<class T> +template<class T, class PacketType> class Socket : public std::enable_shared_from_this<T> { public: @@ -44,31 +44,44 @@ public: void AsyncReadHeader() { - _socket.async_read_some(boost::asio::buffer(_readBuffer, _headerSize), std::bind(&Socket<T>::ReadHeaderHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + _socket.async_read_some(boost::asio::buffer(_readBuffer, _headerSize), std::bind(&Socket<T, PacketType>::ReadHeaderHandlerInternal, this->shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } void AsyncReadData(std::size_t size, std::size_t bufferOffset) { - _socket.async_read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), std::bind(&Socket<T>::ReadDataHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + _socket.async_read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), std::bind(&Socket<T, PacketType>::ReadDataHandlerInternal, this->shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } void ReadData(std::size_t size, std::size_t bufferOffset) { - _socket.read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size)); + boost::system::error_code error; + + _socket.read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), error); + + if (error) + { + TC_LOG_DEBUG("network", "Socket::ReadData: %s errored with: %i (%s)", GetRemoteIpAddress().to_string().c_str(), error.value(), error.message().c_str()); + + CloseSocket(); + } } - void AsyncWrite(std::vector<uint8> const& data) + void AsyncWrite(PacketType const& data) { - boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket<T>::WriteHandler, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket<T, PacketType>::WriteHandler, this->shared_from_this(), std::placeholders::_1, + std::placeholders::_2)); } bool IsOpen() const { return _socket.is_open(); } void CloseSocket() { - boost::system::error_code socketError; - _socket.close(socketError); - if (socketError) - TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when closing socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), socketError.value(), socketError.message().c_str()); + boost::system::error_code error; + _socket.close(error); + if (error) + TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when closing socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), + error.value(), error.message().c_str()); } uint8* GetReadBuffer() { return _readBuffer; } @@ -78,7 +91,7 @@ protected: virtual void ReadDataHandler(boost::system::error_code error, size_t transferedBytes) = 0; std::mutex _writeLock; - std::queue<std::vector<uint8> > _writeQueue; + std::queue<PacketType> _writeQueue; private: void ReadHeaderHandlerInternal(boost::system::error_code error, size_t transferedBytes) { ReadHeaderHandler(error, transferedBytes); } @@ -90,6 +103,7 @@ private: { std::lock_guard<std::mutex> deleteGuard(_writeLock); + DeletePacket(_writeQueue.front()); _writeQueue.pop(); if (!_writeQueue.empty()) @@ -99,6 +113,12 @@ private: CloseSocket(); } + template<typename Q = PacketType> + typename std::enable_if<std::is_pointer<Q>::value>::type DeletePacket(PacketType& packet) { delete packet; } + + template<typename Q = PacketType> + typename std::enable_if<!std::is_pointer<Q>::value>::type DeletePacket(PacketType const& /*packet*/) { } + tcp::socket _socket; uint8 _readBuffer[4096]; diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index ba4894fc32e..520c1a85fc2 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -32,6 +32,7 @@ #include <cstring> #include <time.h> #include <math.h> +#include <boost/asio/buffer.hpp> // Root of ByteBuffer exception hierarchy class ByteBufferException : public std::exception @@ -80,12 +81,30 @@ class ByteBuffer _storage.reserve(reserve); } - // copy constructor - ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos), - _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf._storage) + ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos), + _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(std::move(buf._storage)) { } + ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos), + _bitpos(right._bitpos), _curbitval(right._curbitval), _storage(right._storage) + { + } + + ByteBuffer& operator=(ByteBuffer const& right) + { + if (this != &right) + { + _rpos = right._rpos; + _wpos = right._wpos; + _bitpos = right._bitpos; + _curbitval = right._curbitval; + _storage = right._storage; + } + + return *this; + } + virtual ~ByteBuffer() { } void clear() @@ -510,18 +529,18 @@ class ByteBuffer return *this; } - uint8 * contents() + uint8* contents() { if (_storage.empty()) throw ByteBufferException(); - return &_storage[0]; + return _storage.data(); } - const uint8 *contents() const + uint8 const* contents() const { if (_storage.empty()) throw ByteBufferException(); - return &_storage[0]; + return _storage.data(); } size_t size() const { return _storage.size(); } @@ -737,5 +756,15 @@ inline void ByteBuffer::read_skip<std::string>() read_skip<char*>(); } -#endif +namespace boost +{ + namespace asio + { + inline const_buffers_1 buffer(ByteBuffer const& packet) + { + return buffer(packet.contents(), packet.size()); + } + } +} +#endif diff --git a/src/server/shared/Threading/ProducerConsumerQueue.h b/src/server/shared/Threading/ProducerConsumerQueue.h index 45a1cbc692a..1fee1d0685f 100644 --- a/src/server/shared/Threading/ProducerConsumerQueue.h +++ b/src/server/shared/Threading/ProducerConsumerQueue.h @@ -22,12 +22,11 @@ #include <mutex> #include <queue> #include <atomic> +#include <type_traits> template <typename T> class ProducerConsumerQueue { - static_assert(std::is_pointer<T>::value, "T for ProducerConsumerQueue must be a pointer"); - private: std::mutex _queueLock; std::queue<T> _queue; @@ -94,7 +93,7 @@ public: { T& value = _queue.front(); - delete value; + DeleteQueuedObject(value); _queue.pop(); } @@ -105,8 +104,13 @@ public: _condition.notify_all(); } -}; -#endif +private: + template<typename E = T> + typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; } + template<typename E = T> + typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { } +}; +#endif diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index fcb4010075f..ce512628e98 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -196,11 +196,10 @@ Compression = 1 # Description: Maximum number of players in the world. Excluding Mods, GMs and Admins. # Important: If you want to block players and only allow Mods, GMs or Admins to join the # server, use the DB field "auth.realmlist.allowedSecurityLevel". -# Default: 100 - (Enabled) +# Default: 0 - (Disabled, No limit) # 1+ - (Enabled) -# 0 - (Disabled, No limit) -PlayerLimit = 100 +PlayerLimit = 0 # # SaveRespawnTimeImmediately diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 94b5f3607cf..3437355c0a9 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -171,19 +171,14 @@ namespace MMAP { while (1) { - uint32* mapId = nullptr; + uint32 mapId; _queue.WaitAndPop(mapId); if (_cancelationToken) return; - if (!mapId) // shouldn't happen? - continue; - - buildMap(*mapId); - - delete mapId; + buildMap(mapId); } } @@ -205,7 +200,7 @@ namespace MMAP if (!shouldSkipMap(mapId)) { if (threads > 0) - _queue.Push(new uint32(mapId)); + _queue.Push(mapId); else buildMap(mapId); } diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index c2168d048b4..1d688ccfa77 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -143,7 +143,7 @@ namespace MMAP rcContext* m_rcContext; std::vector<std::thread> _workerThreads; - ProducerConsumerQueue<uint32*> _queue; + ProducerConsumerQueue<uint32> _queue; std::atomic<bool> _cancelationToken; }; } |