'ssl_socket cannot convert from '_Ty' to 'ssl::stream<asio::ip::tcp::socket>'

i was following a javid tutorial about networking and websockets with boost Asio

I've made cool progress but was stuck on securing the websocket connection using ssl

Here's what I made so far Note: I will shorten my 3000 long lines of code to something more digestible

first the includes

#include <boost/asio.hpp>
#include <boost/asio/ts/buffer.hpp>
#include <boost/asio/ts/internet.hpp>
#include <boost/asio/ssl.hpp>

using namespace boost;

namespace ssl = boost::asio::ssl;
typedef ssl::stream<asio::ip::tcp::socket> ssl_socket;

After these includes and typedefs Comes the connection class

    template<typename T>
    class connection;

    template<typename T>
    class connection : public std::enable_shared_from_this<connection<T>>
    {
    public:
        enum class owner
        {
            server,
            client
        };

    public:
        connection(owner parent, asio::io_context& asioContext, ssl_socket socket, tsqueue<owned_message<T>>& qIn)
            : m_asioContext(asioContext), m_socket(std::move(socket)), m_qMessagesIn(qIn)
        {
            m_nOwnerType = parent;

            // Construct validation check data
            if (m_nOwnerType == owner::server)
            {
                m_nHandshakeOut = uint64_t(std::chrono::system_clock::now().time_since_epoch().count());

                m_nHandshakeCheck = scramble(m_nHandshakeOut);
            }
            else
            {
                m_nHandshakeIn = 0;
                m_nHandshakeOut = 0;
            }
        }
...
protected:
        // Each connection has a unique socket to a remote 
        ssl_socket m_socket;

And i'm creating this connection class this way

bool Connect(const std::string& host, const uint16_t port)
        {
            try
            {
                ssl::context ctx(ssl::context::sslv23);
                ctx.set_default_verify_paths();

                asio::ip::tcp::resolver resolver(m_context);
                asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(host, std::to_string(port));

                m_connection = std::make_unique<connection<T>>(connection<T>::owner::client, m_context, ssl_socket(m_context, ctx), m_qMessagesIn);

                m_connection->ConnectToServer(endpoints);

                thrContext = std::thread([this]() { m_context.run(); });
            }
            catch (std::exception& e)
            {
                std::cerr << "[ASIO] Client Exception: " << e.what() << "\n";
                return false;
            }
            return true;
        }

Problem is i get an error when i try to compile my code Error says:

D:\Microsoft Visual Studio 2022\VC\Tools\MSVC\14.30.30705\include\xutility(149,56): error C2664: 'olc::net::connection<T>::connection(olc::net::connection<T>::owner,boost::asio::io_context &,ssl_socket,olc::net::tsqueue<olc::net::owned_message<T>> &)': cannot convert argument 3 from '_Ty' to 'ssl_socket'
    with
    [
        T=GameMsg
    ]
    and
    [
        _Ty=boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::any_io_executor>
    ] (compiling source file ..\..\Classes\EmptyScene.cpp)
D:\Microsoft Visual Studio 2022\VC\Tools\MSVC\14.30.30705\include\xutility(149,77): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called (compiling source file ..\..\Classes\EmptyScene.cpp)

I'm quite a noob in these C++ type things From my understanding is that it cannot convert to T But how can I that when I need T to be asio::ip::tcp::socket like in ssl_socket typedef?



Solution 1:[1]

the basic_stream_socket doesn't have a copyable constructor, it has a movable constructor instead of, which means that you must move the socket instance instead of copy it:

For example, I'm using streams that are built from a socket, which needs to receive the whole socket instead of copying it:

class wscnx : public std::enable_shared_from_this<wscnx>, public jomt::connection
    {
        using t_ws_ssl = boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::tcp_stream>>;

        std::unique_ptr<t_ws_ssl> m_wss;
          //...

    public:

        wscnx(boost::asio::ip::tcp::socket &&sck, boost::asio::ssl::context &cnx,
           //...
    };

wscnx::wscnx(boost::asio::ip::tcp::socket &&sck, boost::asio::ssl::context &cntx,
        std::shared_ptr<wsserver> server) :m_wss(new t_ws_ssl(std::move(sck), cntx)) 
{
    //...
}

In the previous sample, the semantic of the constructor wscnx is for moveable, in the case of boost::asio::ip::tcp::socket &&sck, in this way you need to use the function std::move to transfer the instance instead of copying it, so when the program gets the socket instance, you need to move it into the stream, as the sample below shows:

boost::asio::ip::tcp::socket socket

// Create the instance of the socket

// Move the instance of the socket into the constructor
std::shared_ptr<wscnx> cnx = std::make_shared<wscnx>(std::move(socket), std::ref(m_ssl_ioc), shared_from_this());

The instruction std::move(socket)move the instance of wscnx which will allocate the instance of socket into its stream m_wss that is created int he constructor with another move instruction: m_wss(new t_ws_ssl(std::move(sck), cnx)) where t_ws_ssl is an alias for boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::tcp_stream>>

I hope it could help you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jorge Omar Medra