mqtt_send_connect_op.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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_SEND_CONNECT_OP_HPP__
  11. #define __ASIO2_SEND_CONNECT_OP_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <asio2/base/iopool.hpp>
  16. #include <asio2/base/define.hpp>
  17. #include <asio2/base/detail/util.hpp>
  18. #include <asio2/mqtt/message.hpp>
  19. namespace asio2::detail
  20. {
  21. template<class SocketT, class HandlerT>
  22. class mqtt_send_connect_op : public asio::coroutine
  23. {
  24. ASIO2_CLASS_FRIEND_DECLARE_BASE;
  25. ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE;
  26. ASIO2_CLASS_FRIEND_DECLARE_TCP_SERVER;
  27. ASIO2_CLASS_FRIEND_DECLARE_TCP_SESSION;
  28. ASIO2_CLASS_FRIEND_DECLARE_TCP_CLIENT;
  29. public:
  30. asio::io_context & context_;
  31. SocketT& socket_;
  32. HandlerT handler_;
  33. std::vector<char> connect_buffer{};
  34. std::unique_ptr<asio::streambuf> stream{ std::make_unique<asio::streambuf>() };
  35. template<class SKT, class H>
  36. mqtt_send_connect_op(asio::io_context& context, mqtt::message& connect_msg, SKT& skt, H&& h)
  37. : context_(context)
  38. , socket_ (skt)
  39. , handler_(std::forward<H>(h))
  40. {
  41. std::visit([this](auto& message) mutable { message.serialize(connect_buffer); }, connect_msg.base());
  42. (*this)();
  43. }
  44. template<typename = void>
  45. void operator()(error_code ec = {}, std::size_t bytes_transferred = 0)
  46. {
  47. detail::ignore_unused(ec, bytes_transferred);
  48. // There is no need to use a timeout timer because there is already has
  49. // connect_timeout_cp
  50. ASIO_CORO_REENTER(*this)
  51. {
  52. // The client connects to the server, and sends a connect message
  53. ASIO_CORO_YIELD
  54. {
  55. auto buffer = asio::buffer(connect_buffer);
  56. asio::async_write(socket_, buffer, asio::transfer_exactly(buffer.size()), std::move(*this));
  57. }
  58. if (ec)
  59. goto end;
  60. // The server send a connack message or auth message.
  61. ASIO_CORO_YIELD
  62. {
  63. asio::streambuf& strbuf = *stream;
  64. asio::async_read_until(socket_, strbuf, mqtt::mqtt_match_role, std::move(*this));
  65. }
  66. if (ec)
  67. goto end;
  68. end:
  69. handler_(ec, std::move(stream));
  70. }
  71. }
  72. };
  73. // C++17 class template argument deduction guides
  74. template<class SKT, class H>
  75. mqtt_send_connect_op(asio::io_context&, mqtt::message&, SKT&, H)->mqtt_send_connect_op<SKT, H>;
  76. }
  77. #endif // !__ASIO2_SEND_CONNECT_OP_HPP__