aboutsummaryrefslogtreecommitdiffstats
path: root/websocketpp/connection.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'websocketpp/connection.hpp')
-rw-r--r--websocketpp/connection.hpp1651
1 files changed, 1651 insertions, 0 deletions
diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp
new file mode 100644
index 00000000..3bbbbb31
--- /dev/null
+++ b/websocketpp/connection.hpp
@@ -0,0 +1,1651 @@
+/*
+ * Copyright (c) 2014, Peter Thorson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the WebSocket++ Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WEBSOCKETPP_CONNECTION_HPP
+#define WEBSOCKETPP_CONNECTION_HPP
+
+#include <websocketpp/close.hpp>
+#include <websocketpp/error.hpp>
+#include <websocketpp/frame.hpp>
+
+#include <websocketpp/logger/levels.hpp>
+#include <websocketpp/processors/processor.hpp>
+#include <websocketpp/transport/base/connection.hpp>
+#include <websocketpp/http/constants.hpp>
+
+#include <websocketpp/common/connection_hdl.hpp>
+#include <websocketpp/common/cpp11.hpp>
+#include <websocketpp/common/functional.hpp>
+
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace websocketpp {
+
+/// The type and function signature of an open handler
+/**
+ * The open handler is called once for every successful WebSocket connection
+ * attempt. Either the fail handler or the open handler will be called for each
+ * WebSocket connection attempt. HTTP Connections that did not attempt to
+ * upgrade the connection to the WebSocket protocol will trigger the http
+ * handler instead of fail/open.
+ */
+typedef lib::function<void(connection_hdl)> open_handler;
+
+/// The type and function signature of a close handler
+/**
+ * The close handler is called once for every successfully established
+ * connection after it is no longer capable of sending or receiving new messages
+ *
+ * The close handler will be called exactly once for every connection for which
+ * the open handler was called.
+ */
+typedef lib::function<void(connection_hdl)> close_handler;
+
+/// The type and function signature of a fail handler
+/**
+ * The fail handler is called once for every unsuccessful WebSocket connection
+ * attempt. Either the fail handler or the open handler will be called for each
+ * WebSocket connection attempt. HTTP Connections that did not attempt to
+ * upgrade the connection to the WebSocket protocol will trigger the http
+ * handler instead of fail/open.
+ */
+typedef lib::function<void(connection_hdl)> fail_handler;
+
+/// The type and function signature of an interrupt handler
+/**
+ * The interrupt handler is called when a connection receives an interrupt
+ * request from the application. Interrupts allow the application to trigger a
+ * handler to be run in the absense of a WebSocket level handler trigger (like
+ * a new message).
+ *
+ * This is typically used by another application thread to schedule some tasks
+ * that can only be run from within the handler chain for thread safety reasons.
+ */
+typedef lib::function<void(connection_hdl)> interrupt_handler;
+
+/// The type and function signature of a ping handler
+/**
+ * The ping handler is called when the connection receives a WebSocket ping
+ * control frame. The string argument contains the ping payload. The payload is
+ * a binary string up to 126 bytes in length. The ping handler returns a bool,
+ * true if a pong response should be sent, false if the pong response should be
+ * suppressed.
+ */
+typedef lib::function<bool(connection_hdl,std::string)> ping_handler;
+
+/// The type and function signature of a pong handler
+/**
+ * The pong handler is called when the connection receives a WebSocket pong
+ * control frame. The string argument contains the pong payload. The payload is
+ * a binary string up to 126 bytes in length.
+ */
+typedef lib::function<void(connection_hdl,std::string)> pong_handler;
+
+/// The type and function signature of a pong timeout handler
+/**
+ * The pong timeout handler is called when a ping goes unanswered by a pong for
+ * longer than the locally specified timeout period.
+ */
+typedef lib::function<void(connection_hdl,std::string)> pong_timeout_handler;
+
+/// The type and function signature of a validate handler
+/**
+ * The validate handler is called after a WebSocket handshake has been received
+ * and processed but before it has been accepted. This gives the application a
+ * chance to implement connection details specific policies for accepting
+ * connections and the ability to negotiate extensions and subprotocols.
+ *
+ * The validate handler return value indicates whether or not the connection
+ * should be accepted. Additional methods may be called during the function to
+ * set response headers, set HTTP return/error codes, etc.
+ */
+typedef lib::function<bool(connection_hdl)> validate_handler;
+
+/// The type and function signature of a http handler
+/**
+ * The http handler is called when an HTTP connection is made that does not
+ * attempt to upgrade the connection to the WebSocket protocol. This allows
+ * WebSocket++ servers to respond to these requests with regular HTTP responses.
+ *
+ * This can be used to deliver error pages & dashboards and to deliver static
+ * files such as the base HTML & JavaScript for an otherwise single page
+ * WebSocket application.
+ *
+ * Note: WebSocket++ is designed to be a high performance WebSocket server. It
+ * is not tuned to provide a full featured, high performance, HTTP web server
+ * solution. The HTTP handler is appropriate only for low volume HTTP traffic.
+ * If you expect to serve high volumes of HTTP traffic a dedicated HTTP web
+ * server is strongly recommended.
+ *
+ * The default HTTP handler will return a 426 Upgrade Required error. Custom
+ * handlers may override the response status code to deliver any type of
+ * response.
+ */
+typedef lib::function<void(connection_hdl)> http_handler;
+
+//
+typedef lib::function<void(lib::error_code const & ec, size_t bytes_transferred)> read_handler;
+typedef lib::function<void(lib::error_code const & ec)> write_frame_handler;
+
+// constants related to the default WebSocket protocol versions available
+#ifdef _WEBSOCKETPP_INITIALIZER_LISTS_ // simplified C++11 version
+ /// Container that stores the list of protocol versions supported
+ /**
+ * @todo Move this to configs to allow compile/runtime disabling or enabling
+ * of protocol versions
+ */
+ static std::vector<int> const versions_supported = {0,7,8,13};
+#else
+ /// Helper array to get around lack of initializer lists pre C++11
+ static int const helper[] = {0,7,8,13};
+ /// Container that stores the list of protocol versions supported
+ /**
+ * @todo Move this to configs to allow compile/runtime disabling or enabling
+ * of protocol versions
+ */
+ static std::vector<int> const versions_supported(helper,helper+4);
+#endif
+
+namespace session {
+namespace state {
+ // externally visible session state (states based on the RFC)
+ enum value {
+ connecting = 0,
+ open = 1,
+ closing = 2,
+ closed = 3
+ };
+} // namespace state
+
+
+namespace fail {
+namespace status {
+ enum value {
+ GOOD = 0, // no failure yet!
+ SYSTEM = 1, // system call returned error, check that code
+ WEBSOCKET = 2, // websocket close codes contain error
+ UNKNOWN = 3, // No failure information is available
+ TIMEOUT_TLS = 4, // TLS handshake timed out
+ TIMEOUT_WS = 5 // WS handshake timed out
+ };
+} // namespace status
+} // namespace fail
+
+namespace internal_state {
+ // More granular internal states. These are used for multi-threaded
+ // connection synchronization and preventing values that are not yet or no
+ // longer available from being used.
+
+ enum value {
+ USER_INIT = 0,
+ TRANSPORT_INIT = 1,
+ READ_HTTP_REQUEST = 2,
+ WRITE_HTTP_REQUEST = 3,
+ READ_HTTP_RESPONSE = 4,
+ WRITE_HTTP_RESPONSE = 5,
+ PROCESS_HTTP_REQUEST = 6,
+ PROCESS_CONNECTION = 7
+ };
+} // namespace internal_state
+
+
+namespace http_state {
+ // states to keep track of the progress of http connections
+
+ enum value {
+ init = 0,
+ deferred = 1,
+ headers_written = 2,
+ body_written = 3,
+ closed = 4
+ };
+} // namespace http_state
+
+} // namespace session
+
+/// Represents an individual WebSocket connection
+template <typename config>
+class connection
+ : public config::transport_type::transport_con_type
+ , public config::connection_base
+{
+public:
+ /// Type of this connection
+ typedef connection<config> type;
+ /// Type of a shared pointer to this connection
+ typedef lib::shared_ptr<type> ptr;
+ /// Type of a weak pointer to this connection
+ typedef lib::weak_ptr<type> weak_ptr;
+
+ /// Type of the concurrency component of this connection
+ typedef typename config::concurrency_type concurrency_type;
+ /// Type of the access logging policy
+ typedef typename config::alog_type alog_type;
+ /// Type of the error logging policy
+ typedef typename config::elog_type elog_type;
+
+ /// Type of the transport component of this connection
+ typedef typename config::transport_type::transport_con_type
+ transport_con_type;
+ /// Type of a shared pointer to the transport component of this connection
+ typedef typename transport_con_type::ptr transport_con_ptr;
+
+ typedef lib::function<void(ptr)> termination_handler;
+
+ typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
+ typedef typename concurrency_type::mutex_type mutex_type;
+
+ typedef typename config::request_type request_type;
+ typedef typename config::response_type response_type;
+
+ typedef typename config::message_type message_type;
+ typedef typename message_type::ptr message_ptr;
+
+ typedef typename config::con_msg_manager_type con_msg_manager_type;
+ typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
+
+ /// Type of RNG
+ typedef typename config::rng_type rng_type;
+
+ typedef processor::processor<config> processor_type;
+ typedef lib::shared_ptr<processor_type> processor_ptr;
+
+ // Message handler (needs to know message type)
+ typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
+
+ /// Type of a pointer to a transport timer handle
+ typedef typename transport_con_type::timer_ptr timer_ptr;
+
+ // Misc Convenience Types
+ typedef session::internal_state::value istate_type;
+
+private:
+ enum terminate_status {
+ failed = 1,
+ closed,
+ unknown
+ };
+public:
+
+ explicit connection(bool p_is_server, std::string const & ua, alog_type& alog,
+ elog_type& elog, rng_type & rng)
+ : transport_con_type(p_is_server, alog, elog)
+ , m_handle_read_frame(lib::bind(
+ &type::handle_read_frame,
+ this,
+ lib::placeholders::_1,
+ lib::placeholders::_2
+ ))
+ , m_write_frame_handler(lib::bind(
+ &type::handle_write_frame,
+ this,
+ lib::placeholders::_1
+ ))
+ , m_user_agent(ua)
+ , m_open_handshake_timeout_dur(config::timeout_open_handshake)
+ , m_close_handshake_timeout_dur(config::timeout_close_handshake)
+ , m_pong_timeout_dur(config::timeout_pong)
+ , m_max_message_size(config::max_message_size)
+ , m_state(session::state::connecting)
+ , m_internal_state(session::internal_state::USER_INIT)
+ , m_msg_manager(new con_msg_manager_type())
+ , m_send_buffer_size(0)
+ , m_write_flag(false)
+ , m_read_flag(true)
+ , m_is_server(p_is_server)
+ , m_alog(alog)
+ , m_elog(elog)
+ , m_rng(rng)
+ , m_local_close_code(close::status::abnormal_close)
+ , m_remote_close_code(close::status::abnormal_close)
+ , m_is_http(false)
+ , m_http_state(session::http_state::init)
+ , m_was_clean(false)
+ {
+ m_alog.write(log::alevel::devel,"connection constructor");
+ }
+
+ /// Get a shared pointer to this component
+ ptr get_shared() {
+ return lib::static_pointer_cast<type>(transport_con_type::get_shared());
+ }
+
+ ///////////////////////////
+ // Set Handler Callbacks //
+ ///////////////////////////
+
+ /// Set open handler
+ /**
+ * The open handler is called after the WebSocket handshake is complete and
+ * the connection is considered OPEN.
+ *
+ * @param h The new open_handler
+ */
+ void set_open_handler(open_handler h) {
+ m_open_handler = h;
+ }
+
+ /// Set close handler
+ /**
+ * The close handler is called immediately after the connection is closed.
+ *
+ * @param h The new close_handler
+ */
+ void set_close_handler(close_handler h) {
+ m_close_handler = h;
+ }
+
+ /// Set fail handler
+ /**
+ * The fail handler is called whenever the connection fails while the
+ * handshake is bring processed.
+ *
+ * @param h The new fail_handler
+ */
+ void set_fail_handler(fail_handler h) {
+ m_fail_handler = h;
+ }
+
+ /// Set ping handler
+ /**
+ * The ping handler is called whenever the connection receives a ping
+ * control frame. The ping payload is included.
+ *
+ * The ping handler's return time controls whether or not a pong is
+ * sent in response to this ping. Returning false will suppress the
+ * return pong. If no ping handler is set a pong will be sent.
+ *
+ * @param h The new ping_handler
+ */
+ void set_ping_handler(ping_handler h) {
+ m_ping_handler = h;
+ }
+
+ /// Set pong handler
+ /**
+ * The pong handler is called whenever the connection receives a pong
+ * control frame. The pong payload is included.
+ *
+ * @param h The new pong_handler
+ */
+ void set_pong_handler(pong_handler h) {
+ m_pong_handler = h;
+ }
+
+ /// Set pong timeout handler
+ /**
+ * If the transport component being used supports timers, the pong timeout
+ * handler is called whenever a pong control frame is not received with the
+ * configured timeout period after the application sends a ping.
+ *
+ * The config setting `timeout_pong` controls the length of the timeout
+ * period. It is specified in milliseconds.
+ *
+ * This can be used to probe the health of the remote endpoint's WebSocket
+ * implementation. This does not guarantee that the remote application
+ * itself is still healthy but can be a useful diagnostic.
+ *
+ * Note: receipt of this callback doesn't mean the pong will never come.
+ * This functionality will not suppress delivery of the pong in question
+ * should it arrive after the timeout.
+ *
+ * @param h The new pong_timeout_handler
+ */
+ void set_pong_timeout_handler(pong_timeout_handler h) {
+ m_pong_timeout_handler = h;
+ }
+
+ /// Set interrupt handler
+ /**
+ * The interrupt handler is called whenever the connection is manually
+ * interrupted by the application.
+ *
+ * @param h The new interrupt_handler
+ */
+ void set_interrupt_handler(interrupt_handler h) {
+ m_interrupt_handler = h;
+ }
+
+ /// Set http handler
+ /**
+ * The http handler is called after an HTTP request other than a WebSocket
+ * upgrade request is received. It allows a WebSocket++ server to respond
+ * to regular HTTP requests on the same port as it processes WebSocket
+ * connections. This can be useful for hosting error messages, flash
+ * policy files, status pages, and other simple HTTP responses. It is not
+ * intended to be used as a primary web server.
+ *
+ * @param h The new http_handler
+ */
+ void set_http_handler(http_handler h) {
+ m_http_handler = h;
+ }
+
+ /// Set validate handler
+ /**
+ * The validate handler is called after a WebSocket handshake has been
+ * parsed but before a response is returned. It provides the application
+ * a chance to examine the request and determine whether or not it wants
+ * to accept the connection.
+ *
+ * Returning false from the validate handler will reject the connection.
+ * If no validate handler is present, all connections will be allowed.
+ *
+ * @param h The new validate_handler
+ */
+ void set_validate_handler(validate_handler h) {
+ m_validate_handler = h;
+ }
+
+ /// Set message handler
+ /**
+ * The message handler is called after a new message has been received.
+ *
+ * @param h The new message_handler
+ */
+ void set_message_handler(message_handler h) {
+ m_message_handler = h;
+ }
+
+ //////////////////////////////////////////
+ // Connection timeouts and other limits //
+ //////////////////////////////////////////
+
+ /// Set open handshake timeout
+ /**
+ * Sets the length of time the library will wait after an opening handshake
+ * has been initiated before cancelling it. This can be used to prevent
+ * excessive wait times for outgoing clients or excessive resource usage
+ * from broken clients or DoS attacks on servers.
+ *
+ * Connections that time out will have their fail handlers called with the
+ * open_handshake_timeout error code.
+ *
+ * The default value is specified via the compile time config value
+ * 'timeout_open_handshake'. The default value in the core config
+ * is 5000ms. A value of 0 will disable the timer entirely.
+ *
+ * To be effective, the transport you are using must support timers. See
+ * the documentation for your transport policy for details about its
+ * timer support.
+ *
+ * @param dur The length of the open handshake timeout in ms
+ */
+ void set_open_handshake_timeout(long dur) {
+ m_open_handshake_timeout_dur = dur;
+ }
+
+ /// Set close handshake timeout
+ /**
+ * Sets the length of time the library will wait after a closing handshake
+ * has been initiated before cancelling it. This can be used to prevent
+ * excessive wait times for outgoing clients or excessive resource usage
+ * from broken clients or DoS attacks on servers.
+ *
+ * Connections that time out will have their close handlers called with the
+ * close_handshake_timeout error code.
+ *
+ * The default value is specified via the compile time config value
+ * 'timeout_close_handshake'. The default value in the core config
+ * is 5000ms. A value of 0 will disable the timer entirely.
+ *
+ * To be effective, the transport you are using must support timers. See
+ * the documentation for your transport policy for details about its
+ * timer support.
+ *
+ * @param dur The length of the close handshake timeout in ms
+ */
+ void set_close_handshake_timeout(long dur) {
+ m_close_handshake_timeout_dur = dur;
+ }
+
+ /// Set pong timeout
+ /**
+ * Sets the length of time the library will wait for a pong response to a
+ * ping. This can be used as a keepalive or to detect broken connections.
+ *
+ * Pong responses that time out will have the pong timeout handler called.
+ *
+ * The default value is specified via the compile time config value
+ * 'timeout_pong'. The default value in the core config
+ * is 5000ms. A value of 0 will disable the timer entirely.
+ *
+ * To be effective, the transport you are using must support timers. See
+ * the documentation for your transport policy for details about its
+ * timer support.
+ *
+ * @param dur The length of the pong timeout in ms
+ */
+ void set_pong_timeout(long dur) {
+ m_pong_timeout_dur = dur;
+ }
+
+ /// Get maximum message size
+ /**
+ * Get maximum message size. Maximum message size determines the point at
+ * which the connection will fail with the message_too_big protocol error.
+ *
+ * The default is set by the endpoint that creates the connection.
+ *
+ * @since 0.3.0
+ */
+ size_t get_max_message_size() const {
+ return m_max_message_size;
+ }
+
+ /// Set maximum message size
+ /**
+ * Set maximum message size. Maximum message size determines the point at
+ * which the connection will fail with the message_too_big protocol error.
+ * This value may be changed during the connection.
+ *
+ * The default is set by the endpoint that creates the connection.
+ *
+ * @since 0.3.0
+ *
+ * @param new_value The value to set as the maximum message size.
+ */
+ void set_max_message_size(size_t new_value) {
+ m_max_message_size = new_value;
+ if (m_processor) {
+ m_processor->set_max_message_size(new_value);
+ }
+ }
+
+ /// Get maximum HTTP message body size
+ /**
+ * Get maximum HTTP message body size. Maximum message body size determines
+ * the point at which the connection will stop reading an HTTP request whose
+ * body is too large.
+ *
+ * The default is set by the endpoint that creates the connection.
+ *
+ * @since 0.5.0
+ *
+ * @return The maximum HTTP message body size
+ */
+ size_t get_max_http_body_size() const {
+ return m_request.get_max_body_size();
+ }
+
+ /// Set maximum HTTP message body size
+ /**
+ * Set maximum HTTP message body size. Maximum message body size determines
+ * the point at which the connection will stop reading an HTTP request whose
+ * body is too large.
+ *
+ * The default is set by the endpoint that creates the connection.
+ *
+ * @since 0.5.0
+ *
+ * @param new_value The value to set as the maximum message size.
+ */
+ void set_max_http_body_size(size_t new_value) {
+ m_request.set_max_body_size(new_value);
+ }
+
+ //////////////////////////////////
+ // Uncategorized public methods //
+ //////////////////////////////////
+
+ /// Get the size of the outgoing write buffer (in payload bytes)
+ /**
+ * Retrieves the number of bytes in the outgoing write buffer that have not
+ * already been dispatched to the transport layer. This represents the bytes
+ * that are presently cancelable without uncleanly ending the websocket
+ * connection
+ *
+ * This method invokes the m_write_lock mutex
+ *
+ * @return The current number of bytes in the outgoing send buffer.
+ */
+ size_t get_buffered_amount() const;
+
+ /// Get the size of the outgoing write buffer (in payload bytes)
+ /**
+ * @deprecated use `get_buffered_amount` instead
+ */
+ size_t buffered_amount() const {
+ return get_buffered_amount();
+ }
+
+ ////////////////////
+ // Action Methods //
+ ////////////////////
+
+ /// Create a message and then add it to the outgoing send queue
+ /**
+ * Convenience method to send a message given a payload string and
+ * optionally an opcode. Default opcode is utf8 text.
+ *
+ * This method locks the m_write_lock mutex
+ *
+ * @param payload The payload string to generated the message with
+ *
+ * @param op The opcode to generated the message with. Default is
+ * frame::opcode::text
+ */
+ lib::error_code send(std::string const & payload, frame::opcode::value op =
+ frame::opcode::text);
+
+ /// Send a message (raw array overload)
+ /**
+ * Convenience method to send a message given a raw array and optionally an
+ * opcode. Default opcode is binary.
+ *
+ * This method locks the m_write_lock mutex
+ *
+ * @param payload A pointer to the array containing the bytes to send.
+ *
+ * @param len Length of the array.
+ *
+ * @param op The opcode to generated the message with. Default is
+ * frame::opcode::binary
+ */
+ lib::error_code send(void const * payload, size_t len, frame::opcode::value
+ op = frame::opcode::binary);
+
+ /// Add a message to the outgoing send queue
+ /**
+ * If presented with a prepared message it is added without validation or
+ * framing. If presented with an unprepared message it is validated, framed,
+ * and then added
+ *
+ * Errors are returned via an exception
+ * \todo make exception system_error rather than error_code
+ *
+ * This method invokes the m_write_lock mutex
+ *
+ * @param msg A message_ptr to the message to send.
+ */
+ lib::error_code send(message_ptr msg);
+
+ /// Asyncronously invoke handler::on_inturrupt
+ /**
+ * Signals to the connection to asyncronously invoke the on_inturrupt
+ * callback for this connection's handler once it is safe to do so.
+ *
+ * When the on_inturrupt handler callback is called it will be from
+ * within the transport event loop with all the thread safety features
+ * guaranteed by the transport to regular handlers
+ *
+ * Multiple inturrupt signals can be active at once on the same connection
+ *
+ * @return An error code
+ */
+ lib::error_code interrupt();
+
+ /// Transport inturrupt callback
+ void handle_interrupt();
+
+ /// Pause reading of new data
+ /**
+ * Signals to the connection to halt reading of new data. While reading is paused,
+ * the connection will stop reading from its associated socket. In turn this will
+ * result in TCP based flow control kicking in and slowing data flow from the remote
+ * endpoint.
+ *
+ * This is useful for applications that push new requests to a queue to be processed
+ * by another thread and need a way to signal when their request queue is full without
+ * blocking the network processing thread.
+ *
+ * Use `resume_reading()` to resume.
+ *
+ * If supported by the transport this is done asynchronously. As such reading may not
+ * stop until the current read operation completes. Typically you can expect to
+ * receive no more bytes after initiating a read pause than the size of the read
+ * buffer.
+ *
+ * If reading is paused for this connection already nothing is changed.
+ */
+ lib::error_code pause_reading();
+
+ /// Pause reading callback
+ void handle_pause_reading();
+
+ /// Resume reading of new data
+ /**
+ * Signals to the connection to resume reading of new data after it was paused by
+ * `pause_reading()`.
+ *
+ * If reading is not paused for this connection already nothing is changed.
+ */
+ lib::error_code resume_reading();
+
+ /// Resume reading callback
+ void handle_resume_reading();
+
+ /// Send a ping
+ /**
+ * Initiates a ping with the given payload/
+ *
+ * There is no feedback directly from ping except in cases of immediately
+ * detectable errors. Feedback will be provided via on_pong or
+ * on_pong_timeout callbacks.
+ *
+ * Ping locks the m_write_lock mutex
+ *
+ * @param payload Payload to be used for the ping
+ */
+ void ping(std::string const & payload);
+
+ /// exception free variant of ping
+ void ping(std::string const & payload, lib::error_code & ec);
+
+ /// Utility method that gets called back when the ping timer expires
+ void handle_pong_timeout(std::string payload, lib::error_code const & ec);
+
+ /// Send a pong
+ /**
+ * Initiates a pong with the given payload.
+ *
+ * There is no feedback from a pong once sent.
+ *
+ * Pong locks the m_write_lock mutex
+ *
+ * @param payload Payload to be used for the pong
+ */
+ void pong(std::string const & payload);
+
+ /// exception free variant of pong
+ void pong(std::string const & payload, lib::error_code & ec);
+
+ /// Close the connection
+ /**
+ * Initiates the close handshake process.
+ *
+ * If close returns successfully the connection will be in the closing
+ * state and no additional messages may be sent. All messages sent prior
+ * to calling close will be written out before the connection is closed.
+ *
+ * If no reason is specified none will be sent. If no code is specified
+ * then no code will be sent.
+ *
+ * The handler's on_close callback will be called once the close handshake
+ * is complete.
+ *
+ * Reasons will be automatically truncated to the maximum length (123 bytes)
+ * if necessary.
+ *
+ * @param code The close code to send
+ * @param reason The close reason to send
+ */
+ void close(close::status::value const code, std::string const & reason);
+
+ /// exception free variant of close
+ void close(close::status::value const code, std::string const & reason,
+ lib::error_code & ec);
+
+ ////////////////////////////////////////////////
+ // Pass-through access to the uri information //
+ ////////////////////////////////////////////////
+
+ /// Returns the secure flag from the connection URI
+ /**
+ * This value is available after the HTTP request has been fully read and
+ * may be called from any thread.
+ *
+ * @return Whether or not the connection URI is flagged secure.
+ */
+ bool get_secure() const;
+
+ /// Returns the host component of the connection URI
+ /**
+ * This value is available after the HTTP request has been fully read and
+ * may be called from any thread.
+ *
+ * @return The host component of the connection URI
+ */
+ std::string const & get_host() const;
+
+ /// Returns the resource component of the connection URI
+ /**
+ * This value is available after the HTTP request has been fully read and
+ * may be called from any thread.
+ *
+ * @return The resource component of the connection URI
+ */
+ std::string const & get_resource() const;
+
+ /// Returns the port component of the connection URI
+ /**
+ * This value is available after the HTTP request has been fully read and
+ * may be called from any thread.
+ *
+ * @return The port component of the connection URI
+ */
+ uint16_t get_port() const;
+
+ /// Gets the connection URI
+ /**
+ * This should really only be called by internal library methods unless you
+ * really know what you are doing.
+ *
+ * @return A pointer to the connection's URI
+ */
+ uri_ptr get_uri() const;
+
+ /// Sets the connection URI
+ /**
+ * This should really only be called by internal library methods unless you
+ * really know what you are doing.
+ *
+ * @param uri The new URI to set
+ */
+ void set_uri(uri_ptr uri);
+
+ /////////////////////////////
+ // Subprotocol negotiation //
+ /////////////////////////////
+
+ /// Gets the negotated subprotocol
+ /**
+ * Retrieves the subprotocol that was negotiated during the handshake. This
+ * method is valid in the open handler and later.
+ *
+ * @return The negotiated subprotocol
+ */
+ std::string const & get_subprotocol() const;
+
+ /// Gets all of the subprotocols requested by the client
+ /**
+ * Retrieves the subprotocols that were requested during the handshake. This
+ * method is valid in the validate handler and later.
+ *
+ * @return A vector of the requested subprotocol
+ */
+ std::vector<std::string> const & get_requested_subprotocols() const;
+
+ /// Adds the given subprotocol string to the request list (exception free)
+ /**
+ * Adds a subprotocol to the list to send with the opening handshake. This
+ * may be called multiple times to request more than one. If the server
+ * supports one of these, it may choose one. If so, it will return it
+ * in it's handshake reponse and the value will be available via
+ * get_subprotocol(). Subprotocol requests should be added in order of
+ * preference.
+ *
+ * @param request The subprotocol to request
+ * @param ec A reference to an error code that will be filled in the case of
+ * errors
+ */
+ void add_subprotocol(std::string const & request, lib::error_code & ec);
+
+ /// Adds the given subprotocol string to the request list
+ /**
+ * Adds a subprotocol to the list to send with the opening handshake. This
+ * may be called multiple times to request more than one. If the server
+ * supports one of these, it may choose one. If so, it will return it
+ * in it's handshake reponse and the value will be available via
+ * get_subprotocol(). Subprotocol requests should be added in order of
+ * preference.
+ *
+ * @param request The subprotocol to request
+ */
+ void add_subprotocol(std::string const & request);
+
+ /// Select a subprotocol to use (exception free)
+ /**
+ * Indicates which subprotocol should be used for this connection. Valid
+ * only during the validate handler callback. Subprotocol selected must have
+ * been requested by the client. Consult get_requested_subprotocols() for a
+ * list of valid subprotocols.
+ *
+ * This member function is valid on server endpoints/connections only
+ *
+ * @param value The subprotocol to select
+ * @param ec A reference to an error code that will be filled in the case of
+ * errors
+ */
+ void select_subprotocol(std::string const & value, lib::error_code & ec);
+
+ /// Select a subprotocol to use
+ /**
+ * Indicates which subprotocol should be used for this connection. Valid
+ * only during the validate handler callback. Subprotocol selected must have
+ * been requested by the client. Consult get_requested_subprotocols() for a
+ * list of valid subprotocols.
+ *
+ * This member function is valid on server endpoints/connections only
+ *
+ * @param value The subprotocol to select
+ */
+ void select_subprotocol(std::string const & value);
+
+ /////////////////////////////////////////////////////////////
+ // Pass-through access to the request and response objects //
+ /////////////////////////////////////////////////////////////
+
+ /// Retrieve a request header
+ /**
+ * Retrieve the value of a header from the handshake HTTP request.
+ *
+ * @param key Name of the header to get
+ * @return The value of the header
+ */
+ std::string const & get_request_header(std::string const & key) const;
+
+ /// Retrieve a request body
+ /**
+ * Retrieve the value of the request body. This value is typically used with
+ * PUT and POST requests to upload files or other data. Only HTTP
+ * connections will ever have bodies. WebSocket connection's will always
+ * have blank bodies.
+ *
+ * @return The value of the request body.
+ */
+ std::string const & get_request_body() const;
+
+ /// Retrieve a response header
+ /**
+ * Retrieve the value of a header from the handshake HTTP request.
+ *
+ * @param key Name of the header to get
+ * @return The value of the header
+ */
+ std::string const & get_response_header(std::string const & key) const;
+
+ /// Get response HTTP status code
+ /**
+ * Gets the response status code
+ *
+ * @since 0.7.0
+ *
+ * @return The response status code sent
+ */
+ http::status_code::value get_response_code() const {
+ return m_response.get_status_code();
+ }
+
+ /// Get response HTTP status message
+ /**
+ * Gets the response status message
+ *
+ * @since 0.7.0
+ *
+ * @return The response status message sent
+ */
+ std::string const & get_response_msg() const {
+ return m_response.get_status_msg();
+ }
+
+ /// Set response status code and message
+ /**
+ * Sets the response status code to `code` and looks up the corresponding
+ * message for standard codes. Non-standard codes will be entered as Unknown
+ * use set_status(status_code::value,std::string) overload to set both
+ * values explicitly.
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks.
+ *
+ * @param code Code to set
+ * @param msg Message to set
+ * @see websocketpp::http::response::set_status
+ */
+ void set_status(http::status_code::value code);
+
+ /// Set response status code and message
+ /**
+ * Sets the response status code and message to independent custom values.
+ * use set_status(status_code::value) to set the code and have the standard
+ * message be automatically set.
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks.
+ *
+ * @param code Code to set
+ * @param msg Message to set
+ * @see websocketpp::http::response::set_status
+ */
+ void set_status(http::status_code::value code, std::string const & msg);
+
+ /// Set response body content
+ /**
+ * Set the body content of the HTTP response to the parameter string. Note
+ * set_body will also set the Content-Length HTTP header to the appropriate
+ * value. If you want the Content-Length header to be something else set it
+ * to something else after calling set_body
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks.
+ *
+ * @param value String data to include as the body content.
+ * @see websocketpp::http::response::set_body
+ */
+ void set_body(std::string const & value);
+
+ /// Append a header
+ /**
+ * If a header with this name already exists the value will be appended to
+ * the existing header to form a comma separated list of values. Use
+ * `connection::replace_header` to overwrite existing values.
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks, or to a client connection before connect has been called.
+ *
+ * @param key Name of the header to set
+ * @param val Value to add
+ * @see replace_header
+ * @see websocketpp::http::parser::append_header
+ */
+ void append_header(std::string const & key, std::string const & val);
+
+ /// Replace a header
+ /**
+ * If a header with this name already exists the old value will be replaced
+ * Use `connection::append_header` to append to a list of existing values.
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks, or to a client connection before connect has been called.
+ *
+ * @param key Name of the header to set
+ * @param val Value to set
+ * @see append_header
+ * @see websocketpp::http::parser::replace_header
+ */
+ void replace_header(std::string const & key, std::string const & val);
+
+ /// Remove a header
+ /**
+ * Removes a header from the response.
+ *
+ * This member function is valid only from the http() and validate() handler
+ * callbacks, or to a client connection before connect has been called.
+ *
+ * @param key The name of the header to remove
+ * @see websocketpp::http::parser::remove_header
+ */
+ void remove_header(std::string const & key);
+
+ /// Get request object
+ /**
+ * Direct access to request object. This can be used to call methods of the
+ * request object that are not part of the standard request API that
+ * connection wraps.
+ *
+ * Note use of this method involves using behavior specific to the
+ * configured HTTP policy. Such behavior may not work with alternate HTTP
+ * policies.
+ *
+ * @since 0.3.0-alpha3
+ *
+ * @return A const reference to the raw request object
+ */
+ request_type const & get_request() const {
+ return m_request;
+ }
+
+ /// Get response object
+ /**
+ * Direct access to the HTTP response sent or received as a part of the
+ * opening handshake. This can be used to call methods of the response
+ * object that are not part of the standard request API that connection
+ * wraps.
+ *
+ * Note use of this method involves using behavior specific to the
+ * configured HTTP policy. Such behavior may not work with alternate HTTP
+ * policies.
+ *
+ * @since 0.7.0
+ *
+ * @return A const reference to the raw response object
+ */
+ response_type const & get_response() const {
+ return m_response;
+ }
+
+ /// Defer HTTP Response until later (Exception free)
+ /**
+ * Used in the http handler to defer the HTTP response for this connection
+ * until later. Handshake timers will be canceled and the connection will be
+ * left open until `send_http_response` or an equivalent is called.
+ *
+ * Warning: deferred connections won't time out and as a result can tie up
+ * resources.
+ *
+ * @since 0.6.0
+ *
+ * @return A status code, zero on success, non-zero otherwise
+ */
+ lib::error_code defer_http_response();
+
+ /// Send deferred HTTP Response (exception free)
+ /**
+ * Sends an http response to an HTTP connection that was deferred. This will
+ * send a complete response including all headers, status line, and body
+ * text. The connection will be closed afterwards.
+ *
+ * @since 0.6.0
+ *
+ * @param ec A status code, zero on success, non-zero otherwise
+ */
+ void send_http_response(lib::error_code & ec);
+
+ /// Send deferred HTTP Response
+ void send_http_response();
+
+ // TODO HTTPNBIO: write_headers
+ // function that processes headers + status so far and writes it to the wire
+ // beginning the HTTP response body state. This method will ignore anything
+ // in the response body.
+
+ // TODO HTTPNBIO: write_body_message
+ // queues the specified message_buffer for async writing
+
+ // TODO HTTPNBIO: finish connection
+ //
+
+ // TODO HTTPNBIO: write_response
+ // Writes the whole response, headers + body and closes the connection
+
+
+
+ /////////////////////////////////////////////////////////////
+ // Pass-through access to the other connection information //
+ /////////////////////////////////////////////////////////////
+
+ /// Get Connection Handle
+ /**
+ * The connection handle is a token that can be shared outside the
+ * WebSocket++ core for the purposes of identifying a connection and
+ * sending it messages.
+ *
+ * @return A handle to the connection
+ */
+ connection_hdl get_handle() const {
+ return m_connection_hdl;
+ }
+
+ /// Get whether or not this connection is part of a server or client
+ /**
+ * @return whether or not the connection is attached to a server endpoint
+ */
+ bool is_server() const {
+ return m_is_server;
+ }
+
+ /// Return the same origin policy origin value from the opening request.
+ /**
+ * This value is available after the HTTP request has been fully read and
+ * may be called from any thread.
+ *
+ * @return The connection's origin value from the opening handshake.
+ */
+ std::string const & get_origin() const;
+
+ /// Return the connection state.
+ /**
+ * Values can be connecting, open, closing, and closed
+ *
+ * @return The connection's current state.
+ */
+ session::state::value get_state() const;
+
+
+ /// Get the WebSocket close code sent by this endpoint.
+ /**
+ * @return The WebSocket close code sent by this endpoint.
+ */
+ close::status::value get_local_close_code() const {
+ return m_local_close_code;
+ }
+
+ /// Get the WebSocket close reason sent by this endpoint.
+ /**
+ * @return The WebSocket close reason sent by this endpoint.
+ */
+ std::string const & get_local_close_reason() const {
+ return m_local_close_reason;
+ }
+
+ /// Get the WebSocket close code sent by the remote endpoint.
+ /**
+ * @return The WebSocket close code sent by the remote endpoint.
+ */
+ close::status::value get_remote_close_code() const {
+ return m_remote_close_code;
+ }
+
+ /// Get the WebSocket close reason sent by the remote endpoint.
+ /**
+ * @return The WebSocket close reason sent by the remote endpoint.
+ */
+ std::string const & get_remote_close_reason() const {
+ return m_remote_close_reason;
+ }
+
+ /// Get the internal error code for a closed/failed connection
+ /**
+ * Retrieves a machine readable detailed error code indicating the reason
+ * that the connection was closed or failed. Valid only after the close or
+ * fail handler is called.
+ *
+ * @return Error code indicating the reason the connection was closed or
+ * failed
+ */
+ lib::error_code get_ec() const {
+ return m_ec;
+ }
+
+ /// Get a message buffer
+ /**
+ * Warning: The API related to directly sending message buffers may change
+ * before the 1.0 release. If you plan to use it, please keep an eye on any
+ * breaking changes notifications in future release notes. Also if you have
+ * any feedback about usage and capabilities now is a great time to provide
+ * it.
+ *
+ * Message buffers are used to store message payloads and other message
+ * metadata.
+ *
+ * The size parameter is a hint only. Your final payload does not need to
+ * match it. There may be some performance benefits if the initial size
+ * guess is equal to or slightly higher than the final payload size.
+ *
+ * @param op The opcode for the new message
+ * @param size A hint to optimize the initial allocation of payload space.
+ * @return A new message buffer
+ */
+ message_ptr get_message(websocketpp::frame::opcode::value op, size_t size)
+ const
+ {
+ return m_msg_manager->get_message(op, size);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // The remaining public member functions are for internal/policy use //
+ // only. Do not call from application code unless you understand what //
+ // you are doing. //
+ ////////////////////////////////////////////////////////////////////////
+
+
+
+ void read_handshake(size_t num_bytes);
+
+ void handle_read_handshake(lib::error_code const & ec,
+ size_t bytes_transferred);
+ void handle_read_http_response(lib::error_code const & ec,
+ size_t bytes_transferred);
+
+
+ void handle_write_http_response(lib::error_code const & ec);
+ void handle_send_http_request(lib::error_code const & ec);
+
+ void handle_open_handshake_timeout(lib::error_code const & ec);
+ void handle_close_handshake_timeout(lib::error_code const & ec);
+
+ void handle_read_frame(lib::error_code const & ec, size_t bytes_transferred);
+ void read_frame();
+
+ /// Get array of WebSocket protocol versions that this connection supports.
+ std::vector<int> const & get_supported_versions() const;
+
+ /// Sets the handler for a terminating connection. Should only be used
+ /// internally by the endpoint class.
+ void set_termination_handler(termination_handler new_handler);
+
+ void terminate(lib::error_code const & ec);
+ void handle_terminate(terminate_status tstat, lib::error_code const & ec);
+
+ /// Checks if there are frames in the send queue and if there are sends one
+ /**
+ * \todo unit tests
+ *
+ * This method locks the m_write_lock mutex
+ */
+ void write_frame();
+
+ /// Process the results of a frame write operation and start the next write
+ /**
+ * \todo unit tests
+ *
+ * This method locks the m_write_lock mutex
+ *
+ * @param terminate Whether or not to terminate the connection upon
+ * completion of this write.
+ *
+ * @param ec A status code from the transport layer, zero on success,
+ * non-zero otherwise.
+ */
+ void handle_write_frame(lib::error_code const & ec);
+// protected:
+ // This set of methods would really like to be protected, but doing so
+ // requires that the endpoint be able to friend the connection. This is
+ // allowed with C++11, but not prior versions
+
+ /// Start the connection state machine
+ void start();
+
+ /// Set Connection Handle
+ /**
+ * The connection handle is a token that can be shared outside the
+ * WebSocket++ core for the purposes of identifying a connection and
+ * sending it messages.
+ *
+ * @param hdl A connection_hdl that the connection will use to refer
+ * to itself.
+ */
+ void set_handle(connection_hdl hdl) {
+ m_connection_hdl = hdl;
+ transport_con_type::set_handle(hdl);
+ }
+protected:
+ void handle_transport_init(lib::error_code const & ec);
+
+ /// Set m_processor based on information in m_request. Set m_response
+ /// status and return an error code indicating status.
+ lib::error_code initialize_processor();
+
+ /// Perform WebSocket handshake validation of m_request using m_processor.
+ /// set m_response and return an error code indicating status.
+ lib::error_code process_handshake_request();
+private:
+
+
+ /// Completes m_response, serializes it, and sends it out on the wire.
+ void write_http_response(lib::error_code const & ec);
+
+ /// Sends an opening WebSocket connect request
+ void send_http_request();
+
+ /// Alternate path for write_http_response in error conditions
+ void write_http_response_error(lib::error_code const & ec);
+
+ /// Process control message
+ /**
+ *
+ */
+ void process_control_frame(message_ptr msg);
+
+ /// Send close acknowledgement
+ /**
+ * If no arguments are present no close code/reason will be specified.
+ *
+ * Note: the close code/reason values provided here may be overrided by
+ * other settings (such as silent close).
+ *
+ * @param code The close code to send
+ * @param reason The close reason to send
+ * @return A status code, zero on success, non-zero otherwise
+ */
+ lib::error_code send_close_ack(close::status::value code =
+ close::status::blank, std::string const & reason = std::string());
+
+ /// Send close frame
+ /**
+ * If no arguments are present no close code/reason will be specified.
+ *
+ * Note: the close code/reason values provided here may be overrided by
+ * other settings (such as silent close).
+ *
+ * The ack flag determines what to do in the case of a blank status and
+ * whether or not to terminate the TCP connection after sending it.
+ *
+ * @param code The close code to send
+ * @param reason The close reason to send
+ * @param ack Whether or not this is an acknowledgement close frame
+ * @return A status code, zero on success, non-zero otherwise
+ */
+ lib::error_code send_close_frame(close::status::value code =
+ close::status::blank, std::string const & reason = std::string(), bool ack = false,
+ bool terminal = false);
+
+ /// Get a pointer to a new WebSocket protocol processor for a given version
+ /**
+ * @param version Version number of the WebSocket protocol to get a
+ * processor for. Negative values indicate invalid/unknown versions and will
+ * always return a null ptr
+ *
+ * @return A shared_ptr to a new instance of the appropriate processor or a
+ * null ptr if there is no installed processor that matches the version
+ * number.
+ */
+ processor_ptr get_processor(int version) const;
+
+ /// Add a message to the write queue
+ /**
+ * Adds a message to the write queue and updates any associated shared state
+ *
+ * Must be called while holding m_write_lock
+ *
+ * @todo unit tests
+ *
+ * @param msg The message to push
+ */
+ void write_push(message_ptr msg);
+
+ /// Pop a message from the write queue
+ /**
+ * Removes and returns a message from the write queue and updates any
+ * associated shared state.
+ *
+ * Must be called while holding m_write_lock
+ *
+ * @todo unit tests
+ *
+ * @return the message_ptr at the front of the queue
+ */
+ message_ptr write_pop();
+
+ /// Prints information about the incoming connection to the access log
+ /**
+ * Prints information about the incoming connection to the access log.
+ * Includes: connection type, websocket version, remote endpoint, user agent
+ * path, status code.
+ */
+ void log_open_result();
+
+ /// Prints information about a connection being closed to the access log
+ /**
+ * Includes: local and remote close codes and reasons
+ */
+ void log_close_result();
+
+ /// Prints information about a connection being failed to the access log
+ /**
+ * Includes: error code and message for why it was failed
+ */
+ void log_fail_result();
+
+ /// Prints information about HTTP connections
+ /**
+ * Includes: TODO
+ */
+ void log_http_result();
+
+ /// Prints information about an arbitrary error code on the specified channel
+ template <typename error_type>
+ void log_err(log::level l, char const * msg, error_type const & ec) {
+ std::stringstream s;
+ s << msg << " error: " << ec << " (" << ec.message() << ")";
+ m_elog.write(l, s.str());
+ }
+
+ // internal handler functions
+ read_handler m_handle_read_frame;
+ write_frame_handler m_write_frame_handler;
+
+ // static settings
+ std::string const m_user_agent;
+
+ /// Pointer to the connection handle
+ connection_hdl m_connection_hdl;
+
+ /// Handler objects
+ open_handler m_open_handler;
+ close_handler m_close_handler;
+ fail_handler m_fail_handler;
+ ping_handler m_ping_handler;
+ pong_handler m_pong_handler;
+ pong_timeout_handler m_pong_timeout_handler;
+ interrupt_handler m_interrupt_handler;
+ http_handler m_http_handler;
+ validate_handler m_validate_handler;
+ message_handler m_message_handler;
+
+ /// constant values
+ long m_open_handshake_timeout_dur;
+ long m_close_handshake_timeout_dur;
+ long m_pong_timeout_dur;
+ size_t m_max_message_size;
+
+ /// External connection state
+ /**
+ * Lock: m_connection_state_lock
+ */
+ session::state::value m_state;
+
+ /// Internal connection state
+ /**
+ * Lock: m_connection_state_lock
+ */
+ istate_type m_internal_state;
+
+ mutable mutex_type m_connection_state_lock;
+
+ /// The lock used to protect the message queue
+ /**
+ * Serializes access to the write queue as well as shared state within the
+ * processor.
+ */
+ mutex_type m_write_lock;
+
+ // connection resources
+ char m_buf[config::connection_read_buffer_size];
+ size_t m_buf_cursor;
+ termination_handler m_termination_handler;
+ con_msg_manager_ptr m_msg_manager;
+ timer_ptr m_handshake_timer;
+ timer_ptr m_ping_timer;
+
+ /// @todo this is not memory efficient. this value is not used after the
+ /// handshake.
+ std::string m_handshake_buffer;
+
+ /// Pointer to the processor object for this connection
+ /**
+ * The processor provides functionality that is specific to the WebSocket
+ * protocol version that the client has negotiated. It also contains all of
+ * the state necessary to encode and decode the incoming and outgoing
+ * WebSocket byte streams
+ *
+ * Use of the prepare_data_frame method requires lock: m_write_lock
+ */
+ processor_ptr m_processor;
+
+ /// Queue of unsent outgoing messages
+ /**
+ * Lock: m_write_lock
+ */
+ std::queue<message_ptr> m_send_queue;
+
+ /// Size in bytes of the outstanding payloads in the write queue
+ /**
+ * Lock: m_write_lock
+ */
+ size_t m_send_buffer_size;
+
+ /// buffer holding the various parts of the current message being writen
+ /**
+ * Lock m_write_lock
+ */
+ std::vector<transport::buffer> m_send_buffer;
+
+ /// a list of pointers to hold on to the messages being written to keep them
+ /// from going out of scope before the write is complete.
+ std::vector<message_ptr> m_current_msgs;
+
+ /// True if there is currently an outstanding transport write
+ /**
+ * Lock m_write_lock
+ */
+ bool m_write_flag;
+
+ /// True if this connection is presently reading new data
+ bool m_read_flag;
+
+ // connection data
+ request_type m_request;
+ response_type m_response;
+ uri_ptr m_uri;
+ std::string m_subprotocol;
+
+ // connection data that might not be necessary to keep around for the life
+ // of the whole connection.
+ std::vector<std::string> m_requested_subprotocols;
+
+ bool const m_is_server;
+ alog_type& m_alog;
+ elog_type& m_elog;
+
+ rng_type & m_rng;
+
+ // Close state
+ /// Close code that was sent on the wire by this endpoint
+ close::status::value m_local_close_code;
+
+ /// Close reason that was sent on the wire by this endpoint
+ std::string m_local_close_reason;
+
+ /// Close code that was received on the wire from the remote endpoint
+ close::status::value m_remote_close_code;
+
+ /// Close reason that was received on the wire from the remote endpoint
+ std::string m_remote_close_reason;
+
+ /// Detailed internal error code
+ lib::error_code m_ec;
+
+ /// A flag that gets set once it is determined that the connection is an
+ /// HTTP connection and not a WebSocket one.
+ bool m_is_http;
+
+ /// A flag that gets set when the completion of an http connection is
+ /// deferred until later.
+ session::http_state::value m_http_state;
+
+ bool m_was_clean;
+
+ /// Whether or not this endpoint initiated the closing handshake.
+ bool m_closed_by_me;
+
+ /// ???
+ bool m_failed_by_me;
+
+ /// Whether or not this endpoint initiated the drop of the TCP connection
+ bool m_dropped_by_me;
+};
+
+} // namespace websocketpp
+
+#include <websocketpp/impl/connection_impl.hpp>
+
+#endif // WEBSOCKETPP_CONNECTION_HPP