1a9643ea8Slogwang
2a9643ea8Slogwang /**
3a9643ea8Slogwang * Tencent is pleased to support the open source community by making MSEC available.
4a9643ea8Slogwang *
5a9643ea8Slogwang * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6a9643ea8Slogwang *
7a9643ea8Slogwang * Licensed under the GNU General Public License, Version 2.0 (the "License");
8a9643ea8Slogwang * you may not use this file except in compliance with the License. You may
9a9643ea8Slogwang * obtain a copy of the License at
10a9643ea8Slogwang *
11a9643ea8Slogwang * https://opensource.org/licenses/GPL-2.0
12a9643ea8Slogwang *
13a9643ea8Slogwang * Unless required by applicable law or agreed to in writing, software distributed under the
14a9643ea8Slogwang * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15a9643ea8Slogwang * either express or implied. See the License for the specific language governing permissions
16a9643ea8Slogwang * and limitations under the License.
17a9643ea8Slogwang */
18a9643ea8Slogwang
19a9643ea8Slogwang
20a9643ea8Slogwang /**
21a9643ea8Slogwang * @file mt_mbuf_pool.cpp
22a9643ea8Slogwang * @time 20130924
23a9643ea8Slogwang **/
24a9643ea8Slogwang
25a9643ea8Slogwang #include <errno.h>
26a9643ea8Slogwang #include <netinet/tcp.h>
27a9643ea8Slogwang #include "micro_thread.h"
28a9643ea8Slogwang #include "mt_sys_hook.h"
29a9643ea8Slogwang #include "ff_hook.h"
30a9643ea8Slogwang #include "mt_net.h"
31a9643ea8Slogwang
32a9643ea8Slogwang
33a9643ea8Slogwang using namespace std;
34a9643ea8Slogwang using namespace NS_MICRO_THREAD;
35a9643ea8Slogwang
CNetHelper()36a9643ea8Slogwang CNetHelper::CNetHelper()
37a9643ea8Slogwang {
38a9643ea8Slogwang handler = (void*)CNetMgr::Instance()->AllocNetItem();
39a9643ea8Slogwang }
40a9643ea8Slogwang
~CNetHelper()41a9643ea8Slogwang CNetHelper::~CNetHelper()
42a9643ea8Slogwang {
43a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
44a9643ea8Slogwang if (handler != NULL)
45a9643ea8Slogwang {
46a9643ea8Slogwang net_handler->Reset();
47a9643ea8Slogwang CNetMgr::Instance()->FreeNetItem(net_handler);
48a9643ea8Slogwang handler = NULL;
49a9643ea8Slogwang }
50a9643ea8Slogwang }
51a9643ea8Slogwang
SendRecv(void * data,uint32_t len,uint32_t timeout)52a9643ea8Slogwang int32_t CNetHelper::SendRecv(void* data, uint32_t len, uint32_t timeout)
53a9643ea8Slogwang {
54a9643ea8Slogwang if (handler != NULL) {
55a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
56a9643ea8Slogwang return net_handler->SendRecv(data, len, timeout);
57a9643ea8Slogwang } else {
58a9643ea8Slogwang return RC_INVALID_HANDLER;
59a9643ea8Slogwang }
60a9643ea8Slogwang }
61a9643ea8Slogwang
GetRspBuff()62a9643ea8Slogwang void* CNetHelper::GetRspBuff()
63a9643ea8Slogwang {
64a9643ea8Slogwang if (handler != NULL) {
65a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
66a9643ea8Slogwang return net_handler->GetRspBuff();
67a9643ea8Slogwang } else {
68a9643ea8Slogwang return NULL;
69a9643ea8Slogwang }
70a9643ea8Slogwang }
71a9643ea8Slogwang
GetRspLen()72a9643ea8Slogwang uint32_t CNetHelper::GetRspLen()
73a9643ea8Slogwang {
74a9643ea8Slogwang if (handler != NULL) {
75a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
76a9643ea8Slogwang return net_handler->GetRspLen();
77a9643ea8Slogwang } else {
78a9643ea8Slogwang return 0;
79a9643ea8Slogwang }
80a9643ea8Slogwang }
81a9643ea8Slogwang
GetErrMsg(int32_t result)82a9643ea8Slogwang char* CNetHelper::GetErrMsg(int32_t result)
83a9643ea8Slogwang {
84a9643ea8Slogwang static const char* errmsg = "unknown error type";
85a9643ea8Slogwang
86a9643ea8Slogwang switch (result)
87a9643ea8Slogwang {
88a9643ea8Slogwang case RC_SUCCESS:
89a9643ea8Slogwang errmsg = "success";
90a9643ea8Slogwang break;
91a9643ea8Slogwang
92a9643ea8Slogwang case RC_ERR_SOCKET:
93a9643ea8Slogwang errmsg = "create socket failed";
94a9643ea8Slogwang break;
95a9643ea8Slogwang
96a9643ea8Slogwang case RC_SEND_FAIL:
97a9643ea8Slogwang errmsg = "send pakeage timeout or failed";
98a9643ea8Slogwang break;
99a9643ea8Slogwang
100a9643ea8Slogwang case RC_RECV_FAIL:
101a9643ea8Slogwang errmsg = "recv response timeout or failed";
102a9643ea8Slogwang break;
103a9643ea8Slogwang
104a9643ea8Slogwang case RC_CONNECT_FAIL:
105a9643ea8Slogwang errmsg = "connect timeout or failed";
106a9643ea8Slogwang break;
107a9643ea8Slogwang
108a9643ea8Slogwang case RC_CHECK_PKG_FAIL:
109a9643ea8Slogwang errmsg = "user package check failed";
110a9643ea8Slogwang break;
111a9643ea8Slogwang
112a9643ea8Slogwang case RC_NO_MORE_BUFF:
113a9643ea8Slogwang errmsg = "user response buffer too small";
114a9643ea8Slogwang break;
115a9643ea8Slogwang
116a9643ea8Slogwang case RC_REMOTE_CLOSED:
117a9643ea8Slogwang errmsg = "remote close connection";
118a9643ea8Slogwang break;
119a9643ea8Slogwang
120a9643ea8Slogwang case RC_INVALID_PARAM:
121a9643ea8Slogwang errmsg = "params invalid";
122a9643ea8Slogwang break;
123a9643ea8Slogwang
124a9643ea8Slogwang case RC_INVALID_HANDLER:
125a9643ea8Slogwang errmsg = "net handler invalid";
126a9643ea8Slogwang break;
127a9643ea8Slogwang
128a9643ea8Slogwang case RC_MEM_ERROR:
129a9643ea8Slogwang errmsg = "no more memory, alloc failed";
130a9643ea8Slogwang break;
131a9643ea8Slogwang
132a9643ea8Slogwang case RC_CONFLICT_SID:
133a9643ea8Slogwang errmsg = "session id with the dest address conflict";
134a9643ea8Slogwang break;
135a9643ea8Slogwang
136a9643ea8Slogwang case RC_KQUEUE_ERROR:
137a9643ea8Slogwang errmsg = "epoll system error";
138a9643ea8Slogwang break;
139a9643ea8Slogwang
140a9643ea8Slogwang default:
141a9643ea8Slogwang break;
142a9643ea8Slogwang }
143a9643ea8Slogwang
144a9643ea8Slogwang return (char*)errmsg;
145a9643ea8Slogwang }
146a9643ea8Slogwang
SetProtoType(MT_PROTO_TYPE type)147a9643ea8Slogwang void CNetHelper::SetProtoType(MT_PROTO_TYPE type)
148a9643ea8Slogwang {
149a9643ea8Slogwang if (handler != NULL) {
150a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
151a9643ea8Slogwang return net_handler->SetProtoType(type);
152a9643ea8Slogwang }
153a9643ea8Slogwang }
154a9643ea8Slogwang
SetDestAddress(struct sockaddr_in * dst)155a9643ea8Slogwang void CNetHelper::SetDestAddress(struct sockaddr_in* dst)
156a9643ea8Slogwang {
157a9643ea8Slogwang if (handler != NULL) {
158a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
159a9643ea8Slogwang return net_handler->SetDestAddress(dst);
160a9643ea8Slogwang }
161a9643ea8Slogwang }
162a9643ea8Slogwang
SetSessionId(uint64_t sid)163a9643ea8Slogwang void CNetHelper::SetSessionId(uint64_t sid)
164a9643ea8Slogwang {
165a9643ea8Slogwang if (handler != NULL) {
166a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
167a9643ea8Slogwang return net_handler->SetSessionId(sid);
168a9643ea8Slogwang }
169a9643ea8Slogwang }
170a9643ea8Slogwang
SetSessionCallback(CHECK_SESSION_CALLBACK function)171a9643ea8Slogwang void CNetHelper::SetSessionCallback(CHECK_SESSION_CALLBACK function)
172a9643ea8Slogwang {
173a9643ea8Slogwang if (handler != NULL) {
174a9643ea8Slogwang CNetHandler* net_handler = (CNetHandler*)handler;
175a9643ea8Slogwang return net_handler->SetSessionCallback(function);
176a9643ea8Slogwang }
177a9643ea8Slogwang }
178a9643ea8Slogwang
Reset()179a9643ea8Slogwang void CNetHandler::Reset()
180a9643ea8Slogwang {
181a9643ea8Slogwang this->Unlink();
182a9643ea8Slogwang this->UnRegistSession();
183a9643ea8Slogwang
184a9643ea8Slogwang if (_rsp_buff != NULL) {
185a9643ea8Slogwang delete_sk_buffer(_rsp_buff);
186a9643ea8Slogwang _rsp_buff = NULL;
187a9643ea8Slogwang }
188a9643ea8Slogwang
189a9643ea8Slogwang _thread = NULL;
190a9643ea8Slogwang _proto_type = NET_PROTO_TCP;
191a9643ea8Slogwang _conn_type = TYPE_CONN_SESSION;
192a9643ea8Slogwang _dest_ipv4.sin_addr.s_addr = 0;
193a9643ea8Slogwang _dest_ipv4.sin_port = 0;
194a9643ea8Slogwang _session_id = 0;
195a9643ea8Slogwang _callback = NULL;
196a9643ea8Slogwang _err_no = 0;
197a9643ea8Slogwang _state_flags = 0;
198a9643ea8Slogwang _conn_ptr = NULL;
199a9643ea8Slogwang _send_pos = 0;
200a9643ea8Slogwang _req_len = 0;
201a9643ea8Slogwang _req_data = NULL;
202a9643ea8Slogwang
203a9643ea8Slogwang }
204a9643ea8Slogwang
CNetHandler()205a9643ea8Slogwang CNetHandler::CNetHandler()
206a9643ea8Slogwang {
207a9643ea8Slogwang _state_flags = 0;
208a9643ea8Slogwang _rsp_buff = NULL;
209a9643ea8Slogwang
210a9643ea8Slogwang this->Reset();
211a9643ea8Slogwang }
212a9643ea8Slogwang
~CNetHandler()213a9643ea8Slogwang CNetHandler::~CNetHandler()
214a9643ea8Slogwang {
215a9643ea8Slogwang this->Reset();
216a9643ea8Slogwang }
217a9643ea8Slogwang
CheckParams()218a9643ea8Slogwang int32_t CNetHandler::CheckParams()
219a9643ea8Slogwang {
220a9643ea8Slogwang if ((NULL == _req_data) || (_req_len == 0))
221a9643ea8Slogwang {
222a9643ea8Slogwang MTLOG_ERROR("param invalid, data[%p], len[%u]", _req_data, _req_len);
223a9643ea8Slogwang return RC_INVALID_PARAM;
224a9643ea8Slogwang }
225a9643ea8Slogwang
226a9643ea8Slogwang if ((_dest_ipv4.sin_addr.s_addr == 0) || (_dest_ipv4.sin_port == 0))
227a9643ea8Slogwang {
228a9643ea8Slogwang MTLOG_ERROR("param invalid, ip[%u], port[%u]", _dest_ipv4.sin_addr.s_addr,
229a9643ea8Slogwang _dest_ipv4.sin_port);
230a9643ea8Slogwang return RC_INVALID_PARAM;
231a9643ea8Slogwang }
232a9643ea8Slogwang
233a9643ea8Slogwang if (_conn_type == TYPE_CONN_SESSION)
234a9643ea8Slogwang {
235a9643ea8Slogwang if ((_callback == NULL) || (_session_id == 0))
236a9643ea8Slogwang {
237a9643ea8Slogwang MTLOG_ERROR("param invalid, callback[%p], session_id[%llu]", _callback, _session_id);
238a9643ea8Slogwang return RC_INVALID_PARAM;
239a9643ea8Slogwang }
240a9643ea8Slogwang
241a9643ea8Slogwang if (!this->RegistSession())
242a9643ea8Slogwang {
243a9643ea8Slogwang MTLOG_ERROR("param invalid, session_id[%llu] regist failed", _session_id);
244a9643ea8Slogwang return RC_CONFLICT_SID;
245a9643ea8Slogwang }
246a9643ea8Slogwang }
247a9643ea8Slogwang
248a9643ea8Slogwang return 0;
249a9643ea8Slogwang }
250a9643ea8Slogwang
GetConnLink()251a9643ea8Slogwang int32_t CNetHandler::GetConnLink()
252a9643ea8Slogwang {
253a9643ea8Slogwang CDestLinks key;
254a9643ea8Slogwang key.SetKeyInfo(_dest_ipv4.sin_addr.s_addr, _dest_ipv4.sin_port, _proto_type, _conn_type);
255a9643ea8Slogwang
256a9643ea8Slogwang CDestLinks* dest_link = CNetMgr::Instance()->FindCreateDest(&key);
257a9643ea8Slogwang if (NULL == dest_link)
258a9643ea8Slogwang {
259a9643ea8Slogwang MTLOG_ERROR("get dest link handle failed");
260a9643ea8Slogwang return RC_MEM_ERROR;
261a9643ea8Slogwang }
262a9643ea8Slogwang
263a9643ea8Slogwang CSockLink* sock_link = dest_link->GetSockLink();
264a9643ea8Slogwang if (NULL == sock_link)
265a9643ea8Slogwang {
266a9643ea8Slogwang MTLOG_ERROR("get sock link handle failed");
267a9643ea8Slogwang return RC_MEM_ERROR;
268a9643ea8Slogwang }
269a9643ea8Slogwang
270a9643ea8Slogwang this->Link(sock_link);
271a9643ea8Slogwang
272a9643ea8Slogwang return 0;
273a9643ea8Slogwang }
274a9643ea8Slogwang
WaitConnect(uint64_t timeout)275a9643ea8Slogwang int32_t CNetHandler::WaitConnect(uint64_t timeout)
276a9643ea8Slogwang {
277a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
278a9643ea8Slogwang if (NULL == conn)
279a9643ea8Slogwang {
280a9643ea8Slogwang MTLOG_ERROR("get sock link handle failed");
281a9643ea8Slogwang return RC_MEM_ERROR;
282a9643ea8Slogwang }
283a9643ea8Slogwang
284a9643ea8Slogwang int32_t fd = conn->CreateSock();
285a9643ea8Slogwang if (fd < 0)
286a9643ea8Slogwang {
287a9643ea8Slogwang MTLOG_ERROR("create sock failed, ret %d[%m]", fd);
288a9643ea8Slogwang return RC_ERR_SOCKET;
289a9643ea8Slogwang }
290a9643ea8Slogwang
291a9643ea8Slogwang if (conn->Connect())
292a9643ea8Slogwang {
293a9643ea8Slogwang MTLOG_DEBUG("sock conncet ok");
294a9643ea8Slogwang return RC_SUCCESS;
295a9643ea8Slogwang }
296a9643ea8Slogwang
297a9643ea8Slogwang this->SwitchToConn();
298a9643ea8Slogwang
299a9643ea8Slogwang MtFrame* mtframe = MtFrame::Instance();
300a9643ea8Slogwang mtframe->WaitNotify(timeout);
301a9643ea8Slogwang
302a9643ea8Slogwang this->SwitchToIdle();
303a9643ea8Slogwang
304a9643ea8Slogwang if (_err_no != 0)
305a9643ea8Slogwang {
306a9643ea8Slogwang MTLOG_ERROR("connect get out errno %d", _err_no);
307a9643ea8Slogwang return _err_no;
308a9643ea8Slogwang }
309a9643ea8Slogwang
310a9643ea8Slogwang if (conn->Connected())
311a9643ea8Slogwang {
312a9643ea8Slogwang MTLOG_DEBUG("connect ok");
313a9643ea8Slogwang return 0;
314a9643ea8Slogwang }
315a9643ea8Slogwang else
316a9643ea8Slogwang {
317a9643ea8Slogwang MTLOG_TRACE("connect not ok, maybe timeout");
318a9643ea8Slogwang return RC_CONNECT_FAIL;
319a9643ea8Slogwang }
320a9643ea8Slogwang }
321a9643ea8Slogwang
WaitSend(uint64_t timeout)322a9643ea8Slogwang int32_t CNetHandler::WaitSend(uint64_t timeout)
323a9643ea8Slogwang {
324a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
325a9643ea8Slogwang if (NULL == conn)
326a9643ea8Slogwang {
327a9643ea8Slogwang MTLOG_ERROR("get sock link handle failed");
328a9643ea8Slogwang return RC_MEM_ERROR;
329a9643ea8Slogwang }
330a9643ea8Slogwang
331a9643ea8Slogwang int32_t ret = conn->SendData(_req_data, _req_len);
332a9643ea8Slogwang if (ret < 0)
333a9643ea8Slogwang {
334a9643ea8Slogwang MTLOG_ERROR("sock send failed, ret %d[%m]", ret);
335a9643ea8Slogwang return RC_SEND_FAIL;
336a9643ea8Slogwang }
337a9643ea8Slogwang this->SkipSendPos(ret);
338a9643ea8Slogwang
339a9643ea8Slogwang if (_req_len == 0)
340a9643ea8Slogwang {
341a9643ea8Slogwang MTLOG_DEBUG("sock send ok");
342a9643ea8Slogwang return RC_SUCCESS;
343a9643ea8Slogwang }
344a9643ea8Slogwang
345a9643ea8Slogwang this->SwitchToSend();
346a9643ea8Slogwang
347a9643ea8Slogwang MtFrame* mtframe = MtFrame::Instance();
348a9643ea8Slogwang mtframe->WaitNotify(timeout);
349a9643ea8Slogwang
350a9643ea8Slogwang this->SwitchToIdle();
351a9643ea8Slogwang
352a9643ea8Slogwang if (_err_no != 0)
353a9643ea8Slogwang {
354a9643ea8Slogwang MTLOG_ERROR("send get out errno %d", _err_no);
355a9643ea8Slogwang return _err_no;
356a9643ea8Slogwang }
357a9643ea8Slogwang
358a9643ea8Slogwang if (_req_len == 0)
359a9643ea8Slogwang {
360a9643ea8Slogwang MTLOG_DEBUG("send req ok, len %u", _send_pos);
361a9643ea8Slogwang return 0;
362a9643ea8Slogwang }
363a9643ea8Slogwang else
364a9643ea8Slogwang {
365a9643ea8Slogwang MTLOG_TRACE("send req not ok, left len %u", _req_len);
366a9643ea8Slogwang return RC_SEND_FAIL;
367a9643ea8Slogwang }
368a9643ea8Slogwang }
369a9643ea8Slogwang
WaitRecv(uint64_t timeout)370a9643ea8Slogwang int32_t CNetHandler::WaitRecv(uint64_t timeout)
371a9643ea8Slogwang {
372a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
373a9643ea8Slogwang if (NULL == conn)
374a9643ea8Slogwang {
375a9643ea8Slogwang MTLOG_ERROR("get sock link handle failed");
376a9643ea8Slogwang return RC_MEM_ERROR;
377a9643ea8Slogwang }
378a9643ea8Slogwang
379a9643ea8Slogwang if (_conn_type == TYPE_CONN_SENDONLY)
380a9643ea8Slogwang {
381a9643ea8Slogwang MTLOG_DEBUG("only send, without recv");
382a9643ea8Slogwang return 0;
383a9643ea8Slogwang }
384a9643ea8Slogwang
385a9643ea8Slogwang this->SwitchToRecv();
386a9643ea8Slogwang
387a9643ea8Slogwang MtFrame* mtframe = MtFrame::Instance();
388a9643ea8Slogwang mtframe->WaitNotify(timeout);
389a9643ea8Slogwang
390a9643ea8Slogwang this->SwitchToIdle();
391a9643ea8Slogwang
392a9643ea8Slogwang if ((_rsp_buff != NULL) && (_rsp_buff->data_len > 0))
393a9643ea8Slogwang {
394a9643ea8Slogwang MTLOG_DEBUG("recv get rsp, len %d", _rsp_buff->data_len);
395a9643ea8Slogwang return 0;
396a9643ea8Slogwang }
397a9643ea8Slogwang else
398a9643ea8Slogwang {
399a9643ea8Slogwang MTLOG_TRACE("recv get out errno %d", _err_no);
400a9643ea8Slogwang return RC_RECV_FAIL;
401a9643ea8Slogwang }
402a9643ea8Slogwang }
403a9643ea8Slogwang
SendRecv(void * data,uint32_t len,uint32_t timeout)404a9643ea8Slogwang int32_t CNetHandler::SendRecv(void* data, uint32_t len, uint32_t timeout)
405a9643ea8Slogwang {
406a9643ea8Slogwang utime64_t start_ms = MtFrame::Instance()->GetLastClock();
407a9643ea8Slogwang utime64_t cost_time = 0;
408a9643ea8Slogwang uint64_t time_left = timeout;
409a9643ea8Slogwang this->_req_data = data;
410a9643ea8Slogwang this->_req_len = len;
411a9643ea8Slogwang
412a9643ea8Slogwang int32_t ret = this->CheckParams();
413a9643ea8Slogwang if (ret < 0)
414a9643ea8Slogwang {
415a9643ea8Slogwang MTLOG_ERROR("check params failed, ret[%d]", ret);
416a9643ea8Slogwang goto EXIT_LABEL;
417a9643ea8Slogwang }
418a9643ea8Slogwang
419a9643ea8Slogwang ret = this->GetConnLink();
420a9643ea8Slogwang if (ret < 0)
421a9643ea8Slogwang {
422a9643ea8Slogwang MTLOG_ERROR("get sock conn failed, ret: %d", ret);
423a9643ea8Slogwang goto EXIT_LABEL;
424a9643ea8Slogwang }
425a9643ea8Slogwang
426a9643ea8Slogwang ret = this->WaitConnect(time_left);
427a9643ea8Slogwang if (ret < 0)
428a9643ea8Slogwang {
429a9643ea8Slogwang MTLOG_ERROR("sock connect failed, ret: %d", ret);
430a9643ea8Slogwang goto EXIT_LABEL;
431a9643ea8Slogwang }
432a9643ea8Slogwang
433a9643ea8Slogwang cost_time = MtFrame::Instance()->GetLastClock() - start_ms;
434a9643ea8Slogwang time_left = (timeout > (uint32_t)cost_time) ? (timeout - (uint32_t)cost_time) : 0;
435a9643ea8Slogwang ret = this->WaitSend(time_left);
436a9643ea8Slogwang if (ret < 0)
437a9643ea8Slogwang {
438a9643ea8Slogwang MTLOG_ERROR("sock send failed, ret: %d", ret);
439a9643ea8Slogwang goto EXIT_LABEL;
440a9643ea8Slogwang }
441a9643ea8Slogwang
442a9643ea8Slogwang cost_time = MtFrame::Instance()->GetLastClock() - start_ms;
443a9643ea8Slogwang time_left = (timeout > (uint32_t)cost_time) ? (timeout - (uint32_t)cost_time) : 0;
444a9643ea8Slogwang ret = this->WaitRecv(time_left);
445a9643ea8Slogwang if (ret < 0)
446a9643ea8Slogwang {
447a9643ea8Slogwang MTLOG_ERROR("sock recv failed, ret: %d", ret);
448a9643ea8Slogwang goto EXIT_LABEL;
449a9643ea8Slogwang }
450a9643ea8Slogwang
451a9643ea8Slogwang ret = 0;
452a9643ea8Slogwang
453a9643ea8Slogwang EXIT_LABEL:
454a9643ea8Slogwang
455a9643ea8Slogwang this->Unlink();
456a9643ea8Slogwang
457a9643ea8Slogwang this->UnRegistSession();
458a9643ea8Slogwang
459a9643ea8Slogwang return ret;
460a9643ea8Slogwang }
461a9643ea8Slogwang
SkipSendPos(uint32_t len)462a9643ea8Slogwang uint32_t CNetHandler::SkipSendPos(uint32_t len)
463a9643ea8Slogwang {
464a9643ea8Slogwang uint32_t skip_len = (len >= _req_len) ? _req_len : len;
465a9643ea8Slogwang _req_len -= skip_len;
466a9643ea8Slogwang _send_pos += skip_len;
467a9643ea8Slogwang _req_data = (char*)_req_data + skip_len;
468a9643ea8Slogwang
469a9643ea8Slogwang return skip_len;
470a9643ea8Slogwang }
471a9643ea8Slogwang
Link(CSockLink * conn)472a9643ea8Slogwang void CNetHandler::Link(CSockLink* conn)
473a9643ea8Slogwang {
474a9643ea8Slogwang this->_conn_ptr = conn;
475a9643ea8Slogwang this->SwitchToIdle();
476a9643ea8Slogwang }
477a9643ea8Slogwang
Unlink()478a9643ea8Slogwang void CNetHandler::Unlink()
479a9643ea8Slogwang {
480a9643ea8Slogwang if (this->_state_flags != 0)
481a9643ea8Slogwang {
482a9643ea8Slogwang this->DetachConn();
483a9643ea8Slogwang }
484a9643ea8Slogwang this->_conn_ptr = NULL;
485a9643ea8Slogwang }
486a9643ea8Slogwang
SwitchToConn()487a9643ea8Slogwang void CNetHandler::SwitchToConn()
488a9643ea8Slogwang {
489a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
490a9643ea8Slogwang if (NULL == conn)
491a9643ea8Slogwang {
492a9643ea8Slogwang MTLOG_ERROR("net handler invalid");
493a9643ea8Slogwang return;
494a9643ea8Slogwang }
495a9643ea8Slogwang
496a9643ea8Slogwang this->DetachConn();
497a9643ea8Slogwang
498a9643ea8Slogwang this->_state_flags |= STATE_IN_CONNECT;
499a9643ea8Slogwang conn->AppendToList(CSockLink::LINK_CONN_LIST, this);
500a9643ea8Slogwang }
501a9643ea8Slogwang
SwitchToSend()502a9643ea8Slogwang void CNetHandler::SwitchToSend()
503a9643ea8Slogwang {
504a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
505a9643ea8Slogwang if (NULL == conn)
506a9643ea8Slogwang {
507a9643ea8Slogwang MTLOG_ERROR("net handler invalid");
508a9643ea8Slogwang return;
509a9643ea8Slogwang }
510a9643ea8Slogwang
511a9643ea8Slogwang this->DetachConn();
512a9643ea8Slogwang
513a9643ea8Slogwang this->_state_flags |= STATE_IN_SEND;
514a9643ea8Slogwang conn->AppendToList(CSockLink::LINK_SEND_LIST, this);
515a9643ea8Slogwang }
516a9643ea8Slogwang
SwitchToRecv()517a9643ea8Slogwang void CNetHandler::SwitchToRecv()
518a9643ea8Slogwang {
519a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
520a9643ea8Slogwang if (NULL == conn)
521a9643ea8Slogwang {
522a9643ea8Slogwang MTLOG_ERROR("net handler invalid");
523a9643ea8Slogwang return;
524a9643ea8Slogwang }
525a9643ea8Slogwang
526a9643ea8Slogwang this->DetachConn();
527a9643ea8Slogwang
528a9643ea8Slogwang this->_state_flags |= STATE_IN_RECV;
529a9643ea8Slogwang conn->AppendToList(CSockLink::LINK_RECV_LIST, this);
530a9643ea8Slogwang }
531a9643ea8Slogwang
SwitchToIdle()532a9643ea8Slogwang void CNetHandler::SwitchToIdle()
533a9643ea8Slogwang {
534a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
535a9643ea8Slogwang if (NULL == conn)
536a9643ea8Slogwang {
537a9643ea8Slogwang MTLOG_ERROR("net handler invalid");
538a9643ea8Slogwang return;
539a9643ea8Slogwang }
540a9643ea8Slogwang
541a9643ea8Slogwang this->DetachConn();
542a9643ea8Slogwang
543a9643ea8Slogwang this->_state_flags |= STATE_IN_IDLE;
544a9643ea8Slogwang conn->AppendToList(CSockLink::LINK_IDLE_LIST, this);
545a9643ea8Slogwang }
546a9643ea8Slogwang
DetachConn()547a9643ea8Slogwang void CNetHandler::DetachConn()
548a9643ea8Slogwang {
549a9643ea8Slogwang CSockLink* conn = (CSockLink*)this->_conn_ptr;
550a9643ea8Slogwang if (NULL == conn)
551a9643ea8Slogwang {
552a9643ea8Slogwang MTLOG_DEBUG("net handler not set");
553a9643ea8Slogwang return;
554a9643ea8Slogwang }
555a9643ea8Slogwang
556*35a81399Slogwang if (_state_flags == 0)
557a9643ea8Slogwang {
558a9643ea8Slogwang return;
559a9643ea8Slogwang }
560a9643ea8Slogwang
561a9643ea8Slogwang if (_state_flags & STATE_IN_CONNECT)
562a9643ea8Slogwang {
563a9643ea8Slogwang conn->RemoveFromList(CSockLink::LINK_CONN_LIST, this);
564a9643ea8Slogwang _state_flags &= ~STATE_IN_CONNECT;
565a9643ea8Slogwang }
566a9643ea8Slogwang
567a9643ea8Slogwang if (_state_flags & STATE_IN_SEND)
568a9643ea8Slogwang {
569a9643ea8Slogwang conn->RemoveFromList(CSockLink::LINK_SEND_LIST, this);
570a9643ea8Slogwang _state_flags &= ~STATE_IN_SEND;
571a9643ea8Slogwang }
572a9643ea8Slogwang
573a9643ea8Slogwang if (_state_flags & STATE_IN_RECV)
574a9643ea8Slogwang {
575a9643ea8Slogwang conn->RemoveFromList(CSockLink::LINK_RECV_LIST, this);
576a9643ea8Slogwang _state_flags &= ~STATE_IN_RECV;
577a9643ea8Slogwang }
578a9643ea8Slogwang
579a9643ea8Slogwang if (_state_flags & STATE_IN_IDLE)
580a9643ea8Slogwang {
581a9643ea8Slogwang conn->RemoveFromList(CSockLink::LINK_IDLE_LIST, this);
582a9643ea8Slogwang _state_flags &= ~STATE_IN_IDLE;
583a9643ea8Slogwang }
584a9643ea8Slogwang }
585a9643ea8Slogwang
HashValue()586a9643ea8Slogwang uint32_t CNetHandler::HashValue()
587a9643ea8Slogwang {
588a9643ea8Slogwang uint32_t ip = _dest_ipv4.sin_addr.s_addr;
589a9643ea8Slogwang ip ^= (_dest_ipv4.sin_port << 16) | (_proto_type << 8) | (_conn_type << 8);
590a9643ea8Slogwang
591a9643ea8Slogwang uint32_t hash = (_session_id >> 32) & 0xffffffff;
592a9643ea8Slogwang hash ^= _session_id & 0xffffffff;
593a9643ea8Slogwang hash ^= ip;
594a9643ea8Slogwang
595a9643ea8Slogwang return hash;
596a9643ea8Slogwang }
597a9643ea8Slogwang
HashCmp(HashKey * rhs)598a9643ea8Slogwang int32_t CNetHandler::HashCmp(HashKey* rhs)
599a9643ea8Slogwang {
600a9643ea8Slogwang CNetHandler* data = (CNetHandler*)(rhs);
601a9643ea8Slogwang if (!data) {
602a9643ea8Slogwang return -1;
603a9643ea8Slogwang }
604a9643ea8Slogwang if (this->_session_id != data->_session_id)
605a9643ea8Slogwang {
606a9643ea8Slogwang return (this->_session_id > data->_session_id) ? 1 : -1;
607a9643ea8Slogwang }
608a9643ea8Slogwang
609a9643ea8Slogwang if (this->_dest_ipv4.sin_addr.s_addr != data->_dest_ipv4.sin_addr.s_addr) {
610a9643ea8Slogwang return (this->_dest_ipv4.sin_addr.s_addr > data->_dest_ipv4.sin_addr.s_addr) ? 1 : -1;
611a9643ea8Slogwang }
612a9643ea8Slogwang if (this->_dest_ipv4.sin_port != data->_dest_ipv4.sin_port) {
613a9643ea8Slogwang return (this->_dest_ipv4.sin_port > data->_dest_ipv4.sin_port) ? 1 : -1;
614a9643ea8Slogwang }
615a9643ea8Slogwang if (this->_proto_type != data->_proto_type) {
616a9643ea8Slogwang return (this->_proto_type > data->_proto_type) ? 1 : -1;
617a9643ea8Slogwang }
618a9643ea8Slogwang if (this->_conn_type != data->_conn_type) {
619a9643ea8Slogwang return (this->_conn_type > data->_conn_type) ? 1 : -1;
620a9643ea8Slogwang }
621a9643ea8Slogwang
622a9643ea8Slogwang return 0;
623a9643ea8Slogwang };
624a9643ea8Slogwang
RegistSession()625a9643ea8Slogwang bool CNetHandler::RegistSession()
626a9643ea8Slogwang {
627a9643ea8Slogwang if (CNetMgr::Instance()->FindNetItem(this) != NULL)
628a9643ea8Slogwang {
629a9643ea8Slogwang return false;
630a9643ea8Slogwang }
631a9643ea8Slogwang
632a9643ea8Slogwang MtFrame* mtframe = MtFrame::Instance();
633a9643ea8Slogwang this->_thread = mtframe->GetActiveThread();
634a9643ea8Slogwang
635a9643ea8Slogwang CNetMgr::Instance()->InsertNetItem(this);
636a9643ea8Slogwang this->_state_flags |= STATE_IN_SESSION;
637a9643ea8Slogwang return true;
638a9643ea8Slogwang }
639a9643ea8Slogwang
UnRegistSession()640a9643ea8Slogwang void CNetHandler::UnRegistSession()
641a9643ea8Slogwang {
642a9643ea8Slogwang if (this->_state_flags & STATE_IN_SESSION)
643a9643ea8Slogwang {
644a9643ea8Slogwang CNetMgr::Instance()->RemoveNetItem(this);
645a9643ea8Slogwang this->_state_flags &= ~STATE_IN_SESSION;
646a9643ea8Slogwang }
647a9643ea8Slogwang }
648a9643ea8Slogwang
GetItemList(int32_t type)649a9643ea8Slogwang TNetItemList* CSockLink::GetItemList(int32_t type)
650a9643ea8Slogwang {
651a9643ea8Slogwang TNetItemList* list = NULL;
652a9643ea8Slogwang switch (type)
653a9643ea8Slogwang {
654a9643ea8Slogwang case LINK_IDLE_LIST:
655a9643ea8Slogwang list = &this->_idle_list;
656a9643ea8Slogwang break;
657a9643ea8Slogwang
658a9643ea8Slogwang case LINK_CONN_LIST:
659a9643ea8Slogwang list = &this->_wait_connect;
660a9643ea8Slogwang break;
661a9643ea8Slogwang
662a9643ea8Slogwang case LINK_SEND_LIST:
663a9643ea8Slogwang list = &this->_wait_send;
664a9643ea8Slogwang break;
665a9643ea8Slogwang
666a9643ea8Slogwang case LINK_RECV_LIST:
667a9643ea8Slogwang list = &this->_wait_recv;
668a9643ea8Slogwang break;
669a9643ea8Slogwang
670a9643ea8Slogwang default:
671a9643ea8Slogwang break;
672a9643ea8Slogwang }
673a9643ea8Slogwang
674a9643ea8Slogwang return list;
675a9643ea8Slogwang }
676a9643ea8Slogwang
AppendToList(int32_t type,CNetHandler * item)677a9643ea8Slogwang void CSockLink::AppendToList(int32_t type, CNetHandler* item)
678a9643ea8Slogwang {
679a9643ea8Slogwang TNetItemList* list = this->GetItemList(type);
680a9643ea8Slogwang if (NULL == list)
681a9643ea8Slogwang {
682a9643ea8Slogwang MTLOG_ERROR("unknown list type: %d", type);
683a9643ea8Slogwang return;
684a9643ea8Slogwang }
685a9643ea8Slogwang
686a9643ea8Slogwang TAILQ_INSERT_TAIL(list, item, _link_entry);
687a9643ea8Slogwang }
688a9643ea8Slogwang
RemoveFromList(int32_t type,CNetHandler * item)689a9643ea8Slogwang void CSockLink::RemoveFromList(int32_t type, CNetHandler* item)
690a9643ea8Slogwang {
691a9643ea8Slogwang TNetItemList* list = this->GetItemList(type);
692a9643ea8Slogwang if (NULL == list)
693a9643ea8Slogwang {
694a9643ea8Slogwang MTLOG_ERROR("unknown list type: %d", type);
695a9643ea8Slogwang return;
696a9643ea8Slogwang }
697a9643ea8Slogwang
698a9643ea8Slogwang TAILQ_REMOVE(list, item, _link_entry);
699a9643ea8Slogwang }
700a9643ea8Slogwang
NotifyThread(CNetHandler * item,int32_t result)701a9643ea8Slogwang void CSockLink::NotifyThread(CNetHandler* item, int32_t result)
702a9643ea8Slogwang {
703a9643ea8Slogwang static MtFrame* frame = NULL;
704a9643ea8Slogwang if (frame == NULL) {
705a9643ea8Slogwang frame = MtFrame::Instance();
706a9643ea8Slogwang }
707a9643ea8Slogwang
708a9643ea8Slogwang if (result != RC_SUCCESS)
709a9643ea8Slogwang {
710a9643ea8Slogwang item->SetErrNo(result);
711a9643ea8Slogwang }
712a9643ea8Slogwang
713a9643ea8Slogwang MicroThread* thread = item->GetThread();
714a9643ea8Slogwang if ((thread != NULL) && (thread->HasFlag(MicroThread::IO_LIST)))
715a9643ea8Slogwang {
716a9643ea8Slogwang frame->RemoveIoWait(thread);
717a9643ea8Slogwang frame->InsertRunable(thread);
718a9643ea8Slogwang }
719a9643ea8Slogwang }
720a9643ea8Slogwang
NotifyAll(int32_t result)721a9643ea8Slogwang void CSockLink::NotifyAll(int32_t result)
722a9643ea8Slogwang {
723a9643ea8Slogwang CNetHandler* item = NULL;
724a9643ea8Slogwang CNetHandler* tmp = NULL;
725a9643ea8Slogwang
726a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_connect, _link_entry, tmp)
727a9643ea8Slogwang {
728a9643ea8Slogwang NotifyThread(item, result);
729a9643ea8Slogwang item->Unlink();
730a9643ea8Slogwang }
731a9643ea8Slogwang
732a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
733a9643ea8Slogwang {
734a9643ea8Slogwang NotifyThread(item, result);
735a9643ea8Slogwang item->Unlink();
736a9643ea8Slogwang }
737a9643ea8Slogwang
738a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_recv, _link_entry, tmp)
739a9643ea8Slogwang {
740a9643ea8Slogwang NotifyThread(item, result);
741a9643ea8Slogwang item->Unlink();
742a9643ea8Slogwang }
743a9643ea8Slogwang
744a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_idle_list, _link_entry, tmp)
745a9643ea8Slogwang {
746a9643ea8Slogwang NotifyThread(item, result);
747a9643ea8Slogwang item->Unlink();
748a9643ea8Slogwang }
749a9643ea8Slogwang }
750a9643ea8Slogwang
Reset()751a9643ea8Slogwang void CSockLink::Reset()
752a9643ea8Slogwang {
753a9643ea8Slogwang this->Close();
754a9643ea8Slogwang this->NotifyAll(_errno);
755a9643ea8Slogwang
756a9643ea8Slogwang rw_cache_destroy(&_recv_cache);
757a9643ea8Slogwang if (_rsp_buff != NULL)
758a9643ea8Slogwang {
759a9643ea8Slogwang delete_sk_buffer(_rsp_buff);
760a9643ea8Slogwang _rsp_buff = NULL;
761a9643ea8Slogwang }
762a9643ea8Slogwang
763a9643ea8Slogwang TAILQ_INIT(&_wait_connect);
764a9643ea8Slogwang TAILQ_INIT(&_wait_send);
765a9643ea8Slogwang TAILQ_INIT(&_wait_recv);
766a9643ea8Slogwang TAILQ_INIT(&_idle_list);
767a9643ea8Slogwang
768a9643ea8Slogwang _proto_type = NET_PROTO_TCP;
769a9643ea8Slogwang _errno = 0;
770a9643ea8Slogwang _state = 0;
771a9643ea8Slogwang _last_access = mt_time_ms();
772a9643ea8Slogwang _parents = NULL;
773a9643ea8Slogwang
774a9643ea8Slogwang this->KqueuerObj::Reset();
775a9643ea8Slogwang }
776a9643ea8Slogwang
CSockLink()777a9643ea8Slogwang CSockLink::CSockLink()
778a9643ea8Slogwang {
779a9643ea8Slogwang rw_cache_init(&_recv_cache, NULL);
780a9643ea8Slogwang _rsp_buff = NULL;
781a9643ea8Slogwang
782a9643ea8Slogwang TAILQ_INIT(&_wait_connect);
783a9643ea8Slogwang TAILQ_INIT(&_wait_send);
784a9643ea8Slogwang TAILQ_INIT(&_wait_recv);
785a9643ea8Slogwang TAILQ_INIT(&_idle_list);
786a9643ea8Slogwang
787a9643ea8Slogwang _proto_type = NET_PROTO_TCP;
788a9643ea8Slogwang _errno = 0;
789a9643ea8Slogwang _state = 0;
790a9643ea8Slogwang _last_access = mt_time_ms();
791a9643ea8Slogwang _parents = NULL;
792a9643ea8Slogwang }
793a9643ea8Slogwang
~CSockLink()794a9643ea8Slogwang CSockLink::~CSockLink()
795a9643ea8Slogwang {
796a9643ea8Slogwang this->Reset();
797a9643ea8Slogwang }
798a9643ea8Slogwang
SetProtoType(MT_PROTO_TYPE type)799a9643ea8Slogwang void CSockLink::SetProtoType(MT_PROTO_TYPE type)
800a9643ea8Slogwang {
801a9643ea8Slogwang _proto_type = type;
802a9643ea8Slogwang _recv_cache.pool = CNetMgr::Instance()->GetSkBuffMng(type);
803a9643ea8Slogwang }
804a9643ea8Slogwang
Close()805a9643ea8Slogwang void CSockLink::Close()
806a9643ea8Slogwang {
807a9643ea8Slogwang if (_fd < 0)
808a9643ea8Slogwang {
809a9643ea8Slogwang return;
810a9643ea8Slogwang }
811a9643ea8Slogwang
812a9643ea8Slogwang MtFrame::Instance()->KqueueDelObj(this);
813a9643ea8Slogwang
814a9643ea8Slogwang close(_fd);
815a9643ea8Slogwang _fd = -1;
816a9643ea8Slogwang }
817a9643ea8Slogwang
Destroy()818a9643ea8Slogwang void CSockLink::Destroy()
819a9643ea8Slogwang {
820a9643ea8Slogwang CDestLinks* dstlink = (CDestLinks*)_parents;
821a9643ea8Slogwang if (NULL == dstlink)
822a9643ea8Slogwang {
823a9643ea8Slogwang MTLOG_ERROR("socket link without parents ptr, maybe wrong");
824a9643ea8Slogwang delete this;
825a9643ea8Slogwang }
826a9643ea8Slogwang else
827a9643ea8Slogwang {
828a9643ea8Slogwang MTLOG_DEBUG("socket link just free");
829a9643ea8Slogwang dstlink->FreeSockLink(this);
830a9643ea8Slogwang }
831a9643ea8Slogwang }
832a9643ea8Slogwang
CreateSock()833a9643ea8Slogwang int32_t CSockLink::CreateSock()
834a9643ea8Slogwang {
835*35a81399Slogwang if (_fd > 0)
836a9643ea8Slogwang {
837a9643ea8Slogwang return _fd;
838a9643ea8Slogwang }
839a9643ea8Slogwang
840a9643ea8Slogwang if (NET_PROTO_TCP == _proto_type)
841a9643ea8Slogwang {
842a9643ea8Slogwang _fd = socket(AF_INET, SOCK_STREAM, 0);
843a9643ea8Slogwang }
844a9643ea8Slogwang else
845a9643ea8Slogwang {
846a9643ea8Slogwang _fd = socket(AF_INET, SOCK_DGRAM, 0);
847a9643ea8Slogwang }
848a9643ea8Slogwang
849a9643ea8Slogwang if (_fd < 0)
850a9643ea8Slogwang {
851a9643ea8Slogwang MTLOG_ERROR("create socket failed, ret %d[%m]", _fd);
852a9643ea8Slogwang return -1;
853a9643ea8Slogwang }
854a9643ea8Slogwang
855a9643ea8Slogwang int flags = 1;
856a9643ea8Slogwang if (ioctl(_fd, FIONBIO, &flags) < 0)
857a9643ea8Slogwang {
858a9643ea8Slogwang MTLOG_ERROR("socket unblock failed, %m");
859a9643ea8Slogwang close(_fd);
860a9643ea8Slogwang _fd = -1;
861a9643ea8Slogwang return -2;
862a9643ea8Slogwang }
863a9643ea8Slogwang
864a9643ea8Slogwang if (NET_PROTO_TCP == _proto_type)
865a9643ea8Slogwang {
866a9643ea8Slogwang setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));
867*35a81399Slogwang this->EnableOutput();
868a9643ea8Slogwang }
869a9643ea8Slogwang
870a9643ea8Slogwang this->EnableInput();
871a9643ea8Slogwang if (!MtFrame::Instance()->KqueueAddObj(this))
872a9643ea8Slogwang {
873a9643ea8Slogwang MTLOG_ERROR("socket epoll mng failed, %m");
874a9643ea8Slogwang close(_fd);
875a9643ea8Slogwang _fd = -1;
876a9643ea8Slogwang return -3;
877a9643ea8Slogwang }
878a9643ea8Slogwang
879a9643ea8Slogwang return _fd;
880a9643ea8Slogwang }
881a9643ea8Slogwang
GetDestAddr(struct sockaddr_in * addr)882a9643ea8Slogwang struct sockaddr_in* CSockLink::GetDestAddr(struct sockaddr_in* addr)
883a9643ea8Slogwang {
884a9643ea8Slogwang CDestLinks* dstlink = (CDestLinks*)_parents;
885a9643ea8Slogwang if ((NULL == _parents) || (NULL == addr)) {
886a9643ea8Slogwang return NULL;
887a9643ea8Slogwang }
888a9643ea8Slogwang
889a9643ea8Slogwang uint32_t ip = 0;
890a9643ea8Slogwang uint16_t port = 0;
891a9643ea8Slogwang dstlink->GetDestIP(ip, port);
892a9643ea8Slogwang
893a9643ea8Slogwang addr->sin_family = AF_INET;
894a9643ea8Slogwang addr->sin_addr.s_addr = ip;
895a9643ea8Slogwang addr->sin_port = port;
896a9643ea8Slogwang
897a9643ea8Slogwang return addr;
898a9643ea8Slogwang }
899a9643ea8Slogwang
Connect()900a9643ea8Slogwang bool CSockLink::Connect()
901a9643ea8Slogwang {
902a9643ea8Slogwang this->_last_access = mt_time_ms();
903a9643ea8Slogwang
904a9643ea8Slogwang if (_proto_type == NET_PROTO_UDP)
905a9643ea8Slogwang {
906a9643ea8Slogwang _state |= LINK_CONNECTED;
907a9643ea8Slogwang }
908a9643ea8Slogwang
909a9643ea8Slogwang if (_state & LINK_CONNECTED)
910a9643ea8Slogwang {
911a9643ea8Slogwang return true;
912a9643ea8Slogwang }
913a9643ea8Slogwang
914a9643ea8Slogwang if (_state & LINK_CONNECTING)
915a9643ea8Slogwang {
916a9643ea8Slogwang return false;
917a9643ea8Slogwang }
918a9643ea8Slogwang
919a9643ea8Slogwang struct sockaddr_in addr = {0};
920a9643ea8Slogwang
921a9643ea8Slogwang mt_hook_syscall(connect);
922a9643ea8Slogwang int32_t ret = ff_hook_connect(_fd, (struct sockaddr*)this->GetDestAddr(&addr), sizeof(struct sockaddr_in));
923a9643ea8Slogwang if (ret < 0)
924a9643ea8Slogwang {
925a9643ea8Slogwang int32_t err = errno;
926a9643ea8Slogwang if (err == EISCONN)
927a9643ea8Slogwang {
928a9643ea8Slogwang _state |= LINK_CONNECTED;
929a9643ea8Slogwang return true;
930a9643ea8Slogwang }
931a9643ea8Slogwang else
932a9643ea8Slogwang {
933a9643ea8Slogwang _state |= LINK_CONNECTING;
934a9643ea8Slogwang if ((err == EINPROGRESS) || (err == EALREADY) || (err == EINTR))
935a9643ea8Slogwang {
936a9643ea8Slogwang MTLOG_DEBUG("Open connect not ok, maybe first try, sock %d, errno %d", _fd, err);
937a9643ea8Slogwang return false;
938a9643ea8Slogwang }
939a9643ea8Slogwang else
940a9643ea8Slogwang {
941a9643ea8Slogwang MTLOG_ERROR("Open connect not ok, sock %d, errno %d", _fd, err);
942a9643ea8Slogwang return false;
943a9643ea8Slogwang }
944a9643ea8Slogwang }
945a9643ea8Slogwang }
946a9643ea8Slogwang else
947a9643ea8Slogwang {
948a9643ea8Slogwang _state |= LINK_CONNECTED;
949a9643ea8Slogwang return true;
950a9643ea8Slogwang }
951a9643ea8Slogwang }
952a9643ea8Slogwang
SendCacheUdp(void * data,uint32_t len)953a9643ea8Slogwang int32_t CSockLink::SendCacheUdp(void* data, uint32_t len)
954a9643ea8Slogwang {
955a9643ea8Slogwang mt_hook_syscall(sendto);
956a9643ea8Slogwang void* buff = NULL;
957a9643ea8Slogwang uint32_t buff_len = 0;
958a9643ea8Slogwang
959a9643ea8Slogwang CNetHandler* item = NULL;
960a9643ea8Slogwang CNetHandler* tmp = NULL;
961a9643ea8Slogwang struct sockaddr_in dst = {0};
962a9643ea8Slogwang
963a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
964a9643ea8Slogwang {
965a9643ea8Slogwang item->GetSendData(buff, buff_len);
966a9643ea8Slogwang if ((NULL == buff) || (buff_len == 0))
967a9643ea8Slogwang {
968a9643ea8Slogwang MTLOG_ERROR("get buff ptr invalid, log it");
969a9643ea8Slogwang NotifyThread(item, 0);
970a9643ea8Slogwang item->SwitchToIdle();
971a9643ea8Slogwang continue;
972a9643ea8Slogwang }
973a9643ea8Slogwang
974a9643ea8Slogwang int32_t ret = ff_hook_sendto(_fd, buff, buff_len, 0,
975a9643ea8Slogwang (struct sockaddr*)this->GetDestAddr(&dst), sizeof(struct sockaddr_in));
976a9643ea8Slogwang if (ret == -1)
977a9643ea8Slogwang {
978a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
979a9643ea8Slogwang {
980a9643ea8Slogwang return 0;
981a9643ea8Slogwang }
982a9643ea8Slogwang else
983a9643ea8Slogwang {
984a9643ea8Slogwang MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _fd,
985a9643ea8Slogwang errno, strerror(errno));
986a9643ea8Slogwang return -2;
987a9643ea8Slogwang }
988a9643ea8Slogwang }
989a9643ea8Slogwang
990a9643ea8Slogwang NotifyThread(item, 0);
991a9643ea8Slogwang item->SwitchToIdle();
992a9643ea8Slogwang }
993a9643ea8Slogwang
994a9643ea8Slogwang if ((data == NULL) || (len == 0))
995a9643ea8Slogwang {
996a9643ea8Slogwang return 0;
997a9643ea8Slogwang }
998a9643ea8Slogwang
999a9643ea8Slogwang int32_t ret = ff_hook_sendto(_fd, data, len, 0,
1000a9643ea8Slogwang (struct sockaddr*)this->GetDestAddr(&dst), sizeof(struct sockaddr_in));
1001a9643ea8Slogwang if (ret == -1)
1002a9643ea8Slogwang {
1003a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
1004a9643ea8Slogwang {
1005a9643ea8Slogwang return 0;
1006a9643ea8Slogwang }
1007a9643ea8Slogwang else
1008a9643ea8Slogwang {
1009a9643ea8Slogwang MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _fd,
1010a9643ea8Slogwang errno, strerror(errno));
1011a9643ea8Slogwang return -2;
1012a9643ea8Slogwang }
1013a9643ea8Slogwang }
1014a9643ea8Slogwang else
1015a9643ea8Slogwang {
1016a9643ea8Slogwang return ret;
1017a9643ea8Slogwang }
1018a9643ea8Slogwang }
1019a9643ea8Slogwang
SendCacheTcp(void * data,uint32_t len)1020a9643ea8Slogwang int32_t CSockLink::SendCacheTcp(void* data, uint32_t len)
1021a9643ea8Slogwang {
1022a9643ea8Slogwang void* buff = NULL;
1023a9643ea8Slogwang uint32_t buff_len = 0;
1024a9643ea8Slogwang struct iovec iov[64];
1025a9643ea8Slogwang int32_t count = 0;
1026a9643ea8Slogwang CNetHandler* item = NULL;
1027a9643ea8Slogwang CNetHandler* tmp = NULL;
1028a9643ea8Slogwang
1029a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
1030a9643ea8Slogwang {
1031a9643ea8Slogwang item->GetSendData(buff, buff_len);
1032a9643ea8Slogwang iov[count].iov_base = buff;
1033a9643ea8Slogwang iov[count].iov_len = (int32_t)buff_len;
1034a9643ea8Slogwang count++;
1035a9643ea8Slogwang if (count >= 64)
1036a9643ea8Slogwang {
1037a9643ea8Slogwang break;
1038a9643ea8Slogwang }
1039a9643ea8Slogwang }
1040a9643ea8Slogwang if ((count < 64) && (data != NULL))
1041a9643ea8Slogwang {
1042a9643ea8Slogwang iov[count].iov_base = data;
1043a9643ea8Slogwang iov[count].iov_len = (int32_t)len;
1044a9643ea8Slogwang count++;
1045a9643ea8Slogwang }
1046a9643ea8Slogwang
1047a9643ea8Slogwang ssize_t bytes = writev(_fd, iov, count);
1048a9643ea8Slogwang if (bytes < 0)
1049a9643ea8Slogwang {
1050a9643ea8Slogwang if ((errno == EAGAIN) || (errno == EINTR))
1051a9643ea8Slogwang {
1052a9643ea8Slogwang return 0;
1053a9643ea8Slogwang }
1054a9643ea8Slogwang else
1055a9643ea8Slogwang {
1056a9643ea8Slogwang MTLOG_ERROR("socket writev failed, fd %d, errno %d(%s)", _fd,
1057a9643ea8Slogwang errno, strerror(errno));
1058a9643ea8Slogwang return -1;
1059a9643ea8Slogwang }
1060a9643ea8Slogwang }
1061a9643ea8Slogwang
1062a9643ea8Slogwang uint32_t send_left = (uint32_t)bytes;
1063a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_send, _link_entry, tmp)
1064a9643ea8Slogwang {
1065a9643ea8Slogwang send_left -= item->SkipSendPos(send_left);
1066a9643ea8Slogwang item->GetSendData(buff, buff_len);
1067a9643ea8Slogwang if (buff_len == 0)
1068a9643ea8Slogwang {
1069a9643ea8Slogwang NotifyThread(item, 0);
1070a9643ea8Slogwang item->SwitchToIdle();
1071a9643ea8Slogwang }
1072a9643ea8Slogwang
1073a9643ea8Slogwang if (send_left == 0)
1074a9643ea8Slogwang {
1075a9643ea8Slogwang break;
1076a9643ea8Slogwang }
1077a9643ea8Slogwang }
1078a9643ea8Slogwang
1079a9643ea8Slogwang return send_left;
1080a9643ea8Slogwang }
1081a9643ea8Slogwang
SendData(void * data,uint32_t len)1082a9643ea8Slogwang int32_t CSockLink::SendData(void* data, uint32_t len)
1083a9643ea8Slogwang {
1084a9643ea8Slogwang int32_t ret = 0;
1085a9643ea8Slogwang bool rc = false;
1086a9643ea8Slogwang
1087a9643ea8Slogwang this->_last_access = mt_time_ms();
1088a9643ea8Slogwang
1089a9643ea8Slogwang if (_proto_type == NET_PROTO_UDP)
1090a9643ea8Slogwang {
1091a9643ea8Slogwang ret = SendCacheUdp(data, len);
1092a9643ea8Slogwang }
1093a9643ea8Slogwang else
1094a9643ea8Slogwang {
1095a9643ea8Slogwang ret = SendCacheTcp(data, len);
1096a9643ea8Slogwang }
1097a9643ea8Slogwang
1098a9643ea8Slogwang if (ret < (int32_t)len)
1099a9643ea8Slogwang {
1100a9643ea8Slogwang this->EnableOutput();
1101a9643ea8Slogwang rc = MtFrame::Instance()->KqueueCtrlAdd(_fd, KQ_EVENT_READ);
1102a9643ea8Slogwang }
1103a9643ea8Slogwang else
1104a9643ea8Slogwang {
1105a9643ea8Slogwang this->DisableOutput();
1106a9643ea8Slogwang rc = MtFrame::Instance()->KqueueCtrlDel(_fd, KQ_EVENT_WRITE);
1107a9643ea8Slogwang }
1108a9643ea8Slogwang
1109a9643ea8Slogwang if (!rc)
1110a9643ea8Slogwang {
1111a9643ea8Slogwang MTLOG_ERROR("socket epoll mng failed[%m], wait timeout");
1112a9643ea8Slogwang }
1113a9643ea8Slogwang
1114a9643ea8Slogwang return ret;
1115a9643ea8Slogwang }
1116a9643ea8Slogwang
RecvDispath()1117a9643ea8Slogwang int32_t CSockLink::RecvDispath()
1118a9643ea8Slogwang {
1119a9643ea8Slogwang if (_proto_type == NET_PROTO_UDP)
1120a9643ea8Slogwang {
1121a9643ea8Slogwang return this->DispathUdp();
1122a9643ea8Slogwang }
1123a9643ea8Slogwang else
1124a9643ea8Slogwang {
1125a9643ea8Slogwang return this->DispathTcp();
1126a9643ea8Slogwang }
1127a9643ea8Slogwang }
1128a9643ea8Slogwang
ExtendRecvRsp()1129a9643ea8Slogwang void CSockLink::ExtendRecvRsp()
1130a9643ea8Slogwang {
1131a9643ea8Slogwang if (NULL == _rsp_buff)
1132a9643ea8Slogwang {
1133a9643ea8Slogwang _rsp_buff = new_sk_buffer(512);
1134a9643ea8Slogwang if (NULL == _rsp_buff)
1135a9643ea8Slogwang {
1136a9643ea8Slogwang MTLOG_ERROR("no more memory, error");
1137a9643ea8Slogwang return;
1138a9643ea8Slogwang }
1139a9643ea8Slogwang }
1140a9643ea8Slogwang
1141a9643ea8Slogwang _rsp_buff->data_len += read_cache_begin(&_recv_cache, _rsp_buff->data_len,
1142a9643ea8Slogwang _rsp_buff->data + _rsp_buff->data_len , _rsp_buff->size - _rsp_buff->data_len);
1143a9643ea8Slogwang }
1144a9643ea8Slogwang
GetSessionCallback()1145a9643ea8Slogwang CHECK_SESSION_CALLBACK CSockLink::GetSessionCallback()
1146a9643ea8Slogwang {
1147a9643ea8Slogwang CHECK_SESSION_CALLBACK check_session = NULL;
1148a9643ea8Slogwang
1149a9643ea8Slogwang CNetHandler* item = TAILQ_FIRST(&_wait_recv);
1150a9643ea8Slogwang if (NULL == item)
1151a9643ea8Slogwang {
1152a9643ea8Slogwang MTLOG_DEBUG("recv data with no wait item, err");
1153a9643ea8Slogwang goto EXIT_LABEL;
1154a9643ea8Slogwang }
1155a9643ea8Slogwang
1156a9643ea8Slogwang check_session = item->GetSessionCallback();
1157a9643ea8Slogwang if (NULL == check_session)
1158a9643ea8Slogwang {
1159a9643ea8Slogwang MTLOG_ERROR("recv data with no session callback, err");
1160a9643ea8Slogwang goto EXIT_LABEL;
1161a9643ea8Slogwang }
1162a9643ea8Slogwang
1163a9643ea8Slogwang EXIT_LABEL:
1164a9643ea8Slogwang
1165a9643ea8Slogwang CDestLinks* dstlink = (CDestLinks*)_parents;
1166a9643ea8Slogwang if (NULL == dstlink)
1167a9643ea8Slogwang {
1168a9643ea8Slogwang return check_session;
1169a9643ea8Slogwang }
1170a9643ea8Slogwang
1171a9643ea8Slogwang if (check_session != NULL)
1172a9643ea8Slogwang {
1173a9643ea8Slogwang dstlink->SetDefaultCallback(check_session);
1174a9643ea8Slogwang }
1175a9643ea8Slogwang else
1176a9643ea8Slogwang {
1177a9643ea8Slogwang check_session = dstlink->GetDefaultCallback();
1178a9643ea8Slogwang }
1179a9643ea8Slogwang
1180a9643ea8Slogwang return check_session;
1181a9643ea8Slogwang }
1182a9643ea8Slogwang
DispathTcp()1183a9643ea8Slogwang int32_t CSockLink::DispathTcp()
1184a9643ea8Slogwang {
1185a9643ea8Slogwang CHECK_SESSION_CALLBACK check_session = this->GetSessionCallback();
1186a9643ea8Slogwang if (NULL == check_session)
1187a9643ea8Slogwang {
1188a9643ea8Slogwang MTLOG_ERROR("recv data with no session callback, err");
1189a9643ea8Slogwang return -1;
1190a9643ea8Slogwang }
1191a9643ea8Slogwang
1192a9643ea8Slogwang uint32_t need_len = 0;
1193a9643ea8Slogwang uint64_t sid = 0;
1194a9643ea8Slogwang int32_t ret = 0;
1195a9643ea8Slogwang while (_recv_cache.len > 0)
1196a9643ea8Slogwang {
1197a9643ea8Slogwang this->ExtendRecvRsp();
1198a9643ea8Slogwang if (NULL == _rsp_buff)
1199a9643ea8Slogwang {
1200a9643ea8Slogwang MTLOG_ERROR("alloc memory, error");
1201a9643ea8Slogwang _errno = RC_MEM_ERROR;
1202a9643ea8Slogwang return -3;
1203a9643ea8Slogwang }
1204a9643ea8Slogwang
1205a9643ea8Slogwang need_len = 0;
1206a9643ea8Slogwang ret = check_session(_rsp_buff->data, _rsp_buff->data_len, &sid, &need_len);
1207a9643ea8Slogwang
1208a9643ea8Slogwang if (ret < 0)
1209a9643ea8Slogwang {
1210a9643ea8Slogwang MTLOG_ERROR("user check resp failed, ret %d", ret);
1211a9643ea8Slogwang _errno = RC_CHECK_PKG_FAIL;
1212a9643ea8Slogwang return -1;
1213a9643ea8Slogwang }
1214a9643ea8Slogwang
1215a9643ea8Slogwang if (ret == 0)
1216a9643ea8Slogwang {
1217a9643ea8Slogwang if ((need_len == 0) && (_rsp_buff->data_len == _rsp_buff->size))
1218a9643ea8Slogwang {
1219a9643ea8Slogwang MTLOG_DEBUG("recv default buff full[%u], but user no set need length", _rsp_buff->size);
1220a9643ea8Slogwang need_len = _rsp_buff->size * 2;
1221a9643ea8Slogwang }
1222a9643ea8Slogwang
1223a9643ea8Slogwang if ((need_len <= _rsp_buff->size) || (need_len > 100*1024*1024))
1224a9643ea8Slogwang {
1225a9643ea8Slogwang MTLOG_DEBUG("maybe need wait more data: %u", need_len);
1226a9643ea8Slogwang return 0;
1227a9643ea8Slogwang }
1228a9643ea8Slogwang
1229a9643ea8Slogwang _rsp_buff = reserve_sk_buffer(_rsp_buff, need_len);
1230a9643ea8Slogwang if (NULL == _rsp_buff)
1231a9643ea8Slogwang {
1232a9643ea8Slogwang MTLOG_ERROR("no more memory, error");
1233a9643ea8Slogwang _errno = RC_MEM_ERROR;
1234a9643ea8Slogwang return -3;
1235a9643ea8Slogwang }
1236a9643ea8Slogwang
1237a9643ea8Slogwang if (_rsp_buff->data_len >= _recv_cache.len)
1238a9643ea8Slogwang {
1239a9643ea8Slogwang MTLOG_DEBUG("maybe need wait more data, now %u", _recv_cache.len);
1240a9643ea8Slogwang return 0;
1241a9643ea8Slogwang }
1242a9643ea8Slogwang
1243a9643ea8Slogwang continue;
1244a9643ea8Slogwang }
1245a9643ea8Slogwang
1246a9643ea8Slogwang if (ret > (int32_t)_recv_cache.len)
1247a9643ea8Slogwang {
1248a9643ea8Slogwang MTLOG_DEBUG("maybe pkg not all ok, wait more");
1249a9643ea8Slogwang return 0;
1250a9643ea8Slogwang }
1251a9643ea8Slogwang
1252a9643ea8Slogwang CNetHandler* session = this->FindSession(sid);
1253a9643ea8Slogwang if (NULL == session)
1254a9643ea8Slogwang {
1255a9643ea8Slogwang MTLOG_DEBUG("session id %llu, find failed, maybe timeout", sid);
1256a9643ea8Slogwang cache_skip_data(&_recv_cache, ret);
1257a9643ea8Slogwang delete_sk_buffer(_rsp_buff);
1258a9643ea8Slogwang _rsp_buff = NULL;
1259a9643ea8Slogwang }
1260a9643ea8Slogwang else
1261a9643ea8Slogwang {
1262a9643ea8Slogwang MTLOG_DEBUG("session id %llu, find ok, wakeup it", sid);
1263a9643ea8Slogwang cache_skip_data(&_recv_cache, ret);
1264a9643ea8Slogwang this->NotifyThread(session, 0);
1265a9643ea8Slogwang session->SwitchToIdle();
1266*35a81399Slogwang _rsp_buff->data_len = ret;
1267a9643ea8Slogwang session->SetRespBuff(_rsp_buff);
1268a9643ea8Slogwang _rsp_buff = NULL;
1269a9643ea8Slogwang }
1270a9643ea8Slogwang }
1271a9643ea8Slogwang
1272a9643ea8Slogwang return 0;
1273a9643ea8Slogwang
1274a9643ea8Slogwang }
1275a9643ea8Slogwang
DispathUdp()1276a9643ea8Slogwang int32_t CSockLink::DispathUdp()
1277a9643ea8Slogwang {
1278a9643ea8Slogwang CHECK_SESSION_CALLBACK check_session = NULL;
1279a9643ea8Slogwang CNetHandler* item = TAILQ_FIRST(&_wait_recv);
1280a9643ea8Slogwang if (NULL == item)
1281a9643ea8Slogwang {
1282a9643ea8Slogwang MTLOG_DEBUG("recv data with no wait item, maybe wrong pkg recv");
1283a9643ea8Slogwang }
1284a9643ea8Slogwang else
1285a9643ea8Slogwang {
1286a9643ea8Slogwang check_session = item->GetSessionCallback();
1287a9643ea8Slogwang if (NULL == check_session)
1288a9643ea8Slogwang {
1289a9643ea8Slogwang MTLOG_TRACE("recv data with no session callback, err");
1290a9643ea8Slogwang }
1291a9643ea8Slogwang }
1292a9643ea8Slogwang
1293a9643ea8Slogwang uint64_t sid = 0;
1294a9643ea8Slogwang uint32_t need_len = 0;
1295a9643ea8Slogwang int32_t ret = 0;
1296a9643ea8Slogwang TSkBuffer* block = NULL;
1297a9643ea8Slogwang while ((block = TAILQ_FIRST(&_recv_cache.list)) != NULL)
1298a9643ea8Slogwang {
1299a9643ea8Slogwang if (check_session == NULL)
1300a9643ea8Slogwang {
1301a9643ea8Slogwang MTLOG_DEBUG("no recv wait, skip first block");
1302a9643ea8Slogwang cache_skip_data(&_recv_cache, block->data_len);
1303a9643ea8Slogwang continue;
1304a9643ea8Slogwang }
1305a9643ea8Slogwang
1306a9643ea8Slogwang need_len = 0;
1307a9643ea8Slogwang ret = check_session(block->data, block->data_len, &sid, &need_len);
1308a9643ea8Slogwang if ((ret <= 0) || (ret > (int32_t)block->data_len))
1309a9643ea8Slogwang {
1310a9643ea8Slogwang MTLOG_DEBUG("maybe wrong pkg come, skip it");
1311a9643ea8Slogwang cache_skip_data(&_recv_cache, block->data_len);
1312a9643ea8Slogwang continue;
1313a9643ea8Slogwang }
1314a9643ea8Slogwang
1315a9643ea8Slogwang CNetHandler* session = this->FindSession(sid);
1316a9643ea8Slogwang if (NULL == session)
1317a9643ea8Slogwang {
1318a9643ea8Slogwang MTLOG_DEBUG("session id %llu, find failed, maybe timeout", sid);
1319a9643ea8Slogwang cache_skip_data(&_recv_cache, block->data_len);
1320a9643ea8Slogwang }
1321a9643ea8Slogwang else
1322a9643ea8Slogwang {
1323a9643ea8Slogwang MTLOG_DEBUG("session id %llu, find ok, wakeup it", sid);
1324a9643ea8Slogwang this->NotifyThread(session, 0);
1325a9643ea8Slogwang session->SwitchToIdle();
1326a9643ea8Slogwang cache_skip_first_buffer(&_recv_cache);
1327a9643ea8Slogwang session->SetRespBuff(block);
1328a9643ea8Slogwang }
1329a9643ea8Slogwang }
1330a9643ea8Slogwang
1331a9643ea8Slogwang return 0;
1332a9643ea8Slogwang }
1333a9643ea8Slogwang
FindSession(uint64_t sid)1334a9643ea8Slogwang CNetHandler* CSockLink::FindSession(uint64_t sid)
1335a9643ea8Slogwang {
1336a9643ea8Slogwang CNetHandler key;
1337a9643ea8Slogwang CDestLinks* dstlink = (CDestLinks*)_parents;
1338a9643ea8Slogwang if (NULL == dstlink)
1339a9643ea8Slogwang {
1340a9643ea8Slogwang MTLOG_ERROR("session dest link invalid, maybe error");
1341a9643ea8Slogwang return NULL;
1342a9643ea8Slogwang }
1343a9643ea8Slogwang struct sockaddr_in addr;
1344a9643ea8Slogwang key.SetDestAddress(this->GetDestAddr(&addr));
1345a9643ea8Slogwang key.SetConnType(dstlink->GetConnType());
1346a9643ea8Slogwang key.SetProtoType(dstlink->GetProtoType());
1347a9643ea8Slogwang key.SetSessionId(sid);
1348a9643ea8Slogwang
1349a9643ea8Slogwang return CNetMgr::Instance()->FindNetItem(&key);
1350a9643ea8Slogwang }
1351a9643ea8Slogwang
InputNotify()1352a9643ea8Slogwang int CSockLink::InputNotify()
1353a9643ea8Slogwang {
1354a9643ea8Slogwang int32_t ret = 0;
1355a9643ea8Slogwang
1356a9643ea8Slogwang this->_last_access = mt_time_ms();
1357a9643ea8Slogwang
1358a9643ea8Slogwang if (_proto_type == NET_PROTO_UDP)
1359a9643ea8Slogwang {
1360a9643ea8Slogwang ret = cache_udp_recv(&_recv_cache, _fd, NULL);
1361a9643ea8Slogwang }
1362a9643ea8Slogwang else
1363a9643ea8Slogwang {
1364a9643ea8Slogwang ret = cache_tcp_recv(&_recv_cache, _fd);
1365a9643ea8Slogwang }
1366a9643ea8Slogwang
1367a9643ea8Slogwang if (ret < 0)
1368a9643ea8Slogwang {
1369a9643ea8Slogwang if (ret == -SK_ERR_NEED_CLOSE)
1370a9643ea8Slogwang {
1371a9643ea8Slogwang MTLOG_DEBUG("recv on link failed, remote close");
1372a9643ea8Slogwang _errno = RC_REMOTE_CLOSED;
1373a9643ea8Slogwang }
1374a9643ea8Slogwang else
1375a9643ea8Slogwang {
1376a9643ea8Slogwang MTLOG_ERROR("recv on link failed, close it, ret %d[%m]", ret);
1377a9643ea8Slogwang _errno = RC_RECV_FAIL;
1378a9643ea8Slogwang }
1379a9643ea8Slogwang
1380a9643ea8Slogwang this->Destroy();
1381a9643ea8Slogwang return -1;
1382a9643ea8Slogwang }
1383a9643ea8Slogwang
1384a9643ea8Slogwang ret = this->RecvDispath();
1385a9643ea8Slogwang if (ret < 0)
1386a9643ea8Slogwang {
1387a9643ea8Slogwang MTLOG_DEBUG("recv dispath failed, close it, ret %d[%m]", ret);
1388a9643ea8Slogwang this->Destroy();
1389a9643ea8Slogwang return -2;
1390a9643ea8Slogwang }
1391a9643ea8Slogwang
1392a9643ea8Slogwang return 0;
1393a9643ea8Slogwang
1394a9643ea8Slogwang }
1395a9643ea8Slogwang
OutputNotify()1396a9643ea8Slogwang int CSockLink::OutputNotify()
1397a9643ea8Slogwang {
1398a9643ea8Slogwang int32_t ret = 0;
1399a9643ea8Slogwang
1400a9643ea8Slogwang this->_last_access = mt_time_ms();
1401a9643ea8Slogwang
1402a9643ea8Slogwang if (_state & LINK_CONNECTING)
1403a9643ea8Slogwang {
1404a9643ea8Slogwang _state &= ~LINK_CONNECTING;
1405a9643ea8Slogwang _state |= LINK_CONNECTED;
1406a9643ea8Slogwang
1407a9643ea8Slogwang CNetHandler* item = NULL;
1408a9643ea8Slogwang CNetHandler* tmp = NULL;
1409a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_wait_connect, _link_entry, tmp)
1410a9643ea8Slogwang {
1411a9643ea8Slogwang NotifyThread(item, 0);
1412a9643ea8Slogwang item->SwitchToIdle();
1413a9643ea8Slogwang }
1414a9643ea8Slogwang }
1415a9643ea8Slogwang
1416a9643ea8Slogwang if (_proto_type == NET_PROTO_UDP)
1417a9643ea8Slogwang {
1418a9643ea8Slogwang ret = SendCacheUdp(NULL, 0);
1419a9643ea8Slogwang }
1420a9643ea8Slogwang else
1421a9643ea8Slogwang {
1422a9643ea8Slogwang ret = SendCacheTcp(NULL, 0);
1423a9643ea8Slogwang }
1424a9643ea8Slogwang
1425a9643ea8Slogwang if (ret < 0)
1426a9643ea8Slogwang {
1427a9643ea8Slogwang MTLOG_ERROR("Send on link failed, close it, ret %d[%m]", ret);
1428a9643ea8Slogwang _errno = RC_SEND_FAIL;
1429a9643ea8Slogwang this->Destroy();
1430a9643ea8Slogwang return ret;
1431a9643ea8Slogwang }
1432a9643ea8Slogwang
1433a9643ea8Slogwang if (TAILQ_EMPTY(&_wait_send))
1434a9643ea8Slogwang {
1435a9643ea8Slogwang this->DisableOutput();
1436a9643ea8Slogwang if (!MtFrame::Instance()->KqueueCtrlDel(_fd, KQ_EVENT_WRITE))
1437a9643ea8Slogwang {
1438a9643ea8Slogwang MTLOG_ERROR("socket epoll mng failed[%m], wait timeout");
1439a9643ea8Slogwang }
1440a9643ea8Slogwang }
1441a9643ea8Slogwang
1442a9643ea8Slogwang return 0;
1443a9643ea8Slogwang }
1444a9643ea8Slogwang
HangupNotify()1445a9643ea8Slogwang int CSockLink::HangupNotify()
1446a9643ea8Slogwang {
1447a9643ea8Slogwang MTLOG_ERROR("socket epoll error, fd %d", _fd);
1448a9643ea8Slogwang
1449a9643ea8Slogwang this->_errno = RC_KQUEUE_ERROR;
1450a9643ea8Slogwang this->Destroy();
1451a9643ea8Slogwang return -1;
1452a9643ea8Slogwang }
1453a9643ea8Slogwang
CDestLinks()1454a9643ea8Slogwang CDestLinks::CDestLinks()
1455a9643ea8Slogwang {
1456*35a81399Slogwang _timeout = 5*60*1000;
1457a9643ea8Slogwang _addr_ipv4 = 0;
1458a9643ea8Slogwang _net_port = 0;
1459a9643ea8Slogwang _proto_type = NET_PROTO_UNDEF;
1460a9643ea8Slogwang _conn_type = TYPE_CONN_SESSION;
1461a9643ea8Slogwang
1462*35a81399Slogwang _max_links = 3; // 默认3个
1463a9643ea8Slogwang _curr_link = 0;
1464a9643ea8Slogwang _dflt_callback = NULL;
1465a9643ea8Slogwang
1466a9643ea8Slogwang TAILQ_INIT(&_sock_list);
1467a9643ea8Slogwang }
1468a9643ea8Slogwang
Reset()1469a9643ea8Slogwang void CDestLinks::Reset()
1470a9643ea8Slogwang {
1471a9643ea8Slogwang CSockLink* item = NULL;
1472a9643ea8Slogwang CSockLink* temp = NULL;
1473a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_sock_list, _link_entry, temp)
1474a9643ea8Slogwang {
1475a9643ea8Slogwang item->Destroy();
1476a9643ea8Slogwang }
1477a9643ea8Slogwang TAILQ_INIT(&_sock_list);
1478a9643ea8Slogwang
1479a9643ea8Slogwang CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
1480a9643ea8Slogwang if (NULL != timer)
1481a9643ea8Slogwang {
1482a9643ea8Slogwang timer->stop_timer(this);
1483a9643ea8Slogwang }
1484a9643ea8Slogwang
1485*35a81399Slogwang _timeout = 5*60*1000;
1486a9643ea8Slogwang _addr_ipv4 = 0;
1487a9643ea8Slogwang _net_port = 0;
1488a9643ea8Slogwang _proto_type = NET_PROTO_UNDEF;
1489a9643ea8Slogwang _conn_type = TYPE_CONN_SESSION;
1490a9643ea8Slogwang
1491*35a81399Slogwang _max_links = 3;
1492a9643ea8Slogwang _curr_link = 0;
1493a9643ea8Slogwang }
1494a9643ea8Slogwang
~CDestLinks()1495a9643ea8Slogwang CDestLinks::~CDestLinks()
1496a9643ea8Slogwang {
1497a9643ea8Slogwang this->Reset();
1498a9643ea8Slogwang }
1499a9643ea8Slogwang
StartTimer()1500a9643ea8Slogwang void CDestLinks::StartTimer()
1501a9643ea8Slogwang {
1502a9643ea8Slogwang CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
1503a9643ea8Slogwang if ((NULL == timer) || !timer->start_timer(this, 60*1000))
1504a9643ea8Slogwang {
1505a9643ea8Slogwang MTLOG_ERROR("obj %p attach timer failed, error", this);
1506a9643ea8Slogwang }
1507a9643ea8Slogwang }
1508a9643ea8Slogwang
FreeSockLink(CSockLink * sock)1509a9643ea8Slogwang void CDestLinks::FreeSockLink(CSockLink* sock)
1510a9643ea8Slogwang {
1511a9643ea8Slogwang if ((sock == NULL) || (sock->GetParentsPtr() != (void*)this))
1512a9643ea8Slogwang {
1513a9643ea8Slogwang MTLOG_ERROR("invalid socklink %p, error", sock);
1514a9643ea8Slogwang return;
1515a9643ea8Slogwang }
1516a9643ea8Slogwang
1517a9643ea8Slogwang TAILQ_REMOVE(&_sock_list, sock, _link_entry);
1518a9643ea8Slogwang if (this->_curr_link > 0) {
1519a9643ea8Slogwang this->_curr_link--;
1520a9643ea8Slogwang }
1521a9643ea8Slogwang
1522a9643ea8Slogwang sock->Reset();
1523a9643ea8Slogwang CNetMgr::Instance()->FreeSockLink(sock);
1524a9643ea8Slogwang }
1525a9643ea8Slogwang
GetSockLink()1526a9643ea8Slogwang CSockLink* CDestLinks::GetSockLink()
1527a9643ea8Slogwang {
1528a9643ea8Slogwang CSockLink* link = NULL;
1529a9643ea8Slogwang if (_curr_link < _max_links)
1530a9643ea8Slogwang {
1531a9643ea8Slogwang link = CNetMgr::Instance()->AllocSockLink();
1532a9643ea8Slogwang if (NULL == link)
1533a9643ea8Slogwang {
1534a9643ea8Slogwang MTLOG_ERROR("alloc sock link failed, error");
1535a9643ea8Slogwang return NULL;
1536a9643ea8Slogwang }
1537a9643ea8Slogwang link->SetParentsPtr(this);
1538a9643ea8Slogwang link->SetProtoType(_proto_type);
1539a9643ea8Slogwang TAILQ_INSERT_TAIL(&_sock_list, link, _link_entry);
1540a9643ea8Slogwang _curr_link++;
1541a9643ea8Slogwang }
1542a9643ea8Slogwang else
1543a9643ea8Slogwang {
1544a9643ea8Slogwang link = TAILQ_FIRST(&_sock_list);
1545a9643ea8Slogwang TAILQ_REMOVE(&_sock_list, link, _link_entry);
1546a9643ea8Slogwang TAILQ_INSERT_TAIL(&_sock_list, link, _link_entry);
1547a9643ea8Slogwang }
1548a9643ea8Slogwang
1549a9643ea8Slogwang return link;
1550a9643ea8Slogwang }
1551a9643ea8Slogwang
timer_notify()1552a9643ea8Slogwang void CDestLinks::timer_notify()
1553a9643ea8Slogwang {
1554a9643ea8Slogwang uint64_t now = mt_time_ms();
1555a9643ea8Slogwang CSockLink* item = NULL;
1556a9643ea8Slogwang CSockLink* temp = NULL;
1557a9643ea8Slogwang TAILQ_FOREACH_SAFE(item, &_sock_list, _link_entry, temp)
1558a9643ea8Slogwang {
1559a9643ea8Slogwang if ((item->GetLastAccess() + this->_timeout) < now)
1560a9643ea8Slogwang {
1561a9643ea8Slogwang MTLOG_DEBUG("link timeout, last[%llu], now [%llu]", item->GetLastAccess(), now);
1562a9643ea8Slogwang item->Destroy();
1563a9643ea8Slogwang }
1564a9643ea8Slogwang }
1565a9643ea8Slogwang
1566a9643ea8Slogwang item = TAILQ_FIRST(&_sock_list);
1567a9643ea8Slogwang if (NULL == item)
1568a9643ea8Slogwang {
1569a9643ea8Slogwang MTLOG_DEBUG("dest links timeout, now [%llu]", now);
1570a9643ea8Slogwang CNetMgr::Instance()->DeleteDestLink(this);
1571a9643ea8Slogwang return;
1572a9643ea8Slogwang }
1573a9643ea8Slogwang
1574a9643ea8Slogwang this->StartTimer();
1575a9643ea8Slogwang
1576a9643ea8Slogwang return;
1577a9643ea8Slogwang }
1578a9643ea8Slogwang
1579a9643ea8Slogwang CNetMgr* CNetMgr::_instance = NULL;
Instance(void)1580a9643ea8Slogwang CNetMgr* CNetMgr::Instance (void)
1581a9643ea8Slogwang {
1582a9643ea8Slogwang if (NULL == _instance)
1583a9643ea8Slogwang {
1584a9643ea8Slogwang _instance = new CNetMgr();
1585a9643ea8Slogwang }
1586a9643ea8Slogwang
1587a9643ea8Slogwang return _instance;
1588a9643ea8Slogwang }
1589a9643ea8Slogwang
Destroy()1590a9643ea8Slogwang void CNetMgr::Destroy()
1591a9643ea8Slogwang {
1592a9643ea8Slogwang if( _instance != NULL )
1593a9643ea8Slogwang {
1594a9643ea8Slogwang delete _instance;
1595a9643ea8Slogwang _instance = NULL;
1596a9643ea8Slogwang }
1597a9643ea8Slogwang }
1598a9643ea8Slogwang
FindNetItem(CNetHandler * key)1599a9643ea8Slogwang CNetHandler* CNetMgr::FindNetItem(CNetHandler* key)
1600a9643ea8Slogwang {
1601a9643ea8Slogwang if (NULL == this->_session_hash)
1602a9643ea8Slogwang {
1603a9643ea8Slogwang return NULL;
1604a9643ea8Slogwang }
1605a9643ea8Slogwang
1606a9643ea8Slogwang return (CNetHandler*)_session_hash->HashFind(key);
1607a9643ea8Slogwang }
1608a9643ea8Slogwang
InsertNetItem(CNetHandler * item)1609a9643ea8Slogwang void CNetMgr::InsertNetItem(CNetHandler* item)
1610a9643ea8Slogwang {
1611a9643ea8Slogwang if (NULL == this->_session_hash)
1612a9643ea8Slogwang {
1613a9643ea8Slogwang return;
1614a9643ea8Slogwang }
1615a9643ea8Slogwang
1616a9643ea8Slogwang int32_t ret = _session_hash->HashInsert(item);
1617a9643ea8Slogwang if (ret < 0)
1618a9643ea8Slogwang {
1619a9643ea8Slogwang MTLOG_ERROR("session insert failed, ret %d", ret);
1620a9643ea8Slogwang }
1621a9643ea8Slogwang
1622a9643ea8Slogwang return;
1623a9643ea8Slogwang }
1624a9643ea8Slogwang
RemoveNetItem(CNetHandler * item)1625a9643ea8Slogwang void CNetMgr::RemoveNetItem(CNetHandler* item)
1626a9643ea8Slogwang {
1627a9643ea8Slogwang CNetHandler* handler = this->FindNetItem(item);
1628a9643ea8Slogwang if (NULL == handler)
1629a9643ea8Slogwang {
1630a9643ea8Slogwang return;
1631a9643ea8Slogwang }
1632a9643ea8Slogwang
1633a9643ea8Slogwang _session_hash->HashRemove(handler);
1634a9643ea8Slogwang }
1635a9643ea8Slogwang
FindDestLink(CDestLinks * key)1636a9643ea8Slogwang CDestLinks* CNetMgr::FindDestLink(CDestLinks* key)
1637a9643ea8Slogwang {
1638a9643ea8Slogwang if (NULL == this->_ip_hash)
1639a9643ea8Slogwang {
1640a9643ea8Slogwang return NULL;
1641a9643ea8Slogwang }
1642a9643ea8Slogwang
1643a9643ea8Slogwang return (CDestLinks*)_ip_hash->HashFind(key);
1644a9643ea8Slogwang }
1645a9643ea8Slogwang
InsertDestLink(CDestLinks * item)1646a9643ea8Slogwang void CNetMgr::InsertDestLink(CDestLinks* item)
1647a9643ea8Slogwang {
1648a9643ea8Slogwang if (NULL == this->_ip_hash)
1649a9643ea8Slogwang {
1650a9643ea8Slogwang return;
1651a9643ea8Slogwang }
1652a9643ea8Slogwang
1653a9643ea8Slogwang int32_t ret = _ip_hash->HashInsert(item);
1654a9643ea8Slogwang if (ret < 0)
1655a9643ea8Slogwang {
1656a9643ea8Slogwang MTLOG_ERROR("ip dest insert failed, ret %d", ret);
1657a9643ea8Slogwang }
1658a9643ea8Slogwang
1659a9643ea8Slogwang return;
1660a9643ea8Slogwang }
1661a9643ea8Slogwang
RemoveDestLink(CDestLinks * item)1662a9643ea8Slogwang void CNetMgr::RemoveDestLink(CDestLinks* item)
1663a9643ea8Slogwang {
1664a9643ea8Slogwang CDestLinks* handler = this->FindDestLink(item);
1665a9643ea8Slogwang if (NULL == handler)
1666a9643ea8Slogwang {
1667a9643ea8Slogwang return;
1668a9643ea8Slogwang }
1669a9643ea8Slogwang
1670a9643ea8Slogwang _ip_hash->HashRemove(handler);
1671a9643ea8Slogwang }
1672a9643ea8Slogwang
FindCreateDest(CDestLinks * key)1673a9643ea8Slogwang CDestLinks* CNetMgr::FindCreateDest(CDestLinks* key)
1674a9643ea8Slogwang {
1675a9643ea8Slogwang CDestLinks* dest = this->FindDestLink(key);
1676a9643ea8Slogwang if (dest != NULL)
1677a9643ea8Slogwang {
1678a9643ea8Slogwang MTLOG_DEBUG("dest links reuse ok");
1679a9643ea8Slogwang return dest;
1680a9643ea8Slogwang }
1681a9643ea8Slogwang
1682a9643ea8Slogwang dest = this->AllocDestLink();
1683a9643ea8Slogwang if (NULL == dest)
1684a9643ea8Slogwang {
1685a9643ea8Slogwang MTLOG_ERROR("dest links alloc failed, log it");
1686a9643ea8Slogwang return NULL;
1687a9643ea8Slogwang }
1688a9643ea8Slogwang
1689a9643ea8Slogwang dest->CopyKeyInfo(key);
1690a9643ea8Slogwang dest->StartTimer();
1691a9643ea8Slogwang this->InsertDestLink(dest);
1692a9643ea8Slogwang
1693a9643ea8Slogwang return dest;
1694a9643ea8Slogwang }
1695a9643ea8Slogwang
DeleteDestLink(CDestLinks * dst)1696a9643ea8Slogwang void CNetMgr::DeleteDestLink(CDestLinks* dst)
1697a9643ea8Slogwang {
1698a9643ea8Slogwang this->RemoveDestLink(dst);
1699*35a81399Slogwang dst->Reset();
1700a9643ea8Slogwang this->FreeDestLink(dst);
1701a9643ea8Slogwang }
1702a9643ea8Slogwang
CNetMgr()1703a9643ea8Slogwang CNetMgr::CNetMgr()
1704a9643ea8Slogwang {
1705a9643ea8Slogwang sk_buffer_mng_init(&_tcp_pool, 60, 4096);
1706a9643ea8Slogwang sk_buffer_mng_init(&_udp_pool, 60, SK_DFLT_BUFF_SIZE);
1707a9643ea8Slogwang
1708a9643ea8Slogwang _ip_hash = new HashList(100000);
1709a9643ea8Slogwang _session_hash = new HashList(100000);
1710a9643ea8Slogwang }
1711a9643ea8Slogwang
~CNetMgr()1712a9643ea8Slogwang CNetMgr::~CNetMgr()
1713a9643ea8Slogwang {
1714a9643ea8Slogwang if (_ip_hash != NULL)
1715a9643ea8Slogwang {
1716a9643ea8Slogwang HashKey* hash_item = _ip_hash->HashGetFirst();
1717a9643ea8Slogwang while (hash_item)
1718a9643ea8Slogwang {
1719a9643ea8Slogwang delete hash_item;
1720a9643ea8Slogwang hash_item = _ip_hash->HashGetFirst();
1721a9643ea8Slogwang }
1722a9643ea8Slogwang
1723a9643ea8Slogwang delete _ip_hash;
1724a9643ea8Slogwang _ip_hash = NULL;
1725a9643ea8Slogwang }
1726a9643ea8Slogwang
1727a9643ea8Slogwang if (_session_hash != NULL)
1728a9643ea8Slogwang {
1729a9643ea8Slogwang HashKey* hash_item = _session_hash->HashGetFirst();
1730a9643ea8Slogwang while (hash_item)
1731a9643ea8Slogwang {
1732a9643ea8Slogwang delete hash_item;
1733a9643ea8Slogwang hash_item = _session_hash->HashGetFirst();
1734a9643ea8Slogwang }
1735a9643ea8Slogwang
1736a9643ea8Slogwang delete _session_hash;
1737a9643ea8Slogwang _session_hash = NULL;
1738a9643ea8Slogwang }
1739a9643ea8Slogwang
1740a9643ea8Slogwang sk_buffer_mng_destroy(&_tcp_pool);
1741a9643ea8Slogwang sk_buffer_mng_destroy(&_udp_pool);
1742a9643ea8Slogwang }
1743a9643ea8Slogwang
RecycleObjs(uint64_t now)1744a9643ea8Slogwang void CNetMgr::RecycleObjs(uint64_t now)
1745a9643ea8Slogwang {
1746a9643ea8Slogwang uint32_t now_s = (uint32_t)(now / 1000);
1747a9643ea8Slogwang
1748a9643ea8Slogwang recycle_sk_buffer(&_udp_pool, now_s);
1749a9643ea8Slogwang recycle_sk_buffer(&_tcp_pool, now_s);
1750a9643ea8Slogwang
1751a9643ea8Slogwang _net_item_pool.RecycleItem(now);
1752a9643ea8Slogwang _sock_link_pool.RecycleItem(now);
1753a9643ea8Slogwang _dest_ip_pool.RecycleItem(now);
1754a9643ea8Slogwang }
1755