From e77c0b6ed4516c09c648a6443b054b8b9e1edcf1 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 27 Jul 2014 14:59:46 +0200 Subject: Core/Network: Allow storing any packet types in Socket write queue to reduce the amount of copying going on --- src/server/authserver/Server/AuthSession.cpp | 10 +++------- src/server/authserver/Server/AuthSession.h | 9 +++++---- src/server/game/Server/WorldSocket.h | 6 ++++-- src/server/shared/Networking/Socket.h | 27 +++++++++++++++++++-------- src/server/shared/Packets/ByteBuffer.h | 13 ++++++++++++- 5 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index cc5dc8cbb1b..697fe027f5e 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 data(packet.size()); - std::memcpy(data.data(), packet.contents(), packet.size()); - std::lock_guard 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..822f3c334fc 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -22,16 +22,17 @@ #include "Common.h" #include "Socket.h" #include "BigNumber.h" +#include "ByteBuffer.h" #include #include using boost::asio::ip::tcp; struct AuthHandler; -class ByteBuffer; -class AuthSession : public Socket +class AuthSession : public Socket { + typedef Socket Base; public: static std::unordered_map InitHandlers(); @@ -47,8 +48,8 @@ public: AsyncReadHeader(); } - using Socket::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/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 57732547b17..f355308ff7a 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -40,8 +40,10 @@ struct ClientPktHeader #pragma pack(pop) -class WorldSocket : public Socket +class WorldSocket : public Socket > { + typedef Socket > Base; + public: WorldSocket(tcp::socket&& socket); @@ -50,8 +52,8 @@ public: void Start() override; + using Base::AsyncWrite; void AsyncWrite(WorldPacket const& packet); - using Socket::AsyncWrite; protected: void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 676418c27a7..96f597257be 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2005-2009 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 @@ -26,12 +25,13 @@ #include #include #include +#include #include #include using boost::asio::ip::tcp; -template +template class Socket : public std::enable_shared_from_this { public: @@ -44,12 +44,14 @@ public: void AsyncReadHeader() { - _socket.async_read_some(boost::asio::buffer(_readBuffer, _headerSize), std::bind(&Socket::ReadHeaderHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + _socket.async_read_some(boost::asio::buffer(_readBuffer, _headerSize), std::bind(&Socket::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::ReadDataHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + _socket.async_read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), std::bind(&Socket::ReadDataHandlerInternal, this->shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } void ReadData(std::size_t size, std::size_t bufferOffset) @@ -57,9 +59,10 @@ public: _socket.read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size)); } - void AsyncWrite(std::vector const& data) + void AsyncWrite(PacketType const& data) { - boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket::WriteHandler, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket::WriteHandler, this->shared_from_this(), std::placeholders::_1, + std::placeholders::_2)); } bool IsOpen() const { return _socket.is_open(); } @@ -68,7 +71,8 @@ public: 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()); + TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when closing socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), + socketError.value(), socketError.message().c_str()); } uint8* GetReadBuffer() { return _readBuffer; } @@ -78,7 +82,7 @@ protected: virtual void ReadDataHandler(boost::system::error_code error, size_t transferedBytes) = 0; std::mutex _writeLock; - std::queue > _writeQueue; + std::queue _writeQueue; private: void ReadHeaderHandlerInternal(boost::system::error_code error, size_t transferedBytes) { ReadHeaderHandler(error, transferedBytes); } @@ -90,6 +94,7 @@ private: { std::lock_guard deleteGuard(_writeLock); + DeletePacket(_writeQueue.front()); _writeQueue.pop(); if (!_writeQueue.empty()) @@ -99,6 +104,12 @@ private: CloseSocket(); } + template + typename std::enable_if::value>::type DeletePacket(PacketType& packet) { delete packet; } + + template + typename std::enable_if::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 81c6bcd977c..311143b384c 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -32,6 +32,7 @@ #include #include #include +#include // Root of ByteBuffer exception hierarchy class ByteBufferException : public std::exception @@ -608,5 +609,15 @@ inline void ByteBuffer::read_skip() read_skip(); } -#endif +namespace boost +{ + namespace asio + { + inline const_buffers_1 buffer(ByteBuffer const& packet) + { + return buffer(packet.contents(), packet.size()); + } + } +} +#endif -- cgit v1.2.3 From 7c498a0cf960b43b6974d99f0cf265911c296711 Mon Sep 17 00:00:00 2001 From: Dr-J Date: Sun, 27 Jul 2014 15:03:22 +0100 Subject: DB/Misc: Fix some spell area issues Add spell area entries so some spells get removed when players leaves zone where its intended to be used: - Closes #12669 Also fixes imbued scourge shroud http://www.wowhead.com/item=34782/imbued-scourge-shroud so the aura gets removed when player leaves the Temple City of En'kilah. --- sql/updates/world/2014_07_27_03_world_misc.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 sql/updates/world/2014_07_27_03_world_misc.sql diff --git a/sql/updates/world/2014_07_27_03_world_misc.sql b/sql/updates/world/2014_07_27_03_world_misc.sql new file mode 100644 index 00000000000..6acbe68e67f --- /dev/null +++ b/sql/updates/world/2014_07_27_03_world_misc.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_area` WHERE `spell` IN(48763,48761, 45614); +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(48763, 4180, 12274, 0, 0, 0, 0, 0, 74, 11), +(48761, 4180, 12274, 0, 0, 0, 1, 0, 74, 11), +(45614, 4125, 11633, 0, 0, 0, 2, 0, 74, 11), +(45614, 4135, 11633, 0, 0, 0, 2, 0, 74, 11), +(45614, 4136, 11633, 0, 0, 0, 2, 0, 74, 11), +(45614, 4137, 11633, 0, 0, 0, 2, 0, 74, 11); -- cgit v1.2.3 From f162bce473205ccf70d9322cc0b36a7430152cdb Mon Sep 17 00:00:00 2001 From: DDuarte Date: Sun, 27 Jul 2014 15:29:02 +0100 Subject: CI/Travis: Compile all branches Also added master and 4.3.4 build status to the README --- .travis.yml | 16 +++++++--------- README.md | 5 +++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9be57a5afb6..97d35a9b30a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,18 +6,16 @@ before_install: - echo "yes" | sudo add-apt-repository ppa:kalakris/cmake - echo "yes" | sudo add-apt-repository ppa:boost-latest/ppa - echo "yes" | sudo add-apt-repository ppa:ubuntu-toolchain-r/test - - sudo apt-get update -qq - - sudo apt-get install build-essential libtool gcc-4.8 g++-4.8 make cmake openssl libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev libboost1.55-dev libboost-thread1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev + - sudo apt-get -qq update + - sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake openssl + - sudo apt-get -qq libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev + - sudo apt-get -qq libboost1.55-dev libboost-thread1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev + +script: - mkdir bin - cd bin - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=1 -DUSE_COREPCH=0 -DUSE_SCRIPTPCH=0 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DCMAKE_BUILD_TYPE=Release - -script: make -j 8 - -branches: - only: - - master - - 4.3.4 + - make -j 8 git: depth: 1 diff --git a/README.md b/README.md index d89fd842687..fdb05c81eb4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # ![logo](http://www.trinitycore.org/f/public/style_images/1_trinitycore.png) TrinityCore -[![Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=master)](https://travis-ci.org/TrinityCore/TrinityCore) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/435/badge.svg)](https://scan.coverity.com/projects/435) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/435/badge.svg)](https://scan.coverity.com/projects/435) +`3.3.5`: [![3.3.5 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=master)](https://travis-ci.org/TrinityCore/TrinityCore) +`4.3.4`: [![4.3.4 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=4.3.4)](https://travis-ci.org/TrinityCore/TrinityCore) ## Introduction -- cgit v1.2.3 From 7024dee19bb6984ecf19e76a632420f6c99e4a0c Mon Sep 17 00:00:00 2001 From: DDuarte Date: Sun, 27 Jul 2014 15:35:31 +0100 Subject: CI/Travis: Fix typo added in previous commit --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97d35a9b30a..bbeafd424a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,8 @@ before_install: - echo "yes" | sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt-get -qq update - sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake openssl - - sudo apt-get -qq libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev - - sudo apt-get -qq libboost1.55-dev libboost-thread1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev + - sudo apt-get -qq install libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev + - sudo apt-get -qq install libboost1.55-dev libboost-thread1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev script: - mkdir bin -- cgit v1.2.3 From 8a05231994342bc826fa98f3f1df741cc14e19f7 Mon Sep 17 00:00:00 2001 From: DDuarte Date: Sun, 27 Jul 2014 15:46:34 +0100 Subject: Conf/World: Disable player limit by default --- src/server/worldserver/worldserver.conf.dist | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 20660c979f5..dd8f213b6df 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -195,11 +195,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 -- cgit v1.2.3 From 6f272ea5b7d6551844aa1a1f748cee5c79b746f3 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 27 Jul 2014 17:46:46 +0200 Subject: Core/Network: Optimized packet sending by removing unneccessary memory copying --- src/server/authserver/Server/AuthSession.h | 2 +- src/server/game/Calendar/CalendarMgr.cpp | 2 +- src/server/game/Calendar/CalendarMgr.h | 2 +- src/server/game/Entities/Object/Object.cpp | 2 +- .../game/Entities/Object/Updates/UpdateData.h | 8 +++ src/server/game/Entities/Unit/Unit.cpp | 6 ++- src/server/game/Handlers/CombatHandler.cpp | 6 ++- src/server/game/Maps/Map.cpp | 2 +- src/server/game/Maps/Map.h | 2 +- src/server/game/Scripting/ScriptMgr.cpp | 24 ++++++--- src/server/game/Scripting/ScriptMgr.h | 6 +-- src/server/game/Server/WorldSession.cpp | 12 ++--- src/server/game/Server/WorldSession.h | 4 +- src/server/game/Server/WorldSocket.cpp | 13 ++--- src/server/game/Server/WorldSocket.h | 58 ++++++++++++++++++++-- src/server/shared/Packets/ByteBuffer.h | 30 ++++++++--- src/server/shared/Packets/WorldPacket.h | 22 ++++++-- .../shared/Threading/ProducerConsumerQueue.h | 14 ++++-- 18 files changed, 162 insertions(+), 53 deletions(-) diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 822f3c334fc..14129d76fd8 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -20,9 +20,9 @@ #define __AUTHSESSION_H__ #include "Common.h" +#include "ByteBuffer.h" #include "Socket.h" #include "BigNumber.h" -#include "ByteBuffer.h" #include #include diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 03d65fb134d..92f19c0adeb 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -636,7 +636,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 e238119defb..9bdb7c0a187 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -329,7 +329,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 23af4a70d3e..dfc0c438662 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -548,7 +548,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons if (iter == data_map.end()) { - std::pair p = data_map.insert(UpdateDataMapType::value_type(player, UpdateData())); + std::pair p = data_map.emplace(player, UpdateData()); 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 16bdec46aba..1ec86192fab 100644 --- a/src/server/game/Entities/Object/Updates/UpdateData.h +++ b/src/server/game/Entities/Object/Updates/UpdateData.h @@ -53,6 +53,11 @@ class UpdateData { public: UpdateData(); + UpdateData(UpdateData&& right) : m_blockCount(right.m_blockCount), + m_outOfRangeGUIDs(std::move(right.m_outOfRangeGUIDs)), + m_data(std::move(right.m_data)) + { + } void AddOutOfRangeGUID(std::set& guids); void AddOutOfRangeGUID(uint64 guid); @@ -69,6 +74,9 @@ class UpdateData ByteBuffer m_data; void Compress(void* dst, uint32 *dst_size, void* src, int src_size); + + 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 9472fba6572..f5b72b845a5 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2223,7 +2223,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/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index fbc33418e47..b0164b77f1c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2682,7 +2682,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 b431ca4ba17..70198cb20a3 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -423,7 +423,7 @@ class Map : public GridRefManager 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/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 1b91ed1690c..0d1983ab463 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 socket, bool wasNew) FOREACH_SCRIPT(ServerScript)->OnSocketClose(socket, wasNew); } -void ScriptMgr::OnPacketReceive(std::shared_ptr socket, WorldPacket packet) +void ScriptMgr::OnPacketReceive(std::shared_ptr 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 socket, WorldPacket packet) +void ScriptMgr::OnPacketSend(std::shared_ptr 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 socket, WorldPacket packet) +void ScriptMgr::OnUnknownPacketReceive(std::shared_ptr 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 325a0743d79..0b5813a7f58 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -910,9 +910,9 @@ class ScriptMgr void OnNetworkStop(); void OnSocketOpen(std::shared_ptr socket); void OnSocketClose(std::shared_ptr socket, bool wasNew); - void OnPacketReceive(std::shared_ptr socket, WorldPacket packet); - void OnPacketSend(std::shared_ptr socket, WorldPacket packet); - void OnUnknownPacketReceive(std::shared_ptr socket, WorldPacket packet); + void OnPacketReceive(std::shared_ptr socket, WorldPacket const& packet); + void OnPacketSend(std::shared_ptr socket, WorldPacket const& packet); + void OnUnknownPacketReceive(std::shared_ptr socket, WorldPacket const& packet); public: /* WorldScript */ diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index eb83a5f55be..279e69a4267 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -186,7 +186,7 @@ uint32 WorldSession::GetGuidLow() const } /// Send a packet to the client -void WorldSession::SendPacket(WorldPacket const* packet) +void WorldSession::SendPacket(WorldPacket* packet) { if (!m_Socket) return; @@ -288,7 +288,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) { TC_LOG_ERROR("network.opcode", "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerInfo().c_str()); - sScriptMgr->OnUnknownPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnUnknownPacketReceive(m_Socket, *packet); } else { @@ -318,7 +318,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); } @@ -331,7 +331,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) else { // not expected _player or must checked in packet handler - sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); + sScriptMgr->OnPacketReceive(m_Socket, *packet); (this->*opHandle.handler)(*packet); LogUnprocessedTail(packet); } @@ -343,7 +343,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); } @@ -361,7 +361,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 7ad43907355..d5b2146ae79 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -178,7 +178,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 @@ -222,7 +222,7 @@ class WorldSession void ReadMovementInfo(WorldPacket& data, MovementInfo* mi); void WriteMovementInfo(WorldPacket* data, MovementInfo* mi); - void SendPacket(WorldPacket const* packet); + void SendPacket(WorldPacket* packet); 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 f078b2acc15..ea0bfc234bf 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -18,7 +18,6 @@ #include #include "WorldSocket.h" -#include "ServerPktHeader.h" #include "BigNumber.h" #include "Opcodes.h" #include "ScriptMgr.h" @@ -140,7 +139,7 @@ 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); @@ -149,18 +148,12 @@ void WorldSocket::AsyncWrite(WorldPacket const& packet) ServerPktHeader header(packet.size() + 2, packet.GetOpcode()); - std::vector data(header.getHeaderLength() + packet.size()); - std::memcpy(data.data(), header.header, header.getHeaderLength()); - - if (!packet.empty()) - std::memcpy(&data[header.getHeaderLength()], packet.contents(), packet.size()); - std::lock_guard 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 f355308ff7a..1fa08c2b5f1 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 "AuthCrypt.h" +#include "ServerPktHeader.h" #include "Socket.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" #include #include +#include using boost::asio::ip::tcp; @@ -40,9 +52,49 @@ struct ClientPktHeader #pragma pack(pop) -class WorldSocket : public Socket > +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 { - typedef Socket > Base; + typedef Socket Base; public: WorldSocket(tcp::socket&& socket); @@ -53,7 +105,7 @@ public: void Start() override; using Base::AsyncWrite; - void AsyncWrite(WorldPacket const& packet); + void AsyncWrite(WorldPacket& packet); protected: void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 311143b384c..9744904f0dc 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -81,12 +81,28 @@ class ByteBuffer _storage.reserve(reserve); } - // copy constructor - ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos), - _storage(buf._storage) + ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos), + _storage(std::move(buf._storage)) { } + ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos), + _storage(right._storage) + { + } + + ByteBuffer& operator=(ByteBuffer const& right) + { + if (this != &right) + { + _rpos = right._rpos; + _wpos = right._wpos; + _storage = right._storage; + } + + return *this; + } + virtual ~ByteBuffer() { } void clear() @@ -383,18 +399,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(); } diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h index 6703c5ed2ea..8851b9f3e45 100644 --- a/src/server/shared/Packets/WorldPacket.h +++ b/src/server/shared/Packets/WorldPacket.h @@ -29,12 +29,28 @@ class WorldPacket : public ByteBuffer WorldPacket() : ByteBuffer(0), m_opcode(0) { } + explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } - // copy constructor - WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) + + WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode) + { + } + + WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode) { } + WorldPacket& operator=(WorldPacket const& right) + { + if (this != &right) + { + m_opcode = right.m_opcode; + ByteBuffer::operator =(right); + } + + return *this; + } + void Initialize(uint16 opcode, size_t newres=200) { clear(); @@ -48,5 +64,5 @@ class WorldPacket : public ByteBuffer protected: uint16 m_opcode; }; -#endif +#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 #include #include +#include template class ProducerConsumerQueue { - static_assert(std::is_pointer::value, "T for ProducerConsumerQueue must be a pointer"); - private: std::mutex _queueLock; std::queue _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 std::enable_if::value>::type DeleteQueuedObject(E& obj) { delete obj; } + template + typename std::enable_if::value>::type DeleteQueuedObject(E const& /*packet*/) { } +}; +#endif -- cgit v1.2.3 From eabf0f44dd4d3514dd302cd7608fbcaa8e3fa776 Mon Sep 17 00:00:00 2001 From: DDuarte Date: Sun, 27 Jul 2014 17:33:42 +0100 Subject: Tools/mmaps: Change the PCQ queue to uint32 again 6f272ea5b7d65518 re-added support for non-pointer types --- src/tools/mmaps_generator/MapBuilder.cpp | 11 +++-------- src/tools/mmaps_generator/MapBuilder.h | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) 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 _workerThreads; - ProducerConsumerQueue _queue; + ProducerConsumerQueue _queue; std::atomic _cancelationToken; }; } -- cgit v1.2.3 From e502e01f5d16964e67685c956e204ae41b756d26 Mon Sep 17 00:00:00 2001 From: leak Date: Sun, 27 Jul 2014 17:33:56 +0200 Subject: Fixed a rare crash case when authserver socket was forcefully closed during read Closes #12634 --- src/server/shared/Networking/Socket.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 96f597257be..9c3ec180b0a 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -56,7 +56,16 @@ public: 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(PacketType const& data) @@ -68,11 +77,11 @@ public: bool IsOpen() const { return _socket.is_open(); } void CloseSocket() { - boost::system::error_code socketError; - _socket.close(socketError); - if (socketError) + 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(), - socketError.value(), socketError.message().c_str()); + error.value(), error.message().c_str()); } uint8* GetReadBuffer() { return _readBuffer; } -- cgit v1.2.3