/** * Tencent is pleased to support the open source community by making MSEC available. * * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the GNU General Public License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may * obtain a copy of the License at * * https://opensource.org/licenses/GPL-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ /** * @file mt_connection.h * @time 20130924 **/ #ifndef __MT_CONNECTION_H__ #define __MT_CONNECTION_H__ #include #include #include "mt_mbuf_pool.h" #include "hash_list.h" #include "mt_action.h" namespace NS_MICRO_THREAD { using std::queue; enum CONN_OBJ_TYPE { OBJ_CONN_UNDEF = 0, OBJ_SHORT_CONN = 1, OBJ_TCP_KEEP = 2, OBJ_UDP_SESSION = 3, }; class IMtConnection { public: IMtConnection(); virtual ~IMtConnection(); virtual void Reset(); CONN_OBJ_TYPE GetConnType() { return _type; }; void SetIMtActon(IMtAction* action ) { _action = action; }; IMtAction* GetIMtActon() { return _action; }; void SetNtfyObj(KqueuerObj* obj ) { _ntfy_obj = obj; }; KqueuerObj* GetNtfyObj() { return _ntfy_obj; }; void SetMtMsgBuff(MtMsgBuf* msg_buf) { _msg_buff = msg_buf; }; MtMsgBuf* GetMtMsgBuff() { return _msg_buff; }; public: virtual int CreateSocket() {return 0;}; virtual int OpenCnnect() {return 0;}; virtual int SendData() {return 0;}; virtual int RecvData() {return 0;}; virtual int CloseSocket() {return 0;}; protected: CONN_OBJ_TYPE _type; IMtAction* _action; KqueuerObj* _ntfy_obj; MtMsgBuf* _msg_buff; }; class UdpShortConn : public IMtConnection { public: UdpShortConn() { _osfd = -1; _type = OBJ_SHORT_CONN; }; virtual ~UdpShortConn() { CloseSocket(); }; virtual void Reset(); virtual int CreateSocket(); virtual int SendData(); virtual int RecvData(); virtual int CloseSocket(); protected: int _osfd; }; enum TcpKeepFlag { TCP_KEEP_IN_LIST = 0x1, TCP_KEEP_IN_KQUEUE = 0x2, }; class UdpSessionConn : public IMtConnection { public: UdpSessionConn() { _type = OBJ_UDP_SESSION; }; virtual ~UdpSessionConn() { }; virtual int CreateSocket(); virtual int SendData(); virtual int RecvData(); virtual int CloseSocket(); }; typedef TAILQ_ENTRY(TcpKeepConn) KeepConnLink; typedef TAILQ_HEAD(__KeepConnTailq, TcpKeepConn) KeepConnList; class TcpKeepConn : public IMtConnection, public CTimerNotify { public: int _keep_flag; KeepConnLink _keep_entry; TcpKeepConn() { _osfd = -1; _keep_time = 10*60*1000; _keep_flag = 0; _type = OBJ_TCP_KEEP; _keep_ntfy.SetKeepNtfyObj(this); }; virtual ~TcpKeepConn() { CloseSocket(); }; virtual void Reset(); virtual int OpenCnnect(); virtual int CreateSocket(); virtual int SendData(); virtual int RecvData(); virtual int CloseSocket(); void ConnReuseClean(); bool IdleAttach(); bool IdleDetach(); void SetDestAddr(struct sockaddr_in* dst) { memcpy(&_dst_addr, dst, sizeof(_dst_addr)); } struct sockaddr_in* GetDestAddr() { return &_dst_addr; } virtual void timer_notify(); void SetKeepTime(unsigned int time) { _keep_time = time; }; protected: int _osfd; unsigned int _keep_time; TcpKeepNtfy _keep_ntfy; struct sockaddr_in _dst_addr; }; class TcpKeepKey : public HashKey { public: TcpKeepKey() { _addr_ipv4 = 0; _net_port = 0; TAILQ_INIT(&_keep_list); this->SetDataPtr(this); }; TcpKeepKey(struct sockaddr_in * dst) { _addr_ipv4 = dst->sin_addr.s_addr; _net_port = dst->sin_port; TAILQ_INIT(&_keep_list); this->SetDataPtr(this); }; ~TcpKeepKey() { TAILQ_INIT(&_keep_list); }; virtual uint32_t HashValue(){ return _addr_ipv4 ^ ((_net_port << 16) | _net_port); }; virtual int HashCmp(HashKey* rhs){ TcpKeepKey* data = dynamic_cast(rhs); if (!data) { return -1; } if (this->_addr_ipv4 != data->_addr_ipv4) { return this->_addr_ipv4 - data->_addr_ipv4; } if (this->_net_port != data->_net_port) { return this->_net_port - data->_net_port; } return 0; }; void InsertConn(TcpKeepConn* conn) { if (conn->_keep_flag & TCP_KEEP_IN_LIST) { return; } TAILQ_INSERT_TAIL(&_keep_list, conn, _keep_entry); conn->_keep_flag |= TCP_KEEP_IN_LIST; }; void RemoveConn(TcpKeepConn* conn) { if (!(conn->_keep_flag & TCP_KEEP_IN_LIST)) { return; } TAILQ_REMOVE(&_keep_list, conn, _keep_entry); conn->_keep_flag &= ~TCP_KEEP_IN_LIST; }; TcpKeepConn* GetFirstConn() { return TAILQ_FIRST(&_keep_list); }; private: uint32_t _addr_ipv4; uint16_t _net_port; KeepConnList _keep_list; }; class TcpKeepMgr { public: typedef CPtrPool TcpKeepQueue; TcpKeepMgr(); ~TcpKeepMgr(); TcpKeepConn* GetTcpKeepConn(struct sockaddr_in* dst); bool CacheTcpKeepConn(TcpKeepConn* conn); bool RemoveTcpKeepConn(TcpKeepConn* conn); void FreeTcpKeepConn(TcpKeepConn* conn, bool force_free); private: HashList* _keep_hash; TcpKeepQueue _mem_queue; }; class ConnectionMgr { public: typedef CPtrPool UdpShortQueue; typedef CPtrPool UdpSessionQueue; static ConnectionMgr* Instance (void); static void Destroy(void); IMtConnection* GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst); void FreeConnection(IMtConnection* conn, bool force_free); void CloseIdleTcpKeep(TcpKeepConn* conn); ~ConnectionMgr(); private: ConnectionMgr(); static ConnectionMgr * _instance; UdpShortQueue _udp_short_queue; UdpSessionQueue _udp_session_queue; TcpKeepMgr _tcp_keep_mgr; }; } #endif