#pragma once #ifndef NETWORK_MODULE_SESSION_H #define NETWORK_MODULE_SESSION_H //================================================================================================== #define SEND_POSTED 1 #define RECV_POSTED 2 #define ACCEPT_POSTED 3 #define DISCONNECT_POSTED 4 class SendBuffer; class RecvBuffer; class SessionPool; class NetworkObject; class Session; /// OVERLAPPED È®Àå ±¸Á¶Ã¼ struct OVERLAPPEDEX : public OVERLAPPED { DWORD operation_type; Session* session; }; //================================================================================================== /// ±âº»ÀûÀÎ ¼ÒÄÏ Ã³¸® ±â´ÉÀ» °®°í ÀÖ´Â ¼¼¼Ç Ŭ·¡½º /** @remarks ÀÌ Å¬·¡½º¸¦ »ó¼Ó ¹Þ¾Æ È®Àå À¯Á® Ŭ·¡½º¸¦ ¸¸µé ¼ö ÀÖ´Ù. @par - ¼¼¼ÇÀ» »ó¼Ó¹ÞÀº Ŭ·¡½º¿¡¼­´Â ´ÙÀ½ÀÇ ÇÔ¼öµéÀ» ÀçÁ¤ÀÇ ÇØ¼­ »ç¿ëÇÑ´Ù. - OnAccept: Ŭ¶óÀÌ¾ðÆ®°¡ acceptµÇ¾úÀ» ¶§ È£ÃâµÈ´Ù. - OnDisConnect: Ŭ¶óÀ̾ðÆ®ÀÇ Á¢¼ÓÀÌ ÇØÁ¦ µÇ¾úÀ» ¶§ È£ÃâµÈ´Ù. - OnRecv: Ŭ¶ó¸®¾ðÆ®°¡ ÆÐŶÀ» ¼ö½ÅÇßÀ» ¶§ È£ÃâµÈ´Ù. - OnConnect: ´Ù¸¥ ¼­¹ö·ÎÀÇ connect°¡ ¼º°ø ¶Ç´Â ½ÇÆÐÇßÀ» ¶§ È£ÃâµÈ´Ù. - OnUpdate: ¸ÅÇÁ·¹ÀÓ IO ¿£ÁøÀÌ UpdateµÉ ¶§¸¶´Ù È£ÃâµÈ´Ù. @note - ws2_32.lib Ãß°¡ÇÒ °Í - winsock2.h Æ÷ÇÔÇÒ °Í */ //================================================================================================== // class Session { friend unsigned __stdcall io_thread(LPVOID param); friend class SessionPool; public: /// timeout °ªÀÌ 0ÀÌ¸é ¸Þ¼¼Áö ¼Û½ÅÀÌ ¾ø¾îµµ Á¢¼ÓÀ» ²÷Áö ¾Ê´Â´Ù. Session(DWORD send_buffer_size, DWORD recv_buffer_size, DWORD max_packet_size, DWORD timeout); virtual ~Session(); void Init(); void Reuse(HANDLE iocp_handle); bool Send(BYTE* pMsg, WORD size); bool SendEx(DWORD number_of_messages, BYTE** ppMsg, WORD* pwSize); bool PreSend(); bool PreRecv(); bool PreAccept(SOCKET listen_socket); SOCKET CreateSocket(); bool ProcessReceivedPacket(int max_packet_size); void BindNetworkObject(NetworkObject* network_object); void UnbindNetworkObject(); void OnAccept(); void OnConnect(bool success); void OnLogString(const char* log_string, ...); int SetSockOpt(int level, int optname, const char FAR* optval, int optlen); void SetSocket(SOCKET socket); void SetSockAddr(SOCKADDR_IN& sockaddr); void CloseSocket(); NetworkObject* GetNetworkObject() const; SendBuffer* GetSendBuffer() const; ///< º¸³»±â ¹öÆÛ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. RecvBuffer* GetRecvBuffer() const; ///< ¹Þ±â ¹öÆÛ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. SOCKET GetSocket() const; ///< ¼ÒÄÏ ÇÚµéÀ» ¸®ÅÏÇÑ´Ù. SOCKADDR* GetSockAddr() const; ///< ¼ÒÄÏ ÁÖ¼ÒÀÇ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. char* GetIP() const; ///< ¼¼¼Ç¿¡ ¹°¸° ¼ÒÄÏÀÇ IP¸¦ ½ºÆ®¸µÀ¸·Î ¹Ýȯ DWORD GetIdleTick() const; bool IsOnIdle() const; DWORD GetIndex() const; bool IsAcceptSocket() const; void SetAcceptSocketFlag(); void Remove(); void ResetKillFlag(); bool ShouldBeRemoved(); void Disconnect(bool bGracefulDisconnect); bool HasDisconnectOrdered() const; // NOTE: f110616.5L, bool StoppedReception() const; void StopReception(); void ResumeReception(); private: void SetIndex(DWORD index); void ResetTimeOut(); #pragma warning(push) #pragma warning(disable : 4201) union { char field_start_pos_[1]; long removed_; //volatile... reordered position, force a change memory state on update }; NetworkObject* network_object_; SendBuffer* send_buffer_; RecvBuffer* recv_buffer_; DWORD session_index_; SOCKET socket_; bool accept_socket_; bool disconnect_ordered_; long stopped_reception_; // NOTE: f110616.1L, close socket because of a missing event OVERLAPPEDEX send_io_data_; OVERLAPPEDEX recv_io_data_; OVERLAPPEDEX accept_io_data_; OVERLAPPEDEX disconnect_io_data_; DWORD last_sync_tick_; DWORD timeout_; // Àӽà Å×½ºÆ® ¿ë struct { int backup_net_category_; int backup_net_protocol_; int backup_net_msg_size_; }; SOCKADDR_IN sockaddr_in_; char field_end_pos_[1]; // static DWORD m_dwSessionNum; #pragma warning(pop) }; //================================================================================================== inline void Session::SetSocket(SOCKET socket) { socket_ = socket; } inline void Session::SetSockAddr(SOCKADDR_IN& sockaddr) { sockaddr_in_ = sockaddr; } inline void Session::CloseSocket() { closesocket(socket_); socket_ = INVALID_SOCKET; } inline NetworkObject* Session::GetNetworkObject() const { return network_object_; } inline SendBuffer* Session::GetSendBuffer() const { return send_buffer_; } ///< º¸³»±â ¹öÆÛ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. inline RecvBuffer* Session::GetRecvBuffer() const { return recv_buffer_; } ///< ¹Þ±â ¹öÆÛ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. inline SOCKET Session::GetSocket() const { return socket_; } ///< ¼ÒÄÏ ÇÚµéÀ» ¸®ÅÏÇÑ´Ù. inline SOCKADDR* Session::GetSockAddr() const { return (SOCKADDR*)&sockaddr_in_; } ///< ¼ÒÄÏ ÁÖ¼ÒÀÇ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. inline char* Session::GetIP() const { return inet_ntoa(sockaddr_in_.sin_addr); } ///< ¼¼¼Ç¿¡ ¹°¸° ¼ÒÄÏÀÇ IP¸¦ ½ºÆ®¸µÀ¸·Î ¹Ýȯ inline DWORD Session::GetIdleTick() const { return timeout_? last_sync_tick_ + timeout_ : 0; } inline bool Session::IsOnIdle() const { return timeout_ ? last_sync_tick_ + timeout_ < GetTickCount() : false; } inline DWORD Session::GetIndex() const { return session_index_; } inline bool Session::IsAcceptSocket() const { return accept_socket_; } inline void Session::SetAcceptSocketFlag() { accept_socket_ = true; } inline void Session::ResetKillFlag() { InterlockedExchange(&removed_, false); InterlockedExchange(&stopped_reception_, false); } inline bool Session::ShouldBeRemoved() { return removed_ != false; } inline void Session::Remove() { InterlockedExchange(&removed_, true); } inline bool Session::HasDisconnectOrdered() const { return disconnect_ordered_; } inline bool Session::StoppedReception() const { return (stopped_reception_ != false); } // NOTE: f110616.5L, stop messages reception because of insufficient buffer inline void Session::StopReception() { InterlockedExchange(&stopped_reception_, true); } // NOTE: f110616.5L, thie methods support external reception events. inline void Session::ResumeReception() { if (stopped_reception_) { InterlockedExchange(&stopped_reception_, (this->PreRecv() == false)); }; } inline void Session::SetIndex(DWORD index) { session_index_ = index; } inline void Session::ResetTimeOut() { last_sync_tick_ = GetTickCount(); } #endif //NETWORK_MODULE_SESSION_H