Gibberish coming from ASIO SSL Server code after the first message -
i'm trying write ssl-based async server using boost asio example code here.
i first message , response correctly @ client side. then, send second message received fine @ server, when response sent client. comes gibberish.
i have uploaded server code pastebin. also, find below:
// file - server.h class server { public: explicit server(const std::string &address, int port, std::size_t threadpoolsize); // run io_service loop void run(); // stop server void stop(); private: //handle async accept operation void handleaccept(const boost::system::error_code &e); // number of threads in thread pool std::size_t _threadpoolsize; // io_service boost::asio::io_service _ioservice; // acceptor listen incoming connections boost::asio::ip::tcp::acceptor _acceptor; std::string get_password() { return "password"; } // ssl context boost::asio::ssl::context _context; connectionptr _connection; }; ////////////////////////////////////////////////////////////////////////// // file - server.cpp ////////////////////////////////////////////////////////////////////////// server::server(const std::string& address, int port, std::size_t threadpoolsize) : _threadpoolsize(threadpoolsize), _acceptor(_ioservice), _context(_ioservice, boost::asio::ssl::context::sslv23), _connection() { try { debug_2("starting server on port: ", port); boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); _acceptor.open(endpoint.protocol()); _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); _acceptor.bind(endpoint); _acceptor.listen(); _context.set_options( boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); _context.set_password_callback(boost::bind(&server::get_password, this)); _context.use_certificate_chain_file("./democa/cacert.pem"); _context.use_private_key_file("./democa/private/cakey.pem", boost::asio::ssl::context::pem); // _context.use_tmp_dh_file("dh512.pem"); _connection.reset(new cclconnection(_ioservice, _context)); _acceptor.async_accept(_connection->socket(), boost::bind(&server::handleaccept, this, boost::asio::placeholders::error)); } catch(std::exception& e) { std_exception_message; throw; } } void server::run() { // create pool of threads run of io_services. std::vector<boost::shared_ptr<boost::thread> > threads; (std::size_t = 0; < _threadpoolsize; ++i) { boost::shared_ptr<boost::thread> thread(new boost::thread( boost::bind(&boost::asio::io_service::run, &_ioservice) ) ); threads.push_back(thread); } // wait threads in pool exit. (std::size_t = 0; < threads.size(); ++i) threads[i]->join(); } void server::stop() { _ioservice.stop(); } void server::handleaccept(const boost::system::error_code& e) { if (!e) { _connection->handshake(); _connection.reset(new cclconnection(_ioservice, _context)); _acceptor.async_accept(_connection->socket(), boost::bind(&server::handleaccept, this, boost::asio::placeholders::error)); } } //////////////////////////////////////////////////////////// // file - connection.h //////////////////////////////////////////////////////////// #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> typedef boost::asio::ssl::stream< boost::asio::ip::tcp::socket > ssl_socket; class connection : public boost::enable_shared_from_this<connection> { public: explicit connection(boost::asio::io_service& io_service, boost::asio::ssl::context& context); //get socket connection ssl_socket::lowest_layer_type& socket(); // ssl handshake void handshake(); //get socket connection boost::asio::io_service::strand& strand(); // start first async operation void start(); void sendresponse(const response& response); void close(); // remote ip address connection std::string getipaddress(); private: void handleread(const boost::system::error_code& e, std::size_t bytestransferred); void handlewrite(const boost::system::error_code& e); boost::asio::io_service::strand _strand; ssl_socket _socket; void handlehandshake(const boost::system::error_code& e); boost::array<char, 8192> _buffer; }; typedef boost::shared_ptr<connection> connectionptr; /////////////////////////////////////////////////////////////// // file - connection.cpp /////////////////////////////////////////////////////////////// connection::connection(boost::asio::io_service& io_service, boost::asio::ssl::context& context) : _strand(io_service), _socket(io_service, context) { } ssl_socket::lowest_layer_type& connection::socket() { return _socket.lowest_layer(); } boost::asio::io_service::strand& connection::strand() { return _strand; } void connection::start() { _socket.async_read_some(boost::asio::buffer(_buffer), _strand.wrap( boost::bind( &connection::handleread, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); } void connection::handshake() { std::cout << "doing ssl handshake" << std::endl; _socket.async_handshake(boost::asio::ssl::stream_base::server, _strand.wrap( boost::bind( &connection::handlehandshake, shared_from_this(), boost::asio::placeholders::error ) ) ); } void connection::handlehandshake(const boost::system::error_code& error) { if (!error) { _socket.async_read_some(boost::asio::buffer(_buffer), _strand.wrap( boost::bind( &connection::handleread, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); } else { std::cout << "error occured: " << error.message(); this->close(); } } void connection::handleread(const boost::system::error_code& e, std::size_t bytestransferred) { if (!e) { // handle read data this->start(); } else { this->close(); } } void connection::handlewrite(const boost::system::error_code& e) { if (!e) { this->start(); } else { this->close(); } } void connection::sendresponse(const response& response) { boost::asio::async_write(_socket, boost::asio::buffer(converttostring(response)), _strand.wrap( boost::bind( &connection::handlewrite, shared_from_this(), boost::asio::placeholders::error ) ) ); } void connection::close() { boost::system::error_code ignoredcode; socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredcode); } std::string connection::getipaddress() { return socket().remote_endpoint().address().to_string(); }
can point me out being done wrongly here?
update: issue resolved noted me in comment. issue similar old question on stackoverflow.
your code doesn't recognize, boost::asio::buffer
wrapper objects constructed. here (in connection::sendresponse
):
boost::asio::buffer(converttostring(response))
you created buffer out of (probably) temporary object, was destroyed before used boost::asio::async_write
.
boost.asio documentation tells that in paragraph "buffer invalidation"
for boost::asio::buffer overloads accept argument of type std::string, buffer objects returned invalidated according rules defined invalidation of references, pointers , iterators referring elements of sequence (c++ std, 21.3).
Comments
Post a Comment