/* * st_asio_wrapper_ssl_object.h * * Created on: 2012-3-2 * Author: youngwolf * email: mail2tao@163.com * QQ: 676218192 * Community on QQ: 198941541 * * make st_asio_wrapper support asio::ssl */ #ifndef ST_ASIO_WRAPPER_SSL_H_ #define ST_ASIO_WRAPPER_SSL_H_ #include #include "st_asio_wrapper_object_pool.h" #include "st_asio_wrapper_tcp_client.h" #include "st_asio_wrapper_server.h" namespace st_asio_wrapper { template > class st_ssl_connector_base : public st_connector_base { public: st_ssl_connector_base(boost::asio::io_service& io_service_, boost::asio::ssl::context& ctx) : st_connector_base(io_service_, ctx), authorized_(false) {} virtual void reset() {authorized_ = false; st_connector_base::reset();} bool authorized() const {return authorized_;} protected: virtual bool do_start() //connect or receive { if (!ST_THIS get_io_service().stopped()) { if (ST_THIS reconnecting && !ST_THIS is_connected()) ST_THIS lowest_layer().async_connect(ST_THIS server_addr, boost::bind(&st_ssl_connector_base::connect_handler, this, boost::asio::placeholders::error)); else if (!authorized_) ST_THIS next_layer().async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&st_ssl_connector_base::handshake_handler, this, boost::asio::placeholders::error)); else ST_THIS do_recv_msg(); return true; } return false; } virtual void on_unpack_error() {authorized_ = false; st_connector_base::on_unpack_error();} virtual void on_recv_error(const boost::system::error_code& ec) {authorized_ = false; st_connector_base::on_recv_error(ec);} virtual void on_handshake(bool result) { if (result) unified_out::info_out("handshake success."); else { unified_out::error_out("handshake failed!"); ST_THIS force_close(false); } } virtual bool is_send_allowed() const {return authorized() && st_connector_base::is_send_allowed();} void connect_handler(const boost::system::error_code& ec) { if (!ec) { ST_THIS connected = true; ST_THIS reconnecting = false; ST_THIS on_connect(); do_start(); } else st_connector_base::connect_handler(ec); } void handshake_handler(const boost::system::error_code& ec) { on_handshake(!ec); if (ec) unified_out::error_out("handshake failed: %s", ec.message().data()); else { authorized_ = true; ST_THIS send_msg(); //send buffer may have msgs, send them do_start(); } } protected: bool authorized_; }; typedef st_ssl_connector_base<> st_ssl_connector; typedef st_sclient st_ssl_tcp_sclient; template class st_ssl_object_pool : public st_object_pool { public: st_ssl_object_pool(st_service_pump& service_pump_, boost::asio::ssl::context::method m) : st_object_pool(service_pump_), ctx(m) {} boost::asio::ssl::context& ssl_context() {return ctx;} typename st_ssl_object_pool::object_type create_object() { auto client_ptr = ST_THIS reuse_object(); return client_ptr ? client_ptr : boost::make_shared(ST_THIS service_pump, ctx); } template typename st_ssl_object_pool::object_type create_object(Arg& arg) { auto client_ptr = ST_THIS reuse_object(); return client_ptr ? client_ptr : boost::make_shared(arg, ctx); } protected: boost::asio::ssl::context ctx; }; typedef st_tcp_client_base> st_ssl_tcp_client; template> class st_ssl_server_socket_base : public st_server_socket_base { public: st_ssl_server_socket_base(Server& server_, boost::asio::ssl::context& ctx) : st_server_socket_base(server_, ctx) {} }; typedef st_ssl_server_socket_base<> st_ssl_server_socket; template, typename Server = i_server> class st_ssl_server_base : public st_server_base { public: st_ssl_server_base(st_service_pump& service_pump_, boost::asio::ssl::context::method m) : st_server_base(service_pump_, m) {} protected: virtual void on_handshake(bool result, typename st_ssl_server_base::object_ctype& client_ptr) { if (result) client_ptr->show_info("handshake with", "success."); else client_ptr->show_info("handshake with", "failed!"); } virtual void start_next_accept() { auto client_ptr = ST_THIS create_object(boost::ref(*this)); ST_THIS acceptor.async_accept(client_ptr->lowest_layer(), boost::bind(&st_ssl_server_base::accept_handler, this, boost::asio::placeholders::error, client_ptr)); } protected: void accept_handler(const boost::system::error_code& ec, typename st_ssl_server_base::object_ctype& client_ptr) { if (!ec) { if (ST_THIS on_accept(client_ptr)) client_ptr->next_layer().async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&st_ssl_server_base::handshake_handler, this, boost::asio::placeholders::error, client_ptr)); start_next_accept(); } else ST_THIS stop_listen(); } void handshake_handler(const boost::system::error_code& ec, typename st_ssl_server_base::object_ctype& client_ptr) { on_handshake(!ec, client_ptr); if (ec) unified_out::error_out("handshake failed: %s", ec.message().data()); else if (ST_THIS add_client(client_ptr)) { client_ptr->start(); return; } else client_ptr->show_info("client:", "been refused cause of too many clients."); client_ptr->force_close(); } }; typedef st_ssl_server_base<> st_ssl_server; } //namespace #endif /* ST_ASIO_WRAPPER_SSL_H_ */