#include #include #include #include #include typedef boost::asio::ssl::stream ssl_socket; class session { public: session(boost::asio::io_service& io_service, boost::asio::ssl::context& context) : socket_(io_service, context) { } ssl_socket::lowest_layer_type& socket() { return socket_.lowest_layer(); } void start() { socket_.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&session::handle_handshake, this, boost::asio::placeholders::error)); } void handle_handshake(const boost::asio::error& error) { if (!error) { socket_.async_read_some(boost::asio::buffer(data_, max_length), boost::bind(&session::handle_read_header, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { delete this; } } void handle_read_header(const boost::asio::error& error, size_t bytes_transferred) { if (!error && bytes_transferred == 4) { size_t size; memcpy(&size, data_, sizeof size); // size of the incoming string _buffer.resize(size); std::cout << "Message Header Read, incoming message size is " << size << std::endl; boost::asio::async_read(socket_, boost::asio::buffer(&_buffer[0], _buffer.size()), boost::bind(&session::handle_read_data, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { delete this; } } void handle_read_data(const boost::asio::error& error, size_t bytes_transferred) { if (!error) { std::cout << "Received size " << _buffer.size() << ": " << _buffer.substr(0, _buffer.size() > 60 ? 60 : _buffer.size()) << std::endl; char dataSize[20]; sprintf(dataSize, "%d", _buffer.size()); _buffer = "Received "; _buffer += dataSize; _buffer += " bytes"; boost::asio::async_write(socket_, boost::asio::buffer(_buffer), boost::bind(&session::handle_write, this, boost::asio::placeholders::error)); } else { delete this; } } void handle_write(const boost::asio::error& error) { if (!error) { socket_.async_read_some(boost::asio::buffer(data_, max_length), boost::bind(&session::handle_read_header, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { delete this; } } private: ssl_socket socket_; enum { max_length = 1024 }; char data_[max_length]; std::string _buffer; }; class server { public: 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_(io_service, boost::asio::ssl::context::sslv23) { context_.set_options( boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); context_.use_certificate_chain_file("server.pem"); context_.use_private_key_file("server2.pem", boost::asio::ssl::context::pem); context_.use_tmp_dh_file("dh512.pem"); session* new_session = new session(io_service_, context_); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } void handle_accept(session* new_session, const boost::asio::error& error) { if (!error) { new_session->start(); new_session = new session(io_service_, context_); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } else if (error == boost::asio::error::connection_aborted) { acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } else { delete new_session; } } private: boost::asio::io_service& io_service_; boost::asio::ip::tcp::acceptor acceptor_; boost::asio::ssl::context context_; }; int servermain(int argc, char* argv[]) { try { if (argc != 2) { std::cerr << "Usage: server \n"; return 1; } boost::asio::io_service io_service; using namespace std; // For atoi. server s(io_service, atoi(argv[1])); io_service.run(); } catch (boost::asio::error& e) { std::cerr << e << "\n"; } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }