f-stack/app/micro_thread/mt_net.cpp

1988 lines
44 KiB
C++
Raw Normal View History

2017-04-21 10:43:26 +00:00
/**
* 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_mbuf_pool.cpp
* @info ΢<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>Ϣbuf<EFBFBD>ع<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>
* @time 20130924
**/
#include <errno.h>
#include <netinet/tcp.h>
#include "micro_thread.h"
#include "mt_sys_hook.h"
#include "ff_hook.h"
#include "mt_net.h"
using namespace std;
using namespace NS_MICRO_THREAD;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CNetHelper::CNetHelper()
{
handler = (void*)CNetMgr::Instance()->AllocNetItem();
}
CNetHelper::~CNetHelper()
{
CNetHandler* net_handler = (CNetHandler*)handler;
if (handler != NULL)
{
net_handler->Reset();
CNetMgr::Instance()->FreeNetItem(net_handler);
handler = NULL;
}
}
// ͬ<><CDAC><EFBFBD>շ<EFBFBD><D5B7>ӿ<EFBFBD>
int32_t CNetHelper::SendRecv(void* data, uint32_t len, uint32_t timeout)
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->SendRecv(data, len, timeout);
} else {
return RC_INVALID_HANDLER;
}
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>buff<66><66>Ϣ, <20><>Ч<EFBFBD><D0A7>ֱ<EFBFBD><D6B1>helper<65><72><EFBFBD><EFBFBD>
void* CNetHelper::GetRspBuff()
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->GetRspBuff();
} else {
return NULL;
}
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>buff<66><66>Ϣ, <20><>Ч<EFBFBD><D0A7>ֱ<EFBFBD><D6B1>helper<65><72><EFBFBD><EFBFBD>
uint32_t CNetHelper::GetRspLen()
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->GetRspLen();
} else {
return 0;
}
}
// ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
char* CNetHelper::GetErrMsg(int32_t result)
{
static const char* errmsg = "unknown error type";
switch (result)
{
case RC_SUCCESS:
errmsg = "success";
break;
case RC_ERR_SOCKET:
errmsg = "create socket failed";
break;
case RC_SEND_FAIL:
errmsg = "send pakeage timeout or failed";
break;
case RC_RECV_FAIL:
errmsg = "recv response timeout or failed";
break;
case RC_CONNECT_FAIL:
errmsg = "connect timeout or failed";
break;
case RC_CHECK_PKG_FAIL:
errmsg = "user package check failed";
break;
case RC_NO_MORE_BUFF:
errmsg = "user response buffer too small";
break;
case RC_REMOTE_CLOSED:
errmsg = "remote close connection";
break;
case RC_INVALID_PARAM:
errmsg = "params invalid";
break;
case RC_INVALID_HANDLER:
errmsg = "net handler invalid";
break;
case RC_MEM_ERROR:
errmsg = "no more memory, alloc failed";
break;
case RC_CONFLICT_SID:
errmsg = "session id with the dest address conflict";
break;
case RC_KQUEUE_ERROR:
errmsg = "epoll system error";
break;
default:
break;
}
return (char*)errmsg;
}
// <20><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, Ĭ<><C4AC>UDP
void CNetHelper::SetProtoType(MT_PROTO_TYPE type)
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->SetProtoType(type);
}
}
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>IP<49><50>ַ
void CNetHelper::SetDestAddress(struct sockaddr_in* dst)
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->SetDestAddress(dst);
}
}
// <20><><EFBFBD><EFBFBD>session<6F><6E><EFBFBD><EFBFBD>session id<69><64>Ϣ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
void CNetHelper::SetSessionId(uint64_t sid)
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->SetSessionId(sid);
}
}
// <20><><EFBFBD><EFBFBD>session<6F><6E><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
void CNetHelper::SetSessionCallback(CHECK_SESSION_CALLBACK function)
{
if (handler != NULL) {
CNetHandler* net_handler = (CNetHandler*)handler;
return net_handler->SetSessionCallback(function);
}
}
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>net handler, <20><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD>
void CNetHandler::Reset()
{
// ȥ<><C8A5>session<6F><6E>connection<6F><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->Unlink();
this->UnRegistSession();
// <20><>̬<EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>
if (_rsp_buff != NULL) {
delete_sk_buffer(_rsp_buff);
_rsp_buff = NULL;
}
// <20>ֶγ<D6B6>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
_thread = NULL;
_proto_type = NET_PROTO_TCP;
_conn_type = TYPE_CONN_SESSION;
_dest_ipv4.sin_addr.s_addr = 0;
_dest_ipv4.sin_port = 0;
_session_id = 0;
_callback = NULL;
_err_no = 0;
_state_flags = 0;
_conn_ptr = NULL;
_send_pos = 0;
_req_len = 0;
_req_data = NULL;
}
// <20><><EFBFBD><EFBFBD><ECBAAF>
CNetHandler::CNetHandler()
{
_state_flags = 0;
_rsp_buff = NULL;
this->Reset();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CNetHandler::~CNetHandler()
{
this->Reset();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>Ϣ
int32_t CNetHandler::CheckParams()
{
// 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
if ((NULL == _req_data) || (_req_len == 0))
{
MTLOG_ERROR("param invalid, data[%p], len[%u]", _req_data, _req_len);
return RC_INVALID_PARAM;
}
// 2. Ŀ<>ĵ<EFBFBD>ַ<EFBFBD><D6B7>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
if ((_dest_ipv4.sin_addr.s_addr == 0) || (_dest_ipv4.sin_port == 0))
{
MTLOG_ERROR("param invalid, ip[%u], port[%u]", _dest_ipv4.sin_addr.s_addr,
_dest_ipv4.sin_port);
return RC_INVALID_PARAM;
}
// 3. session <20><><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
if (_conn_type == TYPE_CONN_SESSION)
{
if ((_callback == NULL) || (_session_id == 0))
{
MTLOG_ERROR("param invalid, callback[%p], session_id[%llu]", _callback, _session_id);
return RC_INVALID_PARAM;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>session<6F><6E>Ϣ
if (!this->RegistSession())
{
MTLOG_ERROR("param invalid, session_id[%llu] regist failed", _session_id);
return RC_CONFLICT_SID;
}
}
// 4. <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>
return 0;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>, ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ӵĶ<D3B5><C4B6><EFBFBD><EFBFBD><EFBFBD>
int32_t CNetHandler::GetConnLink()
{
CDestLinks key;
key.SetKeyInfo(_dest_ipv4.sin_addr.s_addr, _dest_ipv4.sin_port, _proto_type, _conn_type);
CDestLinks* dest_link = CNetMgr::Instance()->FindCreateDest(&key);
if (NULL == dest_link)
{
MTLOG_ERROR("get dest link handle failed");
return RC_MEM_ERROR;
}
CSockLink* sock_link = dest_link->GetSockLink();
if (NULL == sock_link)
{
MTLOG_ERROR("get sock link handle failed");
return RC_MEM_ERROR;
}
this->Link(sock_link);
return 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>Ϣ
int32_t CNetHandler::WaitConnect(uint64_t timeout)
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("get sock link handle failed");
return RC_MEM_ERROR;
}
int32_t fd = conn->CreateSock();
if (fd < 0)
{
MTLOG_ERROR("create sock failed, ret %d[%m]", fd);
return RC_ERR_SOCKET;
}
if (conn->Connect())
{
MTLOG_DEBUG("sock conncet ok");
return RC_SUCCESS;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>connect<63><74><EFBFBD><EFBFBD>
this->SwitchToConn();
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
MtFrame* mtframe = MtFrame::Instance();
mtframe->WaitNotify(timeout);
// ɾ<><C9BE><EFBFBD><EFBFBD>connect<63><74><EFBFBD><EFBFBD>, <20><>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EEB4A6>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->SwitchToIdle();
if (_err_no != 0)
{
MTLOG_ERROR("connect get out errno %d", _err_no);
return _err_no;
}
// <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
if (conn->Connected())
{
MTLOG_DEBUG("connect ok");
return 0;
}
else
{
MTLOG_TRACE("connect not ok, maybe timeout");
return RC_CONNECT_FAIL;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>Ϣ
int32_t CNetHandler::WaitSend(uint64_t timeout)
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("get sock link handle failed");
return RC_MEM_ERROR;
}
int32_t ret = conn->SendData(_req_data, _req_len);
if (ret < 0)
{
MTLOG_ERROR("sock send failed, ret %d[%m]", ret);
return RC_SEND_FAIL;
}
this->SkipSendPos(ret);
if (_req_len == 0)
{
MTLOG_DEBUG("sock send ok");
return RC_SUCCESS;
}
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>л<EFBFBD><D0BB>ѷ<EFBFBD><D1B7>͵<EFBFBD><CDB5><EFBFBD>Ϣ
this->SwitchToSend();
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
MtFrame* mtframe = MtFrame::Instance();
mtframe->WaitNotify(timeout);
// ɾ<><C9BE><EFBFBD><EFBFBD>connect<63><74><EFBFBD><EFBFBD>
this->SwitchToIdle();
// <20><EFBFBD><ECB3A3><EFBFBD><EFBFBD>
if (_err_no != 0)
{
MTLOG_ERROR("send get out errno %d", _err_no);
return _err_no;
}
// <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
if (_req_len == 0)
{
MTLOG_DEBUG("send req ok, len %u", _send_pos);
return 0;
}
else
{
MTLOG_TRACE("send req not ok, left len %u", _req_len);
return RC_SEND_FAIL;
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>Ϣ
int32_t CNetHandler::WaitRecv(uint64_t timeout)
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("get sock link handle failed");
return RC_MEM_ERROR;
}
if (_conn_type == TYPE_CONN_SENDONLY)
{
MTLOG_DEBUG("only send, without recv");
return 0;
}
// <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>
this->SwitchToRecv();
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
MtFrame* mtframe = MtFrame::Instance();
mtframe->WaitNotify(timeout);
// ɾ<><C9BE><EFBFBD><EFBFBD>connect<63><74><EFBFBD><EFBFBD>
this->SwitchToIdle();
// <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
if ((_rsp_buff != NULL) && (_rsp_buff->data_len > 0))
{
MTLOG_DEBUG("recv get rsp, len %d", _rsp_buff->data_len);
return 0;
}
else
{
MTLOG_TRACE("recv get out errno %d", _err_no);
return RC_RECV_FAIL;
}
}
// ͬ<><CDAC><EFBFBD>շ<EFBFBD><D5B7>ӿ<EFBFBD>, <20>޸<EFBFBD>Ϊsessionר<6E><D7A8>
int32_t CNetHandler::SendRecv(void* data, uint32_t len, uint32_t timeout)
{
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
utime64_t cost_time = 0;
uint64_t time_left = timeout;
this->_req_data = data;
this->_req_len = len;
// 0. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
int32_t ret = this->CheckParams();
if (ret < 0)
{
MTLOG_ERROR("check params failed, ret[%d]", ret);
goto EXIT_LABEL;
}
// 1. <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·ָ<C2B7><D6B8>
ret = this->GetConnLink();
if (ret < 0)
{
MTLOG_ERROR("get sock conn failed, ret: %d", ret);
goto EXIT_LABEL;
}
// 2. <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ӳɹ<D3B3>
ret = this->WaitConnect(time_left);
if (ret < 0)
{
MTLOG_ERROR("sock connect failed, ret: %d", ret);
goto EXIT_LABEL;
}
// 3. <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ͳɹ<CDB3>
cost_time = MtFrame::Instance()->GetLastClock() - start_ms;
time_left = (timeout > (uint32_t)cost_time) ? (timeout - (uint32_t)cost_time) : 0;
ret = this->WaitSend(time_left);
if (ret < 0)
{
MTLOG_ERROR("sock send failed, ret: %d", ret);
goto EXIT_LABEL;
}
// 4. <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ճɹ<D5B3>
cost_time = MtFrame::Instance()->GetLastClock() - start_ms;
time_left = (timeout > (uint32_t)cost_time) ? (timeout - (uint32_t)cost_time) : 0;
ret = this->WaitRecv(time_left);
if (ret < 0)
{
MTLOG_ERROR("sock recv failed, ret: %d", ret);
goto EXIT_LABEL;
}
// 5. <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>
ret = 0;
EXIT_LABEL:
// <20><><EFBFBD>η<EFBFBD><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>ҪUNLINK, <20><><EFBFBD><EFBFBD>NETHANDLER֧<52><D6A7>
this->Unlink();
// <20>ɹ<EFBFBD>ʧ<EFBFBD><CAA7>, <20><>Ҫȥ<D2AA><C8A5>sessionע<6E><D7A2>
this->UnRegistSession();
return ret;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>󳤶<EFBFBD>
uint32_t CNetHandler::SkipSendPos(uint32_t len)
{
uint32_t skip_len = (len >= _req_len) ? _req_len : len;
_req_len -= skip_len;
_send_pos += skip_len;
_req_data = (char*)_req_data + skip_len;
return skip_len;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>
void CNetHandler::Link(CSockLink* conn)
{
this->_conn_ptr = conn;
this->SwitchToIdle();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>
void CNetHandler::Unlink()
{
if (this->_state_flags != 0)
{
this->DetachConn();
}
this->_conn_ptr = NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ڵȴ<DAB5><C8B4><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>
void CNetHandler::SwitchToConn()
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("net handler invalid");
return;
}
this->DetachConn();
this->_state_flags |= STATE_IN_CONNECT;
conn->AppendToList(CSockLink::LINK_CONN_LIST, this);
}
// <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
void CNetHandler::SwitchToSend()
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("net handler invalid");
return;
}
this->DetachConn();
this->_state_flags |= STATE_IN_SEND;
conn->AppendToList(CSockLink::LINK_SEND_LIST, this);
}
// <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD><D5B6><EFBFBD>
void CNetHandler::SwitchToRecv()
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("net handler invalid");
return;
}
this->DetachConn();
this->_state_flags |= STATE_IN_RECV;
conn->AppendToList(CSockLink::LINK_RECV_LIST, this);
}
// <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
void CNetHandler::SwitchToIdle()
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_ERROR("net handler invalid");
return;
}
this->DetachConn();
this->_state_flags |= STATE_IN_IDLE;
conn->AppendToList(CSockLink::LINK_IDLE_LIST, this);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>
void CNetHandler::DetachConn()
{
CSockLink* conn = (CSockLink*)this->_conn_ptr;
if (NULL == conn)
{
MTLOG_DEBUG("net handler not set");
return;
}
if (_state_flags == 0) // <20><>ʱ<EFBFBD><CAB1><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>, 2<><32><EFBFBD><EFBFBD>֧, <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
return;
}
if (_state_flags & STATE_IN_CONNECT)
{
conn->RemoveFromList(CSockLink::LINK_CONN_LIST, this);
_state_flags &= ~STATE_IN_CONNECT;
}
if (_state_flags & STATE_IN_SEND)
{
conn->RemoveFromList(CSockLink::LINK_SEND_LIST, this);
_state_flags &= ~STATE_IN_SEND;
}
if (_state_flags & STATE_IN_RECV)
{
conn->RemoveFromList(CSockLink::LINK_RECV_LIST, this);
_state_flags &= ~STATE_IN_RECV;
}
if (_state_flags & STATE_IN_IDLE)
{
conn->RemoveFromList(CSockLink::LINK_IDLE_LIST, this);
_state_flags &= ~STATE_IN_IDLE;
}
}
/**
* @brief <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hash<EFBFBD>, <EFBFBD><EFBFBD>ȡkey<EFBFBD><EFBFBD>hashֵ
* @return <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hashֵ
*/
uint32_t CNetHandler::HashValue()
{
uint32_t ip = _dest_ipv4.sin_addr.s_addr;
ip ^= (_dest_ipv4.sin_port << 16) | (_proto_type << 8) | (_conn_type << 8);
uint32_t hash = (_session_id >> 32) & 0xffffffff;
hash ^= _session_id & 0xffffffff;
hash ^= ip;
return hash;
}
/**
* @brief <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>cmp<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ͬһͰID<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>key<EFBFBD>Ƚ<EFBFBD>
* @return <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hashֵ
*/
int32_t CNetHandler::HashCmp(HashKey* rhs)
{
CNetHandler* data = (CNetHandler*)(rhs);
if (!data) {
return -1;
}
if (this->_session_id != data->_session_id)
{
return (this->_session_id > data->_session_id) ? 1 : -1;
}
if (this->_dest_ipv4.sin_addr.s_addr != data->_dest_ipv4.sin_addr.s_addr) {
return (this->_dest_ipv4.sin_addr.s_addr > data->_dest_ipv4.sin_addr.s_addr) ? 1 : -1;
}
if (this->_dest_ipv4.sin_port != data->_dest_ipv4.sin_port) {
return (this->_dest_ipv4.sin_port > data->_dest_ipv4.sin_port) ? 1 : -1;
}
if (this->_proto_type != data->_proto_type) {
return (this->_proto_type > data->_proto_type) ? 1 : -1;
}
if (this->_conn_type != data->_conn_type) {
return (this->_conn_type > data->_conn_type) ? 1 : -1;
}
return 0;
};
// ע<><D7A2>session<6F><6E><EFBFBD><EFBFBD>
bool CNetHandler::RegistSession()
{
if (CNetMgr::Instance()->FindNetItem(this) != NULL)
{
return false;
}
MtFrame* mtframe = MtFrame::Instance();
this->_thread = mtframe->GetActiveThread();
CNetMgr::Instance()->InsertNetItem(this);
this->_state_flags |= STATE_IN_SESSION;
return true;
}
// ȡ<><C8A1>ע<EFBFBD><D7A2>session
void CNetHandler::UnRegistSession()
{
if (this->_state_flags & STATE_IN_SESSION)
{
CNetMgr::Instance()->RemoveNetItem(this);
this->_state_flags &= ~STATE_IN_SESSION;
}
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TNetItemList* CSockLink::GetItemList(int32_t type)
{
TNetItemList* list = NULL;
switch (type)
{
case LINK_IDLE_LIST:
list = &this->_idle_list;
break;
case LINK_CONN_LIST:
list = &this->_wait_connect;
break;
case LINK_SEND_LIST:
list = &this->_wait_send;
break;
case LINK_RECV_LIST:
list = &this->_wait_recv;
break;
default:
break;
}
return list;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
void CSockLink::AppendToList(int32_t type, CNetHandler* item)
{
TNetItemList* list = this->GetItemList(type);
if (NULL == list)
{
MTLOG_ERROR("unknown list type: %d", type);
return;
}
TAILQ_INSERT_TAIL(list, item, _link_entry);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
void CSockLink::RemoveFromList(int32_t type, CNetHandler* item)
{
TNetItemList* list = this->GetItemList(type);
if (NULL == list)
{
MTLOG_ERROR("unknown list type: %d", type);
return;
}
TAILQ_REMOVE(list, item, _link_entry);
}
// ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
void CSockLink::NotifyThread(CNetHandler* item, int32_t result)
{
static MtFrame* frame = NULL;
if (frame == NULL) {
frame = MtFrame::Instance();
}
// <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
if (result != RC_SUCCESS)
{
item->SetErrNo(result);
}
// <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>
MicroThread* thread = item->GetThread();
if ((thread != NULL) && (thread->HasFlag(MicroThread::IO_LIST)))
{
frame->RemoveIoWait(thread);
frame->InsertRunable(thread);
}
}
// ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
void CSockLink::NotifyAll(int32_t result)
{
CNetHandler* item = NULL;
CNetHandler* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &_wait_connect, _link_entry, tmp)
{
NotifyThread(item, result);
item->Unlink();
}
TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
{
NotifyThread(item, result);
item->Unlink();
}
TAILQ_FOREACH_SAFE(item, &_wait_recv, _link_entry, tmp)
{
NotifyThread(item, result);
item->Unlink();
}
TAILQ_FOREACH_SAFE(item, &_idle_list, _link_entry, tmp)
{
NotifyThread(item, result);
item->Unlink();
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>߼<EFBFBD>
void CSockLink::Reset()
{
// <20>ر<EFBFBD>fd, ֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
this->Close();
this->NotifyAll(_errno);
// <20><><EFBFBD><EFBFBD>cache<68><65><EFBFBD><EFBFBD>
rw_cache_destroy(&_recv_cache);
if (_rsp_buff != NULL)
{
delete_sk_buffer(_rsp_buff);
_rsp_buff = NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>ѵȴ<D1B5><C8B4>߳<EFBFBD>
TAILQ_INIT(&_wait_connect);
TAILQ_INIT(&_wait_send);
TAILQ_INIT(&_wait_recv);
TAILQ_INIT(&_idle_list);
_proto_type = NET_PROTO_TCP;
_errno = 0;
_state = 0;
_last_access = mt_time_ms();
_parents = NULL;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->KqueuerObj::Reset();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CSockLink::CSockLink()
{
rw_cache_init(&_recv_cache, NULL);
_rsp_buff = NULL;
TAILQ_INIT(&_wait_connect);
TAILQ_INIT(&_wait_send);
TAILQ_INIT(&_wait_recv);
TAILQ_INIT(&_idle_list);
_proto_type = NET_PROTO_TCP;
_errno = 0;
_state = 0;
_last_access = mt_time_ms();
_parents = NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CSockLink::~CSockLink()
{
this->Reset();
}
// <20><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>buff<66>ص<EFBFBD>ָ<EFBFBD><D6B8>
void CSockLink::SetProtoType(MT_PROTO_TYPE type)
{
_proto_type = type;
_recv_cache.pool = CNetMgr::Instance()->GetSkBuffMng(type);
}
// <20>ر<EFBFBD><D8B1><EFBFBD>·<EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>
void CSockLink::Close()
{
// 1. <20><><EFBFBD><EFBFBD>δ<EFBFBD><CEB4>ʼ<EFBFBD><CABC>, ֱ<>ӷ<EFBFBD><D3B7><EFBFBD>
if (_fd < 0)
{
return;
}
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>
MtFrame::Instance()->KqueueDelObj(this);
// 3. <20>رվ<D8B1><D5BE><EFBFBD>
close(_fd);
_fd = -1;
}
// <20><EFBFBD><ECB3A3>ֹ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void CSockLink::Destroy()
{
CDestLinks* dstlink = (CDestLinks*)_parents;
if (NULL == dstlink)
{
MTLOG_ERROR("socket link without parents ptr, maybe wrong");
delete this;
}
else
{
MTLOG_DEBUG("socket link just free");
dstlink->FreeSockLink(this);
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>򴴽<EFBFBD>socket<65><74><EFBFBD><EFBFBD>
int32_t CSockLink::CreateSock()
{
if (_fd > 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
{
return _fd;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>𴴽<EFBFBD>
if (NET_PROTO_TCP == _proto_type)
{
_fd = socket(AF_INET, SOCK_STREAM, 0);
}
else
{
_fd = socket(AF_INET, SOCK_DGRAM, 0);
}
if (_fd < 0)
{
MTLOG_ERROR("create socket failed, ret %d[%m]", _fd);
return -1;
}
// <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>
int flags = 1;
if (ioctl(_fd, FIONBIO, &flags) < 0)
{
MTLOG_ERROR("socket unblock failed, %m");
close(_fd);
_fd = -1;
return -2;
}
// ѡ<><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, NODELAY
if (NET_PROTO_TCP == _proto_type)
{
setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));
this->EnableOutput(); // TCP <20>ȴ<EFBFBD>connect<63><74><EFBFBD><EFBFBD>, ʡһ<CAA1><D2BB>epollctrl
}
// <20><><EFBFBD><EFBFBD>epoll<6C><6C><EFBFBD><EFBFBD>
this->EnableInput();
if (!MtFrame::Instance()->KqueueAddObj(this))
{
MTLOG_ERROR("socket epoll mng failed, %m");
close(_fd);
_fd = -1;
return -3;
}
return _fd;
}
// <20><>ȡĿ<C8A1><C4BF>ip<69><70>Ϣ
struct sockaddr_in* CSockLink::GetDestAddr(struct sockaddr_in* addr)
{
CDestLinks* dstlink = (CDestLinks*)_parents;
if ((NULL == _parents) || (NULL == addr)) {
return NULL;
}
uint32_t ip = 0;
uint16_t port = 0;
dstlink->GetDestIP(ip, port);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = ip;
addr->sin_port = port;
return addr;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD>
bool CSockLink::Connect()
{
this->_last_access = mt_time_ms();
// 1. UDP<44><50><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD>
if (_proto_type == NET_PROTO_UDP)
{
_state |= LINK_CONNECTED;
}
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬, <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>
if (_state & LINK_CONNECTED)
{
return true;
}
// 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>˳<EFBFBD><CBB3>ȴ<EFBFBD>
if (_state & LINK_CONNECTING)
{
return false;
}
// 4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>״<EFBFBD><D7B4><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD>
struct sockaddr_in addr = {0};
mt_hook_syscall(connect);
int32_t ret = ff_hook_connect(_fd, (struct sockaddr*)this->GetDestAddr(&addr), sizeof(struct sockaddr_in));
if (ret < 0)
{
int32_t err = errno;
if (err == EISCONN)
{
_state |= LINK_CONNECTED;
return true;
}
else
{
_state |= LINK_CONNECTING;
if ((err == EINPROGRESS) || (err == EALREADY) || (err == EINTR))
{
MTLOG_DEBUG("Open connect not ok, maybe first try, sock %d, errno %d", _fd, err);
return false;
}
else
{
MTLOG_ERROR("Open connect not ok, sock %d, errno %d", _fd, err);
return false;
}
}
}
else
{
_state |= LINK_CONNECTED;
return true;
}
}
// <20><>UDP<44>ķ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>͵ȴ<CDB5><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, һ<><D2BB>ֱ<EFBFBD>Ӿͷ<D3BE><CDB7><EFBFBD>OK
int32_t CSockLink::SendCacheUdp(void* data, uint32_t len)
{
mt_hook_syscall(sendto);
void* buff = NULL;
uint32_t buff_len = 0;
CNetHandler* item = NULL;
CNetHandler* tmp = NULL;
struct sockaddr_in dst = {0};
// 1. <20><><EFBFBD>Է<EFBFBD><D4B7>͵ȴ<CDB5><C8B4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
{
item->GetSendData(buff, buff_len);
if ((NULL == buff) || (buff_len == 0))
{
MTLOG_ERROR("get buff ptr invalid, log it");
NotifyThread(item, 0);
item->SwitchToIdle();
continue;
}
int32_t ret = ff_hook_sendto(_fd, buff, buff_len, 0,
(struct sockaddr*)this->GetDestAddr(&dst), sizeof(struct sockaddr_in));
if (ret == -1)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _fd,
errno, strerror(errno));
return -2;
}
}
NotifyThread(item, 0);
item->SwitchToIdle();
}
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OK<4F><4B>, <20>ٷ<EFBFBD><D9B7>ͱ<EFBFBD><CDB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, û<>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((data == NULL) || (len == 0))
{
return 0;
}
int32_t ret = ff_hook_sendto(_fd, data, len, 0,
(struct sockaddr*)this->GetDestAddr(&dst), sizeof(struct sockaddr_in));
if (ret == -1)
{
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
{
return 0;
}
else
{
MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _fd,
errno, strerror(errno));
return -2;
}
}
else
{
return ret;
}
}
// TCP<43>Ļ<EFBFBD><C4BB><EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD>
int32_t CSockLink::SendCacheTcp(void* data, uint32_t len)
{
void* buff = NULL;
uint32_t buff_len = 0;
struct iovec iov[64];
int32_t count = 0;
CNetHandler* item = NULL;
CNetHandler* tmp = NULL;
// 1. <20><><EFBFBD>Է<EFBFBD><D4B7>͵ȴ<CDB5><C8B4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
{
item->GetSendData(buff, buff_len);
iov[count].iov_base = buff;
iov[count].iov_len = (int32_t)buff_len;
count++;
if (count >= 64)
{
break;
}
}
if ((count < 64) && (data != NULL))
{
iov[count].iov_base = data;
iov[count].iov_len = (int32_t)len;
count++;
}
ssize_t bytes = writev(_fd, iov, count);
if (bytes < 0)
{
if ((errno == EAGAIN) || (errno == EINTR))
{
return 0;
}
else
{
MTLOG_ERROR("socket writev failed, fd %d, errno %d(%s)", _fd,
errno, strerror(errno));
return -1;
}
}
// 2. <20><><EFBFBD>Է<EFBFBD><D4B7>͵ȴ<CDB5><C8B4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
uint32_t send_left = (uint32_t)bytes;
TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
{
send_left -= item->SkipSendPos(send_left);
item->GetSendData(buff, buff_len);
if (buff_len == 0)
{
NotifyThread(item, 0);
item->SwitchToIdle();
}
if (send_left == 0)
{
break;
}
}
return send_left;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD>
int32_t CSockLink::SendData(void* data, uint32_t len)
{
int32_t ret = 0;
bool rc = false;
this->_last_access = mt_time_ms();
// 1. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>Ŷӵ<C5B6><D3B5><EFBFBD><EFBFBD><EFBFBD>
if (_proto_type == NET_PROTO_UDP)
{
ret = SendCacheUdp(data, len);
}
else
{
ret = SendCacheTcp(data, len);
}
// 2. <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OUT
if (ret < (int32_t)len)
{
this->EnableOutput();
rc = MtFrame::Instance()->KqueueCtrlAdd(_fd, KQ_EVENT_READ);
}
else
{
this->DisableOutput();
rc = MtFrame::Instance()->KqueueCtrlDel(_fd, KQ_EVENT_WRITE);
}
// 3. <20><><EFBFBD><EFBFBD>ˢ<EFBFBD>¾<EFBFBD><C2BE><EFBFBD>epollע<6C><D7A2>
if (!rc)
{
MTLOG_ERROR("socket epoll mng failed[%m], wait timeout");
}
return ret;
}
// <20><><EFBFBD>ݷַ<DDB7><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int32_t CSockLink::RecvDispath()
{
if (_proto_type == NET_PROTO_UDP)
{
return this->DispathUdp();
}
else
{
return this->DispathTcp();
}
}
// <20><><EFBFBD>Խ<EFBFBD><D4BD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD>ʱbuff
void CSockLink::ExtendRecvRsp()
{
if (NULL == _rsp_buff)
{
// buff<66><66><EFBFBD>η<EFBFBD><CEB7><EFBFBD>, <20><><EFBFBD><EFBFBD>̫<EFBFBD><CCAB>, <20><EFBFBD><E1B5BC><EFBFBD>ظ<EFBFBD><D8B8>Ŀ<EFBFBD><C4BF><EFBFBD>; <20><><EFBFBD><EFBFBD>̫С, <20><EFBFBD><E1B5BC>2<EFBFBD><32>check<63><6B><EFBFBD><EFBFBD>
// Ȩ<><C8A8>һ<EFBFBD><D2BB>, <20>ݶ<EFBFBD>500<30>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>, <20>󲿷ֳ<F3B2BFB7><D6B3><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ, <20>˷Ѳ<CBB7><D1B2><EFBFBD>, С<><D0A1><EFBFBD>ֳ<EFBFBD><D6B3><EFBFBD>
// <20><>Ҫrealloc, <20><>500<30>ֽڿ<D6BD><DABF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>
_rsp_buff = new_sk_buffer(512);
if (NULL == _rsp_buff)
{
MTLOG_ERROR("no more memory, error");
return;
}
}
_rsp_buff->data_len += read_cache_begin(&_recv_cache, _rsp_buff->data_len,
_rsp_buff->data + _rsp_buff->data_len , _rsp_buff->size - _rsp_buff->data_len);
}
// <20><><EFBFBD>߻ص<DFBB><D8B5><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>ȴ<EFBFBD><C8B4>Ŷӵȴ<D3B5><C8B4>л<EFBFBD>ȡ, <20><><EFBFBD>ݴӸ<DDB4><D3B8>ڵ<EFBFBD><DAB5><EFBFBD>ȡ
CHECK_SESSION_CALLBACK CSockLink::GetSessionCallback()
{
CHECK_SESSION_CALLBACK check_session = NULL;
// 1. <20>Ŷӻ<C5B6>ȡ<EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
CNetHandler* item = TAILQ_FIRST(&_wait_recv);
if (NULL == item)
{
MTLOG_DEBUG("recv data with no wait item, err");
goto EXIT_LABEL;
}
check_session = item->GetSessionCallback();
if (NULL == check_session)
{
MTLOG_ERROR("recv data with no session callback, err");
goto EXIT_LABEL;
}
EXIT_LABEL:
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ΪNULL, ֱ<>ӷ<EFBFBD><D3B7>ض<EFBFBD><D8B6>н<EFBFBD><D0BD><EFBFBD>
CDestLinks* dstlink = (CDestLinks*)_parents;
if (NULL == dstlink)
{
return check_session;
}
// 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD>Ϊ<EFBFBD><CEAA>, <20><><EFBFBD><EFBFBD>·Ĭ<C2B7>ϻ<EFBFBD><CFBB><EFBFBD><EFBFBD><EFBFBD>func; <20><>Ϊ<EFBFBD><CEAA>, <20>򱣴<EFBFBD><F2B1A3B4><EFBFBD>
if (check_session != NULL)
{
dstlink->SetDefaultCallback(check_session);
}
else
{
check_session = dstlink->GetDefaultCallback();
}
return check_session;
}
// TCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
int32_t CSockLink::DispathTcp()
{
// 1. TCP<43>޵ȴ<DEB5><C8B4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β, ֻ<>ܹر<DCB9>
CHECK_SESSION_CALLBACK check_session = this->GetSessionCallback();
if (NULL == check_session)
{
MTLOG_ERROR("recv data with no session callback, err");
return -1;
}
// 2. <20><><EFBFBD><EFBFBD>ͬһIP/PORT<52><54>Э<EFBFBD><D0AD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>
uint32_t need_len = 0;
uint64_t sid = 0;
int32_t ret = 0;
while (_recv_cache.len > 0)
{
this->ExtendRecvRsp();
if (NULL == _rsp_buff)
{
MTLOG_ERROR("alloc memory, error");
_errno = RC_MEM_ERROR;
return -3;
}
need_len = 0;
ret = check_session(_rsp_buff->data, _rsp_buff->data_len, &sid, &need_len);
if (ret < 0)
{
MTLOG_ERROR("user check resp failed, ret %d", ret);
_errno = RC_CHECK_PKG_FAIL;
return -1;
}
if (ret == 0)
{
// 1. <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, Ĭ<><C4AC>2<EFBFBD><32><EFBFBD><EFBFBD>չ, <20><><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD>Ӱ<EFBFBD><D3B0>
if ((need_len == 0) && (_rsp_buff->data_len == _rsp_buff->size))
{
MTLOG_DEBUG("recv default buff full[%u], but user no set need length", _rsp_buff->size);
need_len = _rsp_buff->size * 2;
}
// 2. <20><><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD>ռ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>; <20><><EFBFBD><EFBFBD><EFBFBD>ռ<D5BC><E4B3AC>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((need_len <= _rsp_buff->size) || (need_len > 100*1024*1024))
{
MTLOG_DEBUG("maybe need wait more data: %u", need_len);
return 0;
}
// 3. <20><>չbuff<66><66><EFBFBD><EFBFBD>, ׼<><D7BC><EFBFBD>ٳ<EFBFBD><D9B3><EFBFBD>һ<EFBFBD><D2BB>
_rsp_buff = reserve_sk_buffer(_rsp_buff, need_len);
if (NULL == _rsp_buff)
{
MTLOG_ERROR("no more memory, error");
_errno = RC_MEM_ERROR;
return -3;
}
// 4. <20>Ѿ<EFBFBD><D1BE>޶<EFBFBD><DEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ, <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>
if (_rsp_buff->data_len >= _recv_cache.len)
{
MTLOG_DEBUG("maybe need wait more data, now %u", _recv_cache.len);
return 0;
}
// 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD>
continue;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>
if (ret > (int32_t)_recv_cache.len)
{
MTLOG_DEBUG("maybe pkg not all ok, wait more");
return 0;
}
// <20><>ѯ<EFBFBD><D1AF>session<6F>Ķ<EFBFBD><C4B6><EFBFBD>
CNetHandler* session = this->FindSession(sid);
if (NULL == session)
{
MTLOG_DEBUG("session id %llu, find failed, maybe timeout", sid);
cache_skip_data(&_recv_cache, ret);
delete_sk_buffer(_rsp_buff);
_rsp_buff = NULL;
}
else
{
MTLOG_DEBUG("session id %llu, find ok, wakeup it", sid);
cache_skip_data(&_recv_cache, ret);
this->NotifyThread(session, 0);
session->SwitchToIdle();
_rsp_buff->data_len = ret; //TCPʵ<50><CAB5><EFBFBD><EFBFBD>Ч<EFBFBD>ı<EFBFBD><C4B1>ij<EFBFBD><C4B3>ȱ<EFBFBD><C8B1><EFBFBD>
session->SetRespBuff(_rsp_buff);
_rsp_buff = NULL;
}
}
return 0;
}
// UDP<44><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
int32_t CSockLink::DispathUdp()
{
// 1. UDP<44><50><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еı<D0B5><C4B1><EFBFBD>
CHECK_SESSION_CALLBACK check_session = NULL;
CNetHandler* item = TAILQ_FIRST(&_wait_recv);
if (NULL == item)
{
MTLOG_DEBUG("recv data with no wait item, maybe wrong pkg recv");
// <20>˴<EFBFBD><CBB4><EFBFBD><EFBFBD>˳<EFBFBD>, <20><>Ϊ<EFBFBD><CEAA><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>UDPӦ<50><D3A6>(<28><>ʱ<EFBFBD><CAB1>\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
}
else
{
check_session = item->GetSessionCallback();
if (NULL == check_session)
{
MTLOG_TRACE("recv data with no session callback, err");
}
}
// 2. <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>, <20>ҵ<EFBFBD>session<6F>ʹ<EFBFBD><CDB4><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint64_t sid = 0;
uint32_t need_len = 0;
int32_t ret = 0;
TSkBuffer* block = NULL;
while ((block = TAILQ_FIRST(&_recv_cache.list)) != NULL)
{
if (check_session == NULL)
{
MTLOG_DEBUG("no recv wait, skip first block");
cache_skip_data(&_recv_cache, block->data_len);
continue;
}
need_len = 0;
ret = check_session(block->data, block->data_len, &sid, &need_len);
if ((ret <= 0) || (ret > (int32_t)block->data_len))
{
MTLOG_DEBUG("maybe wrong pkg come, skip it");
cache_skip_data(&_recv_cache, block->data_len);
continue;
}
// <20><>ѯ<EFBFBD><D1AF>session<6F>Ķ<EFBFBD><C4B6><EFBFBD>
CNetHandler* session = this->FindSession(sid);
if (NULL == session)
{
MTLOG_DEBUG("session id %llu, find failed, maybe timeout", sid);
cache_skip_data(&_recv_cache, block->data_len);
}
else
{
MTLOG_DEBUG("session id %llu, find ok, wakeup it", sid);
this->NotifyThread(session, 0);
session->SwitchToIdle();
cache_skip_first_buffer(&_recv_cache);
session->SetRespBuff(block);
}
}
return 0;
}
// <20><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>sessionid<69><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>session<6F><6E>Ϣ
CNetHandler* CSockLink::FindSession(uint64_t sid)
{
CNetHandler key;
CDestLinks* dstlink = (CDestLinks*)_parents;
if (NULL == dstlink)
{
MTLOG_ERROR("session dest link invalid, maybe error");
return NULL;
}
struct sockaddr_in addr;
key.SetDestAddress(this->GetDestAddr(&addr));
key.SetConnType(dstlink->GetConnType());
key.SetProtoType(dstlink->GetProtoType());
key.SetSessionId(sid);
return CNetMgr::Instance()->FindNetItem(&key);
}
/**
* @brief <EFBFBD>ɶ<EFBFBD><EFBFBD>¼<EFBFBD>֪ͨ<EFBFBD>ӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return 0 <EFBFBD><EFBFBD>fd<EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>; !=0 <EFBFBD><EFBFBD>fd<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int CSockLink::InputNotify()
{
int32_t ret = 0;
this->_last_access = mt_time_ms();
// 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (_proto_type == NET_PROTO_UDP)
{
ret = cache_udp_recv(&_recv_cache, _fd, NULL);
}
else
{
ret = cache_tcp_recv(&_recv_cache, _fd);
}
// 2. <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (ret < 0)
{
if (ret == -SK_ERR_NEED_CLOSE)
{
MTLOG_DEBUG("recv on link failed, remote close");
_errno = RC_REMOTE_CLOSED;
}
else
{
MTLOG_ERROR("recv on link failed, close it, ret %d[%m]", ret);
_errno = RC_RECV_FAIL;
}
this->Destroy();
return -1;
}
// 3. <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TCP
ret = this->RecvDispath();
if (ret < 0)
{
MTLOG_DEBUG("recv dispath failed, close it, ret %d[%m]", ret);
this->Destroy();
return -2;
}
// 4. <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>
return 0;
}
/**
* @brief <EFBFBD><EFBFBD>д<EFBFBD>¼<EFBFBD>֪ͨ<EFBFBD>ӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return 0 <EFBFBD><EFBFBD>fd<EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>; !=0 <EFBFBD><EFBFBD>fd<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int CSockLink::OutputNotify()
{
int32_t ret = 0;
this->_last_access = mt_time_ms();
// 1. <20><><EFBFBD>ӵȴ<D3B5><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
if (_state & LINK_CONNECTING)
{
_state &= ~LINK_CONNECTING;
_state |= LINK_CONNECTED;
CNetHandler* item = NULL;
CNetHandler* tmp = NULL;
TAILQ_FOREACH_SAFE(item, &_wait_connect, _link_entry, tmp)
{
NotifyThread(item, 0);
item->SwitchToIdle();
}
}
// 2. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (_proto_type == NET_PROTO_UDP)
{
ret = SendCacheUdp(NULL, 0);
}
else
{
ret = SendCacheTcp(NULL, 0);
}
// 3. <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (ret < 0)
{
MTLOG_ERROR("Send on link failed, close it, ret %d[%m]", ret);
_errno = RC_SEND_FAIL;
this->Destroy();
return ret;
}
// 4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>epoll
if (TAILQ_EMPTY(&_wait_send))
{
this->DisableOutput();
if (!MtFrame::Instance()->KqueueCtrlDel(_fd, KQ_EVENT_WRITE))
{
MTLOG_ERROR("socket epoll mng failed[%m], wait timeout");
}
}
return 0;
}
/**
* @brief <EFBFBD>֪ͨ<EFBFBD>ӿ<EFBFBD>
* @return <EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD>ֵ, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int CSockLink::HangupNotify()
{
MTLOG_ERROR("socket epoll error, fd %d", _fd);
this->_errno = RC_KQUEUE_ERROR;
this->Destroy();
return -1;
}
// <20><><EFBFBD><EFBFBD><ECBAAF>
CDestLinks::CDestLinks()
{
_timeout = 5*60*1000; // Ĭ<><C4AC>5<EFBFBD><35><EFBFBD><EFBFBD>
_addr_ipv4 = 0;
_net_port = 0;
_proto_type = NET_PROTO_UNDEF;
_conn_type = TYPE_CONN_SESSION;
_max_links = 3; // Ĭ<><C4AC>3<EFBFBD><33>
_curr_link = 0;
_dflt_callback = NULL;
TAILQ_INIT(&_sock_list);
}
// <20><><EFBFBD>ø<EFBFBD><C3B8>õĽӿں<D3BF><DABA><EFBFBD>
void CDestLinks::Reset()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>
CSockLink* item = NULL;
CSockLink* temp = NULL;
TAILQ_FOREACH_SAFE(item, &_sock_list, _link_entry, temp)
{
item->Destroy();
}
TAILQ_INIT(&_sock_list);
// <20><>ʱ<EFBFBD><CAB1>ɾ<EFBFBD><C9BE>
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
if (NULL != timer)
{
timer->stop_timer(this);
}
// <20><><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD>Ϣ
_timeout = 5*60*1000; // Ĭ<><C4AC>5<EFBFBD><35><EFBFBD><EFBFBD>
_addr_ipv4 = 0;
_net_port = 0;
_proto_type = NET_PROTO_UNDEF;
_conn_type = TYPE_CONN_SESSION;
_max_links = 3; // Ĭ<><C4AC>3<EFBFBD><33>
_curr_link = 0;
}
// <20><><EFBFBD><EFBFBD><ECBAAF>
CDestLinks::~CDestLinks()
{
this->Reset();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
void CDestLinks::StartTimer()
{
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
if ((NULL == timer) || !timer->start_timer(this, 60*1000))
{
MTLOG_ERROR("obj %p attach timer failed, error", this);
}
}
// <20>ͷ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>link
void CDestLinks::FreeSockLink(CSockLink* sock)
{
if ((sock == NULL) || (sock->GetParentsPtr() != (void*)this))
{
MTLOG_ERROR("invalid socklink %p, error", sock);
return;
}
TAILQ_REMOVE(&_sock_list, sock, _link_entry);
if (this->_curr_link > 0) {
this->_curr_link--;
}
sock->Reset();
CNetMgr::Instance()->FreeSockLink(sock);
}
// <20><>ȡһ<C8A1><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>link, ĿǰΪ<C7B0><CEAA>ѯ
CSockLink* CDestLinks::GetSockLink()
{
CSockLink* link = NULL;
if (_curr_link < _max_links)
{
link = CNetMgr::Instance()->AllocSockLink();
if (NULL == link)
{
MTLOG_ERROR("alloc sock link failed, error");
return NULL;
}
link->SetParentsPtr(this);
link->SetProtoType(_proto_type);
TAILQ_INSERT_TAIL(&_sock_list, link, _link_entry);
_curr_link++;
}
else
{
link = TAILQ_FIRST(&_sock_list);
TAILQ_REMOVE(&_sock_list, link, _link_entry);
TAILQ_INSERT_TAIL(&_sock_list, link, _link_entry);
}
return link;
}
/**
* @brief <EFBFBD><EFBFBD>ʱ֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void CDestLinks::timer_notify()
{
// 1. <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>п<EFBFBD><D0BF>е<EFBFBD><D0B5><EFBFBD>·, ɾ<><C9BE><EFBFBD><EFBFBD>
uint64_t now = mt_time_ms();
CSockLink* item = NULL;
CSockLink* temp = NULL;
TAILQ_FOREACH_SAFE(item, &_sock_list, _link_entry, temp)
{
if ((item->GetLastAccess() + this->_timeout) < now)
{
MTLOG_DEBUG("link timeout, last[%llu], now [%llu]", item->GetLastAccess(), now);
item->Destroy();
}
}
// 2. <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>·, û<><C3BB><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
item = TAILQ_FIRST(&_sock_list);
if (NULL == item)
{
MTLOG_DEBUG("dest links timeout, now [%llu]", now);
CNetMgr::Instance()->DeleteDestLink(this);
return;
}
// 3. <20><><EFBFBD>¼<EFBFBD><C2BC>붨ʱ<EBB6A8><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->StartTimer();
return;
}
/**
* @brief sessionȫ<EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return ȫ<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
*/
CNetMgr* CNetMgr::_instance = NULL;
CNetMgr* CNetMgr::Instance (void)
{
if (NULL == _instance)
{
_instance = new CNetMgr();
}
return _instance;
}
/**
* @brief session<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽӿ<EFBFBD>
*/
void CNetMgr::Destroy()
{
if( _instance != NULL )
{
delete _instance;
_instance = NULL;
}
}
// <20><>ѯ<EFBFBD>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB>sid<69>Ķ<EFBFBD><C4B6><EFBFBD>
CNetHandler* CNetMgr::FindNetItem(CNetHandler* key)
{
if (NULL == this->_session_hash)
{
return NULL;
}
return (CNetHandler*)_session_hash->HashFind(key);
}
// ע<><D7A2>һ<EFBFBD><D2BB>item, <20>Ȳ<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>֤<EFBFBD>޳<EFBFBD>ͻ
void CNetMgr::InsertNetItem(CNetHandler* item)
{
if (NULL == this->_session_hash)
{
return;
}
int32_t ret = _session_hash->HashInsert(item);
if (ret < 0)
{
MTLOG_ERROR("session insert failed, ret %d", ret);
}
return;
}
// <20>Ƴ<EFBFBD>һ<EFBFBD><D2BB>item<65><6D><EFBFBD><EFBFBD>
void CNetMgr::RemoveNetItem(CNetHandler* item)
{
CNetHandler* handler = this->FindNetItem(item);
if (NULL == handler)
{
return;
}
_session_hash->HashRemove(handler);
}
// <20><>ѯ<EFBFBD>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB>sid<69>Ķ<EFBFBD><C4B6><EFBFBD>
CDestLinks* CNetMgr::FindDestLink(CDestLinks* key)
{
if (NULL == this->_ip_hash)
{
return NULL;
}
return (CDestLinks*)_ip_hash->HashFind(key);
}
// ע<><D7A2>һ<EFBFBD><D2BB>item, <20>Ȳ<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>֤<EFBFBD>޳<EFBFBD>ͻ
void CNetMgr::InsertDestLink(CDestLinks* item)
{
if (NULL == this->_ip_hash)
{
return;
}
int32_t ret = _ip_hash->HashInsert(item);
if (ret < 0)
{
MTLOG_ERROR("ip dest insert failed, ret %d", ret);
}
return;
}
// <20>Ƴ<EFBFBD>һ<EFBFBD><D2BB>item<65><6D><EFBFBD><EFBFBD>
void CNetMgr::RemoveDestLink(CDestLinks* item)
{
CDestLinks* handler = this->FindDestLink(item);
if (NULL == handler)
{
return;
}
_ip_hash->HashRemove(handler);
}
// <20><>ѯ<EFBFBD>򴴽<EFBFBD>һ<EFBFBD><D2BB>Ŀ<EFBFBD><C4BF>ip<69><70>links<6B>ڵ<EFBFBD>
CDestLinks* CNetMgr::FindCreateDest(CDestLinks* key)
{
CDestLinks* dest = this->FindDestLink(key);
if (dest != NULL)
{
MTLOG_DEBUG("dest links reuse ok");
return dest;
}
dest = this->AllocDestLink();
if (NULL == dest)
{
MTLOG_ERROR("dest links alloc failed, log it");
return NULL;
}
dest->CopyKeyInfo(key);
dest->StartTimer();
this->InsertDestLink(dest);
return dest;
}
// <20><>ѯ<EFBFBD>򴴽<EFBFBD>һ<EFBFBD><D2BB>Ŀ<EFBFBD><C4BF>ip<69><70>links<6B>ڵ<EFBFBD>
void CNetMgr::DeleteDestLink(CDestLinks* dst)
{
this->RemoveDestLink(dst);
dst->Reset(); // ֱ<><D6B1>freeǰ<65><C7B0><EFBFBD><EFBFBD> reset
this->FreeDestLink(dst);
}
// <20><><EFBFBD><EFBFBD><ECBAAF>ʵ<EFBFBD><CAB5>
CNetMgr::CNetMgr()
{
sk_buffer_mng_init(&_tcp_pool, 60, 4096);
sk_buffer_mng_init(&_udp_pool, 60, SK_DFLT_BUFF_SIZE);
_ip_hash = new HashList(100000);
_session_hash = new HashList(100000);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
CNetMgr::~CNetMgr()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>dest<73><74>Դ
if (_ip_hash != NULL)
{
HashKey* hash_item = _ip_hash->HashGetFirst();
while (hash_item)
{
delete hash_item;
hash_item = _ip_hash->HashGetFirst();
}
delete _ip_hash;
_ip_hash = NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> netitem <20><>Դ
if (_session_hash != NULL)
{
HashKey* hash_item = _session_hash->HashGetFirst();
while (hash_item)
{
delete hash_item;
hash_item = _session_hash->HashGetFirst();
}
delete _session_hash;
_session_hash = NULL;
}
// <20><><EFBFBD><EFBFBD>buff<66><66><EFBFBD><EFBFBD>Դ
sk_buffer_mng_destroy(&_tcp_pool);
sk_buffer_mng_destroy(&_udp_pool);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>Ϣ
*/
void CNetMgr::RecycleObjs(uint64_t now)
{
uint32_t now_s = (uint32_t)(now / 1000);
recycle_sk_buffer(&_udp_pool, now_s);
recycle_sk_buffer(&_tcp_pool, now_s);
_net_item_pool.RecycleItem(now);
_sock_link_pool.RecycleItem(now);
_dest_ip_pool.RecycleItem(now);
}