xref: /f-stack/app/micro_thread/mt_net.h (revision a9643ea8)
1 
2 /**
3  * Tencent is pleased to support the open source community by making MSEC available.
4  *
5  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6  *
7  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License. You may
9  * obtain a copy of the License at
10  *
11  *     https://opensource.org/licenses/GPL-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software distributed under the
14  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language governing permissions
16  * and limitations under the License.
17  */
18 
19 
20 /**
21  *  @file mt_net.h
22  *  @info ΢�̷߳�װ������ӿ���
23  **/
24 
25 #ifndef __MT_NET_H__
26 #define __MT_NET_H__
27 
28 #include "micro_thread.h"
29 #include "hash_list.h"
30 #include "mt_api.h"
31 #include "mt_cache.h"
32 #include "mt_net_api.h"
33 
34 namespace NS_MICRO_THREAD {
35 
36 /**
37  * @brief �������Ͷ���
38  */
39 enum MT_CONN_TYPE
40 {
41     TYPE_CONN_UNKNOWN   = 0,
42     TYPE_CONN_SHORT     = 0x1,          ///< ������, һ�ν�����ر�
43     TYPE_CONN_POOL      = 0x2,          ///< �����ӣ�ÿ��ʹ�ú�, �ɻ����ظ�ʹ��
44     TYPE_CONN_SESSION   = 0x4,          ///< �����ӣ���session id ����, ������
45     TYPE_CONN_SENDONLY  = 0x8,          ///< ֻ������
46 };
47 
48 
49 /******************************************************************************/
50 /*  �ڲ�ʵ�ֲ���                                                              */
51 /******************************************************************************/
52 class CSockLink;
53 
54 /**
55  * @brief ��ʱ���յĶ����ģ��ʵ��
56  * @info  List������tailq, Type ��Ҫ��reset����, releasetime, linkentry�ֶ�
57  */
58 template <typename List, typename Type>
59 class CRecyclePool
60 {
61 public:
62 
63     // ���캯��, Ĭ��60s��ʱ
64     CRecyclePool() {
65         _expired = 60 * 1000;
66         _count = 0;
67         TAILQ_INIT(&_free_list);
68     };
69 
70     // ��������, ɾ������Ԫ��
71     ~CRecyclePool() {
72         Type* item = NULL;
73         Type* tmp = NULL;
74         TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
75         {
76             TAILQ_REMOVE(&_free_list, item, _link_entry);
77             delete item;
78         }
79         _count = 0;
80     };
81 
82     // ���û��´�������
83     Type* AllocItem() {
84         Type* item = TAILQ_FIRST(&_free_list);
85         if (item != NULL)
86         {
87             TAILQ_REMOVE(&_free_list, item, _link_entry);
88             _count--;
89             return item;
90         }
91 
92         item = new Type();
93         if (NULL == item)
94         {
95             return NULL;
96         }
97 
98         return item;
99     };
100 
101     // �ͷŹ������
102     void FreeItem(Type* obj) {
103         //obj->Reset();
104         TAILQ_INSERT_TAIL(&_free_list, obj, _link_entry);
105         obj->_release_time = mt_time_ms();
106         _count++;
107     };
108 
109 
110     // ���վ��
111     void RecycleItem(uint64_t now) {
112         Type* item = NULL;
113         Type* tmp = NULL;
114         TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
115         {
116             if ((now - item->_release_time) < _expired) {
117                 break;
118             }
119 
120             TAILQ_REMOVE(&_free_list, item, _link_entry);
121             delete item;
122             _count--;
123         }
124     };
125 
126     // �����Զ���ij�ʱʱ��
127     void SetExpiredTime(uint64_t expired) {
128         _expired = expired;
129     };
130 
131 private:
132 
133     List            _free_list;      ///< ��������
134     uint64_t        _expired;        ///< ��ʱʱ��
135     uint32_t        _count;          ///< Ԫ�ؼ���
136 };
137 
138 
139 
140 /**
141  * @brief ÿ��IO����һ���������
142  */
143 class CNetHandler : public HashKey
144 {
145 public:
146 
147     // ���״̬����
148     enum {
149         STATE_IN_SESSION    = 0x1,
150         STATE_IN_CONNECT    = 0x2,
151         STATE_IN_SEND       = 0x4,
152         STATE_IN_RECV       = 0x8,
153         STATE_IN_IDLE       = 0x10,
154     };
155 
156     /**
157      *  @brief �ڵ�Ԫ�ص�hash�㷨, ��ȡkey��hashֵ
158      *  @return �ڵ�Ԫ�ص�hashֵ
159      */
160     virtual uint32_t HashValue();
161 
162     /**
163      *  @brief �ڵ�Ԫ�ص�cmp����, ͬһͰID��, ��key�Ƚ�
164      *  @return �ڵ�Ԫ�ص�hashֵ
165      */
166     virtual int HashCmp(HashKey* rhs);
167 
168     // ͬ���շ��ӿ�
169     int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
170 
171     // ��ȡ����buff��Ϣ, ��Ч��ֱ��helper����
172     void* GetRspBuff() {
173         if (_rsp_buff != NULL) {
174             return _rsp_buff->data;
175         } else {
176             return NULL;
177         }
178     };
179 
180     // ��ȡ����buff��Ϣ, ��Ч��ֱ��helper����
181     uint32_t GetRspLen() {
182         if (_rsp_buff != NULL) {
183             return _rsp_buff->data_len;
184         } else {
185             return 0;
186         }
187     };
188 
189     // ����rsp��Ϣ
190     void SetRespBuff(TSkBuffer* buff) {
191         if (_rsp_buff != NULL) {
192             delete_sk_buffer(_rsp_buff);
193             _rsp_buff = NULL;
194         }
195 
196         _rsp_buff = buff;
197     };
198 
199     // ����Э�������, Ĭ��UDP
200     void SetProtoType(MT_PROTO_TYPE type) {
201         _proto_type = type;
202     };
203 
204     // ������������, Ĭ�ϳ�����
205     void SetConnType(MT_CONN_TYPE type) {
206         _conn_type = type;
207     };
208 
209     // ����Ŀ��IP��ַ
210 	void SetDestAddress(struct sockaddr_in* dst) {
211         if (dst != NULL) {
212             memcpy(&_dest_ipv4, dst, sizeof(*dst));
213         }
214 	};
215 
216 	// ����session����session id��Ϣ, �����0
217 	void SetSessionId(uint64_t sid) {
218         _session_id = sid;
219 	};
220 
221     // ����session�����ص�����
222     void SetSessionCallback(CHECK_SESSION_CALLBACK function) {
223         _callback = function;
224     };
225 
226     // ��ȡ�ص�������Ϣ
227     CHECK_SESSION_CALLBACK GetSessionCallback() {
228         return _callback;
229     };
230 
231 
232 public:
233 
234     // �������Ӷ���
235     void Link(CSockLink* conn);
236 
237     // �������Ӷ���
238     void Unlink();
239 
240     // ����Ҫ�IJ�����Ϣ
241     int32_t CheckParams();
242 
243     // ��ȡ����, ͬʱ�������ȴ����ӵĶ�����
244     int32_t GetConnLink();
245 
246     // ����Ҫ�IJ�����Ϣ
247     int32_t WaitConnect(uint64_t timeout);
248 
249     // ����Ҫ�IJ�����Ϣ
250     int32_t WaitSend(uint64_t timeout);
251 
252     // ����Ҫ�IJ�����Ϣ
253     int32_t WaitRecv(uint64_t timeout);
254 
255     // �����ڵȴ����Ӷ���
256     void SwitchToConn();
257 
258     // �л������Ͷ���
259     void SwitchToSend();
260 
261     // �л������ն���
262     void SwitchToRecv();
263 
264     // �л�������״̬
265     void SwitchToIdle();
266 
267     // �������Ӷ���
268     void DetachConn();
269 
270     // ע��session����
271     bool RegistSession();
272 
273     // ȡ��ע��session
274     void UnRegistSession();
275 
276     // �������͵�������
277     uint32_t SkipSendPos(uint32_t len);
278 
279     // ���÷�����
280     void SetErrNo(int32_t err) {
281         _err_no = err;
282     };
283 
284     // ��ȡ�������߳���Ϣ
285     MicroThread* GetThread() {
286         return _thread;
287     };
288 
289     // ��ȡ�����͵�ָ�������ݳ���
290     void GetSendData(void*& data, uint32_t& len) {
291         data = _req_data;
292         len  = _req_len;
293     };
294 
295     // ���ýӿ�
296     void Reset();
297 
298     // ����������
299     CNetHandler();
300     ~CNetHandler();
301 
302     // ���п�ݷ��ʵĺ궨��
303     TAILQ_ENTRY(CNetHandler)    _link_entry;
304     uint64_t                    _release_time;
305 
306 protected:
307 
308     MicroThread*        _thread;            ///< �����߳�ָ�����
309     MT_PROTO_TYPE       _proto_type;        ///< Э������
310     MT_CONN_TYPE        _conn_type;         ///< ��������
311     struct sockaddr_in  _dest_ipv4;         ///< ipv4Ŀ�ĵ�ַ
312     uint64_t            _session_id;        ///< �ỰID
313     CHECK_SESSION_CALLBACK _callback;       ///< �Ự��ȡ�ص�����
314     uint32_t            _state_flags;       ///< �ڲ�״̬�ֶ�
315     int32_t             _err_no;            ///< ��������Ϣ
316     void*               _conn_ptr;          ///< socket ��·ָ��
317     uint32_t            _send_pos;          ///< �ѷ��͵�posλ��
318     uint32_t            _req_len;           ///< ���������
319     void*               _req_data;          ///< �����ָ��
320     TSkBuffer*          _rsp_buff;          ///< Ӧ��buff��Ϣ
321 
322 };
323 typedef TAILQ_HEAD(__NetHandlerList, CNetHandler) TNetItemList;  ///< ��Ч��˫������
324 typedef CRecyclePool<TNetItemList, CNetHandler>   TNetItemPool;   ///< ��ʱ���յĶ����
325 
326 
327 /**
328  * @brief ��������·����
329  */
330 class CSockLink : public KqueuerObj
331 {
332 public:
333 
334     // ���״̬����
335     enum {
336         LINK_CONNECTING     = 0x1,
337         LINK_CONNECTED      = 0x2,
338     };
339 
340     // ״̬���ж���
341     enum {
342         LINK_IDLE_LIST      = 1,
343         LINK_CONN_LIST      = 2,
344         LINK_SEND_LIST      = 3,
345         LINK_RECV_LIST      = 4,
346     };
347 
348     // ������socket���
349     int32_t CreateSock();
350 
351     // �ر���·�ľ��
352     void Close();
353 
354     // �������ӹ���
355     bool Connect();
356     bool Connected() {
357         return (_state & LINK_CONNECTED);
358     }
359 
360     // �쳣��ֹ�Ĵ�����
361     void Destroy();
362 
363     // ��ȡ��������
364     TNetItemList* GetItemList(int32_t type);
365 
366     // ��������Ϣ
367     void AppendToList(int32_t type, CNetHandler* item);
368 
369     // ��������Ϣ
370     void RemoveFromList(int32_t type, CNetHandler* item);
371 
372     // ��ȡĿ��ip��Ϣ
373     struct sockaddr_in* GetDestAddr(struct sockaddr_in* addr);
374 
375     // �������ӹ���
376     int32_t SendData(void* data, uint32_t len);
377 
378     // udp��������
379     int32_t SendCacheUdp(void* data, uint32_t len);
380 
381     // tcp��������
382     int32_t SendCacheTcp(void* data, uint32_t len);
383 
384     // ���Խ��ո�������ݵ���ʱbuff
385     void ExtendRecvRsp();
386 
387     // ���ݷַ��������
388     int32_t RecvDispath();
389 
390     // ���߻ص�����, ���ȴ��Ŷӵȴ��л�ȡ, ���ݴӸ��ڵ��ȡ
391     CHECK_SESSION_CALLBACK GetSessionCallback();
392 
393     // TCP����������������ַ�
394     int32_t DispathTcp();
395 
396     // UDP����������������ַ�
397     int32_t DispathUdp();
398 
399     // ��ѯ����sessionid������session��Ϣ
400     CNetHandler* FindSession(uint64_t sid);
401 
402     /**
403      *  @brief �ɶ��¼�֪ͨ�ӿ�, ����֪ͨ������ܻ��ƻ�����, ���÷���ֵ����
404      *  @return 0 ��fd�ɼ������������¼�; !=0 ��fd�������ص�����
405      */
406     virtual int InputNotify();
407 
408     /**
409      *  @brief ��д�¼�֪ͨ�ӿ�, ����֪ͨ������ܻ��ƻ�����, ���÷���ֵ����
410      *  @return 0 ��fd�ɼ������������¼�; !=0 ��fd�������ص�����
411      */
412     virtual int OutputNotify();
413 
414     /**
415      *  @brief �쳣֪ͨ�ӿ�
416      *  @return ���Է���ֵ, ���������¼�����
417      */
418     virtual int HangupNotify();
419 
420 
421     // ��������������
422     CSockLink();
423     ~CSockLink();
424 
425     // �����ó�ʼ���߼�
426     void Reset();
427 
428     // ֪ͨ�����߳�
429     void NotifyThread(CNetHandler* item, int32_t result);
430 
431     // ֪ͨ�����߳�
432     void NotifyAll(int32_t result);
433 
434     // ����Э������, ����buff�ص�ָ��
435     void SetProtoType(MT_PROTO_TYPE type);
436 
437     // �����ϼ�ָ����Ϣ
438     void SetParentsPtr(void* ptr) {
439         _parents = ptr;
440     };
441 
442     // ��ȡ�ϼ��ڵ�ָ��
443     void* GetParentsPtr() {
444         return _parents;
445     };
446 
447     // ��ȡ�ϴεķ���ʱ��
448     uint64_t GetLastAccess() {
449         return _last_access;
450     };
451 
452 
453 
454 public:
455 
456     // ���п�ݷ��ʵĺ궨��
457     TAILQ_ENTRY(CSockLink) _link_entry;
458     uint64_t               _release_time;
459 
460 private:
461 
462     TNetItemList        _wait_connect;
463     TNetItemList        _wait_send;
464     TNetItemList        _wait_recv;
465     TNetItemList        _idle_list;
466     MT_PROTO_TYPE       _proto_type;
467     int32_t             _errno;
468     uint32_t            _state;
469     uint64_t            _last_access;
470     TRWCache            _recv_cache;
471     TSkBuffer*          _rsp_buff;
472     void*               _parents;
473 };
474 typedef TAILQ_HEAD(__SocklinkList, CSockLink) TLinkList;  ///< ��Ч��˫������
475 typedef CRecyclePool<TLinkList, CSockLink>    TLinkPool;   ///< ��ʱ���յĶ����
476 
477 
478 class CDestLinks : public CTimerNotify, public HashKey
479 {
480 public:
481 
482     // ���캯��
483     CDestLinks();
484 
485     // ��������
486     ~CDestLinks();
487 
488     // ���ø��õĽӿں���
489     void Reset();
490 
491     // ������ʱ��
492     void StartTimer();
493 
494     // ��ȡһ������link, ��ʱ����ѯ
495     CSockLink* GetSockLink();
496 
497     // �ͷ�һ������link
498     void FreeSockLink(CSockLink* sock);
499 
500     // ��ȡЭ������
501     MT_PROTO_TYPE GetProtoType() {
502         return _proto_type;
503     };
504 
505     // ��ȡ��������
506     MT_CONN_TYPE GetConnType() {
507         return _conn_type;
508     };
509 
510 
511     // ���ùؼ���Ϣ
512     void SetKeyInfo(uint32_t ipv4, uint16_t port, MT_PROTO_TYPE proto, MT_CONN_TYPE conn) {
513         _addr_ipv4  = ipv4;
514         _net_port   = port;
515         _proto_type = proto;
516         _conn_type  = conn;
517     };
518 
519     // ����KEY��Ϣ
520     void CopyKeyInfo(CDestLinks* key) {
521         _addr_ipv4  = key->_addr_ipv4;
522         _net_port   = key->_net_port;
523         _proto_type = key->_proto_type;
524         _conn_type  = key->_conn_type;
525     };
526 
527     // ��ȡIP port��Ϣ
528     void GetDestIP(uint32_t& ip, uint16_t& port) {
529         ip = _addr_ipv4;
530         port = _net_port;
531     };
532 
533     /**
534      * @brief ��ʱ֪ͨ����, ��������·, ���������·����
535      */
536     virtual void timer_notify();
537 
538     /**
539      *  @brief �ڵ�Ԫ�ص�hash�㷨, ��ȡkey��hashֵ
540      *  @return �ڵ�Ԫ�ص�hashֵ
541      */
542     virtual uint32_t HashValue() {
543         return _addr_ipv4 ^ (((uint32_t)_net_port << 16) | (_proto_type << 8) | _conn_type);
544     };
545 
546     /**
547      *  @brief �ڵ�Ԫ�ص�cmp����, ͬһͰID��, ��key�Ƚ�
548      *  @return �ڵ�Ԫ�ص�hashֵ
549      */
550     virtual int HashCmp(HashKey* rhs) {
551         CDestLinks* data = (CDestLinks*)(rhs);
552         if (!data) {
553             return -1;
554         }
555         if (this->_addr_ipv4 != data->_addr_ipv4) {
556             return (this->_addr_ipv4 > data->_addr_ipv4) ?  1 : -1;
557         }
558         if (this->_net_port != data->_net_port) {
559             return (this->_net_port > data->_net_port) ? 1 : -1;
560         }
561         if (this->_proto_type != data->_proto_type) {
562             return (this->_proto_type > data->_proto_type) ? 1 : -1;
563         }
564         if (this->_conn_type != data->_conn_type) {
565             return (this->_conn_type > data->_conn_type) ? 1 : -1;
566         }
567 
568         return 0;
569     };
570 
571     // ����session�����ص�����
572     void SetDefaultCallback(CHECK_SESSION_CALLBACK function) {
573         _dflt_callback = function;
574     };
575 
576     // ��ȡ�ص�������Ϣ
577     CHECK_SESSION_CALLBACK GetDefaultCallback() {
578         return _dflt_callback;
579     };
580 
581     // ���п�ݷ��ʵĺ궨��
582     TAILQ_ENTRY(CDestLinks) _link_entry;
583     uint64_t                _release_time;
584 
585 private:
586 
587     uint32_t            _timeout;       ///< idle�ij�ʱʱ��
588     uint32_t            _addr_ipv4;     ///< ip��ַ
589     uint16_t            _net_port;      ///< port ��������
590     MT_PROTO_TYPE       _proto_type;    ///< Э������
591     MT_CONN_TYPE        _conn_type;     ///< ��������
592 
593     uint32_t            _max_links;     ///< ���������
594     uint32_t            _curr_link;     ///< ��ǰ������
595     TLinkList           _sock_list;     ///< ��������
596     CHECK_SESSION_CALLBACK _dflt_callback; ///< Ĭ�ϵ�check����
597 
598 };
599 typedef TAILQ_HEAD(__DestlinkList, CDestLinks) TDestList;  ///< ��Ч��˫������
600 typedef CRecyclePool<TDestList, CDestLinks>    TDestPool;   ///< ��ʱ���յĶ����
601 
602 /**
603  * @brief ���ӹ�����ģ��
604  */
605 class CNetMgr
606 {
607 public:
608 
609     /**
610      * @brief ��Ϣbuff��ȫ�ֹ������ӿ�
611      * @return ȫ�־��ָ��
612      */
613     static CNetMgr* Instance (void);
614 
615     /**
616      * @brief ��Ϣ����ӿ�
617      */
618     static void Destroy(void);
619 
620     // ��ѯ�Ƿ��Ѿ�����ͬһ��sid�Ķ���
621     CNetHandler* FindNetItem(CNetHandler* key);
622 
623     // ע��һ��item, �Ȳ�ѯ�����, ��֤�޳�ͻ
624     void InsertNetItem(CNetHandler* item);
625 
626     // �Ƴ�һ��item����
627     void RemoveNetItem(CNetHandler* item);
628 
629     // ��ѯ����һ��Ŀ��ip��links�ڵ�
630     CDestLinks* FindCreateDest(CDestLinks* key);
631 
632     // ɾ�������е�Ŀ����·��Ϣ
633     void DeleteDestLink(CDestLinks* dst);
634 
635     // ��ѯ�Ƿ��Ѿ�����ͬһ��sid�Ķ���
636     CDestLinks* FindDestLink(CDestLinks* key);
637 
638     // ע��һ��item, �Ȳ�ѯ�����, ��֤�޳�ͻ
639     void InsertDestLink(CDestLinks* item);
640 
641     // �Ƴ�һ��item����
642     void RemoveDestLink(CDestLinks* item);
643 
644     /**
645      * @brief ��Ϣbuff����������
646      */
647     ~CNetMgr();
648 
649     /**
650      * @brief ������Դ��Ϣ
651      */
652     void RecycleObjs(uint64_t now);
653 
654     // ����һ�����������
655     CNetHandler* AllocNetItem() {
656         return _net_item_pool.AllocItem();
657     };
658 
659     // �ͷ�һ�����������
660     void FreeNetItem(CNetHandler* item) {
661         return _net_item_pool.FreeItem(item);
662     };
663 
664     // ����һ��SOCK������·
665     CSockLink* AllocSockLink() {
666         return _sock_link_pool.AllocItem();
667     };
668 
669     // �ͷ�һ��SOCK������·
670     void FreeSockLink(CSockLink* item) {
671         return _sock_link_pool.FreeItem(item);
672     };
673 
674     // ����һ��SOCK������·
675     CDestLinks* AllocDestLink() {
676         return _dest_ip_pool.AllocItem();
677     };
678 
679     // �ͷ�һ��SOCK������·
680     void FreeDestLink(CDestLinks* item) {
681         return _dest_ip_pool.FreeItem(item);
682     };
683 
684     // ��ȡudp��buff����Ϣ
685     TSkBuffMng* GetSkBuffMng(MT_PROTO_TYPE type) {
686         if (type == NET_PROTO_TCP) {
687             return &_tcp_pool;
688         } else {
689             return &_udp_pool;
690         }
691     };
692 
693 
694 private:
695     /**
696      * @brief ��Ϣbuff�Ĺ��캯��
697      */
698     CNetMgr();
699 
700     static CNetMgr *    _instance;          ///< ��������
701     HashList*           _ip_hash;           ///< Ŀ�ĵ�ַhash
702     HashList*           _session_hash;      ///< session id��hash
703     TSkBuffMng          _udp_pool;          ///< udp pool, 64K
704     TSkBuffMng          _tcp_pool;          ///< tcp pool, 4K
705     TDestPool           _dest_ip_pool;      ///< Ŀ��ip�����
706     TLinkPool           _sock_link_pool;    ///< socket pool
707     TNetItemPool        _net_item_pool;     ///< net handle pool
708 };
709 
710 
711 
712 
713 
714 }
715 
716 #endif
717 
718 
719