Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| abf927bb24 | |||
| e1f75756d1 | |||
| 322e3bafbf | |||
| 9019af0070 | |||
| e65b277017 | |||
| 8434139b67 | |||
| d4a4b79684 | |||
| 6b09310479 | |||
| 2b310fa80b | |||
| 0bb33e4bca | |||
| ebd0afd67d | |||
| 5f42305bbd | |||
| a2f182733a | |||
| 59fb9ece5d | |||
| 73c3b81411 | |||
| cc851aa167 | |||
| 0f2df92ae4 | |||
| 6b702cc050 | |||
| 92c1f0c415 | |||
| 9e5163364f | |||
| 8f0fab3e77 | |||
| 94fe989840 | |||
| 9da5ac93ec | |||
| 891a7a5ed5 | |||
| 1013aa89bc | |||
| 366679b50a | |||
| 94cc1ec5cb | |||
| 6f128a5499 | |||
| f5d14f3ad3 | |||
| 918745a7ea |
+40
-23
@@ -1,18 +1,42 @@
|
||||
|
||||
############ Setup project and cmake
|
||||
|
||||
# Project name
|
||||
project (websocketpp)
|
||||
|
||||
# Minimum cmake requirement. We should require a quite recent
|
||||
# cmake for the dependency find macros etc. to be up to date.
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
cmake_minimum_required (VERSION 2.8.8)
|
||||
|
||||
############ Paths
|
||||
|
||||
set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp)
|
||||
set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin)
|
||||
set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib)
|
||||
|
||||
# CMake install step prefix. I assume linux users want the prefix to
|
||||
# be the default /usr or /usr/local so this is only adjusted on Windows.
|
||||
# This must be set prior to any call to project or it will not be read correctly.
|
||||
# - Windows: Build the INSTALL project in your solution file.
|
||||
# - Linux/OSX: make install.
|
||||
if (WIN32)
|
||||
set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install" CACHE PATH "")
|
||||
endif ()
|
||||
|
||||
############ Project name and version
|
||||
set (WEBSOCKETPP_MAJOR_VERSION 0)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 7)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 8)
|
||||
set (WEBSOCKETPP_PATCH_VERSION 0)
|
||||
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})
|
||||
|
||||
if(POLICY CMP0048)
|
||||
cmake_policy(GET CMP0048 _version_policy)
|
||||
endif()
|
||||
|
||||
if(_version_allowed STREQUAL NEW)
|
||||
project (websocketpp VERSION ${WEBSOCKETPP_VERSION})
|
||||
else()
|
||||
project (websocketpp)
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
|
||||
@@ -44,21 +68,6 @@ set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "Conf
|
||||
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
include (CMakeHelpers)
|
||||
|
||||
############ Paths
|
||||
|
||||
set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp)
|
||||
set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin)
|
||||
set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib)
|
||||
|
||||
# CMake install step prefix. I assume linux users want the prefix to
|
||||
# be the default /usr or /usr/local so this is only adjusted on Windows.
|
||||
# - Windows: Build the INSTALL project in your solution file.
|
||||
# - Linux/OSX: make install.
|
||||
if (MSVC)
|
||||
set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install")
|
||||
endif ()
|
||||
|
||||
############ Build customization
|
||||
|
||||
@@ -250,8 +259,16 @@ print_used_build_config()
|
||||
|
||||
export (PACKAGE websocketpp)
|
||||
|
||||
configure_file (websocketpp-config.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake" @ONLY)
|
||||
configure_file (websocketpp-configVersion.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake" @ONLY)
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(websocketpp-config.cmake.in
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake"
|
||||
PATH_VARS INSTALL_INCLUDE_DIR
|
||||
INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}"
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
)
|
||||
write_basic_package_version_file("${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake"
|
||||
VERSION ${WEBSOCKETPP_VERSION}
|
||||
COMPATIBILITY ExactVersion)
|
||||
|
||||
# Install the websocketpp-config.cmake and websocketpp-configVersion.cmake
|
||||
install (FILES
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = WebSocket++
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.7.0
|
||||
PROJECT_NUMBER = 0.8.0-dev
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -234,10 +234,14 @@ echo_server = SConscript('#/examples/echo_server/SConscript',variant_dir = build
|
||||
# echo_client
|
||||
echo_client = SConscript('#/examples/echo_client/SConscript',variant_dir = builddir + 'echo_client',duplicate = 0)
|
||||
|
||||
# print_client
|
||||
print_client = SConscript('#/examples/print_client/SConscript',variant_dir = builddir + 'print_client',duplicate = 0)
|
||||
|
||||
# echo_server_tls
|
||||
if tls_build:
|
||||
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',variant_dir = builddir + 'echo_server_tls',duplicate = 0)
|
||||
echo_server_both = SConscript('#/examples/echo_server_both/SConscript',variant_dir = builddir + 'echo_server_both',duplicate = 0)
|
||||
print_client_tls = SConscript('#/examples/print_client_tls/SConscript',variant_dir = builddir + 'print_client_tls',duplicate = 0)
|
||||
|
||||
# broadcast_server
|
||||
broadcast_server = SConscript('#/examples/broadcast_server/SConscript',variant_dir = builddir + 'broadcast_server',duplicate = 0)
|
||||
|
||||
+35
-5
@@ -1,4 +1,34 @@
|
||||
HEAD
|
||||
- Examples: Add `print_client` example. This demonstrates a minimal non-TLS
|
||||
client that connects to a server and prints out the messages it receives.
|
||||
- Examples: Add `print_client_tls` example. This demonstrates a minimal TLS
|
||||
client, including basic support via Asio+OpenSSL for certificate chain
|
||||
and hostname verification.
|
||||
- Feature: Add getter for all headers to the HTTP parsers. This allows a
|
||||
wrapping library to enumerate all headers to send upstream. Thank you Jupp
|
||||
Müller for reporting and an initial pull request.
|
||||
- Improvement: Move the `socket_init_handler` to execute as a part of `init_asio`
|
||||
rather than connection `pre_init`. This allows setting of socket options prior
|
||||
to the bind/listen/accept system calls. Thank you ChristianRobl3D for
|
||||
reporting #530.
|
||||
- Compatibility: Make sure the chrono library used by Boost/Asio is in sync
|
||||
with what the websocketpp is using. Thank you Flow86 for reporting and a
|
||||
patch.
|
||||
- Compatibility: Update `telemetry_client` to use a slightly more cross platform
|
||||
method of sleeping. Should work on windows now. Thank you Meir Yanovich for
|
||||
reporting.
|
||||
- Bug: Store loggers in shared pointers to avoid crashes related to connections
|
||||
trying to write logs entries after their respective endpoint has been
|
||||
deallocated. Thank you Thalhammer for reporting and Jupp Müller for the
|
||||
patch. #539 #501
|
||||
- Bug: Change default listen backlog from 0 to `socket_base::max_connections`.
|
||||
#549. Thank you derwassi and zwelab for reporting and na1pir for providing
|
||||
access to hardware to debug the issue.
|
||||
- Bug: Fix a crash in the accept loop when `get_connection` fails. #551 Thank you
|
||||
Walter Gray for a patch.
|
||||
- Bug/Documentation: Fix incorrect example code that used
|
||||
`websocketpp::lib::error_code` instead of `websocketpp::exception`. Thank you
|
||||
heretic13 for reporting
|
||||
|
||||
0.7.0 - 2016-02-22
|
||||
- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method
|
||||
@@ -31,9 +61,9 @@ HEAD
|
||||
and `string::empty()`. This avoids generating unnecessary temporary objects.
|
||||
#468 Thank you Vladislav Yaroslavlev for reporting and a patch.
|
||||
- Documentation: Adds an example demonstrating the use of external `io_service`
|
||||
- Documentation: Adds a simple echo_client example.
|
||||
- Documentation: Adds a simple `echo_client` example.
|
||||
- Documentation: Begins migration of the web based user manual into Doxygen.
|
||||
- Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark
|
||||
- Bug: Fix memory leak when `init_asio` produces an error. #454 Thank you Mark
|
||||
Grimes for reporting and fixing.
|
||||
- Bug: Fix crash when processing a specially crafted HTTP header. Thank you Eli
|
||||
Fidler for reporting, test cases, and a patch. #456
|
||||
@@ -51,7 +81,7 @@ HEAD
|
||||
- Bug: Fix an issue where TLS includes were broken for Asio Standalone builds.
|
||||
Thank you giachi and Bastien Brunnenstein for reporting. #491
|
||||
- Bug: Remove the use of cached read and write handlers in the Asio transport.
|
||||
This feature caused memory leaks when the io_service the connection was
|
||||
This feature caused memory leaks when the `io_service` the connection was
|
||||
running on was abruptly stopped. There isn't a clean and safe way of using
|
||||
this optimization without global state and the associated locks. The locks
|
||||
perform worse. Thank you Xavier Gibert for reporting, test cases, and code.
|
||||
@@ -60,8 +90,8 @@ HEAD
|
||||
Xavier Gibert for reporting and a patch #524
|
||||
- Compatibility: Fixes a number of build & config issues on Visual Studio 2015
|
||||
- Compatibility: Removes non-standards compliant masking behavior. #395, #469
|
||||
- Compatibility: Replace deprecated use of auto_ptr on systems where unique_ptr
|
||||
is available.
|
||||
- Compatibility: Replace deprecated use of `auto_ptr` on systems where
|
||||
`unique_ptr` is available.
|
||||
|
||||
0.6.0 - 2015-06-02
|
||||
- MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be
|
||||
|
||||
@@ -14,15 +14,15 @@ macro (print_used_build_config)
|
||||
message (STATUS "WEBSOCKETPP_BOOST_LIBS = ${WEBSOCKETPP_BOOST_LIBS}")
|
||||
message (STATUS "WEBSOCKETPP_PLATFORM_LIBS = ${WEBSOCKETPP_PLATFORM_LIBS}")
|
||||
message (STATUS "WEBSOCKETPP_PLATFORM_TLS_LIBS = ${WEBSOCKETPP_PLATFORM_TLS_LIBS}")
|
||||
message ("")
|
||||
message ("")
|
||||
message (STATUS "OPENSSL_FOUND = ${OPENSSL_FOUND}")
|
||||
message (STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
|
||||
message (STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
|
||||
message (STATUS "OPENSSL_VERSION = ${OPENSSL_VERSION}")
|
||||
message ("")
|
||||
message ("")
|
||||
endmacro ()
|
||||
|
||||
# Adds the given folder_name into the source files of the current project.
|
||||
# Adds the given folder_name into the source files of the current project.
|
||||
# Use this macro when your module contains .cpp and .h files in several subdirectories.
|
||||
# Your sources variable needs to be WSPP_SOURCE_FILES and headers variable WSPP_HEADER_FILES.
|
||||
macro(add_source_folder folder_name)
|
||||
@@ -39,7 +39,7 @@ macro (init_target NAME)
|
||||
set (TARGET_NAME ${NAME})
|
||||
message ("** " ${TARGET_NAME})
|
||||
|
||||
# Include our own module path. This makes #include "x.h"
|
||||
# Include our own module path. This makes #include "x.h"
|
||||
# work in project subfolders to include the main directory headers.
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endmacro ()
|
||||
@@ -74,8 +74,8 @@ endmacro ()
|
||||
# Finalize target for all types
|
||||
macro (final_target)
|
||||
if ("${TARGET_LIB_TYPE}" STREQUAL "EXECUTABLE")
|
||||
install (TARGETS ${TARGET_NAME}
|
||||
RUNTIME DESTINATION "bin"
|
||||
install (TARGETS ${TARGET_NAME}
|
||||
RUNTIME DESTINATION "bin"
|
||||
CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES})
|
||||
endif ()
|
||||
|
||||
@@ -89,14 +89,17 @@ endmacro ()
|
||||
|
||||
macro (link_boost)
|
||||
target_link_libraries (${TARGET_NAME} ${Boost_LIBRARIES})
|
||||
set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
|
||||
endmacro ()
|
||||
|
||||
macro (link_openssl)
|
||||
target_link_libraries (${TARGET_NAME} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
|
||||
set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
|
||||
endmacro ()
|
||||
|
||||
macro (link_zlib)
|
||||
target_link_libraries (${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIR})
|
||||
endmacro ()
|
||||
|
||||
macro (include_subdirs PARENT)
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/** \page reference.config Config Reference
|
||||
|
||||
WebSocket++ uses a config template parameter to supply a number of compile type policy types and default numerical values for buffer sizes, timeouts, security behavior, etc. Swapping policies allows changing certain core library behavior designed to be pluggable.
|
||||
|
||||
A custom config can be made standalone or can subclass one of the bundled configs and just override a few things.
|
||||
|
||||
__Example__
|
||||
```
|
||||
// some config options may require additional includes or dependencies.
|
||||
// syslog logging policy, for example, requires <syslog.h>,
|
||||
// the permessage deflate settings require zlib.
|
||||
#include <websocketpp/logger/syslog.hpp>
|
||||
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
|
||||
|
||||
// Custom server config based on bundled asio config
|
||||
struct custom_server_config : public websocketpp::config::asio {
|
||||
// Replace default stream logger with a syslog logger
|
||||
typedef websocketpp::log::syslog<concurrency_type, websocketpp::log::elevel> elog_type;
|
||||
typedef websocketpp::log::syslog<concurrency_type, websocketpp::log::alevel> alog_type;
|
||||
|
||||
// Reduce read buffer size to optimize for small messages
|
||||
static const size_t connection_read_buffer_size = 1024;
|
||||
|
||||
// enable permessage_compress extension
|
||||
struct permessage_deflate_config {};
|
||||
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<custom_server_config> server_endpoint_type;
|
||||
```
|
||||
|
||||
Core Config Options
|
||||
-------------------
|
||||
|
||||
### Policies
|
||||
|
||||
Policies are classes used to allow clean swapping of behavior without changing the core library
|
||||
|
||||
| Typedef Name | Effect |
|
||||
| ------------------------- | -------------------------------------- |
|
||||
| concurrency_type | Concurrency policy |
|
||||
| elog_type | Error logger type |
|
||||
| alog_type | Access logger type |
|
||||
| request_type | HTTP request type |
|
||||
| response_type | HTTP response type |
|
||||
| message_type | Type to deliver recieved messages |
|
||||
| con_msg_manager_type | Connection level message manager |
|
||||
| endpoint_msg_manager_type | Endpoint level message manager |
|
||||
| rng_type | Random Number Generation policy |
|
||||
| transport_type | Transport policy to use |
|
||||
| endpoint_base | User overridable Endpoint base class |
|
||||
| connection_base | User overridable Connection base class |
|
||||
|
||||
### Timeouts Values
|
||||
|
||||
These represent the length of time (in ms) before the given operation is aborted
|
||||
|
||||
| Field | Type | Default | Operation |
|
||||
| ----------------------- | ---- | ------- | --------------------------- |
|
||||
| timeout_open_handshake | long | 5000 | Opening handshake |
|
||||
| timeout_close_handshake | long | 5000 | Closing handshake |
|
||||
| timeout_pong | long | 5000 | No pong recieved after ping |
|
||||
|
||||
### Performance tuning
|
||||
|
||||
| Field | Type | Default | Meaning |
|
||||
| --------------------------- | ------ | -------- | ------------------------------------------------------------------ |
|
||||
| connection_read_buffer_size | size_t | 16384 | Size of the per-connection read buffer |
|
||||
| enable_multithreading | bool | true | Disabling may reduce locking overhead for single threaded programs |
|
||||
|
||||
#### Connection Read Buffer
|
||||
|
||||
Each connection has an internal buffer of this size. A larger value will result in fewer trips through the library and less CPU overhead at the expense of increased memory usage per connection.
|
||||
|
||||
If your application primarily deals in very large messages you may want to try setting this value higher.
|
||||
|
||||
If your application has a lot of connections or primarily deals in small messages you may want to try setting this smaller.
|
||||
|
||||
### Security settings
|
||||
|
||||
| Field | Type | Default | Effect |
|
||||
| ---------------------- | ------ | ------- | -------------------------------------- |
|
||||
| drop_on_protocol_error | bool | false | Omit close handshake on protocol error |
|
||||
| silent_close | bool | false | Don't return close codes or reasons |
|
||||
| max_message_size | size_t | 32MB | WebSocket max message size limit |
|
||||
| max_http_body_size | size_t | 32MB | HTTP Parser's max body size limit |
|
||||
|
||||
#### Drop on protocol error
|
||||
Drop connections on protocol error rather than sending a close frame. Off by default. This may result in legitimate messages near the error being dropped as well. It may free up resources otherwise spent dealing with misbehaving clients.
|
||||
|
||||
#### Silent Close
|
||||
Silence close suppresses the return of detailed connection close information during the closing handshake. This information is useful for debugging and presenting useful errors to end users but may be undesirable for security reasons in some production environments. Close reasons could be used by an attacker to confirm that the endpoint is out of resources or be used to identify the WebSocket implementation in use.
|
||||
|
||||
Note: this will suppress *all* close codes, including those explicitly sent by local applications.
|
||||
|
||||
#### Max message size
|
||||
Default value for the processor's maximum message size. Maximum message size determines the point at which the library will drop a connection with the message_too_big protocol error.
|
||||
|
||||
#### Max HTTP header size
|
||||
Maximum body size determines the point at which the library will abort reading an HTTP message body and return the 413/request entity too large error.
|
||||
|
||||
Transport Config Options
|
||||
------------------------
|
||||
|
||||
### Policies
|
||||
|
||||
Policies are classes used to allow clean swapping of behavior without changing the core library
|
||||
|
||||
| Typedef Name | Effect |
|
||||
| ---------------- | ------------------ |
|
||||
| concurrency_type | Concurrency Policy |
|
||||
| elog_type | Error logger type |
|
||||
| alog_type | Access logger type |
|
||||
| request_type | HTTP request type |
|
||||
| response_type | HTTP response type |
|
||||
|
||||
### Timeouts Values
|
||||
|
||||
These represent the length of time (in ms) before the given operation is aborted
|
||||
|
||||
| Field | Type | Default | Operation |
|
||||
| ------------------------ | ---- | ------- | --------------------------------------------- |
|
||||
| timeout_socket_pre_init | long | 5000 | Transport dependent |
|
||||
| timeout_proxy | long | 5000 | Proxy handshake |
|
||||
| timeout_socket_post_init | long | 5000 | Transport dependent (commonly: TLS handshake) |
|
||||
| timeout_dns_resolve | long | 5000 | DNS resolution |
|
||||
| timeout_connect | long | 5000 | TCP Connect |
|
||||
| timeout_socket_shutdown | long | 5000 | Socket shutdown |
|
||||
|
||||
### Performance tuning
|
||||
|
||||
| Field | Type | Default | Meaning |
|
||||
| --------------------------- | ------ | -------- | ------------------------------------------------------------------ |
|
||||
| enable_multithreading | bool | true | Disabling may reduce locking overhead for single threaded programs |
|
||||
|
||||
*/
|
||||
@@ -1,5 +1,74 @@
|
||||
/** \page faq FAQ
|
||||
|
||||
## General Library Usage
|
||||
|
||||
### Can a handler be changed after a connection is established? Can one be removed?
|
||||
Yes, but not globally.
|
||||
|
||||
Handlers assigned to endpoints will be automatically copied to the connections created by that endpoint. Changing a handler on an endpoint will only affect future connections.
|
||||
|
||||
Once a particular connection is created, it's handlers can be changed individually by calling the `set_*_handler` methods. Once changed, all future events of that type for that connection will use the new handler.
|
||||
|
||||
To remove a handler that was previously set, call the set method with `nullptr` or `NULL`.
|
||||
|
||||
### Can I reject or conditionally accept a connection
|
||||
Yes. The `validate` handler is called after the initial handshake has been recieved but before WebSocket++ has responded. This gives you the opportunity to inspect the incoming connection request, its headers, origin, subprotocols, and the remote endpoint IP. Return `true` from the validate handler to accept the connection and `false` to reject it.
|
||||
|
||||
To set a custom HTTP error message for your rejection, use `websocketpp::connection::set_status` and (optionally) `websocketpp::connection::set_body()` to set the HTTP status code and error message body text. If you do not set body text a message will be generated automatically based on the status code.
|
||||
|
||||
### How do I negotiate subprotocols?
|
||||
WebSocket connections may offer a particular subprotocol they want to use. The WebSocket protocol does not define the meaning or interpretation of the subprotocol. This interpretation is left up to the individual application endpoints.
|
||||
|
||||
WebSocket++ servers can read the requested subprotocols during the `validate` handler by calling `websocketpp::connection::get_requested_subprotocols`. The list is ordered by client priority. You may optionally choose one of these subprotocols with `websocketpp::connection::select_subprotocol`. The handshake will then complete and let the client know which one was chosen. If you do not choose any, the "blank"/empty/none subprotocol will be used.
|
||||
|
||||
WebSocket++ clients can add a subprotocol to an outgoing connection by calling `websocketpp::connection::add_subprotocol` before calling `websocketpp::client::connect`. The order of adding will be interpreted as the order of preference.
|
||||
|
||||
In both caases, after the connection has been established, the selected subprotocol is available via the `websocketpp::connection::get_subprotocol` method.
|
||||
|
||||
Note: some browsers will allow the connection to continue if they requested a subprotocol and your server doesn't select one. Others will reject the connection.
|
||||
|
||||
### How do I cleanly exit an Asio transport based program
|
||||
|
||||
The Asio transport based clients and servers use the Asio library's underlying `io_service` to handle asyncronous networking operations. The standard behavior of the io_service is to run until there are no async operations left and then return. WebSocket++, when using the Asio transport, behaves like a standard Asio application. If you want your WebSocket++/Asio based program to stop network operations and cleanly close all sockets you will want to do the following:
|
||||
|
||||
- For servers, call `websocketpp::transport::asio::endpoint::stop_listening` to initiate the closing of the server listening socket.
|
||||
- For clients, if you have engaged perpetual mode with `websocketpp::transport::asio::endpoint::start_perpetual`, disable it with `websocketpp::transport::asio::endpoint::stop_perpetual`.
|
||||
- For both, run `websocketpp::endpoint::close` or `websocketpp::connection::close` on all currently outstanding connections. This will initiate the WebSocket closing handshake for these connections
|
||||
- Wait. Asio is asyncronous. When the calls to the above methods (stop_listening, close, etc) complete the server *will still be listening*, the connections *will still be active* until the io_service gets around to asyncronously processing the socket and WebSocket protocol closing handshakes. The `io_service::run` method will exit cleanly and automatically when all operations are complete.
|
||||
|
||||
__WARNING__: Asio's `io_service` has a method called `stop`. WebSocket++ wraps this method as `websocketpp::transport::asio::endpoint::stop`. While this operation has a benign sounding name, it is a powerful and destructive operation that should only be used in special cases. If you are using `io_service::stop` or `endpoint::stop` without a very good reason your program is likely broken and may exhibit erratic behavior. Specifically, `io_service::stop` stops the processing of events entirely. This does not give current operations (such as socket closing handshakes) the opportunity to finish. It will leave your sockets in a dangling state that may invoke operating system level timeouts or other errors.
|
||||
|
||||
__Special cases__:
|
||||
- If your client uses the `start_perpetual` method it will prevent the io_service from exiting even if it has nothing to do. This is useful if you want a client endpoint to idle in the background to allow new connections to be formed on demand rather than generating a new endpoint for each.
|
||||
- If you are using an external io_service and/or are placing non-WebSocket++ operations on the `io_service` those operations may keep the `io_service` open even after all WebSocket++ operations have completed.
|
||||
- If you are using `poll`/`poll_one`/`run_one` or otherwise manually driving the `io_service` event loop you may need to adjust usage to make sure you are correctly recognizing the "done with work" and "not done but idling / `io_service::work`" cases.
|
||||
|
||||
### Is there a way to check the validity of a `connection_hdl`?
|
||||
|
||||
Sometimes, not generally though, because there isn’t a way to check if a TCP connection is valid.
|
||||
|
||||
You can try upgrading your hdl to a full connection_ptr using `websocketpp::endpoint::get_con_from_hdl`. If this fails, the hdl is definitely invalid. If it succeeds it may or may not be. The only way to tell definitively is to try and send something (either a message or a ping).
|
||||
|
||||
If you handle errors from methods like send, ping, close, etc correctly then you shouldn’t have to worry about accidentally sending to dead connections. The send/ping/pong/close methods will set or throw a specific error in the case that you tried to send something but the connection was closed/gone/etc.
|
||||
|
||||
### How do I fix the "address is in use" error when trying to restart my server?
|
||||
|
||||
Normally, for security purposes, operating systems prevent programs from listening on sockets created by other programs. When your program crashes and restarts, the new instance is a different program from the perspective of the operating system. As such it can’t listen on the socket address/port that the previous program was using until after a timeout occurs to make sure the old program was done with it.
|
||||
|
||||
The the first step for handling this is to make sure that you provide a method (signal handler, admin websocket message, etc) to perform a clean server shutdown. There is a question elsewhere in this FAQ that describes the steps necessary for this.
|
||||
|
||||
The clean close strategy won't help in the case of crashes or other abnormal closures. An option to consider for these cases is the use of the SO_REUSEADDR socket option. This instructs the OS to not request an exclusive lock on the socket. This means that after your program crashes the replacement you start can immediately listen on that address/port combo again.
|
||||
|
||||
__Please note__: how this works exactly depends on your operating system. Additionally, not exclusively locking your listening socket could allow hijacking by other programs if you are running in a shared resource environment. For development this is generally no problem. For a production environment, think carefully about the security model. `websocketpp::transport::asio::endpoint::set_reuse_addr` is the method to do this. You must specify this setting before calling `websocketpp::transport::asio::endpoint::listen`.
|
||||
|
||||
### How do I send and recieve binary messages?
|
||||
|
||||
When supported by the remote endpoint, WebSocket++ allows reading and sending messages in the two formats specified in RFC6455, UTF8 text and binary. WebSocket++ performs UTF8 validation on all outgoing text messages to ensure that they meet the specification. Binary messages do not have any additional processing and their interpretation is left entirely to the library user.
|
||||
|
||||
To determine the type of an incoming message, use `websocketpp::message_buffer::message::get_opcode`. The relevant return values are `websocketpp::frame::opcode::text` and `websocketpp::frame::opcode::binary`. There is no difference in how payloads are retrieved between these modes, only in how WebSocket++ validated the contents and how the library user is to interpret the data.
|
||||
|
||||
To specify the type of an outgoing message, use the frame opcode values listed above as the second op parameter for `websocketpp::connection::send`. There are two relevant overloads of send. One that takes a `std::string` and defaults to op=text. The other that takes a `void const *` and a `size_t` length and defaults to op=binary. Note: You can send binary messages via the string overload and text messages via the void * overload. In the case that you are manually building a message buffer rather than using the automatic send member functions, you can pass the opcode in as a parameter to the message buffer constructor or user the `websocketpp::message_buffer::message::set_opcode` member function to set or re-set it later.
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### Can WebSocket++ be used without Boost?
|
||||
@@ -19,6 +88,8 @@ Whether an Asio endpoint uses TLS or not is determined by its config template pa
|
||||
|
||||
The `<websocketpp/config/asio.hpp>` and `<websocketpp/config/asio_client.hpp>` headers will include both the TLS and non-TLS varients of their respective configs and require the presence of OpenSSL. The `<websocketpp/config/asio_no_tls.hpp>` and `<websocketpp/config/asio_no_tls_client.hpp>` headers will include only the non-TLS configs and do not require OpenSSL.
|
||||
|
||||
### Build issues with TLS on recent versions of OS X
|
||||
Mac OS X ships a severely outdated version of the OpenSSL library. To securely use TLS with WebSocket++ on OS X you will need to install a modern version of OpenSSL via homebrew or compiling from source.
|
||||
|
||||
## Compression
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/** \page reference.logging Logging Reference
|
||||
|
||||
WebSocket++ has the capability of logging events during the lifetime of the connections that it processes. Each endpoint has two independent logging interfaces that are used by all connections created by that endpoint. The first is an access interface that allows logging routine events in the life of a connection (such as connect/disconnect and receipt of messages). The other is an error interface that allows logging non-routine problems or errors. Each interface has a number of different named channels that can be toggled on and off independently.
|
||||
|
||||
Exactly how these logs are processed and where they are written to depends on which logging policy is in use. Several logging policies are included by default and you can write your own policy if you need something more specialized. Selecting a policy is done via the \subpage reference.config "endpoint config".
|
||||
|
||||
Common functionality (all policies)
|
||||
-----------------------------------
|
||||
|
||||
### Logging Channels
|
||||
|
||||
Each logging interface is divided into 32 named channels. Log messages are written to a specific interface on a specific channel. Which log messages are actually printed is determined by which channels are enabled or not. Channels can be enabled or disabled either at compile time or at runtime.
|
||||
|
||||
### Enabling and Disabling Channels
|
||||
|
||||
Channels disabled at compile time are removed from the code entirely (assuming correct compiler optimization settings) and are not available for runtime enabling or disabling. To disable channels at compile time, use the `alog_level` and `elog_level` values within your \subpage reference.config "endpoint config". Channels not disabled at compile time can be enabled or disabled at runtime using the `websocketpp::endpoint::set_access_channels()`, `websocketpp::endpoint::clear_access_channels()`, `websocketpp::endpoint::set_error_channels()`, and `websocketpp::endpoint::clear_error_channels()` methods.
|
||||
|
||||
The set and clear functions act only on the channels specified. `set_access_channels(log::alevel::connect)` will enable logging of new connections. Following this with `set_access_channels(log::alevel::disconnect)` will enable logging of disconnections in addition to connections. Use `clear*` functions to disable a specific channel. Channels may be combined using bitwise operations to create aggregate packages of channels that may be set or cleared at once. Default packages include `websocketpp::log::alevel::all`, `websocketpp::log::elevel::all`, `websocketpp::log::alevel::none`, `websocketpp::log::elevel::none`. These represent all possible access/error channels and no access/error channels respectively. For convenience, setting none is aliased to clearing all.
|
||||
|
||||
### Examples
|
||||
|
||||
__Disable all__
|
||||
|
||||
`clear_access_channels(log::alevel::all)`
|
||||
|
||||
__Disable all (alternative method)__
|
||||
|
||||
`set_access_channels(log::alevel::none)`
|
||||
|
||||
__Multiple channels at once__
|
||||
|
||||
`log::alevel::message_payload | log::alevel::message_payload`
|
||||
|
||||
__All except one__
|
||||
|
||||
`log::alevel::all ^ log::alevel::message_payload`
|
||||
|
||||
__Default settings__
|
||||
|
||||
By default, only debug/development logging is disabled.
|
||||
|
||||
### Access to underlying loggers
|
||||
|
||||
Logging interfaces may be directly accessed via their associated endpoint or connection using get_alog() and get_elog(). This allows access to methods specific to the chosen logging policy.
|
||||
|
||||
Basic Logging (Default Policy)
|
||||
------------------------------
|
||||
|
||||
The basic logging policy (`websocketpp::log::basic`) writes logs to a std::ostream. By default, access logs are written to stdout and error logs are written to stderr. Each logging interface may be optionally redirected to an arbitrary C++ stream (including file streams) using the `websocketpp::log::basic::set_ostream()` method.
|
||||
|
||||
Syslog Logging
|
||||
--------------
|
||||
|
||||
The syslog logging policy (`websocketpp::log::syslog`) logs to POSIX syslog. It is included in the header `<websocketpp/logger/syslog.hpp>`. It requires a system with `<syslog.h>`.
|
||||
|
||||
Stub Logging
|
||||
------------
|
||||
|
||||
The stub logging policy (`websocketpp::log::stub`) implements the logging policy interface but ignores all input and provides no output. It can be used to stub out the logging system in tests or to completely disable and remove nearly all logging related code.
|
||||
|
||||
The stub logger also provides documentation for the minimal required interface to build a custom logging policy.
|
||||
|
||||
Log level reference
|
||||
-------------------
|
||||
|
||||
### Error Logging Levels
|
||||
|
||||
Each of these channels is in the namespace `websocketpp::log::elevel`
|
||||
|
||||
| Level | Description |
|
||||
| ------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| none | Special aggregate value representing "no levels" |
|
||||
| devel | Low level debugging information (warning: very chatty). Requires debug or custom config. |
|
||||
| library | Information about unusual system states or other minor internal library problems, less chatty than devel. |
|
||||
| info | Information about minor configuration problems or additional information about other warnings. |
|
||||
| warn | Information about important problems not severe enough to terminate connections. |
|
||||
| rerror | Recoverable error. Recovery may mean cleanly closing the connection with an appropriate error code to the remote endpoint. |
|
||||
| fatal | Unrecoverable error. This error will trigger immediate unclean termination of the connection or endpoint. |
|
||||
| all | Special aggregate value representing "all levels" |
|
||||
|
||||
### Access Logging Levels
|
||||
|
||||
Each of these channels is in the namespace `websocketpp::log::alevel`
|
||||
|
||||
| Level | Description |
|
||||
| --------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| none | Special aggregate value representing "no levels" |
|
||||
| connect | One line for each new connection that includes a host of information including: the remote address, websocket version, requested resource, http code, remote user agent |
|
||||
| disconnect | One line for each connection that is closed. Includes closing codes and reasons |
|
||||
| control | One line per control message |
|
||||
| frame_header | One line per frame, includes the full frame header |
|
||||
| frame_payload | One line per frame, includes the full message payload (warning: lots of output for large messages) |
|
||||
| message_header | Reserved |
|
||||
| message_payload | Reserved |
|
||||
| endpoint | Reserved |
|
||||
| debug_handshake | Extra information about opening handshakes |
|
||||
| debug_close | Extra information about closing handshakes |
|
||||
| devel | Development messages (warning: very chatty). Requires debug or custom config. |
|
||||
| app | Special channel for application specific logs. Not used by the library. |
|
||||
| all | Special aggregate value representing "all levels" |
|
||||
|
||||
*/
|
||||
@@ -16,6 +16,8 @@ In order to accommodate the wide variety of use cases WebSocket++ has collected,
|
||||
- \subpage md_changelog "Change Log / Version History"
|
||||
- Reference
|
||||
- \subpage reference.handlers "Handler Reference"
|
||||
- \subpage reference.config "Config Reference"
|
||||
- \subpage reference.logging "Logging Reference"
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -157,10 +157,10 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
perftest endpoint;
|
||||
endpoint.start(uri);
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (std::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
|
||||
@@ -128,9 +128,9 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@ int main() {
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ void on_message(EndpointType* s, websocketpp::connection_hdl hdl,
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,55 +1,57 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA77v5VbFaq+geVd/RCLXoKTWj/LgXGjiOXBpJZca3o5edi7N1
|
||||
Ej41/13jfZ4OxgFIRFAALd+fU4NsObXzskth3rJLmJjUtGajRIPqF2IUVjFMmybQ
|
||||
9dUDSqPzd/bG+ul0DP7DNuiBcLC8XNC3/kchPUzVq9gNDk56jXn87kMoIkVXBWQS
|
||||
Rwk0yCtELSfwxxRCrGKgQDfXnRdwmkPe42DmKtdGksXJlUhP1UVTAXaSw1Nz64LV
|
||||
9bJje/eoDsSe4OxifVVToE6ZxIW+r1jVgrcupeYXQrSHIztl2U/rx2JkGMN0eS+P
|
||||
qrsJmkmRBN1cpgmvSV7WoM3hj6Eq71z4Dfv6EwIDAQABAoIBAEXAL19bZsI1mv3p
|
||||
TOx34MB8tuXEuhQK+ICbtVdDZhLW/iOzZxCTwSo3qwTVg/7gSKJ3lFXEhprJ1idE
|
||||
ZU8u157vyUbw0JJceoxoxSdghgI9/cf2lz2vaHHDGgeBaYt/eSB+z1WeeGrNQUDQ
|
||||
CXiWQXmQbWq+Ra4v70BSieDY8UhmzCTRhvfZV80vaY/4SnHxJ9C8Nu8/An7U3pwq
|
||||
ccfTaWMp3Q5ztmEnExF6/b1SUsnI8rzFovw/4C50AU09N/Z6zZVFsXgJAT2Kd1Tx
|
||||
HfP1vUkWZ/TJ6kcmVIV9U3uMcedBD8Rb/3M0Qdp+eymQ+1oYQ3K3/a2RlUQIeXzf
|
||||
hRbE4wECgYEA/WyULrwBsvSMPqK0K9pZpv921Yl6d4bGnpxKze7ltc9o5/LsU35q
|
||||
8u29Es7cPyhyUDOsPW8v2CNjw54t+eFGsu59bBvXZNz5gB7hTUEyLntB24cO5PmN
|
||||
kVExcMDFC6NgPaauBtUhODievKJ2C8P7sRJDAVKE9KkavDddU7nSEjMCgYEA8ivG
|
||||
AqwNXYsiIFjAo4uj3kuBFt8LU/q4m6GXI+9qyxfiJjuF1dROx5qaQGiE85VaBFUu
|
||||
gpbnjZH7s+BBgoaQhrB4i6mztljdN1KKuAlnjhB+Fywg8m8N9lAi3wIaxnIEqDkU
|
||||
vFiIFPTBCk0U7IZ/OyCrKPQTE9ApWHfBwA/vWKECgYBQixrJg61SkBCms5Vpvprx
|
||||
zY2aLniC1o33yRqpOr09PG9OENH1c19QWCjYenBbjmJOhS2/1L+zBQRnHrXkDion
|
||||
Ik8wdeTORMDzbF0U7ZyiU0BKIjGkqn/I6LI68LlvinxC+9+hgkltkek5cLTt5lrv
|
||||
Gyu6ltx02e4KVdpOiuduKwKBgQC3U0PWigCkK8ttyUIrjG5Evcu/UKH2tPpDdpQ/
|
||||
8+JYVIAyiSTLtqjcmcDjuTvMWeeHGCTZXvtzRGvSw5VUBiIqlDTtJU6SX7s3QhkZ
|
||||
MKVf+kQ5roJShJeBOzDquWEjkPTNlEiKPErn8lCgR7HrS/XNAPIRUpOOkCp8ekwF
|
||||
5Qo/gQKBgAue3TeCeIzxh4PxSAk39Uaj+AaLvlYg8C+ucEodCNQZnJ7jOO0hHkfT
|
||||
NvZBes0VukCGlBLOGRQtC3kgtyrerscnDiZOhdnJrhPIdNPC0k/p/uAfh7+C5Sxm
|
||||
rCEL0S7kORdEjlIGd5j6ZEN/HZe8FyOYSjbFAoJSlAId9WMSxycQ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDMYjHlTUeUGSys
|
||||
Fz5PZcvgS3gojBlEAOu2gXFQDcJ7kq6dJ4jKsPaH1Q5jAtEDkU/el8otzfacOgyp
|
||||
2ZxioRimpmcORWGU0bKJcenh4ZQ1oK1CQObjeYk1YgE7H8/sBetSdtL4n1rB8LIz
|
||||
AV/k6kwSZFu3/lSmc6g09H4efSKGKVBcVOjBamcvFGVH4KhM2NyL+ffeV5H2Ucxk
|
||||
ipyhpr4uxEoC3EV60sQxloqZb+upBM0LS4kVvaYMcn39XkUx3Z8FwN5+hFGwsWda
|
||||
tU8zDxEuRMrZxG7mwDXLBGehtQvoJIVMQbOuwBQcgAbsVyy1dxV3aczbLX0iGEuG
|
||||
eBhdFE+BAgMBAAECggEAQaPn0nUXYAEVz89HO8i9ybNzS9Jy6txA18SK1+MTawyY
|
||||
9/AShsZ+5vEORc5JwpOQyzSEwmE7qsEaABLbnvGOMTeQMY0m4dzXMj1bmCgSqYaJ
|
||||
HpYpkTUfU/2913dIF81u3nU7HI5RX6gmEyuF2MdG10FUE6ujFDJg+2DqgHA//kYD
|
||||
hkXFinVS2PuZs8d5xdzpF0aCIWTuOc+Fgsyhdm/lZRIzFdID45YUVuPIN2uh+GkM
|
||||
ENp/r1x7dPlDRqiL1ufP0mTQGs26S5kQSF8W0BClkOIOgmrhSON4+Vqhqx+ki/7w
|
||||
RY+7mmgdvt0uzYT+Lk2cDw4f89Rsh7rR1EieBpQ2YQKBgQDq6zAHWfweJmkugT0w
|
||||
HzI0UKfcOdzlJBwMu6tSgSHU99dnXlTwQY8sG7vtfRekokoo7XY4JsSk1n6E9OVy
|
||||
4UKuEvU1+llDGxtvHxEEGOAgwB8wxMuY4uNYgDVhTlUzr2ERcet7FOIGzxEWzSsg
|
||||
5vgnTQfyMzAh5/6k8CsHVI4u2wKBgQDeuYVCgg555lcc5rvTFxfU15d3fweSd78+
|
||||
akgIBaXAlFbxI+5znGPmKG/ii4N2XObC8B568fA2nIxw6M1xgbKyvvmN3ECYiqWv
|
||||
bx8x6Vg5Slg0vJr+DrPgvIKbOWEEKF/cfpTeeVLP0gUBT63mA3qezuRx1r0JJr7A
|
||||
k9a4Td9j0wKBgDmRQMfMaVgKGaRnz1LHkkn3qerx0wvj+Wu1YZpqQpwp0ANovm/R
|
||||
4P/yG+9qxCx4CKxW5K2F8pJibcavLLsmMGzwAF8l5lHnhqWIe2cBoYrlCb+tuibR
|
||||
Et1RLcOWqpJr2+GmhQo4Z9s7SvjHdlYtw4n9+oCDwrvMWj6ZDDJTqjQZAoGAEhRt
|
||||
RODZ2/texvHT/Wa6gISfvwuIydL+q0plXoFW2zMve5O3H5tqYJyXuIQqv8j60og7
|
||||
cS+CmGxM2j2Lr9MfdnMaPvHKLJfUq1ER7zNJ/hyS3HUS/9yhrXSgBYm63mOIpJWB
|
||||
8C1ZE5Ww4lJdg3Z01b9lu/f6kGucwHU/0OZBZBECgYAQ+dl2kKKd+lQ9O/LVz7oD
|
||||
goQMPYF+QZcEhY4vlYKkWVtR2A0CiY6XeTi6vO/qVUt/ht+UO3XIJFOjGV1VyORQ
|
||||
Bhibfstxl5s59jGlns5y5QqcRKzCiX74BKG0xQUtHgga7Od6L+GJKbJAPBfncYwW
|
||||
U7Tfwwi0WbbgQoy5Xr/5gg==
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEpzCCA4+gAwIBAgIJAMlCHvwnJ+F/MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCSUwxEDAOBgNVBAcTB0NoaWNhZ28xGTAXBgNVBAoT
|
||||
EFdlYlNvY2tldCsrIERlbW8xIjAgBgNVBAMTGXV0aWxpdGllcy53ZWJzb2NrZXRw
|
||||
cC5vcmcxJjAkBgkqhkiG9w0BCQEWF3dlYnNvY2tldHBwQHphcGhveWQuY29tMB4X
|
||||
DTE1MDQyNTE1NTk1M1oXDTE4MDMyODE1NTk1M1owgZMxCzAJBgNVBAYTAlVTMQsw
|
||||
CQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEZMBcGA1UEChMQV2ViU29ja2V0
|
||||
KysgRGVtbzEiMCAGA1UEAxMZdXRpbGl0aWVzLndlYnNvY2tldHBwLm9yZzEmMCQG
|
||||
CSqGSIb3DQEJARYXd2Vic29ja2V0cHBAemFwaG95ZC5jb20wggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDvu/lVsVqr6B5V39EItegpNaP8uBcaOI5cGkll
|
||||
xrejl52Ls3USPjX/XeN9ng7GAUhEUAAt359Tg2w5tfOyS2HeskuYmNS0ZqNEg+oX
|
||||
YhRWMUybJtD11QNKo/N39sb66XQM/sM26IFwsLxc0Lf+RyE9TNWr2A0OTnqNefzu
|
||||
QygiRVcFZBJHCTTIK0QtJ/DHFEKsYqBAN9edF3CaQ97jYOYq10aSxcmVSE/VRVMB
|
||||
dpLDU3PrgtX1smN796gOxJ7g7GJ9VVOgTpnEhb6vWNWCty6l5hdCtIcjO2XZT+vH
|
||||
YmQYw3R5L4+quwmaSZEE3VymCa9JXtagzeGPoSrvXPgN+/oTAgMBAAGjgfswgfgw
|
||||
HQYDVR0OBBYEFAWNBET93ZzSukXGkuGb93CfmUkDMIHIBgNVHSMEgcAwgb2AFAWN
|
||||
BET93ZzSukXGkuGb93CfmUkDoYGZpIGWMIGTMQswCQYDVQQGEwJVUzELMAkGA1UE
|
||||
CBMCSUwxEDAOBgNVBAcTB0NoaWNhZ28xGTAXBgNVBAoTEFdlYlNvY2tldCsrIERl
|
||||
bW8xIjAgBgNVBAMTGXV0aWxpdGllcy53ZWJzb2NrZXRwcC5vcmcxJjAkBgkqhkiG
|
||||
9w0BCQEWF3dlYnNvY2tldHBwQHphcGhveWQuY29tggkAyUIe/Ccn4X8wDAYDVR0T
|
||||
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA2DRQSDmo2Q5t8MEjp6jddRIFts5t
|
||||
BDBWPSwJ0qvmheFt53MuLds2hhvMn42WGrKtVJiLiDyOWuUZ41REJZb1uaissUuY
|
||||
r9pLuP5QLdibx7+/30iDEY0OGTgtSTfgwNx8bIApBSHoZEN3/HaikqplBng2+6u/
|
||||
kTe6UnRrBJ+8JOGl+duhCXNPeSyLa2NcrxE9XpWC/k1kC9MTUF+2NuqCtK3zO8ci
|
||||
p0mqARWDSrEBYISh3dAOgDFrcX6zj+0MK+iswu3ijEdItGAjxjlQ2t4XT1T/CDbc
|
||||
ysHg04TJw7v682+v124GrnrAPYUK34OK8kFVJ60SNYRUi7euOCdTM4Lwkw==
|
||||
MIIFBTCCAu2gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVT
|
||||
MQswCQYDVQQIDAJJTDEUMBIGA1UECgwLV2ViU29ja2V0KysxKjAoBgNVBAsMIVdl
|
||||
YlNvY2tldCsrIENlcnRpZmljYXRlIEF1dGhvcml0eTEkMCIGA1UEAwwbV2ViU29j
|
||||
a2V0KysgSW50ZXJtZWRpYXRlIENBMB4XDTE2MDYwODEyNDUxMloXDTI2MDYwNjEy
|
||||
NDUxMlowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGlj
|
||||
YWdvMRQwEgYDVQQKDAtXZWJTb2NrZXQrKzEgMB4GA1UECwwXV2ViU29ja2V0Kysg
|
||||
VExTIEV4YW1wbGUxGDAWBgNVBAMMD3dlYnNvY2tldHBwLm9yZzCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAMxiMeVNR5QZLKwXPk9ly+BLeCiMGUQA67aB
|
||||
cVANwnuSrp0niMqw9ofVDmMC0QORT96Xyi3N9pw6DKnZnGKhGKamZw5FYZTRsolx
|
||||
6eHhlDWgrUJA5uN5iTViATsfz+wF61J20vifWsHwsjMBX+TqTBJkW7f+VKZzqDT0
|
||||
fh59IoYpUFxU6MFqZy8UZUfgqEzY3Iv5995XkfZRzGSKnKGmvi7ESgLcRXrSxDGW
|
||||
iplv66kEzQtLiRW9pgxyff1eRTHdnwXA3n6EUbCxZ1q1TzMPES5EytnEbubANcsE
|
||||
Z6G1C+gkhUxBs67AFByABuxXLLV3FXdpzNstfSIYS4Z4GF0UT4ECAwEAAaOBhzCB
|
||||
hDALBgNVHQ8EBAMCBDAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwYAYDVR0RBFkwV4IP
|
||||
d2Vic29ja2V0cHAub3JnghN3d3cud2Vic29ja2V0cHAub3Jnghl1dGlsaXRpZXMu
|
||||
d2Vic29ja2V0cHAub3JnghRkb2NzLndlYnNvY2tldHBwLm9yZzANBgkqhkiG9w0B
|
||||
AQsFAAOCAgEAelJvIWFikBU3HVoP0icuoezTHGqABPLCeooTC/GELq7lHCFEjiqW
|
||||
p96Zc3vrk+0Z0tkYy3E0fpuzPtlTUhBzO3fMF41FpB5ix3W/tH9YJvrozlIuDD1I
|
||||
IEusxomeeiMRbyYpX/gkSOO74ylCzMEQVzleMNdpzpeXOg0Kp5z2JNShdEoT7eMR
|
||||
qkJQJjMdL6QeXUqWNvX1Zqb8v6VeWGWjuu/cl374P8D8bjn89VwZQ5HFqoLOhI5v
|
||||
XEYsMViZWwLSMcfWTU2Rdi0RxUZQVciLP/3GQROR1/0/e1J1kd7GsRWQMZcU20Vy
|
||||
jXBVAiWhW1bgd0XOrrFILsAmnBtinEJiE+h5UC4ksZtwWf9x1IhXGlpb9bmD4+Ud
|
||||
93wmqytPXBFL6wwlj4IYjjy0gU6xP6h7nwhHXnBlwFWGDpe8Cco9qgyJxJxBTtj9
|
||||
MbBv+BSLXJoniDASdk6RIqCjPWZtWbQ7j5mIKV0bdJQZpBX553QOy8AoIpJE32An
|
||||
FzR0SSCHOCgSAbqtM8CvLO6mquEJunmwKQx6xfos5N6ee+D+JtUFTw04TrjZUzFs
|
||||
Z7v3SN/N4Hd13iTBDSu4XY/tJYICvTRLYNrzQRh/XEVbEEVxXhL8rxNn5aL1pqrV
|
||||
yEnvHXrnSXWxTif1K+hS2HfTkQ6d1GjglvmwkoBqBHuRH0OJ1VguTqM=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@ void on_message(ws_echo_server* s, websocketpp::connection_hdl hdl, ws_echo_serv
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (websocketpp::lib::error_code const & e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
} catch (websocketpp::exception const & e) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Echo Failed: "+e.message());
|
||||
std::string("Echo Failed: ")+e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (print_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
@@ -0,0 +1,23 @@
|
||||
## Print client example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('print_client', ["print_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('print_client', ["print_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
|
||||
std::cout << msg->get_payload() << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
client c;
|
||||
|
||||
std::string uri = "ws://localhost:9002";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
// Set logging to be pretty verbose (everything except message payloads)
|
||||
c.set_access_channels(websocketpp::log::alevel::all);
|
||||
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
c.set_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
c.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
c.set_message_handler(&on_message);
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = c.get_connection(uri, ec);
|
||||
if (ec) {
|
||||
std::cout << "could not create connection because: " << ec.message() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note that connect here only requests a connection. No network messages are
|
||||
// exchanged until the event loop starts running in the next line.
|
||||
c.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// this will cause a single connection to be made to the server. c.run()
|
||||
// will exit when this connection is closed.
|
||||
c.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (print_client_tls)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,24 @@
|
||||
## Print client tls example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('print_client_tls', ["print_client_tls.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('print_client_tls', ["print_client_tls.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,66 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFxTCCA62gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx
|
||||
CzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdvMRQwEgYDVQQKDAtXZWJTb2Nr
|
||||
ZXQrKzEcMBoGA1UEAwwTV2ViU29ja2V0KysgUm9vdCBDQTAeFw0xNjA1MjUxMzU4
|
||||
MjdaFw0yNjA1MjMxMzU4MjdaMIGCMQswCQYDVQQGEwJVUzELMAkGA1UECAwCSUwx
|
||||
FDASBgNVBAoMC1dlYlNvY2tldCsrMSowKAYDVQQLDCFXZWJTb2NrZXQrKyBDZXJ0
|
||||
aWZpY2F0ZSBBdXRob3JpdHkxJDAiBgNVBAMMG1dlYlNvY2tldCsrIEludGVybWVk
|
||||
aWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMNaFAzlx0KJ
|
||||
gG15yRHI3xn9+B1woHG4uuOr124Sk1JllPcO3enusgIYTMl0FiYYW9CsyPoe4L0P
|
||||
wflbz20vDDjxmXG+NPgjuYmnPaq7q2JXYz+cShv9+o60EIwEIe+EWk1ZQs9YSdQ0
|
||||
r4UOxGVq6eEuWJi8Wh02cbnxdjwvrk7lTMFVY+z5EX8cCj6Tbrd0lyIf/0X8OkOb
|
||||
q2HOqqzTgT2apBCWCEW6grW6rtMOoDx93BOZDBEGz39sJ5i8AQ8XIdYCdUcOMdJU
|
||||
SCAw/MMyFTHXhv8hJdG5GcDSfc7woB9xRUf8UHuCH0nYkTb260TWvyDCYJy001ko
|
||||
SWoRbh2hVgPqQ9FTDMzMTY8T8C5u3BRfGN5PHuSPhwfHv/p1g4uPnltDBe4CNtOs
|
||||
wu8w1wbrr3uI7qETnqOzbXlcT7o4rCrrRQqLbNOssf2mMH+Phq6dINjXpZjiAhO0
|
||||
SURtBMmQdAZcQkGStzFitEkb2Py5LEIxQ068i8RCowTyD9+/jbO1fZyxJ4X8TDUe
|
||||
Xx48xWnu0i4f8/9ldnWLwX9h3ilaZVsr7buNYJoMlz+v73TQoWKSybJ2SMe/Cddj
|
||||
OZCy5r1UakuZhX6n1ScD/hbO8FEfmQRpAywYajyU4dZ9XMbf5bo6OAUqlJ2f4yYh
|
||||
VAy5mi1JHfD5PiJN90j79GXXvtBTJc4hAgMBAAGjZjBkMB0GA1UdDgQWBBTKMn5O
|
||||
3NUPpztL1bAz8UCsOBLpkjAfBgNVHSMEGDAWgBTNBBKZQN694xplMGyMruXFv27o
|
||||
eTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0B
|
||||
AQsFAAOCAgEAyNkZUEAdP73th4/RLu0d2foMiIqKlcvw3JsW0tto3MT5lvQ5UugH
|
||||
OwluhWhnMLE0KsknQd7/p4ZwyZugWAYjGcDydp0GDIDfNBBEOQkOAL23KkYiRFqt
|
||||
VPBTZi9S7P2MJLY0j94liIg94nikhz/0q7JxxWFlvSHUjwZxXrbFjfZRPOS1vIq/
|
||||
/VK2QjUsdIXE3NOPYfQwd9FpG2YS8ZcMeipwNYVAs2FBEeWzGH1j6i2hP8FFBDYP
|
||||
0LTvJYOJvlCeyIvPBjKk9461/Z4CPJcKtKC59onQmiqSK/Juak/bpPoY7jJ228KG
|
||||
bEBzClIEHgbDiBewFTHbyOWhW2ySRLOGsPeqKDSbm4J1N5rfKnrSQB9PfOmWoRfJ
|
||||
vqPlXFSlpdgD4j/WnEumpvt78fT+cn+AkRG8tE5DQrCWZTK47TSWn902Fm0A19Rl
|
||||
pSbE9qsulXurOqEuOOayrzcUmbZ/jkU+wj+/tN4Gl8K98WbjcXvwz0sRL3SgRRrI
|
||||
awUdaGWKQHrTJNEOTisepUAuHVDmvuQz0j/Ru+PbB9K3GcKY6X6+o1c2JBC1V6KX
|
||||
aHHZQ+xPm+VEa1pG/QVHGpt2AbGUQlXwDYtOIRwEhO27tFbH8Q68s2cMLYjsF5gd
|
||||
MWuMYCPkFv10/V2f2lAIPSEzw2pldIGERcb4VG4xuD0qU+HH/aAID7k=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFpjCCA46gAwIBAgIJAL42eqbfw976MA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJJTDEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIGA1UECgwL
|
||||
V2ViU29ja2V0KysxHDAaBgNVBAMME1dlYlNvY2tldCsrIFJvb3QgQ0EwHhcNMTYw
|
||||
NTI1MTM1MTUzWhcNMzYwNTIwMTM1MTUzWjBgMQswCQYDVQQGEwJVUzELMAkGA1UE
|
||||
CAwCSUwxEDAOBgNVBAcMB0NoaWNhZ28xFDASBgNVBAoMC1dlYlNvY2tldCsrMRww
|
||||
GgYDVQQDDBNXZWJTb2NrZXQrKyBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOC
|
||||
Ag8AMIICCgKCAgEA4QjJ0v5yri+pAN67I/XPz88D8oIczCW96CIuwc44aDC9Kptb
|
||||
9iY8xwbGCyQsFZ/1IQ74QfnXZSwq8EwedcBIdcyHdBu6qtNkCVKeDIZAMBef6Hx+
|
||||
tWSe1op3sDbUlT8NHiTxZCZWk/2/yIi8yPzQTi4y1vF04vvrQS5RFomCz17kdyOa
|
||||
NdxO5p+I4afdoVKtzA1aHoBqdTe7vzM3eww4AxKfgIEDdIuOGDiglI/b/frlwiOi
|
||||
SfTOsPzu52TOPW2d1Ad5BG4GuMpnTUOVnc8j18w9LdeXO0J10oVyCmwiPuzFCcDB
|
||||
g1xvVr5TXzIZ5J+qlso7+mUfZGH+nxOT7Tc78o1EvX6JbfQAI2PrpcksmJfFnN4l
|
||||
4XnXDW/eKl8AlLUr/cW5axAfql4QHJoBCZcfYldQpMoL5R1ikLtY53cOJpycFoWm
|
||||
1IEfkLBZ4C1old+KoaErG0+Aur8/kwAJGMnmMvZqGZ5pgXtVipOLy5TKuS6ZKO8g
|
||||
MRzalaF/naiu3pF+/sctaqkAPvOr65WrANNGxTQ93ePdyuT6sOEUKXxaXcTtAOOM
|
||||
5FCgX8dPxkOACxTrxppvb+bYmYL9GIuYDGYxSRu3Fm+04eXIh+uCqcuWPQuRPc5t
|
||||
VXvk/M0fPaJvKfP6lRAoE5Dp4qPRvL6tRVtOXfP6d+O+yGnxRoLKAW7ejoMCAwEA
|
||||
AaNjMGEwHQYDVR0OBBYEFM0EEplA3r3jGmUwbIyu5cW/buh5MB8GA1UdIwQYMBaA
|
||||
FM0EEplA3r3jGmUwbIyu5cW/buh5MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
|
||||
BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAQ4eY4LhW795wl9XuDVg2vOFTYmIS0
|
||||
OxrunFX4f3RjddbIbXzYmQ0cJ8pJ5l7eGYcg/DYQRY4Tk6LjXMs9VhIU10akqLS4
|
||||
qGE+Bmp3Jhu5NxZbKkY+k+kTAA1LYxFCjGjSV0v5QNLFULDAmGer2zWwU5DcDwwq
|
||||
8yWyBuI974UyE/49/TeckfqwBrb90LL2lFEwoL86XZK2IZMPyMBC/S1X5P/Kc15Q
|
||||
d8lwOPS5AirFkkrzs/px+mRia5U1uWKIPRLq9Medvjf8HR8SFWq9eRtkxiLaWyRv
|
||||
HBVyVRKCubCZR8psVLK/zrF+Bc+Hr9aAi3TuqTKjIOI7hrq5oJcJpebZDNoBIqoj
|
||||
kab13WcRwG+BQvuK1CEkd1aq8Nh2GX6Reb2Zv82/WntgP1a0sztbIGgrUBYQryb5
|
||||
HF79v4e2byY613SiQ3lz+g/AWxaZsYH80/Zl+hEwEtU4fFz34Jcv9Kvda1JpknBT
|
||||
Fi63ugfoNeNriO02AReMmDvuBG3X8RF1UQyBoTU3uZuW7X26MizEjiVCK9qaOLED
|
||||
WDSEoyKLe4JKd387CVlsCY8K/6fBlFTI/hJhggDz8pZFj3n2irUI44kjgOmoxOrW
|
||||
JY2jgY89AEMN9yOKkyQGara8pF9IJxTQ7jurYnWcUbompWeybJRwvWN0h+tGV+bd
|
||||
l/aq/5LwL3fVpg==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
|
||||
typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
|
||||
std::cout << msg->get_payload() << std::endl;
|
||||
}
|
||||
|
||||
/// Verify that one of the subject alternative names matches the given hostname
|
||||
bool verify_subject_alternative_name(const char * hostname, X509 * cert) {
|
||||
STACK_OF(GENERAL_NAME) * san_names = NULL;
|
||||
|
||||
san_names = (STACK_OF(GENERAL_NAME) *) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
|
||||
if (san_names == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int san_names_count = sk_GENERAL_NAME_num(san_names);
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (int i = 0; i < san_names_count; i++) {
|
||||
const GENERAL_NAME * current_name = sk_GENERAL_NAME_value(san_names, i);
|
||||
|
||||
if (current_name->type != GEN_DNS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char * dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
|
||||
|
||||
// Make sure there isn't an embedded NUL character in the DNS name
|
||||
if (ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
|
||||
break;
|
||||
}
|
||||
// Compare expected hostname with the CN
|
||||
result = (strcasecmp(hostname, dns_name) == 0);
|
||||
}
|
||||
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Verify that the certificate common name matches the given hostname
|
||||
bool verify_common_name(const char * hostname, X509 * cert) {
|
||||
// Find the position of the CN field in the Subject field of the certificate
|
||||
int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(cert), NID_commonName, -1);
|
||||
if (common_name_loc < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract the CN field
|
||||
X509_NAME_ENTRY * common_name_entry = X509_NAME_get_entry(X509_get_subject_name(cert), common_name_loc);
|
||||
if (common_name_entry == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert the CN field to a C string
|
||||
ASN1_STRING * common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
|
||||
if (common_name_asn1 == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char * common_name_str = (char *) ASN1_STRING_data(common_name_asn1);
|
||||
|
||||
// Make sure there isn't an embedded NUL character in the CN
|
||||
if (ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare expected hostname with the CN
|
||||
return (strcasecmp(hostname, common_name_str) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This code is derived from examples and documentation found ato00po
|
||||
* http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp03/ssl/client.cpp
|
||||
* and
|
||||
* https://github.com/iSECPartners/ssl-conservatory
|
||||
*/
|
||||
bool verify_certificate(const char * hostname, bool preverified, boost::asio::ssl::verify_context& ctx) {
|
||||
// The verify callback can be used to check whether the certificate that is
|
||||
// being presented is valid for the peer. For example, RFC 2818 describes
|
||||
// the steps involved in doing this for HTTPS. Consult the OpenSSL
|
||||
// documentation for more details. Note that the callback is called once
|
||||
// for each certificate in the certificate chain, starting from the root
|
||||
// certificate authority.
|
||||
|
||||
// Retrieve the depth of the current cert in the chain. 0 indicates the
|
||||
// actual server cert, upon which we will perform extra validation
|
||||
// (specifically, ensuring that the hostname matches. For other certs we
|
||||
// will use the 'preverified' flag from Asio, which incorporates a number of
|
||||
// non-implementation specific OpenSSL checking, such as the formatting of
|
||||
// certs and the trusted status based on the CA certs we imported earlier.
|
||||
int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());
|
||||
|
||||
// if we are on the final cert and everything else checks out, ensure that
|
||||
// the hostname is present on the list of SANs or the common name (CN).
|
||||
if (depth == 0 && preverified) {
|
||||
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
|
||||
|
||||
if (verify_subject_alternative_name(hostname, cert)) {
|
||||
return true;
|
||||
} else if (verify_common_name(hostname, cert)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return preverified;
|
||||
}
|
||||
|
||||
/// TLS Initialization handler
|
||||
/**
|
||||
* WebSocket++ core and the Asio Transport do not handle TLS context creation
|
||||
* and setup. This callback is provided so that the end user can set up their
|
||||
* TLS context using whatever settings make sense for their application.
|
||||
*
|
||||
* As Asio and OpenSSL do not provide great documentation for the very common
|
||||
* case of connect and actually perform basic verification of server certs this
|
||||
* example includes a basic implementation (using Asio and OpenSSL) of the
|
||||
* following reasonable default settings and verification steps:
|
||||
*
|
||||
* - Disable SSLv2 and SSLv3
|
||||
* - Load trusted CA certificates and verify the server cert is trusted.
|
||||
* - Verify that the hostname matches either the common name or one of the
|
||||
* subject alternative names on the certificate.
|
||||
*
|
||||
* This is not meant to be an exhaustive reference implimentation of a perfect
|
||||
* TLS client, but rather a reasonable starting point for building a secure
|
||||
* TLS encrypted WebSocket client.
|
||||
*
|
||||
* If any TLS, Asio, or OpenSSL experts feel that these settings are poor
|
||||
* defaults or there are critically missing steps please open a GitHub issue
|
||||
* or drop a line on the project mailing list.
|
||||
*
|
||||
* Note the bundled CA cert ca-chain.cert.pem is the CA cert that signed the
|
||||
* cert bundled with echo_server_tls. You can use print_client_tls with this
|
||||
* CA cert to connect to echo_server_tls as long as you use /etc/hosts or
|
||||
* something equivilent to spoof one of the names on that cert
|
||||
* (websocketpp.org, for example).
|
||||
*/
|
||||
context_ptr on_tls_init(const char * hostname, websocketpp::connection_hdl) {
|
||||
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
|
||||
|
||||
ctx->set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
ctx->set_verify_callback(bind(&verify_certificate, hostname, ::_1, ::_2));
|
||||
|
||||
// Here we load the CA certificates of all CA's that this client trusts.
|
||||
ctx->load_verify_file("ca-chain.cert.pem");
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
client c;
|
||||
|
||||
std::string hostname = "localhost";
|
||||
std::string port = "9002";
|
||||
|
||||
|
||||
if (argc == 3) {
|
||||
hostname = argv[1];
|
||||
port = argv[2];
|
||||
} else {
|
||||
std::cout << "Usage: print_server_tls <hostname> <port>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string uri = "wss://" + hostname + ":" + port;
|
||||
|
||||
try {
|
||||
// Set logging to be pretty verbose (everything except message payloads)
|
||||
c.set_access_channels(websocketpp::log::alevel::all);
|
||||
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
c.set_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
c.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
c.set_message_handler(&on_message);
|
||||
c.set_tls_init_handler(bind(&on_tls_init, hostname.c_str(), ::_1));
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = c.get_connection(uri, ec);
|
||||
if (ec) {
|
||||
std::cout << "could not create connection because: " << ec.message() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note that connect here only requests a connection. No network messages are
|
||||
// exchanged until the event loop starts running in the next line.
|
||||
c.connect(con);
|
||||
|
||||
c.get_alog().write(websocketpp::log::alevel::app, "Connecting to " + uri);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// this will cause a single connection to be made to the server. c.run()
|
||||
// will exit when this connection is closed.
|
||||
c.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -60,9 +60,9 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
*/
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "Echo failed because: "
|
||||
<< "(" << e.what() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +96,10 @@ int main(int argc, char * argv[]) {
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,17 @@
|
||||
// is configured.
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
|
||||
/**
|
||||
* Define a semi-cross platform helper method that waits/sleeps for a bit.
|
||||
*/
|
||||
void wait_a_bit() {
|
||||
#ifdef WIN32
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* The telemetry client connects to a WebSocket server and sends a message every
|
||||
* second containing an integer count. This example can be used as the basis for
|
||||
@@ -111,7 +122,7 @@ public:
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
sleep(1);
|
||||
wait_a_bit();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -132,7 +143,7 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
wait_a_bit();
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
WebSocket++ (0.7.0)
|
||||
WebSocket++ (0.8.0-dev)
|
||||
==========================
|
||||
|
||||
WebSocket++ is a header only C++ library that implements RFC6455 The WebSocket
|
||||
@@ -28,7 +28,7 @@ Get Involved
|
||||
http://www.zaphoyd.com/websocketpp/
|
||||
|
||||
**User Manual**
|
||||
http://www.zaphoyd.com/websocketpp/manual/
|
||||
http://docs.websocketpp.org/
|
||||
|
||||
**GitHub Repository**
|
||||
https://github.com/zaphoyd/websocketpp/
|
||||
|
||||
@@ -132,11 +132,14 @@ struct debug_config_client : public websocketpp::config::core {
|
||||
};
|
||||
|
||||
struct connection_setup {
|
||||
connection_setup(bool p_is_server) : c(p_is_server, "", alog, elog, rng) {}
|
||||
connection_setup(bool p_is_server)
|
||||
: alog(websocketpp::lib::make_shared<stub_config::alog_type>())
|
||||
, elog(websocketpp::lib::make_shared<stub_config::elog_type>())
|
||||
, c(p_is_server, "", alog, elog, rng) {}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
stub_config::alog_type alog;
|
||||
stub_config::elog_type elog;
|
||||
websocketpp::lib::shared_ptr<stub_config::alog_type> alog;
|
||||
websocketpp::lib::shared_ptr<stub_config::elog_type> elog;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::connection<stub_config> c;
|
||||
};
|
||||
|
||||
@@ -506,6 +506,18 @@ BOOST_AUTO_TEST_CASE( basic_request_with_body ) {
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "5" );
|
||||
BOOST_CHECK_EQUAL( r.get_body(), "abcde" );
|
||||
|
||||
BOOST_CHECK_EQUAL( r.get_headers().size(), 2);
|
||||
|
||||
websocketpp::http::parser::header_list::const_iterator it = r.get_headers().begin();
|
||||
|
||||
BOOST_CHECK_EQUAL( it->first, "Content-Length");
|
||||
BOOST_CHECK_EQUAL( it->second, "5");
|
||||
|
||||
it++;
|
||||
|
||||
BOOST_CHECK_EQUAL( it->first, "Host");
|
||||
BOOST_CHECK_EQUAL( it->second, "www.example.com");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_request_with_body_split ) {
|
||||
|
||||
@@ -115,7 +115,9 @@ context_ptr on_tls_init(websocketpp::connection_hdl) {
|
||||
struct mock_con: public websocketpp::transport::asio::connection<config> {
|
||||
typedef websocketpp::transport::asio::connection<config> base;
|
||||
|
||||
mock_con(bool a, config::alog_type& b, config::elog_type& c) : base(a,b,c) {}
|
||||
mock_con(bool a, const websocketpp::lib::shared_ptr<config::alog_type>& b,
|
||||
const websocketpp::lib::shared_ptr<config::elog_type>& c)
|
||||
: base(a,b,c) {}
|
||||
|
||||
void start() {
|
||||
base::init(websocketpp::lib::bind(&mock_con::handle_start,this,
|
||||
@@ -139,8 +141,8 @@ struct mock_endpoint : public websocketpp::transport::asio::endpoint<config> {
|
||||
typedef websocketpp::transport::asio::endpoint<config> base;
|
||||
|
||||
mock_endpoint() {
|
||||
alog.set_channels(websocketpp::log::alevel::all);
|
||||
base::init_logging(&alog,&elog);
|
||||
alog->set_channels(websocketpp::log::alevel::all);
|
||||
base::init_logging(alog,elog);
|
||||
init_asio();
|
||||
}
|
||||
|
||||
@@ -170,8 +172,8 @@ struct mock_endpoint : public websocketpp::transport::asio::endpoint<config> {
|
||||
}
|
||||
|
||||
connection_ptr m_con;
|
||||
config::alog_type alog;
|
||||
config::elog_type elog;
|
||||
websocketpp::lib::shared_ptr<config::alog_type> alog;
|
||||
websocketpp::lib::shared_ptr<config::elog_type> elog;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( tls_handshake_timeout ) {
|
||||
|
||||
@@ -58,7 +58,7 @@ struct stub_con : public iostream_con {
|
||||
typedef websocketpp::lib::shared_ptr<type> ptr;
|
||||
typedef iostream_con::timer_ptr timer_ptr;
|
||||
|
||||
stub_con(bool is_server, config::alog_type & a, config::elog_type & e)
|
||||
stub_con(bool is_server, const websocketpp::lib::shared_ptr<config::alog_type>& a, const websocketpp::lib::shared_ptr<config::elog_type>& e)
|
||||
: iostream_con(is_server,a,e)
|
||||
// Set the error to a known code that is unused by the library
|
||||
// This way we can easily confirm that the handler was run at all.
|
||||
@@ -164,8 +164,8 @@ struct stub_con : public iostream_con {
|
||||
};
|
||||
|
||||
// Stubs
|
||||
config::alog_type alogger;
|
||||
config::elog_type elogger;
|
||||
websocketpp::lib::shared_ptr<config::alog_type> alogger = websocketpp::lib::make_shared<config::alog_type>();
|
||||
websocketpp::lib::shared_ptr<config::elog_type> elogger = websocketpp::lib::make_shared<config::elog_type>();
|
||||
|
||||
BOOST_AUTO_TEST_CASE( const_methods ) {
|
||||
iostream_con::ptr con(new iostream_con(true,alogger,elogger));
|
||||
@@ -580,6 +580,16 @@ BOOST_AUTO_TEST_CASE( shutdown_handler ) {
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::error::general) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( clear_handler ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
con->set_shutdown_handler(&sd_handler);
|
||||
con->set_shutdown_handler(NULL);
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
con->shutdown();
|
||||
BOOST_CHECK_EQUAL( con->ec, websocketpp::lib::error_code() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( shared_pointer_memory_cleanup ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
|
||||
@@ -3,5 +3,12 @@
|
||||
# WEBSOCKETPP_FOUND - indicates that the module was found
|
||||
# WEBSOCKETPP_INCLUDE_DIR - include directories
|
||||
|
||||
@PACKAGE_INIT@
|
||||
set_and_check(WEBSOCKETPP_INCLUDE_DIR "@PACKAGE_INSTALL_INCLUDE_DIR@")
|
||||
set(WEBSOCKETPP_FOUND TRUE)
|
||||
set(WEBSOCKETPP_INCLUDE_DIR "@INSTALL_INCLUDE_DIR@")
|
||||
|
||||
#This is a bit of a hack, but it works well. It also allows continued support of CMake 2.8
|
||||
if(${CMAKE_VERSION} VERSION_GREATER 3.0.0 OR ${CMAKE_VERSION} VERSION_EQUAL 3.0.0)
|
||||
add_library(websocketpp::websocketpp INTERFACE IMPORTED)
|
||||
set_target_properties(websocketpp::websocketpp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${WEBSOCKETPP_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
set(PACKAGE_VERSION "@WEBSOCKETPP_VERSION@")
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -101,9 +101,19 @@ namespace lib {
|
||||
bool is_neg(T duration) {
|
||||
return duration.count() < 0;
|
||||
}
|
||||
inline lib::chrono::milliseconds milliseconds(long duration) {
|
||||
return lib::chrono::milliseconds(duration);
|
||||
}
|
||||
|
||||
// If boost believes it has std::chrono available it will use it
|
||||
// so we should also use it for things that relate to boost, even
|
||||
// if the library would otherwise use boost::chrono.
|
||||
#if defined(BOOST_ASIO_HAS_STD_CHRONO)
|
||||
inline std::chrono::milliseconds milliseconds(long duration) {
|
||||
return std::chrono::milliseconds(duration);
|
||||
}
|
||||
#else
|
||||
inline lib::chrono::milliseconds milliseconds(long duration) {
|
||||
return lib::chrono::milliseconds(duration);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// Using boost::asio <1.49 we pretend a deadline timer is a steady
|
||||
// timer and wrap the negative detection and duration conversion
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
|
||||
// Loggers
|
||||
#include <websocketpp/logger/basic.hpp>
|
||||
#include <websocketpp/logger/levels.hpp>
|
||||
|
||||
// RNG
|
||||
#include <websocketpp/random/none.hpp>
|
||||
@@ -188,7 +189,18 @@ struct core {
|
||||
static const websocketpp::log::level alog_level =
|
||||
websocketpp::log::alevel::all ^ websocketpp::log::alevel::devel;
|
||||
|
||||
///
|
||||
/// Size of the per-connection read buffer
|
||||
/**
|
||||
* Each connection has an internal buffer of this size. A larger value will
|
||||
* result in fewer trips through the library and less CPU overhead at the
|
||||
* expense of increased memory usage per connection.
|
||||
*
|
||||
* If your application primarily deals in very large messages you may want
|
||||
* to try setting this value higher.
|
||||
*
|
||||
* If your application has a lot of connections or primarily deals in small
|
||||
* messages you may want to try setting this smaller.
|
||||
*/
|
||||
static const size_t connection_read_buffer_size = 16384;
|
||||
|
||||
/// Drop connections immediately on protocol error.
|
||||
|
||||
@@ -294,8 +294,8 @@ private:
|
||||
};
|
||||
public:
|
||||
|
||||
explicit connection(bool p_is_server, std::string const & ua, alog_type& alog,
|
||||
elog_type& elog, rng_type & rng)
|
||||
explicit 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)
|
||||
: transport_con_type(p_is_server, alog, elog)
|
||||
, m_handle_read_frame(lib::bind(
|
||||
&type::handle_read_frame,
|
||||
@@ -329,7 +329,7 @@ public:
|
||||
, m_http_state(session::http_state::init)
|
||||
, m_was_clean(false)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"connection constructor");
|
||||
m_alog->write(log::alevel::devel,"connection constructor");
|
||||
}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -1486,7 +1486,7 @@ private:
|
||||
void log_err(log::level l, char const * msg, error_type const & ec) {
|
||||
std::stringstream s;
|
||||
s << msg << " error: " << ec << " (" << ec.message() << ")";
|
||||
m_elog.write(l, s.str());
|
||||
m_elog->write(l, s.str());
|
||||
}
|
||||
|
||||
// internal handler functions
|
||||
@@ -1603,8 +1603,8 @@ private:
|
||||
std::vector<std::string> m_requested_subprotocols;
|
||||
|
||||
bool const m_is_server;
|
||||
alog_type& m_alog;
|
||||
elog_type& m_elog;
|
||||
const lib::shared_ptr<alog_type> m_alog;
|
||||
const lib::shared_ptr<elog_type> m_elog;
|
||||
|
||||
rng_type & m_rng;
|
||||
|
||||
|
||||
+24
-24
@@ -89,8 +89,8 @@ public:
|
||||
//friend connection;
|
||||
|
||||
explicit endpoint(bool p_is_server)
|
||||
: m_alog(config::alog_level, log::channel_type_hint::access)
|
||||
, m_elog(config::elog_level, log::channel_type_hint::error)
|
||||
: m_alog(new alog_type(config::alog_level, log::channel_type_hint::access))
|
||||
, m_elog(new elog_type(config::elog_level, log::channel_type_hint::error))
|
||||
, m_user_agent(::websocketpp::user_agent)
|
||||
, m_open_handshake_timeout_dur(config::timeout_open_handshake)
|
||||
, m_close_handshake_timeout_dur(config::timeout_close_handshake)
|
||||
@@ -99,12 +99,12 @@ public:
|
||||
, m_max_http_body_size(config::max_http_body_size)
|
||||
, m_is_server(p_is_server)
|
||||
{
|
||||
m_alog.set_channels(config::alog_level);
|
||||
m_elog.set_channels(config::elog_level);
|
||||
m_alog->set_channels(config::alog_level);
|
||||
m_elog->set_channels(config::elog_level);
|
||||
|
||||
m_alog.write(log::alevel::devel, "endpoint constructor");
|
||||
m_alog->write(log::alevel::devel, "endpoint constructor");
|
||||
|
||||
transport_type::init_logging(&m_alog, &m_elog);
|
||||
transport_type::init_logging(m_alog, m_elog);
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
* @param channels The channel value(s) to set
|
||||
*/
|
||||
void set_access_channels(log::level channels) {
|
||||
m_alog.set_channels(channels);
|
||||
m_alog->set_channels(channels);
|
||||
}
|
||||
|
||||
/// Clear Access logging channels
|
||||
@@ -229,7 +229,7 @@ public:
|
||||
* @param channels The channel value(s) to clear
|
||||
*/
|
||||
void clear_access_channels(log::level channels) {
|
||||
m_alog.clear_channels(channels);
|
||||
m_alog->clear_channels(channels);
|
||||
}
|
||||
|
||||
/// Set Error logging channel
|
||||
@@ -240,7 +240,7 @@ public:
|
||||
* @param channels The channel value(s) to set
|
||||
*/
|
||||
void set_error_channels(log::level channels) {
|
||||
m_elog.set_channels(channels);
|
||||
m_elog->set_channels(channels);
|
||||
}
|
||||
|
||||
/// Clear Error logging channels
|
||||
@@ -251,7 +251,7 @@ public:
|
||||
* @param channels The channel value(s) to clear
|
||||
*/
|
||||
void clear_error_channels(log::level channels) {
|
||||
m_elog.clear_channels(channels);
|
||||
m_elog->clear_channels(channels);
|
||||
}
|
||||
|
||||
/// Get reference to access logger
|
||||
@@ -259,7 +259,7 @@ public:
|
||||
* @return A reference to the access logger
|
||||
*/
|
||||
alog_type & get_alog() {
|
||||
return m_alog;
|
||||
return *m_alog;
|
||||
}
|
||||
|
||||
/// Get reference to error logger
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
* @return A reference to the error logger
|
||||
*/
|
||||
elog_type & get_elog() {
|
||||
return m_elog;
|
||||
return *m_elog;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
@@ -275,52 +275,52 @@ public:
|
||||
/*************************/
|
||||
|
||||
void set_open_handler(open_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_open_handler");
|
||||
m_alog->write(log::alevel::devel,"set_open_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_open_handler = h;
|
||||
}
|
||||
void set_close_handler(close_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_close_handler");
|
||||
m_alog->write(log::alevel::devel,"set_close_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_close_handler = h;
|
||||
}
|
||||
void set_fail_handler(fail_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_fail_handler");
|
||||
m_alog->write(log::alevel::devel,"set_fail_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_fail_handler = h;
|
||||
}
|
||||
void set_ping_handler(ping_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_ping_handler");
|
||||
m_alog->write(log::alevel::devel,"set_ping_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_ping_handler = h;
|
||||
}
|
||||
void set_pong_handler(pong_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_pong_handler");
|
||||
m_alog->write(log::alevel::devel,"set_pong_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_pong_handler = h;
|
||||
}
|
||||
void set_pong_timeout_handler(pong_timeout_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_pong_timeout_handler");
|
||||
m_alog->write(log::alevel::devel,"set_pong_timeout_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_pong_timeout_handler = h;
|
||||
}
|
||||
void set_interrupt_handler(interrupt_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_interrupt_handler");
|
||||
m_alog->write(log::alevel::devel,"set_interrupt_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_interrupt_handler = h;
|
||||
}
|
||||
void set_http_handler(http_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_http_handler");
|
||||
m_alog->write(log::alevel::devel,"set_http_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_http_handler = h;
|
||||
}
|
||||
void set_validate_handler(validate_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_validate_handler");
|
||||
m_alog->write(log::alevel::devel,"set_validate_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_validate_handler = h;
|
||||
}
|
||||
void set_message_handler(message_handler h) {
|
||||
m_alog.write(log::alevel::devel,"set_message_handler");
|
||||
m_alog->write(log::alevel::devel,"set_message_handler");
|
||||
scoped_lock_type guard(m_mutex);
|
||||
m_message_handler = h;
|
||||
}
|
||||
@@ -661,8 +661,8 @@ public:
|
||||
protected:
|
||||
connection_ptr create_connection();
|
||||
|
||||
alog_type m_alog;
|
||||
elog_type m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
private:
|
||||
// dynamic settings
|
||||
std::string m_user_agent;
|
||||
|
||||
@@ -176,6 +176,10 @@ inline void parser::process_header(std::string::iterator begin,
|
||||
strip_lws(std::string(cursor+sizeof(header_separator)-1,end)));
|
||||
}
|
||||
|
||||
inline header_list const & parser::get_headers() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
inline std::string parser::raw_headers() const {
|
||||
std::stringstream raw;
|
||||
|
||||
|
||||
@@ -441,6 +441,16 @@ public:
|
||||
bool get_header_as_plist(std::string const & key, parameter_list & out)
|
||||
const;
|
||||
|
||||
/// Return a list of all HTTP headers
|
||||
/**
|
||||
* Return a list of all HTTP headers
|
||||
*
|
||||
* @since 0.8.0
|
||||
*
|
||||
* @return A list of all HTTP headers
|
||||
*/
|
||||
header_list const & get_headers() const;
|
||||
|
||||
/// Append a value to an existing HTTP header
|
||||
/**
|
||||
* This method will set the value of the HTTP header `key` with the
|
||||
|
||||
@@ -53,7 +53,7 @@ template <typename config>
|
||||
void connection<config>::set_termination_handler(
|
||||
termination_handler new_handler)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"connection set_termination_handler");
|
||||
|
||||
//scoped_lock_type lock(m_connection_state_lock);
|
||||
@@ -103,8 +103,8 @@ lib::error_code connection<config>::send(void const * payload, size_t len,
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::send(typename config::message_type::ptr msg)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection send");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection send");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -153,8 +153,8 @@ lib::error_code connection<config>::send(typename config::message_type::ptr msg)
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::ping(std::string const& payload, lib::error_code& ec) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection ping");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection ping");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -162,7 +162,7 @@ void connection<config>::ping(std::string const& payload, lib::error_code& ec) {
|
||||
if (m_state != session::state::open) {
|
||||
std::stringstream ss;
|
||||
ss << "connection::ping called from invalid state " << m_state;
|
||||
m_alog.write(log::alevel::devel,ss.str());
|
||||
m_alog->write(log::alevel::devel,ss.str());
|
||||
ec = error::make_error_code(error::invalid_state);
|
||||
return;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ void connection<config>::ping(std::string const& payload, lib::error_code& ec) {
|
||||
|
||||
if (!m_ping_timer) {
|
||||
// Our transport doesn't support timers
|
||||
m_elog.write(log::elevel::warn,"Warning: a pong_timeout_handler is \
|
||||
m_elog->write(log::elevel::warn,"Warning: a pong_timeout_handler is \
|
||||
set but the transport in use does not support timeouts.");
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ void connection<config>::handle_pong_timeout(std::string payload,
|
||||
return;
|
||||
}
|
||||
|
||||
m_elog.write(log::elevel::devel,"pong_timeout error: "+ec.message());
|
||||
m_elog->write(log::elevel::devel,"pong_timeout error: "+ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -250,8 +250,8 @@ void connection<config>::handle_pong_timeout(std::string payload,
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::pong(std::string const& payload, lib::error_code& ec) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection pong");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection pong");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -259,7 +259,7 @@ void connection<config>::pong(std::string const& payload, lib::error_code& ec) {
|
||||
if (m_state != session::state::open) {
|
||||
std::stringstream ss;
|
||||
ss << "connection::pong called from invalid state " << m_state;
|
||||
m_alog.write(log::alevel::devel,ss.str());
|
||||
m_alog->write(log::alevel::devel,ss.str());
|
||||
ec = error::make_error_code(error::invalid_state);
|
||||
return;
|
||||
}
|
||||
@@ -304,8 +304,8 @@ template <typename config>
|
||||
void connection<config>::close(close::status::value const code,
|
||||
std::string const & reason, lib::error_code & ec)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection close");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection close");
|
||||
}
|
||||
|
||||
// Truncate reason to maximum size allowable in a close frame.
|
||||
@@ -339,7 +339,7 @@ void connection<config>::close(close::status::value const code,
|
||||
*/
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::interrupt() {
|
||||
m_alog.write(log::alevel::devel,"connection connection::interrupt");
|
||||
m_alog->write(log::alevel::devel,"connection connection::interrupt");
|
||||
return transport_con_type::interrupt(
|
||||
lib::bind(
|
||||
&type::handle_interrupt,
|
||||
@@ -358,7 +358,7 @@ void connection<config>::handle_interrupt() {
|
||||
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::pause_reading() {
|
||||
m_alog.write(log::alevel::devel,"connection connection::pause_reading");
|
||||
m_alog->write(log::alevel::devel,"connection connection::pause_reading");
|
||||
return transport_con_type::dispatch(
|
||||
lib::bind(
|
||||
&type::handle_pause_reading,
|
||||
@@ -370,13 +370,13 @@ lib::error_code connection<config>::pause_reading() {
|
||||
/// Pause reading handler. Not safe to call directly
|
||||
template <typename config>
|
||||
void connection<config>::handle_pause_reading() {
|
||||
m_alog.write(log::alevel::devel,"connection connection::handle_pause_reading");
|
||||
m_alog->write(log::alevel::devel,"connection connection::handle_pause_reading");
|
||||
m_read_flag = false;
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::resume_reading() {
|
||||
m_alog.write(log::alevel::devel,"connection connection::resume_reading");
|
||||
m_alog->write(log::alevel::devel,"connection connection::resume_reading");
|
||||
return transport_con_type::dispatch(
|
||||
lib::bind(
|
||||
&type::handle_resume_reading,
|
||||
@@ -714,10 +714,10 @@ void connection<config>::send_http_response() {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::start() {
|
||||
m_alog.write(log::alevel::devel,"connection start");
|
||||
m_alog->write(log::alevel::devel,"connection start");
|
||||
|
||||
if (m_internal_state != istate::USER_INIT) {
|
||||
m_alog.write(log::alevel::devel,"Start called in invalid state");
|
||||
m_alog->write(log::alevel::devel,"Start called in invalid state");
|
||||
this->terminate(error::make_error_code(error::invalid_state));
|
||||
return;
|
||||
}
|
||||
@@ -738,12 +738,12 @@ void connection<config>::start() {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::handle_transport_init(lib::error_code const & ec) {
|
||||
m_alog.write(log::alevel::devel,"connection handle_transport_init");
|
||||
m_alog->write(log::alevel::devel,"connection handle_transport_init");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
if (m_internal_state != istate::TRANSPORT_INIT) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_transport_init must be called from transport init state");
|
||||
ecm = error::make_error_code(error::invalid_state);
|
||||
}
|
||||
@@ -751,7 +751,7 @@ void connection<config>::handle_transport_init(lib::error_code const & ec) {
|
||||
if (ecm) {
|
||||
std::stringstream s;
|
||||
s << "handle_transport_init received error: "<< ecm.message();
|
||||
m_elog.write(log::elevel::rerror,s.str());
|
||||
m_elog->write(log::elevel::rerror,s.str());
|
||||
|
||||
this->terminate(ecm);
|
||||
return;
|
||||
@@ -772,7 +772,7 @@ void connection<config>::handle_transport_init(lib::error_code const & ec) {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::read_handshake(size_t num_bytes) {
|
||||
m_alog.write(log::alevel::devel,"connection read_handshake");
|
||||
m_alog->write(log::alevel::devel,"connection read_handshake");
|
||||
|
||||
if (m_open_handshake_timeout_dur > 0) {
|
||||
m_handshake_timer = transport_con_type::set_timer(
|
||||
@@ -804,7 +804,7 @@ template <typename config>
|
||||
void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
size_t bytes_transferred)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"connection handle_read_handshake");
|
||||
m_alog->write(log::alevel::devel,"connection handle_read_handshake");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
@@ -819,7 +819,7 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
// The connection was canceled while the response was being sent,
|
||||
// usually by the handshake timer. This is basically expected
|
||||
// (though hopefully rare) and there is nothing we can do so ignore.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_read_handshake invoked after connection was closed");
|
||||
return;
|
||||
} else {
|
||||
@@ -830,7 +830,7 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
if (ecm) {
|
||||
if (ecm == transport::error::eof && m_state == session::state::closed) {
|
||||
// we expect to get eof if the connection is closed already
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"got (expected) eof/state error from closed con");
|
||||
return;
|
||||
}
|
||||
@@ -842,7 +842,7 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
|
||||
// Boundaries checking. TODO: How much of this should be done?
|
||||
if (bytes_transferred > config::connection_read_buffer_size) {
|
||||
m_elog.write(log::elevel::fatal,"Fatal boundaries checking error.");
|
||||
m_elog->write(log::elevel::fatal,"Fatal boundaries checking error.");
|
||||
this->terminate(make_error_code(error::general));
|
||||
return;
|
||||
}
|
||||
@@ -861,16 +861,16 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
// More paranoid boundaries checking.
|
||||
// TODO: Is this overkill?
|
||||
if (bytes_processed > bytes_transferred) {
|
||||
m_elog.write(log::elevel::fatal,"Fatal boundaries checking error.");
|
||||
m_elog->write(log::elevel::fatal,"Fatal boundaries checking error.");
|
||||
this->terminate(make_error_code(error::general));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "bytes_transferred: " << bytes_transferred
|
||||
<< " bytes, bytes processed: " << bytes_processed << " bytes";
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
if (m_request.ready()) {
|
||||
@@ -891,17 +891,17 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
bytes_processed += 8;
|
||||
} else {
|
||||
// TODO: need more bytes
|
||||
m_alog.write(log::alevel::devel,"short key3 read");
|
||||
m_alog->write(log::alevel::devel,"short key3 read");
|
||||
m_response.set_status(http::status_code::internal_server_error);
|
||||
this->write_http_response_error(processor::error::make_error_code(processor::error::short_key3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,m_request.raw());
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,m_request.raw());
|
||||
if (!m_request.get_header("Sec-WebSocket-Key3").empty()) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
utility::to_hex(m_request.get_header("Sec-WebSocket-Key3")));
|
||||
}
|
||||
}
|
||||
@@ -948,7 +948,7 @@ void connection<config>::handle_read_handshake(lib::error_code const & ec,
|
||||
template <typename config>
|
||||
void connection<config>::write_http_response_error(lib::error_code const & ec) {
|
||||
if (m_internal_state != istate::READ_HTTP_REQUEST) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"write_http_response_error called in invalid state");
|
||||
this->terminate(error::make_error_code(error::invalid_state));
|
||||
return;
|
||||
@@ -965,7 +965,7 @@ template <typename config>
|
||||
void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
size_t bytes_transferred)
|
||||
{
|
||||
//m_alog.write(log::alevel::devel,"connection handle_read_frame");
|
||||
//m_alog->write(log::alevel::devel,"connection handle_read_frame");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
@@ -980,7 +980,7 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
if (m_state == session::state::closed) {
|
||||
// we expect to get eof if the connection is closed already
|
||||
// just ignore it
|
||||
m_alog.write(log::alevel::devel,"got eof from closed con");
|
||||
m_alog->write(log::alevel::devel,"got eof from closed con");
|
||||
return;
|
||||
} else if (m_state == session::state::closing && !m_is_server) {
|
||||
// If we are a client we expect to get eof in the closing state,
|
||||
@@ -995,7 +995,7 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
// changed and should be ignored as they pose no problems and there
|
||||
// is nothing useful that we can do about them.
|
||||
if (m_state == session::state::closed) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_read_frame: got invalid istate in closed state");
|
||||
return;
|
||||
}
|
||||
@@ -1019,32 +1019,32 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
|
||||
// Boundaries checking. TODO: How much of this should be done?
|
||||
/*if (bytes_transferred > config::connection_read_buffer_size) {
|
||||
m_elog.write(log::elevel::fatal,"Fatal boundaries checking error");
|
||||
m_elog->write(log::elevel::fatal,"Fatal boundaries checking error");
|
||||
this->terminate(make_error_code(error::general));
|
||||
return;
|
||||
}*/
|
||||
|
||||
size_t p = 0;
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "p = " << p << " bytes transferred = " << bytes_transferred;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
while (p < bytes_transferred) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "calling consume with " << bytes_transferred-p << " bytes";
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
lib::error_code consume_ec;
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "Processing Bytes: " << utility::to_hex(reinterpret_cast<uint8_t*>(m_buf)+p,bytes_transferred-p);
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
p += m_processor->consume(
|
||||
@@ -1053,10 +1053,10 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
consume_ec
|
||||
);
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "bytes left after consume: " << bytes_transferred-p;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
if (consume_ec) {
|
||||
log_err(log::elevel::rerror, "consume", consume_ec);
|
||||
@@ -1082,20 +1082,20 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
}
|
||||
|
||||
if (m_processor->ready()) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "Complete message received. Dispatching";
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
message_ptr msg = m_processor->get_message();
|
||||
|
||||
if (!msg) {
|
||||
m_alog.write(log::alevel::devel, "null message from m_processor");
|
||||
m_alog->write(log::alevel::devel, "null message from m_processor");
|
||||
} else if (!is_control(msg->get_opcode())) {
|
||||
// data message, dispatch to user
|
||||
if (m_state != session::state::open) {
|
||||
m_elog.write(log::elevel::warn, "got non-close frame while closing");
|
||||
m_elog->write(log::elevel::warn, "got non-close frame while closing");
|
||||
} else if (m_message_handler) {
|
||||
m_message_handler(m_connection_hdl, msg);
|
||||
}
|
||||
@@ -1132,7 +1132,7 @@ void connection<config>::read_frame() {
|
||||
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::initialize_processor() {
|
||||
m_alog.write(log::alevel::devel,"initialize_processor");
|
||||
m_alog->write(log::alevel::devel,"initialize_processor");
|
||||
|
||||
// if it isn't a websocket handshake nothing to do.
|
||||
if (!processor::is_websocket_handshake(m_request)) {
|
||||
@@ -1142,7 +1142,7 @@ lib::error_code connection<config>::initialize_processor() {
|
||||
int version = processor::get_websocket_version(m_request);
|
||||
|
||||
if (version < 0) {
|
||||
m_alog.write(log::alevel::devel, "BAD REQUEST: can't determine version");
|
||||
m_alog->write(log::alevel::devel, "BAD REQUEST: can't determine version");
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return error::make_error_code(error::invalid_version);
|
||||
}
|
||||
@@ -1156,7 +1156,7 @@ lib::error_code connection<config>::initialize_processor() {
|
||||
|
||||
// We don't have a processor for this version. Return bad request
|
||||
// with Sec-WebSocket-Version header filled with values we do accept
|
||||
m_alog.write(log::alevel::devel, "BAD REQUEST: no processor for version");
|
||||
m_alog->write(log::alevel::devel, "BAD REQUEST: no processor for version");
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
|
||||
std::stringstream ss;
|
||||
@@ -1174,11 +1174,11 @@ lib::error_code connection<config>::initialize_processor() {
|
||||
|
||||
template <typename config>
|
||||
lib::error_code connection<config>::process_handshake_request() {
|
||||
m_alog.write(log::alevel::devel,"process handshake request");
|
||||
m_alog->write(log::alevel::devel,"process handshake request");
|
||||
|
||||
if (!processor::is_websocket_handshake(m_request)) {
|
||||
// this is not a websocket handshake. Process as plain HTTP
|
||||
m_alog.write(log::alevel::devel,"HTTP REQUEST");
|
||||
m_alog->write(log::alevel::devel,"HTTP REQUEST");
|
||||
|
||||
// extract URI from request
|
||||
m_uri = processor::get_uri_from_host(
|
||||
@@ -1187,7 +1187,7 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
);
|
||||
|
||||
if (!m_uri->get_valid()) {
|
||||
m_alog.write(log::alevel::devel, "Bad request: failed to parse uri");
|
||||
m_alog->write(log::alevel::devel, "Bad request: failed to parse uri");
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return error::make_error_code(error::invalid_uri);
|
||||
}
|
||||
@@ -1212,7 +1212,7 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
// Validate: make sure all required elements are present.
|
||||
if (ec){
|
||||
// Not a valid handshake request
|
||||
m_alog.write(log::alevel::devel, "Bad request " + ec.message());
|
||||
m_alog->write(log::alevel::devel, "Bad request " + ec.message());
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return ec;
|
||||
}
|
||||
@@ -1225,7 +1225,7 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
if (neg_results.first) {
|
||||
// There was a fatal error in extension parsing that should result in
|
||||
// a failed connection attempt.
|
||||
m_alog.write(log::alevel::devel, "Bad request: " + neg_results.first.message());
|
||||
m_alog->write(log::alevel::devel, "Bad request: " + neg_results.first.message());
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return neg_results.first;
|
||||
} else {
|
||||
@@ -1243,7 +1243,7 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
|
||||
|
||||
if (!m_uri->get_valid()) {
|
||||
m_alog.write(log::alevel::devel, "Bad request: failed to parse uri");
|
||||
m_alog->write(log::alevel::devel, "Bad request: failed to parse uri");
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return error::make_error_code(error::invalid_uri);
|
||||
}
|
||||
@@ -1267,14 +1267,14 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
if (ec) {
|
||||
std::stringstream s;
|
||||
s << "Processing error: " << ec << "(" << ec.message() << ")";
|
||||
m_alog.write(log::alevel::devel, s.str());
|
||||
m_alog->write(log::alevel::devel, s.str());
|
||||
|
||||
m_response.set_status(http::status_code::internal_server_error);
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
// User application has rejected the handshake
|
||||
m_alog.write(log::alevel::devel, "USER REJECT");
|
||||
m_alog->write(log::alevel::devel, "USER REJECT");
|
||||
|
||||
// Use Bad Request if the user handler did not provide a more
|
||||
// specific http response error code.
|
||||
@@ -1291,10 +1291,10 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::write_http_response(lib::error_code const & ec) {
|
||||
m_alog.write(log::alevel::devel,"connection write_http_response");
|
||||
m_alog->write(log::alevel::devel,"connection write_http_response");
|
||||
|
||||
if (ec == error::make_error_code(error::http_connection_ended)) {
|
||||
m_alog.write(log::alevel::http,"An HTTP handler took over the connection.");
|
||||
m_alog->write(log::alevel::http,"An HTTP handler took over the connection.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1324,10 +1324,10 @@ void connection<config>::write_http_response(lib::error_code const & ec) {
|
||||
m_handshake_buffer = m_response.raw();
|
||||
}
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"Raw Handshake response:\n"+m_handshake_buffer);
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"Raw Handshake response:\n"+m_handshake_buffer);
|
||||
if (!m_response.get_header("Sec-WebSocket-Key3").empty()) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
utility::to_hex(m_response.get_header("Sec-WebSocket-Key3")));
|
||||
}
|
||||
}
|
||||
@@ -1346,7 +1346,7 @@ void connection<config>::write_http_response(lib::error_code const & ec) {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::handle_write_http_response(lib::error_code const & ec) {
|
||||
m_alog.write(log::alevel::devel,"handle_write_http_response");
|
||||
m_alog->write(log::alevel::devel,"handle_write_http_response");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
@@ -1361,7 +1361,7 @@ void connection<config>::handle_write_http_response(lib::error_code const & ec)
|
||||
// The connection was canceled while the response was being sent,
|
||||
// usually by the handshake timer. This is basically expected
|
||||
// (though hopefully rare) and there is nothing we can do so ignore.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_write_http_response invoked after connection was closed");
|
||||
return;
|
||||
} else {
|
||||
@@ -1372,7 +1372,7 @@ void connection<config>::handle_write_http_response(lib::error_code const & ec)
|
||||
if (ecm) {
|
||||
if (ecm == transport::error::eof && m_state == session::state::closed) {
|
||||
// we expect to get eof if the connection is closed already
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"got (expected) eof/state error from closed con");
|
||||
return;
|
||||
}
|
||||
@@ -1397,7 +1397,7 @@ void connection<config>::handle_write_http_response(lib::error_code const & ec)
|
||||
std::stringstream s;
|
||||
s << "Handshake ended with HTTP error: "
|
||||
<< m_response.get_status_code();
|
||||
m_elog.write(log::elevel::rerror,s.str());
|
||||
m_elog->write(log::elevel::rerror,s.str());
|
||||
} else {
|
||||
// if this was not a websocket connection, we have written
|
||||
// the expected response and the connection can be closed.
|
||||
@@ -1405,7 +1405,7 @@ void connection<config>::handle_write_http_response(lib::error_code const & ec)
|
||||
this->log_http_result();
|
||||
|
||||
if (m_ec) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"got to writing HTTP results with m_ec set: "+m_ec.message());
|
||||
}
|
||||
m_ec = make_error_code(error::http_connection_ended);
|
||||
@@ -1429,7 +1429,7 @@ void connection<config>::handle_write_http_response(lib::error_code const & ec)
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::send_http_request() {
|
||||
m_alog.write(log::alevel::devel,"connection send_http_request");
|
||||
m_alog->write(log::alevel::devel,"connection send_http_request");
|
||||
|
||||
// TODO: origin header?
|
||||
|
||||
@@ -1445,7 +1445,7 @@ void connection<config>::send_http_request() {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_elog.write(log::elevel::fatal,"Internal library error: missing processor");
|
||||
m_elog->write(log::elevel::fatal,"Internal library error: missing processor");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1460,8 +1460,8 @@ void connection<config>::send_http_request() {
|
||||
|
||||
m_handshake_buffer = m_request.raw();
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"Raw Handshake request:\n"+m_handshake_buffer);
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"Raw Handshake request:\n"+m_handshake_buffer);
|
||||
}
|
||||
|
||||
if (m_open_handshake_timeout_dur > 0) {
|
||||
@@ -1488,7 +1488,7 @@ void connection<config>::send_http_request() {
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::handle_send_http_request(lib::error_code const & ec) {
|
||||
m_alog.write(log::alevel::devel,"handle_send_http_request");
|
||||
m_alog->write(log::alevel::devel,"handle_send_http_request");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
@@ -1505,7 +1505,7 @@ void connection<config>::handle_send_http_request(lib::error_code const & ec) {
|
||||
// The connection was canceled while the response was being sent,
|
||||
// usually by the handshake timer. This is basically expected
|
||||
// (though hopefully rare) and there is nothing we can do so ignore.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_send_http_request invoked after connection was closed");
|
||||
return;
|
||||
} else {
|
||||
@@ -1516,7 +1516,7 @@ void connection<config>::handle_send_http_request(lib::error_code const & ec) {
|
||||
if (ecm) {
|
||||
if (ecm == transport::error::eof && m_state == session::state::closed) {
|
||||
// we expect to get eof if the connection is closed already
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"got (expected) eof/state error from closed con");
|
||||
return;
|
||||
}
|
||||
@@ -1543,7 +1543,7 @@ template <typename config>
|
||||
void connection<config>::handle_read_http_response(lib::error_code const & ec,
|
||||
size_t bytes_transferred)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"handle_read_http_response");
|
||||
m_alog->write(log::alevel::devel,"handle_read_http_response");
|
||||
|
||||
lib::error_code ecm = ec;
|
||||
|
||||
@@ -1558,7 +1558,7 @@ void connection<config>::handle_read_http_response(lib::error_code const & ec,
|
||||
// The connection was canceled while the response was being sent,
|
||||
// usually by the handshake timer. This is basically expected
|
||||
// (though hopefully rare) and there is nothing we can do so ignore.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_read_http_response invoked after connection was closed");
|
||||
return;
|
||||
} else {
|
||||
@@ -1569,7 +1569,7 @@ void connection<config>::handle_read_http_response(lib::error_code const & ec,
|
||||
if (ecm) {
|
||||
if (ecm == transport::error::eof && m_state == session::state::closed) {
|
||||
// we expect to get eof if the connection is closed already
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"got (expected) eof/state error from closed con");
|
||||
return;
|
||||
}
|
||||
@@ -1584,13 +1584,13 @@ void connection<config>::handle_read_http_response(lib::error_code const & ec,
|
||||
try {
|
||||
bytes_processed = m_response.consume(m_buf,bytes_transferred);
|
||||
} catch (http::exception & e) {
|
||||
m_elog.write(log::elevel::rerror,
|
||||
m_elog->write(log::elevel::rerror,
|
||||
std::string("error in handle_read_http_response: ")+e.what());
|
||||
this->terminate(make_error_code(error::general));
|
||||
return;
|
||||
}
|
||||
|
||||
m_alog.write(log::alevel::devel,std::string("Raw response: ")+m_response.raw());
|
||||
m_alog->write(log::alevel::devel,std::string("Raw response: ")+m_response.raw());
|
||||
|
||||
if (m_response.headers_ready()) {
|
||||
if (m_handshake_timer) {
|
||||
@@ -1621,7 +1621,7 @@ void connection<config>::handle_read_http_response(lib::error_code const & ec,
|
||||
// doesn't match the options requested by the client. Its possible
|
||||
// that the best behavior in this cases is to log and continue with
|
||||
// an unextended connection.
|
||||
m_alog.write(log::alevel::devel, "Extension negotiation failed: "
|
||||
m_alog->write(log::alevel::devel, "Extension negotiation failed: "
|
||||
+ neg_results.first.message());
|
||||
this->terminate(make_error_code(error::extension_neg_failed));
|
||||
// TODO: close connection with reason 1010 (and list extensions)
|
||||
@@ -1664,13 +1664,13 @@ void connection<config>::handle_open_handshake_timeout(
|
||||
lib::error_code const & ec)
|
||||
{
|
||||
if (ec == transport::error::operation_aborted) {
|
||||
m_alog.write(log::alevel::devel,"open handshake timer cancelled");
|
||||
m_alog->write(log::alevel::devel,"open handshake timer cancelled");
|
||||
} else if (ec) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"open handle_open_handshake_timeout error: "+ec.message());
|
||||
// TODO: ignore or fail here?
|
||||
} else {
|
||||
m_alog.write(log::alevel::devel,"open handshake timer expired");
|
||||
m_alog->write(log::alevel::devel,"open handshake timer expired");
|
||||
terminate(make_error_code(error::open_handshake_timeout));
|
||||
}
|
||||
}
|
||||
@@ -1680,21 +1680,21 @@ void connection<config>::handle_close_handshake_timeout(
|
||||
lib::error_code const & ec)
|
||||
{
|
||||
if (ec == transport::error::operation_aborted) {
|
||||
m_alog.write(log::alevel::devel,"asio close handshake timer cancelled");
|
||||
m_alog->write(log::alevel::devel,"asio close handshake timer cancelled");
|
||||
} else if (ec) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio open handle_close_handshake_timeout error: "+ec.message());
|
||||
// TODO: ignore or fail here?
|
||||
} else {
|
||||
m_alog.write(log::alevel::devel, "asio close handshake timer expired");
|
||||
m_alog->write(log::alevel::devel, "asio close handshake timer expired");
|
||||
terminate(make_error_code(error::close_handshake_timeout));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::terminate(lib::error_code const & ec) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection terminate");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection terminate");
|
||||
}
|
||||
|
||||
// Cancel close handshake timer
|
||||
@@ -1727,7 +1727,7 @@ void connection<config>::terminate(lib::error_code const & ec) {
|
||||
m_state = session::state::closed;
|
||||
tstat = closed;
|
||||
} else {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"terminate called on connection that was already terminated");
|
||||
return;
|
||||
}
|
||||
@@ -1748,8 +1748,8 @@ template <typename config>
|
||||
void connection<config>::handle_terminate(terminate_status tstat,
|
||||
lib::error_code const & ec)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection handle_terminate");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection handle_terminate");
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
@@ -1770,7 +1770,7 @@ void connection<config>::handle_terminate(terminate_status tstat,
|
||||
}
|
||||
log_close_result();
|
||||
} else {
|
||||
m_elog.write(log::elevel::rerror,"Unknown terminate_status");
|
||||
m_elog->write(log::elevel::rerror,"Unknown terminate_status");
|
||||
}
|
||||
|
||||
// call the termination handler if it exists
|
||||
@@ -1780,7 +1780,7 @@ void connection<config>::handle_terminate(terminate_status tstat,
|
||||
try {
|
||||
m_termination_handler(type::get_shared());
|
||||
} catch (std::exception const & e) {
|
||||
m_elog.write(log::elevel::warn,
|
||||
m_elog->write(log::elevel::warn,
|
||||
std::string("termination_handler call failed. Reason was: ")+e.what());
|
||||
}
|
||||
}
|
||||
@@ -1788,7 +1788,7 @@ void connection<config>::handle_terminate(terminate_status tstat,
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::write_frame() {
|
||||
//m_alog.write(log::alevel::devel,"connection write_frame");
|
||||
//m_alog->write(log::alevel::devel,"connection write_frame");
|
||||
|
||||
{
|
||||
scoped_lock_type lock(m_write_lock);
|
||||
@@ -1834,8 +1834,8 @@ void connection<config>::write_frame() {
|
||||
}
|
||||
|
||||
// Print detailed send stats if those log levels are enabled
|
||||
if (m_alog.static_test(log::alevel::frame_header)) {
|
||||
if (m_alog.dynamic_test(log::alevel::frame_header)) {
|
||||
if (m_alog->static_test(log::alevel::frame_header)) {
|
||||
if (m_alog->dynamic_test(log::alevel::frame_header)) {
|
||||
std::stringstream general,header,payload;
|
||||
|
||||
general << "Dispatching write containing " << m_current_msgs.size()
|
||||
@@ -1855,8 +1855,8 @@ void connection<config>::write_frame() {
|
||||
<< m_current_msgs[i]->get_header().size() << ") "
|
||||
<< utility::to_hex(m_current_msgs[i]->get_header()) << "\n";
|
||||
|
||||
if (m_alog.static_test(log::alevel::frame_payload)) {
|
||||
if (m_alog.dynamic_test(log::alevel::frame_payload)) {
|
||||
if (m_alog->static_test(log::alevel::frame_payload)) {
|
||||
if (m_alog->dynamic_test(log::alevel::frame_payload)) {
|
||||
payload << "[" << i << "] ("
|
||||
<< m_current_msgs[i]->get_payload().size() << ") ["<<m_current_msgs[i]->get_opcode()<<"] "
|
||||
<< (m_current_msgs[i]->get_opcode() == frame::opcode::text ?
|
||||
@@ -1870,9 +1870,9 @@ void connection<config>::write_frame() {
|
||||
|
||||
general << hbytes << " header bytes and " << pbytes << " payload bytes";
|
||||
|
||||
m_alog.write(log::alevel::frame_header,general.str());
|
||||
m_alog.write(log::alevel::frame_header,header.str());
|
||||
m_alog.write(log::alevel::frame_payload,payload.str());
|
||||
m_alog->write(log::alevel::frame_header,general.str());
|
||||
m_alog->write(log::alevel::frame_header,header.str());
|
||||
m_alog->write(log::alevel::frame_payload,payload.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1885,8 +1885,8 @@ void connection<config>::write_frame() {
|
||||
template <typename config>
|
||||
void connection<config>::handle_write_frame(lib::error_code const & ec)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"connection handle_write_frame");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"connection handle_write_frame");
|
||||
}
|
||||
|
||||
bool terminal = m_current_msgs.back()->get_terminal();
|
||||
@@ -1933,21 +1933,21 @@ std::vector<int> const & connection<config>::get_supported_versions() const
|
||||
template <typename config>
|
||||
void connection<config>::process_control_frame(typename config::message_type::ptr msg)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"process_control_frame");
|
||||
m_alog->write(log::alevel::devel,"process_control_frame");
|
||||
|
||||
frame::opcode::value op = msg->get_opcode();
|
||||
lib::error_code ec;
|
||||
|
||||
std::stringstream s;
|
||||
s << "Control frame received with opcode " << op;
|
||||
m_alog.write(log::alevel::control,s.str());
|
||||
m_alog->write(log::alevel::control,s.str());
|
||||
|
||||
if (m_state == session::state::closed) {
|
||||
m_elog.write(log::elevel::warn,"got frame in state closed");
|
||||
m_elog->write(log::elevel::warn,"got frame in state closed");
|
||||
return;
|
||||
}
|
||||
if (op != frame::opcode::CLOSE && m_state != session::state::open) {
|
||||
m_elog.write(log::elevel::warn,"got non-close frame in state closing");
|
||||
m_elog->write(log::elevel::warn,"got non-close frame in state closing");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1972,7 +1972,7 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
m_ping_timer->cancel();
|
||||
}
|
||||
} else if (op == frame::opcode::CLOSE) {
|
||||
m_alog.write(log::alevel::devel,"got close frame");
|
||||
m_alog->write(log::alevel::devel,"got close frame");
|
||||
// record close code and reason somewhere
|
||||
|
||||
m_remote_close_code = close::extract_code(msg->get_payload(),ec);
|
||||
@@ -1981,12 +1981,12 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
if (config::drop_on_protocol_error) {
|
||||
s << "Received invalid close code " << m_remote_close_code
|
||||
<< " dropping connection per config.";
|
||||
m_elog.write(log::elevel::devel,s.str());
|
||||
m_elog->write(log::elevel::devel,s.str());
|
||||
this->terminate(ec);
|
||||
} else {
|
||||
s << "Received invalid close code " << m_remote_close_code
|
||||
<< " sending acknowledgement and closing";
|
||||
m_elog.write(log::elevel::devel,s.str());
|
||||
m_elog->write(log::elevel::devel,s.str());
|
||||
ec = send_close_ack(close::status::protocol_error,
|
||||
"Invalid close code");
|
||||
if (ec) {
|
||||
@@ -1999,11 +1999,11 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
m_remote_close_reason = close::extract_reason(msg->get_payload(),ec);
|
||||
if (ec) {
|
||||
if (config::drop_on_protocol_error) {
|
||||
m_elog.write(log::elevel::devel,
|
||||
m_elog->write(log::elevel::devel,
|
||||
"Received invalid close reason. Dropping connection per config");
|
||||
this->terminate(ec);
|
||||
} else {
|
||||
m_elog.write(log::elevel::devel,
|
||||
m_elog->write(log::elevel::devel,
|
||||
"Received invalid close reason. Sending acknowledgement and closing");
|
||||
ec = send_close_ack(close::status::protocol_error,
|
||||
"Invalid close reason");
|
||||
@@ -2018,7 +2018,7 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
s.str("");
|
||||
s << "Received close frame with code " << m_remote_close_code
|
||||
<< " and reason " << m_remote_close_reason;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
|
||||
ec = send_close_ack();
|
||||
if (ec) {
|
||||
@@ -2026,7 +2026,7 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
}
|
||||
} else if (m_state == session::state::closing && !m_was_clean) {
|
||||
// ack of our close
|
||||
m_alog.write(log::alevel::devel, "Got acknowledgement of close");
|
||||
m_alog->write(log::alevel::devel, "Got acknowledgement of close");
|
||||
|
||||
m_was_clean = true;
|
||||
|
||||
@@ -2042,11 +2042,11 @@ void connection<config>::process_control_frame(typename config::message_type::pt
|
||||
}
|
||||
} else {
|
||||
// spurious, ignore
|
||||
m_elog.write(log::elevel::devel, "Got close frame in wrong state");
|
||||
m_elog->write(log::elevel::devel, "Got close frame in wrong state");
|
||||
}
|
||||
} else {
|
||||
// got an invalid control opcode
|
||||
m_elog.write(log::elevel::devel, "Got control frame with invalid opcode");
|
||||
m_elog->write(log::elevel::devel, "Got control frame with invalid opcode");
|
||||
// initiate protocol error shutdown
|
||||
}
|
||||
}
|
||||
@@ -2062,7 +2062,7 @@ template <typename config>
|
||||
lib::error_code connection<config>::send_close_frame(close::status::value code,
|
||||
std::string const & reason, bool ack, bool terminal)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"send_close_frame");
|
||||
m_alog->write(log::alevel::devel,"send_close_frame");
|
||||
|
||||
// check for special codes
|
||||
|
||||
@@ -2073,24 +2073,24 @@ lib::error_code connection<config>::send_close_frame(close::status::value code,
|
||||
// send blank info. If it is an ack then echo the close information from
|
||||
// the remote endpoint.
|
||||
if (config::silent_close) {
|
||||
m_alog.write(log::alevel::devel,"closing silently");
|
||||
m_alog->write(log::alevel::devel,"closing silently");
|
||||
m_local_close_code = close::status::no_status;
|
||||
m_local_close_reason.clear();
|
||||
} else if (code != close::status::blank) {
|
||||
m_alog.write(log::alevel::devel,"closing with specified codes");
|
||||
m_alog->write(log::alevel::devel,"closing with specified codes");
|
||||
m_local_close_code = code;
|
||||
m_local_close_reason = reason;
|
||||
} else if (!ack) {
|
||||
m_alog.write(log::alevel::devel,"closing with no status code");
|
||||
m_alog->write(log::alevel::devel,"closing with no status code");
|
||||
m_local_close_code = close::status::no_status;
|
||||
m_local_close_reason.clear();
|
||||
} else if (m_remote_close_code == close::status::no_status) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"acknowledging a no-status close with normal code");
|
||||
m_local_close_code = close::status::normal;
|
||||
m_local_close_reason.clear();
|
||||
} else {
|
||||
m_alog.write(log::alevel::devel,"acknowledging with remote codes");
|
||||
m_alog->write(log::alevel::devel,"acknowledging with remote codes");
|
||||
m_local_close_code = m_remote_close_code;
|
||||
m_local_close_reason = m_remote_close_reason;
|
||||
}
|
||||
@@ -2098,7 +2098,7 @@ lib::error_code connection<config>::send_close_frame(close::status::value code,
|
||||
std::stringstream s;
|
||||
s << "Closing with code: " << m_local_close_code << ", and reason: "
|
||||
<< m_local_close_reason;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
|
||||
message_ptr msg = m_msg_manager->get_message();
|
||||
if (!msg) {
|
||||
@@ -2213,11 +2213,11 @@ void connection<config>::write_push(typename config::message_type::ptr msg)
|
||||
m_send_buffer_size += msg->get_payload().size();
|
||||
m_send_queue.push(msg);
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "write_push: message count: " << m_send_queue.size()
|
||||
<< " buffer size: " << m_send_buffer_size;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2235,11 +2235,11 @@ typename config::message_type::ptr connection<config>::write_pop()
|
||||
m_send_buffer_size -= msg->get_payload().size();
|
||||
m_send_queue.pop();
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "write_pop: message count: " << m_send_queue.size()
|
||||
<< " buffer size: " << m_send_buffer_size;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
@@ -2282,7 +2282,7 @@ void connection<config>::log_open_result()
|
||||
// Status code
|
||||
s << m_response.get_status_code();
|
||||
|
||||
m_alog.write(log::alevel::connect,s.str());
|
||||
m_alog->write(log::alevel::connect,s.str());
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
@@ -2296,7 +2296,7 @@ void connection<config>::log_close_result()
|
||||
<< "] remote:[" << m_remote_close_code
|
||||
<< (m_remote_close_reason.empty() ? "" : ","+m_remote_close_reason) << "]";
|
||||
|
||||
m_alog.write(log::alevel::disconnect,s.str());
|
||||
m_alog->write(log::alevel::disconnect,s.str());
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
@@ -2335,7 +2335,7 @@ void connection<config>::log_fail_result()
|
||||
// WebSocket++ error code & reason
|
||||
s << " " << m_ec << " " << m_ec.message();
|
||||
|
||||
m_alog.write(log::alevel::fail,s.str());
|
||||
m_alog->write(log::alevel::fail,s.str());
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
@@ -2343,7 +2343,7 @@ void connection<config>::log_http_result() {
|
||||
std::stringstream s;
|
||||
|
||||
if (processor::is_websocket_handshake(m_request)) {
|
||||
m_alog.write(log::alevel::devel,"Call to log_http_result for WebSocket");
|
||||
m_alog->write(log::alevel::devel,"Call to log_http_result for WebSocket");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2364,7 +2364,7 @@ void connection<config>::log_http_result() {
|
||||
s << " \"" << utility::string_replace_all(ua,"\"","\\\"") << "\" ";
|
||||
}
|
||||
|
||||
m_alog.write(log::alevel::http,s.str());
|
||||
m_alog->write(log::alevel::http,s.str());
|
||||
}
|
||||
|
||||
} // namespace websocketpp
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace websocketpp {
|
||||
template <typename connection, typename config>
|
||||
typename endpoint<connection,config>::connection_ptr
|
||||
endpoint<connection,config>::create_connection() {
|
||||
m_alog.write(log::alevel::devel,"create_connection");
|
||||
m_alog->write(log::alevel::devel,"create_connection");
|
||||
//scoped_lock_type lock(m_state_lock);
|
||||
|
||||
/*if (m_state == STOPPING || m_state == STOPPED) {
|
||||
@@ -45,7 +45,7 @@ endpoint<connection,config>::create_connection() {
|
||||
//scoped_lock_type guard(m_mutex);
|
||||
// Create a connection on the heap and manage it using a shared pointer
|
||||
connection_ptr con = lib::make_shared<connection_type>(m_is_server,
|
||||
m_user_agent, lib::ref(m_alog), lib::ref(m_elog), lib::ref(m_rng));
|
||||
m_user_agent, m_alog, m_elog, lib::ref(m_rng));
|
||||
|
||||
connection_weak_ptr w(con);
|
||||
|
||||
@@ -85,7 +85,7 @@ endpoint<connection,config>::create_connection() {
|
||||
|
||||
ec = transport_type::init(con);
|
||||
if (ec) {
|
||||
m_elog.write(log::elevel::fatal,ec.message());
|
||||
m_elog->write(log::elevel::fatal,ec.message());
|
||||
return connection_ptr();
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ void endpoint<connection,config>::interrupt(connection_hdl hdl, lib::error_code
|
||||
connection_ptr con = get_con_from_hdl(hdl,ec);
|
||||
if (ec) {return;}
|
||||
|
||||
m_alog.write(log::alevel::devel,"Interrupting connection");
|
||||
m_alog->write(log::alevel::devel,"Interrupting connection");
|
||||
|
||||
ec = con->interrupt();
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
|
||||
explicit client() : endpoint_type(false)
|
||||
{
|
||||
endpoint_type::m_alog.write(log::alevel::devel, "client constructor");
|
||||
endpoint_type::m_alog->write(log::alevel::devel, "client constructor");
|
||||
}
|
||||
|
||||
/// Get a new connection
|
||||
@@ -157,10 +157,10 @@ private:
|
||||
if (ec) {
|
||||
con->terminate(ec);
|
||||
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
endpoint_type::m_elog->write(log::elevel::rerror,
|
||||
"handle_connect error: "+ec.message());
|
||||
} else {
|
||||
endpoint_type::m_alog.write(log::alevel::connect,
|
||||
endpoint_type::m_alog->write(log::alevel::connect,
|
||||
"Successful connection");
|
||||
|
||||
con->start();
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
explicit server() : endpoint_type(true)
|
||||
{
|
||||
endpoint_type::m_alog.write(log::alevel::devel, "server constructor");
|
||||
endpoint_type::m_alog->write(log::alevel::devel, "server constructor");
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
|
||||
// no copy constructor because endpoints are not copyable
|
||||
server<config>(server<config> &) = delete;
|
||||
|
||||
|
||||
// no copy assignment operator because endpoints are not copyable
|
||||
server<config> & operator=(server<config> const &) = delete;
|
||||
#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
*
|
||||
* Refer to documentation for the transport policy you are using for
|
||||
* instructions on how to stop this acceptance loop.
|
||||
*
|
||||
*
|
||||
* @param [out] ec A status code indicating an error, if any.
|
||||
*/
|
||||
void start_accept(lib::error_code & ec) {
|
||||
@@ -126,13 +126,18 @@ public:
|
||||
|
||||
ec = lib::error_code();
|
||||
connection_ptr con = get_connection();
|
||||
|
||||
|
||||
if (!con) {
|
||||
ec = error::make_error_code(error::con_creation_failed);
|
||||
return;
|
||||
}
|
||||
|
||||
transport_type::async_accept(
|
||||
lib::static_pointer_cast<transport_con_type>(con),
|
||||
lib::bind(&type::handle_accept,this,con,lib::placeholders::_1),
|
||||
ec
|
||||
);
|
||||
|
||||
|
||||
if (ec && con) {
|
||||
// If the connection was constructed but the accept failed,
|
||||
// terminate the connection to prevent memory leaks
|
||||
@@ -163,10 +168,10 @@ public:
|
||||
con->terminate(ec);
|
||||
|
||||
if (ec == error::operation_canceled) {
|
||||
endpoint_type::m_elog.write(log::elevel::info,
|
||||
endpoint_type::m_elog->write(log::elevel::info,
|
||||
"handle_accept error: "+ec.message());
|
||||
} else {
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
endpoint_type::m_elog->write(log::elevel::rerror,
|
||||
"handle_accept error: "+ec.message());
|
||||
}
|
||||
} else {
|
||||
@@ -176,10 +181,10 @@ public:
|
||||
lib::error_code start_ec;
|
||||
start_accept(start_ec);
|
||||
if (start_ec == error::async_accept_not_listening) {
|
||||
endpoint_type::m_elog.write(log::elevel::info,
|
||||
endpoint_type::m_elog->write(log::elevel::info,
|
||||
"Stopping acceptance of new connections because the underlying transport is no longer listening.");
|
||||
} else if (start_ec) {
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
endpoint_type::m_elog->write(log::elevel::rerror,
|
||||
"Restarting async_accept loop failed: "+ec.message());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +98,12 @@ public:
|
||||
friend class endpoint<config>;
|
||||
|
||||
// generate and manage our own io_service
|
||||
explicit connection(bool is_server, alog_type & alog, elog_type & elog)
|
||||
explicit connection(bool is_server, const lib::shared_ptr<alog_type> & alog, const lib::shared_ptr<elog_type> & elog)
|
||||
: m_is_server(is_server)
|
||||
, m_alog(alog)
|
||||
, m_elog(elog)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"asio con transport constructor");
|
||||
m_alog->write(log::alevel::devel,"asio con transport constructor");
|
||||
}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
std::string ret = socket_con_type::get_remote_endpoint(ec);
|
||||
|
||||
if (ec) {
|
||||
m_elog.write(log::elevel::info,ret);
|
||||
m_elog->write(log::elevel::info,ret);
|
||||
return "Unknown";
|
||||
} else {
|
||||
return ret;
|
||||
@@ -408,8 +408,8 @@ public:
|
||||
*/
|
||||
protected:
|
||||
void init(init_handler callback) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection init");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection init");
|
||||
}
|
||||
|
||||
// TODO: pre-init timeout. Right now no implemented socket policies
|
||||
@@ -472,8 +472,8 @@ protected:
|
||||
}
|
||||
|
||||
void handle_pre_init(init_handler callback, lib::error_code const & ec) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection handle pre_init");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection handle pre_init");
|
||||
}
|
||||
|
||||
if (m_tcp_pre_init_handler) {
|
||||
@@ -494,8 +494,8 @@ protected:
|
||||
}
|
||||
|
||||
void post_init(init_handler callback) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection post_init");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection post_init");
|
||||
}
|
||||
|
||||
timer_ptr post_timer;
|
||||
@@ -540,7 +540,7 @@ protected:
|
||||
|
||||
if (ec) {
|
||||
if (ec == transport::error::operation_aborted) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio post init timer cancelled");
|
||||
return;
|
||||
}
|
||||
@@ -555,7 +555,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
m_alog.write(log::alevel::devel, "Asio transport post-init timed out");
|
||||
m_alog->write(log::alevel::devel, "Asio transport post-init timed out");
|
||||
cancel_socket_checked();
|
||||
callback(ret_ec);
|
||||
}
|
||||
@@ -575,7 +575,7 @@ protected:
|
||||
if (ec == transport::error::operation_aborted ||
|
||||
(post_timer && lib::asio::is_neg(post_timer->expires_from_now())))
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"post_init cancelled");
|
||||
m_alog->write(log::alevel::devel,"post_init cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -583,8 +583,8 @@ protected:
|
||||
post_timer->cancel();
|
||||
}
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection handle_post_init");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection handle_post_init");
|
||||
}
|
||||
|
||||
if (m_tcp_post_init_handler) {
|
||||
@@ -595,12 +595,12 @@ protected:
|
||||
}
|
||||
|
||||
void proxy_write(init_handler callback) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection proxy_write");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection proxy_write");
|
||||
}
|
||||
|
||||
if (!m_proxy_data) {
|
||||
m_elog.write(log::elevel::library,
|
||||
m_elog->write(log::elevel::library,
|
||||
"assertion failed: !m_proxy_data in asio::connection::proxy_write");
|
||||
callback(make_error_code(error::general));
|
||||
return;
|
||||
@@ -611,7 +611,7 @@ protected:
|
||||
m_bufs.push_back(lib::asio::buffer(m_proxy_data->write_buf.data(),
|
||||
m_proxy_data->write_buf.size()));
|
||||
|
||||
m_alog.write(log::alevel::devel,m_proxy_data->write_buf);
|
||||
m_alog->write(log::alevel::devel,m_proxy_data->write_buf);
|
||||
|
||||
// Set a timer so we don't wait forever for the proxy to respond
|
||||
m_proxy_data->timer = this->set_timer(
|
||||
@@ -651,14 +651,14 @@ protected:
|
||||
void handle_proxy_timeout(init_handler callback, lib::error_code const & ec)
|
||||
{
|
||||
if (ec == transport::error::operation_aborted) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio handle_proxy_write timer cancelled");
|
||||
return;
|
||||
} else if (ec) {
|
||||
log_err(log::elevel::devel,"asio handle_proxy_write",ec);
|
||||
callback(ec);
|
||||
} else {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio handle_proxy_write timer expired");
|
||||
cancel_socket_checked();
|
||||
callback(make_error_code(transport::error::timeout));
|
||||
@@ -668,8 +668,8 @@ protected:
|
||||
void handle_proxy_write(init_handler callback,
|
||||
lib::asio::error_code const & ec)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio connection handle_proxy_write");
|
||||
}
|
||||
|
||||
@@ -681,7 +681,7 @@ protected:
|
||||
if (ec == lib::asio::error::operation_aborted ||
|
||||
lib::asio::is_neg(m_proxy_data->timer->expires_from_now()))
|
||||
{
|
||||
m_elog.write(log::elevel::devel,"write operation aborted");
|
||||
m_elog->write(log::elevel::devel,"write operation aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -696,12 +696,12 @@ protected:
|
||||
}
|
||||
|
||||
void proxy_read(init_handler callback) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection proxy_read");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection proxy_read");
|
||||
}
|
||||
|
||||
if (!m_proxy_data) {
|
||||
m_elog.write(log::elevel::library,
|
||||
m_elog->write(log::elevel::library,
|
||||
"assertion failed: !m_proxy_data in asio::connection::proxy_read");
|
||||
m_proxy_data->timer->cancel();
|
||||
callback(make_error_code(error::general));
|
||||
@@ -742,8 +742,8 @@ protected:
|
||||
void handle_proxy_read(init_handler callback,
|
||||
lib::asio::error_code const & ec, size_t)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio connection handle_proxy_read");
|
||||
}
|
||||
|
||||
@@ -753,7 +753,7 @@ protected:
|
||||
if (ec == lib::asio::error::operation_aborted ||
|
||||
lib::asio::is_neg(m_proxy_data->timer->expires_from_now()))
|
||||
{
|
||||
m_elog.write(log::elevel::devel,"read operation aborted");
|
||||
m_elog->write(log::elevel::devel,"read operation aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -761,12 +761,12 @@ protected:
|
||||
m_proxy_data->timer->cancel();
|
||||
|
||||
if (ec) {
|
||||
m_elog.write(log::elevel::info,
|
||||
m_elog->write(log::elevel::info,
|
||||
"asio handle_proxy_read error: "+ec.message());
|
||||
callback(make_error_code(error::pass_through));
|
||||
} else {
|
||||
if (!m_proxy_data) {
|
||||
m_elog.write(log::elevel::library,
|
||||
m_elog->write(log::elevel::library,
|
||||
"assertion failed: !m_proxy_data in asio::connection::handle_proxy_read");
|
||||
callback(make_error_code(error::general));
|
||||
return;
|
||||
@@ -783,7 +783,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
m_alog.write(log::alevel::devel,m_proxy_data->res.raw());
|
||||
m_alog->write(log::alevel::devel,m_proxy_data->res.raw());
|
||||
|
||||
if (m_proxy_data->res.get_status_code() != http::status_code::ok) {
|
||||
// got an error response back
|
||||
@@ -795,7 +795,7 @@ protected:
|
||||
<< " ("
|
||||
<< m_proxy_data->res.get_status_msg()
|
||||
<< ")";
|
||||
m_elog.write(log::elevel::info,s.str());
|
||||
m_elog->write(log::elevel::info,s.str());
|
||||
callback(make_error_code(error::proxy_failed));
|
||||
return;
|
||||
}
|
||||
@@ -820,16 +820,16 @@ protected:
|
||||
void async_read_at_least(size_t num_bytes, char *buf, size_t len,
|
||||
read_handler handler)
|
||||
{
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
std::stringstream s;
|
||||
s << "asio async_read_at_least: " << num_bytes;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
}
|
||||
|
||||
// TODO: safety vs speed ?
|
||||
// maybe move into an if devel block
|
||||
/*if (num_bytes > len) {
|
||||
m_elog.write(log::elevel::devel,
|
||||
m_elog->write(log::elevel::devel,
|
||||
"asio async_read_at_least error::invalid_num_bytes");
|
||||
handler(make_error_code(transport::error::invalid_num_bytes),
|
||||
size_t(0));
|
||||
@@ -871,7 +871,7 @@ protected:
|
||||
void handle_async_read(read_handler handler, lib::asio::error_code const & ec,
|
||||
size_t bytes_transferred)
|
||||
{
|
||||
m_alog.write(log::alevel::devel, "asio con handle_async_read");
|
||||
m_alog->write(log::alevel::devel, "asio con handle_async_read");
|
||||
|
||||
// translate asio error codes into more lib::error_codes
|
||||
lib::error_code tec;
|
||||
@@ -897,7 +897,7 @@ protected:
|
||||
} else {
|
||||
// This can happen in cases where the connection is terminated while
|
||||
// the transport is waiting on a read.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_async_read called with null read handler");
|
||||
}
|
||||
}
|
||||
@@ -989,7 +989,7 @@ protected:
|
||||
} else {
|
||||
// This can happen in cases where the connection is terminated while
|
||||
// the transport is waiting on a read.
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"handle_async_write called with null write handler");
|
||||
}
|
||||
}
|
||||
@@ -1034,8 +1034,8 @@ protected:
|
||||
|
||||
/// close and clean up the underlying socket
|
||||
void async_shutdown(shutdown_handler callback) {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"asio connection async_shutdown");
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,"asio connection async_shutdown");
|
||||
}
|
||||
|
||||
timer_ptr shutdown_timer;
|
||||
@@ -1074,7 +1074,7 @@ protected:
|
||||
|
||||
if (ec) {
|
||||
if (ec == transport::error::operation_aborted) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio socket shutdown timer cancelled");
|
||||
return;
|
||||
}
|
||||
@@ -1085,7 +1085,7 @@ protected:
|
||||
ret_ec = make_error_code(transport::error::timeout);
|
||||
}
|
||||
|
||||
m_alog.write(log::alevel::devel,
|
||||
m_alog->write(log::alevel::devel,
|
||||
"Asio transport socket shutdown timed out");
|
||||
cancel_socket_checked();
|
||||
callback(ret_ec);
|
||||
@@ -1097,7 +1097,7 @@ protected:
|
||||
if (ec == lib::asio::error::operation_aborted ||
|
||||
lib::asio::is_neg(shutdown_timer->expires_from_now()))
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"async_shutdown cancelled");
|
||||
m_alog->write(log::alevel::devel,"async_shutdown cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1129,8 +1129,8 @@ protected:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
m_alog->write(log::alevel::devel,
|
||||
"asio con handle_async_shutdown");
|
||||
}
|
||||
}
|
||||
@@ -1143,7 +1143,7 @@ protected:
|
||||
if (cec) {
|
||||
if (cec == lib::asio::error::operation_not_supported) {
|
||||
// cancel not supported on this OS, ignore and log at dev level
|
||||
m_alog.write(log::alevel::devel, "socket cancel not supported");
|
||||
m_alog->write(log::alevel::devel, "socket cancel not supported");
|
||||
} else {
|
||||
log_err(log::elevel::warn, "socket cancel failed", cec);
|
||||
}
|
||||
@@ -1156,13 +1156,13 @@ private:
|
||||
void log_err(log::level l, const char * msg, const error_type & ec) {
|
||||
std::stringstream s;
|
||||
s << msg << " error: " << ec << " (" << ec.message() << ")";
|
||||
m_elog.write(l,s.str());
|
||||
m_elog->write(l,s.str());
|
||||
}
|
||||
|
||||
// static settings
|
||||
const bool m_is_server;
|
||||
alog_type& m_alog;
|
||||
elog_type& m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
|
||||
struct proxy_data {
|
||||
proxy_data() : timeout_proxy(config::timeout_proxy) {}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <websocketpp/uri.hpp>
|
||||
#include <websocketpp/logger/levels.hpp>
|
||||
|
||||
#include <websocketpp/common/asio.hpp>
|
||||
#include <websocketpp/common/functional.hpp>
|
||||
|
||||
#include <sstream>
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
explicit endpoint()
|
||||
: m_io_service(NULL)
|
||||
, m_external_io_service(false)
|
||||
, m_listen_backlog(0)
|
||||
, m_listen_backlog(lib::asio::socket_base::max_connections)
|
||||
, m_reuse_addr(false)
|
||||
, m_state(UNINITIALIZED)
|
||||
{
|
||||
@@ -314,8 +315,10 @@ public:
|
||||
*
|
||||
* New values affect future calls to listen only.
|
||||
*
|
||||
* A value of zero will use the operating system default. This is the
|
||||
* default value.
|
||||
* The default value is specified as *::asio::socket_base::max_connections
|
||||
* which uses the operating system defined maximum queue length. Your OS
|
||||
* may restrict or silently lower this value. A value of zero may cause
|
||||
* all connections to be rejected.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*
|
||||
@@ -328,10 +331,13 @@ public:
|
||||
/// Sets whether to use the SO_REUSEADDR flag when opening listening sockets
|
||||
/**
|
||||
* Specifies whether or not to use the SO_REUSEADDR TCP socket option. What
|
||||
* this flag does depends on your operating system. Please consult operating
|
||||
* system documentation for more details.
|
||||
* this flag does depends on your operating system.
|
||||
*
|
||||
* New values affect future calls to listen only.
|
||||
* Please consult operating system documentation for more details. There
|
||||
* may be security consequences to enabling this option.
|
||||
*
|
||||
* New values affect future calls to listen only so set this value prior to
|
||||
* calling listen.
|
||||
*
|
||||
* The default is false.
|
||||
*
|
||||
@@ -743,7 +749,7 @@ public:
|
||||
void async_accept(transport_con_ptr tcon, accept_handler callback,
|
||||
lib::error_code & ec)
|
||||
{
|
||||
if (m_state != LISTENING) {
|
||||
if (m_state != LISTENING || !m_acceptor) {
|
||||
using websocketpp::error::make_error_code;
|
||||
ec = make_error_code(websocketpp::error::async_accept_not_listening);
|
||||
return;
|
||||
@@ -795,7 +801,7 @@ protected:
|
||||
* haven't been constructed yet, and cannot be used in the transport
|
||||
* destructor as they will have been destroyed by then.
|
||||
*/
|
||||
void init_logging(alog_type* a, elog_type* e) {
|
||||
void init_logging(const lib::shared_ptr<alog_type>& a, const lib::shared_ptr<elog_type>& e) {
|
||||
m_alog = a;
|
||||
m_elog = e;
|
||||
}
|
||||
@@ -1133,8 +1139,8 @@ private:
|
||||
int m_listen_backlog;
|
||||
bool m_reuse_addr;
|
||||
|
||||
elog_type* m_elog;
|
||||
alog_type* m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
|
||||
// Transport state
|
||||
state m_state;
|
||||
|
||||
@@ -171,6 +171,10 @@ protected:
|
||||
m_socket = lib::make_shared<lib::asio::ip::tcp::socket>(
|
||||
lib::ref(*service));
|
||||
|
||||
if (m_socket_init_handler) {
|
||||
m_socket_init_handler(m_hdl, *m_socket);
|
||||
}
|
||||
|
||||
m_state = READY;
|
||||
|
||||
return lib::error_code();
|
||||
@@ -204,10 +208,6 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_socket_init_handler) {
|
||||
m_socket_init_handler(m_hdl,*m_socket);
|
||||
}
|
||||
|
||||
m_state = READING;
|
||||
|
||||
callback(lib::error_code());
|
||||
|
||||
@@ -196,6 +196,10 @@ protected:
|
||||
m_socket = lib::make_shared<socket_type>(
|
||||
_WEBSOCKETPP_REF(*service),lib::ref(*m_context));
|
||||
|
||||
if (m_socket_init_handler) {
|
||||
m_socket_init_handler(m_hdl, get_socket());
|
||||
}
|
||||
|
||||
m_io_service = service;
|
||||
m_strand = strand;
|
||||
m_is_server = is_server;
|
||||
@@ -245,10 +249,6 @@ protected:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_socket_init_handler) {
|
||||
m_socket_init_handler(m_hdl,get_socket());
|
||||
}
|
||||
|
||||
callback(lib::error_code());
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace websocketpp {
|
||||
* `connection_hdl` and any error that occurred.
|
||||
*
|
||||
* **init_logging**
|
||||
* `void init_logging(alog_type * a, elog_type * e)`\n
|
||||
* `void init_logging(const lib::shared_ptr<alog_type>& a, const lib::shared_ptr<elog_type>& e)`\n
|
||||
* Called once after construction to provide pointers to the endpoint's access
|
||||
* and error loggers. These may be stored and used to log messages or ignored.
|
||||
*/
|
||||
|
||||
@@ -73,10 +73,10 @@ public:
|
||||
|
||||
typedef lib::shared_ptr<timer> timer_ptr;
|
||||
|
||||
explicit connection(bool is_server, alog_type & alog, elog_type & elog)
|
||||
explicit connection(bool is_server, const lib::shared_ptr<alog_type> & alog, const lib::shared_ptr<elog_type> & elog)
|
||||
: m_reading(false), m_is_server(is_server), m_alog(alog), m_elog(elog)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"debug con transport constructor");
|
||||
m_alog->write(log::alevel::devel,"debug con transport constructor");
|
||||
}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
* needed.
|
||||
*/
|
||||
timer_ptr set_timer(long, timer_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"debug connection set timer");
|
||||
m_alog->write(log::alevel::devel,"debug connection set timer");
|
||||
m_timer_handler = handler;
|
||||
return timer_ptr();
|
||||
}
|
||||
@@ -215,7 +215,7 @@ protected:
|
||||
* @param handler The `init_handler` to call when initialization is done
|
||||
*/
|
||||
void init(init_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"debug connection init");
|
||||
m_alog->write(log::alevel::devel,"debug connection init");
|
||||
handler(lib::error_code());
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ protected:
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "debug_con async_read_at_least: " << num_bytes;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
|
||||
if (num_bytes > len) {
|
||||
handler(make_error_code(error::invalid_num_bytes),size_t(0));
|
||||
@@ -286,7 +286,7 @@ protected:
|
||||
* @param handler Callback to invoke with operation status.
|
||||
*/
|
||||
void async_write(char const *, size_t, write_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"debug_con async_write");
|
||||
m_alog->write(log::alevel::devel,"debug_con async_write");
|
||||
m_write_handler = handler;
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ protected:
|
||||
* @param handler Callback to invoke with operation status.
|
||||
*/
|
||||
void async_write(std::vector<buffer> const &, write_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"debug_con async_write buffer list");
|
||||
m_alog->write(log::alevel::devel,"debug_con async_write buffer list");
|
||||
m_write_handler = handler;
|
||||
}
|
||||
|
||||
@@ -337,10 +337,10 @@ protected:
|
||||
}
|
||||
|
||||
size_t read_some_impl(char const * buf, size_t len) {
|
||||
m_alog.write(log::alevel::devel,"debug_con read_some");
|
||||
m_alog->write(log::alevel::devel,"debug_con read_some");
|
||||
|
||||
if (!m_reading) {
|
||||
m_elog.write(log::elevel::devel,"write while not reading");
|
||||
m_elog->write(log::elevel::devel,"write while not reading");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -399,8 +399,8 @@ private:
|
||||
bool m_reading;
|
||||
bool const m_is_server;
|
||||
bool m_is_secure;
|
||||
alog_type & m_alog;
|
||||
elog_type & m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
std::string m_remote_endpoint;
|
||||
};
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ protected:
|
||||
* @param a A pointer to the access logger to use.
|
||||
* @param e A pointer to the error logger to use.
|
||||
*/
|
||||
void init_logging(alog_type *, elog_type *) {}
|
||||
void init_logging(lib::shared_ptr<alog_type>, lib::shared_ptr<elog_type>) {}
|
||||
|
||||
/// Initiate a new connection
|
||||
/**
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
typedef lib::shared_ptr<timer> timer_ptr;
|
||||
|
||||
explicit connection(bool is_server, alog_type & alog, elog_type & elog)
|
||||
explicit connection(bool is_server, const lib::shared_ptr<alog_type> & alog, const lib::shared_ptr<elog_type> & elog)
|
||||
: m_output_stream(NULL)
|
||||
, m_reading(false)
|
||||
, m_is_server(is_server)
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
, m_elog(elog)
|
||||
, m_remote_endpoint("iostream transport")
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"iostream con transport constructor");
|
||||
m_alog->write(log::alevel::devel,"iostream con transport constructor");
|
||||
}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -408,7 +408,7 @@ protected:
|
||||
* @param handler The `init_handler` to call when initialization is done
|
||||
*/
|
||||
void init(init_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"iostream connection init");
|
||||
m_alog->write(log::alevel::devel,"iostream connection init");
|
||||
handler(lib::error_code());
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ protected:
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "iostream_con async_read_at_least: " << num_bytes;
|
||||
m_alog.write(log::alevel::devel,s.str());
|
||||
m_alog->write(log::alevel::devel,s.str());
|
||||
|
||||
if (num_bytes > len) {
|
||||
handler(make_error_code(error::invalid_num_bytes),size_t(0));
|
||||
@@ -487,7 +487,7 @@ protected:
|
||||
void async_write(char const * buf, size_t len, transport::write_handler
|
||||
handler)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"iostream_con async_write");
|
||||
m_alog->write(log::alevel::devel,"iostream_con async_write");
|
||||
// TODO: lock transport state?
|
||||
|
||||
lib::error_code ec;
|
||||
@@ -527,7 +527,7 @@ protected:
|
||||
void async_write(std::vector<buffer> const & bufs, transport::write_handler
|
||||
handler)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"iostream_con async_write buffer list");
|
||||
m_alog->write(log::alevel::devel,"iostream_con async_write buffer list");
|
||||
// TODO: lock transport state?
|
||||
|
||||
lib::error_code ec;
|
||||
@@ -601,18 +601,18 @@ protected:
|
||||
}
|
||||
private:
|
||||
void read(std::istream &in) {
|
||||
m_alog.write(log::alevel::devel,"iostream_con read");
|
||||
m_alog->write(log::alevel::devel,"iostream_con read");
|
||||
|
||||
while (in.good()) {
|
||||
if (!m_reading) {
|
||||
m_elog.write(log::elevel::devel,"write while not reading");
|
||||
m_elog->write(log::elevel::devel,"write while not reading");
|
||||
break;
|
||||
}
|
||||
|
||||
in.read(m_buf+m_cursor,static_cast<std::streamsize>(m_len-m_cursor));
|
||||
|
||||
if (in.gcount() == 0) {
|
||||
m_elog.write(log::elevel::devel,"read zero bytes");
|
||||
m_elog->write(log::elevel::devel,"read zero bytes");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -632,10 +632,10 @@ private:
|
||||
}
|
||||
|
||||
size_t read_some_impl(char const * buf, size_t len) {
|
||||
m_alog.write(log::alevel::devel,"iostream_con read_some");
|
||||
m_alog->write(log::alevel::devel,"iostream_con read_some");
|
||||
|
||||
if (!m_reading) {
|
||||
m_elog.write(log::elevel::devel,"write while not reading");
|
||||
m_elog->write(log::elevel::devel,"write while not reading");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -694,8 +694,8 @@ private:
|
||||
bool m_reading;
|
||||
bool const m_is_server;
|
||||
bool m_is_secure;
|
||||
alog_type & m_alog;
|
||||
elog_type & m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
std::string m_remote_endpoint;
|
||||
|
||||
// This lock ensures that only one thread can edit read data for this
|
||||
|
||||
@@ -168,7 +168,7 @@ protected:
|
||||
* @param a A pointer to the access logger to use.
|
||||
* @param e A pointer to the error logger to use.
|
||||
*/
|
||||
void init_logging(alog_type * a, elog_type * e) {
|
||||
void init_logging(lib::shared_ptr<alog_type> a, lib::shared_ptr<elog_type> e) {
|
||||
m_elog = e;
|
||||
m_alog = a;
|
||||
}
|
||||
@@ -209,8 +209,8 @@ private:
|
||||
shutdown_handler m_shutdown_handler;
|
||||
write_handler m_write_handler;
|
||||
|
||||
elog_type * m_elog;
|
||||
alog_type * m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
bool m_is_secure;
|
||||
};
|
||||
|
||||
|
||||
@@ -72,10 +72,10 @@ public:
|
||||
|
||||
typedef lib::shared_ptr<timer> timer_ptr;
|
||||
|
||||
explicit connection(bool is_server, alog_type & alog, elog_type & elog)
|
||||
explicit connection(bool is_server, const lib::shared_ptr<alog_type> & alog, const lib::shared_ptr<elog_type> & elog)
|
||||
: m_alog(alog), m_elog(elog)
|
||||
{
|
||||
m_alog.write(log::alevel::devel,"stub con transport constructor");
|
||||
m_alog->write(log::alevel::devel,"stub con transport constructor");
|
||||
}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -175,7 +175,7 @@ protected:
|
||||
* @param handler The `init_handler` to call when initialization is done
|
||||
*/
|
||||
void init(init_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"stub connection init");
|
||||
m_alog->write(log::alevel::devel,"stub connection init");
|
||||
handler(make_error_code(error::not_implemented));
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ protected:
|
||||
void async_read_at_least(size_t num_bytes, char * buf, size_t len,
|
||||
read_handler handler)
|
||||
{
|
||||
m_alog.write(log::alevel::devel, "stub_con async_read_at_least");
|
||||
m_alog->write(log::alevel::devel, "stub_con async_read_at_least");
|
||||
handler(make_error_code(error::not_implemented), 0);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ protected:
|
||||
* @param handler Callback to invoke with operation status.
|
||||
*/
|
||||
void async_write(char const * buf, size_t len, write_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"stub_con async_write");
|
||||
m_alog->write(log::alevel::devel,"stub_con async_write");
|
||||
handler(make_error_code(error::not_implemented));
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ protected:
|
||||
* @param handler Callback to invoke with operation status.
|
||||
*/
|
||||
void async_write(std::vector<buffer> const & bufs, write_handler handler) {
|
||||
m_alog.write(log::alevel::devel,"stub_con async_write buffer list");
|
||||
m_alog->write(log::alevel::devel,"stub_con async_write buffer list");
|
||||
handler(make_error_code(error::not_implemented));
|
||||
}
|
||||
|
||||
@@ -274,8 +274,8 @@ protected:
|
||||
}
|
||||
private:
|
||||
// member variables!
|
||||
alog_type & m_alog;
|
||||
elog_type & m_elog;
|
||||
lib::shared_ptr<alog_type> m_alog;
|
||||
lib::shared_ptr<elog_type> m_elog;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace websocketpp {
|
||||
/// Library major version number
|
||||
static int const major_version = 0;
|
||||
/// Library minor version number
|
||||
static int const minor_version = 7;
|
||||
static int const minor_version = 8;
|
||||
/// Library patch version number
|
||||
static int const patch_version = 0;
|
||||
/// Library pre-release flag
|
||||
@@ -51,10 +51,10 @@ static int const patch_version = 0;
|
||||
* versions (dev, alpha, beta, rc). This will be blank for release versions.
|
||||
*/
|
||||
|
||||
static char const prerelease_flag[] = "";
|
||||
static char const prerelease_flag[] = "dev";
|
||||
|
||||
/// Default user agent string
|
||||
static char const user_agent[] = "WebSocket++/0.7.0";
|
||||
static char const user_agent[] = "WebSocket++/0.8.0-dev";
|
||||
|
||||
} // namespace websocketpp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user