Compare commits

..

177 Commits

Author SHA1 Message Date
Alexander Afanasyev ac4e021333 Fix compilation with boost 1.70.0 2019-04-25 17:23:23 -04:00
Peter Thorson c6d7e295bf Set version flags for release 2018-07-16 07:40:53 -05:00
Peter Thorson c43242523c Update changelog 2018-07-16 07:38:45 -05:00
Peter Thorson 12b8f37cf5 Merge branch 'pr/732' into develop 2018-07-16 07:34:02 -05:00
Peter Thorson 6b8dfe02c2 Merge branch 'pr/731' into develop 2018-07-16 07:32:03 -05:00
Gianfranco Costamagna e99aef04c3 cmake: Install websocketpp includes in the right cmake way, leaving out the examples and other stuff 2018-07-12 20:25:09 +02:00
Gianfranco Costamagna 5c48a114f4 Fix testsuite errors, due to a "Connection: upgrade" seen differently than "Connection: Upgrade" 2018-07-12 19:10:02 +02:00
Peter Thorson c2fd89bede Update version flags for future development 2018-07-12 07:52:49 -05:00
Peter Thorson c612a35f06 Set version flags for 0.8.0 release 2018-07-12 07:50:48 -05:00
Peter Thorson 99d169f586 Update changelog for recent PRs 2018-07-12 07:46:21 -05:00
Peter Thorson 241741ba01 Merge pull request #727 from bauerj/patch-1
Make HTTP Connection header capitalized
2018-07-12 07:27:05 -05:00
Johann Bauer 702b6a919b Make HTTP Connection header capitalized
This is what other implementations do and what the example in RFC 6455 uses.
2018-06-18 12:46:01 +02:00
Peter Thorson 19cad9925f credits 2017-09-24 10:48:12 -05:00
Peter Thorson c4050979c3 tcp_pre_bind_handler returns a lib::error_code not an asio::error_code. These are sometimes the same but not always. Fix ensures that the error code types always match correctly no matter what they are. Update test suite to reflect adjusted behavior 2017-09-24 10:44:21 -05:00
Peter Thorson 7e8c8a8fad Fix preprocessor syntax issue 2017-09-24 09:56:21 -05:00
Peter Thorson 88de392422 Merge pull request #652 from vadz/preserve-asio-errors
Preserve ASIO errors if possible
2017-09-24 09:52:52 -05:00
Peter Thorson e79e0d1f94 Merge branch 'develop' of https://github.com/zaphoyd/websocketpp into develop 2017-09-24 09:27:47 -05:00
Peter Thorson bc12b81b29 Merge branch 'pr/608' into develop
# Conflicts:
#	changelog.md
2017-09-24 09:27:42 -05:00
Peter Thorson 8bc11bdf24 credits 2017-09-24 09:19:50 -05:00
Peter Thorson 1cb045d946 Add pointers in the docs to new mingw support 2017-09-24 09:17:34 -05:00
Peter Thorson 2a36e41a9a Remove auto selection of mingw-std-threads when MinGW is detected. Increase the priority of mingw-std-threads given its optional status. 2017-09-24 09:17:17 -05:00
Peter Thorson 0e1fc63b83 remove submodule 2017-09-24 09:16:05 -05:00
Peter Thorson 0b0871d879 remove submodules 2017-09-24 08:55:47 -05:00
Peter Thorson 20c67910e1 Merge pull request #658 from gjasny/drop-unused-members
Drop unused class members
2017-09-24 08:49:12 -05:00
Peter Thorson e943c9e1ed credits for patch 2017-09-24 08:44:28 -05:00
Peter Thorson 749b119b6b Merge pull request #665 from gegles/develop
Fix compile issues for ASIO_STANDALONE
2017-09-24 08:41:15 -05:00
Guillaume Egles e9c65467b3 Fix compile issues for ASIO_STANDALONE 2017-08-30 14:46:56 -07:00
Gregor Jasny b34a1786bc Drop unused class members 2017-07-04 09:31:37 +02:00
Peter Thorson e50ed8c1b1 update changelog for PR 2017-06-11 17:49:41 -05:00
Peter Thorson 67224f71b5 Merge pull request #636 from gjasny/remove-undefined-behaviour
Avoid undefined behaviour at circular shift
2017-06-11 17:47:47 -05:00
Peter Thorson 0b2e14ee3a Merge branch 'pr/589' into develop 2017-06-11 17:44:02 -05:00
Peter Thorson 1cb9666036 Update changelog for PR 2017-06-11 17:43:09 -05:00
Peter Thorson cb3d7de91f Remove deprecated features to allow compiling with C++17 compilers fixes #592 2017-06-11 17:37:14 -05:00
Peter Thorson 9baab8faa9 Normalize line endings to unix format fixes #644 2017-06-11 17:27:41 -05:00
Peter Thorson 6330286ad5 Use separate buffers for compression and decompression to prevent corruption when reading and writing from separate threads. references #633 references #615 2017-06-11 17:24:51 -05:00
Peter Thorson cb4cf66911 Merge branch 'pr/634' into develop 2017-06-11 16:46:31 -05:00
Peter Thorson 99e1a99633 change log update for PR 2017-06-11 16:46:18 -05:00
Peter Thorson 96b2d42c83 Merge branch 'pr/638' into develop 2017-06-11 16:39:32 -05:00
Peter Thorson bc04ae4f5f update changelog for PR 2017-06-11 16:37:46 -05:00
Peter Thorson ee74047c2d Merge pull request #645 from alex-che/integration_tests_sleep
Fix refused client connection due to servers not yet started
2017-06-11 16:34:49 -05:00
Peter Thorson 2819d364d9 Merge branch 'develop' into integration_tests_sleep 2017-06-11 16:31:21 -05:00
Peter Thorson d282738c81 Merge branch 'pr/643' into develop 2017-06-11 16:28:58 -05:00
Peter Thorson a32eb0887b change log entry for PR 2017-06-11 16:28:47 -05:00
Peter Thorson 6645fcb390 Merge pull request #646 from alex-che/timers_tests_sleep
Fix the tls_handshake_timeout unit test failing due to server thread …
2017-06-11 16:18:00 -05:00
Peter Thorson 29bb4ada91 Merge branch 'pr/647' into develop 2017-06-11 16:16:38 -05:00
Peter Thorson ac9164c3b5 update changelog for PR 2017-06-11 16:16:13 -05:00
Peter Thorson 4cab5e5c0c minor adjustments to recent extension negotiation related fixes, refactor a bit more extension negotiation code to be simpler 2017-06-11 16:13:25 -05:00
Peter Thorson 16d126ee61 Remove custom handling of SSL_R_SHORT_READ errors. fixes #599 2017-06-11 15:41:06 -05:00
Peter Thorson 9ddb300d87 Update permessage-deflate support to reflect that zlib doesn't support a 256 bit window. Improve extension negotiation error checking and documentation. fixes #596 fixes #653 2017-06-11 15:24:43 -05:00
Vadim Zeitlin 81ef065ccf Preserve ASIO errors if possible in asio::endpoint too
This was already done in asio::xxx_socket::connection methods by using
translate_ec() which allowed to preserve the error code when possible (i.e.
when using Boost.ASIO with Boost.System or standalone ASIO with C++11
std::error_code), but errors also can happen in endpoint methods such as
handle_connect(), where they were totally lost and replaced with a rather
useless error::pass_through.

With these changes, the real error codes are preserved and applications using
the library can give more useful error messages if connection fails.
2017-06-04 16:50:14 +02:00
Vadim Zeitlin e6e14df950 Make asio::connection::xxx_socket::translate_ec() methods static
These methods don't need any object to operate on, so make them static to
allow calling them without an actual connection object at hand.
2017-06-04 01:56:59 +02:00
Alex Korotkin 527f401049 Fix unitialized shared_ptr in mock_endpoint 2017-05-17 09:54:14 +03:00
Alex Korotkin 00456642fa Fix the tls_handshake_timeout unit test failing due to server thread not having enough time to start 2017-05-17 09:48:33 +03:00
Alex Korotkin 7be37565ca Fix refused client connection due to servers not yet started
The server thread in a unit test may not have enough time to start and the
ongoing client connection will be refused. Fix this by adding sleep.
2017-05-16 18:13:11 +03:00
Alex Korotkin 5675036891 Fix unit test timers clashing between tests
If unit tests run long enough, then test timers fired for former unit tests can start to fail while running latter unit tests.
2017-05-16 16:51:43 +03:00
Alex Korotkin 4b6cfed3fc "stdint header included to fix uintXX_t compilation error" 2017-05-06 13:11:17 +03:00
Gregor Jasny 6578aaea02 Avoid undefined behaviour at circular shift
Clang UBSAN complains about 64 bit wide shifts.
2017-04-09 23:59:23 -07:00
Gregor Jasny 229134aa95 Add pre bind handler for listen socket
Within this handler socket options like IPV6_ONLY could be set.
2017-04-04 22:34:11 +02:00
Peter Taylor c7bef866e4 Fixed Capatialisation issue with submodule 2016-12-11 11:31:08 +00:00
emersont1 3ad502916e Added MinGW threading Capability 2016-12-08 18:41:49 +00:00
jbwdevries 7451e0c58b Merge pull request #1 from ronneke1996/implement_close_code_1014
Fixed typo in error message
2016-10-18 18:46:44 +02:00
Ron Nabuurs facb698845 Fixed typo in error message 2016-10-18 16:59:38 +02:00
Peter Thorson 37ce8abc77 Merge branch 'pr/593' into develop 2016-10-14 08:28:55 -05:00
Peter Thorson abf927bb24 Fix some bugs, normalize code style, update documentation, add tests
Method needs to be public to be useful, updated return type to const
reference for efficiency
2016-10-14 08:27:06 -05:00
Jupp Müller e1f75756d1 Expose HTTP request headers
This change allows users to get a full list of HTTP request headers
allowing libraries that build on top of websocketpp to pass those on
to their users without exposing access to the already existing getter
methods.
2016-10-14 13:17:28 +02:00
Johan de Vries f94b3c0e4c Implemented close code 1014
Also adds two missing messages to get_string()
2016-10-10 10:05:15 +02:00
Peter Thorson 322e3bafbf Update telemetry_client to use Sleep on windows references #574 2016-10-04 07:41:02 -05:00
Peter Thorson 9019af0070 Add FAQ entry 2016-10-03 19:04:27 -05:00
Peter Thorson e65b277017 Remove catching websocketpp::lib::error_code in examples, fixes #584
A few versions ago the library was standardized to only throw
websocketpp::exception. Not all example code was updated.
2016-10-03 19:04:12 -05:00
Peter Thorson 8434139b67 Add first draft of print_client and print_client_tls 2016-06-10 07:24:36 -04:00
Peter Thorson d4a4b79684 update changelog for recent PR 2016-06-09 09:22:17 -04:00
Peter Thorson 6b09310479 Merge pull request #553 from yeswalrus/fix-tls-crash
Fix server_endpoint crash on connection failure
2016-06-09 09:08:12 -04:00
Peter Thorson 2b310fa80b Merge branch 'develop' of https://github.com/zaphoyd/websocketpp into develop 2016-05-25 08:11:20 -04:00
Peter Thorson 0bb33e4bca Change default listen backlog to socket_base::max_connections from 0, fixes #549
After a change in Linux Kernel 4.4 the value of 0 causes all
connections to be rejected rather than the default value being used.
The default is now the asio::socket_base::max_connections value instead
(which is the default asio uses when no value is provided).
Documentation has been updated accordingly.
2016-05-25 08:10:47 -04:00
Walter Gray ebd0afd67d Check the return of get_connection, raise an appropriate error if it failed. 2016-05-19 16:00:20 -07:00
Walter Gray 5f42305bbd remove trailing whitespaces 2016-05-19 13:47:20 -07:00
Peter Thorson a2f182733a Merge pull request #550 from wal-rus/fix-cmake
Fix CMake config files
2016-05-18 08:38:11 -04:00
Walter Gray 59fb9ece5d Added interface target to config file for cmake versions > 3.0 2016-05-11 16:54:41 -07:00
Walter Gray 73c3b81411 Added include directories to targets (How was this ever working?) 2016-05-11 16:54:40 -07:00
Walter Gray cc851aa167 remove whitespace at end of lines in CMakeHelpers.cmake 2016-05-11 16:54:39 -07:00
Walter Gray 0f2df92ae4 Use CMakePackageConfigHelpers, make websocketpp-config.cmake.in relocatable 2016-05-11 16:54:39 -07:00
Walter Gray 6b702cc050 Updated minimum required version to 2.8.8, Added VERSION argument to project if supported. 2016-05-11 16:54:38 -07:00
Walter Gray 92c1f0c415 Fix default CMAKE_INSTALL_PREFIX setting on windows 2016-05-10 13:44:25 -07:00
Peter Thorson 9e5163364f Add logging reference documentation 2016-04-27 09:00:30 -04:00
Peter Thorson 8f0fab3e77 Update docs & FAQ 2016-04-23 08:05:01 -04:00
Peter Thorson 94fe989840 Store loggers in shared pointers references #501 #537
adds related changelog entry and fix one overzealous find and replace
operation.
2016-04-06 09:38:45 -04:00
Peter Thorson 9da5ac93ec Merge pull request #539 from jupp0r/feature/shutdown-fix-for-shared-ioservice
Fix shutdown bugs by holding loggers in shared_ptrs
2016-04-06 09:27:35 -04:00
Peter Thorson 891a7a5ed5 documentation 2016-04-03 11:39:46 -04:00
Jupp Müller 1013aa89bc Fix shutdown bugs by holding loggers in shared_ptrs
This change fixes a shutdown crash occuring when using an
external io_service to drive a websocketpp server. The crash
itself is reproduced by the following code:

