udp_recv_op.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. #ifndef __ASIO2_UDP_RECV_OP_HPP__
  11. #define __ASIO2_UDP_RECV_OP_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <memory>
  16. #include <future>
  17. #include <utility>
  18. #include <string_view>
  19. #include <asio2/base/error.hpp>
  20. #include <asio2/base/detail/ecs.hpp>
  21. namespace asio2::detail
  22. {
  23. template<class derived_t, class args_t>
  24. class udp_recv_op
  25. {
  26. public:
  27. /**
  28. * @brief constructor
  29. */
  30. udp_recv_op() noexcept {}
  31. /**
  32. * @brief destructor
  33. */
  34. ~udp_recv_op() = default;
  35. protected:
  36. template<typename C>
  37. void _udp_post_recv(std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs)
  38. {
  39. derived_t& derive = static_cast<derived_t&>(*this);
  40. ASIO2_ASSERT(derive.io_->running_in_this_thread());
  41. if (!derive.is_started())
  42. {
  43. if (derive.state_ == state_t::started)
  44. {
  45. derive._do_disconnect(asio2::get_last_error(), std::move(this_ptr));
  46. }
  47. return;
  48. }
  49. #if defined(_DEBUG) || defined(DEBUG)
  50. ASIO2_ASSERT(derive.post_recv_counter_.load() == 0);
  51. derive.post_recv_counter_++;
  52. #endif
  53. ASIO2_ASSERT(derive.reading_ == false);
  54. derive.reading_ = true;
  55. derive.socket().async_receive(derive.buffer().prepare(derive.buffer().pre_size()),
  56. make_allocator(derive.rallocator(),
  57. [&derive, this_ptr = std::move(this_ptr), ecs = std::move(ecs)]
  58. (const error_code & ec, std::size_t bytes_recvd) mutable
  59. {
  60. #if defined(_DEBUG) || defined(DEBUG)
  61. derive.post_recv_counter_--;
  62. #endif
  63. derive.reading_ = false;
  64. derive._handle_recv(ec, bytes_recvd, std::move(this_ptr), std::move(ecs));
  65. }));
  66. }
  67. template<typename C>
  68. inline void _udp_do_handle_recv(
  69. const error_code& ec, std::size_t bytes_recvd,
  70. std::shared_ptr<derived_t>& this_ptr, std::shared_ptr<ecs_t<C>>& ecs)
  71. {
  72. using condition_lowest_type = typename ecs_t<C>::condition_lowest_type;
  73. derived_t& derive = static_cast<derived_t&>(*this);
  74. if (!ec)
  75. {
  76. std::string_view data = std::string_view(static_cast<std::string_view::const_pointer>
  77. (derive.buffer().data().data()), bytes_recvd);
  78. if constexpr (!std::is_same_v<typename ecs_t<C>::condition_lowest_type, use_kcp_t>)
  79. {
  80. derive._fire_recv(this_ptr, ecs, data);
  81. }
  82. else
  83. {
  84. if (derive.kcp_stream_)
  85. {
  86. derive.kcp_stream_->_kcp_handle_recv(ec, data, this_ptr, ecs);
  87. }
  88. else
  89. {
  90. ASIO2_ASSERT(false);
  91. derive._do_disconnect(asio::error::invalid_argument, this_ptr);
  92. derive._stop_readend_timer(std::move(this_ptr));
  93. }
  94. }
  95. }
  96. else
  97. {
  98. ASIO2_LOG_DEBUG("_udp_handle_recv with error: {} {}", ec.value(), ec.message());
  99. if (ec == asio::error::eof)
  100. {
  101. ASIO2_ASSERT(bytes_recvd == 0);
  102. if (bytes_recvd)
  103. {
  104. // http://www.purecpp.cn/detail?id=2303
  105. ASIO2_LOG_INFOR("_udp_handle_recv with eof: {}", bytes_recvd);
  106. }
  107. }
  108. }
  109. }
  110. template<typename C>
  111. inline void _udp_session_handle_recv(
  112. const error_code& ec, std::size_t bytes_recvd,
  113. std::shared_ptr<derived_t>& this_ptr, std::shared_ptr<ecs_t<C>>& ecs)
  114. {
  115. derived_t& derive = static_cast<derived_t&>(*this);
  116. derive._udp_do_handle_recv(ec, bytes_recvd, this_ptr, ecs);
  117. }
  118. template<typename C>
  119. void _udp_client_handle_recv(
  120. const error_code& ec, std::size_t bytes_recvd,
  121. std::shared_ptr<derived_t>& this_ptr, std::shared_ptr<ecs_t<C>>& ecs)
  122. {
  123. derived_t& derive = static_cast<derived_t&>(*this);
  124. if (ec == asio::error::operation_aborted || ec == asio::error::connection_refused)
  125. {
  126. derive._do_disconnect(ec, this_ptr);
  127. derive._stop_readend_timer(std::move(this_ptr));
  128. return;
  129. }
  130. derive.buffer().commit(bytes_recvd);
  131. derive._udp_do_handle_recv(ec, bytes_recvd, this_ptr, ecs);
  132. derive.buffer().consume(derive.buffer().size());
  133. if (bytes_recvd == derive.buffer().pre_size())
  134. {
  135. derive.buffer().pre_size((std::min)(derive.buffer().pre_size() * 2, derive.buffer().max_size()));
  136. }
  137. derive._post_recv(this_ptr, ecs);
  138. }
  139. template<typename C>
  140. void _udp_handle_recv(
  141. const error_code& ec, std::size_t bytes_recvd,
  142. std::shared_ptr<derived_t>& this_ptr, std::shared_ptr<ecs_t<C>>& ecs)
  143. {
  144. derived_t& derive = static_cast<derived_t&>(*this);
  145. ASIO2_ASSERT(derive.io_->running_in_this_thread());
  146. set_last_error(ec);
  147. if (!derive.is_started())
  148. {
  149. if (derive.state_ == state_t::started)
  150. {
  151. derive._do_disconnect(ec, this_ptr);
  152. }
  153. derive._stop_readend_timer(std::move(this_ptr));
  154. return;
  155. }
  156. // every times recv data,we update the last alive time.
  157. if (!ec)
  158. {
  159. derive.update_alive_time();
  160. }
  161. if constexpr (args_t::is_session)
  162. {
  163. derive._udp_session_handle_recv(ec, bytes_recvd, this_ptr, ecs);
  164. }
  165. else
  166. {
  167. derive._udp_client_handle_recv(ec, bytes_recvd, this_ptr, ecs);
  168. }
  169. }
  170. protected:
  171. };
  172. }
  173. #endif // !__ASIO2_UDP_RECV_OP_HPP__