ws_send_op.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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_WS_SEND_OP_HPP__
  11. #define __ASIO2_WS_SEND_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/external/asio.hpp>
  20. #include <asio2/external/beast.hpp>
  21. #include <asio2/base/error.hpp>
  22. #include <asio2/http/request.hpp>
  23. #include <asio2/http/response.hpp>
  24. namespace asio2::detail
  25. {
  26. template<class derived_t, class args_t>
  27. class ws_send_op
  28. {
  29. public:
  30. /**
  31. * @brief constructor
  32. */
  33. ws_send_op() = default;
  34. /**
  35. * @brief destructor
  36. */
  37. ~ws_send_op() = default;
  38. protected:
  39. template<class Data, class Callback>
  40. inline bool _ws_send(Data& data, Callback&& callback)
  41. {
  42. derived_t& derive = static_cast<derived_t&>(*this);
  43. #if defined(_DEBUG) || defined(DEBUG)
  44. ASIO2_ASSERT(derive.post_send_counter_.load() == 0);
  45. derive.post_send_counter_++;
  46. #endif
  47. derive.ws_stream().async_write(asio::buffer(data), make_allocator(derive.wallocator(),
  48. [&derive, callback = std::forward<Callback>(callback)]
  49. (const error_code& ec, std::size_t bytes_sent) mutable
  50. {
  51. #if defined(_DEBUG) || defined(DEBUG)
  52. derive.post_send_counter_--;
  53. #endif
  54. set_last_error(ec);
  55. callback(ec, bytes_sent);
  56. if (ec)
  57. {
  58. // must stop, otherwise re-sending will cause body confusion
  59. if (derive.state_ == state_t::started)
  60. {
  61. derive._do_disconnect(ec, derive.selfptr());
  62. }
  63. }
  64. }));
  65. return true;
  66. }
  67. template<bool isRequest, class Body, class Fields, class Callback>
  68. inline bool _ws_send(http::message<isRequest, Body, Fields>& data, Callback&& callback)
  69. {
  70. derived_t& derive = static_cast<derived_t&>(*this);
  71. std::vector<asio::const_buffer> buffers;
  72. http::serializer<isRequest, Body, Fields> sr(data);
  73. sr.split(false);
  74. for (;;)
  75. {
  76. error_code ec;
  77. sr.next(ec, [&sr, &buffers](error_code&, auto const& bufs) mutable
  78. {
  79. for (auto const& buf : bufs)
  80. {
  81. buffers.emplace_back(buf.data(), buf.size());
  82. sr.consume(buf.size());
  83. }
  84. });
  85. if (ec)
  86. break;
  87. if (sr.is_done())
  88. break;
  89. }
  90. #if defined(_DEBUG) || defined(DEBUG)
  91. ASIO2_ASSERT(derive.post_send_counter_.load() == 0);
  92. derive.post_send_counter_++;
  93. #endif
  94. derive.ws_stream().async_write(buffers, make_allocator(derive.wallocator(),
  95. [&derive, callback = std::forward<Callback>(callback)]
  96. (const error_code& ec, std::size_t bytes_sent) mutable
  97. {
  98. #if defined(_DEBUG) || defined(DEBUG)
  99. derive.post_send_counter_--;
  100. #endif
  101. set_last_error(ec);
  102. callback(ec, bytes_sent);
  103. if (ec)
  104. {
  105. // must stop, otherwise re-sending will cause body confusion
  106. if (derive.state_ == state_t::started)
  107. {
  108. derive._do_disconnect(ec, derive.selfptr());
  109. }
  110. }
  111. }));
  112. return true;
  113. }
  114. template<class Body, class Fields, class Callback>
  115. inline bool _ws_send(detail::http_request_impl_t<Body, Fields>& data, Callback&& callback)
  116. {
  117. derived_t& derive = static_cast<derived_t&>(*this);
  118. return derive._ws_send(data.base(), std::forward<Callback>(callback));
  119. }
  120. template<class Body, class Fields, class Callback>
  121. inline bool _ws_send(detail::http_response_impl_t<Body, Fields>& data, Callback&& callback)
  122. {
  123. derived_t& derive = static_cast<derived_t&>(*this);
  124. return derive._ws_send(data.base(), std::forward<Callback>(callback));
  125. }
  126. protected:
  127. };
  128. }
  129. #endif // !__ASIO2_WS_SEND_OP_HPP__