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 */ 59 typedef lib::function<void(connection_hdl)> open_handler; 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 */ 69 typedef lib::function<void(connection_hdl)> close_handler; 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 */ 79 typedef lib::function<void(connection_hdl)> fail_handler; 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 */ 91 typedef lib::function<void(connection_hdl)> interrupt_handler; 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 */ 101 typedef lib::function<bool(connection_hdl,std::string)> ping_handler; 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 */ 109 typedef lib::function<void(connection_hdl,std::string)> pong_handler; 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 */ 116 typedef lib::function<void(connection_hdl,std::string)> pong_timeout_handler; 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 */ 129 typedef lib::function<bool(connection_hdl)> validate_handler; 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 */ 151 typedef lib::function<void(connection_hdl)> http_handler; 152 153 // 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; 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 256 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; 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 284 typedef typename transport_con_type::timer_ptr timer_ptr; 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 connection(bool p_is_server,std::string const & ua,const lib::shared_ptr<alog_type> & alog,const lib::shared_ptr<elog_type> & elog,rng_type & rng)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 get_shared()336 ptr get_shared() { 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 */ set_open_handler(open_handler h)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 */ set_close_handler(close_handler h)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 */ set_fail_handler(fail_handler h)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 */ set_ping_handler(ping_handler h)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 */ set_pong_handler(pong_handler h)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 */ set_pong_timeout_handler(pong_timeout_handler h)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 */ set_interrupt_handler(interrupt_handler h)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 */ set_http_handler(http_handler h)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 */ set_validate_handler(validate_handler h)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 */ set_message_handler(message_handler h)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 */ set_open_handshake_timeout(long dur)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 */ set_close_handshake_timeout(long dur)525 void set_close_handshake_timeout(long dur) { 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 */ set_pong_timeout(long dur)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 */ get_max_message_size() const559 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 */ set_max_message_size(size_t new_value)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 */ get_max_http_body_size() const594 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 */ set_max_http_body_size(size_t new_value)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 */ buffered_amount() const635 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 */ 655 lib::error_code send(std::string const & payload, frame::opcode::value op = 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 */ 688 lib::error_code send(message_ptr msg); 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 */ 703 lib::error_code interrupt(); 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 */ 728 lib::error_code pause_reading(); 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 */ 740 lib::error_code resume_reading(); 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 */ get_response_code() const983 http::status_code::value get_response_code() const { 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 */ get_response_msg() const995 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 */ get_request() const1102 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 */ get_response() const1121 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 */ 1138 lib::error_code defer_http_response(); 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 */ get_handle() const1183 connection_hdl get_handle() const { 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 */ is_server() const1191 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 */ get_local_close_code() const1217 close::status::value get_local_close_code() const { 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 */ get_local_close_reason() const1225 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 */ get_remote_close_code() const1233 close::status::value get_remote_close_code() const { 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 */ get_remote_close_reason() const1241 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 */ get_ec() const1254 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 */ get_message(websocketpp::frame::opcode::value op,size_t size) const1277 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 */ set_handle(connection_hdl hdl)1356 void set_handle(connection_hdl hdl) { 1357 m_connection_hdl = hdl; 1358 transport_con_type::set_handle(hdl); 1359 } 1360 protected: 1361 void handle_transport_init(lib::error_code const & ec); 1362 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(); 1366 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(); 1370 private: 1371 1372 1373 /// Completes m_response, serializes it, and sends it out on the wire. 1374 void write_http_response(lib::error_code const & ec); 1375 1376 /// Sends an opening WebSocket connect request 1377 void send_http_request(); 1378 1379 /// Alternate path for write_http_response in error conditions 1380 void write_http_response_error(lib::error_code const & ec); 1381 1382 /// Process control message 1383 /** 1384 * 1385 */ 1386 void process_control_frame(message_ptr msg); 1387 1388 /// Send close acknowledgement 1389 /** 1390 * If no arguments are present no close code/reason will be specified. 1391 * 1392 * Note: the close code/reason values provided here may be overrided by 1393 * other settings (such as silent close). 1394 * 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 1398 */ 1399 lib::error_code send_close_ack(close::status::value code = 1400 close::status::blank, std::string const & reason = std::string()); 1401 1402 /// Send close frame 1403 /** 1404 * If no arguments are present no close code/reason will be specified. 1405 * 1406 * Note: the close code/reason values provided here may be overrided by 1407 * other settings (such as silent close). 1408 * 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. 1411 * 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 1416 */ 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); 1420 1421 /// Get a pointer to a new WebSocket protocol processor for a given version 1422 /** 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 1426 * 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 1429 * number. 1430 */ 1431 processor_ptr get_processor(int version) const; 1432 1433 /// Add a message to the write queue 1434 /** 1435 * Adds a message to the write queue and updates any associated shared state 1436 * 1437 * Must be called while holding m_write_lock 1438 * 1439 * @todo unit tests 1440 * 1441 * @param msg The message to push 1442 */ 1443 void write_push(message_ptr msg); 1444 1445 /// Pop a message from the write queue 1446 /** 1447 * Removes and returns a message from the write queue and updates any 1448 * associated shared state. 1449 * 1450 * Must be called while holding m_write_lock 1451 * 1452 * @todo unit tests 1453 * 1454 * @return the message_ptr at the front of the queue 1455 */ 1456 message_ptr write_pop(); 1457 1458 /// Prints information about the incoming connection to the access log 1459 /** 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. 1463 */ 1464 void log_open_result(); 1465 1466 /// Prints information about a connection being closed to the access log 1467 /** 1468 * Includes: local and remote close codes and reasons 1469 */ 1470 void log_close_result(); 1471 1472 /// Prints information about a connection being failed to the access log 1473 /** 1474 * Includes: error code and message for why it was failed 1475 */ 1476 void log_fail_result(); 1477 1478 /// Prints information about HTTP connections 1479 /** 1480 * Includes: TODO 1481 */ 1482 void log_http_result(); 1483 1484 /// Prints information about an arbitrary error code on the specified channel 1485 template <typename error_type> log_err(log::level l,char const * msg,error_type const & ec)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()); 1490 } 1491 1492 // internal handler functions 1493 read_handler m_handle_read_frame; 1494 write_frame_handler m_write_frame_handler; 1495 1496 // static settings 1497 std::string const m_user_agent; 1498 1499 /// Pointer to the connection handle 1500 connection_hdl m_connection_hdl; 1501 1502 /// Handler objects 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; 1513 1514 /// constant values 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; 1519 1520 /// External connection state 1521 /** 1522 * Lock: m_connection_state_lock 1523 */ 1524 session::state::value m_state; 1525 1526 /// Internal connection state 1527 /** 1528 * Lock: m_connection_state_lock 1529 */ 1530 istate_type m_internal_state; 1531 1532 mutable mutex_type m_connection_state_lock; 1533 1534 /// The lock used to protect the message queue 1535 /** 1536 * Serializes access to the write queue as well as shared state within the 1537 * processor. 1538 */ 1539 mutex_type m_write_lock; 1540 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; 1548 1549 /// @todo this is not memory efficient. this value is not used after the 1550 /// handshake. 1551 std::string m_handshake_buffer; 1552 1553 /// Pointer to the processor object for this connection 1554 /** 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 1559 * 1560 * Use of the prepare_data_frame method requires lock: m_write_lock 1561 */ 1562 processor_ptr m_processor; 1563 1564 /// Queue of unsent outgoing messages 1565 /** 1566 * Lock: m_write_lock 1567 */ 1568 std::queue<message_ptr> m_send_queue; 1569 1570 /// Size in bytes of the outstanding payloads in the write queue 1571 /** 1572 * Lock: m_write_lock 1573 */ 1574 size_t m_send_buffer_size; 1575 1576 /// buffer holding the various parts of the current message being writen 1577 /** 1578 * Lock m_write_lock 1579 */ 1580 std::vector<transport::buffer> m_send_buffer; 1581 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; 1585 1586 /// True if there is currently an outstanding transport write 1587 /** 1588 * Lock m_write_lock 1589 */ 1590 bool m_write_flag; 1591 1592 /// True if this connection is presently reading new data 1593 bool m_read_flag; 1594 1595 // connection data 1596 request_type m_request; 1597 response_type m_response; 1598 uri_ptr m_uri; 1599 std::string m_subprotocol; 1600 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; 1604 1605 bool const m_is_server; 1606 const lib::shared_ptr<alog_type> m_alog; 1607 const lib::shared_ptr<elog_type> m_elog; 1608 1609 rng_type & m_rng; 1610 1611 // Close state 1612 /// Close code that was sent on the wire by this endpoint 1613 close::status::value m_local_close_code; 1614 1615 /// Close reason that was sent on the wire by this endpoint 1616 std::string m_local_close_reason; 1617 1618 /// Close code that was received on the wire from the remote endpoint 1619 close::status::value m_remote_close_code; 1620 1621 /// Close reason that was received on the wire from the remote endpoint 1622 std::string m_remote_close_reason; 1623 1624 /// Detailed internal error code 1625 lib::error_code m_ec; 1626 1627 /// A flag that gets set once it is determined that the connection is an 1628 /// HTTP connection and not a WebSocket one. 1629 bool m_is_http; 1630 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; 1634 1635 bool m_was_clean; 1636 }; 1637 1638 } // namespace websocketpp 1639 1640 #include <websocketpp/impl/connection_impl.hpp> 1641 1642 #endif // WEBSOCKETPP_CONNECTION_HPP 1643