f-stack/app/micro_thread/mt_connection.h

339 lines
6.7 KiB
C++

/**
* 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 <netinet/in.h>
#include <queue>
#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<TcpKeepKey*>(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<TcpKeepConn> 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<UdpShortConn> UdpShortQueue;
typedef CPtrPool<UdpSessionConn> 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