Reputation: 13
I am trying to write a https flex server, that can upgrade to websocket based on upgrade request. https class does the ssl handshake on std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> m_ptls_stream
Now I need to transfer this stream to websocket class and transform it into type
std::shared_ptr<boost::beast::websocket::stream<
boost::beast::ssl_stream<boost::beast::tcp_stream>>>
But for some reason the constructor of websocket stream doesn't accept a shared pointer, and I am unable to dereference the ssl_stream shared_ptr as I get the error that the copy constructor is deleted
Severity Code Description Project File Line Suppression State Error C2280 'boost::beast::ssl_streamboost::beast::tcp_stream::ssl_stream(const boost::beast::ssl_streamboost::beast::tcp_stream &)': attempting to reference a deleted function D:\Work\remote_pc\out\build\x64-Debug\remote_pc D:\Work\boost_1_73_0\boost\asio\impl\executor.hpp 218
void async_ws_client::add_stream(std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>>&& ptls_stream)
{
if (m_ptls_context)
{
m_p_wss_stream = std::make_shared<
boost::beast::websocket::stream<
boost::beast::ssl_stream<
boost::beast::tcp_stream>>>(std::move(*ptls_stream), *m_ptls_context);
}
}
Feels like im missing something, unable to figure it out for a couple of days. Please help..!!
Also, if I do it this way
m_p_wss_stream = std::make_shared<
boost::beast::websocket::stream<
boost::beast::ssl_stream<
boost::beast::tcp_stream>>>(std::move(ptls_stream->next_layer()),
*m_ptls_context);
The socket throws error : uninitialized when I do async_accept() on the stream after creating it.
Upvotes: 1
Views: 1161
Reputation: 13
made a stupid mistake in understanding, cannot pass tls_context into websocket::stream constructor. The following code worked
void async_ws_client::add_stream(
std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>>&& ptls_stream)
{
if (m_ptls_context)
{
m_p_wss_stream = std::make_shared<
boost::beast::websocket::stream<
boost::beast::ssl_stream<
boost::beast::tcp_stream>>>(std::move(*ptls_stream));
}
}
Upvotes: 0
Reputation: 392833
Dereferencing works. It's just that you can't construct the type you want from the arguments you pass.
Simplifying your code so it becomes readable and self-contained:
#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio.hpp>
namespace net = boost::asio;
namespace beast = boost::beast;
namespace ws = beast::websocket;
namespace ssl = net::ssl;
struct async_ws_client {
using tcp_stream = beast::tcp_stream;
using ssl_stream = beast::ssl_stream<tcp_stream>;
void add_stream(std::shared_ptr<ws::stream<tcp_stream>> ptls_stream)
{
if (m_ptls_context) {
m_p_wss_stream = std::make_shared<ws::stream<ssl_stream>>(
std::move(*ptls_stream), *m_ptls_context);
}
}
std::shared_ptr<ws::stream<tcp_stream>> m_p_tls_stream;
std::shared_ptr<ssl::context> m_ptls_context;
std::shared_ptr<ws::stream<ssl_stream>> m_p_wss_stream;
};
int main() {
}
The error novel hides the messages deep inside the shared_ptr construction forwarding machinery. However, the equivalent, much simpler code also will not compile, and for the same reason:
struct simple_async_ws_client {
using tcp_stream = beast::tcp_stream;
using ssl_stream = beast::ssl_stream<tcp_stream>;
void add_stream(ws::stream<tcp_stream>&& tls_stream) {
m_wss_stream.emplace(std::move(tls_stream), m_tls_context);
}
net::io_context m_io;
ws::stream<tcp_stream> m_tls_stream{m_io};
ssl::context m_tls_context;
std::optional<ws::stream<ssl_stream>> m_wss_stream;
};
A quick glance at your link tells me that ought to have been more like: Live On Coliru
m_wss_stream.emplace(tls_stream.next_layer().release_socket(),
m_tls_context);
Now, you can translate that back to the fully shared_ptr-overgrown version of the code:
struct async_ws_client {
using tcp_stream = beast::tcp_stream;
using ssl_stream = beast::ssl_stream<tcp_stream>;
void add_stream(std::shared_ptr<ws::stream<tcp_stream>> const& p_tls_stream)
{
if (m_p_tls_context) {
m_p_wss_stream = std::make_shared<ws::stream<ssl_stream>>(
p_tls_stream->next_layer().release_socket(), *m_p_tls_context);
}
}
std::shared_ptr<ws::stream<tcp_stream>> m_p_tls_stream;
std::shared_ptr<ssl::context> m_p_tls_context;
std::shared_ptr<ws::stream<ssl_stream>> m_p_wss_stream;
};
Note though that (ab)using shared pointers at this scale is a bit of an anti-pattern. You should probably considerunique_ptr
or optional
(for lazy-constructed types), or indeed enable_shared_from_this
for the entire class, so all members have shared ownership by extension. This is also used in the linked documentation sample.
Upvotes: 0