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_connection.cpp
22a9643ea8Slogwang * @time 20130924
23a9643ea8Slogwang **/
24a9643ea8Slogwang #include <fcntl.h>
25a9643ea8Slogwang #include <sys/types.h>
26a9643ea8Slogwang #include <sys/socket.h>
27a9643ea8Slogwang #include <netinet/in.h>
28a9643ea8Slogwang #include <arpa/inet.h>
29a9643ea8Slogwang
30a9643ea8Slogwang #include "micro_thread.h"
31a9643ea8Slogwang #include "mt_msg.h"
32a9643ea8Slogwang #include "mt_notify.h"
33a9643ea8Slogwang #include "mt_connection.h"
34a9643ea8Slogwang #include "mt_sys_hook.h"
35a9643ea8Slogwang #include "ff_hook.h"
36a9643ea8Slogwang
37a9643ea8Slogwang using namespace std;
38a9643ea8Slogwang using namespace NS_MICRO_THREAD;
39a9643ea8Slogwang
IMtConnection()40a9643ea8Slogwang IMtConnection::IMtConnection()
41a9643ea8Slogwang {
42a9643ea8Slogwang _type = OBJ_CONN_UNDEF;
43a9643ea8Slogwang _action = NULL;
44a9643ea8Slogwang _ntfy_obj = NULL;
45a9643ea8Slogwang _msg_buff = NULL;
46a9643ea8Slogwang }
~IMtConnection()47a9643ea8Slogwang IMtConnection::~IMtConnection()
48a9643ea8Slogwang {
49a9643ea8Slogwang if (_ntfy_obj) {
50a9643ea8Slogwang NtfyObjMgr::Instance()->FreeNtfyObj(_ntfy_obj);
51a9643ea8Slogwang _ntfy_obj = NULL;
52a9643ea8Slogwang }
53a9643ea8Slogwang
54a9643ea8Slogwang if (_msg_buff) {
55a9643ea8Slogwang MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
56a9643ea8Slogwang _msg_buff = NULL;
57a9643ea8Slogwang }
58a9643ea8Slogwang }
59a9643ea8Slogwang
Reset()60a9643ea8Slogwang void IMtConnection::Reset()
61a9643ea8Slogwang {
62a9643ea8Slogwang if (_ntfy_obj) {
63a9643ea8Slogwang NtfyObjMgr::Instance()->FreeNtfyObj(_ntfy_obj);
64a9643ea8Slogwang _ntfy_obj = NULL;
65a9643ea8Slogwang }
66a9643ea8Slogwang
67a9643ea8Slogwang if (_msg_buff) {
68a9643ea8Slogwang MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
69a9643ea8Slogwang _msg_buff = NULL;
70a9643ea8Slogwang }
71a9643ea8Slogwang
72a9643ea8Slogwang _action = NULL;
73a9643ea8Slogwang _ntfy_obj = NULL;
74a9643ea8Slogwang _msg_buff = NULL;
75a9643ea8Slogwang }
76a9643ea8Slogwang
CreateSocket()77a9643ea8Slogwang int UdpShortConn::CreateSocket()
78a9643ea8Slogwang {
79a9643ea8Slogwang _osfd = socket(AF_INET, SOCK_DGRAM, 0);
80a9643ea8Slogwang if (_osfd < 0)
81a9643ea8Slogwang {
82a9643ea8Slogwang MTLOG_ERROR("socket create failed, errno %d(%s)", errno, strerror(errno));
83a9643ea8Slogwang return -1;
84a9643ea8Slogwang }
85a9643ea8Slogwang
86a9643ea8Slogwang int flags = 1;
87a9643ea8Slogwang if (ioctl(_osfd, FIONBIO, &flags) < 0)
88a9643ea8Slogwang {
89a9643ea8Slogwang MTLOG_ERROR("socket unblock failed, errno %d(%s)", errno, strerror(errno));
90a9643ea8Slogwang close(_osfd);
91a9643ea8Slogwang _osfd = -1;
92a9643ea8Slogwang return -2;
93a9643ea8Slogwang }
94a9643ea8Slogwang
95a9643ea8Slogwang if (_ntfy_obj) {
96a9643ea8Slogwang _ntfy_obj->SetOsfd(_osfd);
97a9643ea8Slogwang }
98a9643ea8Slogwang
99a9643ea8Slogwang return _osfd;
100a9643ea8Slogwang }
101a9643ea8Slogwang
CloseSocket()102a9643ea8Slogwang int UdpShortConn::CloseSocket()
103a9643ea8Slogwang {
104a9643ea8Slogwang if (_osfd < 0)
105a9643ea8Slogwang {
106a9643ea8Slogwang return 0;
107a9643ea8Slogwang }
108a9643ea8Slogwang
109a9643ea8Slogwang close(_osfd);
110a9643ea8Slogwang _osfd = -1;
111a9643ea8Slogwang
112a9643ea8Slogwang return 0;
113a9643ea8Slogwang }
114a9643ea8Slogwang
SendData()115a9643ea8Slogwang int UdpShortConn::SendData()
116a9643ea8Slogwang {
117a9643ea8Slogwang if (!_action || !_msg_buff) {
118a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
119a9643ea8Slogwang return -100;
120a9643ea8Slogwang }
121a9643ea8Slogwang
122a9643ea8Slogwang mt_hook_syscall(sendto);
123a9643ea8Slogwang int ret = ff_hook_sendto(_osfd, _msg_buff->GetMsgBuff(), _msg_buff->GetMsgLen(), 0,
124a9643ea8Slogwang (struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
125a9643ea8Slogwang if (ret == -1)
126a9643ea8Slogwang {
127a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
128a9643ea8Slogwang {
129a9643ea8Slogwang return 0;
130a9643ea8Slogwang }
131a9643ea8Slogwang else
132a9643ea8Slogwang {
133a9643ea8Slogwang MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _osfd,
134a9643ea8Slogwang errno, strerror(errno));
135a9643ea8Slogwang return -2;
136a9643ea8Slogwang }
137a9643ea8Slogwang }
138a9643ea8Slogwang else
139a9643ea8Slogwang {
140a9643ea8Slogwang _msg_buff->SetHaveSndLen(ret);
141a9643ea8Slogwang return ret;
142a9643ea8Slogwang }
143a9643ea8Slogwang }
144a9643ea8Slogwang
RecvData()145a9643ea8Slogwang int UdpShortConn::RecvData()
146a9643ea8Slogwang {
147a9643ea8Slogwang if (!_action || !_msg_buff) {
148a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
149a9643ea8Slogwang return -100;
150a9643ea8Slogwang }
151a9643ea8Slogwang
152a9643ea8Slogwang struct sockaddr_in from;
153a9643ea8Slogwang socklen_t fromlen = sizeof(from);
154a9643ea8Slogwang mt_hook_syscall(recvfrom);
155a9643ea8Slogwang int ret = ff_hook_recvfrom(_osfd, _msg_buff->GetMsgBuff(), _msg_buff->GetMaxLen(),
156a9643ea8Slogwang 0, (struct sockaddr*)&from, &fromlen);
157a9643ea8Slogwang if (ret < 0)
158a9643ea8Slogwang {
159a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
160a9643ea8Slogwang {
161a9643ea8Slogwang return 0;
162a9643ea8Slogwang }
163a9643ea8Slogwang else
164a9643ea8Slogwang {
165a9643ea8Slogwang MTLOG_ERROR("socket recv failed, fd %d, errno %d(%s)", _osfd,
166a9643ea8Slogwang errno, strerror(errno));
167*35a81399Slogwang return -2;
168a9643ea8Slogwang }
169a9643ea8Slogwang }
170a9643ea8Slogwang else if (ret == 0)
171a9643ea8Slogwang {
172*35a81399Slogwang return -1;
173a9643ea8Slogwang }
174a9643ea8Slogwang else
175a9643ea8Slogwang {
176a9643ea8Slogwang _msg_buff->SetHaveRcvLen(ret);
177a9643ea8Slogwang }
178a9643ea8Slogwang
179a9643ea8Slogwang ret = _action->DoInput();
180a9643ea8Slogwang if (ret > 0)
181a9643ea8Slogwang {
182a9643ea8Slogwang _msg_buff->SetMsgLen(ret);
183a9643ea8Slogwang return ret;
184a9643ea8Slogwang }
185a9643ea8Slogwang else if (ret == 0)
186a9643ea8Slogwang {
187a9643ea8Slogwang return 0;
188a9643ea8Slogwang }
189a9643ea8Slogwang else if (ret == -65535)
190a9643ea8Slogwang {
191a9643ea8Slogwang _msg_buff->SetHaveRcvLen(0);
192a9643ea8Slogwang return 0;
193a9643ea8Slogwang }
194a9643ea8Slogwang else
195a9643ea8Slogwang {
196a9643ea8Slogwang return -1;
197a9643ea8Slogwang }
198a9643ea8Slogwang }
199a9643ea8Slogwang
Reset()200a9643ea8Slogwang void UdpShortConn::Reset()
201a9643ea8Slogwang {
202a9643ea8Slogwang CloseSocket();
203a9643ea8Slogwang this->IMtConnection::Reset();
204a9643ea8Slogwang }
205a9643ea8Slogwang
OpenCnnect()206a9643ea8Slogwang int TcpKeepConn::OpenCnnect()
207a9643ea8Slogwang {
208a9643ea8Slogwang if (!_action || !_msg_buff) {
209a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
210a9643ea8Slogwang return -100;
211a9643ea8Slogwang }
212a9643ea8Slogwang
213a9643ea8Slogwang int err = 0;
214a9643ea8Slogwang mt_hook_syscall(connect);
215a9643ea8Slogwang int ret = ff_hook_connect(_osfd, (struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
216a9643ea8Slogwang if (ret < 0)
217a9643ea8Slogwang {
218a9643ea8Slogwang err = errno;
219a9643ea8Slogwang if (err == EISCONN)
220a9643ea8Slogwang {
221a9643ea8Slogwang return 0;
222a9643ea8Slogwang }
223a9643ea8Slogwang else
224a9643ea8Slogwang {
225a9643ea8Slogwang if ((err == EINPROGRESS) || (err == EALREADY) || (err == EINTR))
226a9643ea8Slogwang {
227a9643ea8Slogwang MTLOG_DEBUG("Open connect not ok, maybe first try, sock %d, errno %d", _osfd, err);
228a9643ea8Slogwang return -1;
229a9643ea8Slogwang }
230a9643ea8Slogwang else
231a9643ea8Slogwang {
232a9643ea8Slogwang MTLOG_ERROR("Open connect not ok, sock %d, errno %d", _osfd, err);
233a9643ea8Slogwang return -2;
234a9643ea8Slogwang }
235a9643ea8Slogwang }
236a9643ea8Slogwang }
237a9643ea8Slogwang else
238a9643ea8Slogwang {
239a9643ea8Slogwang return 0;
240a9643ea8Slogwang }
241a9643ea8Slogwang }
242a9643ea8Slogwang
CreateSocket()243a9643ea8Slogwang int TcpKeepConn::CreateSocket()
244a9643ea8Slogwang {
245*35a81399Slogwang if (_osfd > 0)
246a9643ea8Slogwang {
247a9643ea8Slogwang if (_ntfy_obj) {
248a9643ea8Slogwang _ntfy_obj->SetOsfd(_osfd);
249a9643ea8Slogwang }
250a9643ea8Slogwang
251a9643ea8Slogwang return _osfd;
252a9643ea8Slogwang }
253a9643ea8Slogwang
254a9643ea8Slogwang _osfd = socket(AF_INET, SOCK_STREAM, 0);
255a9643ea8Slogwang if (_osfd < 0)
256a9643ea8Slogwang {
257a9643ea8Slogwang MTLOG_ERROR("create tcp socket failed, error: %d", errno);
258a9643ea8Slogwang return -1;
259a9643ea8Slogwang }
260a9643ea8Slogwang
261a9643ea8Slogwang int flags = 1;
262a9643ea8Slogwang if (ioctl(_osfd, FIONBIO, &flags) < 0)
263a9643ea8Slogwang {
264a9643ea8Slogwang MTLOG_ERROR("set tcp socket unblock failed, error: %d", errno);
265a9643ea8Slogwang close(_osfd);
266a9643ea8Slogwang _osfd = -1;
267a9643ea8Slogwang return -2;
268a9643ea8Slogwang }
269a9643ea8Slogwang
270a9643ea8Slogwang _keep_ntfy.SetOsfd(_osfd);
271a9643ea8Slogwang _keep_ntfy.DisableOutput();
272a9643ea8Slogwang _keep_ntfy.EnableInput();
273a9643ea8Slogwang
274a9643ea8Slogwang if (_ntfy_obj) {
275a9643ea8Slogwang _ntfy_obj->SetOsfd(_osfd);
276a9643ea8Slogwang }
277a9643ea8Slogwang
278a9643ea8Slogwang return _osfd;
279a9643ea8Slogwang }
280a9643ea8Slogwang
SendData()281a9643ea8Slogwang int TcpKeepConn::SendData()
282a9643ea8Slogwang {
283a9643ea8Slogwang if (!_action || !_msg_buff) {
284a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
285a9643ea8Slogwang return -100;
286a9643ea8Slogwang }
287a9643ea8Slogwang
288a9643ea8Slogwang char* msg_ptr = (char*)_msg_buff->GetMsgBuff();
289a9643ea8Slogwang int msg_len = _msg_buff->GetMsgLen();
290a9643ea8Slogwang int have_send_len = _msg_buff->GetHaveSndLen();
291a9643ea8Slogwang mt_hook_syscall(send);
292a9643ea8Slogwang int ret = ff_hook_send(_osfd, msg_ptr + have_send_len, msg_len - have_send_len, 0);
293a9643ea8Slogwang if (ret == -1)
294a9643ea8Slogwang {
295a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
296a9643ea8Slogwang {
297a9643ea8Slogwang return 0;
298a9643ea8Slogwang }
299a9643ea8Slogwang else
300a9643ea8Slogwang {
301a9643ea8Slogwang MTLOG_ERROR("send tcp socket failed, error: %d", errno);
302a9643ea8Slogwang return -1;
303a9643ea8Slogwang }
304a9643ea8Slogwang }
305a9643ea8Slogwang else
306a9643ea8Slogwang {
307a9643ea8Slogwang have_send_len += ret;
308a9643ea8Slogwang _msg_buff->SetHaveSndLen(have_send_len);
309a9643ea8Slogwang }
310a9643ea8Slogwang
311a9643ea8Slogwang if (have_send_len >= msg_len)
312a9643ea8Slogwang {
313a9643ea8Slogwang return msg_len;
314a9643ea8Slogwang }
315a9643ea8Slogwang else
316a9643ea8Slogwang {
317a9643ea8Slogwang return 0;
318a9643ea8Slogwang }
319a9643ea8Slogwang }
320a9643ea8Slogwang
RecvData()321a9643ea8Slogwang int TcpKeepConn::RecvData()
322a9643ea8Slogwang {
323a9643ea8Slogwang if (!_action || !_msg_buff) {
324a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, error", _action, _msg_buff);
325a9643ea8Slogwang return -100;
326a9643ea8Slogwang }
327a9643ea8Slogwang
328a9643ea8Slogwang char* msg_ptr = (char*)_msg_buff->GetMsgBuff();
329a9643ea8Slogwang int max_len = _msg_buff->GetMaxLen();
330a9643ea8Slogwang int have_rcv_len = _msg_buff->GetHaveRcvLen();
331a9643ea8Slogwang mt_hook_syscall(recv);
332a9643ea8Slogwang int ret = ff_hook_recv(_osfd, (char*)msg_ptr + have_rcv_len, max_len - have_rcv_len, 0);
333a9643ea8Slogwang if (ret < 0)
334a9643ea8Slogwang {
335a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
336a9643ea8Slogwang {
337a9643ea8Slogwang return 0;
338a9643ea8Slogwang }
339a9643ea8Slogwang else
340a9643ea8Slogwang {
341a9643ea8Slogwang MTLOG_ERROR("recv tcp socket failed, error: %d", errno);
342*35a81399Slogwang return -2;
343a9643ea8Slogwang }
344a9643ea8Slogwang }
345a9643ea8Slogwang else if (ret == 0)
346a9643ea8Slogwang {
347a9643ea8Slogwang MTLOG_ERROR("tcp remote close, address: %s[%d]",
348a9643ea8Slogwang inet_ntoa(_dst_addr.sin_addr), ntohs(_dst_addr.sin_port));
349*35a81399Slogwang return -1;
350a9643ea8Slogwang }
351a9643ea8Slogwang else
352a9643ea8Slogwang {
353a9643ea8Slogwang have_rcv_len += ret;
354a9643ea8Slogwang _msg_buff->SetHaveRcvLen(have_rcv_len);
355a9643ea8Slogwang }
356a9643ea8Slogwang
357a9643ea8Slogwang ret = _action->DoInput();
358a9643ea8Slogwang if (ret > 0)
359a9643ea8Slogwang {
360a9643ea8Slogwang _msg_buff->SetMsgLen(have_rcv_len);
361a9643ea8Slogwang return ret;
362a9643ea8Slogwang }
363a9643ea8Slogwang else if (ret == 0)
364a9643ea8Slogwang {
365a9643ea8Slogwang return 0;
366a9643ea8Slogwang }
367a9643ea8Slogwang else
368a9643ea8Slogwang {
369a9643ea8Slogwang return -1;
370a9643ea8Slogwang }
371a9643ea8Slogwang }
372a9643ea8Slogwang
CloseSocket()373a9643ea8Slogwang int TcpKeepConn::CloseSocket()
374a9643ea8Slogwang {
375a9643ea8Slogwang if (_osfd < 0)
376a9643ea8Slogwang {
377a9643ea8Slogwang return 0;
378a9643ea8Slogwang }
379a9643ea8Slogwang _keep_ntfy.SetOsfd(-1);
380a9643ea8Slogwang
381a9643ea8Slogwang close(_osfd);
382a9643ea8Slogwang _osfd = -1;
383a9643ea8Slogwang
384a9643ea8Slogwang return 0;
385a9643ea8Slogwang }
386a9643ea8Slogwang
Reset()387a9643ea8Slogwang void TcpKeepConn::Reset()
388a9643ea8Slogwang {
389a9643ea8Slogwang memset(&_dst_addr, 0 ,sizeof(_dst_addr));
390a9643ea8Slogwang CloseSocket();
391a9643ea8Slogwang this->IMtConnection::Reset();
392a9643ea8Slogwang }
393a9643ea8Slogwang
ConnReuseClean()394a9643ea8Slogwang void TcpKeepConn::ConnReuseClean()
395a9643ea8Slogwang {
396a9643ea8Slogwang this->IMtConnection::Reset();
397a9643ea8Slogwang }
398a9643ea8Slogwang
IdleAttach()399a9643ea8Slogwang bool TcpKeepConn::IdleAttach()
400a9643ea8Slogwang {
401a9643ea8Slogwang if (_osfd < 0) {
402a9643ea8Slogwang MTLOG_ERROR("obj %p attach failed, fd %d error", this, _osfd);
403a9643ea8Slogwang return false;
404a9643ea8Slogwang }
405a9643ea8Slogwang
406a9643ea8Slogwang if (_keep_flag & TCP_KEEP_IN_KQUEUE) {
407a9643ea8Slogwang MTLOG_ERROR("obj %p repeat attach, error", this);
408a9643ea8Slogwang return true;
409a9643ea8Slogwang }
410a9643ea8Slogwang
411a9643ea8Slogwang _keep_ntfy.DisableOutput();
412a9643ea8Slogwang _keep_ntfy.EnableInput();
413a9643ea8Slogwang
414a9643ea8Slogwang CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
415a9643ea8Slogwang if ((NULL == timer) || !timer->start_timer(this, _keep_time))
416a9643ea8Slogwang {
417a9643ea8Slogwang MTLOG_ERROR("obj %p attach timer failed, error", this);
418a9643ea8Slogwang return false;
419a9643ea8Slogwang }
420a9643ea8Slogwang
421a9643ea8Slogwang if (MtFrame::Instance()->KqueueAddObj(&_keep_ntfy))
422a9643ea8Slogwang {
423a9643ea8Slogwang _keep_flag |= TCP_KEEP_IN_KQUEUE;
424a9643ea8Slogwang return true;
425a9643ea8Slogwang }
426a9643ea8Slogwang else
427a9643ea8Slogwang {
428a9643ea8Slogwang MTLOG_ERROR("obj %p attach failed, error", this);
429a9643ea8Slogwang return false;
430a9643ea8Slogwang }
431a9643ea8Slogwang }
432a9643ea8Slogwang
IdleDetach()433a9643ea8Slogwang bool TcpKeepConn::IdleDetach()
434a9643ea8Slogwang {
435a9643ea8Slogwang if (_osfd < 0) {
436a9643ea8Slogwang MTLOG_ERROR("obj %p detach failed, fd %d error", this, _osfd);
437a9643ea8Slogwang return false;
438a9643ea8Slogwang }
439a9643ea8Slogwang
440a9643ea8Slogwang if (!(_keep_flag & TCP_KEEP_IN_KQUEUE)) {
441a9643ea8Slogwang MTLOG_DEBUG("obj %p repeat detach, error", this);
442a9643ea8Slogwang return true;
443a9643ea8Slogwang }
444a9643ea8Slogwang
445a9643ea8Slogwang _keep_ntfy.DisableOutput();
446a9643ea8Slogwang _keep_ntfy.EnableInput();
447a9643ea8Slogwang
448a9643ea8Slogwang CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
449a9643ea8Slogwang if (NULL != timer)
450a9643ea8Slogwang {
451a9643ea8Slogwang timer->stop_timer(this);
452a9643ea8Slogwang }
453a9643ea8Slogwang
454a9643ea8Slogwang if (MtFrame::Instance()->KqueueDelObj(&_keep_ntfy))
455a9643ea8Slogwang {
456a9643ea8Slogwang _keep_flag &= ~TCP_KEEP_IN_KQUEUE;
457a9643ea8Slogwang return true;
458a9643ea8Slogwang }
459a9643ea8Slogwang else
460a9643ea8Slogwang {
461a9643ea8Slogwang MTLOG_ERROR("obj %p detach failed, error", this);
462a9643ea8Slogwang return false;
463a9643ea8Slogwang }
464a9643ea8Slogwang }
465a9643ea8Slogwang
timer_notify()466a9643ea8Slogwang void TcpKeepConn::timer_notify()
467a9643ea8Slogwang {
468a9643ea8Slogwang MTLOG_DEBUG("keep timeout[%u], fd %d, close connection", _keep_time, _osfd);
469a9643ea8Slogwang ConnectionMgr::Instance()->CloseIdleTcpKeep(this);
470a9643ea8Slogwang }
471a9643ea8Slogwang
TcpKeepMgr()472a9643ea8Slogwang TcpKeepMgr::TcpKeepMgr()
473a9643ea8Slogwang {
474a9643ea8Slogwang _keep_hash = new HashList(10000);
475a9643ea8Slogwang }
476a9643ea8Slogwang
~TcpKeepMgr()477a9643ea8Slogwang TcpKeepMgr::~TcpKeepMgr()
478a9643ea8Slogwang {
479a9643ea8Slogwang if (!_keep_hash) {
480a9643ea8Slogwang return;
481a9643ea8Slogwang }
482a9643ea8Slogwang
483a9643ea8Slogwang HashKey* hash_item = _keep_hash->HashGetFirst();
484a9643ea8Slogwang while (hash_item)
485a9643ea8Slogwang {
486a9643ea8Slogwang delete hash_item;
487a9643ea8Slogwang hash_item = _keep_hash->HashGetFirst();
488a9643ea8Slogwang }
489a9643ea8Slogwang
490a9643ea8Slogwang delete _keep_hash;
491a9643ea8Slogwang _keep_hash = NULL;
492a9643ea8Slogwang }
493a9643ea8Slogwang
GetTcpKeepConn(struct sockaddr_in * dst)494a9643ea8Slogwang TcpKeepConn* TcpKeepMgr::GetTcpKeepConn(struct sockaddr_in* dst)
495a9643ea8Slogwang {
496a9643ea8Slogwang TcpKeepConn* conn = NULL;
497a9643ea8Slogwang if (NULL == dst)
498a9643ea8Slogwang {
499a9643ea8Slogwang MTLOG_ERROR("input param dst null, error");
500a9643ea8Slogwang return NULL;
501a9643ea8Slogwang }
502a9643ea8Slogwang
503a9643ea8Slogwang TcpKeepKey key(dst);
504a9643ea8Slogwang TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
505a9643ea8Slogwang if ((NULL == conn_list) || (NULL == conn_list->GetFirstConn()))
506a9643ea8Slogwang {
507a9643ea8Slogwang conn = _mem_queue.AllocPtr();
508a9643ea8Slogwang if (conn) {
509a9643ea8Slogwang conn->SetDestAddr(dst);
510a9643ea8Slogwang }
511a9643ea8Slogwang }
512a9643ea8Slogwang else
513a9643ea8Slogwang {
514a9643ea8Slogwang conn = conn_list->GetFirstConn();
515a9643ea8Slogwang conn_list->RemoveConn(conn);
516a9643ea8Slogwang conn->IdleDetach();
517a9643ea8Slogwang }
518a9643ea8Slogwang
519a9643ea8Slogwang return conn;
520a9643ea8Slogwang }
521a9643ea8Slogwang
RemoveTcpKeepConn(TcpKeepConn * conn)522a9643ea8Slogwang bool TcpKeepMgr::RemoveTcpKeepConn(TcpKeepConn* conn)
523a9643ea8Slogwang {
524a9643ea8Slogwang struct sockaddr_in* dst = conn->GetDestAddr();
525a9643ea8Slogwang if ((dst->sin_addr.s_addr == 0) || (dst->sin_port == 0))
526a9643ea8Slogwang {
527a9643ea8Slogwang MTLOG_ERROR("sock addr, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
528a9643ea8Slogwang return false;
529a9643ea8Slogwang }
530a9643ea8Slogwang
531a9643ea8Slogwang TcpKeepKey key(dst);
532a9643ea8Slogwang TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
533a9643ea8Slogwang if (!conn_list)
534a9643ea8Slogwang {
535a9643ea8Slogwang MTLOG_ERROR("no conn cache list, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
536a9643ea8Slogwang return false;
537a9643ea8Slogwang }
538a9643ea8Slogwang
539a9643ea8Slogwang conn->IdleDetach();
540a9643ea8Slogwang conn_list->RemoveConn(conn);
541a9643ea8Slogwang
542a9643ea8Slogwang return true;
543a9643ea8Slogwang
544a9643ea8Slogwang }
545a9643ea8Slogwang
CacheTcpKeepConn(TcpKeepConn * conn)546a9643ea8Slogwang bool TcpKeepMgr::CacheTcpKeepConn(TcpKeepConn* conn)
547a9643ea8Slogwang {
548a9643ea8Slogwang struct sockaddr_in* dst = conn->GetDestAddr();
549a9643ea8Slogwang if ((dst->sin_addr.s_addr == 0) || (dst->sin_port == 0))
550a9643ea8Slogwang {
551a9643ea8Slogwang MTLOG_ERROR("sock addr, invalid, %x:%d", dst->sin_addr.s_addr, dst->sin_port);
552a9643ea8Slogwang return false;
553a9643ea8Slogwang }
554a9643ea8Slogwang
555a9643ea8Slogwang TcpKeepKey key(dst);
556a9643ea8Slogwang TcpKeepKey* conn_list = (TcpKeepKey*)_keep_hash->HashFindData(&key);
557a9643ea8Slogwang if (!conn_list)
558a9643ea8Slogwang {
559a9643ea8Slogwang conn_list = new TcpKeepKey(conn->GetDestAddr());
560a9643ea8Slogwang if (!conn_list) {
561a9643ea8Slogwang MTLOG_ERROR("new conn list failed, error");
562a9643ea8Slogwang return false;
563a9643ea8Slogwang }
564a9643ea8Slogwang _keep_hash->HashInsert(conn_list);
565a9643ea8Slogwang }
566a9643ea8Slogwang
567a9643ea8Slogwang if (!conn->IdleAttach())
568a9643ea8Slogwang {
569a9643ea8Slogwang MTLOG_ERROR("conn IdleAttach failed, error");
570a9643ea8Slogwang return false;
571a9643ea8Slogwang }
572a9643ea8Slogwang
573a9643ea8Slogwang conn->ConnReuseClean();
574a9643ea8Slogwang conn_list->InsertConn(conn);
575a9643ea8Slogwang
576a9643ea8Slogwang
577a9643ea8Slogwang return true;
578a9643ea8Slogwang
579a9643ea8Slogwang }
580a9643ea8Slogwang
FreeTcpKeepConn(TcpKeepConn * conn,bool force_free)581a9643ea8Slogwang void TcpKeepMgr::FreeTcpKeepConn(TcpKeepConn* conn, bool force_free)
582a9643ea8Slogwang {
583a9643ea8Slogwang if (force_free)
584a9643ea8Slogwang {
585a9643ea8Slogwang conn->Reset();
586a9643ea8Slogwang _mem_queue.FreePtr(conn);
587a9643ea8Slogwang return;
588a9643ea8Slogwang }
589a9643ea8Slogwang else
590a9643ea8Slogwang {
591a9643ea8Slogwang if (!CacheTcpKeepConn(conn))
592a9643ea8Slogwang {
593a9643ea8Slogwang conn->Reset();
594a9643ea8Slogwang _mem_queue.FreePtr(conn);
595a9643ea8Slogwang return;
596a9643ea8Slogwang }
597a9643ea8Slogwang }
598a9643ea8Slogwang }
599a9643ea8Slogwang
CreateSocket()600a9643ea8Slogwang int UdpSessionConn::CreateSocket()
601a9643ea8Slogwang {
602a9643ea8Slogwang if (!_action || !_ntfy_obj) {
603a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or _ntfy_obj %p, error", _action, _ntfy_obj);
604a9643ea8Slogwang return -100;
605a9643ea8Slogwang }
606a9643ea8Slogwang SessionProxy* proxy = dynamic_cast<SessionProxy*>(_ntfy_obj);
607a9643ea8Slogwang if (!proxy) {
608a9643ea8Slogwang MTLOG_ERROR("ntfy obj not match, _ntfy_obj %p, error", _ntfy_obj);
609a9643ea8Slogwang return -200;
610a9643ea8Slogwang }
611a9643ea8Slogwang ISessionNtfy* real_ntfy = proxy->GetRealNtfyObj();
612a9643ea8Slogwang if (!real_ntfy) {
613a9643ea8Slogwang MTLOG_ERROR("real ntfy obj not match, _ntfy_obj %p, error", _ntfy_obj);
614a9643ea8Slogwang return -300;
615a9643ea8Slogwang }
616a9643ea8Slogwang
617a9643ea8Slogwang int osfd = real_ntfy->GetOsfd();
618a9643ea8Slogwang if (osfd <= 0)
619a9643ea8Slogwang {
620a9643ea8Slogwang osfd = real_ntfy->CreateSocket();
621a9643ea8Slogwang if (osfd <= 0) {
622a9643ea8Slogwang MTLOG_ERROR("real ntfy obj create fd failed, _ntfy_obj %p, error", real_ntfy);
623a9643ea8Slogwang return -400;
624a9643ea8Slogwang }
625a9643ea8Slogwang }
626a9643ea8Slogwang _ntfy_obj->SetOsfd(osfd);
627a9643ea8Slogwang
628a9643ea8Slogwang return osfd;
629a9643ea8Slogwang }
630a9643ea8Slogwang
CloseSocket()631a9643ea8Slogwang int UdpSessionConn::CloseSocket()
632a9643ea8Slogwang {
633a9643ea8Slogwang return 0;
634a9643ea8Slogwang }
635a9643ea8Slogwang
SendData()636a9643ea8Slogwang int UdpSessionConn::SendData()
637a9643ea8Slogwang {
638a9643ea8Slogwang if (!_action || !_msg_buff || !_ntfy_obj) {
639a9643ea8Slogwang MTLOG_ERROR("conn not set action %p, or msg %p, ntfy %p error", _action, _msg_buff, _ntfy_obj);
640a9643ea8Slogwang return -100;
641a9643ea8Slogwang }
642a9643ea8Slogwang
643a9643ea8Slogwang mt_hook_syscall(sendto);
644a9643ea8Slogwang int ret = ff_hook_sendto(_ntfy_obj->GetOsfd(), _msg_buff->GetMsgBuff(), _msg_buff->GetMsgLen(), 0,
645a9643ea8Slogwang (struct sockaddr*)_action->GetMsgDstAddr(), sizeof(struct sockaddr_in));
646a9643ea8Slogwang if (ret == -1)
647a9643ea8Slogwang {
648a9643ea8Slogwang if ((errno == EINTR) || (errno == EAGAIN) || (errno == EINPROGRESS))
649a9643ea8Slogwang {
650a9643ea8Slogwang return 0;
651a9643ea8Slogwang }
652a9643ea8Slogwang else
653a9643ea8Slogwang {
654a9643ea8Slogwang MTLOG_ERROR("socket send failed, fd %d, errno %d(%s)", _ntfy_obj->GetOsfd(),
655a9643ea8Slogwang errno, strerror(errno));
656a9643ea8Slogwang return -2;
657a9643ea8Slogwang }
658a9643ea8Slogwang }
659a9643ea8Slogwang else
660a9643ea8Slogwang {
661a9643ea8Slogwang _msg_buff->SetHaveSndLen(ret);
662a9643ea8Slogwang return ret;
663a9643ea8Slogwang }
664a9643ea8Slogwang }
665a9643ea8Slogwang
RecvData()666a9643ea8Slogwang int UdpSessionConn::RecvData()
667a9643ea8Slogwang {
668a9643ea8Slogwang if (!_ntfy_obj || !_msg_buff) {
669a9643ea8Slogwang MTLOG_ERROR("conn not set _ntfy_obj %p, or msg %p, error", _ntfy_obj, _msg_buff);
670a9643ea8Slogwang return -100;
671a9643ea8Slogwang }
672a9643ea8Slogwang
673a9643ea8Slogwang if (_ntfy_obj->GetRcvEvents() <= 0) {
674a9643ea8Slogwang MTLOG_DEBUG("conn _ntfy_obj %p, no recv event, retry it", _ntfy_obj);
675a9643ea8Slogwang return 0;
676a9643ea8Slogwang }
677a9643ea8Slogwang
678a9643ea8Slogwang int msg_len = _msg_buff->GetMsgLen();
679a9643ea8Slogwang if (BUFF_RECV == _msg_buff->GetBuffType())
680a9643ea8Slogwang {
681a9643ea8Slogwang return msg_len;
682a9643ea8Slogwang }
683a9643ea8Slogwang else
684a9643ea8Slogwang {
685a9643ea8Slogwang MTLOG_DEBUG("conn msg buff %p, no recv comm", _msg_buff);
686a9643ea8Slogwang return 0;
687a9643ea8Slogwang }
688a9643ea8Slogwang }
689a9643ea8Slogwang
690a9643ea8Slogwang ConnectionMgr* ConnectionMgr::_instance = NULL;
Instance(void)691a9643ea8Slogwang ConnectionMgr* ConnectionMgr::Instance (void)
692a9643ea8Slogwang {
693a9643ea8Slogwang if (NULL == _instance)
694a9643ea8Slogwang {
695a9643ea8Slogwang _instance = new ConnectionMgr();
696a9643ea8Slogwang }
697a9643ea8Slogwang
698a9643ea8Slogwang return _instance;
699a9643ea8Slogwang }
700a9643ea8Slogwang
Destroy()701a9643ea8Slogwang void ConnectionMgr::Destroy()
702a9643ea8Slogwang {
703a9643ea8Slogwang if( _instance != NULL )
704a9643ea8Slogwang {
705a9643ea8Slogwang delete _instance;
706a9643ea8Slogwang _instance = NULL;
707a9643ea8Slogwang }
708a9643ea8Slogwang }
709a9643ea8Slogwang
ConnectionMgr()710a9643ea8Slogwang ConnectionMgr::ConnectionMgr()
711a9643ea8Slogwang {
712a9643ea8Slogwang }
713a9643ea8Slogwang
~ConnectionMgr()714a9643ea8Slogwang ConnectionMgr::~ConnectionMgr()
715a9643ea8Slogwang {
716a9643ea8Slogwang }
717a9643ea8Slogwang
GetConnection(CONN_OBJ_TYPE type,struct sockaddr_in * dst)718a9643ea8Slogwang IMtConnection* ConnectionMgr::GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst)
719a9643ea8Slogwang {
720a9643ea8Slogwang switch (type)
721a9643ea8Slogwang {
722a9643ea8Slogwang case OBJ_SHORT_CONN:
723a9643ea8Slogwang return _udp_short_queue.AllocPtr();
724a9643ea8Slogwang break;
725a9643ea8Slogwang
726a9643ea8Slogwang case OBJ_TCP_KEEP:
727a9643ea8Slogwang return _tcp_keep_mgr.GetTcpKeepConn(dst);
728a9643ea8Slogwang break;
729a9643ea8Slogwang
730a9643ea8Slogwang case OBJ_UDP_SESSION:
731a9643ea8Slogwang return _udp_session_queue.AllocPtr();
732a9643ea8Slogwang break;
733a9643ea8Slogwang
734a9643ea8Slogwang default:
735a9643ea8Slogwang return NULL;
736a9643ea8Slogwang break;
737a9643ea8Slogwang }
738a9643ea8Slogwang
739a9643ea8Slogwang }
740a9643ea8Slogwang
FreeConnection(IMtConnection * conn,bool force_free)741a9643ea8Slogwang void ConnectionMgr::FreeConnection(IMtConnection* conn, bool force_free)
742a9643ea8Slogwang {
743a9643ea8Slogwang if (!conn) {
744a9643ea8Slogwang return;
745a9643ea8Slogwang }
746a9643ea8Slogwang CONN_OBJ_TYPE type = conn->GetConnType();
747a9643ea8Slogwang
748a9643ea8Slogwang switch (type)
749a9643ea8Slogwang {
750a9643ea8Slogwang case OBJ_SHORT_CONN:
751a9643ea8Slogwang conn->Reset();
752a9643ea8Slogwang return _udp_short_queue.FreePtr(dynamic_cast<UdpShortConn*>(conn));
753a9643ea8Slogwang break;
754a9643ea8Slogwang
755a9643ea8Slogwang case OBJ_TCP_KEEP:
756a9643ea8Slogwang return _tcp_keep_mgr.FreeTcpKeepConn(dynamic_cast<TcpKeepConn*>(conn), force_free);
757a9643ea8Slogwang break;
758a9643ea8Slogwang
759a9643ea8Slogwang case OBJ_UDP_SESSION:
760a9643ea8Slogwang conn->Reset();
761a9643ea8Slogwang return _udp_session_queue.FreePtr(dynamic_cast<UdpSessionConn*>(conn));
762a9643ea8Slogwang break;
763a9643ea8Slogwang
764a9643ea8Slogwang default:
765a9643ea8Slogwang break;
766a9643ea8Slogwang }
767a9643ea8Slogwang
768a9643ea8Slogwang delete conn;
769a9643ea8Slogwang return;
770a9643ea8Slogwang }
771a9643ea8Slogwang
CloseIdleTcpKeep(TcpKeepConn * conn)772a9643ea8Slogwang void ConnectionMgr::CloseIdleTcpKeep(TcpKeepConn* conn)
773a9643ea8Slogwang {
774a9643ea8Slogwang _tcp_keep_mgr.RemoveTcpKeepConn(conn);
775a9643ea8Slogwang _tcp_keep_mgr.FreeTcpKeepConn(conn, true);
776a9643ea8Slogwang }
777