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