```

int main(int argc, const char * argv[])
{
    boost::asio::io_service ioService;
        std::unique_ptr<boost::asio::io_service::work> ioServiceWork(new boost::asio::io_service::work(ioService));
            std::thread ioServiceThread(boost::bind(&boost::asio::io_service::run, &ioService));

    {
        auto server = std::unique_ptr<websocketpp::server<websocketpp::config::asio>>(new websocketpp::server<websocketpp::config::asio>());
        server->init_asio(&ioService);
        server->listen(0);
        server->start_accept();

        server->stop();
    }

    ioServiceWork.reset();
    ioService.stop();
    ioServiceThread.join();

    return 0;
}
```

The cause of the crash is a dangling pointer to alog or elog objects in endpoints.
This is mitigated by storing logging objects as shared_ptrs. This ensures that
they are kept alive and able to log even if their owning structures have already
been deallocated.
2016-03-31 16:49:16 +02:00
Peter Thorson 366679b50a Update docs and changelog 2016-03-31 09:57:45 -04:00
Peter Thorson 94cc1ec5cb Fix an issue detecting which version of the chrono library to use references #512
If we are using Boost for Asio, the
websocketpp::lib::asio::milliseconds function should return a chrono
milliseconds object using whatever chrono library boost is using.

Boost does its own autodetection of the std::chrono library and prefers
it over boost::chrono when available. This change checks which chrono
library boost is using and uses that. Otherwise it falls back to the
websocketpp default.
2016-03-31 09:55:07 -04:00
Peter Thorson 6f128a5499 Move socket_init_handler from pre_init to init_asio #530
pre_init happens after bind/listen/accept, preventing socket options
that affect those system calls from being set in time.
2016-02-26 06:37:34 -05:00
Peter Thorson f5d14f3ad3 Bump develop branch version 2016-02-26 06:30:44 -05:00
Peter Thorson 918745a7ea Add test case for un-setting a handler (with NULL) 2016-02-26 06:20:53 -05:00
Peter Thorson 378437aecd Merge branch 'develop' 2016-02-22 08:30:10 -05:00
Peter Thorson cc7d74d8d0 Set version flags for release 2016-02-22 08:28:27 -05:00
Peter Thorson b154ac5907 Add FAQ entry 2016-02-22 08:28:05 -05:00
Peter Thorson 0348510c8d Fix minor issue in hybi00 subprotocol support patch. Update changelog for recent PRs 2016-02-21 18:30:58 -05:00
Peter Thorson a495c8c529 Merge branch 'develop' of https://github.com/zaphoyd/websocketpp into develop 2016-02-21 18:25:14 -05:00
Peter Thorson fabf8bf1ca clarified debugging output in connection read_handshake 2016-02-21 18:24:57 -05:00
Peter Thorson 3f913f97ef update tls version used in tls timer tests 2016-02-21 18:24:37 -05:00
Peter Thorson ffaeba2ec7 switch comment style in connection tests 2016-02-21 18:24:19 -05:00
Peter Thorson db304bfec4 Remove the use of cached read and write handlers in the asio transport. references #490 #525
There isn't a clean way to implement this performance optimization without adding global state/locking, which performs worse. This should fix
2016-02-21 18:23:58 -05:00
Peter Thorson d3bec51d25 Merge pull request #518 from lobermann/hixie76-hybi00-subprotocol-support
added subprotocol support for hybi00 / hixie76
2016-02-21 13:07:24 -05:00
Peter Thorson 8b672f7372 Merge pull request #524 from xavigibert/fix-uri
Fixed uri validator by checking its length.
2016-02-21 13:04:18 -05:00
Xavier Gibert Serra a4a79f6bf6 Fixed uri validator. This bug caused asan error heap-buffer-overflow when passing a short address. 2016-02-18 08:45:20 -08:00
Peter Thorson 9dc013a3aa Add an FAQ entry explaining how to use permessage-deflate in 0.6.0 and 0.7.0 2016-02-18 09:11:19 -05:00
Peter Thorson 931ad40b5f documentation & friend updates 2016-02-18 08:46:15 -05:00
Peter Thorson 842f745e24 Add echo_client example 2016-02-18 08:45:31 -05:00
Lukas Obermann e6f8766707 added subprotocol support for hybi00 / hixie76
This was missing but it is described in the RFC here
https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-1.9
2016-02-10 17:07:02 +01:00
Peter Thorson 17a2647454 Apply tentative fix for explicitly destroying objects that use io_service before it is deleted 2016-02-08 07:32:57 -05:00
Peter Thorson 323dec4efc Merge branch 'strand-fix-1' into develop 2016-02-08 07:31:41 -05:00
Peter Thorson ee343fb282 Adjust use of strand to work better with composite asio operations. references #459
particularly affected TLS servers and connection close behavior
2016-02-08 07:31:06 -05:00
Peter Thorson b76422aa7a explicitly delete work and resolver object before deleting io_service references #510 2016-02-07 11:58:04 -05:00
Peter Thorson 563fcc6b45 wrap TLS async_shutdown in a strand references #459 #466 2016-02-07 11:26:00 -05:00
Peter Thorson b6014cc79b FAQ & Change log minor update 2016-02-02 09:39:12 -05:00
Peter Thorson d917f0924b Remove execute permission from sha1.hpp fixes #489 2016-01-31 15:14:44 -05:00
Peter Thorson e036a5aeab Also fix this use of auto_ptr 2016-01-31 15:11:33 -05:00
Peter Thorson ed335a37b5 Replace deprecated use of auto_ptr when unique_ptr is available 2016-01-31 11:07:36 -05:00
Peter Thorson bb4cbf3d03 Merge branch 'develop' of https://github.com/zaphoyd/websocketpp into develop 2016-01-19 09:34:43 -05:00
Peter Thorson a388817606 Initial work on utility_server tutorial 2016-01-19 09:33:18 -05:00
Peter Thorson b373f1ea6b Merge pull request #509 from mgeier/no-get-uri
telemetry_server: Remove unnecessary call to get_uri()
2016-01-19 09:30:23 -05:00
Peter Thorson 28448c77a5 Merge pull request #507 from mgeier/unneeded-typedef
Remove unneeded typedef from telemetry_server example
2016-01-19 09:29:07 -05:00
Peter Thorson ae097d6a93 Merge pull request #508 from mgeier/lock-guard
broadcast_server: replace explicit unlock() by scoped unlock
2016-01-19 09:28:56 -05:00
Matthias Geier 02f0026a00 telemetry_server: Remove unnecessary call to get_uri() 2016-01-19 13:22:34 +01:00
Matthias Geier aac65bdfd0 broadcast_server: replace explicit unlock() by scoped unlock
Also: Replace some instances of unique_lock with lock_guard.
2016-01-19 12:31:23 +01:00
Matthias Geier 7b368e67ed Remove unneeded typedef from telemetry_server example 2016-01-19 10:29:37 +01:00
Peter Thorson d0802994d8 Merge branch 'pr/502' into develop 2016-01-14 09:12:02 -05:00
Peter Thorson 20cc197967 Fix a few other misc test related things 2016-01-12 10:51:59 -05:00
Gregor Jasny 89df55c577 Register tests to CTest 2016-01-05 09:51:15 +01:00
Peter Thorson 9713455e94 Fix TLS+Asio Standalone builds 2015-12-20 09:36:46 -05:00
Peter Thorson 044eda9cc4 Merge pull request #493 from jchampio/dev/cancel_socket
Always log errors when cancelling sockets
2015-12-19 11:52:24 -05:00
Peter Thorson fc6ec59ab8 more travis updates 2015-12-17 08:11:23 -05:00
Peter Thorson a01cce3b1a travis update 2015-12-17 07:32:26 -05:00
Peter Thorson e1b39037f7 travis config update 2015-12-17 07:30:00 -05:00
Peter Thorson f54fb0669b more docs 2015-12-17 07:29:51 -05:00
Peter Thorson 935c8a3264 Begin update to migrate manual content into the git repository
The goal here is to get all the documentation in one place including
the class reference, text based manual, tutorials, etc.
2015-12-16 10:03:14 -05:00
Peter Thorson 1e12e7aff8 use c++11 thread support on recent visual studio versions (really) 2015-12-15 19:17:11 -05:00
Peter Thorson bda1bd14cb use c++11 thread support on recent visual studio versions 2015-12-15 19:13:37 -05:00
Jacob Champion 5f52127cf7 Always log errors during socket cancel
cancel_socket_checked(), which logs any received errors, is now called
consistently instead of the lower-level cancel_socket().
2015-12-15 15:06:01 -08:00
Jacob Champion 999add0c4b Improve socket cancellation error messages
log_err() includes information about the error code.
2015-12-15 15:04:41 -08:00
Jacob Champion f7448bb1b0 Write to the error log for socket cancel failures
Previously an elevel entry was being written to an alog (possible
copy-paste error?).
2015-12-15 14:40:10 -08:00
Peter Thorson ed45dcc617 Fix an issue where the wrong type of strand was being created. 2015-11-24 10:22:54 -05:00
Peter Thorson 7f19b6ea95 Merge pull request #485 from Meoo/patch-1
Fix make_shared using the wrong strand type
2015-11-24 10:04:03 -05:00
Bastien Brunnenstein 5b99feef7f Fix make_shared using the wrong strand type
Fix compilation with standalone ASIO (#462), where asio::strand and asio::io_service::strand are separate types.
This is the correct type, as m_strand is a ``lib::shared_ptr<lib::asio::io_service::strand>``
2015-11-24 15:24:52 +01:00
Peter Thorson b85affddf4 Test how some doxygen compatible markup behaves on github 2015-11-05 08:29:04 -05:00
Peter Thorson 5500aef4ce Allow accessing the local endpoint when using the Asio transport. fixes #458 2015-11-05 06:33:15 -05:00
Peter Thorson 4e2fb75d07 Removes non-standards compliant masking behavior. fixes #469, fixes #395 2015-10-30 09:26:28 -04:00
Peter Thorson 6a94162264 Fix error handling in debug_client fixes #473 2015-10-30 08:45:32 -04:00
Peter Thorson 536db87c53 Merge branch 'pr/468' into develop 2015-09-30 09:59:11 -04:00
Peter Thorson 39c5f3ae3d Update changelog 2015-09-30 09:56:57 -04:00
vladon cd4af122c0 avoid unnecessary empty strings ("") in favor of clear() and empty() (performance) 2015-09-29 21:36:41 +03:00
Peter Thorson b6817e4c7e Actually have the response status getters work; also tests 2015-09-19 10:54:50 -04:00
Peter Thorson 72e55a76b5 remove alias for better compatibility with older compilers 2015-09-17 10:09:28 -04:00
Peter Thorson 93b75ccc7d Add get_status and get_response methods to connection fixes #465 2015-09-17 10:09:07 -04:00
Peter Thorson 3e8dbf767d Add example demonstrating external io_service 2015-09-17 08:11:48 -04:00
Peter Thorson 3c77ce3cc7 Fix race condition resulting in corruption of responses sent from non-blocking HTTP handers
The HTTP request processing code was expecting that the http response
state would be `deferred` after a call to an HTTP handler that deferred
the response. If, in addition to deferring, you also sent the response
the HTTP state advanced past `deferred` to `response_written`. This
doesn't easily show up in unit tests because the bug requires that the
async write still be in flight and the connection still be open when
the HTTP handler returns.

An asynchronous network transport (like Asio) combined with a
sufficiently large message that Asio yields control back to WebSocket++
before the response is fully written will trigger a second write on the
same connection while the first is in flight. This is not allowed per
the Asio spec and results in undefined behavior.

The HTTP request processing code now checks if the http state is init,
i.e. not deferred and no response has been started rather than just if
it was deferred.
2015-09-09 10:14:37 -04:00
Peter Thorson 54ce641d02 remove tabs 2015-08-25 09:30:00 -04:00
Peter Thorson e0bd3f7e95 Address an issue where an exception could be thrown when a socket gets canceled on Windows XP #460
This fix switches to using the non-exception variant of socket::cancel
and logging the error instead of throwing it. There is a chance that
something else will need to be addressed as a result of this change as
some async operations might not be cancelled? I believe everything in
question has timeouts that will trigger operation cancellation at some
point anyways.
2015-08-25 09:03:00 -04:00
Peter Thorson fb829e0895 Misc changes related to translation of asio transport errors #448 2015-08-20 10:14:55 -04:00
Peter Thorson f9dbc0fd9d Merge branch 'pr/456' into develop 2015-08-06 09:12:05 -04:00
Peter Thorson 0b2b77e4ad update changelog 2015-08-06 09:11:50 -04:00
Eli Fidler 15c78afbf4 fix crash in strip_lws()
Before this fix, a malicious client could cause a websocketpp server to create an invalid std::string.
2015-08-04 12:01:14 -04:00
Peter Thorson 4b18214eda Add preliminary support for C++11 features in Visual Studio 2015 2015-08-01 12:38:18 -04:00
Peter Thorson e80673278f Merge branch 'pr/454' into develop 2015-07-29 09:29:37 -04:00
Peter Thorson 95551e7e94 code style & change log update for PR 2015-07-29 09:28:22 -04:00
Peter Thorson 22918a3992 Merge branch 'permessage-deflate' into develop
Conflicts:
	Doxyfile
	examples/utility_client/CMakeLists.txt
	websocketpp/version.hpp
2015-07-29 09:12:21 -04:00
Peter Thorson 9b09b0b481 Merge branch 'pr/449' into develop 2015-07-29 08:59:14 -04:00
Peter Thorson ef380f7fff Add CMake build support for examples and tests, zlib dependencies 2015-07-29 08:57:56 -04:00
Mark Grimes 1f504001d2 Use smart pointer to hold new io_service temporarily in case of errors 2015-07-29 12:36:22 +01:00
Peter Thorson c54f2abaab utility client build scripts 2015-07-23 07:53:51 -04:00
Peter Thorson 3580530902 Miscellaneous changes
- Updates code style
- Adds some tags for future exception free work
- Fix utility client build scripts
2015-07-23 07:53:31 -04:00
Thijs Wenker bc7ad6550e fixed typo 2015-07-16 12:18:32 +02:00
Thijs Wenker d3fe51fa39 Added missing CMake files, organized the CMake structure between test and example directories using the global variable USE_FOLDERS 2015-07-16 12:17:59 +02:00
Thijs Wenker 7514c82c92 CMake: properly include examples and tests with macro (added unit_test_framework dependency for unit tests) 2015-07-16 11:38:38 +02:00
Peter Thorson dabf32a668 Better std::chrono autodetection for Visual Studio 2015-06-05 08:49:07 -04:00
Peter Thorson 39497aaa61 reset dev branch for work on next version 2015-06-02 08:59:10 -04:00
150 changed files with 6030 additions and 2360 deletions
+4
View File
@@ -88,3 +88,7 @@ examples/wsperf/wsperf_client
*.vcxproj.filters
*.user
install
Makefile
bin
Testing/Temporary/CTestCostData.txt
+3 -5
View File
@@ -2,18 +2,16 @@ language: cpp
compiler:
- gcc
before_install:
- sudo apt-get install libboost-chrono1.48-dev libboost-regex1.48-dev libboost-system1.48-dev libboost-thread1.48-dev libboost-test1.48-dev libboost-random1.48-dev -y
#- sudo apt-get install libboost-chrono1.48-dev libboost-regex1.48-dev libboost-system1.48-dev libboost-thread1.48-dev libboost-test1.48-dev libboost-random1.48-dev -y
- sudo add-apt-repository -y ppa:boost-latest/ppa && sudo apt-get update -q && sudo apt-get install -y libboost-chrono1.55-dev libboost-random1.55-dev libboost-regex1.55-dev libboost-system1.55-dev libboost-thread1.55-dev libboost-test1.55-dev
env:
global:
- BOOST_INCLUDES=/usr/include
- BOOST_LIBS=/usr/lib
- BOOST_LIBS=/usr/lib/x86_64-linux-gnu
script: scons -j 2 && scons test
branches:
only:
- master
- permessage-deflate
- experimental
- 0.3.x-cmake
- develop
notifications:
recipients:
+59 -25
View File
@@ -1,18 +1,44 @@
############ 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 6)
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")
if (WIN32 AND NOT CYGWIN)
set (DEF_INSTALL_CMAKE_DIR cmake)
@@ -42,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
@@ -67,6 +78,8 @@ option (BUILD_TESTS "Build websocketpp tests." FALSE)
if (BUILD_TESTS OR BUILD_EXAMPLES)
enable_testing ()
############ Compiler specific setup
set (WEBSOCKETPP_PLATFORM_LIBS "")
@@ -150,6 +163,10 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
list (APPEND WEBSOCKETPP_BOOST_LIBS random)
endif()
if (BUILD_TESTS)
list (APPEND WEBSOCKETPP_BOOST_LIBS unit_test_framework)
endif()
############ Dependencies
# Set BOOST_ROOT env variable or pass with cmake -DBOOST_ROOT=path.
@@ -180,6 +197,14 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
set (Boost_USE_STATIC_LIBS FALSE)
endif ()
if (BOOST_STATIC)
set (Boost_USE_STATIC_LIBS TRUE)
endif ()
if (NOT Boost_USE_STATIC_LIBS)
add_definitions (/DBOOST_TEST_DYN_LINK)
endif ()
set (Boost_FIND_REQUIRED TRUE)
set (Boost_FIND_QUIETLY TRUE)
set (Boost_DEBUG FALSE)
@@ -212,6 +237,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
endif ()
find_package(OpenSSL)
find_package(ZLIB)
endif()
############ Add projects
@@ -221,20 +247,28 @@ add_subdirectory (websocketpp)
# Add examples
if (BUILD_EXAMPLES)
add_subdirectory (examples)
include_subdirs ("examples")
endif ()
# Add tests
if (BUILD_TESTS)
add_subdirectory (test)
include_subdirs ("test")
endif ()
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
+1501 -1018
View File
File diff suppressed because it is too large Load Diff
+16 -2
View File
@@ -34,6 +34,11 @@ elif os.environ.has_key('BOOST_INCLUDES') and os.environ.has_key('BOOST_LIBS'):
else:
raise SCons.Errors.UserError, "Neither BOOST_ROOT, nor BOOST_INCLUDES + BOOST_LIBS was set!"
## Custom OpenSSL
if os.environ.has_key('OPENSSL_PATH'):
env.Append(CPPPATH = os.path.join(os.environ['OPENSSL_PATH'], 'include'))
env.Append(LIBPATH = os.environ['OPENSSL_PATH'])
if os.environ.has_key('WSPP_ENABLE_CPP11'):
env['WSPP_ENABLE_CPP11'] = True
else:
@@ -93,8 +98,7 @@ if env['PLATFORM'].startswith('win'):
#env['LIBPATH'] = env['BOOST_LIBS']
pass
else:
env['LIBPATH'] = ['/usr/lib',
'/usr/local/lib'] #, env['BOOST_LIBS']
env.Append(LIBPATH = ['/usr/lib', '/usr/local/lib'])
# Compiler specific warning flags
if env['CXX'].startswith('g++'):
@@ -227,10 +231,17 @@ if not env['PLATFORM'].startswith('win'):
# echo_server
echo_server = SConscript('#/examples/echo_server/SConscript',variant_dir = builddir + 'echo_server',duplicate = 0)
# 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)
@@ -260,6 +271,9 @@ subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',varia
# telemetry_server
telemetry_server = SConscript('#/examples/telemetry_server/SConscript',variant_dir = builddir + 'telemetry_server',duplicate = 0)
# external_io_service
external_io_service = SConscript('#/examples/external_io_service/SConscript',variant_dir = builddir + 'external_io_service',duplicate = 0)
if not env['PLATFORM'].startswith('win'):
# iostream_server
iostream_server = SConscript('#/examples/iostream_server/SConscript',variant_dir = builddir + 'iostream_server',duplicate = 0)
+154 -1
View File
@@ -1,6 +1,159 @@
HEAD
0.6.0
0.8.1 - 2018-07-16
Note: This release does not change library behavior. It only corrects issues
in the installer and test system.
- Test Suite: Adjust test suite to match behavior introduced in 0.8.0. Thank
you Gianfranco Costamagna for reporting and a patch. #731
- CMake: Update cmake installer to only install library files globally.
Thank you Gianfraco Costamanga for reporting and a patch. #732
0.8.0 - 2018-07-12
- 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.
- Improvement: Timers in transport integration tests should only fail if their
own test times out, rather than any test. #643 Thank you Alex Korotkin for
reporting and a patch.
- Improvement: Preserve transport layer error codes in more cases, particularly
during calls to `endpoint::listen`. #652 Thank you vadz for reporting and
patches.
- 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.
- Compatibility: Updated permessage-deflate support to reflect that the zlib
library does not actually support a sliding window size of 256 bits.
WebSocket++ will no longer negotiate 256 bit deflate windows. If the user
of the library tries to request a 256 bit window a 512 bit window will be
specified instead (This was the previous behavior). #596 #653 Thank you
Vinnie Falco and Gianfranco Costamagna for reporting.
- Compatibility: Better error handling and logging in cases where extension
requests parse correctly but negotiation fails.
- Compatibility: Removed custom handling of `SSL_R_SHORT_READ` error condition.
This error code no longer exists in modern versions of OpenSSL and causes
a build error. It wasn't being used for anything particularly important
(slightly improving error reporting) and there isn't a great replacement.
#599 Thank you Gianfranco Costamagna for reporting.
- Compatibility: Add missing `<stdint>` headers. Fixes issues with g++ 5.4.0.
#638 Thank you Alex Korotkin for reporting and a patch.
- Compatibility: Remove the use of `std::auto_ptr` and `std::binary_function`
from builds with C++11 or later. These features are deprecated and were
removed entirely in C++17. This change allows building WebSocket++ on
C++17 compilers. #592 Thank you Michal Fojtak for reporting and a patch
- Compatibility: Add 1014 close code and adds missing descriptions for codes
1012 and 1013. #589 Thank you jbwdevries and ronneke1996 for reporting and
patches.
- Compatibility: Add hooks to support `mingw-std-threads` C++11 thread and mutex
polyfill library as an alternative to Boost. #608 Thank you Peter Taylor for
reporting and an initial patch.
- Compatibility: Changed the handshake connection token to 'Upgrade' from
'upgrade'. Technically this header is supposed to be processed case
insensitively. In practice, there are browsers (such as Edge) that don't do
this and they tend to use the uppercase value used as an example in RFC6455.
Thank you Johann Bauer for reporting and a patch. #727
- 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
- Bug: Fix uninitialized shared pointer in Asio transport test suite. #647
Thank you Alex Korotkin for reporting and a patch.
- Bug: Fix a thread safety issue in the permessage-deflate extension that
caused message corruption when sending compressed messages from a different
thread than the main I/O thread. #615 Thank you KyleNyenhuis and Pieter De
Gendt for reporting and a patch.
- Bug: Fix an undefined behavior issue performing a 64 bit wide shift on a 64
bit value. #636 Thank you Gregor Jasny for reporting and a patch
- Bug: Fix some compile issues with ASIO_STANDALONE. #662 #665 Thank you
chronoxor and Guillaume Egles for reporting and patches.
0.7.0 - 2016-02-22
- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method
`cancel_socket` will now return `lib::asio::error_code` instead of `void`.
Custom Asio transport socket policies will need to be updated accordingly.
This does not affect anyone using the bundled socket policies.
- Feature: Basic support for the permessage-deflate extension. #344
- Feature: Allow accessing the local endpoint when using the Asio transport.
This allows inspection of the address and port in cases where they are chosen
by the operating system rather than the user. Thank you Andreas Weis and
Muzahid Hussain for reporting and related code. #458
- Feature: Add support for subprotocols in Hybi00. Thank you Lukas Obermann
for reporting and a patch. #518
- Feature: Adds `tcp_pre_bind handler` to Asio transport. This allows setting
arbitrary socket options after the listen acceptor has been created but before
the socket bind has been performed. #634 #439 Thank you Gregor Jasny for
the patch.
- Improvement: Better automatic std::chrono feature detection for Visual Studio
- Improvement: Major refactoring to bundled CMake build system. CMake can now be
used to build all of the examples and the test suite. Thank you Thijs Wenker
for a significant portion of this code. #378, #435, #449
- Improvement: In build environments where `lib::error_code` and
`lib::asio::error_code` match (such as using `boost::asio` with
`boost::system_error` or standalone asio with `std::system_error`, transport
errors are passed through natively rather than being reported as a translated
`pass_through` error type.
- Improvement: Add a `get_transport_error` method to Asio transport connections
to allow retrieving a machine readable native transport error.
- Improvement: Add `connection::get_response`, `connection::get_response_code`,
and `connection::get_response_msg` methods to allow accessing additional
information about the HTTP responses that WebSocket++ sends. #465 Thank you
Flow86 for reporting.
- Improvement: Removes use of empty strings ("") in favor of `string::clear()`
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: Begins migration of the web based user manual into Doxygen.
- 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
- Bug: Fix an issue where standalone Asio builds that use TLS would not compile
due to lingering boost code. #448 Thank you mjsp for reporting
- Bug: Fix an issue where canceling a socket could throw an exception on some
older Windows XP platforms. It now prints an appropriate set of log messages
instead. Thank you Thijs Wenker for reporting and researching solutions. #460
- Bug: Fix an issue where deferred HTTP connections that start sending a very
long response before their HTTP handler ends would result in a second set of
HTTP headers being injected into the output. Thank you Kevin Smith for
reporting and providing test case details. #443
- Bug: Fix an issue where the wrong type of strand was being created. Thank you
Bastien Brunnenstein for reporting and a patch. #462
- 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
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.
Fixes #490.
- Bug: Fix a heap buffer overflow when checking very short URIs. Thank you
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.
0.6.0 - 2015-06-02
- MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be
required to include a new method `void set_uri(uri_ptr u)`. An implementation
is not required. The stub transport policy includes an example stub method
+43 -12
View File
@@ -13,11 +13,16 @@ macro (print_used_build_config)
message ("")
message (STATUS "WEBSOCKETPP_BOOST_LIBS = ${WEBSOCKETPP_BOOST_LIBS}")
message (STATUS "WEBSOCKETPP_PLATFORM_LIBS = ${WEBSOCKETPP_PLATFORM_LIBS}")
message (STATUS "WEBSOCKETPP_PLATFORM_TSL_LIBS = ${WEBSOCKETPP_PLATFORM_TSL_LIBS}")
message ("")
message (STATUS "WEBSOCKETPP_PLATFORM_TLS_LIBS = ${WEBSOCKETPP_PLATFORM_TLS_LIBS}")
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 ("")
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)
@@ -34,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 ()
@@ -49,30 +54,56 @@ macro (build_executable TARGET_NAME)
include_directories (${WEBSOCKETPP_ROOT} ${WEBSOCKETPP_INCLUDE})
target_link_libraries(${TARGET_NAME} ${WEBSOCKETPP_PLATFORM_LIBS})
set_target_properties (${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${WEBSOCKETPP_BIN})
set_target_properties (${TARGET_NAME} PROPERTIES DEBUG_POSTFIX d)
endmacro ()
# Build executable and register as test
macro (build_test TARGET_NAME)
build_executable (${TARGET_NAME} ${ARGN})
if (${CMAKE_VERSION} VERSION_LESS 3)
message(WARNING "CMake too old to register ${TARGET_NAME} as a test")
else ()
add_test(NAME ${TARGET_NAME} COMMAND $<TARGET_FILE:${TARGET_NAME}>)
endif ()
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 ()
# install headers, directly from current source dir and look for subfolders with headers
file (GLOB_RECURSE TARGET_INSTALL_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.hpp)
foreach (hppfile ${TARGET_INSTALL_HEADERS})
get_filename_component (currdir ${hppfile} PATH)
install (FILES ${hppfile} DESTINATION "include/${TARGET_NAME}/${currdir}")
endforeach()
install (DIRECTORY ${CMAKE_SOURCE_DIR}/${TARGET_NAME}
DESTINATION include/
FILES_MATCHING PATTERN "*.hpp*")
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)
file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PARENT}/*")
foreach (SUBDIR ${SDIRS})
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt")
add_subdirectory ("${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}")
endif ()
endforeach ()
endmacro()
+138
View File
@@ -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 |
*/
+162
View File
@@ -0,0 +1,162 @@
/** \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 isnt 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 shouldnt 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 cant 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?
Yes. WebSocket++ only uses Boost features as polyfills for C++11 language features and libraries. If you have a C++11 compiler and standard library you can use WebSocket++ without Boost. In most cases setting your build environment to use the C++11 (or later) language dialect is sufficient to enable this mode of use.
With less common compilers (and sometimes very recently release compilers) there may be specific issues with certain libraries that aren't automatically detected by the library. For these situations there are additional defines available to fine tune which C++11 libraries and features are used. TODO: more details about them.
For the iostream/raw transport the C++11 standard library is sufficient. For the Asio based transports, there is no C++11 library that provides the networking capabilaties that Asio does. As such even with a C++11 build system, you will need a standalone copy of Asio to use if Boost Asio is not available.
MinGW users who want to avoid Boost should also consult the nearby question about MinGW compatibility.
### Can WebSocket++ be used with standalone Asio
Yes. The process is the same as used with standalone Asio itself. Define `ASIO_STANDALONE` before including Asio or WebSocket++ headers. You will need to download a copy of the Asio headers separately (http://www.think-async.com) and make sure they are in your build system's include path.
### Can WebSocket++ be used without TLS or OpenSSL?
Yes. When using the iostream/raw transport, there are no TLS features and OpenSSL is not required. When using the Asio transport TLS features are optional. You only need OpenSSL if you want to use TLS. You can only make or recieve encrypted connections (https/wss) if you have enabled TLS features.
Whether an Asio endpoint uses TLS or not is determined by its config template parameter. The default bundled `websocketpp::config::asio` and `websocketpp::config::asio_client` configs do not support TLS, the `websocketpp::config::asio_tls` and `websocketpp::config::asio_tls_client` do.
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.
### Can WebSocket++ be used with MinGW
Generally, yes. Note that in C++11 mode MinGW does not currently support the C++11 STL `<thread>` library. WebSocket++ requires a thread/mutex library. Options include Boost thread (the default when a compatible C++11 `<thread>` can't be found) or `mingw-std-threads` (https://github.com/meganz/mingw-std-threads) by including those headers and defining `_WEBSOCKETPP_MINGW_THREAD_`.
## Compression
### How do I use permessage-deflate in version 0.6.0-permessagedeflate and 0.7.0?
These versions of the library require a custom config to use the permessage-deflate extension. Here is a minimal example of such a custom config. You can also integrate these lines into an existing custom config.
Note that in these versions there is no fine grained control over which connections are compressed or not. Clients will request compression with the default settings and use it if the server supports it. Servers will accept whatever parameters clients request.
Outgoing messages by default will be compressed if compression was auto-negotiated during the handshake. There is an option to force a specific message to be sent uncompressed even if compression was negotiated. This may be useful for sending data that you know to be compressed already (images, zip files, etc).
__Server Example__
```
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_server_config : public websocketpp::config::asio {
// ... additional custom config if you need it for other things
/// permessage_compress extension
struct permessage_deflate_config {};
typedef websocketpp::extensions::permessage_deflate::enabled
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::server<deflate_server_config> server_endpoint_type;
```
__Client Example__
```
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_client_config : public websocketpp::config::asio_client {
// ... additional custom config if you need it for other things
/// permessage_compress extension
struct permessage_deflate_config {};
typedef websocketpp::extensions::permessage_deflate::enabled
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::client<deflate_client_config> client_endpoint_type;
```
## Security
### Is it possible to terminate a malicious connection quickly, without tying up resources performing clean close steps,
Yes. The library will automatically detect and terminate connections that violate the WebSocket protocol. In cases where the library believes the remote endpoint to be malicious or sufficiently broken to be unlikely to understand or process the closing handshake, it will be omited.
If your application detects conditions above the protocol level that you believe to be malicious, for example, if you recognize an IP from a known denial of service attack, you can close the connection with two different levels of urgency. Use the standard `websocketpp::endpoint::close` or `websocketpp::connection::close` methods with one of the following special close codes:
- `websocketpp::close::status::omit_handshake`: Omits the closing handshake, but cleanly closes the TCP connection.
- `websocketpp::close::status::force_tcp_drop`: Forcibly drop the TCP connection.
Please note that usage of these disconnect methods results in a violation of the WebSocket protocol and may have negative reprocusions for the remote endpoint with respect to network timeouts. Please use caution when using them.
## Build Issues
### Getting compile errors related to `std::chrono`, `boost::chrono`, `waitable_timer`, or `steady_clock`
Your build system may be confused about whether it is supposed to be using `boost::chrono` or `std::chrono`. Boost automatically detects this setup on some compilers but not others. Defining `BOOST_ASIO_HAS_STD_CHRONO` can help. See http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/overview/cpp2011/chrono.html for more details.
*/
+27
View File
@@ -0,0 +1,27 @@
/** \page getting_started Getting Started
WebSocket++ code is available on github at https://github.com/zaphoyd/websocketpp
The official project homepage lives at http://www.zaphoyd.com/websocketpp
The git repository is organized into several directories:
- **docs**: This documentation
- **examples**: Example programs that demonstrate how to build basic versions of some commonly used patterns for WebSocket clients and servers.
- **test**: Unit tests that confirm that the code you have works properly and help detect platform specific issues.
- **tutorials**: Detailed walkthroughs of a select set of the example programs.
- **websocketpp**: All of the library code and default configuration files.
WebSocket++ is a header only library. You can start using it by including the websocketpp source directory in your project's include path and including the appropriate WebSocket++ headers in your program. You may also need to include and/or link to appropriate Boost/system libraries. TODO: More information: Building a program with WebSocket++, Walkthroughs of the example programs
WebSocket++ includes cmake and scons scripts for building the examples and unit tests. Neither system is needed unless you want to build tests or examples in an automated fashion.
__Usage questions__ should be posted to the project mailing list at http://groups.google.com/group/websocketpp/ or the IRC channel (\#websocketpp on freenode).
__Bugs and issues__ should be posted to the project GitHub issues queue: https://github.com/zaphoyd/websocketpp/issues.
__Pull requests__ on GitHub are welcome. Please make them against the `develop` branch.
WebSocket++ is written and maintained by Peter Thorson. You can contact me via GitHub messaging, IRC, or via email at websocket@zaphoyd.com.
*/
+165
View File
@@ -0,0 +1,165 @@
/** \page reference.handlers Handler Reference
Handlers allow WebSocket++ programs to receive notifications about events
that happen in relation to their connections. Some handlers also behave as
hooks that give the program a chance to modify state or adjust settings before
the connection continues.
Handlers are registered by calling the appropriate `set_*_handler` method on either an
endpoint or connection. The * refers to the name of the handler (as
specified in the signature field below). For example, to set the open handler,
call `set_open_handler(...)`.
Setting handlers on an endpoint will result in them being copied as the default
handler to all new connections created by that endpoint. Changing an endpoint's
handlers will not affect connections that are already in progress. This includes
connections that are in the listening state. As such, it is important to set any
endpoint handlers before you call `endpoint::start_accept` or else the handlers
will not be attached to your first connection.
Setting handlers on a connection will result in the handler being changed for
that connection only, starting at the next time that handler is called. This can
be used to change the handler during a connection.
Connection Handlers
-------------------
These handlers will be called at most once per connection in the order specified below.
### Socket Init Handler
| Event | Signature | Availability |
| --------------------- | ----------------------------------------------------- | -------------------- |
| Socket initialization | `socket_init(connection_hdl, asio::ip::tcp::socket&)` | 0.3.0 Asio Transport |
This hook is triggered after the socket has been initialized but before a connection is established.
It allows setting arbitrary socket options before connections are sent/recieved.
### TCP Pre-init Handler
| Event | Signature | Availability |
| ----------------------------- | ------------------------------ | -------------------- |
| TCP established, no data sent | `tcp_pre_init(connection_hdl)` | 0.3.0 Asio Transport |
This hook is triggered after the TCP connection is established, but before any pre-WebSocket-handshake
operations have been run. Common pre-handshake operations include TLS handshakes and proxy connections.
### TCP Post-init Handler
| Event | Signature | Availability |
| ----------------------- | ------------------------------------------ | ----------------------------- |
| Request for TLS context | `tls_context_ptr tls_init(connection_hdl)` | 0.3.0 Asio Transport with TLS |
This hook is triggered before the TLS handshake to request the TLS context to use. You must
return a pointer to a configured TLS conext to continue. This provides the opportuinity to
set up the TLS settings, certificates, etc.
### Validate Handler
| Event | Signature | Availability |
| ------------------------------------- | ------------------------------- | ---------------------------- |
| Hook to accept or reject a connection | `bool validate(connection_hdl)` | 0.3.0 Core, Server role only |
This hook is triggered for servers during the opening handshake after the request has been
processed but before the response has been sent. It gives a program the opportunity to inspect
headers and other connection details and either accept or reject the connection. Validate happens
before the open or fail handler.
Return true to accept the connection, false to reject. If no validate handler is registered,
all connections will be accepted.
### Open Connection Handler
| Event | Signature | Availability |
| ------------------------- | ---------------------- | ------------ |
| Successful new connection | `open(connection_hdl)` | 0.3.0 Core |
Either open or fail will be called for each connection. Never both. All
connections that begin with an open handler call will also have a matching
close handler call when the connection ends.
### Fail Connection Handler
| Event | Signature | Availability |
| ----------------------------------- | ---------------------- | ------------ |
| Connection failed (before opening) | `fail(connection_hdl)` | 0.3.0 Core |
Either open or fail will be called for each connection. Never both. Connections
that fail will never have a close handler called.
### Close Connection Handler
| Event | Signature | Availability |
| --------------------------------- | ----------------------- | ------------ |
| Connection closed (after opening) | `close(connection_hdl)` | 0.3.0 Core |
Close will be called exactly once for every connection that open was called for.
Close is not called for failed connections.
Message Handlers
----------------
These handers are called in response to incoming messages or message like events. They only will be called while the connection is in the open state.
### Message Handler
| Event | Signature | Availability |
| --------------------- | -------------------------------------- | ------------ |
| Data message recieved | `message(connection_hdl, message_ptr)` | 0.3.0 Core |
Applies to all non-control messages, including both text and binary opcodes. The
`message_ptr` type and its API depends on your endpoint type and its config.
### Ping Handler
| Event | Signature | Availability |
| ------------- | ---------------------------------------- | ------------ |
| Ping recieved | `bool ping(connection_hdl, std::string)` | 0.3.0 Core |
Second (string) argument is the binary ping payload. Handler return value
indicates whether or not to respond to the ping with a pong. If no ping handler
is set, WebSocket++ will respond with a pong containing the same binary data as
the ping (Per requirements in RFC6455).
### Pong Handler
| Event | Signature | Availability |
| ------------- | ----------------------------------- | ------------ |
| Pong recieved | `pong(connection_hdl, std::string)` | 0.3.0 Core |
Second (string) argument is the binary pong payload.
### Pong Timeout Handler
| Event | Signature | Availability |
| ---------------------------------- | ------------------------------------------- | ---------------------------------------- |
| Timed out while waiting for a pong | `pong_timeout(connection_hdl, std::string)` | 0.3.0 Core, transport with timer support |
Triggered if there is no response to a ping after the configured duration. The second
(string) argument is the binary payload of the unanswered ping.
### HTTP Handler
| Event | Signature | Availability |
| --------------------- | --------------------- | ---------------------------- |
| HTTP request recieved | `http(connection_hdl` | 0.3.0 Core, Server role only |
Called when HTTP requests that are not WebSocket handshake upgrade requests are
recieved. Allows responding to regular HTTP requests. If no handler is registered
a 426/Upgrade Required error is returned.
### Interrupt Handler
| Event | Signature | Availability |
| ----------------------------------- | --------------------------- | ------------ |
| Connection was manually interrupted | `interrupt(connection_hdl)` | 0.3.0 Core |
Interrupt events can be triggered by calling `endpoint::interrupt` or `connection::interrupt`.
Interrupt is similar to a timer event with duration zero but with lower overhead. It is useful
for single threaded programs to allow breaking up a very long handler into multiple parts and
for multi threaded programs as a way for worker threads to signale to the main/network thread
that an event is ready.
todo: write low and high watermark handlers
*/
+102
View File
@@ -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" |
*/
+22
View File
@@ -0,0 +1,22 @@
.tabs, .tabs2, .tabs3, .navpath ul {
background-image: none;
background-color: #333;
border: none;
border-bottom: 1px solid #575757;
}
.tablist li, .navpath li {
background-image: none;
background-color: #333;
}
.tablist a, .navpath li.navelem a {
color: #ccc;
text-shadow: 0px 1px 1px black;
}
.tablist a:hover, .navpath li.navelem a:hover {
background-image: none;
background-color: #444;
color: #ccc;
}
+23
View File
@@ -0,0 +1,23 @@
/** \mainpage
WebSocket++ is a C++ library that can be used to implement WebSocket functionality. The goals of the project are to provide a WebSocket implementation that is portable, flexible, lightweight, low level, and high performance.
WebSocket++ does not intend to be used alone as a web application framework or full featured web services platform. As such the components, examples, and performance tuning are geared towards operation as a WebSocket client or server. There are some minimal convenience features that stray from this (for example the ability to respond to HTTP requests other than WebSocket Upgrades) but these are not the focus of the project. In particular WebSocket++ does not intend to implement any non-WebSocket related fallback options (ajax / long polling / comet / etc).
In order to remain compact and improve portability, the WebSocket++ project strives to reduce or eliminate external dependencies where possible and appropriate. WebSocket++ core has no dependencies other than the C++11 standard library. For non-C++11 compilers the Boost libraries provide drop in polyfills for the C++11 functionality used.
WebSocket++ implements a pluggable data transport component. The default component allows reduced functionality by using STL iostream or raw byte shuffling via reading and writing char buffers. This component has no non-STL dependencies and can be used in a C++11 environment without Boost. Also included is an Asio based transport component that provides full featured network client/server functionality. This component requires either Boost Asio or a C++11 compiler and standalone Asio. As an advanced option, WebSocket++ supports custom transport layers if you want to provide your own using another library.
In order to accommodate the wide variety of use cases WebSocket++ has collected, the library is built in a way that most of the major components are loosely coupled and can be swapped out and replaced. WebSocket++ will attempt to track the future development of the WebSocket protocol and any extensions as they are developed.
- \subpage getting_started "Getting Started"
- \subpage faq "FAQ"
- \subpage tutorials "Tutorials"
- \subpage md_changelog "Change Log / Version History"
- Reference
- \subpage reference.handlers "Handler Reference"
- \subpage reference.config "Config Reference"
- \subpage reference.logging "Logging Reference"
*/
+10
View File
@@ -0,0 +1,10 @@
/** \page tutorials Tutorials
These tutorials are works in progress, some are more complete than others.
- \subpage md_tutorials_utility_client_utility_client
- \subpage md_tutorials_utility_server_utility_server
- \subpage md_tutorials_broadcast_tutorial_broadcast_tutorial
- \subpage md_tutorials_chat_tutorial_chat_tutorial
*/
-6
View File
@@ -1,6 +0,0 @@
file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
foreach (SUBDIR ${SDIRS})
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt")
add_subdirectory (${SUBDIR})
endif ()
endforeach ()
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (associative_storage)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
@@ -30,7 +30,7 @@ public:
connection_data data;
data.sessionid = m_next_sessionid++;
data.name = "";
data.name.clear();
m_connections[hdl] = data;
}
@@ -47,7 +47,7 @@ public:
void on_message(connection_hdl hdl, server::message_ptr msg) {
connection_data& data = get_data_from_hdl(hdl);
if (data.name == "") {
if (data.name.empty()) {
data.name = msg->get_payload();
std::cout << "Setting name of connection with sessionid "
<< data.sessionid << " to " << data.name << std::endl;
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (broadcast_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+19 -15
View File
@@ -19,6 +19,7 @@ using websocketpp::lib::bind;
using websocketpp::lib::thread;
using websocketpp::lib::mutex;
using websocketpp::lib::lock_guard;
using websocketpp::lib::unique_lock;
using websocketpp::lib::condition_variable;
@@ -71,27 +72,30 @@ public:
}
void on_open(connection_hdl hdl) {
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_open" << std::endl;
m_actions.push(action(SUBSCRIBE,hdl));
lock.unlock();
{
lock_guard<mutex> guard(m_action_lock);
//std::cout << "on_open" << std::endl;
m_actions.push(action(SUBSCRIBE,hdl));
}
m_action_cond.notify_one();
}
void on_close(connection_hdl hdl) {
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_close" << std::endl;
m_actions.push(action(UNSUBSCRIBE,hdl));
lock.unlock();
{
lock_guard<mutex> guard(m_action_lock);
//std::cout << "on_close" << std::endl;
m_actions.push(action(UNSUBSCRIBE,hdl));
}
m_action_cond.notify_one();
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
// queue message up for sending by processing thread
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_message" << std::endl;
m_actions.push(action(MESSAGE,hdl,msg));
lock.unlock();
{
lock_guard<mutex> guard(m_action_lock);
//std::cout << "on_message" << std::endl;
m_actions.push(action(MESSAGE,hdl,msg));
}
m_action_cond.notify_one();
}
@@ -109,13 +113,13 @@ public:
lock.unlock();
if (a.type == SUBSCRIBE) {
unique_lock<mutex> con_lock(m_connection_lock);
lock_guard<mutex> guard(m_connection_lock);
m_connections.insert(a.hdl);
} else if (a.type == UNSUBSCRIBE) {
unique_lock<mutex> con_lock(m_connection_lock);
lock_guard<mutex> guard(m_connection_lock);
m_connections.erase(a.hdl);
} else if (a.type == MESSAGE) {
unique_lock<mutex> con_lock(m_connection_lock);
lock_guard<mutex> guard(m_connection_lock);
con_list::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
+17
View File
@@ -0,0 +1,17 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
if (OPENSSL_FOUND)
init_target (debug_client)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
endif()
+4 -3
View File
@@ -76,6 +76,7 @@ public:
if (ec) {
m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message());
return;
}
//con->set_proxy("http://humupdates.uchicago.edu:8443");
@@ -156,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;
}
+2
View File
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+5 -5
View File
@@ -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;
}
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
#init_target (dev)
#build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
#link_boost ()
#final_target ()
#set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+1 -1
View File
@@ -179,7 +179,7 @@ int main() {
//foo.handle_accept(con,true);
std::stringstream input;
input << "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
input << "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
//input << "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
input >> *con;
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (echo_client)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+23
View File
@@ -0,0 +1,23 @@
## echo_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] + ['z']
prgs += env_cpp11.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + ['z']
prgs += env.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+97
View File
@@ -0,0 +1,97 @@
/*
* 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;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
// This message handler will be invoked once for each incoming message. It
// prints the message and then sends a copy of the message back to the server.
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
websocketpp::lib::error_code ec;
c->send(hdl, msg->get_payload(), msg->get_opcode(), ec);
if (ec) {
std::cout << "Echo failed because: " << ec.message() << std::endl;
}
}
int main(int argc, char* argv[]) {
// Create a client endpoint
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);
// Initialize ASIO
c.init_asio();
// Register our message handler
c.set_message_handler(bind(&on_message,&c,::_1,::_2));
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;
}
}
+2
View File
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+4 -4
View File
@@ -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;
}
}
@@ -43,7 +43,7 @@ int main() {
echo_server.set_access_channels(websocketpp::log::alevel::all);
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize ASIO
// Initialize Asio
echo_server.init_asio();
// Register our message handler
+3
View File
@@ -12,4 +12,7 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
endif()
@@ -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;
}
}
+3
View File
@@ -12,4 +12,7 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
endif()
+54 -15
View File
@@ -1,3 +1,39 @@
/*
* Copyright (c) 2015, 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.
*
*/
/**
* NOTES
*
* This example uses a number of standard classes through the websocketpp::lib
* namespace. This is to allow easy switching between Boost, the C++11 STL, and
* the standalone Asio library. Your program need not use these namespaces if
* you do not need this sort of flexibility.
*/
#include <websocketpp/config/asio.hpp>
#include <websocketpp/server.hpp>
@@ -12,7 +48,7 @@ using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef websocketpp::config::asio::message_type::ptr message_ptr;
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
std::cout << "on_message called with hdl: " << hdl.lock().get()
@@ -21,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;
}
}
@@ -46,27 +82,30 @@ enum tls_mode {
};
context_ptr on_tls_init(tls_mode mode, websocketpp::connection_hdl hdl) {
namespace asio = websocketpp::lib::asio;
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
std::cout << "using TLS mode: " << (mode == MOZILLA_MODERN ? "Mozilla Modern" : "Mozilla Intermediate") << std::endl;
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
context_ptr ctx = websocketpp::lib::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
try {
if (mode == MOZILLA_MODERN) {
// Modern disables TLSv1
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::no_tlsv1 |
boost::asio::ssl::context::single_dh_use);
ctx->set_options(asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::no_sslv3 |
asio::ssl::context::no_tlsv1 |
asio::ssl::context::single_dh_use);
} else {
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_options(asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::no_sslv3 |
asio::ssl::context::single_dh_use);
}
ctx->set_password_callback(bind(&get_password));
ctx->use_certificate_chain_file("server.pem");
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
ctx->use_private_key_file("server.pem", asio::ssl::context::pem);
// Example method of generating this file:
// `openssl dhparam -out dh.pem 2048`
+55 -53
View File
@@ -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-----
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (enriched_storage)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
@@ -61,7 +61,7 @@ public:
void on_message(connection_hdl hdl, server::message_ptr msg) {
connection_ptr con = m_server.get_con_from_hdl(hdl);
if (con->name == "") {
if (con->name.empty()) {
con->name = msg->get_payload();
std::cout << "Setting name of connection with sessionid "
<< con->sessionid << " to " << con->name << std::endl;
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (external_io_service)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+23
View File
@@ -0,0 +1,23 @@
## Main development 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('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2015, 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 "tcp_echo_server.hpp"
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef websocketpp::server<websocketpp::config::asio> ws_echo_server;
// Define a callback to handle incoming messages
void on_message(ws_echo_server* s, websocketpp::connection_hdl hdl, ws_echo_server::message_ptr msg) {
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
// check for a special command to instruct the server to stop listening so
// it can be cleanly exited.
if (msg->get_payload() == "stop-listening") {
s->stop_listening();
return;
}
try {
s->send(hdl, msg->get_payload(), msg->get_opcode());
} catch (websocketpp::exception const & e) {
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
}
int main() {
asio::io_service service;
// Add a TCP echo server on port 9003
tcp_echo_server custom_http_server(service, 9003);
// Add a WebSocket echo server on port 9002
ws_echo_server ws_server;
ws_server.set_access_channels(websocketpp::log::alevel::all);
ws_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// The only difference in this code between an internal and external
// io_service is the different constructor to init_asio
ws_server.init_asio(&service);
// Register our message handler
ws_server.set_message_handler(bind(&on_message,&ws_server,::_1,::_2));
ws_server.listen(9002);
ws_server.start_accept();
// TODO: add a timer?
// Start the Asio io_service run loop for all
service.run();
}
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, 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.
*/
/**
* TCP Echo Server
*
* This file defines a simple TCP Echo Server. It is adapted from the Asio
* example: cpp03/echo/async_tcp_echo_server.cpp
*/
#include <websocketpp/common/asio.hpp>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/common/functional.hpp>
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
namespace asio = websocketpp::lib::asio;
struct tcp_echo_session : websocketpp::lib::enable_shared_from_this<tcp_echo_session> {
typedef websocketpp::lib::shared_ptr<tcp_echo_session> ptr;
tcp_echo_session(asio::io_service & service) : m_socket(service) {}
void start() {
m_socket.async_read_some(asio::buffer(m_buffer, sizeof(m_buffer)),
websocketpp::lib::bind(
&tcp_echo_session::handle_read, shared_from_this(), _1, _2));
}
void handle_read(const asio::error_code & ec, size_t transferred) {
if (!ec) {
asio::async_write(m_socket,
asio::buffer(m_buffer, transferred),
bind(&tcp_echo_session::handle_write, shared_from_this(), _1));
}
}
void handle_write(const asio::error_code & ec) {
if (!ec) {
m_socket.async_read_some(asio::buffer(m_buffer, sizeof(m_buffer)),
bind(&tcp_echo_session::handle_read, shared_from_this(), _1, _2));
}
}
asio::ip::tcp::socket m_socket;
char m_buffer[1024];
};
struct tcp_echo_server {
tcp_echo_server(asio::io_service & service, short port)
: m_service(service)
, m_acceptor(service, asio::ip::tcp::endpoint(asio::ip::tcp::v6(), port))
{
this->start_accept();
}
void start_accept() {
tcp_echo_session::ptr new_session(new tcp_echo_session(m_service));
m_acceptor.async_accept(new_session->m_socket,
bind(&tcp_echo_server::handle_accept, this, new_session, _1));
}
void handle_accept(tcp_echo_session::ptr new_session, const asio::error_code & ec) {
if (!ec) {
new_session->start();
}
start_accept();
}
asio::io_service & m_service;
asio::ip::tcp::acceptor m_acceptor;
};
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (handler_switch)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (iostream_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+2 -2
View File
@@ -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());
}
}
+12
View File
@@ -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")
+23
View File
@@ -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')
+78
View File
@@ -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;
}
}
+17
View File
@@ -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()
+24
View File
@@ -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;
}
}
+2
View File
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+1 -1
View File
@@ -246,7 +246,7 @@ int main() {
std::string cmd;
int id;
int close_code = websocketpp::close::status::normal;
std::string reason = "";
std::string reason;
ss >> cmd >> id >> close_code;
std::getline(ss,reason);
+5 -5
View File
@@ -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;
}
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (simple_broadcast_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+1
View File
@@ -9,3 +9,4 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+1 -1
View File
@@ -12,7 +12,7 @@ env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is avaliable build using that, otherwise use boost
# 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('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (subprotocol_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+2
View File
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
+13 -2
View File
@@ -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:
+2
View File
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
@@ -32,7 +32,6 @@ class telemetry_server {
public:
typedef websocketpp::connection_hdl connection_hdl;
typedef websocketpp::server<websocketpp::config::asio> server;
typedef websocketpp::lib::lock_guard<websocketpp::lib::mutex> scoped_lock;
telemetry_server() : m_count(0) {
// set up access channels to only log interesting things
@@ -112,7 +111,7 @@ public:
server::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
std::ifstream file;
std::string filename = con->get_uri()->get_resource();
std::string filename = con->get_resource();
std::string response;
m_endpoint.get_alog().write(websocketpp::log::alevel::app,
@@ -201,4 +200,4 @@ int main(int argc, char* argv[]) {
s.run(docroot, port);
return 0;
}
}
+6
View File
@@ -2,10 +2,16 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
if (ZLIB_FOUND)
init_target (testee_client)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_zlib()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
endif()
+17
View File
@@ -0,0 +1,17 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
if (ZLIB_FOUND)
init_target (testee_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_zlib()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
endif()
+8 -18
View File
@@ -1,23 +1,13 @@
## Utility client example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
init_target (utility_client)
prgs = []
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
# 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('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
Return('prgs')
+18 -6
View File
@@ -1,11 +1,23 @@
## Utility client example
##
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
init_target (utility_client)
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
prgs = []
link_boost ()
final_target ()
# 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('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+2 -2
View File
@@ -289,7 +289,7 @@ int main() {
std::string cmd;
int id;
std::string message = "";
std::string message;
ss >> cmd >> id;
std::getline(ss,message);
@@ -301,7 +301,7 @@ int main() {
std::string cmd;
int id;
int close_code = websocketpp::close::status::normal;
std::string reason = "";
std::string reason;
ss >> cmd >> id >> close_code;
std::getline(ss,reason);
+2 -2
View File
@@ -1,4 +1,4 @@
WebSocket++ (0.6.0)
WebSocket++ (0.8.1)
==========================
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/
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (test_connection)
build_test (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+60 -52
View File
@@ -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;
};
@@ -159,12 +162,17 @@ bool validate_set_ua(server* s, websocketpp::connection_hdl hdl) {
}
void http_func(server* s, websocketpp::connection_hdl hdl) {
using namespace websocketpp::http;
server::connection_ptr con = s->get_con_from_hdl(hdl);
std::string res = con->get_resource();
con->set_body(res);
con->set_status(websocketpp::http::status_code::ok);
con->set_status(status_code::ok);
BOOST_CHECK_EQUAL(con->get_response_code(), status_code::ok);
BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok));
}
void defer_http_func(server* s, bool * deferred, websocketpp::connection_hdl hdl) {
@@ -209,8 +217,8 @@ BOOST_AUTO_TEST_CASE( connection_extensions ) {
}
BOOST_AUTO_TEST_CASE( basic_websocket_request ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: ";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: ";
output+=websocketpp::user_agent;
output+="\r\nUpgrade: websocket\r\n\r\n";
@@ -271,8 +279,8 @@ BOOST_AUTO_TEST_CASE( deferred_http_request ) {
}
BOOST_AUTO_TEST_CASE( request_no_server_header ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nUpgrade: websocket\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nUpgrade: websocket\r\n\r\n";
server s;
s.set_user_agent("");
@@ -282,8 +290,8 @@ BOOST_AUTO_TEST_CASE( request_no_server_header ) {
}
BOOST_AUTO_TEST_CASE( request_no_server_header_override ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
server s;
s.set_user_agent("");
@@ -296,7 +304,7 @@ BOOST_AUTO_TEST_CASE( request_no_server_header_override ) {
BOOST_AUTO_TEST_CASE( basic_client_websocket ) {
std::string uri = "ws://localhost";
//std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
//std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
std::string ref = "GET / HTTP/1.1\r\nConnection: Upgrade\r\nFoo: Bar\r\nHost: localhost\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\nSec-WebSocket-Version: 13\r\nUpgrade: websocket\r\nUser-Agent: foo\r\n\r\n";
@@ -318,13 +326,13 @@ BOOST_AUTO_TEST_CASE( basic_client_websocket ) {
}
BOOST_AUTO_TEST_CASE( set_max_message_size ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
// After the handshake, add a single frame with a message that is too long.
char frame0[10] = {char(0x82), char(0x83), 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
input.append(frame0, 10);
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
// After the handshake, add a single frame with a close message with message too big
// error code.
@@ -353,7 +361,7 @@ BOOST_AUTO_TEST_CASE( websocket_fail_parse_error ) {
}
BOOST_AUTO_TEST_CASE( websocket_fail_invalid_version ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: foo\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: foo\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
server s;
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::invalid_version);
@@ -365,7 +373,7 @@ BOOST_AUTO_TEST_CASE( websocket_fail_invalid_version ) {
}
BOOST_AUTO_TEST_CASE( websocket_fail_unsupported_version ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 12\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 12\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
server s;
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::unsupported_version);
@@ -376,31 +384,31 @@ BOOST_AUTO_TEST_CASE( websocket_fail_unsupported_version ) {
BOOST_CHECK(called);
}
/*BOOST_AUTO_TEST_CASE( websocket_fail_invalid_uri ) {
std::string input = "GET http://345.123.123.123/foo HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
// BOOST_AUTO_TEST_CASE( websocket_fail_invalid_uri ) {
// std::string input = "GET http://345.123.123.123/foo HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
server s;
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::unsupported_version);
bool called = false;
s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
s.set_open_handler(bind(&on_open_print,&s,::_1));
// server s;
// websocketpp::lib::error_code ec = make_error_code(websocketpp::error::unsupported_version);
// bool called = false;
// s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
// s.set_open_handler(bind(&on_open_print,&s,::_1));
std::cout << run_server_test(s,input,true) << std::endl;
BOOST_CHECK(called);
}
// std::cout << run_server_test(s,input,true) << std::endl;
// BOOST_CHECK(called);
// }
BOOST_AUTO_TEST_CASE( websocket_fail_invalid_uri_http ) {
std::string input = "GET http://345.123.123.123/foo HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
// BOOST_AUTO_TEST_CASE( websocket_fail_invalid_uri_http ) {
// std::string input = "GET http://345.123.123.123/foo HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
server s;
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::unsupported_version);
bool called = false;
s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
s.set_open_handler(bind(&on_open_print,&s,::_1));
// server s;
// websocketpp::lib::error_code ec = make_error_code(websocketpp::error::unsupported_version);
// bool called = false;
// s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
// s.set_open_handler(bind(&on_open_print,&s,::_1));
std::cout << run_server_test(s,input,true) << std::endl;
BOOST_CHECK(called);
}*/
// std::cout << run_server_test(s,input,true) << std::endl;
// BOOST_CHECK(called);
// }
BOOST_AUTO_TEST_CASE( websocket_fail_upgrade_required ) {
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
@@ -418,26 +426,26 @@ BOOST_AUTO_TEST_CASE( websocket_fail_upgrade_required ) {
// TODO: set max message size mid connection test case
// TODO: [maybe] set max message size in open handler
/*
BOOST_AUTO_TEST_CASE( user_reject_origin ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example2.com\r\n\r\n";
std::string output = "HTTP/1.1 403 Forbidden\r\nServer: "+websocketpp::USER_AGENT+"\r\n\r\n";
BOOST_CHECK(run_server_test(input) == output);
}
// BOOST_AUTO_TEST_CASE( user_reject_origin ) {
// std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example2.com\r\n\r\n";
// std::string output = "HTTP/1.1 403 Forbidden\r\nServer: "+websocketpp::USER_AGENT+"\r\n\r\n";
BOOST_AUTO_TEST_CASE( basic_text_message ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
// BOOST_CHECK(run_server_test(input) == output);
// }
unsigned char frames[8] = {0x82,0x82,0xFF,0xFF,0xFF,0xFF,0xD5,0xD5};
input.append(reinterpret_cast<char*>(frames),8);
// BOOST_AUTO_TEST_CASE( basic_text_message ) {
// std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: "+websocketpp::USER_AGENT+"\r\nUpgrade: websocket\r\n\r\n**";
// unsigned char frames[8] = {0x82,0x82,0xFF,0xFF,0xFF,0xFF,0xD5,0xD5};
// input.append(reinterpret_cast<char*>(frames),8);
// std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: "+websocketpp::USER_AGENT+"\r\nUpgrade: websocket\r\n\r\n**";
// BOOST_CHECK( run_server_test(input) == output);
// }
BOOST_CHECK( run_server_test(input) == output);
}
*/
@@ -473,7 +481,7 @@ BOOST_AUTO_TEST_CASE( client_handshake_timeout_race2 ) {
BOOST_CHECK(!ec);
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: ICX+Yqv66kxgM0FcWaLWlFLwTAI=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ICX+Yqv66kxgM0FcWaLWlFLwTAI=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n";
// This test the case where a handshake times out immediately before the
// handler that would have completed it gets invoked. This situation happens
@@ -493,7 +501,7 @@ BOOST_AUTO_TEST_CASE( client_handshake_timeout_race2 ) {
BOOST_AUTO_TEST_CASE( server_handshake_timeout_race1 ) {
debug_server s;
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\n\r\n";
debug_server::connection_ptr con = s.get_connection();
con->start();
@@ -508,7 +516,7 @@ BOOST_AUTO_TEST_CASE( server_handshake_timeout_race1 ) {
BOOST_AUTO_TEST_CASE( server_handshake_timeout_race2 ) {
debug_server s;
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\n\r\n";
debug_server::connection_ptr con = s.get_connection();
con->start();
+17
View File
@@ -0,0 +1,17 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
if (OPENSSL_FOUND)
init_target (test_endpoint)
build_test (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
link_openssl ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
endif()
+4 -1
View File
@@ -147,8 +147,11 @@ BOOST_AUTO_TEST_CASE( listen_after_listen_failure ) {
server1.listen(ep1, ec);
BOOST_CHECK(!ec);
// This should return some sort of problem. Usually either "pass through" or
// a more specific address in use error. It is hard to capture the full range
// of 'correctly wrong' values.
server2.listen(ep1, ec);
BOOST_REQUIRE_EQUAL(ec, make_error_code(pass_through));
BOOST_REQUIRE(ec);
server2.listen(ep2, ec);
BOOST_CHECK(!ec);
+22
View File
@@ -0,0 +1,22 @@
# Extension Tests
file (GLOB SOURCE extension.cpp)
init_target (test_extension)
build_executable (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
if ( ZLIB_FOUND )
# Permessage-deflate tests
file (GLOB SOURCE permessage_deflate.cpp)
init_target (test_permessage_deflate)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_zlib()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
endif ( ZLIB_FOUND )
+152 -49
View File
@@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_invalid ) {
BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_invalid ) {
BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover ) {
ext_vars v;
v.attr["client_no_context_takeover"] = "";
v.attr["client_no_context_takeover"].clear();
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
@@ -186,15 +186,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_invalid ) {
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_valid ) {
ext_vars v;
// confirm that a request for a value of 8 is interpreted as 9
v.attr["server_max_window_bits"] = "8";
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
v.attr["server_max_window_bits"] = "9";
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
v.attr["server_max_window_bits"] = "15";
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
@@ -213,7 +220,7 @@ BOOST_AUTO_TEST_CASE( invalid_set_server_max_window_bits ) {
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) {
ext_vars v;
v.attr["server_max_window_bits"] = "8";
v.attr["server_max_window_bits"] = "9";
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::decline);
v.esp = v.exts.negotiate(v.attr);
@@ -223,7 +230,7 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) {
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept_8 ) {
ext_vars v;
v.attr["server_max_window_bits"] = "8";
@@ -232,10 +239,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
ext_vars v;
v.attr["server_max_window_bits"] = "9";
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::accept);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest_8 ) {
ext_vars v;
v.attr["server_max_window_bits"] = "8";
@@ -244,10 +263,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
ext_vars v;
v.attr["server_max_window_bits"] = "9";
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::largest);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest_8 ) {
ext_vars v;
v.attr["server_max_window_bits"] = "8";
@@ -256,7 +287,19 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
ext_vars v;
v.attr["server_max_window_bits"] = "9";
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::smallest);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
}
// Negotiate server_max_window_bits
@@ -282,7 +325,7 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_invalid ) {
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) {
ext_vars v;
v.attr["client_max_window_bits"] = "";
v.attr["client_max_window_bits"].clear();
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
@@ -292,7 +335,13 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) {
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
v.attr["client_max_window_bits"] = "9";
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
v.attr["client_max_window_bits"] = "15";
v.esp = v.exts.negotiate(v.attr);
@@ -311,7 +360,7 @@ BOOST_AUTO_TEST_CASE( invalid_set_client_max_window_bits ) {
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline_8 ) {
ext_vars v;
v.attr["client_max_window_bits"] = "8";
@@ -323,7 +372,19 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
ext_vars v;
v.attr["client_max_window_bits"] = "9";
v.ec = v.exts.set_client_max_window_bits(9,pmd_mode::decline);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept_8 ) {
ext_vars v;
v.attr["client_max_window_bits"] = "8";
@@ -332,10 +393,22 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
ext_vars v;
v.attr["client_max_window_bits"] = "9";
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::accept);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest_8 ) {
ext_vars v;
v.attr["client_max_window_bits"] = "8";
@@ -344,10 +417,22 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
ext_vars v;
v.attr["client_max_window_bits"] = "9";
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::largest);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest_8 ) {
ext_vars v;
v.attr["client_max_window_bits"] = "8";
@@ -356,7 +441,19 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
ext_vars v;
v.attr["client_max_window_bits"] = "9";
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::smallest);
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
}
@@ -364,8 +461,8 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["client_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["client_no_context_takeover"].clear();
v.esp = v.exts.negotiate(v.attr);
BOOST_CHECK( v.exts.is_enabled() );
@@ -376,7 +473,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) {
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -388,7 +485,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) {
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["client_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -400,7 +497,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) {
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) {
ext_vars v;
v.attr["client_no_context_takeover"] = "";
v.attr["client_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -412,7 +509,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) {
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated5 ) {
ext_vars v;
v.attr["client_no_context_takeover"] = "";
v.attr["client_no_context_takeover"].clear();
v.attr["client_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -436,8 +533,8 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated6 ) {
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["client_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["client_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -449,8 +546,8 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) {
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["client_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["client_no_context_takeover"].clear();
v.attr["client_max_window_bits"] = "10";
v.esp = v.exts.negotiate(v.attr);
@@ -462,7 +559,7 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) {
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.attr["client_max_window_bits"] = "10";
@@ -475,7 +572,7 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) {
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) {
ext_vars v;
v.attr["client_no_context_takeover"] = "";
v.attr["client_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.attr["client_max_window_bits"] = "10";
@@ -488,8 +585,8 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) {
BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) {
ext_vars v;
v.attr["server_no_context_takeover"] = "";
v.attr["client_no_context_takeover"] = "";
v.attr["server_no_context_takeover"].clear();
v.attr["client_no_context_takeover"].clear();
v.attr["server_max_window_bits"] = "10";
v.attr["client_max_window_bits"] = "10";
@@ -507,7 +604,8 @@ BOOST_AUTO_TEST_CASE( compress_data ) {
std::string compress_out;
std::string decompress_out;
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.compress(compress_in,compress_out);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
@@ -520,7 +618,8 @@ BOOST_AUTO_TEST_CASE( compress_data ) {
BOOST_AUTO_TEST_CASE( compress_data_multiple ) {
ext_vars v;
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
for (int i = 0; i < 2; i++) {
std::string compress_in = "Hello";
@@ -545,11 +644,12 @@ BOOST_AUTO_TEST_CASE( compress_data_large ) {
websocketpp::http::attribute_list alist;
alist["server_max_window_bits"] = "8";
v.exts.set_server_max_window_bits(8,websocketpp::extensions::permessage_deflate::mode::smallest);
alist["server_max_window_bits"] = "9";
v.exts.set_server_max_window_bits(9,websocketpp::extensions::permessage_deflate::mode::smallest);
v.exts.negotiate(alist);
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.compress(compress_in,compress_out);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
@@ -569,11 +669,12 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) {
websocketpp::http::attribute_list alist;
alist["server_no_context_takeover"] = "";
alist["server_no_context_takeover"].clear();
v.exts.enable_server_no_context_takeover();
v.exts.negotiate(alist);
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.compress(compress_in,compress_out1);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
@@ -586,7 +687,7 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) {
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
BOOST_CHECK_EQUAL( compress_in, decompress_out );
decompress_out = "";
decompress_out.clear();
v.ec = v.exts.compress(compress_in,compress_out2);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
@@ -605,19 +706,20 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) {
BOOST_AUTO_TEST_CASE( compress_empty ) {
ext_vars v;
std::string compress_in = "";
std::string compress_in;
std::string compress_out;
std::string decompress_out;
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.compress(compress_in,compress_out);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.decompress(reinterpret_cast<const uint8_t *>(compress_out.data()),compress_out.size(),decompress_out);
compress_out = "";
decompress_out = "";
compress_out.clear();
decompress_out.clear();
v.ec = v.exts.compress(compress_in,compress_out);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
@@ -637,10 +739,11 @@ BOOST_AUTO_TEST_CASE( decompress_data ) {
ext_vars v;
uint8_t in[11] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff};
std::string out = "";
std::string out;
std::string reference = "Hello";
v.exts.init(true);
v.ec = v.exts.init(true);
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
v.ec = v.exts.decompress(in,11,out);
+11
View File
@@ -0,0 +1,11 @@
file (GLOB SOURCE_FILES parser.cpp)
init_target (test_http)
build_test (${TARGET_NAME} ${SOURCE_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+21 -7
View File
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE( extract_token ) {
BOOST_CHECK( ret.second == d1.begin()+3 );
ret = websocketpp::http::parser::extract_token(d2.begin(),d2.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.first.empty() );
BOOST_CHECK( ret.second == d2.begin()+0 );
ret = websocketpp::http::parser::extract_token(d2.begin()+1,d2.end());
@@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE( extract_quoted_string ) {
std::string d1 = "\"foo\"";
std::string d2 = "\"foo\\\"bar\\\"baz\"";
std::string d3 = "\"foo\" ";
std::string d4 = "";
std::string d4;
std::string d5 = "foo";
std::pair<std::string,std::string::const_iterator> ret;
@@ -147,11 +147,11 @@ BOOST_AUTO_TEST_CASE( extract_quoted_string ) {
BOOST_CHECK( ret.second == d3.begin()+5 );
ret = extract_quoted_string(d4.begin(),d4.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.first.empty() );
BOOST_CHECK( ret.second == d4.begin() );
ret = extract_quoted_string(d5.begin(),d5.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.first.empty() );
BOOST_CHECK( ret.second == d5.begin() );
}
@@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE( extract_all_lws ) {
}
BOOST_AUTO_TEST_CASE( extract_attributes_blank ) {
std::string s = "";
std::string s;
websocketpp::http::attribute_list a;
std::string::const_iterator it;
@@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE( extract_attributes_simple ) {
}
BOOST_AUTO_TEST_CASE( extract_parameters ) {
std::string s1 = "";
std::string s1;
std::string s2 = "foo";
std::string s3 = " foo \r\nAbc";
std::string s4 = " \r\n foo ";
@@ -365,6 +365,7 @@ BOOST_AUTO_TEST_CASE( strip_lws ) {
std::string test6 = " \r\n foo ";
std::string test7 = " \t foo ";
std::string test8 = " \t ";
std::string test9 = " \n\r";
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test1), "foo" );
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test2), "foo" );
@@ -374,6 +375,7 @@ BOOST_AUTO_TEST_CASE( strip_lws ) {
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test6), "foo" );
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test7), "foo" );
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test8), "" );
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test9), "" );
}
BOOST_AUTO_TEST_CASE( case_insensitive_headers ) {
@@ -408,7 +410,7 @@ BOOST_AUTO_TEST_CASE( case_insensitive_headers_overwrite ) {
BOOST_AUTO_TEST_CASE( blank_consume ) {
websocketpp::http::parser::request r;
std::string raw = "";
std::string raw;
bool exception = false;
@@ -504,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 ) {
+12
View File
@@ -0,0 +1,12 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (test_logger)
build_test (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+17
View File
@@ -0,0 +1,17 @@
# Test alloc message buffer strategy
file (GLOB SOURCE alloc.cpp)
init_target (test_message_alloc)
build_executable (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test message buffers
file (GLOB SOURCE message.cpp)
init_target (test_message_buffer)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+6 -6
View File
@@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
websocketpp::http::parser::response response;
websocketpp::processor::hybi00<websocketpp::http::parser::request,websocketpp::http::parser::response> p(false);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","WjN}|M(6");
@@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
websocketpp::http::parser::request r;
websocketpp::processor::hybi00<websocketpp::http::parser::request,websocketpp::http::parser::response> p(false);
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
websocketpp::http::parser::request r;
websocketpp::processor::hybi00<websocketpp::http::parser::request,websocketpp::http::parser::response> p(false);
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
websocketpp::http::parser::request r;
websocketpp::processor::hybi00<websocketpp::http::parser::request,websocketpp::http::parser::response> p(false);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
websocketpp::http::parser::request r;
websocketpp::processor::hybi00<websocketpp::http::parser::request,websocketpp::http::parser::response> p(false);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
websocketpp::uri_ptr u;
bool exception = false;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
r.replace_header("Sec-WebSocket-Key3","janelle!");
+59
View File
@@ -0,0 +1,59 @@
# Generic processor tests
file (GLOB SOURCE processor.cpp)
init_target (test_processor)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Hybi00 processor tests
file (GLOB SOURCE hybi00.cpp)
init_target (test_processor_hybi00)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Hybi07 processor tests
file (GLOB SOURCE hybi07.cpp)
init_target (test_processor_hybi07)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Hybi08 processor tests
file (GLOB SOURCE hybi08.cpp)
init_target (test_processor_hybi08)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
if (ZLIB_FOUND)
# Hybi13 processor tests
file (GLOB SOURCE hybi13.cpp)
init_target (test_processor_hybi13)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_zlib()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Permessage compression extension processor tests
file (GLOB SOURCE extension_permessage_compress.cpp)
init_target (test_processor_extension_permessage_compress)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_zlib()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
endif ( ZLIB_FOUND )
@@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) {
<< websocketpp::utility::to_hex(test_out,test_out_size) << std::endl;
std::string input = "Hello";
std::string output = "";
std::string output;
ec = de.compress(input,output);
BOOST_CHECK( ec == processor::extensions::error::uninitialized );
@@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) {
<< websocketpp::utility::to_hex(input) << std::endl
<< websocketpp::utility::to_hex(output) << std::endl;
output = "";
output.clear();
ec = de.compress(input,output);
std::cout << ec.message() << std::endl
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) {
<< websocketpp::utility::to_hex(output) << std::endl;
input = output;
output = "";
output.clear();
ec = de.decompress(input,output);
std::cout << ec.message() << std::endl
<< websocketpp::utility::to_hex(input) << std::endl
+6 -6
View File
@@ -66,7 +66,7 @@ typedef stub_config::message_type::ptr message_ptr;
BOOST_AUTO_TEST_CASE( exact_match ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","WjN}|M(6");
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
BOOST_AUTO_TEST_CASE( non_get_method ) {
processor_setup env(true);
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
BOOST_AUTO_TEST_CASE( old_http_version ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","janelle!");
@@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
processor_setup env(true);
websocketpp::uri_ptr u;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
env.req.replace_header("Sec-WebSocket-Key3","janelle!");
+7 -7
View File
@@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
p.process_handshake(r,"",response);
BOOST_CHECK_EQUAL(response.get_header("Connection"), "upgrade");
BOOST_CHECK_EQUAL(response.get_header("Connection"), "Upgrade");
BOOST_CHECK_EQUAL(response.get_header("Upgrade"), "websocket");
BOOST_CHECK_EQUAL(response.get_header("Sec-WebSocket-Accept"), "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
}
@@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -180,7 +180,7 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 7\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
+7 -7
View File
@@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
p.process_handshake(r,"",response);
BOOST_CHECK(response.get_header("Connection") == "upgrade");
BOOST_CHECK(response.get_header("Connection") == "Upgrade");
BOOST_CHECK(response.get_header("Upgrade") == "websocket");
BOOST_CHECK(response.get_header("Sec-WebSocket-Accept") == "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
}
@@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
websocketpp::uri_ptr u;
websocketpp::lib::error_code ec;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Key: foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
+7 -7
View File
@@ -120,7 +120,7 @@ struct processor_setup_ext {
BOOST_AUTO_TEST_CASE( exact_match ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
@@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
env.p.process_handshake(env.req,"",env.res);
BOOST_CHECK_EQUAL(env.res.get_header("Connection"), "upgrade");
BOOST_CHECK_EQUAL(env.res.get_header("Connection"), "Upgrade");
BOOST_CHECK_EQUAL(env.res.get_header("Upgrade"), "websocket");
BOOST_CHECK_EQUAL(env.res.get_header("Sec-WebSocket-Accept"), "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
}
@@ -147,7 +147,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
BOOST_AUTO_TEST_CASE( non_get_method ) {
processor_setup env(true);
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
@@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
BOOST_AUTO_TEST_CASE( old_http_version ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
@@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
@@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
@@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
BOOST_AUTO_TEST_CASE( bad_host ) {
processor_setup env(true);
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
env.req.consume(handshake.c_str(),handshake.size());
+2 -2
View File
@@ -37,7 +37,7 @@
BOOST_AUTO_TEST_CASE( exact_match ) {
websocketpp::http::parser::request r;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE( ci_exact_match ) {
BOOST_AUTO_TEST_CASE( non_exact_match1 ) {
websocketpp::http::parser::request r;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade,foo\r\nUpgrade: websocket,foo\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade,foo\r\nUpgrade: websocket,foo\r\n\r\n";
r.consume(handshake.c_str(),handshake.size());
+17
View File
@@ -0,0 +1,17 @@
# Test RNG policy none
file (GLOB SOURCE none.cpp)
init_target (test_random_none)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test RNG policy random_device
file (GLOB SOURCE random_device.cpp)
init_target (test_random_random_device)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+17
View File
@@ -0,0 +1,17 @@
# Test client role
file (GLOB SOURCE client.cpp)
init_target (test_roles_client)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test server role
file (GLOB SOURCE server.cpp)
init_target (test_roles_server)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+16 -16
View File
@@ -103,7 +103,7 @@ bool validate_func_subprotocol(server* s, std::string* out, std::string accept,
*out = o.str();
if (accept != "") {
if (!accept.empty()) {
con->select_subprotocol(accept);
}
@@ -118,8 +118,8 @@ void open_func_subprotocol(server* s, std::string* out, websocketpp::connection_
/* Tests */
BOOST_AUTO_TEST_CASE( basic_websocket_request ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
server s;
s.set_user_agent("test");
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE( basic_websocket_request ) {
}
BOOST_AUTO_TEST_CASE( invalid_websocket_version ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: a\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: a\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 400 Bad Request\r\nServer: test\r\n\r\n";
server s;
@@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE( invalid_websocket_version ) {
}
BOOST_AUTO_TEST_CASE( unimplemented_websocket_version ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 14\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 14\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
std::string output = "HTTP/1.1 400 Bad Request\r\nSec-WebSocket-Version: 0,7,8,13\r\nServer: test\r\n\r\n";
@@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE( unimplemented_websocket_version ) {
}
BOOST_AUTO_TEST_CASE( list_subprotocol_empty ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string subprotocol;
@@ -165,9 +165,9 @@ BOOST_AUTO_TEST_CASE( list_subprotocol_empty ) {
}
BOOST_AUTO_TEST_CASE( list_subprotocol_one ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string validate;
std::string open;
@@ -183,9 +183,9 @@ BOOST_AUTO_TEST_CASE( list_subprotocol_one ) {
}
BOOST_AUTO_TEST_CASE( accept_subprotocol_one ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string validate;
std::string open;
@@ -201,9 +201,9 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_one ) {
}
BOOST_AUTO_TEST_CASE( accept_subprotocol_invalid ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string validate;
std::string open;
@@ -219,9 +219,9 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_invalid ) {
}
BOOST_AUTO_TEST_CASE( accept_subprotocol_two ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo, bar\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\nSec-WebSocket-Protocol: foo, bar\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: bar\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: bar\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
std::string validate;
std::string open;
@@ -237,7 +237,7 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_two ) {
}
/*BOOST_AUTO_TEST_CASE( user_reject_origin ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example2.com\r\n\r\n";
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example2.com\r\n\r\n";
std::string output = "HTTP/1.1 403 Forbidden\r\nServer: test\r\n\r\n";
server s;
+71
View File
@@ -0,0 +1,71 @@
if (OPENSSL_FOUND)
# Test transport integration
file (GLOB SOURCE integration.cpp)
init_target (test_transport)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test transport asio timers
file (GLOB SOURCE asio/timers.cpp)
init_target (test_transport_asio_timers)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test transport asio security
file (GLOB SOURCE asio/security.cpp)
init_target (test_transport_asio_security)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
link_openssl()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
endif()
# Test transport iostream base
file (GLOB SOURCE iostream/base.cpp)
init_target (test_transport_iostream_base)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test transport iostream endpoint
file (GLOB SOURCE iostream/endpoint.cpp)
init_target (test_transport_iostream_endpoint)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test transport iostream connection
file (GLOB SOURCE iostream/connection.cpp)
init_target (test_transport_iostream_connection)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test transport asio base
file (GLOB SOURCE asio/base.cpp)
init_target (test_transport_asio_base)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+4
View File
@@ -15,14 +15,18 @@ BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','chrono'],env) +
objs = env.Object('base_boost.o', ["base.cpp"], LIBS = BOOST_LIBS)
objs += env.Object('timers_boost.o', ["timers.cpp"], LIBS = BOOST_LIBS)
objs += env.Object('security_boost.o', ["security.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_base_boost', ["base_boost.o"], LIBS = BOOST_LIBS)
prgs += env.Program('test_timers_boost', ["timers_boost.o"], LIBS = BOOST_LIBS)
prgs += env.Program('test_security_boost', ["security_boost.o"], LIBS = BOOST_LIBS)
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
objs += env_cpp11.Object('base_stl.o', ["base.cpp"], LIBS = BOOST_LIBS_CPP11)
objs += env_cpp11.Object('timers_stl.o', ["timers.cpp"], LIBS = BOOST_LIBS_CPP11)
objs += env_cpp11.Object('security_stl.o', ["security.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_base_stl', ["base_stl.o"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_timers_stl', ["timers_stl.o"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_security_stl', ["security_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2015, 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.
*
*/
//#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE transport_asio_base
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <websocketpp/common/type_traits.hpp>
#include <websocketpp/transport/asio/security/none.hpp>
#include <websocketpp/transport/asio/security/tls.hpp>
template <typename base>
struct dummy_con : public base {
websocketpp::lib::error_code test() {
return this->translate_ec(websocketpp::lib::asio::error_code());
}
};
BOOST_AUTO_TEST_CASE( translated_ec_none ) {
dummy_con<websocketpp::transport::asio::basic_socket::connection> tscon;
// If the current configuration settings result in the library error type and the asio
// error type being the same, then the code should pass through natively. Otherwise
// we should get a generic pass through error.
if(websocketpp::lib::is_same<websocketpp::lib::error_code,websocketpp::lib::asio::error_code>::value) {
BOOST_CHECK_EQUAL( tscon.test(), websocketpp::lib::error_code() );
} else {
BOOST_CHECK_EQUAL( tscon.test(), websocketpp::transport::error::make_error_code(websocketpp::transport::error::pass_through) );
}
}
BOOST_AUTO_TEST_CASE( translated_ec_tls ) {
dummy_con<websocketpp::transport::asio::tls_socket::connection> tscon;
// If the current configuration settings result in the library error type and the asio
// error type being the same, then the code should pass through natively. Otherwise
// we should get a generic pass through error.
if(websocketpp::lib::is_same<websocketpp::lib::error_code,websocketpp::lib::asio::error_code>::value) {
BOOST_CHECK_EQUAL( tscon.test(), websocketpp::lib::error_code() );
} else {
BOOST_CHECK_EQUAL( tscon.test(), websocketpp::transport::error::make_error_code(websocketpp::transport::error::pass_through) );
}
}
+14 -7
View File
@@ -108,14 +108,16 @@ struct config {
// Mock context that does no validation
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
context_ptr on_tls_init(websocketpp::connection_hdl) {
return context_ptr(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
return context_ptr(new boost::asio::ssl::context(boost::asio::ssl::context::sslv23));
}
// Mock connection
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,
@@ -138,9 +140,12 @@ typedef websocketpp::lib::shared_ptr<mock_con> connection_ptr;
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);
mock_endpoint()
: alog(websocketpp::lib::make_shared<config::alog_type>())
, elog(websocketpp::lib::make_shared<config::elog_type>())
{
alog->set_channels(websocketpp::log::alevel::all);
base::init_logging(alog,elog);
init_asio();
}
@@ -170,8 +175,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 ) {
@@ -180,6 +185,8 @@ BOOST_AUTO_TEST_CASE( tls_handshake_timeout ) {
dummy_server.detach();
timer.detach();
sleep(1); // give the server thread some time to start
mock_endpoint endpoint;
endpoint.set_tls_init_handler(&on_tls_init);
endpoint.connect("wss://localhost:9005");
+56 -22
View File
@@ -354,11 +354,35 @@ void close(T * e, websocketpp::connection_hdl hdl) {
e->get_con_from_hdl(hdl)->close(websocketpp::close::status::normal,"");
}
// Wait for the specified time period then fail the test
void run_test_timer(long value) {
sleep(value);
BOOST_FAIL( "Test timed out" );
}
class test_deadline_timer
{
public:
test_deadline_timer(int seconds)
: m_timer(m_io_service, boost::posix_time::seconds(seconds))
{
m_timer.async_wait(bind(&test_deadline_timer::expired, this, ::_1));
std::size_t (boost::asio::io_service::*run)() = &boost::asio::io_service::run;
m_timer_thread = websocketpp::lib::thread(websocketpp::lib::bind(run, &m_io_service));
}
~test_deadline_timer()
{
m_timer.cancel();
m_timer_thread.join();
}
private:
void expired(const boost::system::error_code & ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
BOOST_CHECK(!ec);
BOOST_FAIL("Test timed out");
}
boost::asio::io_service m_io_service;
boost::asio::deadline_timer m_timer;
websocketpp::lib::thread m_timer_thread;
};
BOOST_AUTO_TEST_CASE( pong_no_timeout ) {
server s;
@@ -375,6 +399,8 @@ BOOST_AUTO_TEST_CASE( pong_no_timeout ) {
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
sleep(1); // give the server thread some time to start
// Run a client that closes the connection after 1 seconds
run_time_limited_client(c, "http://localhost:9005", 1, false);
@@ -398,8 +424,9 @@ BOOST_AUTO_TEST_CASE( pong_timeout ) {
websocketpp::lib::error_code(),::_1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
tthread.detach();
sleep(1); // give the server thread some time to start
test_deadline_timer deadline(10);
run_client(c, "http://localhost:9005",false);
@@ -416,9 +443,11 @@ BOOST_AUTO_TEST_CASE( client_open_handshake_timeout ) {
websocketpp::error::open_handshake_timeout,::_1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_dummy_server,9005));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
sthread.detach();
tthread.detach();
sleep(1); // give the server thread some time to start
test_deadline_timer deadline(10);
run_client(c, "http://localhost:9005");
}
@@ -433,8 +462,10 @@ BOOST_AUTO_TEST_CASE( server_open_handshake_timeout ) {
websocketpp::error::open_handshake_timeout,::_1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
tthread.detach();
test_deadline_timer deadline(10);
sleep(1); // give the server thread some time to start
run_dummy_client("9005");
@@ -456,8 +487,10 @@ BOOST_AUTO_TEST_CASE( client_self_initiated_close_handshake_timeout ) {
websocketpp::error::close_handshake_timeout,::_1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
tthread.detach();
test_deadline_timer deadline(10);
sleep(1); // give the server thread some time to start
run_client(c, "http://localhost:9005", false);
@@ -488,10 +521,11 @@ BOOST_AUTO_TEST_CASE( server_self_initiated_close_handshake_timeout ) {
c.set_open_handler(bind(&delay,::_1,1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
tthread.detach();
test_deadline_timer deadline(10);
run_client(c, "http://localhost:9005",false);
sleep(1); // give the server thread some time to start
run_client(c, "http://localhost:9005", false);
sthread.join();
}
@@ -499,8 +533,7 @@ BOOST_AUTO_TEST_CASE( server_self_initiated_close_handshake_timeout ) {
BOOST_AUTO_TEST_CASE( client_runs_out_of_work ) {
client c;
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,3));
tthread.detach();
test_deadline_timer deadline(3);
websocketpp::lib::error_code ec;
c.init_asio(ec);
@@ -566,17 +599,18 @@ BOOST_AUTO_TEST_CASE( stop_listening ) {
c.set_open_handler(bind(&close<client>,&c,::_1));
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,5));
tthread.detach();
test_deadline_timer deadline(5);
run_client(c, "http://localhost:9005",false);
sleep(1); // give the server thread some time to start
run_client(c, "http://localhost:9005", false);
sthread.join();
}
BOOST_AUTO_TEST_CASE( pause_reading ) {
iostream_server s;
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
char buffer[2] = { char(0x81), char(0x80) };
// suppress output (it needs a place to go to avoid error but we don't care what it is)
+13 -3
View File
@@ -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));
+53
View File
@@ -0,0 +1,53 @@
# Test close utilities
file (GLOB SOURCE close.cpp)
init_target (test_close)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test error utilities
file (GLOB SOURCE error.cpp)
init_target (test_error)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test frame utilities
file (GLOB SOURCE frame.cpp)
init_target (test_frame)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test sha1 utilities
file (GLOB SOURCE sha1.cpp)
init_target (test_sha1)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test uri utilities
file (GLOB SOURCE uri.cpp)
init_target (test_uri)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
# Test misc utilities
file (GLOB SOURCE utilities.cpp)
init_target (test_utilities)
build_test (${TARGET_NAME} ${SOURCE})
link_boost ()
final_target ()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test")
+4 -5
View File
@@ -39,7 +39,6 @@ using namespace websocketpp;
BOOST_AUTO_TEST_CASE( reserved_values ) {
BOOST_CHECK( !close::status::reserved(999) );
BOOST_CHECK( close::status::reserved(1004) );
BOOST_CHECK( close::status::reserved(1014) );
BOOST_CHECK( close::status::reserved(1016) );
BOOST_CHECK( close::status::reserved(2999) );
BOOST_CHECK( !close::status::reserved(1000) );
@@ -88,7 +87,7 @@ BOOST_AUTO_TEST_CASE( value_extraction ) {
BOOST_AUTO_TEST_CASE( extract_empty ) {
lib::error_code ec;
std::string payload = "";
std::string payload;
BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status );
BOOST_CHECK( !ec );
@@ -109,12 +108,12 @@ BOOST_AUTO_TEST_CASE( extract_reason ) {
BOOST_CHECK( close::extract_reason(payload,ec) == "Foo" );
BOOST_CHECK( !ec );
payload = "";
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
payload.clear();
BOOST_CHECK( close::extract_reason(payload,ec).empty() );
BOOST_CHECK( !ec );
payload = "00";
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
BOOST_CHECK( close::extract_reason(payload,ec).empty() );
BOOST_CHECK( !ec );
payload = "000";
+1 -1
View File
@@ -246,7 +246,7 @@ int main() {
std::string cmd;
int id;
int close_code = websocketpp::close::status::normal;
std::string reason = "";
std::string reason;
ss >> cmd >> id >> close_code;
std::getline(ss,reason);
+2 -2
View File
@@ -289,7 +289,7 @@ int main() {
std::string cmd;
int id;
std::string message = "";
std::string message;
ss >> cmd >> id;
std::getline(ss,message);
@@ -301,7 +301,7 @@ int main() {
std::string cmd;
int id;
int close_code = websocketpp::close::status::normal;
std::string reason = "";
std::string reason;
ss >> cmd >> id >> close_code;
std::getline(ss,reason);

Some files were not shown because too many files have changed in this diff Show More