mirror of https://github.com/F-Stack/f-stack.git
1988 lines
44 KiB
C++
1988 lines
44 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_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);
|
|||
|
}
|
|||
|
|
|||
|
|