/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __WORLDSOCKET_H__ #define __WORLDSOCKET_H__ #include "AuthCrypt.h" #include "Common.h" #include "MPSCQueue.h" #include "ServerPktHeader.h" #include "Socket.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" #include using boost::asio::ip::tcp; class EncryptablePacket : public WorldPacket { public: EncryptablePacket(WorldPacket const& packet, bool encrypt) : WorldPacket(packet), _encrypt(encrypt) { SocketQueueLink.store(nullptr, std::memory_order_relaxed); } bool NeedsEncryption() const { return _encrypt; } std::atomic SocketQueueLink; private: bool _encrypt; }; namespace WorldPackets { class ServerPacket; } #pragma pack(push, 1) struct ClientPktHeader { uint16 size; uint32 cmd; bool IsValidSize() const { return size >= 4 && size < 10240; } bool IsValidOpcode() const { return cmd < NUM_OPCODE_HANDLERS; } }; #pragma pack(pop) struct AuthSession; class AC_GAME_API WorldSocket : public Socket { typedef Socket BaseSocket; public: WorldSocket(tcp::socket&& socket); ~WorldSocket(); WorldSocket(WorldSocket const& right) = delete; WorldSocket& operator=(WorldSocket const& right) = delete; void Start() override; bool Update() override; void SendPacket(WorldPacket const& packet); void SetSendBufferSize(std::size_t sendBufferSize) { _sendBufferSize = sendBufferSize; } protected: void OnClose() override; void ReadHandler() override; bool ReadHeaderHandler(); enum class ReadDataHandlerResult { Ok = 0, Error = 1, WaitingForQuery = 2 }; ReadDataHandlerResult ReadDataHandler(); private: void CheckIpCallback(PreparedQueryResult result); /// writes network.opcode log /// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock void LogOpcodeText(OpcodeClient opcode, std::unique_lock const& guard) const; /// sends and logs network.opcode without accessing WorldSession void SendPacketAndLogOpcode(WorldPacket const& packet); void HandleSendAuthSession(); void HandleAuthSession(WorldPacket& recvPacket); void HandleAuthSessionCallback(std::shared_ptr authSession, PreparedQueryResult result); void LoadSessionPermissionsCallback(PreparedQueryResult result); void SendAuthResponseError(uint8 code); bool HandlePing(WorldPacket& recvPacket); std::array _authSeed; AuthCrypt _authCrypt; TimePoint _LastPingTime; uint32 _OverSpeedPings; std::mutex _worldSessionLock; WorldSession* _worldSession; bool _authed; MessageBuffer _headerBuffer; MessageBuffer _packetBuffer; MPSCQueue _bufferQueue; std::size_t _sendBufferSize; QueryCallbackProcessor _queryProcessor; std::string _ipCountry; }; #endif