Loading

Paste #pvf5a5mrz

  1. #include <boost/asio.hpp>
  2. #include <boost/asio/ssl.hpp>
  3. #include <memory>
  4. #include <boost/beast/websocket/ssl.hpp>
  5.  
  6. namespace tinychat
  7. {
  8.     namespace utility
  9.     {
  10.         class tag_non_ssl_t {};
  11.         class tag_ssl_t {};
  12.  
  13.         const static tag_non_ssl_t tag_non_ssl;
  14.         const static tag_ssl_t tag_ssl;
  15.  
  16.         template<class NextLayer>
  17.         class optional_ssl_stream
  18.             : public boost::asio::ssl::stream_base
  19.         {
  20.             using stream_type = boost::asio::ssl::stream<NextLayer>;
  21.  
  22.             std::unique_ptr<stream_type> p_;
  23.             boost::asio::ssl::context* ctx_;
  24.  
  25.             NextLayer *next_layer_;
  26.  
  27.             class EmplacableNextLayer {
  28.             public:
  29.                 NextLayer next_layer__;
  30.                 template<class Arg>
  31.                 EmplacableNextLayer(Arg&& arg)
  32.                     :next_layer__(std::forward<Arg>(arg))
  33.                 {}
  34.  
  35.                 EmplacableNextLayer(EmplacableNextLayer&& other)
  36.                     :next_layer__(std::move(other.next_layer__))
  37.                 {}
  38.  
  39.                 ~EmplacableNextLayer() {}
  40.             };
  41.  
  42.             std::unique_ptr<EmplacableNextLayer> next_layer_e;
  43.  
  44.         public:
  45.             /// The native handle type of the SSL stream.
  46.             using native_handle_type = typename stream_type::native_handle_type;
  47.  
  48.             /// Structure for use with deprecated impl_type.
  49.             using impl_struct = typename stream_type::impl_struct;
  50.  
  51.             /// The type of the next layer.
  52.             using next_layer_type = typename stream_type::next_layer_type;
  53.  
  54.             /// The type of the lowest layer.
  55.             using lowest_layer_type = typename stream_type::lowest_layer_type;
  56.  
  57.             /// The type of the executor associated with the object.
  58.             using executor_type = typename stream_type::executor_type;
  59.  
  60.             template<class Arg>
  61.             optional_ssl_stream(const tag_non_ssl_t &tag,
  62.                 Arg&& arg)
  63.                 : p_(), ctx_(nullptr),
  64.                 next_layer_e(new EmplacableNextLayer{ std::forward<Arg>(arg) })
  65.             {
  66.                 next_layer_ = &(next_layer_e->next_layer__);
  67.             }
  68.  
  69.             template<class Arg>
  70.             optional_ssl_stream(const tag_ssl_t &tag,
  71.                 Arg&& arg,
  72.                 boost::asio::ssl::context& ctx)
  73.                 : p_(new stream_type{
  74.                     std::forward<Arg>(arg), ctx })
  75.                     , ctx_(&ctx), next_layer_()
  76.             {
  77.             }
  78.  
  79.             optional_ssl_stream(optional_ssl_stream&& other)
  80.                 : p_(std::move(other.p_))
  81.                 , ctx_(other.ctx_), next_layer_(other.next_layer_),
  82.                 next_layer_e(std::move(other.next_layer_e))
  83.             {
  84.             }
  85.  
  86.             optional_ssl_stream& operator=(optional_ssl_stream&& other)
  87.             {
  88.                 p_ = std::move(other.p_);
  89.                 ctx_ = other.ctx_;
  90.                 next_layer_ = other.next_layer_;
  91.                 next_layer_e = std::move(other.next_layer_e);
  92.                 return *this;
  93.             }
  94.  
  95.             executor_type get_executor() noexcept
  96.             {
  97.                 if (p_)
  98.                 {
  99.                     return p_->get_executor();
  100.                 }
  101.                 else {
  102.                     return next_layer_->get_executor();
  103.                 }
  104.             }
  105.  
  106.             native_handle_type native_handle()
  107.             {
  108.                 if (p_)
  109.                 {
  110.                     return p_->native_handle();
  111.                 }
  112.                 else {
  113.                     throw worded_exception(
  114.                         "error : calling native_handle of a transparent optional_ssl_stream");
  115.                 }
  116.             }
  117.  
  118.             next_layer_type const&
  119.                 next_layer() const
  120.             {
  121.                 if (p_)
  122.                 {
  123.                     return p_->next_layer();
  124.                 }
  125.                 else {
  126.                     return *next_layer_;
  127.                 }
  128.             }
  129.  
  130.             next_layer_type&
  131.                 next_layer()
  132.             {
  133.                 if (p_)
  134.                 {
  135.                     return p_->next_layer();
  136.                 }
  137.                 else {
  138.                     return *next_layer_;
  139.                 }
  140.             }
  141.  
  142.             template <typename lowest_layer_type>
  143.             lowest_layer_type&
  144.                 lowest_layer()
  145.             {
  146.                 if (p_)
  147.                 {
  148.                     return p_->lowest_layer();
  149.                 }
  150.                 else {
  151.                     return next_layer_->lowest_layer();
  152.                 }
  153.             }
  154.  
  155.             lowest_layer_type const&
  156.                 lowest_layer() const
  157.             {
  158.                 if (p_)
  159.                 {
  160.                     return p_->lowest_layer();
  161.                 }
  162.                 else {
  163.                     return next_layer_->lowest_layer();
  164.                 }
  165.             }
  166.  
  167.             void
  168.                 set_verify_mode(boost::asio::ssl::verify_mode v)
  169.             {
  170.                 if (p_)
  171.                 {
  172.                     p_->set_verify_mode(v);
  173.                 }
  174.                 else {
  175.                     throw worded_exception(
  176.                         "error : calling set_verify_mode of a transparent optional_ssl_stream");
  177.                 }
  178.             }
  179.  
  180.             boost::system::error_code
  181.                 set_verify_mode(boost::asio::ssl::verify_mode v,
  182.                     boost::system::error_code& ec)
  183.             {
  184.                 if (p_)
  185.                 {
  186.                     p_->set_verify_mode(v, ec);
  187.                 }
  188.                 else {
  189.                     throw worded_exception(
  190.                         "error : calling set_verify_mode of a transparent optional_ssl_stream");
  191.                 }
  192.             }
  193.  
  194.             void
  195.                 set_verify_depth(int depth)
  196.             {
  197.                 if (p_)
  198.                 {
  199.                     p_->set_verify_depth(depth);
  200.                 }
  201.                 else {
  202.                     throw worded_exception(
  203.                         "error : calling set_verify_depth of a transparent optional_ssl_stream");
  204.                 }
  205.             }
  206.  
  207.             boost::system::error_code
  208.                 set_verify_depth(
  209.                     int depth, boost::system::error_code& ec)
  210.             {
  211.                 if (p_)
  212.                 {
  213.                     p_->set_verify_depth(depth, ec);
  214.                 }
  215.                 else {
  216.                     throw worded_exception(
  217.                         "error : calling set_verify_depth of a transparent optional_ssl_stream");
  218.                 }
  219.             }
  220.  
  221.             template<class VerifyCallback>
  222.             void
  223.                 set_verify_callback(VerifyCallback callback)
  224.             {
  225.                 if (p_)
  226.                 {
  227.                     p_->set_verify_callback(callback);
  228.                 }
  229.                 else {
  230.                     throw worded_exception(
  231.                         "error : calling set_verify_callback of a transparent optional_ssl_stream");
  232.                 }
  233.             }
  234.  
  235.             template<class VerifyCallback>
  236.             boost::system::error_code
  237.                 set_verify_callback(VerifyCallback callback,
  238.                     boost::system::error_code& ec)
  239.             {
  240.                 if (p_)
  241.                 {
  242.                     p_->set_verify_callback(callback, ec);
  243.                 }
  244.                 else {
  245.                     throw worded_exception(
  246.                         "error : calling set_verify_callback of a transparent optional_ssl_stream");
  247.                 }
  248.             }
  249.  
  250.             void
  251.                 handshake(handshake_type type)
  252.             {
  253.                 if (p_)
  254.                 {
  255.                     p_->handshake(type);
  256.                 }
  257.                 else {
  258.                     throw worded_exception(
  259.                         "error : calling handshake of a transparent optional_ssl_stream");
  260.                 }
  261.             }
  262.  
  263.             boost::system::error_code
  264.                 handshake(handshake_type type,
  265.                     boost::system::error_code& ec)
  266.             {
  267.                 if (p_)
  268.                 {
  269.                     p_->handshake(type, ec);
  270.                 }
  271.                 else {
  272.                     throw worded_exception(
  273.                         "error : calling handshake of a transparent optional_ssl_stream");
  274.                 }
  275.             }
  276.  
  277.             template<class ConstBufferSequence>
  278.             void
  279.                 handshake(
  280.                     handshake_type type, ConstBufferSequence const& buffers)
  281.             {
  282.                 if (p_)
  283.                 {
  284.                     p_->handshake(type, buffers);
  285.                 }
  286.                 else {
  287.                     throw worded_exception(
  288.                         "error : calling handshake of a transparent optional_ssl_stream");
  289.                 }
  290.             }
  291.  
  292.             template<class ConstBufferSequence>
  293.             boost::system::error_code
  294.                 handshake(handshake_type type,
  295.                     ConstBufferSequence const& buffers,
  296.                     boost::system::error_code& ec)
  297.             {
  298.                 if (p_)
  299.                 {
  300.                     p_->handshake(type, buffers, ec);
  301.                 }
  302.                 else {
  303.                     throw worded_exception(
  304.                         "error : calling handshake of a transparent optional_ssl_stream");
  305.                 }
  306.             }
  307.  
  308.             template<class HandshakeHandler>
  309.             BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
  310.                 void(boost::system::error_code))
  311.                 async_handshake(handshake_type type,
  312.                     BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
  313.             {
  314.                 if (p_)
  315.                 {
  316.                     return p_->async_handshake(type,
  317.                         BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
  318.                 }
  319.                 else {
  320.                     throw worded_exception(
  321.                         "error : calling handshake of a transparent optional_ssl_stream");
  322.                 }
  323.             }
  324.  
  325.             template<class ConstBufferSequence, class BufferedHandshakeHandler>
  326.             BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
  327.                 void(boost::system::error_code, std::size_t))
  328.                 async_handshake(handshake_type type, ConstBufferSequence const& buffers,
  329.                     BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
  330.             {
  331.                 if (p_)
  332.                 {
  333.                     return p_->async_handshake(type, buffers,
  334.                         BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
  335.                 }
  336.                 else {
  337.                     throw worded_exception(
  338.                         "error : calling handshake of a transparent optional_ssl_stream");
  339.                 }
  340.             }
  341.  
  342.             void
  343.                 shutdown()
  344.             {
  345.                 if (p_)
  346.                 {
  347.                     p_->shutdown();
  348.                 }
  349.                 else {
  350.                     next_layer_->shutdown();
  351.                 }
  352.             }
  353.  
  354.             boost::system::error_code
  355.                 shutdown(boost::system::error_code& ec)
  356.             {
  357.                 if (p_)
  358.                 {
  359.                     return p_->shutdown(ec);
  360.                 }
  361.                 else {
  362.                     return next_layer_->shutdown(ec);
  363.                 }
  364.             }
  365.  
  366.             template<class ShutdownHandler>
  367.             BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
  368.                 void(boost::system::error_code))
  369.                 async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
  370.             {
  371.                 if (p_)
  372.                 {
  373.                     return p_->async_shutdown(
  374.                         BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
  375.                 }
  376.                 else {
  377.                     return next_layer_->async_shutdown(
  378.                         BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
  379.                 }
  380.             }
  381.  
  382.             template<class ConstBufferSequence>
  383.             std::size_t
  384.                 write_some(ConstBufferSequence const& buffers)
  385.             {
  386.                 if (p_)
  387.                 {
  388.                     return p_->write_some(buffers);
  389.                 }
  390.                 else {
  391.                     return next_layer_->write_some(buffers);
  392.                 }
  393.             }
  394.  
  395.             template<class ConstBufferSequence>
  396.             std::size_t
  397.                 write_some(ConstBufferSequence const& buffers,
  398.                     boost::system::error_code& ec)
  399.             {
  400.                 if (p_)
  401.                 {
  402.                     return p_->write_some(buffers, ec);
  403.                 }
  404.                 else {
  405.                     return next_layer_->write_some(buffers, ec);
  406.                 }
  407.             }
  408.  
  409.             template<class ConstBufferSequence, class WriteHandler>
  410.             BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  411.                 void(boost::system::error_code, std::size_t))
  412.                 async_write_some(ConstBufferSequence const& buffers,
  413.                     BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  414.             {
  415.                 if (p_)
  416.                 {
  417.                     return p_->async_write_some(buffers,
  418.                         BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  419.                 }
  420.                 else {
  421.                     return next_layer_->async_write_some(buffers,
  422.                         BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
  423.                 }
  424.             }
  425.  
  426.             template<class MutableBufferSequence>
  427.             std::size_t
  428.                 read_some(MutableBufferSequence const& buffers)
  429.             {
  430.                 if (p_)
  431.                 {
  432.                     return p_->read_some(buffers);
  433.                 }
  434.                 else {
  435.                     return next_layer_->read_some(buffers);
  436.                 }
  437.             }
  438.  
  439.             template<class MutableBufferSequence>
  440.             std::size_t
  441.                 read_some(MutableBufferSequence const& buffers,
  442.                     boost::system::error_code& ec)
  443.             {
  444.                 if (p_)
  445.                 {
  446.                     return p_->read_some(buffers, ec);
  447.                 }
  448.                 else {
  449.                     return next_layer_->read_some(buffers, ec);
  450.                 }
  451.             }
  452.  
  453.             template<class MutableBufferSequence, class ReadHandler>
  454.             BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  455.                 void(boost::system::error_code, std::size_t))
  456.                 async_read_some(MutableBufferSequence const& buffers,
  457.                     BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  458.             {
  459.                 if (p_)
  460.                 {
  461.                     return p_->async_read_some(buffers,
  462.                         BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  463.                 }
  464.                 else {
  465.                     return next_layer_->async_read_some(buffers,
  466.                         BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  467.                 }
  468.             }
  469.  
  470.             template<class SyncStream>
  471.             friend
  472.                 void
  473.                 teardown(boost::beast::websocket::role_type,
  474.                     optional_ssl_stream<SyncStream>& stream,
  475.                     boost::system::error_code& ec);
  476.  
  477.             template<class AsyncStream, class TeardownHandler>
  478.             friend
  479.                 void
  480.                 async_teardown(boost::beast::websocket::role_type,
  481.                     optional_ssl_stream<AsyncStream>& stream, TeardownHandler&& handler);
  482.         };
  483.  
  484.         // These hooks are used to inform boost::beast::websocket::stream on
  485.         // how to tear down the connection as part of the WebSocket
  486.         // protocol specifications
  487.  
  488.         template<class SyncStream>
  489.         inline
  490.             void
  491.             teardown(
  492.                 boost::beast::websocket::role_type role,
  493.                 optional_ssl_stream<SyncStream>& stream,
  494.                 boost::system::error_code& ec)
  495.         {
  496.             // Just forward it to the wrapped ssl::stream
  497.             using boost::beast::websocket::teardown;
  498.             if (stream.p_)
  499.             {
  500.                 teardown(role, *stream.p_, ec);
  501.             }
  502.             else {
  503.                 teardown(role, *stream.next_layer_, ec);
  504.             }
  505.         }
  506.  
  507.         template<class AsyncStream, class TeardownHandler>
  508.         inline
  509.             void
  510.             async_teardown(
  511.                 boost::beast::websocket::role_type role,
  512.                 optional_ssl_stream<AsyncStream>& stream,
  513.                 TeardownHandler&& handler)
  514.         {
  515.             // Just forward it to the wrapped ssl::stream
  516.             using boost::beast::websocket::async_teardown;
  517.             if (stream.p_)
  518.             {
  519.                 async_teardown(role,
  520.                     *stream.p_, std::forward<TeardownHandler>(handler));
  521.             }
  522.             else {
  523.                 async_teardown(role,
  524.                     *stream.next_layer_, std::forward<TeardownHandler>(handler));
  525.             }
  526.         }
  527.  
  528.     }
  529. }