//g++ srv.cpp -lboost_system-mt -lboost_regex-mt -lboost_thread-mt -lssl //g++ srv.cpp -lboost_system-mt -lboost_regex-mt -lboost_thread-mt -lssl -DPATHED #include #include #include #include #include #include #define DEBUG std::cout<<__LINE__<<" "<<__FUNCTION__<<" " typedef boost::asio::ip::tcp::socket tcp_socket; typedef boost::asio::ssl::stream ssl_socket; class connection: public boost::enable_shared_from_this , private boost::noncopyable { public: explicit connection(boost::asio::io_service& io_service, int id); virtual ~connection(); virtual void start(); virtual boost::asio::ip::tcp::socket & get_socket(); protected: void handle_read(const boost::system::error_code& error,std::size_t bytes_transferred); void handle_write(const boost::system::error_code& error,std::size_t bytes_transferred,boost::shared_ptr write_buf); virtual void schedule_read(); virtual void schedule_write(std::string &message); boost::asio::io_service & io_service; boost::asio::streambuf buf; tcp_socket socket; int id; };//class connection class ssl_connection: public connection{ public: explicit ssl_connection(boost::asio::io_service& io_service, int id,boost::asio::ssl::context & context); void start(); boost::asio::ip::tcp::socket & get_socket(); protected: void schedule_read(); void schedule_write(std::string &message); void handle_handshake(const boost::system::error_code& error); ssl_socket ssocket; };//class ssl_connection connection::connection(boost::asio::io_service& io_service, int id): io_service(io_service), socket(io_service), id(id){ DEBUG << std::endl; } connection::~connection(){ DEBUG << std::endl; } void connection::start(){ DEBUG <<"new tcp connection start"<< std::endl; schedule_read(); } boost::asio::ip::tcp::socket & connection::get_socket(){ return socket; } void connection::handle_read(const boost::system::error_code& error,std::size_t bytes_transferred){ DEBUG <<"asynchronous read finished (transferred: "< write_buf){ DEBUG <<"asynchronous write finished (transferred: "< writing_buf(new std::string(message)); boost::asio::async_write( socket, boost::asio::buffer(*writing_buf), boost::bind(&connection::handle_write, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, writing_buf ) ); } ssl_connection::ssl_connection(boost::asio::io_service& io_service,int id,boost::asio::ssl::context & context): connection(io_service,id), ssocket(socket,context){ DEBUG << std::endl; } void ssl_connection::start(){ DEBUG <<"new SSL connection start"<< std::endl; ssocket.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&ssl_connection::handle_handshake, boost::dynamic_pointer_cast(shared_from_this()), boost::asio::placeholders::error ) ); } boost::asio::ip::tcp::socket & ssl_connection::get_socket(){ return socket; } void ssl_connection::schedule_read() { DEBUG <<"starting SSL asynchronous read"<< std::endl; boost::asio::async_read_until( ssocket, buf, boost::regex("[\n\r]"), boost::bind(&ssl_connection::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ); } void ssl_connection::schedule_write(std::string &message) { DEBUG <<"starting SSL asynchronous write"<< std::endl< writing_buf(new std::string(message)); boost::asio::async_write( ssocket, boost::asio::buffer(*writing_buf), boost::bind(&ssl_connection::handle_write, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, writing_buf ) ); } void ssl_connection::handle_handshake(const boost::system::error_code& error){ if (!error){ schedule_read(); } else{ //delete this; socket.close(); } } class server: private boost::noncopyable { int counter; boost::asio::io_service io_service; boost::asio::ip::tcp::acceptor acceptor,ssl_acceptor; boost::asio::ssl::context context; void handle_accept(const boost::system::error_code & error); void handle_ssl_accept(const boost::system::error_code& error); boost::shared_ptr tcp_new; boost::shared_ptr ssl_new; public: server(); void run(); void stop(); }; server::server(): acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 10000)), ssl_acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 10001)), context(io_service, boost::asio::ssl::context::sslv23), counter(0){ context.set_verify_mode(boost::asio::ssl::context::verify_peer); std::string certfile = "server.pem";//config ("ssl.certfile"); std::string keyfile = "server.key";//config ("ssl.keyfile"); context.use_certificate_chain_file(certfile); try { context.use_private_key_file(keyfile, boost::asio::ssl::context::pem); } catch (boost::system::system_error e) { DEBUG << "private key error: " << e.what() << std::endl; } tcp_new.reset(new connection (io_service, counter++)); ssl_new.reset(new ssl_connection (io_service, counter++, context)); acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); ssl_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); } void server::run() { acceptor.async_accept(tcp_new->get_socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); ssl_acceptor.async_accept(ssl_new->get_socket(), boost::bind(&server::handle_ssl_accept, this, boost::asio::placeholders::error)); // Create a pool of threads to run all of the io_services. std::vector > threads; int num_threads = 4;//config("threads"); for (std::size_t i = 0; i < num_threads; ++i) { boost::shared_ptr thread( new boost::thread( boost::bind (&boost::asio::io_service::run, &io_service) ) ); threads.push_back(thread); } //connect to database // Wait for all threads in the pool to exit. for (std::size_t i = 0; i < threads.size(); ++i) threads[i]->join(); } void server::stop() { DEBUG << "stopping server ..." << std::endl; io_service.stop(); DEBUG << "stopping server ... done" << std::endl; } void server::handle_accept(const boost::system::error_code& error){ DEBUG << std::endl; if(!error){ tcp_new->start(); tcp_new.reset(new connection (io_service, counter++)); acceptor.async_accept(tcp_new->get_socket(), boost::bind( &server::handle_accept, this, boost::asio::placeholders::error )); } else{ DEBUG << "error " << error.value() << ": " << error.message() << std::endl; return; } } void server::handle_ssl_accept(const boost::system::error_code& error){ DEBUG << std::endl; if(!error){ ssl_new->start(); ssl_new.reset(new ssl_connection (io_service,counter++,context)); ssl_acceptor.async_accept(ssl_new->get_socket(), boost::bind( &server::handle_ssl_accept, this, boost::asio::placeholders::error )); } else { DEBUG << "error " << error.value() << ": " << error.message() << std::endl; return; } } #ifdef PATHED #include std::vector > locks; void locking_function(int mode, int n, const char *file, int line){ //DEBUG <<((mode & CRYPTO_LOCK)?"lock: ":"unlock: ")<lock(); else locks[n]->unlock(); } void setup_locks(){ locks.reserve(CRYPTO_num_locks()); for(int i=0;i(new boost::signals2::mutex())); } CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))locking_function); } #endif main (){ #ifdef PATHED setup_locks(); #endif server srv; srv.run(); }