diff --git a/src/connection.hpp b/src/connection.hpp index 1d436cfe13..e92421369d 100644 --- a/src/connection.hpp +++ b/src/connection.hpp @@ -254,6 +254,23 @@ public: return m_control_message; } + + // stuff about switching handlers on the fly + // TODO: organize more + void set_handler(handler_ptr new_handler) { + m_endpoint.elog().at(log::elevel::FATAL) + << "Tried to switch to a NULL handler." << log::endl; + if (!new_handler) { + throw "TODO"; + } + + handler_ptr old_handler = get_handler(); + + old_handler->on_unload(type::shared_from_this(),new_handler); + m_handler = new_handler; + new_handler->on_load(type::shared_from_this(),old_handler); + } + // TODO: deprecated. will change to get_rng? int32_t gen() { return 0; @@ -368,28 +385,25 @@ protected: } void process_data(message::data_ptr msg) { - m_endpoint.get_handler()->on_message(type::shared_from_this(),msg); + get_handler()->on_message(type::shared_from_this(),msg); } void process_control(message::control_ptr msg) { bool response; switch (msg->get_opcode()) { case frame::opcode::PING: - response = m_endpoint.get_handler()->on_ping( - type::shared_from_this(), - msg->get_payload() - ); - + response = get_handler()->on_ping(type::shared_from_this(), + msg->get_payload()); if (response) { // send response ping - write_message(m_processor->prepare_frame(frame::opcode::PONG,!m_endpoint.is_server(),msg->get_payload())); + write_message(m_processor->prepare_frame(frame::opcode::PONG, + !m_endpoint.is_server(), + msg->get_payload())); } break; case frame::opcode::PONG: - m_endpoint.get_handler()->on_pong( - type::shared_from_this(), - msg->get_payload()); - + get_handler()->on_pong(type::shared_from_this(), + msg->get_payload()); // TODO: disable ping response timer break; @@ -416,7 +430,8 @@ protected: } break; default: - throw processor::exception("Invalid Opcode",processor::error::PROTOCOL_VIOLATION); + throw processor::exception("Invalid Opcode", + processor::error::PROTOCOL_VIOLATION); break; } } @@ -424,17 +439,20 @@ protected: void send_close(close::status::value code, const std::string& reason) { if (m_state != session::state::OPEN) { m_endpoint.elog().at(log::elevel::WARN) - << "Tried to disconnect a session that wasn't open" << log::endl; + << "Tried to disconnect a session that wasn't open" + << log::endl; return; } if (close::status::invalid(code)) { m_endpoint.elog().at(log::elevel::WARN) - << "Tried to close a connection with invalid close code: " << code << log::endl; + << "Tried to close a connection with invalid close code: " + << code << log::endl; return; } else if (close::status::reserved(code)) { m_endpoint.elog().at(log::elevel::WARN) - << "Tried to close a connection with reserved close code: " << code << log::endl; + << "Tried to close a connection with reserved close code: " + << code << log::endl; return; } @@ -607,10 +625,10 @@ protected: m_state = session::state::CLOSED; if (old_state == session::state::CONNECTING) { - m_endpoint.get_handler()->on_fail(type::shared_from_this()); + get_handler()->on_fail(type::shared_from_this()); } else if (old_state == session::state::OPEN || old_state == session::state::CLOSING) { - m_endpoint.get_handler()->on_close(type::shared_from_this()); + get_handler()->on_close(type::shared_from_this()); } else { // if we were already closed something is wrong } diff --git a/src/endpoint.hpp b/src/endpoint.hpp index f7652e3cdb..04486c6193 100644 --- a/src/endpoint.hpp +++ b/src/endpoint.hpp @@ -147,6 +147,21 @@ public: elogger_type& elog() { return m_elog; } + + /// Updates the default handler to be used for future connections + /** + * @param new_handler A shared pointer to the new default handler. Must not + * be NULL. + */ + void set_handler(handler_ptr new_handler) { + if (!new_handler) { + elog().at(log::elevel::FATAL) + << "Tried to switch to a NULL handler." << log::endl; + throw "TODO: handlers can't be null"; + } + + m_handler = new_handler; + } protected: /// Creates and returns a new connection /** @@ -222,13 +237,34 @@ struct endpoint_traits< endpoint > { /// A shared pointer to the type of connection that this endpoint creates. typedef boost::shared_ptr connection_ptr; - /// Interface (ABC) that handlers for this type of endpoint must impliment - /// role policy and socket policy both may add methods to this interface - class handler : public role_type::handler_interface, - public socket_type::handler_interface {}; - /// A shared pointer to the base class that all handlers for this endpoint + class handler; + + /// A shared pointer to the base class that all handlers for this endpoint /// must derive from. typedef boost::shared_ptr handler_ptr; + + /// Interface (ABC) that handlers for this type of endpoint may impliment. + /// role policy and socket policy both may add methods to this interface + class handler : public role_type::handler_interface, + public socket_type::handler_interface + { + public: + /// on_load is the first callback called for a handler after a new + /// connection has been transferred to it mid flight. + /** + * @param connection A shared pointer to the connection that was transferred + * @param old_handler A shared pointer to the previous handler + */ + virtual void on_load(connection_ptr connection, handler_ptr old_handler) {} + /// on_unload is the last callback called for a handler before control + /// of a connection is handed over to a new handler mid flight. + /** + * @param connection A shared pointer to the connection being transferred + * @param old_handler A shared pointer to the new handler + */ + virtual void on_unload(connection_ptr connection, handler_ptr new_handler) {} + }; + }; } // namespace websocketpp