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