I am a new self taught C++ programmer trying to learn a bit more.
I am attempting to modify the boost ssl example located here:
https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/example/cpp11/ssl/server.cpp
I am using g++ compiler and c++20
there is a lambda function in the do_accept() method in the server class:
acceptor_.async_accept(
[this](const boost::system::error_code& error, tcp::socket socket)
{
if (!error)
{
std::make_shared<session>(
boost::asio::ssl::stream<tcp::socket>(
std::move(socket), context_))->start();
}
do_accept();
});
I would like to change the lambda function to a class method.
My method is:
void server::acceptHandler(const boost::system::error_code& error, tcp::socket socket) {
...
}
When I try to substitute to this: acceptor_.async_accept(boost::bind(&server::acceptHandler, this, boost::asio::placehoders::error, tcp::socket));
I get "error: expected primary-expression before ')' token" on the ')' after tcp::socket
I also tried: acceptor_.async_accept(boost::bind(&server::acceptHandler, this, boost::asio::placehoders::error, boost::placeholders:_2))
I get: "error: use of deleted function 'boost::asio::basic_stream_socket<Protocol,Executor>::basic_stream_socket<Protocol,Executor&>) [with Protocol = boost::asio::ip::tcp; Executor = boost::asio::any_io_executor'
What is the proper method of changing a lambda function to a method function.
Here is the full code for the accept handler:
void acceptHandler(const boost::system::error_code& error, tcp::socket socket) {
if (!error)
{
std::make_shared<session>(
boost::asio::ssl::stream<tcp::socket>(
std::move(socket), context_))->start();
}
do_accept();
}
I get the "error: use of deleted function..." on the std::move(socket)
I imagined some of the surrounding code:
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
namespace asio = boost::asio;
namespace ssl = asio::ssl;
using asio::ip::tcp;
struct session : std::enable_shared_from_this<session> {
session(boost::asio::ssl::stream<tcp::socket> s) : stream_(std::move(s)) {}
void start() {
std::cout << "Accepted connection from " << stream_.lowest_layer().remote_endpoint() << "\n";
stream_.async_handshake(ssl::stream_base::server,
[self = shared_from_this()](boost::system::error_code ec) {
if (!ec) {
self->do_read();
} else {
std::cerr << "Handshake failed: " << ec.message() << "\n";
}
});
}
private:
void do_read() {
stream_.async_read_some(
asio::buffer(data_),
[self = shared_from_this()](boost::system::error_code ec, size_t bytes_transferred) {
if (!ec) {
std::cout << "Received " << bytes_transferred << " bytes\n";
self->do_read();
} else {
std::cerr << "Read failed: " << ec.message() << "\n";
}
});
}
ssl::stream<tcp::socket> stream_;
std::array<char, 1024> data_;
};
struct Server {
Server(asio::any_io_executor ex, uint16_t port) : acc_(ex, {{}, port}) {
// TODO load certificate and private key
do_accept();
}
private:
void do_accept() {
acc_.async_accept([this](boost::system::error_code const& error, tcp::socket socket) {
if (!error) {
std::make_shared<session>(ssl::stream<tcp::socket>(std::move(socket), context_))->start();
}
do_accept();
});
}
tcp::acceptor acc_;
ssl::context context_{ssl::context::tlsv12};
};
int main() {
asio::thread_pool ctx;
Server srv(ctx.get_executor(), 8989);
ctx.join();
}
Because I left the certificate as an exercise for the reader, this is about what it can do:
Now, I don't know why you want it, but you can:
void do_accept() {
acc_.async_accept(std::bind( //
&Server::on_accept, this, std::placeholders::_1, std::placeholders::_2));
}
void on_accept(boost::system::error_code const& error, tcp::socket socket) {
if (!error) {
std::make_shared<session>(ssl::stream<tcp::socket>(std::move(socket), context_))->start();
}
do_accept();
}
Note that tcp::socket
is a type, not a placeholder.