hkcp.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "hkcp.h"
  2. #if WITH_KCP
  3. #include "hevent.h"
  4. #include "hlog.h"
  5. static kcp_setting_t s_kcp_setting;
  6. static int __kcp_output(const char* buf, int len, ikcpcb* ikcp, void* userdata) {
  7. // printf("ikcp_output len=%d\n", len);
  8. rudp_entry_t* rudp = (rudp_entry_t*)userdata;
  9. assert(rudp != NULL && rudp->io != NULL);
  10. int nsend = sendto(rudp->io->fd, buf, len, 0, &rudp->addr.sa, SOCKADDR_LEN(&rudp->addr));
  11. // printf("sendto nsend=%d\n", nsend);
  12. return nsend;
  13. }
  14. static void __kcp_update_timer_cb(htimer_t* timer) {
  15. rudp_entry_t* rudp = (rudp_entry_t*)timer->privdata;
  16. assert(rudp != NULL && rudp->io != NULL && rudp->kcp.ikcp != NULL);
  17. ikcp_update(rudp->kcp.ikcp, (IUINT32)(rudp->io->loop->cur_hrtime / 1000));
  18. }
  19. void kcp_release(kcp_t* kcp) {
  20. if (kcp->ikcp == NULL) return;
  21. if (kcp->update_timer) {
  22. htimer_del(kcp->update_timer);
  23. kcp->update_timer = NULL;
  24. }
  25. HV_FREE(kcp->readbuf.base);
  26. kcp->readbuf.len = 0;
  27. // printf("ikcp_release ikcp=%p\n", kcp->ikcp);
  28. ikcp_release(kcp->ikcp);
  29. kcp->ikcp = NULL;
  30. }
  31. int hio_set_kcp(hio_t* io, kcp_setting_t* setting) {
  32. io->io_type = HIO_TYPE_KCP;
  33. io->kcp_setting = setting;
  34. return 0;
  35. }
  36. kcp_t* hio_get_kcp(hio_t* io, uint32_t conv) {
  37. rudp_entry_t* rudp = hio_get_rudp(io);
  38. assert(rudp != NULL);
  39. kcp_t* kcp = &rudp->kcp;
  40. if (kcp->ikcp != NULL) return kcp;
  41. if (io->kcp_setting == NULL) {
  42. io->kcp_setting = &s_kcp_setting;
  43. }
  44. kcp_setting_t* setting = io->kcp_setting;
  45. kcp->ikcp = ikcp_create(conv, rudp);
  46. // printf("ikcp_create conv=%u ikcp=%p\n", conv, kcp->ikcp);
  47. kcp->ikcp->output = __kcp_output;
  48. kcp->conv = conv;
  49. if (setting->interval > 0) {
  50. ikcp_nodelay(kcp->ikcp, setting->nodelay, setting->interval, setting->fastresend, setting->nocwnd);
  51. }
  52. if (setting->sndwnd > 0 && setting->rcvwnd > 0) {
  53. ikcp_wndsize(kcp->ikcp, setting->sndwnd, setting->rcvwnd);
  54. }
  55. if (setting->mtu > 0) {
  56. ikcp_setmtu(kcp->ikcp, setting->mtu);
  57. }
  58. if (kcp->update_timer == NULL) {
  59. int update_interval = setting->update_interval;
  60. if (update_interval == 0) {
  61. update_interval = DEFAULT_KCP_UPDATE_INTERVAL;
  62. }
  63. kcp->update_timer = htimer_add(io->loop, __kcp_update_timer_cb, update_interval, INFINITE);
  64. kcp->update_timer->privdata = rudp;
  65. }
  66. // NOTE: alloc kcp->readbuf when hio_read_kcp
  67. return kcp;
  68. }
  69. int hio_write_kcp(hio_t* io, const void* buf, size_t len) {
  70. IUINT32 conv = io->kcp_setting ? io->kcp_setting->conv : 0;
  71. kcp_t* kcp = hio_get_kcp(io, conv);
  72. int nsend = ikcp_send(kcp->ikcp, (const char*)buf, len);
  73. // printf("ikcp_send len=%d nsend=%d\n", (int)len, nsend);
  74. if (nsend < 0) {
  75. hloge("ikcp_send error: %d", nsend);
  76. return nsend;
  77. }
  78. ikcp_update(kcp->ikcp, (IUINT32)io->loop->cur_hrtime / 1000);
  79. return len;
  80. }
  81. int hio_read_kcp (hio_t* io, void* buf, int readbytes) {
  82. IUINT32 conv = ikcp_getconv(buf);
  83. kcp_t* kcp = hio_get_kcp(io, conv);
  84. if (kcp->conv != conv) {
  85. hloge("recv invalid kcp packet!");
  86. hio_close_rudp(io, io->peeraddr);
  87. return -1;
  88. }
  89. // printf("ikcp_input len=%d\n", readbytes);
  90. ikcp_input(kcp->ikcp, (const char*)buf, readbytes);
  91. if (kcp->readbuf.base == NULL || kcp->readbuf.len == 0) {
  92. kcp->readbuf.len = DEFAULT_KCP_READ_BUFSIZE;
  93. HV_ALLOC(kcp->readbuf.base, kcp->readbuf.len);
  94. }
  95. int ret = 0;
  96. while (1) {
  97. int nrecv = ikcp_recv(kcp->ikcp, kcp->readbuf.base, kcp->readbuf.len);
  98. // printf("ikcp_recv nrecv=%d\n", nrecv);
  99. if (nrecv < 0) break;
  100. hio_read_cb(io, kcp->readbuf.base, nrecv);
  101. ret += nrecv;
  102. }
  103. return ret;
  104. }
  105. #endif