xref: /f-stack/app/micro_thread/mt_net.h (revision 9bd490e8)
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  **/
23 
24 #ifndef __MT_NET_H__
25 #define __MT_NET_H__
26 
27 #include "micro_thread.h"
28 #include "hash_list.h"
29 #include "mt_api.h"
30 #include "mt_cache.h"
31 #include "mt_net_api.h"
32 
33 namespace NS_MICRO_THREAD {
34 
35 enum MT_CONN_TYPE
36 {
37     TYPE_CONN_UNKNOWN   = 0,
38     TYPE_CONN_SHORT     = 0x1,
39     TYPE_CONN_POOL      = 0x2,
40     TYPE_CONN_SESSION   = 0x4,
41     TYPE_CONN_SENDONLY  = 0x8,
42 };
43 
44 class CSockLink;
45 
46 template <typename List, typename Type>
47 class CRecyclePool
48 {
49 public:
50 
51     CRecyclePool() {
52         _expired = 60 * 1000;
53         _count = 0;
54         TAILQ_INIT(&_free_list);
55     };
56 
57     ~CRecyclePool() {
58         Type* item = NULL;
59         Type* tmp = NULL;
60         TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
61         {
62             TAILQ_REMOVE(&_free_list, item, _link_entry);
63             delete item;
64         }
65         _count = 0;
66     };
67 
68     Type* AllocItem() {
69         Type* item = TAILQ_FIRST(&_free_list);
70         if (item != NULL)
71         {
72             TAILQ_REMOVE(&_free_list, item, _link_entry);
73             _count--;
74             return item;
75         }
76 
77         item = new Type();
78         if (NULL == item)
79         {
80             return NULL;
81         }
82 
83         return item;
84     };
85 
86     void FreeItem(Type* obj) {
87         //obj->Reset();
88         TAILQ_INSERT_TAIL(&_free_list, obj, _link_entry);
89         obj->_release_time = mt_time_ms();
90         _count++;
91     };
92 
93     void RecycleItem(uint64_t now) {
94         Type* item = NULL;
95         Type* tmp = NULL;
96         TAILQ_FOREACH_SAFE(item, &_free_list, _link_entry, tmp)
97         {
98             if ((now - item->_release_time) < _expired) {
99                 break;
100             }
101 
102             TAILQ_REMOVE(&_free_list, item, _link_entry);
103             delete item;
104             _count--;
105         }
106     };
107 
108     void SetExpiredTime(uint64_t expired) {
109         _expired = expired;
110     };
111 
112 private:
113 
114     List            _free_list;
115     uint64_t        _expired;
116     uint32_t        _count;
117 };
118 
119 class CNetHandler : public HashKey
120 {
121 public:
122 
123     enum {
124         STATE_IN_SESSION    = 0x1,
125         STATE_IN_CONNECT    = 0x2,
126         STATE_IN_SEND       = 0x4,
127         STATE_IN_RECV       = 0x8,
128         STATE_IN_IDLE       = 0x10,
129     };
130 
131     virtual uint32_t HashValue();
132 
133     virtual int HashCmp(HashKey* rhs);
134 
135     int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
136 
137     void* GetRspBuff() {
138         if (_rsp_buff != NULL) {
139             return _rsp_buff->data;
140         } else {
141             return NULL;
142         }
143     };
144 
145     uint32_t GetRspLen() {
146         if (_rsp_buff != NULL) {
147             return _rsp_buff->data_len;
148         } else {
149             return 0;
150         }
151     };
152 
153     void SetRespBuff(TSkBuffer* buff) {
154         if (_rsp_buff != NULL) {
155             delete_sk_buffer(_rsp_buff);
156             _rsp_buff = NULL;
157         }
158 
159         _rsp_buff = buff;
160     };
161 
162     void SetProtoType(MT_PROTO_TYPE type) {
163         _proto_type = type;
164     };
165 
166     void SetConnType(MT_CONN_TYPE type) {
167         _conn_type = type;
168     };
169 
170 	void SetDestAddress(struct sockaddr_in* dst) {
171         if (dst != NULL) {
172             memcpy(&_dest_ipv4, dst, sizeof(*dst));
173         }
174 	};
175 
176 	void SetSessionId(uint64_t sid) {
177         _session_id = sid;
178 	};
179 
180     void SetSessionCallback(CHECK_SESSION_CALLBACK function) {
181         _callback = function;
182     };
183 
184     CHECK_SESSION_CALLBACK GetSessionCallback() {
185         return _callback;
186     };
187 
188 
189 public:
190 
191     void Link(CSockLink* conn);
192 
193     void Unlink();
194 
195     int32_t CheckParams();
196 
197     int32_t GetConnLink();
198 
199     int32_t WaitConnect(uint64_t timeout);
200 
201     int32_t WaitSend(uint64_t timeout);
202 
203     int32_t WaitRecv(uint64_t timeout);
204 
205     void SwitchToConn();
206 
207     void SwitchToSend();
208 
209     void SwitchToRecv();
210 
211     void SwitchToIdle();
212 
213     void DetachConn();
214 
215     bool RegistSession();
216 
217     void UnRegistSession();
218 
219     uint32_t SkipSendPos(uint32_t len);
220 
221     void SetErrNo(int32_t err) {
222         _err_no = err;
223     };
224 
225     MicroThread* GetThread() {
226         return _thread;
227     };
228 
229     void GetSendData(void*& data, uint32_t& len) {
230         data = _req_data;
231         len  = _req_len;
232     };
233 
234     void Reset();
235 
236     CNetHandler();
237     ~CNetHandler();
238 
239     TAILQ_ENTRY(CNetHandler)    _link_entry;
240     uint64_t                    _release_time;
241 
242 protected:
243 
244     MicroThread*        _thread;
245     MT_PROTO_TYPE       _proto_type;
246     MT_CONN_TYPE        _conn_type;
247     struct sockaddr_in  _dest_ipv4;
248     uint64_t            _session_id;
249     CHECK_SESSION_CALLBACK _callback;
250     uint32_t            _state_flags;
251     int32_t             _err_no;
252     void*               _conn_ptr;
253     uint32_t            _send_pos;
254     uint32_t            _req_len;
255     void*               _req_data;
256     TSkBuffer*          _rsp_buff;
257 
258 };
259 typedef TAILQ_HEAD(__NetHandlerList, CNetHandler) TNetItemList;
260 typedef CRecyclePool<TNetItemList, CNetHandler>   TNetItemPool;
261 
262 class CSockLink : public KqueuerObj
263 {
264 public:
265 
266     enum {
267         LINK_CONNECTING     = 0x1,
268         LINK_CONNECTED      = 0x2,
269     };
270 
271     enum {
272         LINK_IDLE_LIST      = 1,
273         LINK_CONN_LIST      = 2,
274         LINK_SEND_LIST      = 3,
275         LINK_RECV_LIST      = 4,
276     };
277 
278     int32_t CreateSock();
279 
280     void Close();
281 
282     bool Connect();
283     bool Connected() {
284         return (_state & LINK_CONNECTED);
285     }
286 
287     void Destroy();
288 
289     TNetItemList* GetItemList(int32_t type);
290 
291     void AppendToList(int32_t type, CNetHandler* item);
292 
293     void RemoveFromList(int32_t type, CNetHandler* item);
294 
295     struct sockaddr_in* GetDestAddr(struct sockaddr_in* addr);
296 
297     int32_t SendData(void* data, uint32_t len);
298 
299     int32_t SendCacheUdp(void* data, uint32_t len);
300 
301     int32_t SendCacheTcp(void* data, uint32_t len);
302 
303     void ExtendRecvRsp();
304 
305     int32_t RecvDispath();
306 
307     CHECK_SESSION_CALLBACK GetSessionCallback();
308 
309     int32_t DispathTcp();
310 
311     int32_t DispathUdp();
312 
313     CNetHandler* FindSession(uint64_t sid);
314 
315     virtual int InputNotify();
316 
317     virtual int OutputNotify();
318 
319     virtual int HangupNotify();
320 
321     CSockLink();
322     ~CSockLink();
323 
324     void Reset();
325 
326     void NotifyThread(CNetHandler* item, int32_t result);
327 
328     void NotifyAll(int32_t result);
329 
330     void SetProtoType(MT_PROTO_TYPE type);
331 
332     void SetParentsPtr(void* ptr) {
333         _parents = ptr;
334     };
335 
336     void* GetParentsPtr() {
337         return _parents;
338     };
339 
340     uint64_t GetLastAccess() {
341         return _last_access;
342     };
343 
344 public:
345 
346     TAILQ_ENTRY(CSockLink) _link_entry;
347     uint64_t               _release_time;
348 
349 private:
350 
351     TNetItemList        _wait_connect;
352     TNetItemList        _wait_send;
353     TNetItemList        _wait_recv;
354     TNetItemList        _idle_list;
355     MT_PROTO_TYPE       _proto_type;
356     int32_t             _errno;
357     uint32_t            _state;
358     uint64_t            _last_access;
359     TRWCache            _recv_cache;
360     TSkBuffer*          _rsp_buff;
361     void*               _parents;
362 };
363 typedef TAILQ_HEAD(__SocklinkList, CSockLink) TLinkList;
364 typedef CRecyclePool<TLinkList, CSockLink>    TLinkPool;
365 
366 class CDestLinks : public CTimerNotify, public HashKey
367 {
368 public:
369 
370     CDestLinks();
371     ~CDestLinks();
372 
373     void Reset();
374 
375     void StartTimer();
376 
377     CSockLink* GetSockLink();
378 
379     void FreeSockLink(CSockLink* sock);
380 
381     MT_PROTO_TYPE GetProtoType() {
382         return _proto_type;
383     };
384 
385     MT_CONN_TYPE GetConnType() {
386         return _conn_type;
387     };
388 
389     void SetKeyInfo(uint32_t ipv4, uint16_t port, MT_PROTO_TYPE proto, MT_CONN_TYPE conn) {
390         _addr_ipv4  = ipv4;
391         _net_port   = port;
392         _proto_type = proto;
393         _conn_type  = conn;
394     };
395 
396     void CopyKeyInfo(CDestLinks* key) {
397         _addr_ipv4  = key->_addr_ipv4;
398         _net_port   = key->_net_port;
399         _proto_type = key->_proto_type;
400         _conn_type  = key->_conn_type;
401     };
402 
403     void GetDestIP(uint32_t& ip, uint16_t& port) {
404         ip = _addr_ipv4;
405         port = _net_port;
406     };
407 
408     virtual void timer_notify();
409 
410     virtual uint32_t HashValue() {
411         return _addr_ipv4 ^ (((uint32_t)_net_port << 16) | (_proto_type << 8) | _conn_type);
412     };
413 
414     virtual int HashCmp(HashKey* rhs) {
415         CDestLinks* data = (CDestLinks*)(rhs);
416         if (!data) {
417             return -1;
418         }
419         if (this->_addr_ipv4 != data->_addr_ipv4) {
420             return (this->_addr_ipv4 > data->_addr_ipv4) ?  1 : -1;
421         }
422         if (this->_net_port != data->_net_port) {
423             return (this->_net_port > data->_net_port) ? 1 : -1;
424         }
425         if (this->_proto_type != data->_proto_type) {
426             return (this->_proto_type > data->_proto_type) ? 1 : -1;
427         }
428         if (this->_conn_type != data->_conn_type) {
429             return (this->_conn_type > data->_conn_type) ? 1 : -1;
430         }
431 
432         return 0;
433     };
434 
435     void SetDefaultCallback(CHECK_SESSION_CALLBACK function) {
436         _dflt_callback = function;
437     };
438 
439     CHECK_SESSION_CALLBACK GetDefaultCallback() {
440         return _dflt_callback;
441     };
442 
443     TAILQ_ENTRY(CDestLinks) _link_entry;
444     uint64_t                _release_time;
445 
446 private:
447 
448     uint32_t            _timeout;
449     uint32_t            _addr_ipv4;
450     uint16_t            _net_port;
451     MT_PROTO_TYPE       _proto_type;
452     MT_CONN_TYPE        _conn_type;
453 
454     uint32_t            _max_links;
455     uint32_t            _curr_link;
456     TLinkList           _sock_list;
457     CHECK_SESSION_CALLBACK _dflt_callback;
458 
459 };
460 typedef TAILQ_HEAD(__DestlinkList, CDestLinks) TDestList;
461 typedef CRecyclePool<TDestList, CDestLinks>    TDestPool;
462 
463 class CNetMgr
464 {
465 public:
466 
467     static CNetMgr* Instance (void);
468 
469     static void Destroy(void);
470 
471     CNetHandler* FindNetItem(CNetHandler* key);
472 
473     void InsertNetItem(CNetHandler* item);
474 
475     void RemoveNetItem(CNetHandler* item);
476 
477     CDestLinks* FindCreateDest(CDestLinks* key);
478 
479     void DeleteDestLink(CDestLinks* dst);
480 
481     CDestLinks* FindDestLink(CDestLinks* key);
482 
483     void InsertDestLink(CDestLinks* item);
484 
485     void RemoveDestLink(CDestLinks* item);
486 
487     ~CNetMgr();
488 
489     void RecycleObjs(uint64_t now);
490 
491     CNetHandler* AllocNetItem() {
492         return _net_item_pool.AllocItem();
493     };
494 
495     void FreeNetItem(CNetHandler* item) {
496         return _net_item_pool.FreeItem(item);
497     };
498 
499     CSockLink* AllocSockLink() {
500         return _sock_link_pool.AllocItem();
501     };
502 
503     void FreeSockLink(CSockLink* item) {
504         return _sock_link_pool.FreeItem(item);
505     };
506 
507     CDestLinks* AllocDestLink() {
508         return _dest_ip_pool.AllocItem();
509     };
510 
511     void FreeDestLink(CDestLinks* item) {
512         return _dest_ip_pool.FreeItem(item);
513     };
514 
515     TSkBuffMng* GetSkBuffMng(MT_PROTO_TYPE type) {
516         if (type == NET_PROTO_TCP) {
517             return &_tcp_pool;
518         } else {
519             return &_udp_pool;
520         }
521     };
522 
523 
524 private:
525     CNetMgr();
526 
527     static CNetMgr *    _instance;
528     HashList*           _ip_hash;
529     HashList*           _session_hash;
530     TSkBuffMng          _udp_pool;
531     TSkBuffMng          _tcp_pool;
532     TDestPool           _dest_ip_pool;
533     TLinkPool           _sock_link_pool;
534     TNetItemPool        _net_item_pool;
535 };
536 
537 }
538 
539 #endif
540 
541 
542