#ifndef __INC_METIN_II_GAME_DESC_H__ #define __INC_METIN_II_GAME_DESC_H__ #include "constants.h" #include "input.h" #include "SecureCipher.h" #include "libthecore/ring_buffer.h" //#define MAX_INPUT_LEN 2048 #define MAX_INPUT_LEN 65536 class CInputProcessor; enum EDescType { DESC_TYPE_ACCEPTOR, DESC_TYPE_CONNECTOR }; class CLoginKey { public: CLoginKey(DWORD dwKey, LPDESC pkDesc) : m_dwKey(dwKey), m_pkDesc(pkDesc) { m_dwExpireTime = 0; } void Expire() { m_dwExpireTime = get_dword_time(); m_pkDesc = NULL; } operator DWORD() const { return m_dwKey; } DWORD m_dwKey; DWORD m_dwExpireTime; LPDESC m_pkDesc; }; class DESC { public: EVENTINFO(desc_event_info) { LPDESC desc; desc_event_info() : desc(0) { } }; public: DESC(); virtual ~DESC(); virtual BYTE GetType() { return DESC_TYPE_ACCEPTOR; } virtual void Destroy(); virtual void SetPhase(int _phase); void FlushOutput(); bool Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSockAddr, DWORD _handle); socket_t GetSocket() const { return m_sock; } const char * GetHostName() { return m_stHost.c_str(); } WORD GetPort() { return m_wPort; } void SetP2P(const char * h, WORD w, BYTE b) { m_stP2PHost = h; m_wP2PPort = w; m_bP2PChannel = b; } const char * GetP2PHost() { return m_stP2PHost.c_str(); } WORD GetP2PPort() const { return m_wP2PPort; } BYTE GetP2PChannel() const { return m_bP2PChannel; } void BufferedPacket(const void * c_pvData, int iSize); void Packet(const void * c_pvData, int iSize); void LargePacket(const void * c_pvData, int iSize); int ProcessInput(); // returns -1 if error int ProcessOutput(); // returns -1 if error CInputProcessor * GetInputProcessor() { return m_pInputProcessor; } DWORD GetHandle() const { return m_dwHandle; } size_t GetOutputBufferSize() const { return m_outputBuffer.ReadableBytes(); } void BindAccountTable(TAccountTable * pTable); TAccountTable & GetAccountTable() { return m_accountTable; } void BindCharacter(LPCHARACTER ch); LPCHARACTER GetCharacter() { return m_lpCharacter; } bool IsPhase(int phase) const { return m_iPhase == phase ? true : false; } int32_t GetPhase() const { return m_iPhase; } const struct sockaddr_in & GetAddr() { return m_SockAddr; } void Log(const char * format, ...); DWORD GetClientTime(); void SendKeyChallenge(); bool HandleKeyResponse(const uint8_t* client_pk, const uint8_t* challenge_response); void SendKeyComplete(); SecureCipher& GetSecureCipher() { return m_secureCipher; } const uint8_t* GetSessionToken() const { return m_secureCipher.GetSessionToken(); } bool IsSecureCipherActivated() const { return m_secureCipher.IsActivated(); } // 제국 BYTE GetEmpire(); // for p2p void SetRelay(const char * c_pszName); bool DelayedDisconnect(int iSec); void DisconnectOfSameLogin(); void SetAdminMode(); bool IsAdminMode(); // Handshake 에서 어드민 명령을 쓸수있나? void SetPong(bool b); bool IsPong(); void SendLoginSuccessPacket(); //void SendServerStatePacket(int nIndex); void SetLoginKey(DWORD dwKey); void SetLoginKey(CLoginKey * pkKey); DWORD GetLoginKey(); void AssembleCRCMagicCube(BYTE bProcPiece, BYTE bFilePiece); void SetClientVersion(const char * c_pszTimestamp) { m_stClientVersion = c_pszTimestamp; } const char * GetClientVersion() { return m_stClientVersion.c_str(); } bool isChannelStatusRequested() const { return m_bChannelStatusRequested; } void SetChannelStatusRequested(bool bChannelStatusRequested) { m_bChannelStatusRequested = bChannelStatusRequested; } bool IsExpiredHandshake() const; void SetHandshakeTime(uint32_t handshake_time) { m_handshake_time = handshake_time; } protected: void Initialize(); protected: CInputProcessor * m_pInputProcessor; CInputClose m_inputClose; CInputHandshake m_inputHandshake; CInputLogin m_inputLogin; CInputMain m_inputMain; CInputDead m_inputDead; CInputAuth m_inputAuth; LPFDWATCH m_lpFdw; socket_t m_sock; int m_iPhase; DWORD m_dwHandle; std::string m_stHost; WORD m_wPort; time_t m_LastTryToConnectTime; RingBuffer m_inputBuffer; DWORD m_dwClientTime; RingBuffer m_bufferedOutputBuffer; bool m_hasBufferedOutput; RingBuffer m_outputBuffer; LPEVENT m_pkPingEvent; LPCHARACTER m_lpCharacter; TAccountTable m_accountTable; struct sockaddr_in m_SockAddr; FILE * m_pLogFile; std::string m_stRelayName; std::string m_stP2PHost; WORD m_wP2PPort; BYTE m_bP2PChannel; bool m_bAdminMode; // Handshake 에서 어드민 명령을 쓸수있나? bool m_bPong; CLoginKey * m_pkLoginKey; DWORD m_dwLoginKey; BYTE m_bCRCMagicCubeIdx; DWORD m_dwProcCRC; DWORD m_dwFileCRC; bool m_bHackCRCQuery; std::string m_stClientVersion; std::string m_Login; int m_outtime; int m_playtime; int m_offtime; bool m_bDestroyed; bool m_bChannelStatusRequested; uint32_t m_handshake_time; SecureCipher m_secureCipher; uint8_t m_challenge[SecureCipher::CHALLENGE_SIZE]; public: LPEVENT m_pkDisconnectEvent; public: void SetLogin( const std::string & login ) { m_Login = login; } void SetLogin( const char * login ) { m_Login = login; } const std::string& GetLogin() { return m_Login; } void SetOutTime( int outtime ) { m_outtime = outtime; } void SetOffTime( int offtime ) { m_offtime = offtime; } void SetPlayTime( int playtime ) { m_playtime = playtime; } void RawPacket(const void * c_pvData, int iSize); void ChatPacket(BYTE type, const char * format, ...); public: struct PacketLogEntry { uint32_t seq; uint16_t header; uint16_t length; }; static constexpr size_t PACKET_LOG_SIZE = 32; void LogRecvPacket(uint16_t header, uint16_t length); void LogSentPacket(uint16_t header, uint16_t length); void DumpRecentPackets() const; uint32_t GetRecvPacketSeq() const { return m_dwRecvPacketSeq; } uint32_t GetSentPacketSeq() const { return m_dwSentPacketSeq; } private: PacketLogEntry m_aRecentRecvPackets[PACKET_LOG_SIZE] = {}; PacketLogEntry m_aRecentSentPackets[PACKET_LOG_SIZE] = {}; uint32_t m_dwRecvPacketSeq = 0; uint32_t m_dwSentPacketSeq = 0; }; #endif