WebSocket++  0.8.0-dev
C++ websocket client/server library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
connection.hpp
1 /*
2  * Copyright (c) 2014, Peter Thorson. All rights reserved.
3  *
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.
14  *
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.
25  *
26  */
27 
28 #ifndef WEBSOCKETPP_CONNECTION_HPP
29 #define WEBSOCKETPP_CONNECTION_HPP
30 
31 #include <websocketpp/close.hpp>
32 #include <websocketpp/error.hpp>
33 #include <websocketpp/frame.hpp>
34 
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>
39 
40 #include <websocketpp/common/connection_hdl.hpp>
41 #include <websocketpp/common/cpp11.hpp>
42 #include <websocketpp/common/functional.hpp>
43 
44 #include <queue>
45 #include <sstream>
46 #include <string>
47 #include <vector>
48 
49 namespace websocketpp {
50 
51 /// The type and function signature of an open handler
52 /**
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.
58  */
60 
61 /// The type and function signature of a close handler
62 /**
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
65  *
66  * The close handler will be called exactly once for every connection for which
67  * the open handler was called.
68  */
70 
71 /// The type and function signature of a fail handler
72 /**
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.
78  */
80 
81 /// The type and function signature of an interrupt handler
82 /**
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
86  * a new message).
87  *
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.
90  */
92 
93 /// The type and function signature of a ping handler
94 /**
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
99  * suppressed.
100  */
102 
103 /// The type and function signature of a pong handler
104 /**
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.
108  */
110 
111 /// The type and function signature of a pong timeout handler
112 /**
113  * The pong timeout handler is called when a ping goes unanswered by a pong for
114  * longer than the locally specified timeout period.
115  */
117 
118 /// The type and function signature of a validate handler
119 /**
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.
124  *
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.
128  */
130 
131 /// The type and function signature of a http handler
132 /**
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.
136  *
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.
140  *
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.
146  *
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
149  * response.
150  */
152 
153 //
155 typedef lib::function<void(lib::error_code const & ec)> write_frame_handler;
156 
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
160  /**
161  * @todo Move this to configs to allow compile/runtime disabling or enabling
162  * of protocol versions
163  */
164  static std::vector<int> const versions_supported = {0,7,8,13};
165 #else
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
169  /**
170  * @todo Move this to configs to allow compile/runtime disabling or enabling
171  * of protocol versions
172  */
173  static std::vector<int> const versions_supported(helper,helper+4);
174 #endif
175 
176 namespace session {
177 namespace state {
178  // externally visible session state (states based on the RFC)
179  enum value {
180  connecting = 0,
181  open = 1,
182  closing = 2,
183  closed = 3
184  };
185 } // namespace state
186 
187 
188 namespace fail {
189 namespace status {
190  enum value {
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
197  };
198 } // namespace status
199 } // namespace fail
200 
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.
205 
206  enum value {
207  USER_INIT = 0,
208  TRANSPORT_INIT = 1,
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
215  };
216 } // namespace internal_state
217 
218 
219 namespace http_state {
220  // states to keep track of the progress of http connections
221 
222  enum value {
223  init = 0,
224  deferred = 1,
225  headers_written = 2,
226  body_written = 3,
227  closed = 4
228  };
229 } // namespace http_state
230 
231 } // namespace session
232 
233 /// Represents an individual WebSocket connection
234 template <typename config>
235 class connection
236  : public config::transport_type::transport_con_type
237  , public config::connection_base
238 {
239 public:
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;
246 
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;
253 
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
259 
260  typedef lib::function<void(ptr)> termination_handler;
261 
262  typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
263  typedef typename concurrency_type::mutex_type mutex_type;
264 
265  typedef typename config::request_type request_type;
266  typedef typename config::response_type response_type;
267 
268  typedef typename config::message_type message_type;
269  typedef typename message_type::ptr message_ptr;
270 
271  typedef typename config::con_msg_manager_type con_msg_manager_type;
272  typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
273 
274  /// Type of RNG
275  typedef typename config::rng_type rng_type;
276 
277  typedef processor::processor<config> processor_type;
278  typedef lib::shared_ptr<processor_type> processor_ptr;
279 
280  // Message handler (needs to know message type)
281  typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
282 
283  /// Type of a pointer to a transport timer handle
285 
286  // Misc Convenience Types
287  typedef session::internal_state::value istate_type;
288 
289 private:
290  enum terminate_status {
291  failed = 1,
292  closed,
293  unknown
294  };
295 public:
296 
297  explicit connection(bool p_is_server, std::string const & ua, const lib::shared_ptr<alog_type>& alog,
298  const lib::shared_ptr<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,
302  this,
303  lib::placeholders::_1,
304  lib::placeholders::_2
305  ))
306  , m_write_frame_handler(lib::bind(
307  &type::handle_write_frame,
308  this,
309  lib::placeholders::_1
310  ))
311  , m_user_agent(ua)
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)
321  , m_read_flag(true)
322  , m_is_server(p_is_server)
323  , m_alog(alog)
324  , m_elog(elog)
325  , m_rng(rng)
326  , m_local_close_code(close::status::abnormal_close)
327  , m_remote_close_code(close::status::abnormal_close)
328  , m_is_http(false)
329  , m_http_state(session::http_state::init)
330  , m_was_clean(false)
331  {
332  m_alog->write(log::alevel::devel,"connection constructor");
333  }
334 
335  /// Get a shared pointer to this component
337  return lib::static_pointer_cast<type>(transport_con_type::get_shared());
338  }
339 
340  ///////////////////////////
341  // Set Handler Callbacks //
342  ///////////////////////////
343 
344  /// Set open handler
345  /**
346  * The open handler is called after the WebSocket handshake is complete and
347  * the connection is considered OPEN.
348  *
349  * @param h The new open_handler
350  */
351  void set_open_handler(open_handler h) {
352  m_open_handler = h;
353  }
354 
355  /// Set close handler
356  /**
357  * The close handler is called immediately after the connection is closed.
358  *
359  * @param h The new close_handler
360  */
361  void set_close_handler(close_handler h) {
362  m_close_handler = h;
363  }
364 
365  /// Set fail handler
366  /**
367  * The fail handler is called whenever the connection fails while the
368  * handshake is bring processed.
369  *
370  * @param h The new fail_handler
371  */
372  void set_fail_handler(fail_handler h) {
373  m_fail_handler = h;
374  }
375 
376  /// Set ping handler
377  /**
378  * The ping handler is called whenever the connection receives a ping
379  * control frame. The ping payload is included.
380  *
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.
384  *
385  * @param h The new ping_handler
386  */
387  void set_ping_handler(ping_handler h) {
388  m_ping_handler = h;
389  }
390 
391  /// Set pong handler
392  /**
393  * The pong handler is called whenever the connection receives a pong
394  * control frame. The pong payload is included.
395  *
396  * @param h The new pong_handler
397  */
398  void set_pong_handler(pong_handler h) {
399  m_pong_handler = h;
400  }
401 
402  /// Set pong timeout handler
403  /**
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.
407  *
408  * The config setting `timeout_pong` controls the length of the timeout
409  * period. It is specified in milliseconds.
410  *
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.
414  *
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.
418  *
419  * @param h The new pong_timeout_handler
420  */
421  void set_pong_timeout_handler(pong_timeout_handler h) {
422  m_pong_timeout_handler = h;
423  }
424 
425  /// Set interrupt handler
426  /**
427  * The interrupt handler is called whenever the connection is manually
428  * interrupted by the application.
429  *
430  * @param h The new interrupt_handler
431  */
432  void set_interrupt_handler(interrupt_handler h) {
433  m_interrupt_handler = h;
434  }
435 
436  /// Set http handler
437  /**
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.
444  *
445  * @param h The new http_handler
446  */
447  void set_http_handler(http_handler h) {
448  m_http_handler = h;
449  }
450 
451  /// Set validate handler
452  /**
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.
457  *
458  * Returning false from the validate handler will reject the connection.
459  * If no validate handler is present, all connections will be allowed.
460  *
461  * @param h The new validate_handler
462  */
463  void set_validate_handler(validate_handler h) {
464  m_validate_handler = h;
465  }
466 
467  /// Set message handler
468  /**
469  * The message handler is called after a new message has been received.
470  *
471  * @param h The new message_handler
472  */
473  void set_message_handler(message_handler h) {
474  m_message_handler = h;
475  }
476 
477  //////////////////////////////////////////
478  // Connection timeouts and other limits //
479  //////////////////////////////////////////
480 
481  /// Set open handshake timeout
482  /**
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.
487  *
488  * Connections that time out will have their fail handlers called with the
489  * open_handshake_timeout error code.
490  *
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.
494  *
495  * To be effective, the transport you are using must support timers. See
496  * the documentation for your transport policy for details about its
497  * timer support.
498  *
499  * @param dur The length of the open handshake timeout in ms
500  */
501  void set_open_handshake_timeout(long dur) {
502  m_open_handshake_timeout_dur = dur;
503  }
504 
505  /// Set close handshake timeout
506  /**
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.
511  *
512  * Connections that time out will have their close handlers called with the
513  * close_handshake_timeout error code.
514  *
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.
518  *
519  * To be effective, the transport you are using must support timers. See
520  * the documentation for your transport policy for details about its
521  * timer support.
522  *
523  * @param dur The length of the close handshake timeout in ms
524  */
526  m_close_handshake_timeout_dur = dur;
527  }
528 
529  /// Set pong timeout
530  /**
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.
533  *
534  * Pong responses that time out will have the pong timeout handler called.
535  *
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.
539  *
540  * To be effective, the transport you are using must support timers. See
541  * the documentation for your transport policy for details about its
542  * timer support.
543  *
544  * @param dur The length of the pong timeout in ms
545  */
546  void set_pong_timeout(long dur) {
547  m_pong_timeout_dur = dur;
548  }
549 
550  /// Get maximum message size
551  /**
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.
554  *
555  * The default is set by the endpoint that creates the connection.
556  *
557  * @since 0.3.0
558  */
559  size_t get_max_message_size() const {
560  return m_max_message_size;
561  }
562 
563  /// Set maximum message size
564  /**
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.
568  *
569  * The default is set by the endpoint that creates the connection.
570  *
571  * @since 0.3.0
572  *
573  * @param new_value The value to set as the maximum message size.
574  */
575  void set_max_message_size(size_t new_value) {
576  m_max_message_size = new_value;
577  if (m_processor) {
578  m_processor->set_max_message_size(new_value);
579  }
580  }
581 
582  /// Get maximum HTTP message body size
583  /**
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
586  * body is too large.
587  *
588  * The default is set by the endpoint that creates the connection.
589  *
590  * @since 0.5.0
591  *
592  * @return The maximum HTTP message body size
593  */
594  size_t get_max_http_body_size() const {
595  return m_request.get_max_body_size();
596  }
597 
598  /// Set maximum HTTP message body size
599  /**
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
602  * body is too large.
603  *
604  * The default is set by the endpoint that creates the connection.
605  *
606  * @since 0.5.0
607  *
608  * @param new_value The value to set as the maximum message size.
609  */
610  void set_max_http_body_size(size_t new_value) {
611  m_request.set_max_body_size(new_value);
612  }
613 
614  //////////////////////////////////
615  // Uncategorized public methods //
616  //////////////////////////////////
617 
618  /// Get the size of the outgoing write buffer (in payload bytes)
619  /**
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
623  * connection
624  *
625  * This method invokes the m_write_lock mutex
626  *
627  * @return The current number of bytes in the outgoing send buffer.
628  */
629  size_t get_buffered_amount() const;
630 
631  /// Get the size of the outgoing write buffer (in payload bytes)
632  /**
633  * @deprecated use `get_buffered_amount` instead
634  */
635  size_t buffered_amount() const {
636  return get_buffered_amount();
637  }
638 
639  ////////////////////
640  // Action Methods //
641  ////////////////////
642 
643  /// Create a message and then add it to the outgoing send queue
644  /**
645  * Convenience method to send a message given a payload string and
646  * optionally an opcode. Default opcode is utf8 text.
647  *
648  * This method locks the m_write_lock mutex
649  *
650  * @param payload The payload string to generated the message with
651  *
652  * @param op The opcode to generated the message with. Default is
653  * frame::opcode::text
654  */
656  frame::opcode::text);
657 
658  /// Send a message (raw array overload)
659  /**
660  * Convenience method to send a message given a raw array and optionally an
661  * opcode. Default opcode is binary.
662  *
663  * This method locks the m_write_lock mutex
664  *
665  * @param payload A pointer to the array containing the bytes to send.
666  *
667  * @param len Length of the array.
668  *
669  * @param op The opcode to generated the message with. Default is
670  * frame::opcode::binary
671  */
672  lib::error_code send(void const * payload, size_t len, frame::opcode::value
673  op = frame::opcode::binary);
674 
675  /// Add a message to the outgoing send queue
676  /**
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,
679  * and then added
680  *
681  * Errors are returned via an exception
682  * \todo make exception system_error rather than error_code
683  *
684  * This method invokes the m_write_lock mutex
685  *
686  * @param msg A message_ptr to the message to send.
687  */
689 
690  /// Asyncronously invoke handler::on_inturrupt
691  /**
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.
694  *
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
698  *
699  * Multiple inturrupt signals can be active at once on the same connection
700  *
701  * @return An error code
702  */
704 
705  /// Transport inturrupt callback
706  void handle_interrupt();
707 
708  /// Pause reading of new data
709  /**
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
713  * endpoint.
714  *
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.
718  *
719  * Use `resume_reading()` to resume.
720  *
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
724  * buffer.
725  *
726  * If reading is paused for this connection already nothing is changed.
727  */
729 
730  /// Pause reading callback
731  void handle_pause_reading();
732 
733  /// Resume reading of new data
734  /**
735  * Signals to the connection to resume reading of new data after it was paused by
736  * `pause_reading()`.
737  *
738  * If reading is not paused for this connection already nothing is changed.
739  */
741 
742  /// Resume reading callback
743  void handle_resume_reading();
744 
745  /// Send a ping
746  /**
747  * Initiates a ping with the given payload/
748  *
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.
752  *
753  * Ping locks the m_write_lock mutex
754  *
755  * @param payload Payload to be used for the ping
756  */
757  void ping(std::string const & payload);
758 
759  /// exception free variant of ping
760  void ping(std::string const & payload, lib::error_code & ec);
761 
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);
764 
765  /// Send a pong
766  /**
767  * Initiates a pong with the given payload.
768  *
769  * There is no feedback from a pong once sent.
770  *
771  * Pong locks the m_write_lock mutex
772  *
773  * @param payload Payload to be used for the pong
774  */
775  void pong(std::string const & payload);
776 
777  /// exception free variant of pong
778  void pong(std::string const & payload, lib::error_code & ec);
779 
780  /// Close the connection
781  /**
782  * Initiates the close handshake process.
783  *
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.
787  *
788  * If no reason is specified none will be sent. If no code is specified
789  * then no code will be sent.
790  *
791  * The handler's on_close callback will be called once the close handshake
792  * is complete.
793  *
794  * Reasons will be automatically truncated to the maximum length (123 bytes)
795  * if necessary.
796  *
797  * @param code The close code to send
798  * @param reason The close reason to send
799  */
800  void close(close::status::value const code, std::string const & reason);
801 
802  /// exception free variant of close
803  void close(close::status::value const code, std::string const & reason,
804  lib::error_code & ec);
805 
806  ////////////////////////////////////////////////
807  // Pass-through access to the uri information //
808  ////////////////////////////////////////////////
809 
810  /// Returns the secure flag from the connection URI
811  /**
812  * This value is available after the HTTP request has been fully read and
813  * may be called from any thread.
814  *
815  * @return Whether or not the connection URI is flagged secure.
816  */
817  bool get_secure() const;
818 
819  /// Returns the host component of the connection URI
820  /**
821  * This value is available after the HTTP request has been fully read and
822  * may be called from any thread.
823  *
824  * @return The host component of the connection URI
825  */
826  std::string const & get_host() const;
827 
828  /// Returns the resource component of the connection URI
829  /**
830  * This value is available after the HTTP request has been fully read and
831  * may be called from any thread.
832  *
833  * @return The resource component of the connection URI
834  */
835  std::string const & get_resource() const;
836 
837  /// Returns the port component of the connection URI
838  /**
839  * This value is available after the HTTP request has been fully read and
840  * may be called from any thread.
841  *
842  * @return The port component of the connection URI
843  */
844  uint16_t get_port() const;
845 
846  /// Gets the connection URI
847  /**
848  * This should really only be called by internal library methods unless you
849  * really know what you are doing.
850  *
851  * @return A pointer to the connection's URI
852  */
853  uri_ptr get_uri() const;
854 
855  /// Sets the connection URI
856  /**
857  * This should really only be called by internal library methods unless you
858  * really know what you are doing.
859  *
860  * @param uri The new URI to set
861  */
862  void set_uri(uri_ptr uri);
863 
864  /////////////////////////////
865  // Subprotocol negotiation //
866  /////////////////////////////
867 
868  /// Gets the negotated subprotocol
869  /**
870  * Retrieves the subprotocol that was negotiated during the handshake. This
871  * method is valid in the open handler and later.
872  *
873  * @return The negotiated subprotocol
874  */
875  std::string const & get_subprotocol() const;
876 
877  /// Gets all of the subprotocols requested by the client
878  /**
879  * Retrieves the subprotocols that were requested during the handshake. This
880  * method is valid in the validate handler and later.
881  *
882  * @return A vector of the requested subprotocol
883  */
884  std::vector<std::string> const & get_requested_subprotocols() const;
885 
886  /// Adds the given subprotocol string to the request list (exception free)
887  /**
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
893  * preference.
894  *
895  * @param request The subprotocol to request
896  * @param ec A reference to an error code that will be filled in the case of
897  * errors
898  */
899  void add_subprotocol(std::string const & request, lib::error_code & ec);
900 
901  /// Adds the given subprotocol string to the request list
902  /**
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
908  * preference.
909  *
910  * @param request The subprotocol to request
911  */
912  void add_subprotocol(std::string const & request);
913 
914  /// Select a subprotocol to use (exception free)
915  /**
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.
920  *
921  * This member function is valid on server endpoints/connections only
922  *
923  * @param value The subprotocol to select
924  * @param ec A reference to an error code that will be filled in the case of
925  * errors
926  */
927  void select_subprotocol(std::string const & value, lib::error_code & ec);
928 
929  /// Select a subprotocol to use
930  /**
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.
935  *
936  * This member function is valid on server endpoints/connections only
937  *
938  * @param value The subprotocol to select
939  */
940  void select_subprotocol(std::string const & value);
941 
942  /////////////////////////////////////////////////////////////
943  // Pass-through access to the request and response objects //
944  /////////////////////////////////////////////////////////////
945 
946  /// Retrieve a request header
947  /**
948  * Retrieve the value of a header from the handshake HTTP request.
949  *
950  * @param key Name of the header to get
951  * @return The value of the header
952  */
953  std::string const & get_request_header(std::string const & key) const;
954 
955  /// Retrieve a request body
956  /**
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
960  * have blank bodies.
961  *
962  * @return The value of the request body.
963  */
964  std::string const & get_request_body() const;
965 
966  /// Retrieve a response header
967  /**
968  * Retrieve the value of a header from the handshake HTTP request.
969  *
970  * @param key Name of the header to get
971  * @return The value of the header
972  */
973  std::string const & get_response_header(std::string const & key) const;
974 
975  /// Get response HTTP status code
976  /**
977  * Gets the response status code
978  *
979  * @since 0.7.0
980  *
981  * @return The response status code sent
982  */
984  return m_response.get_status_code();
985  }
986 
987  /// Get response HTTP status message
988  /**
989  * Gets the response status message
990  *
991  * @since 0.7.0
992  *
993  * @return The response status message sent
994  */
995  std::string const & get_response_msg() const {
996  return m_response.get_status_msg();
997  }
998 
999  /// Set response status code and message
1000  /**
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.
1005  *
1006  * This member function is valid only from the http() and validate() handler
1007  * callbacks.
1008  *
1009  * @param code Code to set
1010  * @param msg Message to set
1011  * @see websocketpp::http::response::set_status
1012  */
1013  void set_status(http::status_code::value code);
1014 
1015  /// Set response status code and message
1016  /**
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.
1020  *
1021  * This member function is valid only from the http() and validate() handler
1022  * callbacks.
1023  *
1024  * @param code Code to set
1025  * @param msg Message to set
1026  * @see websocketpp::http::response::set_status
1027  */
1028  void set_status(http::status_code::value code, std::string const & msg);
1029 
1030  /// Set response body content
1031  /**
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
1036  *
1037  * This member function is valid only from the http() and validate() handler
1038  * callbacks.
1039  *
1040  * @param value String data to include as the body content.
1041  * @see websocketpp::http::response::set_body
1042  */
1043  void set_body(std::string const & value);
1044 
1045  /// Append a header
1046  /**
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.
1050  *
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.
1053  *
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
1058  */
1059  void append_header(std::string const & key, std::string const & val);
1060 
1061  /// Replace a header
1062  /**
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.
1065  *
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.
1068  *
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
1073  */
1074  void replace_header(std::string const & key, std::string const & val);
1075 
1076  /// Remove a header
1077  /**
1078  * Removes a header from the response.
1079  *
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.
1082  *
1083  * @param key The name of the header to remove
1084  * @see websocketpp::http::parser::remove_header
1085  */
1086  void remove_header(std::string const & key);
1087 
1088  /// Get request object
1089  /**
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
1092  * connection wraps.
1093  *
1094  * Note use of this method involves using behavior specific to the
1095  * configured HTTP policy. Such behavior may not work with alternate HTTP
1096  * policies.
1097  *
1098  * @since 0.3.0-alpha3
1099  *
1100  * @return A const reference to the raw request object
1101  */
1102  request_type const & get_request() const {
1103  return m_request;
1104  }
1105 
1106  /// Get response object
1107  /**
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
1111  * wraps.
1112  *
1113  * Note use of this method involves using behavior specific to the
1114  * configured HTTP policy. Such behavior may not work with alternate HTTP
1115  * policies.
1116  *
1117  * @since 0.7.0
1118  *
1119  * @return A const reference to the raw response object
1120  */
1121  response_type const & get_response() const {
1122  return m_response;
1123  }
1124 
1125  /// Defer HTTP Response until later (Exception free)
1126  /**
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.
1130  *
1131  * Warning: deferred connections won't time out and as a result can tie up
1132  * resources.
1133  *
1134  * @since 0.6.0
1135  *
1136  * @return A status code, zero on success, non-zero otherwise
1137  */
1139 
1140  /// Send deferred HTTP Response (exception free)
1141  /**
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.
1145  *
1146  * @since 0.6.0
1147  *
1148  * @param ec A status code, zero on success, non-zero otherwise
1149  */
1150  void send_http_response(lib::error_code & ec);
1151 
1152  /// Send deferred HTTP Response
1153  void send_http_response();
1154 
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.
1159 
1160  // TODO HTTPNBIO: write_body_message
1161  // queues the specified message_buffer for async writing
1162 
1163  // TODO HTTPNBIO: finish connection
1164  //
1165 
1166  // TODO HTTPNBIO: write_response
1167  // Writes the whole response, headers + body and closes the connection
1168 
1169 
1170 
1171  /////////////////////////////////////////////////////////////
1172  // Pass-through access to the other connection information //
1173  /////////////////////////////////////////////////////////////
1174 
1175  /// Get Connection Handle
1176  /**
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.
1180  *
1181  * @return A handle to the connection
1182  */
1184  return m_connection_hdl;
1185  }
1186 
1187  /// Get whether or not this connection is part of a server or client
1188  /**
1189  * @return whether or not the connection is attached to a server endpoint
1190  */
1191  bool is_server() const {
1192  return m_is_server;
1193  }
1194 
1195  /// Return the same origin policy origin value from the opening request.
1196  /**
1197  * This value is available after the HTTP request has been fully read and
1198  * may be called from any thread.
1199  *
1200  * @return The connection's origin value from the opening handshake.
1201  */
1202  std::string const & get_origin() const;
1203 
1204  /// Return the connection state.
1205  /**
1206  * Values can be connecting, open, closing, and closed
1207  *
1208  * @return The connection's current state.
1209  */
1210  session::state::value get_state() const;
1211 
1212 
1213  /// Get the WebSocket close code sent by this endpoint.
1214  /**
1215  * @return The WebSocket close code sent by this endpoint.
1216  */
1218  return m_local_close_code;
1219  }
1220 
1221  /// Get the WebSocket close reason sent by this endpoint.
1222  /**
1223  * @return The WebSocket close reason sent by this endpoint.
1224  */
1225  std::string const & get_local_close_reason() const {
1226  return m_local_close_reason;
1227  }
1228 
1229  /// Get the WebSocket close code sent by the remote endpoint.
1230  /**
1231  * @return The WebSocket close code sent by the remote endpoint.
1232  */
1234  return m_remote_close_code;
1235  }
1236 
1237  /// Get the WebSocket close reason sent by the remote endpoint.
1238  /**
1239  * @return The WebSocket close reason sent by the remote endpoint.
1240  */
1241  std::string const & get_remote_close_reason() const {
1242  return m_remote_close_reason;
1243  }
1244 
1245  /// Get the internal error code for a closed/failed connection
1246  /**
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.
1250  *
1251  * @return Error code indicating the reason the connection was closed or
1252  * failed
1253  */
1254  lib::error_code get_ec() const {
1255  return m_ec;
1256  }
1257 
1258  /// Get a message buffer
1259  /**
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
1264  * it.
1265  *
1266  * Message buffers are used to store message payloads and other message
1267  * metadata.
1268  *
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.
1272  *
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
1276  */
1277  message_ptr get_message(websocketpp::frame::opcode::value op, size_t size)
1278  const
1279  {
1280  return m_msg_manager->get_message(op, size);
1281  }
1282 
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  ////////////////////////////////////////////////////////////////////////
1288 
1289 
1290 
1291  void read_handshake(size_t num_bytes);
1292 
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);
1297 
1298 
1299  void handle_write_http_response(lib::error_code const & ec);
1300  void handle_send_http_request(lib::error_code const & ec);
1301 
1302  void handle_open_handshake_timeout(lib::error_code const & ec);
1303  void handle_close_handshake_timeout(lib::error_code const & ec);
1304 
1305  void handle_read_frame(lib::error_code const & ec, size_t bytes_transferred);
1306  void read_frame();
1307 
1308  /// Get array of WebSocket protocol versions that this connection supports.
1309  std::vector<int> const & get_supported_versions() const;
1310 
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);
1314 
1315  void terminate(lib::error_code const & ec);
1316  void handle_terminate(terminate_status tstat, lib::error_code const & ec);
1317 
1318  /// Checks if there are frames in the send queue and if there are sends one
1319  /**
1320  * \todo unit tests
1321  *
1322  * This method locks the m_write_lock mutex
1323  */
1324  void write_frame();
1325 
1326  /// Process the results of a frame write operation and start the next write
1327  /**
1328  * \todo unit tests
1329  *
1330  * This method locks the m_write_lock mutex
1331  *
1332  * @param terminate Whether or not to terminate the connection upon
1333  * completion of this write.
1334  *
1335  * @param ec A status code from the transport layer, zero on success,
1336  * non-zero otherwise.
1337  */
1338  void handle_write_frame(lib::error_code const & ec);
1339 // protected:
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
1343 
1344  /// Start the connection state machine
1345  void start();
1346 
1347  /// Set Connection Handle
1348  /**
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.
1352  *
1353  * @param hdl A connection_hdl that the connection will use to refer
1354  * to itself.
1355  */
1356  void set_handle(connection_hdl hdl) {
1357  m_connection_hdl = hdl;
1358  transport_con_type::set_handle(hdl);
1359  }
1360 
1361  void test() {
1362  std::cout << "m_handle_read_frame: " << sizeof(m_handle_read_frame) << std::endl;
1363  std::cout << "m_write_frame_handler: " << sizeof(m_write_frame_handler) << std::endl;
1364  std::cout << "m_user_agent: " << sizeof(m_user_agent) << std::endl;
1365  std::cout << "m_connection_hdl: " << sizeof(m_connection_hdl) << std::endl;
1366 
1367  std::cout << "m_open_handler: " << sizeof(m_open_handler) << std::endl;
1368  std::cout << "m_close_handler: " << sizeof(m_close_handler) << std::endl;
1369  std::cout << "m_fail_handler: " << sizeof(m_fail_handler) << std::endl;
1370  std::cout << "m_ping_handler: " << sizeof(m_ping_handler) << std::endl;
1371  std::cout << "m_pong_handler: " << sizeof(m_pong_handler) << std::endl;
1372  std::cout << "m_pong_timeout_handler: " << sizeof(m_pong_timeout_handler) << std::endl;
1373  std::cout << "m_interrupt_handler: " << sizeof(m_interrupt_handler) << std::endl;
1374  std::cout << "m_http_handler: " << sizeof(m_http_handler) << std::endl;
1375  std::cout << "m_validate_handler: " << sizeof(m_validate_handler) << std::endl;
1376  std::cout << "m_message_handler: " << sizeof(m_message_handler) << std::endl;
1377 
1378  std::cout << "m_open_handshake_timeout_dur: " << sizeof(m_open_handshake_timeout_dur) << std::endl;
1379  std::cout << "m_close_handshake_timeout_dur: " << sizeof(m_close_handshake_timeout_dur) << std::endl;
1380  std::cout << "m_pong_timeout_dur: " << sizeof(m_pong_timeout_dur) << std::endl;
1381  std::cout << "m_max_message_size: " << sizeof(m_max_message_size) << std::endl;
1382 
1383  std::cout << "m_state: " << sizeof(m_state) << std::endl;
1384  std::cout << "m_internal_state: " << sizeof(m_internal_state) << std::endl;
1385  std::cout << "m_connection_state_lock: " << sizeof(m_connection_state_lock) << std::endl;
1386  std::cout << "m_write_lock: " << sizeof(m_write_lock) << std::endl;
1387 
1388  std::cout << "m_buf: " << sizeof(m_buf) << std::endl;
1389  std::cout << "m_buf_cursor: " << sizeof(m_buf_cursor) << std::endl;
1390  std::cout << "m_termination_handler: " << sizeof(m_termination_handler) << std::endl;
1391  std::cout << "m_msg_manager: " << sizeof(m_msg_manager) << std::endl;
1392  std::cout << "m_handshake_timer: " << sizeof(m_handshake_timer) << std::endl;
1393  std::cout << "m_ping_timer: " << sizeof(m_ping_timer) << std::endl;
1394 
1395  std::cout << "m_processor: " << sizeof(m_processor) << std::endl;
1396  std::cout << "m_send_queue: " << sizeof(m_send_queue) << std::endl;
1397  std::cout << "m_send_buffer_size: " << sizeof(m_send_buffer_size) << std::endl;
1398  std::cout << "m_send_buffer: " << sizeof(m_send_buffer) << std::endl;
1399 
1400  std::cout << "m_current_msgs: " << sizeof(m_current_msgs) << std::endl;
1401  std::cout << "m_write_flag: " << sizeof(m_write_flag) << std::endl;
1402  std::cout << "m_read_flag: " << sizeof(m_read_flag) << std::endl;
1403 
1404  std::cout << "m_request: " << sizeof(m_request) << std::endl;
1405  std::cout << "m_response: " << sizeof(m_response) << std::endl;
1406  std::cout << "m_uri: " << sizeof(m_uri) << std::endl;
1407  std::cout << "m_subprotocol: " << sizeof(m_subprotocol) << std::endl;
1408 
1409  std::cout << "m_requested_subprotocols: " << sizeof(m_requested_subprotocols) << std::endl;
1410 
1411  std::cout << "m_is_server: " << sizeof(m_is_server) << std::endl;
1412  std::cout << "m_alog: " << sizeof(m_alog) << std::endl;
1413  std::cout << "m_elog: " << sizeof(m_elog) << std::endl;
1414  std::cout << "m_rng: " << sizeof(m_rng) << std::endl;
1415 
1416  std::cout << "m_local_close_code: " << sizeof(m_local_close_code) << std::endl;
1417  std::cout << "m_local_close_reason: " << sizeof(m_local_close_reason) << std::endl;
1418  std::cout << "m_remote_close_code: " << sizeof(m_remote_close_code) << std::endl;
1419  std::cout << "m_remote_close_reason: " << sizeof(m_remote_close_reason) << std::endl;
1420 
1421  std::cout << "m_ec: " << sizeof(m_ec) << std::endl;
1422 
1423  std::cout << "m_is_http: " << sizeof(m_is_http) << std::endl;
1424  std::cout << "m_http_state: " << sizeof(m_http_state) << std::endl;
1425  std::cout << "m_was_clean: " << sizeof(m_was_clean) << std::endl;
1426 
1427  std::cout << "m_closed_by_me: " << sizeof(m_closed_by_me) << std::endl;
1428  std::cout << "m_failed_by_me: " << sizeof(m_failed_by_me) << std::endl;
1429  std::cout << "m_dropped_by_me: " << sizeof(m_dropped_by_me) << std::endl;
1430 
1431  std::cout << "transport_con_type: " << sizeof(transport_con_type) << std::endl;
1432  std::cout << "connection_base: " << sizeof(connection_base) << std::endl;
1433 
1434  transport_con_type::test();
1435 
1436  }
1437 
1438 protected:
1439  void handle_transport_init(lib::error_code const & ec);
1440 
1441  /// Set m_processor based on information in m_request. Set m_response
1442  /// status and return an error code indicating status.
1444 
1445  /// Perform WebSocket handshake validation of m_request using m_processor.
1446  /// set m_response and return an error code indicating status.
1448 private:
1449 
1450 
1451  /// Completes m_response, serializes it, and sends it out on the wire.
1452  void write_http_response(lib::error_code const & ec);
1453 
1454  /// Sends an opening WebSocket connect request
1455  void send_http_request();
1456 
1457  /// Alternate path for write_http_response in error conditions
1458  void write_http_response_error(lib::error_code const & ec);
1459 
1460  /// Process control message
1461  /**
1462  *
1463  */
1464  void process_control_frame(message_ptr msg);
1465 
1466  /// Send close acknowledgement
1467  /**
1468  * If no arguments are present no close code/reason will be specified.
1469  *
1470  * Note: the close code/reason values provided here may be overrided by
1471  * other settings (such as silent close).
1472  *
1473  * @param code The close code to send
1474  * @param reason The close reason to send
1475  * @return A status code, zero on success, non-zero otherwise
1476  */
1477  lib::error_code send_close_ack(close::status::value code =
1478  close::status::blank, std::string const & reason = std::string());
1479 
1480  /// Send close frame
1481  /**
1482  * If no arguments are present no close code/reason will be specified.
1483  *
1484  * Note: the close code/reason values provided here may be overrided by
1485  * other settings (such as silent close).
1486  *
1487  * The ack flag determines what to do in the case of a blank status and
1488  * whether or not to terminate the TCP connection after sending it.
1489  *
1490  * @param code The close code to send
1491  * @param reason The close reason to send
1492  * @param ack Whether or not this is an acknowledgement close frame
1493  * @return A status code, zero on success, non-zero otherwise
1494  */
1495  lib::error_code send_close_frame(close::status::value code =
1496  close::status::blank, std::string const & reason = std::string(), bool ack = false,
1497  bool terminal = false);
1498 
1499  /// Get a pointer to a new WebSocket protocol processor for a given version
1500  /**
1501  * @param version Version number of the WebSocket protocol to get a
1502  * processor for. Negative values indicate invalid/unknown versions and will
1503  * always return a null ptr
1504  *
1505  * @return A shared_ptr to a new instance of the appropriate processor or a
1506  * null ptr if there is no installed processor that matches the version
1507  * number.
1508  */
1509  processor_ptr get_processor(int version) const;
1510 
1511  /// Add a message to the write queue
1512  /**
1513  * Adds a message to the write queue and updates any associated shared state
1514  *
1515  * Must be called while holding m_write_lock
1516  *
1517  * @todo unit tests
1518  *
1519  * @param msg The message to push
1520  */
1521  void write_push(message_ptr msg);
1522 
1523  /// Pop a message from the write queue
1524  /**
1525  * Removes and returns a message from the write queue and updates any
1526  * associated shared state.
1527  *
1528  * Must be called while holding m_write_lock
1529  *
1530  * @todo unit tests
1531  *
1532  * @return the message_ptr at the front of the queue
1533  */
1534  message_ptr write_pop();
1535 
1536  /// Prints information about the incoming connection to the access log
1537  /**
1538  * Prints information about the incoming connection to the access log.
1539  * Includes: connection type, websocket version, remote endpoint, user agent
1540  * path, status code.
1541  */
1542  void log_open_result();
1543 
1544  /// Prints information about a connection being closed to the access log
1545  /**
1546  * Includes: local and remote close codes and reasons
1547  */
1548  void log_close_result();
1549 
1550  /// Prints information about a connection being failed to the access log
1551  /**
1552  * Includes: error code and message for why it was failed
1553  */
1554  void log_fail_result();
1555 
1556  /// Prints information about HTTP connections
1557  /**
1558  * Includes: TODO
1559  */
1560  void log_http_result();
1561 
1562  /// Prints information about an arbitrary error code on the specified channel
1563  template <typename error_type>
1564  void log_err(log::level l, char const * msg, error_type const & ec) {
1565  std::stringstream s;
1566  s << msg << " error: " << ec << " (" << ec.message() << ")";
1567  m_elog->write(l, s.str());
1568  }
1569 
1570  // internal handler functions
1571  read_handler m_handle_read_frame;
1572  write_frame_handler m_write_frame_handler;
1573 
1574  // static settings
1575  std::string const m_user_agent;
1576 
1577  /// Pointer to the connection handle
1578  connection_hdl m_connection_hdl;
1579 
1580  /// Handler objects
1581  open_handler m_open_handler;
1582  close_handler m_close_handler;
1583  fail_handler m_fail_handler;
1584  ping_handler m_ping_handler;
1585  pong_handler m_pong_handler;
1586  pong_timeout_handler m_pong_timeout_handler;
1587  interrupt_handler m_interrupt_handler;
1588  http_handler m_http_handler;
1589  validate_handler m_validate_handler;
1590  message_handler m_message_handler;
1591 
1592  /// constant values
1593  long m_open_handshake_timeout_dur;
1594  long m_close_handshake_timeout_dur;
1595  long m_pong_timeout_dur;
1596  size_t m_max_message_size;
1597 
1598  /// External connection state
1599  /**
1600  * Lock: m_connection_state_lock
1601  */
1602  session::state::value m_state;
1603 
1604  /// Internal connection state
1605  /**
1606  * Lock: m_connection_state_lock
1607  */
1608  istate_type m_internal_state;
1609 
1610  mutable mutex_type m_connection_state_lock;
1611 
1612  /// The lock used to protect the message queue
1613  /**
1614  * Serializes access to the write queue as well as shared state within the
1615  * processor.
1616  */
1617  mutex_type m_write_lock;
1618 
1619  // connection resources
1620  char m_buf[config::connection_read_buffer_size];
1621  size_t m_buf_cursor;
1622  termination_handler m_termination_handler;
1623  con_msg_manager_ptr m_msg_manager;
1624  timer_ptr m_handshake_timer;
1625  timer_ptr m_ping_timer;
1626 
1627  /// @todo this is not memory efficient. this value is not used after the
1628  /// handshake.
1629  std::string m_handshake_buffer;
1630 
1631  /// Pointer to the processor object for this connection
1632  /**
1633  * The processor provides functionality that is specific to the WebSocket
1634  * protocol version that the client has negotiated. It also contains all of
1635  * the state necessary to encode and decode the incoming and outgoing
1636  * WebSocket byte streams
1637  *
1638  * Use of the prepare_data_frame method requires lock: m_write_lock
1639  */
1640  processor_ptr m_processor;
1641 
1642  /// Queue of unsent outgoing messages
1643  /**
1644  * Lock: m_write_lock
1645  */
1646  std::queue<message_ptr> m_send_queue;
1647 
1648  /// Size in bytes of the outstanding payloads in the write queue
1649  /**
1650  * Lock: m_write_lock
1651  */
1652  size_t m_send_buffer_size;
1653 
1654  /// buffer holding the various parts of the current message being writen
1655  /**
1656  * Lock m_write_lock
1657  */
1658  std::vector<transport::buffer> m_send_buffer;
1659 
1660  /// a list of pointers to hold on to the messages being written to keep them
1661  /// from going out of scope before the write is complete.
1662  std::vector<message_ptr> m_current_msgs;
1663 
1664  /// True if there is currently an outstanding transport write
1665  /**
1666  * Lock m_write_lock
1667  */
1668  bool m_write_flag;
1669 
1670  /// True if this connection is presently reading new data
1671  bool m_read_flag;
1672 
1673  // connection data
1674  request_type m_request;
1675  response_type m_response;
1676  uri_ptr m_uri;
1677  std::string m_subprotocol;
1678 
1679  // connection data that might not be necessary to keep around for the life
1680  // of the whole connection.
1681  std::vector<std::string> m_requested_subprotocols;
1682 
1683  bool const m_is_server;
1684  const lib::shared_ptr<alog_type> m_alog;
1685  const lib::shared_ptr<elog_type> m_elog;
1686 
1687  rng_type & m_rng;
1688 
1689  // Close state
1690  /// Close code that was sent on the wire by this endpoint
1691  close::status::value m_local_close_code;
1692 
1693  /// Close reason that was sent on the wire by this endpoint
1694  std::string m_local_close_reason;
1695 
1696  /// Close code that was received on the wire from the remote endpoint
1697  close::status::value m_remote_close_code;
1698 
1699  /// Close reason that was received on the wire from the remote endpoint
1700  std::string m_remote_close_reason;
1701 
1702  /// Detailed internal error code
1703  lib::error_code m_ec;
1704 
1705  /// A flag that gets set once it is determined that the connection is an
1706  /// HTTP connection and not a WebSocket one.
1707  bool m_is_http;
1708 
1709  /// A flag that gets set when the completion of an http connection is
1710  /// deferred until later.
1711  session::http_state::value m_http_state;
1712 
1713  bool m_was_clean;
1714 
1715  /// Whether or not this endpoint initiated the closing handshake.
1716  bool m_closed_by_me;
1717 
1718  /// ???
1719  bool m_failed_by_me;
1720 
1721  /// Whether or not this endpoint initiated the drop of the TCP connection
1722  bool m_dropped_by_me;
1723 };
1724 
1725 } // namespace websocketpp
1726 
1727 #include <websocketpp/impl/connection_impl.hpp>
1728 
1729 #endif // WEBSOCKETPP_CONNECTION_HPP
lib::error_code process_handshake_request()
std::string const & get_remote_close_reason() const
Get the WebSocket close reason sent by the remote endpoint.
void pong(std::string const &payload, lib::error_code &ec)
exception free variant of pong
void add_subprotocol(std::string const &request)
Adds the given subprotocol string to the request list.
void add_subprotocol(std::string const &request, lib::error_code &ec)
Adds the given subprotocol string to the request list (exception free)
void set_open_handshake_timeout(long dur)
Set open handshake timeout.
Definition: connection.hpp:501
void set_termination_handler(termination_handler new_handler)
connection_hdl get_handle() const
Get Connection Handle.
void set_pong_timeout(long dur)
Set pong timeout.
Definition: connection.hpp:546
ptr get_shared()
Get a shared pointer to this component.
Definition: connection.hpp:336
void read_frame()
Issue a new transport read unless reading is paused.
std::vector< std::string > const & get_requested_subprotocols() const
Gets all of the subprotocols requested by the client.
void select_subprotocol(std::string const &value)
Select a subprotocol to use.
message_ptr get_message(websocketpp::frame::opcode::value op, size_t size) const
Get a message buffer.
std::string const & get_subprotocol() const
Gets the negotated subprotocol.
lib::error_code pause_reading()
Pause reading of new data.
close::status::value get_local_close_code() const
Get the WebSocket close code sent by this endpoint.
std::string const & get_local_close_reason() const
Get the WebSocket close reason sent by this endpoint.
session::state::value get_state() const
Return the connection state.
static std::vector< int > const versions_supported(helper, helper+4)
Container that stores the list of protocol versions supported.
transport_con_type::ptr transport_con_ptr
Type of a shared pointer to the transport component of this connection.
Definition: connection.hpp:258
void set_open_handler(open_handler h)
Set open handler.
Definition: connection.hpp:351
uri_ptr get_uri() const
Gets the connection URI.
void replace_header(std::string const &key, std::string const &val)
Replace a header.
void ping(std::string const &payload)
Send a ping.
void set_fail_handler(fail_handler h)
Set fail handler.
Definition: connection.hpp:372
size_t get_buffered_amount() const
Get the size of the outgoing write buffer (in payload bytes)
void set_status(http::status_code::value code, std::string const &msg)
Set response status code and message.
void set_http_handler(http_handler h)
Set http handler.
Definition: connection.hpp:447
void select_subprotocol(std::string const &value, lib::error_code &ec)
Select a subprotocol to use (exception free)
void set_close_handler(close_handler h)
Set close handler.
Definition: connection.hpp:361
lib::error_code get_ec() const
Get the internal error code for a closed/failed connection.
void pong(std::string const &payload)
Send a pong.
void send_http_response()
Send deferred HTTP Response.
lib::error_code send(void const *payload, size_t len, frame::opcode::value op=frame::opcode::binary)
Send a message (raw array overload)
void handle_resume_reading()
Resume reading callback.
lib::error_code send(message_ptr msg)
Add a message to the outgoing send queue.
void close(close::status::value const code, std::string const &reason, lib::error_code &ec)
exception free variant of close
config::alog_type alog_type
Type of the access logging policy.
Definition: connection.hpp:250
lib::error_code initialize_processor()
std::string const & get_request_header(std::string const &key) const
Retrieve a request header.
close::status::value get_remote_close_code() const
Get the WebSocket close code sent by the remote endpoint.
void set_pong_handler(pong_handler h)
Set pong handler.
Definition: connection.hpp:398
connection< config > type
Type of this connection.
Definition: connection.hpp:241
void set_close_handshake_timeout(long dur)
Set close handshake timeout.
Definition: connection.hpp:525
lib::error_code resume_reading()
Resume reading of new data.
void start()
Start the connection state machine.
bool is_server() const
Get whether or not this connection is part of a server or client.
void set_handle(connection_hdl hdl)
Set Connection Handle.
lib::error_code defer_http_response()
Defer HTTP Response until later (Exception free)
void set_status(http::status_code::value code)
Set response status code and message.
void handle_pong_timeout(std::string payload, lib::error_code const &ec)
Utility method that gets called back when the ping timer expires.
config::concurrency_type concurrency_type
Type of the concurrency component of this connection.
Definition: connection.hpp:248
config::rng_type rng_type
Type of RNG.
Definition: connection.hpp:275
void append_header(std::string const &key, std::string const &val)
Append a header.
lib::error_code send(std::string const &payload, frame::opcode::value op=frame::opcode::text)
Create a message and then add it to the outgoing send queue.
config::transport_type::transport_con_type transport_con_type
Type of the transport component of this connection.
Definition: connection.hpp:256
void set_ping_handler(ping_handler h)
Set ping handler.
Definition: connection.hpp:387
void write_frame()
Checks if there are frames in the send queue and if there are sends one.
std::string const & get_response_msg() const
Get response HTTP status message.
Definition: connection.hpp:995
void handle_write_frame(lib::error_code const &ec)
Process the results of a frame write operation and start the next write.
void set_max_http_body_size(size_t new_value)
Set maximum HTTP message body size.
Definition: connection.hpp:610
void ping(std::string const &payload, lib::error_code &ec)
exception free variant of ping
void set_max_message_size(size_t new_value)
Set maximum message size.
Definition: connection.hpp:575
std::string const & get_origin() const
Return the same origin policy origin value from the opening request.
void set_pong_timeout_handler(pong_timeout_handler h)
Set pong timeout handler.
Definition: connection.hpp:421
std::string const & get_response_header(std::string const &key) const
Retrieve a response header.
uint16_t get_port() const
Returns the port component of the connection URI.
std::string const & get_resource() const
Returns the resource component of the connection URI.
void handle_accept(connection_ptr con, lib::error_code const &ec)
Handler callback for start_accept.
void set_interrupt_handler(interrupt_handler h)
Set interrupt handler.
Definition: connection.hpp:432
request_type const & get_request() const
Get request object.
std::vector< int > const & get_supported_versions() const
Get array of WebSocket protocol versions that this connection supports.
static int const helper[]
Helper array to get around lack of initializer lists pre C++11.
Definition: connection.hpp:167
void handle_interrupt()
Transport inturrupt callback.
void handle_pause_reading()
Pause reading callback.
void set_validate_handler(validate_handler h)
Set validate handler.
Definition: connection.hpp:463
size_t get_max_message_size() const
Get maximum message size.
Definition: connection.hpp:559
void set_message_handler(message_handler h)
Set message handler.
Definition: connection.hpp:473
response_type const & get_response() const
Get response object.
bool get_secure() const
Returns the secure flag from the connection URI.
size_t buffered_amount() const
Get the size of the outgoing write buffer (in payload bytes)
Definition: connection.hpp:635
std::string const & get_request_body() const
Retrieve a request body.
void set_uri(uri_ptr uri)
Sets the connection URI.
std::string const & get_host() const
Returns the host component of the connection URI.
size_t get_max_http_body_size() const
Get maximum HTTP message body size.
Definition: connection.hpp:594
void send_http_response(lib::error_code &ec)
Send deferred HTTP Response (exception free)
lib::error_code interrupt()
Asyncronously invoke handler::on_inturrupt.
transport_con_type::timer_ptr timer_ptr
Type of a pointer to a transport timer handle.
Definition: connection.hpp:284
config::elog_type elog_type
Type of the error logging policy.
Definition: connection.hpp:252
http::status_code::value get_response_code() const
Get response HTTP status code.
Definition: connection.hpp:983
void remove_header(std::string const &key)
Remove a header.
void set_body(std::string const &value)
Set response body content.