kcp_util.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. * KCP MTU , UDP PACKET MAX LENGTH 576
  11. */
  12. #ifndef __ASIO2_KCP_UTIL_HPP__
  13. #define __ASIO2_KCP_UTIL_HPP__
  14. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #pragma once
  16. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  17. #include <asio2/base/detail/push_options.hpp>
  18. #include <memory>
  19. #include <future>
  20. #include <utility>
  21. #include <string>
  22. #include <string_view>
  23. #include <chrono>
  24. #include <asio2/external/predef.h>
  25. #include <asio2/base/error.hpp>
  26. #include <asio2/base/detail/util.hpp>
  27. #include <asio2/udp/detail/ikcp.h>
  28. namespace asio2::detail::kcp
  29. {
  30. // struct psdhdr
  31. // {
  32. // unsigned long saddr;
  33. // unsigned long daddr;
  34. // char mbz;
  35. // char ptcl;
  36. // unsigned short tcpl;
  37. // };
  38. //
  39. // struct tcphdr
  40. // {
  41. // ::std::uint16_t th_sport; /* source port */
  42. // ::std::uint16_t th_dport; /* destination port */
  43. // ::std::uint32_t th_seq; /* sequence number */
  44. // ::std::uint32_t th_ack; /* acknowledgement number */
  45. //#if IWORDS_BIG_ENDIAN
  46. // ::std::uint16_t th_off : 4; /* data offset */
  47. // ::std::uint16_t th_x2 : 6; /* (unused) */
  48. //#else
  49. // ::std::uint16_t th_x2 : 6; /* (unused) */
  50. // ::std::uint16_t th_off : 4; /* data offset */
  51. //#endif
  52. // ::std::uint16_t thf_urg : 1; /* flags : Urgent Pointer Field Significant */
  53. // ::std::uint16_t thf_ack : 1; /* flags : Acknowledgement field significant */
  54. // ::std::uint16_t thf_psh : 1; /* flags : Push Function */
  55. // ::std::uint16_t thf_rst : 1; /* flags : Reset the connection */
  56. // ::std::uint16_t thf_syn : 1; /* flags : Synchronize sequence numbers */
  57. // ::std::uint16_t thf_fin : 1; /* flags : No more data from sender */
  58. // ::std::uint16_t th_win; /* window */
  59. // ::std::uint16_t th_sum; /* checksum */
  60. // ::std::uint16_t th_urp; /* urgent pointer */
  61. // ::std::uint32_t th_option : 24; /* option */
  62. // ::std::uint32_t th_padding : 8; /* padding */
  63. // };
  64. struct kcphdr
  65. {
  66. ::std::uint32_t th_seq{};
  67. ::std::uint32_t th_ack{};
  68. union
  69. {
  70. ::std::uint8_t byte{};
  71. #if ASIO2_ENDIAN_BIG_BYTE
  72. struct
  73. {
  74. ::std::uint8_t urg : 1;
  75. ::std::uint8_t ack : 1;
  76. ::std::uint8_t psh : 1;
  77. ::std::uint8_t rst : 1;
  78. ::std::uint8_t syn : 1;
  79. ::std::uint8_t fin : 1;
  80. ::std::uint8_t padding : 2;
  81. } bits;
  82. #else
  83. struct
  84. {
  85. ::std::uint8_t padding : 2;
  86. ::std::uint8_t fin : 1;
  87. ::std::uint8_t syn : 1;
  88. ::std::uint8_t rst : 1;
  89. ::std::uint8_t psh : 1;
  90. ::std::uint8_t ack : 1;
  91. ::std::uint8_t urg : 1;
  92. } bits;
  93. #endif
  94. } th_flag {};
  95. ::std::uint8_t th_padding{};
  96. ::std::uint16_t th_sum {};
  97. static constexpr ::std::size_t required_size() noexcept
  98. {
  99. return (0
  100. + sizeof(::std::uint32_t) // ::std::uint32_t th_seq;
  101. + sizeof(::std::uint32_t) // ::std::uint32_t th_ack;
  102. + sizeof(::std::uint8_t ) // ::std::uint8_t th_flag;
  103. + sizeof(::std::uint8_t ) // ::std::uint8_t th_padding;
  104. + sizeof(::std::uint16_t) // ::std::uint16_t th_sum;
  105. );
  106. }
  107. };
  108. struct kcp_deleter
  109. {
  110. inline void operator()(ikcpcb* p) const noexcept { kcp::ikcp_release(p); };
  111. };
  112. namespace
  113. {
  114. ::std::string to_string(kcphdr& hdr)
  115. {
  116. ::std::string s/*{ kcphdr::required_size(), '\0' }*/;
  117. s.resize(kcphdr::required_size());
  118. ::std::string::pointer p = s.data();
  119. detail::write(p, hdr.th_seq );
  120. detail::write(p, hdr.th_ack );
  121. detail::write(p, hdr.th_flag.byte);
  122. detail::write(p, hdr.th_padding );
  123. detail::write(p, hdr.th_sum );
  124. return s;
  125. }
  126. kcphdr to_kcphdr(::std::string_view s) noexcept
  127. {
  128. kcphdr hdr{};
  129. ::std::string_view::pointer p = const_cast<::std::string_view::pointer>(s.data());
  130. if (s.size() >= kcphdr::required_size())
  131. {
  132. hdr.th_seq = detail::read<::std::uint32_t>(p);
  133. hdr.th_ack = detail::read<::std::uint32_t>(p);
  134. hdr.th_flag.byte = detail::read<::std::uint8_t >(p);
  135. hdr.th_padding = detail::read<::std::uint8_t >(p);
  136. hdr.th_sum = detail::read<::std::uint16_t>(p);
  137. }
  138. return hdr;
  139. }
  140. unsigned short checksum(unsigned short * addr, int size) noexcept
  141. {
  142. long sum = 0;
  143. while (size > 1)
  144. {
  145. sum += *(unsigned short*)addr++;
  146. size -= 2;
  147. }
  148. if (size > 0)
  149. {
  150. ::std::uint8_t left_over[2] = { 0 };
  151. left_over[0] = static_cast<::std::uint8_t>(*addr);
  152. sum += *(unsigned short*)left_over;
  153. }
  154. while (sum >> 16)
  155. sum = (sum & 0xffff) + (sum >> 16);
  156. return static_cast<unsigned short>(~sum);
  157. }
  158. inline bool is_kcphdr_syn(::std::string_view s) noexcept
  159. {
  160. if (s.size() != kcphdr::required_size())
  161. return false;
  162. kcphdr hdr = to_kcphdr(s);
  163. if (!(
  164. !hdr.th_flag.bits.urg && !hdr.th_flag.bits.ack && !hdr.th_flag.bits.psh &&
  165. !hdr.th_flag.bits.rst && hdr.th_flag.bits.syn && !hdr.th_flag.bits.fin))
  166. return false;
  167. return (hdr.th_sum == checksum((unsigned short *)(s.data()),
  168. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum))));
  169. }
  170. inline bool is_kcphdr_synack(::std::string_view s, ::std::uint32_t seq, bool ignore_seq = false) noexcept
  171. {
  172. if (s.size() != kcphdr::required_size())
  173. return false;
  174. kcphdr hdr = to_kcphdr(s);
  175. if (!(
  176. !hdr.th_flag.bits.urg && hdr.th_flag.bits.ack && !hdr.th_flag.bits.psh &&
  177. !hdr.th_flag.bits.rst && hdr.th_flag.bits.syn && !hdr.th_flag.bits.fin))
  178. return false;
  179. if (!ignore_seq && hdr.th_ack != seq + 1)
  180. return false;
  181. return (hdr.th_sum == checksum((unsigned short *)(s.data()),
  182. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum))));
  183. }
  184. inline bool is_kcphdr_ack(::std::string_view s, ::std::uint32_t seq, bool ignore_seq = false) noexcept
  185. {
  186. if (s.size() != kcphdr::required_size())
  187. return false;
  188. kcphdr hdr = to_kcphdr(s);
  189. if (!(
  190. !hdr.th_flag.bits.urg && hdr.th_flag.bits.ack && !hdr.th_flag.bits.psh &&
  191. !hdr.th_flag.bits.rst && !hdr.th_flag.bits.syn && !hdr.th_flag.bits.fin))
  192. return false;
  193. if (!ignore_seq && hdr.th_ack != seq + 1)
  194. return false;
  195. return (hdr.th_sum == checksum((unsigned short *)(s.data()),
  196. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum))));
  197. }
  198. inline bool is_kcphdr_fin(::std::string_view s) noexcept
  199. {
  200. if (s.size() != kcphdr::required_size())
  201. return false;
  202. kcphdr hdr = to_kcphdr(s);
  203. if (!(
  204. !hdr.th_flag.bits.urg && !hdr.th_flag.bits.ack && !hdr.th_flag.bits.psh &&
  205. !hdr.th_flag.bits.rst && !hdr.th_flag.bits.syn && hdr.th_flag.bits.fin))
  206. return false;
  207. return (hdr.th_sum == checksum((unsigned short *)(s.data()),
  208. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum))));
  209. }
  210. inline kcphdr make_kcphdr_syn(::std::uint32_t conv, ::std::uint32_t seq)
  211. {
  212. kcphdr hdr{};
  213. hdr.th_seq = seq;
  214. hdr.th_ack = conv;
  215. hdr.th_flag.bits.syn = 1;
  216. ::std::string s = kcp::to_string(hdr);
  217. hdr.th_sum = checksum(reinterpret_cast<unsigned short *>(s.data()),
  218. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum)));
  219. return hdr;
  220. }
  221. inline kcphdr make_kcphdr_synack(::std::uint32_t conv, ::std::uint32_t ack)
  222. {
  223. kcphdr hdr{};
  224. hdr.th_seq = conv;
  225. hdr.th_ack = ack + 1;
  226. hdr.th_flag.bits.ack = 1;
  227. hdr.th_flag.bits.syn = 1;
  228. ::std::string s = kcp::to_string(hdr);
  229. hdr.th_sum = checksum(reinterpret_cast<unsigned short *>(s.data()),
  230. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum)));
  231. return hdr;
  232. }
  233. inline kcphdr make_kcphdr_ack(::std::uint32_t ack)
  234. {
  235. kcphdr hdr{};
  236. hdr.th_ack = ack + 1;
  237. hdr.th_flag.bits.ack = 1;
  238. ::std::string s = kcp::to_string(hdr);
  239. hdr.th_sum = checksum(reinterpret_cast<unsigned short *>(s.data()),
  240. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum)));
  241. return hdr;
  242. }
  243. inline kcphdr make_kcphdr_fin(::std::uint32_t seq)
  244. {
  245. kcphdr hdr{};
  246. hdr.th_seq = seq;
  247. hdr.th_flag.bits.fin = 1;
  248. ::std::string s = kcp::to_string(hdr);
  249. hdr.th_sum = checksum(reinterpret_cast<unsigned short *>(s.data()),
  250. static_cast<int>(kcphdr::required_size() - sizeof(kcphdr::th_sum)));
  251. return hdr;
  252. }
  253. [[maybe_unused]] void ikcp_reset(ikcpcb* kcp)
  254. {
  255. //#### ikcp_release without free
  256. assert(kcp);
  257. if (kcp) {
  258. IKCPSEG* seg;
  259. while (!iqueue_is_empty(&kcp->snd_buf)) {
  260. seg = iqueue_entry(kcp->snd_buf.next, IKCPSEG, node);
  261. iqueue_del(&seg->node);
  262. ikcp_segment_delete(kcp, seg);
  263. }
  264. while (!iqueue_is_empty(&kcp->rcv_buf)) {
  265. seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
  266. iqueue_del(&seg->node);
  267. ikcp_segment_delete(kcp, seg);
  268. }
  269. while (!iqueue_is_empty(&kcp->snd_queue)) {
  270. seg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);
  271. iqueue_del(&seg->node);
  272. ikcp_segment_delete(kcp, seg);
  273. }
  274. while (!iqueue_is_empty(&kcp->rcv_queue)) {
  275. seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node);
  276. iqueue_del(&seg->node);
  277. ikcp_segment_delete(kcp, seg);
  278. }
  279. //if (kcp->buffer) {
  280. // ikcp_free(kcp->buffer);
  281. //}
  282. if (kcp->acklist) {
  283. ikcp_free(kcp->acklist);
  284. }
  285. kcp->nrcv_buf = 0;
  286. kcp->nsnd_buf = 0;
  287. kcp->nrcv_que = 0;
  288. kcp->nsnd_que = 0;
  289. kcp->ackcount = 0;
  290. //kcp->buffer = NULL;
  291. kcp->acklist = NULL;
  292. //ikcp_free(kcp);
  293. }
  294. //#### ikcp_create without malloc
  295. if (kcp) {
  296. //ikcpcb* kcp = (ikcpcb*)ikcp_malloc(sizeof(struct IKCPCB));
  297. //if (kcp == NULL) return NULL;
  298. //kcp->conv = conv;
  299. //kcp->user = user;
  300. kcp->snd_una = 0;
  301. kcp->snd_nxt = 0;
  302. kcp->rcv_nxt = 0;
  303. kcp->ts_recent = 0;
  304. kcp->ts_lastack = 0;
  305. kcp->ts_probe = 0;
  306. kcp->probe_wait = 0;
  307. //kcp->snd_wnd = IKCP_WND_SND; // ikcp_wndsize
  308. //kcp->rcv_wnd = IKCP_WND_RCV; // ikcp_wndsize
  309. kcp->rmt_wnd = IKCP_WND_RCV;
  310. kcp->cwnd = 0;
  311. kcp->incr = 0;
  312. kcp->probe = 0;
  313. //kcp->mtu = IKCP_MTU_DEF; // ikcp_setmtu
  314. //kcp->mss = kcp->mtu - IKCP_OVERHEAD; // ikcp_setmtu
  315. kcp->stream = 0;
  316. //kcp->buffer = (char*)ikcp_malloc((kcp->mtu + IKCP_OVERHEAD) * 3);
  317. //if (kcp->buffer == NULL) {
  318. // ikcp_free(kcp);
  319. // return NULL;
  320. //}
  321. iqueue_init(&kcp->snd_queue);
  322. iqueue_init(&kcp->rcv_queue);
  323. iqueue_init(&kcp->snd_buf);
  324. iqueue_init(&kcp->rcv_buf);
  325. kcp->nrcv_buf = 0;
  326. kcp->nsnd_buf = 0;
  327. kcp->nrcv_que = 0;
  328. kcp->nsnd_que = 0;
  329. kcp->state = 0;
  330. kcp->acklist = NULL;
  331. kcp->ackblock = 0;
  332. kcp->ackcount = 0;
  333. kcp->rx_srtt = 0;
  334. kcp->rx_rttval = 0;
  335. kcp->rx_rto = IKCP_RTO_DEF;
  336. //kcp->rx_minrto = IKCP_RTO_MIN; // ikcp_nodelay
  337. kcp->current = 0;
  338. //kcp->interval = IKCP_INTERVAL; // ikcp_nodelay
  339. kcp->ts_flush = IKCP_INTERVAL;
  340. //kcp->nodelay = 0; // ikcp_nodelay
  341. kcp->updated = 0;
  342. //kcp->logmask = 0;
  343. kcp->ssthresh = IKCP_THRESH_INIT;
  344. //kcp->fastresend = 0; // ikcp_nodelay
  345. //kcp->fastlimit = IKCP_FASTACK_LIMIT;
  346. //kcp->nocwnd = 0; // ikcp_nodelay
  347. kcp->xmit = 0;
  348. //kcp->dead_link = IKCP_DEADLINK;
  349. //kcp->output = NULL;
  350. //kcp->writelog = NULL;
  351. }
  352. }
  353. }
  354. }
  355. #include <asio2/base/detail/pop_options.hpp>
  356. #endif // !__ASIO2_KCP_UTIL_HPP__