2 * Copyright (c) 2014, Peter Thorson. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of the WebSocket++ Project nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef WEBSOCKETPP_CONNECTION_HPP
29 #define WEBSOCKETPP_CONNECTION_HPP
31 #include <websocketpp/close.hpp>
32 #include <websocketpp/error.hpp>
33 #include <websocketpp/frame.hpp>
35 #include <websocketpp/logger/levels.hpp>
36 #include <websocketpp/processors/processor.hpp>
37 #include <websocketpp/transport/base/connection.hpp>
38 #include <websocketpp/http/constants.hpp>
40 #include <websocketpp/common/connection_hdl.hpp>
41 #include <websocketpp/common/cpp11.hpp>
42 #include <websocketpp/common/functional.hpp>
49 namespace websocketpp {
51 /// The type and function signature of an open handler
53 * The open handler is called once for every successful WebSocket connection
54 * attempt. Either the fail handler or the open handler will be called for each
55 * WebSocket connection attempt. HTTP Connections that did not attempt to
56 * upgrade the connection to the WebSocket protocol will trigger the http
57 * handler instead of fail/open.
59 typedef lib::function<void(connection_hdl)> open_handler;
61 /// The type and function signature of a close handler
63 * The close handler is called once for every successfully established
64 * connection after it is no longer capable of sending or receiving new messages
66 * The close handler will be called exactly once for every connection for which
67 * the open handler was called.
69 typedef lib::function<void(connection_hdl)> close_handler;
71 /// The type and function signature of a fail handler
73 * The fail handler is called once for every unsuccessful WebSocket connection
74 * attempt. Either the fail handler or the open handler will be called for each
75 * WebSocket connection attempt. HTTP Connections that did not attempt to
76 * upgrade the connection to the WebSocket protocol will trigger the http
77 * handler instead of fail/open.
79 typedef lib::function<void(connection_hdl)> fail_handler;
81 /// The type and function signature of an interrupt handler
83 * The interrupt handler is called when a connection receives an interrupt
84 * request from the application. Interrupts allow the application to trigger a
85 * handler to be run in the absense of a WebSocket level handler trigger (like
88 * This is typically used by another application thread to schedule some tasks
89 * that can only be run from within the handler chain for thread safety reasons.
91 typedef lib::function<void(connection_hdl)> interrupt_handler;
93 /// The type and function signature of a ping handler
95 * The ping handler is called when the connection receives a WebSocket ping
96 * control frame. The string argument contains the ping payload. The payload is
97 * a binary string up to 126 bytes in length. The ping handler returns a bool,
98 * true if a pong response should be sent, false if the pong response should be
101 typedef lib::function<bool(connection_hdl,std::string)> ping_handler;
103 /// The type and function signature of a pong handler
105 * The pong handler is called when the connection receives a WebSocket pong
106 * control frame. The string argument contains the pong payload. The payload is
107 * a binary string up to 126 bytes in length.
109 typedef lib::function<void(connection_hdl,std::string)> pong_handler;
111 /// The type and function signature of a pong timeout handler
113 * The pong timeout handler is called when a ping goes unanswered by a pong for
114 * longer than the locally specified timeout period.
116 typedef lib::function<void(connection_hdl,std::string)> pong_timeout_handler;
118 /// The type and function signature of a validate handler
120 * The validate handler is called after a WebSocket handshake has been received
121 * and processed but before it has been accepted. This gives the application a
122 * chance to implement connection details specific policies for accepting
123 * connections and the ability to negotiate extensions and subprotocols.
125 * The validate handler return value indicates whether or not the connection
126 * should be accepted. Additional methods may be called during the function to
127 * set response headers, set HTTP return/error codes, etc.
129 typedef lib::function<bool(connection_hdl)> validate_handler;
131 /// The type and function signature of a http handler
133 * The http handler is called when an HTTP connection is made that does not
134 * attempt to upgrade the connection to the WebSocket protocol. This allows
135 * WebSocket++ servers to respond to these requests with regular HTTP responses.
137 * This can be used to deliver error pages & dashboards and to deliver static
138 * files such as the base HTML & JavaScript for an otherwise single page
139 * WebSocket application.
141 * Note: WebSocket++ is designed to be a high performance WebSocket server. It
142 * is not tuned to provide a full featured, high performance, HTTP web server
143 * solution. The HTTP handler is appropriate only for low volume HTTP traffic.
144 * If you expect to serve high volumes of HTTP traffic a dedicated HTTP web
145 * server is strongly recommended.
147 * The default HTTP handler will return a 426 Upgrade Required error. Custom
148 * handlers may override the response status code to deliver any type of
151 typedef lib::function<void(connection_hdl)> http_handler;
154 typedef lib::function<void(lib::error_code const & ec, size_t bytes_transferred)> read_handler;
155 typedef lib::function<void(lib::error_code const & ec)> write_frame_handler;
157 // constants related to the default WebSocket protocol versions available
158 #ifdef _WEBSOCKETPP_INITIALIZER_LISTS_ // simplified C++11 version
159 /// Container that stores the list of protocol versions supported
161 * @todo Move this to configs to allow compile/runtime disabling or enabling
162 * of protocol versions
164 static std::vector<int> const versions_supported = {0,7,8,13};
166 /// Helper array to get around lack of initializer lists pre C++11
167 static int const helper[] = {0,7,8,13};
168 /// Container that stores the list of protocol versions supported
170 * @todo Move this to configs to allow compile/runtime disabling or enabling
171 * of protocol versions
173 static std::vector<int> const versions_supported(helper,helper+4);
178 // externally visible session state (states based on the RFC)
191 GOOD = 0, // no failure yet!
192 SYSTEM = 1, // system call returned error, check that code
193 WEBSOCKET = 2, // websocket close codes contain error
194 UNKNOWN = 3, // No failure information is available
195 TIMEOUT_TLS = 4, // TLS handshake timed out
196 TIMEOUT_WS = 5 // WS handshake timed out
198 } // namespace status
201 namespace internal_state {
202 // More granular internal states. These are used for multi-threaded
203 // connection synchronization and preventing values that are not yet or no
204 // longer available from being used.
209 READ_HTTP_REQUEST = 2,
210 WRITE_HTTP_REQUEST = 3,
211 READ_HTTP_RESPONSE = 4,
212 WRITE_HTTP_RESPONSE = 5,
213 PROCESS_HTTP_REQUEST = 6,
214 PROCESS_CONNECTION = 7
216 } // namespace internal_state
219 namespace http_state {
220 // states to keep track of the progress of http connections
229 } // namespace http_state
231 } // namespace session
233 /// Represents an individual WebSocket connection
234 template <typename config>
236 : public config::transport_type::transport_con_type
237 , public config::connection_base
240 /// Type of this connection
241 typedef connection<config> type;
242 /// Type of a shared pointer to this connection
243 typedef lib::shared_ptr<type> ptr;
244 /// Type of a weak pointer to this connection
245 typedef lib::weak_ptr<type> weak_ptr;
247 /// Type of the concurrency component of this connection
248 typedef typename config::concurrency_type concurrency_type;
249 /// Type of the access logging policy
250 typedef typename config::alog_type alog_type;
251 /// Type of the error logging policy
252 typedef typename config::elog_type elog_type;
254 /// Type of the transport component of this connection
255 typedef typename config::transport_type::transport_con_type
257 /// Type of a shared pointer to the transport component of this connection
258 typedef typename transport_con_type::ptr transport_con_ptr;
260 typedef lib::function<void(ptr)> termination_handler;
262 typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
263 typedef typename concurrency_type::mutex_type mutex_type;
265 typedef typename config::request_type request_type;
266 typedef typename config::response_type response_type;
268 typedef typename config::message_type message_type;
269 typedef typename message_type::ptr message_ptr;
271 typedef typename config::con_msg_manager_type con_msg_manager_type;
272 typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
275 typedef typename config::rng_type rng_type;
277 typedef processor::processor<config> processor_type;
278 typedef lib::shared_ptr<processor_type> processor_ptr;
280 // Message handler (needs to know message type)
281 typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
283 /// Type of a pointer to a transport timer handle
284 typedef typename transport_con_type::timer_ptr timer_ptr;
286 // Misc Convenience Types
287 typedef session::internal_state::value istate_type;
290 enum terminate_status {
297 explicit connection(bool p_is_server, std::string const & ua, alog_type& alog,
298 elog_type& elog, rng_type & rng)
299 : transport_con_type(p_is_server, alog, elog)
300 , m_handle_read_frame(lib::bind(
301 &type::handle_read_frame,
303 lib::placeholders::_1,
304 lib::placeholders::_2
306 , m_write_frame_handler(lib::bind(
307 &type::handle_write_frame,
309 lib::placeholders::_1
312 , m_open_handshake_timeout_dur(config::timeout_open_handshake)
313 , m_close_handshake_timeout_dur(config::timeout_close_handshake)
314 , m_pong_timeout_dur(config::timeout_pong)
315 , m_max_message_size(config::max_message_size)
316 , m_state(session::state::connecting)
317 , m_internal_state(session::internal_state::USER_INIT)
318 , m_msg_manager(new con_msg_manager_type())
319 , m_send_buffer_size(0)
320 , m_write_flag(false)
322 , m_is_server(p_is_server)
326 , m_local_close_code(close::status::abnormal_close)
327 , m_remote_close_code(close::status::abnormal_close)
329 , m_http_state(session::http_state::init)
332 m_alog.write(log::alevel::devel,"connection constructor");
335 /// Get a shared pointer to this component
337 return lib::static_pointer_cast<type>(transport_con_type::get_shared());
340 ///////////////////////////
341 // Set Handler Callbacks //
342 ///////////////////////////
346 * The open handler is called after the WebSocket handshake is complete and
347 * the connection is considered OPEN.
349 * @param h The new open_handler
351 void set_open_handler(open_handler h) {
355 /// Set close handler
357 * The close handler is called immediately after the connection is closed.
359 * @param h The new close_handler
361 void set_close_handler(close_handler h) {
367 * The fail handler is called whenever the connection fails while the
368 * handshake is bring processed.
370 * @param h The new fail_handler
372 void set_fail_handler(fail_handler h) {
378 * The ping handler is called whenever the connection receives a ping
379 * control frame. The ping payload is included.
381 * The ping handler's return time controls whether or not a pong is
382 * sent in response to this ping. Returning false will suppress the
383 * return pong. If no ping handler is set a pong will be sent.
385 * @param h The new ping_handler
387 void set_ping_handler(ping_handler h) {
393 * The pong handler is called whenever the connection receives a pong
394 * control frame. The pong payload is included.
396 * @param h The new pong_handler
398 void set_pong_handler(pong_handler h) {
402 /// Set pong timeout handler
404 * If the transport component being used supports timers, the pong timeout
405 * handler is called whenever a pong control frame is not received with the
406 * configured timeout period after the application sends a ping.
408 * The config setting `timeout_pong` controls the length of the timeout
409 * period. It is specified in milliseconds.
411 * This can be used to probe the health of the remote endpoint's WebSocket
412 * implementation. This does not guarantee that the remote application
413 * itself is still healthy but can be a useful diagnostic.
415 * Note: receipt of this callback doesn't mean the pong will never come.
416 * This functionality will not suppress delivery of the pong in question
417 * should it arrive after the timeout.
419 * @param h The new pong_timeout_handler
421 void set_pong_timeout_handler(pong_timeout_handler h) {
422 m_pong_timeout_handler = h;
425 /// Set interrupt handler
427 * The interrupt handler is called whenever the connection is manually
428 * interrupted by the application.
430 * @param h The new interrupt_handler
432 void set_interrupt_handler(interrupt_handler h) {
433 m_interrupt_handler = h;
438 * The http handler is called after an HTTP request other than a WebSocket
439 * upgrade request is received. It allows a WebSocket++ server to respond
440 * to regular HTTP requests on the same port as it processes WebSocket
441 * connections. This can be useful for hosting error messages, flash
442 * policy files, status pages, and other simple HTTP responses. It is not
443 * intended to be used as a primary web server.
445 * @param h The new http_handler
447 void set_http_handler(http_handler h) {
451 /// Set validate handler
453 * The validate handler is called after a WebSocket handshake has been
454 * parsed but before a response is returned. It provides the application
455 * a chance to examine the request and determine whether or not it wants
456 * to accept the connection.
458 * Returning false from the validate handler will reject the connection.
459 * If no validate handler is present, all connections will be allowed.
461 * @param h The new validate_handler
463 void set_validate_handler(validate_handler h) {
464 m_validate_handler = h;
467 /// Set message handler
469 * The message handler is called after a new message has been received.
471 * @param h The new message_handler
473 void set_message_handler(message_handler h) {
474 m_message_handler = h;
477 //////////////////////////////////////////
478 // Connection timeouts and other limits //
479 //////////////////////////////////////////
481 /// Set open handshake timeout
483 * Sets the length of time the library will wait after an opening handshake
484 * has been initiated before cancelling it. This can be used to prevent
485 * excessive wait times for outgoing clients or excessive resource usage
486 * from broken clients or DoS attacks on servers.
488 * Connections that time out will have their fail handlers called with the
489 * open_handshake_timeout error code.
491 * The default value is specified via the compile time config value
492 * 'timeout_open_handshake'. The default value in the core config
493 * is 5000ms. A value of 0 will disable the timer entirely.
495 * To be effective, the transport you are using must support timers. See
496 * the documentation for your transport policy for details about its
499 * @param dur The length of the open handshake timeout in ms
501 void set_open_handshake_timeout(long dur) {
502 m_open_handshake_timeout_dur = dur;
505 /// Set close handshake timeout
507 * Sets the length of time the library will wait after a closing handshake
508 * has been initiated before cancelling it. This can be used to prevent
509 * excessive wait times for outgoing clients or excessive resource usage
510 * from broken clients or DoS attacks on servers.
512 * Connections that time out will have their close handlers called with the
513 * close_handshake_timeout error code.
515 * The default value is specified via the compile time config value
516 * 'timeout_close_handshake'. The default value in the core config
517 * is 5000ms. A value of 0 will disable the timer entirely.
519 * To be effective, the transport you are using must support timers. See
520 * the documentation for your transport policy for details about its
523 * @param dur The length of the close handshake timeout in ms
525 void set_close_handshake_timeout(long dur) {
526 m_close_handshake_timeout_dur = dur;
531 * Sets the length of time the library will wait for a pong response to a
532 * ping. This can be used as a keepalive or to detect broken connections.
534 * Pong responses that time out will have the pong timeout handler called.
536 * The default value is specified via the compile time config value
537 * 'timeout_pong'. The default value in the core config
538 * is 5000ms. A value of 0 will disable the timer entirely.
540 * To be effective, the transport you are using must support timers. See
541 * the documentation for your transport policy for details about its
544 * @param dur The length of the pong timeout in ms
546 void set_pong_timeout(long dur) {
547 m_pong_timeout_dur = dur;
550 /// Get maximum message size
552 * Get maximum message size. Maximum message size determines the point at
553 * which the connection will fail with the message_too_big protocol error.
555 * The default is set by the endpoint that creates the connection.
559 size_t get_max_message_size() const {
560 return m_max_message_size;
563 /// Set maximum message size
565 * Set maximum message size. Maximum message size determines the point at
566 * which the connection will fail with the message_too_big protocol error.
567 * This value may be changed during the connection.
569 * The default is set by the endpoint that creates the connection.
573 * @param new_value The value to set as the maximum message size.
575 void set_max_message_size(size_t new_value) {
576 m_max_message_size = new_value;
578 m_processor->set_max_message_size(new_value);
582 /// Get maximum HTTP message body size
584 * Get maximum HTTP message body size. Maximum message body size determines
585 * the point at which the connection will stop reading an HTTP request whose
588 * The default is set by the endpoint that creates the connection.
592 * @return The maximum HTTP message body size
594 size_t get_max_http_body_size() const {
595 return m_request.get_max_body_size();
598 /// Set maximum HTTP message body size
600 * Set maximum HTTP message body size. Maximum message body size determines
601 * the point at which the connection will stop reading an HTTP request whose
604 * The default is set by the endpoint that creates the connection.
608 * @param new_value The value to set as the maximum message size.
610 void set_max_http_body_size(size_t new_value) {
611 m_request.set_max_body_size(new_value);
614 //////////////////////////////////
615 // Uncategorized public methods //
616 //////////////////////////////////
618 /// Get the size of the outgoing write buffer (in payload bytes)
620 * Retrieves the number of bytes in the outgoing write buffer that have not
621 * already been dispatched to the transport layer. This represents the bytes
622 * that are presently cancelable without uncleanly ending the websocket
625 * This method invokes the m_write_lock mutex
627 * @return The current number of bytes in the outgoing send buffer.
629 size_t get_buffered_amount() const;
631 /// Get the size of the outgoing write buffer (in payload bytes)
633 * @deprecated use `get_buffered_amount` instead
635 size_t buffered_amount() const {
636 return get_buffered_amount();
643 /// Create a message and then add it to the outgoing send queue
645 * Convenience method to send a message given a payload string and
646 * optionally an opcode. Default opcode is utf8 text.
648 * This method locks the m_write_lock mutex
650 * @param payload The payload string to generated the message with
652 * @param op The opcode to generated the message with. Default is
653 * frame::opcode::text
655 lib::error_code send(std::string const & payload, frame::opcode::value op =
656 frame::opcode::text);
658 /// Send a message (raw array overload)
660 * Convenience method to send a message given a raw array and optionally an
661 * opcode. Default opcode is binary.
663 * This method locks the m_write_lock mutex
665 * @param payload A pointer to the array containing the bytes to send.
667 * @param len Length of the array.
669 * @param op The opcode to generated the message with. Default is
670 * frame::opcode::binary
672 lib::error_code send(void const * payload, size_t len, frame::opcode::value
673 op = frame::opcode::binary);
675 /// Add a message to the outgoing send queue
677 * If presented with a prepared message it is added without validation or
678 * framing. If presented with an unprepared message it is validated, framed,
681 * Errors are returned via an exception
682 * \todo make exception system_error rather than error_code
684 * This method invokes the m_write_lock mutex
686 * @param msg A message_ptr to the message to send.
688 lib::error_code send(message_ptr msg);
690 /// Asyncronously invoke handler::on_inturrupt
692 * Signals to the connection to asyncronously invoke the on_inturrupt
693 * callback for this connection's handler once it is safe to do so.
695 * When the on_inturrupt handler callback is called it will be from
696 * within the transport event loop with all the thread safety features
697 * guaranteed by the transport to regular handlers
699 * Multiple inturrupt signals can be active at once on the same connection
701 * @return An error code
703 lib::error_code interrupt();
705 /// Transport inturrupt callback
706 void handle_interrupt();
708 /// Pause reading of new data
710 * Signals to the connection to halt reading of new data. While reading is paused,
711 * the connection will stop reading from its associated socket. In turn this will
712 * result in TCP based flow control kicking in and slowing data flow from the remote
715 * This is useful for applications that push new requests to a queue to be processed
716 * by another thread and need a way to signal when their request queue is full without
717 * blocking the network processing thread.
719 * Use `resume_reading()` to resume.
721 * If supported by the transport this is done asynchronously. As such reading may not
722 * stop until the current read operation completes. Typically you can expect to
723 * receive no more bytes after initiating a read pause than the size of the read
726 * If reading is paused for this connection already nothing is changed.
728 lib::error_code pause_reading();
730 /// Pause reading callback
731 void handle_pause_reading();
733 /// Resume reading of new data
735 * Signals to the connection to resume reading of new data after it was paused by
738 * If reading is not paused for this connection already nothing is changed.
740 lib::error_code resume_reading();
742 /// Resume reading callback
743 void handle_resume_reading();
747 * Initiates a ping with the given payload/
749 * There is no feedback directly from ping except in cases of immediately
750 * detectable errors. Feedback will be provided via on_pong or
751 * on_pong_timeout callbacks.
753 * Ping locks the m_write_lock mutex
755 * @param payload Payload to be used for the ping
757 void ping(std::string const & payload);
759 /// exception free variant of ping
760 void ping(std::string const & payload, lib::error_code & ec);
762 /// Utility method that gets called back when the ping timer expires
763 void handle_pong_timeout(std::string payload, lib::error_code const & ec);
767 * Initiates a pong with the given payload.
769 * There is no feedback from a pong once sent.
771 * Pong locks the m_write_lock mutex
773 * @param payload Payload to be used for the pong
775 void pong(std::string const & payload);
777 /// exception free variant of pong
778 void pong(std::string const & payload, lib::error_code & ec);
780 /// Close the connection
782 * Initiates the close handshake process.
784 * If close returns successfully the connection will be in the closing
785 * state and no additional messages may be sent. All messages sent prior
786 * to calling close will be written out before the connection is closed.
788 * If no reason is specified none will be sent. If no code is specified
789 * then no code will be sent.
791 * The handler's on_close callback will be called once the close handshake
794 * Reasons will be automatically truncated to the maximum length (123 bytes)
797 * @param code The close code to send
798 * @param reason The close reason to send
800 void close(close::status::value const code, std::string const & reason);
802 /// exception free variant of close
803 void close(close::status::value const code, std::string const & reason,
804 lib::error_code & ec);
806 ////////////////////////////////////////////////
807 // Pass-through access to the uri information //
808 ////////////////////////////////////////////////
810 /// Returns the secure flag from the connection URI
812 * This value is available after the HTTP request has been fully read and
813 * may be called from any thread.
815 * @return Whether or not the connection URI is flagged secure.
817 bool get_secure() const;
819 /// Returns the host component of the connection URI
821 * This value is available after the HTTP request has been fully read and
822 * may be called from any thread.
824 * @return The host component of the connection URI
826 std::string const & get_host() const;
828 /// Returns the resource component of the connection URI
830 * This value is available after the HTTP request has been fully read and
831 * may be called from any thread.
833 * @return The resource component of the connection URI
835 std::string const & get_resource() const;
837 /// Returns the port component of the connection URI
839 * This value is available after the HTTP request has been fully read and
840 * may be called from any thread.
842 * @return The port component of the connection URI
844 uint16_t get_port() const;
846 /// Gets the connection URI
848 * This should really only be called by internal library methods unless you
849 * really know what you are doing.
851 * @return A pointer to the connection's URI
853 uri_ptr get_uri() const;
855 /// Sets the connection URI
857 * This should really only be called by internal library methods unless you
858 * really know what you are doing.
860 * @param uri The new URI to set
862 void set_uri(uri_ptr uri);
864 /////////////////////////////
865 // Subprotocol negotiation //
866 /////////////////////////////
868 /// Gets the negotated subprotocol
870 * Retrieves the subprotocol that was negotiated during the handshake. This
871 * method is valid in the open handler and later.
873 * @return The negotiated subprotocol
875 std::string const & get_subprotocol() const;
877 /// Gets all of the subprotocols requested by the client
879 * Retrieves the subprotocols that were requested during the handshake. This
880 * method is valid in the validate handler and later.
882 * @return A vector of the requested subprotocol
884 std::vector<std::string> const & get_requested_subprotocols() const;
886 /// Adds the given subprotocol string to the request list (exception free)
888 * Adds a subprotocol to the list to send with the opening handshake. This
889 * may be called multiple times to request more than one. If the server
890 * supports one of these, it may choose one. If so, it will return it
891 * in it's handshake reponse and the value will be available via
892 * get_subprotocol(). Subprotocol requests should be added in order of
895 * @param request The subprotocol to request
896 * @param ec A reference to an error code that will be filled in the case of
899 void add_subprotocol(std::string const & request, lib::error_code & ec);
901 /// Adds the given subprotocol string to the request list
903 * Adds a subprotocol to the list to send with the opening handshake. This
904 * may be called multiple times to request more than one. If the server
905 * supports one of these, it may choose one. If so, it will return it
906 * in it's handshake reponse and the value will be available via
907 * get_subprotocol(). Subprotocol requests should be added in order of
910 * @param request The subprotocol to request
912 void add_subprotocol(std::string const & request);
914 /// Select a subprotocol to use (exception free)
916 * Indicates which subprotocol should be used for this connection. Valid
917 * only during the validate handler callback. Subprotocol selected must have
918 * been requested by the client. Consult get_requested_subprotocols() for a
919 * list of valid subprotocols.
921 * This member function is valid on server endpoints/connections only
923 * @param value The subprotocol to select
924 * @param ec A reference to an error code that will be filled in the case of
927 void select_subprotocol(std::string const & value, lib::error_code & ec);
929 /// Select a subprotocol to use
931 * Indicates which subprotocol should be used for this connection. Valid
932 * only during the validate handler callback. Subprotocol selected must have
933 * been requested by the client. Consult get_requested_subprotocols() for a
934 * list of valid subprotocols.
936 * This member function is valid on server endpoints/connections only
938 * @param value The subprotocol to select
940 void select_subprotocol(std::string const & value);
942 /////////////////////////////////////////////////////////////
943 // Pass-through access to the request and response objects //
944 /////////////////////////////////////////////////////////////
946 /// Retrieve a request header
948 * Retrieve the value of a header from the handshake HTTP request.
950 * @param key Name of the header to get
951 * @return The value of the header
953 std::string const & get_request_header(std::string const & key) const;
955 /// Retrieve a request body
957 * Retrieve the value of the request body. This value is typically used with
958 * PUT and POST requests to upload files or other data. Only HTTP
959 * connections will ever have bodies. WebSocket connection's will always
962 * @return The value of the request body.
964 std::string const & get_request_body() const;
966 /// Retrieve a response header
968 * Retrieve the value of a header from the handshake HTTP request.
970 * @param key Name of the header to get
971 * @return The value of the header
973 std::string const & get_response_header(std::string const & key) const;
975 /// Get response HTTP status code
977 * Gets the response status code
981 * @return The response status code sent
983 http::status_code::value get_response_code() const {
984 return m_response.get_status_code();
987 /// Get response HTTP status message
989 * Gets the response status message
993 * @return The response status message sent
995 std::string const & get_response_msg() const {
996 return m_response.get_status_msg();
999 /// Set response status code and message
1001 * Sets the response status code to `code` and looks up the corresponding
1002 * message for standard codes. Non-standard codes will be entered as Unknown
1003 * use set_status(status_code::value,std::string) overload to set both
1004 * values explicitly.
1006 * This member function is valid only from the http() and validate() handler
1009 * @param code Code to set
1010 * @param msg Message to set
1011 * @see websocketpp::http::response::set_status
1013 void set_status(http::status_code::value code);
1015 /// Set response status code and message
1017 * Sets the response status code and message to independent custom values.
1018 * use set_status(status_code::value) to set the code and have the standard
1019 * message be automatically set.
1021 * This member function is valid only from the http() and validate() handler
1024 * @param code Code to set
1025 * @param msg Message to set
1026 * @see websocketpp::http::response::set_status
1028 void set_status(http::status_code::value code, std::string const & msg);
1030 /// Set response body content
1032 * Set the body content of the HTTP response to the parameter string. Note
1033 * set_body will also set the Content-Length HTTP header to the appropriate
1034 * value. If you want the Content-Length header to be something else set it
1035 * to something else after calling set_body
1037 * This member function is valid only from the http() and validate() handler
1040 * @param value String data to include as the body content.
1041 * @see websocketpp::http::response::set_body
1043 void set_body(std::string const & value);
1047 * If a header with this name already exists the value will be appended to
1048 * the existing header to form a comma separated list of values. Use
1049 * `connection::replace_header` to overwrite existing values.
1051 * This member function is valid only from the http() and validate() handler
1052 * callbacks, or to a client connection before connect has been called.
1054 * @param key Name of the header to set
1055 * @param val Value to add
1056 * @see replace_header
1057 * @see websocketpp::http::parser::append_header
1059 void append_header(std::string const & key, std::string const & val);
1061 /// Replace a header
1063 * If a header with this name already exists the old value will be replaced
1064 * Use `connection::append_header` to append to a list of existing values.
1066 * This member function is valid only from the http() and validate() handler
1067 * callbacks, or to a client connection before connect has been called.
1069 * @param key Name of the header to set
1070 * @param val Value to set
1071 * @see append_header
1072 * @see websocketpp::http::parser::replace_header
1074 void replace_header(std::string const & key, std::string const & val);
1078 * Removes a header from the response.
1080 * This member function is valid only from the http() and validate() handler
1081 * callbacks, or to a client connection before connect has been called.
1083 * @param key The name of the header to remove
1084 * @see websocketpp::http::parser::remove_header
1086 void remove_header(std::string const & key);
1088 /// Get request object
1090 * Direct access to request object. This can be used to call methods of the
1091 * request object that are not part of the standard request API that
1094 * Note use of this method involves using behavior specific to the
1095 * configured HTTP policy. Such behavior may not work with alternate HTTP
1098 * @since 0.3.0-alpha3
1100 * @return A const reference to the raw request object
1102 request_type const & get_request() const {
1106 /// Get response object
1108 * Direct access to the HTTP response sent or received as a part of the
1109 * opening handshake. This can be used to call methods of the response
1110 * object that are not part of the standard request API that connection
1113 * Note use of this method involves using behavior specific to the
1114 * configured HTTP policy. Such behavior may not work with alternate HTTP
1119 * @return A const reference to the raw response object
1121 response_type const & get_response() const {
1125 /// Defer HTTP Response until later (Exception free)
1127 * Used in the http handler to defer the HTTP response for this connection
1128 * until later. Handshake timers will be canceled and the connection will be
1129 * left open until `send_http_response` or an equivalent is called.
1131 * Warning: deferred connections won't time out and as a result can tie up
1136 * @return A status code, zero on success, non-zero otherwise
1138 lib::error_code defer_http_response();
1140 /// Send deferred HTTP Response (exception free)
1142 * Sends an http response to an HTTP connection that was deferred. This will
1143 * send a complete response including all headers, status line, and body
1144 * text. The connection will be closed afterwards.
1148 * @param ec A status code, zero on success, non-zero otherwise
1150 void send_http_response(lib::error_code & ec);
1152 /// Send deferred HTTP Response
1153 void send_http_response();
1155 // TODO HTTPNBIO: write_headers
1156 // function that processes headers + status so far and writes it to the wire
1157 // beginning the HTTP response body state. This method will ignore anything
1158 // in the response body.
1160 // TODO HTTPNBIO: write_body_message
1161 // queues the specified message_buffer for async writing
1163 // TODO HTTPNBIO: finish connection
1166 // TODO HTTPNBIO: write_response
1167 // Writes the whole response, headers + body and closes the connection
1171 /////////////////////////////////////////////////////////////
1172 // Pass-through access to the other connection information //
1173 /////////////////////////////////////////////////////////////
1175 /// Get Connection Handle
1177 * The connection handle is a token that can be shared outside the
1178 * WebSocket++ core for the purposes of identifying a connection and
1179 * sending it messages.
1181 * @return A handle to the connection
1183 connection_hdl get_handle() const {
1184 return m_connection_hdl;
1187 /// Get whether or not this connection is part of a server or client
1189 * @return whether or not the connection is attached to a server endpoint
1191 bool is_server() const {
1195 /// Return the same origin policy origin value from the opening request.
1197 * This value is available after the HTTP request has been fully read and
1198 * may be called from any thread.
1200 * @return The connection's origin value from the opening handshake.
1202 std::string const & get_origin() const;
1204 /// Return the connection state.
1206 * Values can be connecting, open, closing, and closed
1208 * @return The connection's current state.
1210 session::state::value get_state() const;
1213 /// Get the WebSocket close code sent by this endpoint.
1215 * @return The WebSocket close code sent by this endpoint.
1217 close::status::value get_local_close_code() const {
1218 return m_local_close_code;
1221 /// Get the WebSocket close reason sent by this endpoint.
1223 * @return The WebSocket close reason sent by this endpoint.
1225 std::string const & get_local_close_reason() const {
1226 return m_local_close_reason;
1229 /// Get the WebSocket close code sent by the remote endpoint.
1231 * @return The WebSocket close code sent by the remote endpoint.
1233 close::status::value get_remote_close_code() const {
1234 return m_remote_close_code;
1237 /// Get the WebSocket close reason sent by the remote endpoint.
1239 * @return The WebSocket close reason sent by the remote endpoint.
1241 std::string const & get_remote_close_reason() const {
1242 return m_remote_close_reason;
1245 /// Get the internal error code for a closed/failed connection
1247 * Retrieves a machine readable detailed error code indicating the reason
1248 * that the connection was closed or failed. Valid only after the close or
1249 * fail handler is called.
1251 * @return Error code indicating the reason the connection was closed or
1254 lib::error_code get_ec() const {
1258 /// Get a message buffer
1260 * Warning: The API related to directly sending message buffers may change
1261 * before the 1.0 release. If you plan to use it, please keep an eye on any
1262 * breaking changes notifications in future release notes. Also if you have
1263 * any feedback about usage and capabilities now is a great time to provide
1266 * Message buffers are used to store message payloads and other message
1269 * The size parameter is a hint only. Your final payload does not need to
1270 * match it. There may be some performance benefits if the initial size
1271 * guess is equal to or slightly higher than the final payload size.
1273 * @param op The opcode for the new message
1274 * @param size A hint to optimize the initial allocation of payload space.
1275 * @return A new message buffer
1277 message_ptr get_message(websocketpp::frame::opcode::value op, size_t size)
1280 return m_msg_manager->get_message(op, size);
1283 ////////////////////////////////////////////////////////////////////////
1284 // The remaining public member functions are for internal/policy use //
1285 // only. Do not call from application code unless you understand what //
1286 // you are doing. //
1287 ////////////////////////////////////////////////////////////////////////
1291 void read_handshake(size_t num_bytes);
1293 void handle_read_handshake(lib::error_code const & ec,
1294 size_t bytes_transferred);
1295 void handle_read_http_response(lib::error_code const & ec,
1296 size_t bytes_transferred);
1299 void handle_write_http_response(lib::error_code const & ec);
1300 void handle_send_http_request(lib::error_code const & ec);
1302 void handle_open_handshake_timeout(lib::error_code const & ec);
1303 void handle_close_handshake_timeout(lib::error_code const & ec);
1305 void handle_read_frame(lib::error_code const & ec, size_t bytes_transferred);
1308 /// Get array of WebSocket protocol versions that this connection supports.
1309 std::vector<int> const & get_supported_versions() const;
1311 /// Sets the handler for a terminating connection. Should only be used
1312 /// internally by the endpoint class.
1313 void set_termination_handler(termination_handler new_handler);
1315 void terminate(lib::error_code const & ec);
1316 void handle_terminate(terminate_status tstat, lib::error_code const & ec);
1318 /// Checks if there are frames in the send queue and if there are sends one
1322 * This method locks the m_write_lock mutex
1326 /// Process the results of a frame write operation and start the next write
1330 * This method locks the m_write_lock mutex
1332 * @param terminate Whether or not to terminate the connection upon
1333 * completion of this write.
1335 * @param ec A status code from the transport layer, zero on success,
1336 * non-zero otherwise.
1338 void handle_write_frame(lib::error_code const & ec);
1340 // This set of methods would really like to be protected, but doing so
1341 // requires that the endpoint be able to friend the connection. This is
1342 // allowed with C++11, but not prior versions
1344 /// Start the connection state machine
1347 /// Set Connection Handle
1349 * The connection handle is a token that can be shared outside the
1350 * WebSocket++ core for the purposes of identifying a connection and
1351 * sending it messages.
1353 * @param hdl A connection_hdl that the connection will use to refer
1356 void set_handle(connection_hdl hdl) {
1357 m_connection_hdl = hdl;
1358 transport_con_type::set_handle(hdl);
1361 void handle_transport_init(lib::error_code const & ec);
1363 /// Set m_processor based on information in m_request. Set m_response
1364 /// status and return an error code indicating status.
1365 lib::error_code initialize_processor();
1367 /// Perform WebSocket handshake validation of m_request using m_processor.
1368 /// set m_response and return an error code indicating status.
1369 lib::error_code process_handshake_request();
1373 /// Completes m_response, serializes it, and sends it out on the wire.
1374 void write_http_response(lib::error_code const & ec);
1376 /// Sends an opening WebSocket connect request
1377 void send_http_request();
1379 /// Alternate path for write_http_response in error conditions
1380 void write_http_response_error(lib::error_code const & ec);
1382 /// Process control message
1386 void process_control_frame(message_ptr msg);
1388 /// Send close acknowledgement
1390 * If no arguments are present no close code/reason will be specified.
1392 * Note: the close code/reason values provided here may be overrided by
1393 * other settings (such as silent close).
1395 * @param code The close code to send
1396 * @param reason The close reason to send
1397 * @return A status code, zero on success, non-zero otherwise
1399 lib::error_code send_close_ack(close::status::value code =
1400 close::status::blank, std::string const & reason = std::string());
1402 /// Send close frame
1404 * If no arguments are present no close code/reason will be specified.
1406 * Note: the close code/reason values provided here may be overrided by
1407 * other settings (such as silent close).
1409 * The ack flag determines what to do in the case of a blank status and
1410 * whether or not to terminate the TCP connection after sending it.
1412 * @param code The close code to send
1413 * @param reason The close reason to send
1414 * @param ack Whether or not this is an acknowledgement close frame
1415 * @return A status code, zero on success, non-zero otherwise
1417 lib::error_code send_close_frame(close::status::value code =
1418 close::status::blank, std::string const & reason = std::string(), bool ack = false,
1419 bool terminal = false);
1421 /// Get a pointer to a new WebSocket protocol processor for a given version
1423 * @param version Version number of the WebSocket protocol to get a
1424 * processor for. Negative values indicate invalid/unknown versions and will
1425 * always return a null ptr
1427 * @return A shared_ptr to a new instance of the appropriate processor or a
1428 * null ptr if there is no installed processor that matches the version
1431 processor_ptr get_processor(int version) const;
1433 /// Add a message to the write queue
1435 * Adds a message to the write queue and updates any associated shared state
1437 * Must be called while holding m_write_lock
1441 * @param msg The message to push
1443 void write_push(message_ptr msg);
1445 /// Pop a message from the write queue
1447 * Removes and returns a message from the write queue and updates any
1448 * associated shared state.
1450 * Must be called while holding m_write_lock
1454 * @return the message_ptr at the front of the queue
1456 message_ptr write_pop();
1458 /// Prints information about the incoming connection to the access log
1460 * Prints information about the incoming connection to the access log.
1461 * Includes: connection type, websocket version, remote endpoint, user agent
1462 * path, status code.
1464 void log_open_result();
1466 /// Prints information about a connection being closed to the access log
1468 * Includes: local and remote close codes and reasons
1470 void log_close_result();
1472 /// Prints information about a connection being failed to the access log
1474 * Includes: error code and message for why it was failed
1476 void log_fail_result();
1478 /// Prints information about HTTP connections
1482 void log_http_result();
1484 /// Prints information about an arbitrary error code on the specified channel
1485 template <typename error_type>
1486 void log_err(log::level l, char const * msg, error_type const & ec) {
1487 std::stringstream s;
1488 s << msg << " error: " << ec << " (" << ec.message() << ")";
1489 m_elog.write(l, s.str());
1492 // internal handler functions
1493 read_handler m_handle_read_frame;
1494 write_frame_handler m_write_frame_handler;
1497 std::string const m_user_agent;
1499 /// Pointer to the connection handle
1500 connection_hdl m_connection_hdl;
1503 open_handler m_open_handler;
1504 close_handler m_close_handler;
1505 fail_handler m_fail_handler;
1506 ping_handler m_ping_handler;
1507 pong_handler m_pong_handler;
1508 pong_timeout_handler m_pong_timeout_handler;
1509 interrupt_handler m_interrupt_handler;
1510 http_handler m_http_handler;
1511 validate_handler m_validate_handler;
1512 message_handler m_message_handler;
1515 long m_open_handshake_timeout_dur;
1516 long m_close_handshake_timeout_dur;
1517 long m_pong_timeout_dur;
1518 size_t m_max_message_size;
1520 /// External connection state
1522 * Lock: m_connection_state_lock
1524 session::state::value m_state;
1526 /// Internal connection state
1528 * Lock: m_connection_state_lock
1530 istate_type m_internal_state;
1532 mutable mutex_type m_connection_state_lock;
1534 /// The lock used to protect the message queue
1536 * Serializes access to the write queue as well as shared state within the
1539 mutex_type m_write_lock;
1541 // connection resources
1542 char m_buf[config::connection_read_buffer_size];
1543 size_t m_buf_cursor;
1544 termination_handler m_termination_handler;
1545 con_msg_manager_ptr m_msg_manager;
1546 timer_ptr m_handshake_timer;
1547 timer_ptr m_ping_timer;
1549 /// @todo this is not memory efficient. this value is not used after the
1551 std::string m_handshake_buffer;
1553 /// Pointer to the processor object for this connection
1555 * The processor provides functionality that is specific to the WebSocket
1556 * protocol version that the client has negotiated. It also contains all of
1557 * the state necessary to encode and decode the incoming and outgoing
1558 * WebSocket byte streams
1560 * Use of the prepare_data_frame method requires lock: m_write_lock
1562 processor_ptr m_processor;
1564 /// Queue of unsent outgoing messages
1566 * Lock: m_write_lock
1568 std::queue<message_ptr> m_send_queue;
1570 /// Size in bytes of the outstanding payloads in the write queue
1572 * Lock: m_write_lock
1574 size_t m_send_buffer_size;
1576 /// buffer holding the various parts of the current message being writen
1580 std::vector<transport::buffer> m_send_buffer;
1582 /// a list of pointers to hold on to the messages being written to keep them
1583 /// from going out of scope before the write is complete.
1584 std::vector<message_ptr> m_current_msgs;
1586 /// True if there is currently an outstanding transport write
1592 /// True if this connection is presently reading new data
1596 request_type m_request;
1597 response_type m_response;
1599 std::string m_subprotocol;
1601 // connection data that might not be necessary to keep around for the life
1602 // of the whole connection.
1603 std::vector<std::string> m_requested_subprotocols;
1605 bool const m_is_server;
1612 /// Close code that was sent on the wire by this endpoint
1613 close::status::value m_local_close_code;
1615 /// Close reason that was sent on the wire by this endpoint
1616 std::string m_local_close_reason;
1618 /// Close code that was received on the wire from the remote endpoint
1619 close::status::value m_remote_close_code;
1621 /// Close reason that was received on the wire from the remote endpoint
1622 std::string m_remote_close_reason;
1624 /// Detailed internal error code
1625 lib::error_code m_ec;
1627 /// A flag that gets set once it is determined that the connection is an
1628 /// HTTP connection and not a WebSocket one.
1631 /// A flag that gets set when the completion of an http connection is
1632 /// deferred until later.
1633 session::http_state::value m_http_state;
1637 /// Whether or not this endpoint initiated the closing handshake.
1638 bool m_closed_by_me;
1641 bool m_failed_by_me;
1643 /// Whether or not this endpoint initiated the drop of the TCP connection
1644 bool m_dropped_by_me;
1647 } // namespace websocketpp
1649 #include <websocketpp/impl/connection_impl.hpp>
1651 #endif // WEBSOCKETPP_CONNECTION_HPP