c++ - Boost.Asio: SSL Server and Client. Server SIGSEGV and Client Short Read error -
i have built ssl samples of boost , have run them no obvious problems. have written own code using http server , ssl examples references. when run code got error client:
handshake failed. error: short read
and server:
debug: connectionmanager::connectionmanager() debug: server::server(boost::asio::io_service&, short unsigned int) debug: std::__cxx11::string server::hpasswordhandler() const debug: void server::startaccept() debug: connection::connection(boost::asio::io_service&, boost::asio::ssl::context&, connectionmanager&) debug: boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >::lowest_layer_type& connection::socket() debug: void server::haccept(const boost::system::error_code&) debug: void connection::start() debug: void server::startaccept() debug: connection::connection(boost::asio::io_service&, boost::asio::ssl::context&, connectionmanager&) debug: boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >::lowest_layer_type& connection::socket() segmentation fault
the debug:
thing tried make little debugging. segmentation fault happens when connect server.
so ideas?
my server code:
#include <iostream> #include <sstream> #include <locale> #include <string> #include <set> #include <boost/enable_shared_from_this.hpp> #include <boost/shared_ptr.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> #include <boost/thread.hpp> inline void debug_msg(const std::string &instr) { std::string res = "debug: "; res += instr; res += "\n"; std::cout << res; std::cout.flush(); // since don't use std::endl } #if defined(debug) && !defined(ndebug) #define _func_debug_ debug_msg(__pretty_function__); #else #define _func_debug_ #endif typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket_t; class connectionmanager; class connection : public boost::enable_shared_from_this<connection> { public: connection(const connection&) = delete; connection &operator=(const connection&) = delete; explicit connection( boost::asio::io_service &io_service, boost::asio::ssl::context &context, connectionmanager &connectionmanager) : socket_(io_service, context), connectionmanager_(connectionmanager) { _func_debug_ } ssl_socket_t::lowest_layer_type &socket() { _func_debug_ return socket_.lowest_layer(); } void start() { _func_debug_ socket_.async_handshake( boost::asio::ssl::stream_base::server, boost::bind(&connection::hhandshake, this, boost::asio::placeholders::error)); } void stop() { _func_debug_ socket_.lowest_layer().cancel(); socket_.shutdown(); socket_.lowest_layer().close(); } protected: ssl_socket_t socket_; connectionmanager &connectionmanager_; boost::asio::streambuf readbuffer_; std::string message_; void hhandshake(const boost::system::error_code &error) { _func_debug_ if (!error) { boost::asio::async_read_until(socket_, readbuffer_, '\0', boost::bind(&connection::hreaduntil, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else if (error != boost::asio::error::operation_aborted) { notifyconnectionmanagertostop(); } } void hreaduntil( const boost::system::error_code &error, size_t bytes_transferred) { _func_debug_ if (!error) { std::string s; std::istream is(&readbuffer_); std::getline(is, s, '\0'); std::cout << "message: " << s << std::endl; message_ = "server received message!"; message_ += std::string("", 1); boost::asio::async_write(socket_, boost::asio::buffer(message_, message_.size()), boost::bind(&connection::hwrite, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else if (error != boost::asio::error::operation_aborted) { // if operation aborted, connection manager // knows it, since sockets // can stopped connection manager notifyconnectionmanagertostop(); } } void hwrite( const boost::system::error_code &error, size_t bytes_transferred) { _func_debug_ if (!error) { // nothing else do. } else if (error != boost::asio::error::operation_aborted) { notifyconnectionmanagertostop(); } } void notifyconnectionmanagertostop(); }; typedef boost::shared_ptr<connection> connection_ptr; class connectionmanager { public: connectionmanager(const connectionmanager&) = delete; connectionmanager &operator=(const connectionmanager&) = delete; connectionmanager() { _func_debug_ } void start(connection_ptr connection) { _func_debug_ connections_.insert(connection); connection->start(); } void stop(connection_ptr connection) { _func_debug_ connections_.erase(connection); connection->stop(); } void stopall() { _func_debug_ (auto connection : connections_) connection->stop(); connections_.clear(); } protected: std::set<connection_ptr> connections_; }; void connection::notifyconnectionmanagertostop() { _func_debug_ connectionmanager_.stop(shared_from_this()); } class server { public: server(const server &) = delete; server &operator=(const server &) = delete; server( boost::asio::io_service &io_service, unsigned short port) : io_service_(io_service), acceptor_(io_service, boost::asio::ip::tcp::endpoint( boost::asio::ip::tcp::v4(), port)), context_(boost::asio::ssl::context::sslv23) { _func_debug_ 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::hpasswordhandler, this)); context_.use_certificate_chain_file("server.crt"); context_.use_private_key_file("server.key", boost::asio::ssl::context::pem); context_.use_tmp_dh_file("dh1024.pem"); startaccept(); } protected: boost::asio::io_service &io_service_; boost::asio::ip::tcp::acceptor acceptor_; boost::asio::ssl::context context_; connectionmanager connection_manager_; connection_ptr new_connection_; std::string hpasswordhandler() const { _func_debug_ return "somehow return password"; } void haccept(const boost::system::error_code &error) { _func_debug_ if (!error) { new_connection_->start(); startaccept(); } else { new_connection_.reset(); } } void startaccept() { _func_debug_ new_connection_.reset(new connection(io_service_, context_, connection_manager_)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::haccept, this, boost::asio::placeholders::error)); } }; int main(int argc, char **argv) { try { if (argc != 2) { std::cerr << "usage: program <port>" << std::endl; return 1; } boost::asio::io_service io_service; server server(io_service, std::atoi(argv[1])); boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); std::cin.get(); io_service.stop(); t.join(); return 0; } catch (std::exception &e) { std::cerr << "exception: " << e.what() << std::endl; return 2; } }
my client code:
#include <iostream> #include <string> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> class client { protected: boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_; std::string message_; boost::asio::streambuf readbuffer_; bool hverifycertificate(bool preverified, boost::asio::ssl::verify_context &ctx) { return preverified; } void hconnect(const boost::system::error_code &error) { if (!error) { socket_.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&client::hhandshake, this, boost::asio::placeholders::error)); } else { std::cout << "connect failed. error: " << error.message() << std::endl; } } void hreaduntil(const boost::system::error_code &error, size_t bytes_transferred) { if (!error) { std::string s; std::istream is(&readbuffer_); std::getline(is, s, '\0'); std::cout << s << std::endl; } else { std::cout << "read failed. error: " << error.message() << std::endl; } } void hwrite(const boost::system::error_code &error, size_t bytes_transferred) { if (!error) { boost::asio::async_read_until(socket_, readbuffer_, '\0', boost::bind(&client::hreaduntil, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { std::cout << "write failed. error: " << error.message() << std::endl; } } void hhandshake(const boost::system::error_code &error) { if (!error) { std::cout << "to send message type something: "; std::getline(std::cin, message_); message_ += std::string("", 1); // append null character boost::asio::async_write(socket_, boost::asio::buffer(message_, message_.size()), boost::bind(&client::hwrite, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { std::cout << "handshake failed. error: " << error.message() << std::endl; } } public: client(boost::asio::io_service &io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) : socket_(io_service, context) { socket_.set_verify_mode(boost::asio::ssl::verify_peer); socket_.set_verify_callback(boost::bind(&client::hverifycertificate, this, _1, _2)); boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator, boost::bind(&client::hconnect, this, boost::asio::placeholders::error)); } }; int main(int argc, char **argv) { try { if (argc != 3) { std::cerr << "usage: program <host> <port>" << std::endl; return 1; } boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); ctx.load_verify_file("server.crt"); client client(io_service, ctx, iterator); io_service.run(); return 0; } catch (std::exception &e) { std::cerr << "exception: " << e.what() << std::endl; return 1; } }
i have used the description here generate ssl related files.
well, simple bug. forgot starting new connection through connection manager connection object deleted , receive segmentation fault. problem solved. :d
Comments
Post a Comment