Compare commits
444 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 378437aecd | |||
| cc7d74d8d0 | |||
| b154ac5907 | |||
| 0348510c8d | |||
| a495c8c529 | |||
| fabf8bf1ca | |||
| 3f913f97ef | |||
| ffaeba2ec7 | |||
| db304bfec4 | |||
| d3bec51d25 | |||
| 8b672f7372 | |||
| a4a79f6bf6 | |||
| 9dc013a3aa | |||
| 931ad40b5f | |||
| 842f745e24 | |||
| e6f8766707 | |||
| 17a2647454 | |||
| 323dec4efc | |||
| ee343fb282 | |||
| b76422aa7a | |||
| 563fcc6b45 | |||
| b6014cc79b | |||
| d917f0924b | |||
| e036a5aeab | |||
| ed335a37b5 | |||
| bb4cbf3d03 | |||
| a388817606 | |||
| b373f1ea6b | |||
| 28448c77a5 | |||
| ae097d6a93 | |||
| 02f0026a00 | |||
| aac65bdfd0 | |||
| 7b368e67ed | |||
| d0802994d8 | |||
| 20cc197967 | |||
| 89df55c577 | |||
| 9713455e94 | |||
| 044eda9cc4 | |||
| fc6ec59ab8 | |||
| a01cce3b1a | |||
| e1b39037f7 | |||
| f54fb0669b | |||
| 935c8a3264 | |||
| 1e12e7aff8 | |||
| bda1bd14cb | |||
| 5f52127cf7 | |||
| 999add0c4b | |||
| f7448bb1b0 | |||
| ed45dcc617 | |||
| 7f19b6ea95 | |||
| 5b99feef7f | |||
| b85affddf4 | |||
| 5500aef4ce | |||
| 4e2fb75d07 | |||
| 6a94162264 | |||
| 536db87c53 | |||
| 39c5f3ae3d | |||
| cd4af122c0 | |||
| b6817e4c7e | |||
| 72e55a76b5 | |||
| 93b75ccc7d | |||
| 3e8dbf767d | |||
| 3c77ce3cc7 | |||
| 54ce641d02 | |||
| e0bd3f7e95 | |||
| fb829e0895 | |||
| f9dbc0fd9d | |||
| 0b2b77e4ad | |||
| 15c78afbf4 | |||
| 4b18214eda | |||
| e80673278f | |||
| 95551e7e94 | |||
| 22918a3992 | |||
| 9b09b0b481 | |||
| ef380f7fff | |||
| 1f504001d2 | |||
| c54f2abaab | |||
| 3580530902 | |||
| bc7ad6550e | |||
| d3fe51fa39 | |||
| 7514c82c92 | |||
| dabf32a668 | |||
| 0d7052d2ae | |||
| 39497aaa61 | |||
| c5510d6de0 | |||
| f931734369 | |||
| af792aeaba | |||
| 2af2135d82 | |||
| f2b38d5634 | |||
| 1b9e40040c | |||
| 8893faff53 | |||
| 430fb82e76 | |||
| 01d4109ae8 | |||
| 4cc678ee93 | |||
| acb53a379c | |||
| c18f210ea3 | |||
| f469b90bfc | |||
| 9d95501536 | |||
| 9351e73e90 | |||
| b817c4499e | |||
| 7829de34a3 | |||
| 6973f02d1c | |||
| 31b75714bd | |||
| 257b5ac8e5 | |||
| 769fe89533 | |||
| d670d69c6e | |||
| 2c843b9343 | |||
| d076e38e00 | |||
| 4331de8a29 | |||
| 6dde40d96e | |||
| d68fd03e40 | |||
| e161ffde69 | |||
| dc313effa5 | |||
| 6300e090ad | |||
| 45dfcbec3c | |||
| 39dbe3a4e0 | |||
| 371d2cdaef | |||
| 13f6da6f81 | |||
| ac5d7ea5af | |||
| 6f7ecc59cd | |||
| f7cea42c92 | |||
| 9efb12e59b | |||
| 174698f1df | |||
| 214cedf949 | |||
| c39412ee38 | |||
| 643e7a0ce1 | |||
| 349717ad46 | |||
| bcd82bd6f4 | |||
| 8f042d95ec | |||
| 0278ba7895 | |||
| 41c37cfd93 | |||
| 4bea90f555 | |||
| f9b08ccea1 | |||
| ce0300e6dc | |||
| f20b2e573f | |||
| 650e4c336b | |||
| 31c761a0a9 | |||
| 681c2331a1 | |||
| fccc78479e | |||
| 3017a9c5e4 | |||
| d55f28fe4b | |||
| a8d4a9a66a | |||
| 17544d4d62 | |||
| 4d1693c96c | |||
| 875d420952 | |||
| d792639c20 | |||
| d4e15c89ad | |||
| 1d29d48bb8 | |||
| 09c5f6505e | |||
| 745ed4f77a | |||
| 854166364b | |||
| 1517d646f9 | |||
| 6bb36a28e7 | |||
| 96362774a3 | |||
| 0a879a6dc2 | |||
| 867b323af0 | |||
| 9dd99ead25 | |||
| e3884e351b | |||
| 23e97bcc11 | |||
| 77e2e2fabb | |||
| ef393f8aef | |||
| 99f4a66221 | |||
| 768472c0d4 | |||
| 1f061a920e | |||
| 07543a5dde | |||
| ff9af5f8ca | |||
| ffedb97372 | |||
| e1f1c8873b | |||
| 922f1c35bc | |||
| 3c6c757d93 | |||
| 71f88c71d6 | |||
| 987f20feda | |||
| 27cea4e58f | |||
| e7b2e69ecb | |||
| bc868a244d | |||
| 77f1bf593d | |||
| 0a47a9a78c | |||
| 6578c5852e | |||
| f9ff42c4b0 | |||
| b9d4187e38 | |||
| cbe887524e | |||
| 8a9b0beec0 | |||
| 18994f7318 | |||
| 3f65b2ff98 | |||
| 0ad2da2083 | |||
| 7404b506db | |||
| b0efc72848 | |||
| beac6e5bb6 | |||
| f6c6552622 | |||
| 12700f2bc2 | |||
| 8cbe22266d | |||
| c23639d394 | |||
| d3ba1187de | |||
| 02b53d979e | |||
| 1d598558d8 | |||
| ff3009ed26 | |||
| d1f3eb9516 | |||
| c0dc3c0e5f | |||
| bfbfe2b052 | |||
| 1edc8deb01 | |||
| 571be82531 | |||
| 9ab9941f5e | |||
| 7dfe0d5815 | |||
| 088625eb53 | |||
| 575834b534 | |||
| 02dd5150fc | |||
| 2917d9262c | |||
| fbc2966cda | |||
| 9de0a087b3 | |||
| e9dd9cbbeb | |||
| dc7431c37f | |||
| 5fe6f8338d | |||
| 19f7886ca4 | |||
| 802e34bd2c | |||
| 4100fc3ce7 | |||
| 6bda8f85d4 | |||
| 56cdbcd1da | |||
| 4c15d27bf4 | |||
| b3b20ebb04 | |||
| 397f5c00bf | |||
| 82502a651a | |||
| b46c0fb142 | |||
| e1a0401d25 | |||
| f23abe8e70 | |||
| 4309749dd9 | |||
| f06b623767 | |||
| 9807283a6b | |||
| 83a66f4e3f | |||
| 2e7a902ef7 | |||
| 55b6cfae90 | |||
| 95bfe7c5ba | |||
| f7aeeaaa30 | |||
| 55827fc825 | |||
| d7a7112c8b | |||
| d6c9905e80 | |||
| 0e66dbfde4 | |||
| e8d25d22bc | |||
| fe6d82e7a3 | |||
| 2f64f8d91a | |||
| 6da47743e8 | |||
| 6c242b205b | |||
| 2d2c62c887 | |||
| 71a10d83c8 | |||
| fe0310b283 | |||
| 8a7beaa86a | |||
| 5d0c2f6341 | |||
| 122d4e2128 | |||
| e203dbed45 | |||
| ad2932bbff | |||
| 3560fa144a | |||
| 296f61b595 | |||
| 65cc3765a8 | |||
| 10be5eee14 | |||
| c39777e4c1 | |||
| af7149ae0a | |||
| 7c3eb3e6c2 | |||
| e7ce038207 | |||
| aaed2c4950 | |||
| 64fffeda9f | |||
| 7137105a81 | |||
| beaa6e98cc | |||
| 79c2d09200 | |||
| c021766592 | |||
| 7f7e9d2c2c | |||
| 70923eea23 | |||
| 99ae2f768c | |||
| 884e7d210c | |||
| 75dd6f3ba5 | |||
| 2ee496c08d | |||
| aabf87b6b1 | |||
| cfabe17e83 | |||
| b92a2b7f61 | |||
| 1f73456e25 | |||
| 0ca2bae121 | |||
| 002d2d0007 | |||
| d8b7cf3fdc | |||
| b358e2cfe8 | |||
| 099fdbd4f1 | |||
| 19a3713b29 | |||
| cd534ad18e | |||
| 7a46203beb | |||
| 497bc574da | |||
| 0bfb67ef11 | |||
| 762c013b93 | |||
| 9d237effc7 | |||
| e2b7a4b9f1 | |||
| e154d955ec | |||
| 2207348abb | |||
| 77495d4076 | |||
| 8752687bc8 | |||
| 0f3a36a630 | |||
| a63f7d8b7b | |||
| edb26d7721 | |||
| b2d698d3ca | |||
| 770b32275c | |||
| 9d8eced9a1 | |||
| fd0c62a8e4 | |||
| 1a68f4b907 | |||
| c3dfb25181 | |||
| 5a5d8321bd | |||
| b805689f9c | |||
| 7eedf25500 | |||
| 3ca53d0064 | |||
| 5e2fadd826 | |||
| 840bb6b59e | |||
| fe00a84f7b | |||
| 337bf2fb0a | |||
| c5b5492e5c | |||
| af15537205 | |||
| bdeb4ad680 | |||
| faad2ec854 | |||
| dc06049df9 | |||
| 3e53c74c3f | |||
| a5a30e554e | |||
| 9c8762c961 | |||
| 797ce35c5a | |||
| 30da3a967b | |||
| e1547bbde8 | |||
| 37f69cc19b | |||
| 93d9b5f820 | |||
| 98fd183210 | |||
| 093806f860 | |||
| 1da45144e9 | |||
| 5f56976290 | |||
| 40ed74a141 | |||
| fbc9db2b5d | |||
| f87c9d4360 | |||
| 99461184d3 | |||
| 9eff0db756 | |||
| 86325b1838 | |||
| 2d2312a1d7 | |||
| afc28be004 | |||
| b7c5a2e791 | |||
| d36925ce7d | |||
| 92dfe9ef97 | |||
| 2ab02197fd | |||
| 89ac45e60a | |||
| 713a05679c | |||
| 0fecf023ef | |||
| ffdf5f842b | |||
| d425caea80 | |||
| ce2c1d6e34 | |||
| 7ceeaa4f9c | |||
| 883410bb77 | |||
| 724974c758 | |||
| 1622cdde04 | |||
| 180543b9e6 | |||
| 7c08cae15b | |||
| 81e0c44b34 | |||
| 722a67a910 | |||
| ba6320ba1c | |||
| d9aa498310 | |||
| 47c46a2fbc | |||
| 9401cf00ce | |||
| acedd4db49 | |||
| 91617150e1 | |||
| c7463afb06 | |||
| ba90910f6e | |||
| bee2c03aa0 | |||
| 8e86ddcf5a | |||
| fe85de763e | |||
| ca97dd1fb8 | |||
| c7ec97795a | |||
| 6ee7c368bb | |||
| 2000746be7 | |||
| c84cc110aa | |||
| 09940a5c0b | |||
| bb21e3cf95 | |||
| 5f3b92c9e4 | |||
| 14074666a7 | |||
| bb431ee0d2 | |||
| 373f180638 | |||
| 021ac0599c | |||
| e44463583b | |||
| 4393a2562b | |||
| 780f7683a4 | |||
| 8f359e6d35 | |||
| ebb65c81e2 | |||
| c7fda5a960 | |||
| 6d4514246f | |||
| c2f2cb951b | |||
| 827f3678bb | |||
| 57cd0e286e | |||
| 87cb5036a4 | |||
| f05f18b384 | |||
| 01963a23ea | |||
| 18036d2b01 | |||
| 17bd89bd80 | |||
| f59f301b91 | |||
| 319507f4af | |||
| 06cdf43dcf | |||
| f8f945433f | |||
| a4f96cf0c3 | |||
| 7032e6940f | |||
| bfd50e1ee1 | |||
| 415533f7e7 | |||
| b87bfc068e | |||
| dbb5f963c8 | |||
| a1872c3790 | |||
| 8993b34b3d | |||
| 7ae83b9efd | |||
| 430c49d394 | |||
| 3e5404e1b1 | |||
| 8524a1a272 | |||
| 6f79894ea5 | |||
| 5e803b57f7 | |||
| 6a3e886f0b | |||
| ac9351f9b3 | |||
| e62823a0af | |||
| 8ce05cd228 | |||
| eb314e55de | |||
| ccbd93f725 | |||
| be9a320fc1 | |||
| 9a73b74a37 | |||
| 48add58dc2 | |||
| e967ffc74d | |||
| 475c478a2e | |||
| b8d962950f | |||
| ba0094a0eb | |||
| eb362007ab | |||
| 4d63c10be7 | |||
| 28f949d955 | |||
| 11906dc2ce | |||
| c60e089553 | |||
| b809bf3706 | |||
| 6920b39aa2 | |||
| f7376ccf46 | |||
| 243cea16db | |||
| 98a75b8cea | |||
| 5323076007 | |||
| d0d97b860b | |||
| 25e8d522b2 | |||
| bd408944fd | |||
| 14aa71091f | |||
| 4607150f82 | |||
| 359f03fb1e | |||
| 4a52e548fd | |||
| 0501f77b57 | |||
| 631261c365 | |||
| a90ccd83dd | |||
| c103032e9c | |||
| c32bebba3e | |||
| 6c6c6951e5 | |||
| aeb0e8fa7d |
+14
@@ -32,11 +32,15 @@ install_manifest.txt
|
||||
*.ncb
|
||||
*/Debug/*
|
||||
*/*/Debug/*
|
||||
bin/Debug
|
||||
*/Release/*
|
||||
*/*/Release/*
|
||||
*/RelWithDebInfo/*
|
||||
*/*/RelWithDebInfo/*
|
||||
|
||||
# explicitly allow this path with /debug/ in it
|
||||
!websocketpp/transport/debug/*
|
||||
|
||||
objs_shared/
|
||||
objs_static/
|
||||
|
||||
@@ -78,3 +82,13 @@ examples/wsperf/wsperf_client
|
||||
*.out
|
||||
|
||||
*.log
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.user
|
||||
install
|
||||
Makefile
|
||||
bin
|
||||
|
||||
Testing/Temporary/CTestCostData.txt
|
||||
|
||||
+4
-5
@@ -2,18 +2,17 @@ language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
before_install:
|
||||
- sudo apt-get install 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:
|
||||
- travis@zaphoyd.com
|
||||
|
||||
+32
-8
@@ -9,10 +9,12 @@ project (websocketpp)
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
set (WEBSOCKETPP_MAJOR_VERSION 0)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 3)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 7)
|
||||
set (WEBSOCKETPP_PATCH_VERSION 0)
|
||||
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})
|
||||
|
||||
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)
|
||||
@@ -67,10 +69,12 @@ option (BUILD_TESTS "Build websocketpp tests." FALSE)
|
||||
|
||||
if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
|
||||
enable_testing ()
|
||||
|
||||
############ Compiler specific setup
|
||||
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS "")
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS "")
|
||||
set (WEBSOCKETPP_PLATFORM_TLS_LIBS "")
|
||||
set (WEBSOCKETPP_BOOST_LIBS "")
|
||||
|
||||
# VC9 and C++11 reasoning
|
||||
@@ -87,7 +91,14 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
|
||||
# C++11 defines
|
||||
if (ENABLE_CPP11)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_STL_)
|
||||
if (MSVC)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_FUNCTIONAL_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_SYSTEM_ERROR_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_RANDOM_DEVICE_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_MEMORY_)
|
||||
else()
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_STL_)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
# Visual studio
|
||||
@@ -104,9 +115,9 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
# g++
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_PLATFORM_TLS_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
if (NOT APPLE)
|
||||
add_definitions (-DNDEBUG -Wall -Wcast-align) # todo: should we use CMAKE_C_FLAGS for these?
|
||||
endif ()
|
||||
@@ -126,7 +137,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
else()
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS pthread)
|
||||
endif()
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_PLATFORM_TLS_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x -stdlib=libc++") # todo: is libc++ really needed here?
|
||||
if (NOT APPLE)
|
||||
@@ -143,6 +154,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.
|
||||
@@ -173,6 +188,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)
|
||||
@@ -205,6 +228,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
endif ()
|
||||
|
||||
find_package(OpenSSL)
|
||||
find_package(ZLIB)
|
||||
endif()
|
||||
|
||||
############ Add projects
|
||||
@@ -214,12 +238,12 @@ 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()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Main Library:
|
||||
|
||||
Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
Copyright (c) 2014, 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:
|
||||
|
||||
+54
-9
@@ -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:
|
||||
@@ -79,6 +84,8 @@ elif env['PLATFORM'] == 'posix':
|
||||
env.Append(CCFLAGS = ['-Wall'])
|
||||
#env['LINKFLAGS'] = ''
|
||||
elif env['PLATFORM'] == 'darwin':
|
||||
if not os.environ.has_key('CXX'):
|
||||
env['CXX'] = "clang++"
|
||||
if env.has_key('DEBUG'):
|
||||
env.Append(CCFLAGS = ['-g', '-O0'])
|
||||
else:
|
||||
@@ -91,21 +98,38 @@ 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++'):
|
||||
#env.Append(CCFLAGS = ['-Wconversion'])
|
||||
env.Append(CCFLAGS = ['-Wcast-align'])
|
||||
env.Append(CCFLAGS = ['-Wshadow'])
|
||||
env.Append(CCFLAGS = ['-Wunused-parameter'])
|
||||
elif env['CXX'].startswith('clang++'):
|
||||
#env.Append(CCFLAGS = ['-Wcast-align'])
|
||||
#env.Append(CCFLAGS = ['-Wglobal-constructors'])
|
||||
#env.Append(CCFLAGS = ['-Wconversion'])
|
||||
env.Append(CCFLAGS = ['-Wno-padded'])
|
||||
env.Append(CCFLAGS = ['-Wshadow'])
|
||||
env.Append(CCFLAGS = ['-Wunused-parameter'])
|
||||
|
||||
env.Append(CCFLAGS = ['-Wsometimes-uninitialized'])
|
||||
env.Append(CCFLAGS = ['-Wuninitialized'])
|
||||
|
||||
#env.Append(CCFLAGS = ['-Weverything'])
|
||||
#env.Append(CCFLAGS = ['-Wno-documentation'])
|
||||
#env.Append(CCFLAGS = ['-Wno-weak-vtables'])
|
||||
#env.Append(CCFLAGS = ['-Wno-global-constructors'])
|
||||
#env.Append(CCFLAGS = ['-Wno-sign-conversion'])
|
||||
#env.Append(CCFLAGS = ['-Wno-exit-time-destructors'])
|
||||
|
||||
|
||||
|
||||
|
||||
# Wpadded
|
||||
# Wsign-conversion
|
||||
#
|
||||
|
||||
platform_libs = []
|
||||
tls_libs = []
|
||||
@@ -128,7 +152,7 @@ env.Append(CPPPATH = ['#'])
|
||||
|
||||
##### Set up C++11 environment
|
||||
polyfill_libs = [] # boost libraries used as drop in replacements for incomplete
|
||||
# C++11 STL implementations
|
||||
# C++11 STL implementations
|
||||
env_cpp11 = env.Clone ()
|
||||
|
||||
if env_cpp11['CXX'].startswith('g++'):
|
||||
@@ -142,6 +166,7 @@ if env_cpp11['CXX'].startswith('g++'):
|
||||
print "C++11 build environment is not supported on this version of G++"
|
||||
elif env_cpp11['CXX'].startswith('clang++'):
|
||||
print "C++11 build environment enabled"
|
||||
env.Append(CXXFLANGS = ['-stdlib=libc++'],LINKFLAGS=['-stdlib=libc++'])
|
||||
env_cpp11.Append(WSPP_CPP11_ENABLED = "true",CXXFLAGS = ['-std=c++0x','-stdlib=libc++'],LINKFLAGS = ['-stdlib=libc++'],TOOLSET = ['clang++'],CPPDEFINES = ['_WEBSOCKETPP_CPP11_STL_'])
|
||||
|
||||
# look for optional second boostroot compiled with clang's libc++ STL library
|
||||
@@ -160,18 +185,18 @@ else:
|
||||
# values then use it for the boost libraries. Otherwise just add them to the
|
||||
# regular CPPPATH values.
|
||||
if env['CXX'].startswith('g++') or env['CXX'].startswith('clang'):
|
||||
env.Append(CPPFLAGS = '-isystem ' + env['BOOST_INCLUDES'])
|
||||
env.Append(CPPFLAGS = '-isystem ' + env['BOOST_INCLUDES'])
|
||||
else:
|
||||
env.Append(CPPPATH = [env['BOOST_INCLUDES']])
|
||||
env.Append(CPPPATH = [env['BOOST_INCLUDES']])
|
||||
env.Append(LIBPATH = [env['BOOST_LIBS']])
|
||||
|
||||
# if the build system is known to allow the isystem modifier for library include
|
||||
# values then use it for the boost libraries. Otherwise just add them to the
|
||||
# regular CPPPATH values.
|
||||
if env_cpp11['CXX'].startswith('g++') or env_cpp11['CXX'].startswith('clang'):
|
||||
env_cpp11.Append(CPPFLAGS = '-isystem ' + env_cpp11['BOOST_INCLUDES'])
|
||||
env_cpp11.Append(CPPFLAGS = '-isystem ' + env_cpp11['BOOST_INCLUDES'])
|
||||
else:
|
||||
env_cpp11.Append(CPPPATH = [env_cpp11['BOOST_INCLUDES']])
|
||||
env_cpp11.Append(CPPPATH = [env_cpp11['BOOST_INCLUDES']])
|
||||
env_cpp11.Append(LIBPATH = [env_cpp11['BOOST_LIBS']])
|
||||
|
||||
releasedir = 'build/release/'
|
||||
@@ -206,9 +231,13 @@ 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)
|
||||
|
||||
# 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)
|
||||
|
||||
# broadcast_server
|
||||
broadcast_server = SConscript('#/examples/broadcast_server/SConscript',variant_dir = builddir + 'broadcast_server',duplicate = 0)
|
||||
@@ -219,12 +248,28 @@ testee_server = SConscript('#/examples/testee_server/SConscript',variant_dir = b
|
||||
# testee_client
|
||||
testee_client = SConscript('#/examples/testee_client/SConscript',variant_dir = builddir + 'testee_client',duplicate = 0)
|
||||
|
||||
# utility_client
|
||||
utility_client = SConscript('#/examples/utility_client/SConscript',variant_dir = builddir + 'utility_client',duplicate = 0)
|
||||
# scratch_client
|
||||
scratch_client = SConscript('#/examples/scratch_client/SConscript',variant_dir = builddir + 'scratch_client',duplicate = 0)
|
||||
|
||||
# scratch_server
|
||||
scratch_server = SConscript('#/examples/scratch_server/SConscript',variant_dir = builddir + 'scratch_server',duplicate = 0)
|
||||
|
||||
|
||||
# debug_client
|
||||
debug_client = SConscript('#/examples/debug_client/SConscript',variant_dir = builddir + 'debug_client',duplicate = 0)
|
||||
|
||||
# debug_server
|
||||
debug_server = SConscript('#/examples/debug_server/SConscript',variant_dir = builddir + 'debug_server',duplicate = 0)
|
||||
|
||||
# subprotocol_server
|
||||
subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',variant_dir = builddir + 'subprotocol_server',duplicate = 0)
|
||||
|
||||
# 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)
|
||||
|
||||
+268
-9
@@ -1,12 +1,271 @@
|
||||
HEAD
|
||||
- Adds URI method to extract query string from URI. Thank you Banaan for code.
|
||||
#298
|
||||
- Numerous performance improvements. Including: tuned default buffer sizes based
|
||||
on profiling, caching of handler binding for async reads/writes, non-malloc
|
||||
allocators for read/write handlers, disabling of a number of questionably
|
||||
useful range sanity checks in tight inner loops.
|
||||
- Adds a compile time switch to asio transport config to disable certain
|
||||
multithreading features (some locks, asio strands)
|
||||
|
||||
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
|
||||
- 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
|
||||
that can be added to any existing custom transport policy to fulfill this
|
||||
requirement. This does not affect anyone using the bundled transports or
|
||||
configs.
|
||||
- MINOR BREAKING SOCKET POLICY CHANGE: Custom asio transport socket policies
|
||||
will now be required to include a new method `void set_uri(uri_ptr u)`. Like
|
||||
with the transport layer, an implementation is not required. This does not
|
||||
affect anyone using the bundled socket policies.
|
||||
- MINOR BREAKING DEPENDENCY CHANGE: When using Boost versions greater than or
|
||||
equal to 1.49 in C++03 mode, `libboost-chrono` is needed now instead of
|
||||
`libboost-date_time`. Users with C++11 compilers or using Boost versions 1.48
|
||||
and earlier are not affected. Note: This change affects the bundled unit test
|
||||
suite.
|
||||
- Feature: WebSocket++ Asio transport policy can now be used with the standalone
|
||||
version of Asio (1.8.0+) when a C++11 compiler and standard library are
|
||||
present. This means that it is possible now to use WebSocket++'s Asio
|
||||
transport entirely without Boost. Thank you Robert Seiler for proof of concept
|
||||
code that was used as a guide for this implementation. Fixes #324
|
||||
- Feature: Adds a vectored/scatter-gather write handler to the iostream
|
||||
transport.
|
||||
- Feature: Adds the ability to defer sending an HTTP response until sometime
|
||||
after the `http_handler` is run. This allows processing of long running http
|
||||
handlers to defer their response until it is ready without blocking the
|
||||
network thread. references #425
|
||||
- Improvement: `echo_server_tls` has been update to demonstrate how to configure
|
||||
it for Mozilla's recommended intermediate and modern TLS security profiles.
|
||||
- Improvement: `endpoint::set_timer` now uses a steady clock provided by
|
||||
`boost::chrono` or `std::chrono` where available instead of the non-monotonic
|
||||
system clock. Thank you breyed for reporting. fixes #241
|
||||
- Improvement: Outgoing TLS connections to servers using the SNI extension to
|
||||
choose a certificate will now work. Thank you moozzyk for reporting.
|
||||
Fixes #400
|
||||
- Improvement: Removes an unnecessary mutex lock in `get_con_from_hdl`.
|
||||
- Cleanup: Asio transport policy has been refactored to remove many Boost
|
||||
dependencies. On C++03 compilers the `boost::noncopyable` dependency has been
|
||||
removed and the `boost::date_time` dependency has been replaced with the newer
|
||||
`boost::chrono` when possible. On C++11 compilers the `boost::aligned_storage`
|
||||
and `boost::date_time` dependencies are gone, replaced with equivalent C++11
|
||||
standard library features.
|
||||
- Bug: Fixes a potential dangling pointer and inconsistent error message
|
||||
handling in `websocketpp::exception`. #432 Thank you Tom Swirly for the fix.
|
||||
|
||||
0.5.1 - 2015-02-27
|
||||
- Bug: Fixes an issue where some frame data was counted against the max header
|
||||
size limit, resulting in connections that included a lot of frame data
|
||||
immediately after the opening handshake to fail.
|
||||
- Bug: Fix a typo in the name of the set method for `max_http_body_size`. #406
|
||||
Thank you jplatte for reporting.
|
||||
|
||||
0.5.0 - 2015-01-22
|
||||
- BREAKING UTILITY CHANGE: Deprecated methods `http::parser::parse_headers`,
|
||||
`http::response::parse_complete`, and `http::request::parse_complete` have
|
||||
been removed.
|
||||
- Security: Disabled SSLv3 in example servers.
|
||||
- Feature: Adds basic support for accessing HTTP request bodies in the http
|
||||
handler. #181
|
||||
- Feature: Adds the ability to register a shutdown handler when using the
|
||||
iostream transport. This provides a clean interface for triggering the shut
|
||||
down of external sockets and other cleanup without hooking in to higher level
|
||||
WebSocket handlers.
|
||||
- Feature: Adds the ability to register a write handler when using the iostream
|
||||
transport. This handler can be used to handle transport output in place of
|
||||
registering an ostream to write to.
|
||||
- Feature: Adds a new logging policy that outputs to syslog. #386 Thank you Tom
|
||||
Hughes for submitting the initial version of this policy.
|
||||
- Improvement: Message payload logging now prints text for text messages rather
|
||||
than binary.
|
||||
- Improvement: Overhaul of handshake state machine. Should make it impossible
|
||||
for exceptions to bubble out of transport methods like `io_service::run`.
|
||||
- Improvement: Overhaul of handshake error reporting. Fail handler error codes
|
||||
will be more detailed and precise. Adds new [fail] and [http] logging channels
|
||||
that log failed websocket connections and successful HTTP connections
|
||||
respectively. A new aggregate channel package, `alevel::access_core`, allows
|
||||
enabling connect, disconnect, fail, and http together. Successful HTTP
|
||||
connections will no longer trigger a fail handler.
|
||||
- Improvement: Ability to terminate connection during an http handler to cleanly
|
||||
suppress the default outgoing HTTP response.
|
||||
- Documentation: Add Sending & Receiving Messages step to chapter one of the
|
||||
`utility_client` tutorial. Update `utility_client` example to match.
|
||||
- Cleanup: Removes unused files & STL includes. Adds required STL includes.
|
||||
Normalizes include order.
|
||||
- Bug: Fixes a fatal state error when a handshake response is completed
|
||||
immediately after that handshake times out. #389
|
||||
- Bug: MinGW fixes; C++11 feature detection, localtime use. #393 Thank you
|
||||
Schebb for reporting, code, and testing.
|
||||
- Bug: Fixes an issue where `websocketpp::exception::what()` could return an out
|
||||
of scope pointer. #397 Thank you fabioang for reporting.
|
||||
- Bug: Fixes an issue where endpoints were not reset properly after a call to
|
||||
`endpoint::listen` failed. #390 Thank you wyyqyl for reporting.
|
||||
|
||||
0.4.0 - 2014-11-04
|
||||
- BREAKING API CHANGE: All WebSocket++ methods now throw an exception of type
|
||||
`websocketpp::exception` which derives from `std::exception`. This normalizes
|
||||
all exception types under the standard exception hierarchy and allows
|
||||
WebSocket++ exceptions to be caught in the same statement as others. The error
|
||||
code that was previously thrown is wrapped in the exception object and can be
|
||||
accessed via the `websocketpp::exception::code()` method.
|
||||
- BREAKING API CHANGE: Custom logging policies have some new required
|
||||
constructors that take generic config settings rather than pointers to
|
||||
std::ostreams. This allows writing logging policies that do not involve the
|
||||
use of std::ostream. This does not affect anyone using the built in logging
|
||||
policies.
|
||||
- BREAKING UTILITY CHANGE: `websocketpp::lib::net::htonll` and
|
||||
`websocketpp::lib::net::ntohll` have been prefixed with an underscore to avoid
|
||||
conflicts with similarly named macros in some operating systems. If you are
|
||||
using the WebSocket++ provided 64 bit host/network byte order functions you
|
||||
will need to switch to the prefixed versions.
|
||||
- BREAKING UTILITY CHANGE: The signature of `base64_encode` has changed from
|
||||
`websocketpp::base64_encode(unsigned char const *, unsigned int)` to
|
||||
`websocketpp::base64_encode(unsigned char const *, size_t)`.
|
||||
- BREAKING UTILITY CHANGE: The signature of `sha1::calc` has changed from
|
||||
`websocketpp::sha1::calc(void const *, int, unsigned char *)` to
|
||||
`websocketpp::sha1::calc(void const *, size_t, unsigned char *)`
|
||||
- Feature: Adds incomplete `minimal_server` and `minimal_client` configs that
|
||||
can be used to build custom configs without pulling in the dependencies of
|
||||
`core` or `core_client`. These configs will offer a stable base config to
|
||||
future-proof custom configs.
|
||||
- Improvement: Core library no longer has std::iostream as a dependency.
|
||||
std::iostream is still required for the optional iostream logging policy and
|
||||
iostream transport.
|
||||
- Bug: C++11 Chrono support was being incorrectly detected by the `boost_config`
|
||||
header. Thank you Max Dmitrichenko for reporting and a patch.
|
||||
- Bug: use of `std::put_time` is now guarded by a unique flag rather than a
|
||||
chrono library flag. Thank you Max Dmitrichenko for reporting.
|
||||
- Bug: Fixes non-thread safe use of std::localtime. #347 #383
|
||||
- Compatibility: Adjust usage of std::min to be more compatible with systems
|
||||
that define a min(...) macro.
|
||||
- Compatibility: Removes unused parameters from all library, test, and example
|
||||
code. This assists with those developing with -Werror and -Wunused-parameter
|
||||
#376
|
||||
- Compatibility: Renames ntohll and htonll methods to avoid conflicts with
|
||||
platform specific macros. #358 #381, #382 Thank you logotype, unphased,
|
||||
svendjo
|
||||
- Cleanup: Removes unused functions, fixes variable shadow warnings, normalizes
|
||||
all whitespace in library, examples, and tests to 4 spaces. #376
|
||||
|
||||
0.3.0 - 2014-08-10
|
||||
- Feature: Adds `start_perpetual` and `stop_perpetual` methods to asio transport
|
||||
These may be used to replace manually managed `asio::io_service::work` objects
|
||||
- Feature: Allow setting pong and handshake timeouts at runtime.
|
||||
- Feature: Allows changing the listen backlog queue length.
|
||||
- Feature: Split tcp init into pre and post init.
|
||||
- Feature: Adds URI method to extract query string from URI. Thank you Banaan
|
||||
for code. #298
|
||||
- Feature: Adds a compile time switch to asio transport config to disable
|
||||
certain multithreading features (some locks, asio strands)
|
||||
- Feature: Adds the ability to pause reading on a connection. Paused connections
|
||||
will not read more data from their socket, allowing TCP flow control to work
|
||||
without blocking the main thread.
|
||||
- Feature: Adds the ability to specify whether or not to use the `SO_REUSEADDR`
|
||||
TCP socket option. The default for this value has been changed from `true` to
|
||||
`false`.
|
||||
- Feature: Adds the ability to specify a maximum message size.
|
||||
- Feature: Adds `close::status::get_string(...)` method to look up a human
|
||||
readable string given a close code value.
|
||||
- Feature: Adds `connection::read_all(...)` method to iostream transport as a
|
||||
convenience method for reading all data into the connection buffer without the
|
||||
end user needing to manually loop on `read_some`.
|
||||
- Improvement: Open, close, and pong timeouts can be disabled entirely by
|
||||
setting their duration to 0.
|
||||
- Improvement: Numerous performance improvements. Including: tuned default
|
||||
buffer sizes based on profiling, caching of handler binding for async
|
||||
reads/writes, non-malloc allocators for read/write handlers, disabling of a
|
||||
number of questionably useful range sanity checks in tight inner loops.
|
||||
- Improvement: Cleaned up the handling of TLS related errors. TLS errors will
|
||||
now be reported with more detail on the info channel rather than all being
|
||||
`tls_short_read` or `pass_through`. In addition, many cases where a TLS short
|
||||
read was in fact expected are no longer classified as errors. Expected TLS
|
||||
short reads and quasi-expected socket shutdown related errors will no longer
|
||||
be reported as unclean WebSocket shutdowns to the application. Information
|
||||
about them will remain in the info error channel for debugging purposes.
|
||||
- Improvement: `start_accept` and `listen` errors are now reported to the caller
|
||||
either via an exception or an ec parameter.
|
||||
- Improvement: Outgoing writes are now batched for improved message throughput
|
||||
and reduced system call and TCP frame overhead.
|
||||
- Bug: Fix some cases of calls to empty lib::function objects.
|
||||
- Bug: Fix memory leak of connection objects due to cached handlers holding on to
|
||||
reference counted pointers. #310 Thank you otaras for reporting.
|
||||
- Bug: Fix issue with const endpoint accessors (such as `get_user_agent`) not
|
||||
compiling due to non-const mutex use. #292 Thank you logofive for reporting.
|
||||
- Bug: Fix handler allocation crash with multithreaded `io_service`.
|
||||
- Bug: Fixes incorrect whitespace handling in header parsing. #301 Thank you
|
||||
Wolfram Schroers for reporting
|
||||
- Bug: Fix a crash when parsing empty HTTP headers. Thank you Thingol for
|
||||
reporting.
|
||||
- Bug: Fix a crash following use of the `stop_listening` function. Thank you
|
||||
Thingol for reporting.
|
||||
- Bug: Fix use of variable names that shadow function parameters. The library
|
||||
should compile cleanly with -Wshadow now. Thank you giszo for reporting. #318
|
||||
- Bug: Fix an issue where `set_open_handshake_timeout` was ignored by server
|
||||
code. Thank you Robin Rowe for reporting.
|
||||
- Bug: Fix an issue where custom timeout values weren't being propagated from
|
||||
endpoints to new connections.
|
||||
- Bug: Fix a number of memory leaks related to server connection failures. #323
|
||||
#333 #334 #335 Thank you droppy and aydany for reporting and patches.
|
||||
reporting.
|
||||
- Compatibility: Fix compile time conflict with Visual Studio's MIN/MAX macros.
|
||||
Thank you Robin Rowe for reporting.
|
||||
- Documentation: Examples and test suite build system now defaults to clang on
|
||||
OS X
|
||||
|
||||
0.3.0-alpha4 - 2013-10-11
|
||||
- HTTP requests ending normally are no longer logged as errors. Thank you Banaan
|
||||
@@ -73,7 +332,7 @@ HEAD
|
||||
- Change default HTTP response error code when no http_handler is defined from
|
||||
500/Internal Server Error to 426/Upgrade Required
|
||||
- Remove timezone from logger timestamp to work around issues with the Windows
|
||||
implimentation of strftime. Thank you breyed for testing and code. #257
|
||||
implementation of strftime. Thank you breyed for testing and code. #257
|
||||
- Switch integer literals to char literals to improve VCPP compatibility.
|
||||
Thank you breyed for testing and code. #257
|
||||
- Add MSVCPP warning suppression for the bundled SHA1 library. Thank you breyed
|
||||
|
||||
@@ -13,7 +13,12 @@ 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 (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 ()
|
||||
|
||||
@@ -49,10 +54,23 @@ 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")
|
||||
@@ -76,3 +94,16 @@ endmacro ()
|
||||
macro (link_openssl)
|
||||
target_link_libraries (${TARGET_NAME} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
|
||||
endmacro ()
|
||||
|
||||
macro (link_zlib)
|
||||
target_link_libraries (${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||
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()
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/** \page faq FAQ
|
||||
|
||||
## 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.
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
*/
|
||||
@@ -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.
|
||||
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/** \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"
|
||||
|
||||
*/
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
|
||||
@@ -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
|
||||
|
||||
*/
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
/*#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
@@ -18,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;
|
||||
|
||||
@@ -34,7 +36,8 @@ enum action_type {
|
||||
|
||||
struct action {
|
||||
action(action_type t, connection_hdl h) : type(t), hdl(h) {}
|
||||
action(action_type t, server::message_ptr m) : type(t), msg(m) {}
|
||||
action(action_type t, connection_hdl h, server::message_ptr m)
|
||||
: type(t), hdl(h), msg(m) {}
|
||||
|
||||
action_type type;
|
||||
websocketpp::connection_hdl hdl;
|
||||
@@ -58,42 +61,41 @@ public:
|
||||
m_server.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
m_server.start_accept();
|
||||
m_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// Start the ASIO io_service run loop
|
||||
try {
|
||||
m_server.run();
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
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,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();
|
||||
}
|
||||
|
||||
@@ -111,13 +113,13 @@ public:
|
||||
lock.unlock();
|
||||
|
||||
if (a.type == SUBSCRIBE) {
|
||||
unique_lock<mutex> lock(m_connection_lock);
|
||||
lock_guard<mutex> guard(m_connection_lock);
|
||||
m_connections.insert(a.hdl);
|
||||
} else if (a.type == UNSUBSCRIBE) {
|
||||
unique_lock<mutex> lock(m_connection_lock);
|
||||
lock_guard<mutex> guard(m_connection_lock);
|
||||
m_connections.erase(a.hdl);
|
||||
} else if (a.type == MESSAGE) {
|
||||
unique_lock<mutex> 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) {
|
||||
@@ -129,7 +131,7 @@ public:
|
||||
}
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl> > con_list;
|
||||
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
@@ -141,18 +143,18 @@ private:
|
||||
};
|
||||
|
||||
int main() {
|
||||
try {
|
||||
broadcast_server server;
|
||||
try {
|
||||
broadcast_server server_instance;
|
||||
|
||||
// Start a thread to run the processing loop
|
||||
thread t(bind(&broadcast_server::process_messages,&server));
|
||||
// Start a thread to run the processing loop
|
||||
thread t(bind(&broadcast_server::process_messages,&server_instance));
|
||||
|
||||
// Run the asio loop with the main thread
|
||||
server.run(9002);
|
||||
// Run the asio loop with the main thread
|
||||
server_instance.run(9002);
|
||||
|
||||
t.join();
|
||||
t.join();
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (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()
|
||||
@@ -0,0 +1,24 @@
|
||||
## Debug client 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('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_client.hpp>
|
||||
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
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_tls_client::message_type::ptr message_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
typedef client::connection_ptr connection_ptr;
|
||||
|
||||
|
||||
|
||||
class perftest {
|
||||
public:
|
||||
typedef perftest type;
|
||||
typedef std::chrono::duration<int,std::micro> dur_type;
|
||||
|
||||
perftest () {
|
||||
m_endpoint.set_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.set_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
m_endpoint.init_asio();
|
||||
|
||||
// Register our handlers
|
||||
m_endpoint.set_socket_init_handler(bind(&type::on_socket_init,this,::_1));
|
||||
//m_endpoint.set_tls_init_handler(bind(&type::on_tls_init,this,::_1));
|
||||
m_endpoint.set_message_handler(bind(&type::on_message,this,::_1,::_2));
|
||||
m_endpoint.set_open_handler(bind(&type::on_open,this,::_1));
|
||||
m_endpoint.set_close_handler(bind(&type::on_close,this,::_1));
|
||||
m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1));
|
||||
}
|
||||
|
||||
void start(std::string uri) {
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = m_endpoint.get_connection(uri, ec);
|
||||
|
||||
if (ec) {
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
//con->set_proxy("http://humupdates.uchicago.edu:8443");
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
m_start = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.run();
|
||||
}
|
||||
|
||||
void on_socket_init(websocketpp::connection_hdl) {
|
||||
m_socket_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl) {
|
||||
m_tls_init = std::chrono::high_resolution_clock::now();
|
||||
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
|
||||
|
||||
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);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void on_fail(websocketpp::connection_hdl hdl) {
|
||||
client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Fail handler" << std::endl;
|
||||
std::cout << con->get_state() << std::endl;
|
||||
std::cout << con->get_local_close_code() << std::endl;
|
||||
std::cout << con->get_local_close_reason() << std::endl;
|
||||
std::cout << con->get_remote_close_code() << std::endl;
|
||||
std::cout << con->get_remote_close_reason() << std::endl;
|
||||
std::cout << con->get_ec() << " - " << con->get_ec().message() << std::endl;
|
||||
}
|
||||
|
||||
void on_open(websocketpp::connection_hdl hdl) {
|
||||
m_open = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.send(hdl, "", websocketpp::frame::opcode::text);
|
||||
}
|
||||
void on_message(websocketpp::connection_hdl hdl, message_ptr) {
|
||||
m_message = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.close(hdl,websocketpp::close::status::going_away,"");
|
||||
}
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
m_close = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << "Socket Init: " << std::chrono::duration_cast<dur_type>(m_socket_init-m_start).count() << std::endl;
|
||||
std::cout << "TLS Init: " << std::chrono::duration_cast<dur_type>(m_tls_init-m_start).count() << std::endl;
|
||||
std::cout << "Open: " << std::chrono::duration_cast<dur_type>(m_open-m_start).count() << std::endl;
|
||||
std::cout << "Message: " << std::chrono::duration_cast<dur_type>(m_message-m_start).count() << std::endl;
|
||||
std::cout << "Close: " << std::chrono::duration_cast<dur_type>(m_close-m_start).count() << std::endl;
|
||||
}
|
||||
private:
|
||||
client m_endpoint;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
std::chrono::high_resolution_clock::time_point m_socket_init;
|
||||
std::chrono::high_resolution_clock::time_point m_tls_init;
|
||||
std::chrono::high_resolution_clock::time_point m_open;
|
||||
std::chrono::high_resolution_clock::time_point m_message;
|
||||
std::chrono::high_resolution_clock::time_point m_close;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string uri = "wss://echo.websocket.org";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
perftest endpoint;
|
||||
endpoint.start(uri);
|
||||
} 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 (debug_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
@@ -0,0 +1,23 @@
|
||||
## Debug server 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('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/debug_asio_no_tls.hpp>
|
||||
|
||||
// Custom logger
|
||||
#include <websocketpp/logger/syslog.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////// Custom Config for debugging custom policies //////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct debug_custom : public websocketpp::config::debug_asio {
|
||||
typedef debug_custom type;
|
||||
typedef debug_asio base;
|
||||
|
||||
typedef base::concurrency_type concurrency_type;
|
||||
|
||||
typedef base::request_type request_type;
|
||||
typedef base::response_type response_type;
|
||||
|
||||
typedef base::message_type message_type;
|
||||
typedef base::con_msg_manager_type con_msg_manager_type;
|
||||
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
/// Custom Logging policies
|
||||
/*typedef websocketpp::log::syslog<concurrency_type,
|
||||
websocketpp::log::elevel> elog_type;
|
||||
typedef websocketpp::log::syslog<concurrency_type,
|
||||
websocketpp::log::alevel> alog_type;
|
||||
*/
|
||||
typedef base::alog_type alog_type;
|
||||
typedef base::elog_type elog_type;
|
||||
|
||||
typedef base::rng_type rng_type;
|
||||
|
||||
struct transport_config : public base::transport_config {
|
||||
typedef type::concurrency_type concurrency_type;
|
||||
typedef type::alog_type alog_type;
|
||||
typedef type::elog_type elog_type;
|
||||
typedef type::request_type request_type;
|
||||
typedef type::response_type response_type;
|
||||
typedef websocketpp::transport::asio::basic_socket::endpoint
|
||||
socket_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
static const long timeout_open_handshake = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef websocketpp::server<debug_custom> server;
|
||||
|
||||
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 server::message_ptr message_ptr;
|
||||
|
||||
bool validate(server *, websocketpp::connection_hdl) {
|
||||
//sleep(6);
|
||||
return true;
|
||||
}
|
||||
|
||||
void on_http(server* s, websocketpp::connection_hdl hdl) {
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::string res = con->get_request_body();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "got HTTP request with " << res.size() << " bytes of body data.";
|
||||
|
||||
con->set_body(ss.str());
|
||||
con->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
|
||||
void on_fail(server* s, websocketpp::connection_hdl hdl) {
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Fail handler: " << con->get_ec() << " " << con->get_ec().message() << std::endl;
|
||||
}
|
||||
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
std::cout << "Close handler" << std::endl;
|
||||
}
|
||||
|
||||
// Define a callback to handle incoming messages
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
echo_server.set_reuse_addr(true);
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
|
||||
echo_server.set_http_handler(bind(&on_http,&echo_server,::_1));
|
||||
echo_server.set_fail_handler(bind(&on_fail,&echo_server,::_1));
|
||||
echo_server.set_close_handler(&on_close);
|
||||
|
||||
echo_server.set_validate_handler(bind(&validate,&echo_server,::_1));
|
||||
|
||||
// Listen on port 9012
|
||||
echo_server.listen(9012);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} 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 (dev)
|
||||
|
||||
#build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
#link_boost ()
|
||||
#final_target ()
|
||||
|
||||
#set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
+122
-122
@@ -1,5 +1,5 @@
|
||||
//#ifndef _WEBSOCKETPP_CPP11_STL_
|
||||
// #define _WEBSOCKETPP_CPP11_STL_
|
||||
// #define _WEBSOCKETPP_CPP11_STL_
|
||||
//#endif
|
||||
|
||||
#include <random>
|
||||
@@ -24,177 +24,177 @@
|
||||
typedef websocketpp::server<websocketpp::config::core> server;
|
||||
|
||||
/*class handler : public server::handler {
|
||||
bool validate(connection_ptr con) {
|
||||
std::cout << "handler validate" << std::endl;
|
||||
if (con->get_origin() != "http://www.example.com") {
|
||||
con->set_status(websocketpp::http::status_code::FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool validate(connection_ptr con) {
|
||||
std::cout << "handler validate" << std::endl;
|
||||
if (con->get_origin() != "http://www.example.com") {
|
||||
con->set_status(websocketpp::http::status_code::FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void http(connection_ptr con) {
|
||||
std::cout << "handler http" << std::endl;
|
||||
}
|
||||
void http(connection_ptr con) {
|
||||
std::cout << "handler http" << std::endl;
|
||||
}
|
||||
|
||||
void on_load(connection_ptr con, ptr old_handler) {
|
||||
std::cout << "handler on_load" << std::endl;
|
||||
}
|
||||
void on_unload(connection_ptr con, ptr new_handler) {
|
||||
std::cout << "handler on_unload" << std::endl;
|
||||
}
|
||||
void on_load(connection_ptr con, ptr old_handler) {
|
||||
std::cout << "handler on_load" << std::endl;
|
||||
}
|
||||
void on_unload(connection_ptr con, ptr new_handler) {
|
||||
std::cout << "handler on_unload" << std::endl;
|
||||
}
|
||||
|
||||
void on_open(connection_ptr con) {
|
||||
std::cout << "handler on_open" << std::endl;
|
||||
}
|
||||
void on_fail(connection_ptr con) {
|
||||
std::cout << "handler on_fail" << std::endl;
|
||||
}
|
||||
void on_open(connection_ptr con) {
|
||||
std::cout << "handler on_open" << std::endl;
|
||||
}
|
||||
void on_fail(connection_ptr con) {
|
||||
std::cout << "handler on_fail" << std::endl;
|
||||
}
|
||||
|
||||
void on_message(connection_ptr con, message_ptr msg) {
|
||||
std::cout << "handler on_message" << std::endl;
|
||||
void on_message(connection_ptr con, message_ptr msg) {
|
||||
std::cout << "handler on_message" << std::endl;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void on_close(connection_ptr con) {
|
||||
std::cout << "handler on_close" << std::endl;
|
||||
}
|
||||
void on_close(connection_ptr con) {
|
||||
std::cout << "handler on_close" << std::endl;
|
||||
}
|
||||
};*/
|
||||
|
||||
int main() {
|
||||
typedef websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
typedef websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
|
||||
con_msg_man_type::ptr manager(new con_msg_man_type());
|
||||
con_msg_man_type::ptr manager = websocketpp::lib::make_shared<con_msg_man_type>();
|
||||
|
||||
size_t foo = 1024;
|
||||
size_t foo = 1024;
|
||||
|
||||
message_type::ptr input = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
message_type::ptr output = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
websocketpp::frame::masking_key_type key;
|
||||
message_type::ptr input = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
message_type::ptr output = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
websocketpp::frame::masking_key_type key;
|
||||
|
||||
std::random_device dev;
|
||||
std::random_device dev;
|
||||
|
||||
|
||||
|
||||
key.i = 0x12345678;
|
||||
key.i = 0x12345678;
|
||||
|
||||
double m = 18094238402394.0824923;
|
||||
double m = 18094238402394.0824923;
|
||||
|
||||
/*std::cout << "Some Math" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
/*std::cout << "Some Math" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
for (int i = 0; i < foo; i++) {
|
||||
m /= 1.001;
|
||||
}
|
||||
for (int i = 0; i < foo; i++) {
|
||||
m /= 1.001;
|
||||
}
|
||||
|
||||
}*/
|
||||
}*/
|
||||
|
||||
std::cout << m << std::endl;
|
||||
std::cout << m << std::endl;
|
||||
|
||||
std::cout << "Random Gen" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
std::cout << "Random Gen" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
}
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
}
|
||||
|
||||
std::cout << "Out of place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
std::cout << "Out of place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(output->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(output->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
|
||||
std::cout << "In place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
std::cout << "In place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "Out of place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "Out of place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin(), key);
|
||||
}
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin(), key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "In place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "In place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), input->get_raw_payload().begin(), key);
|
||||
}
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), input->get_raw_payload().begin(), key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'a');
|
||||
output->get_raw_payload().replace(0,foo,foo,'b');
|
||||
std::cout << "Copy" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
input->get_raw_payload().replace(0,foo,foo,'a');
|
||||
output->get_raw_payload().replace(0,foo,foo,'b');
|
||||
std::cout << "Copy" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
std::copy(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin());
|
||||
}
|
||||
std::copy(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin());
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
/*server::handler::ptr h(new handler());
|
||||
/*server::handler::ptr h(new handler());
|
||||
|
||||
server test_server(h);
|
||||
server::connection_ptr con;
|
||||
server test_server(h);
|
||||
server::connection_ptr con;
|
||||
|
||||
std::stringstream output;
|
||||
std::stringstream output;
|
||||
|
||||
test_server.register_ostream(&output);
|
||||
test_server.register_ostream(&output);
|
||||
|
||||
con = test_server.get_connection();
|
||||
con = test_server.get_connection();
|
||||
|
||||
con->start();
|
||||
con->start();
|
||||
|
||||
//foo.handle_accept(con,true);
|
||||
//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\n\r\n";
|
||||
input >> *con;
|
||||
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\n\r\n";
|
||||
input >> *con;
|
||||
|
||||
std::stringstream input2;
|
||||
input2 << "messageabc2";
|
||||
input2 >> *con;
|
||||
std::stringstream input2;
|
||||
input2 << "messageabc2";
|
||||
input2 >> *con;
|
||||
|
||||
std::stringstream input3;
|
||||
input3 << "messageabc3";
|
||||
input3 >> *con;
|
||||
std::stringstream input3;
|
||||
input3 << "messageabc3";
|
||||
input3 >> *con;
|
||||
|
||||
std::stringstream input4;
|
||||
input4 << "close";
|
||||
input4 >> *con;
|
||||
std::stringstream input4;
|
||||
input4 << "close";
|
||||
input4 >> *con;
|
||||
|
||||
std::cout << "connection output:" << std::endl;
|
||||
std::cout << output.str() << std::endl;*/
|
||||
std::cout << "connection output:" << std::endl;
|
||||
std::cout << output.str() << std::endl;*/
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
@@ -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')
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
#define WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
|
||||
class echo_handler : public server::handler {
|
||||
void on_message(connection_ptr con, std::string msg) {
|
||||
con->write(msg);
|
||||
}
|
||||
void on_message(connection_ptr con, std::string msg) {
|
||||
con->write(msg);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
|
||||
@@ -19,6 +19,13 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
<< " 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 (const websocketpp::lib::error_code& e) {
|
||||
@@ -28,15 +35,15 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
try {
|
||||
// Set logging settings
|
||||
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
|
||||
@@ -48,12 +55,10 @@ int main() {
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (echo_server_both)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,24 @@
|
||||
## Combo plain+tls echo server
|
||||
##
|
||||
|
||||
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('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,87 @@
|
||||
#include <websocketpp/config/asio.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// define types for two different server endpoints, one for each config we are
|
||||
// using
|
||||
typedef websocketpp::server<websocketpp::config::asio> server_plain;
|
||||
typedef websocketpp::server<websocketpp::config::asio_tls> server_tls;
|
||||
|
||||
// alias some of the bind related functions as they are a bit long
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// type of the ssl context pointer is long so alias it
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
|
||||
// The shared on_message handler takes a template parameter so the function can
|
||||
// resolve any endpoint dependent types like message_ptr or connection_ptr
|
||||
template <typename EndpointType>
|
||||
void on_message(EndpointType* s, websocketpp::connection_hdl hdl,
|
||||
typename EndpointType::message_ptr msg)
|
||||
{
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// No change to TLS init methods from echo_server_tls
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
|
||||
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_password_callback(bind(&get_password));
|
||||
ctx->use_certificate_chain_file("server.pem");
|
||||
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// set up an external io_service to run both endpoints on. This is not
|
||||
// strictly necessary, but simplifies thread management a bit.
|
||||
boost::asio::io_service ios;
|
||||
|
||||
// set up plain endpoint
|
||||
server_plain endpoint_plain;
|
||||
// initialize asio with our external io_service rather than an internal one
|
||||
endpoint_plain.init_asio(&ios);
|
||||
endpoint_plain.set_message_handler(
|
||||
bind(&on_message<server_plain>,&endpoint_plain,::_1,::_2));
|
||||
endpoint_plain.listen(80);
|
||||
endpoint_plain.start_accept();
|
||||
|
||||
// set up tls endpoint
|
||||
server_tls endpoint_tls;
|
||||
endpoint_tls.init_asio(&ios);
|
||||
endpoint_tls.set_message_handler(
|
||||
bind(&on_message<server_tls>,&endpoint_tls,::_1,::_2));
|
||||
// TLS endpoint has an extra handler for the tls init
|
||||
endpoint_tls.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
// tls endpoint listens on a different port
|
||||
endpoint_tls.listen(443);
|
||||
endpoint_tls.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop running both endpoints
|
||||
ios.run();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,A0ED66EF872A48A9
|
||||
|
||||
gXuvKojXzApVhhPVNdRliiajbC4PtwQG5c8TA7JADLgwOR7o9t6KtXEr37bDRpvB
|
||||
9aO9P+SJaK5OOp3XKPGthOdqv+tvCRTlmzmC8GjPLBX389DWT2xoGu7JkGwDtdSm
|
||||
rnF49Rlp5bfjpACk5xKNiKeDo1CWfeEJzw9Kto0g+5eMaEdors64oPzjXs3geA2g
|
||||
TxCJSHv9qSX6++pCLKKCUTbyzidAxV/Zb0AAubt5V40QKqX4HhSwwstFnTaX3tlb
|
||||
3QOdY+y04VIkM6d7qN5W8M7NzRkMpZ1qBpQcUMpkhQcRzWP2wub5AAff9D2GntRd
|
||||
4Dz1vn3u41U3Okdr0CNj+iH7byCzuokoAhk6ZQEN6WB+GTpGgfBXdtUZrfpb0MKm
|
||||
UNYP5AF2AmUqJRXhViTDVtu/V2tHF3LGuNT+W2Dz+spFZEq0byEO0N858eR0dikc
|
||||
6jOASvNQbSwD0+mkgBC1gXKKU3ngj2gpJUwljeACdWFd8N2egrZfyI05CmX7vPNC
|
||||
NXbs7k2buWNdjP4/D8IM+HDVidWzQa/kG/qokXKqllem9Egg37lUucwnP3cX2/Hw
|
||||
U2mfaBWzeZtqc+GqRp08rYIql+Reai3sUYlQMnNk01prVY47UQb+dxuqjaxGV5Xx
|
||||
Xkx0s2mfQnNRjL4S7Hjhqelufi6GpkCQ2EGsPpA+6K1ztZ0ame9Q2BE1SXeM/6vU
|
||||
rxT5nRrCxueyXAyQSGcqMX9//gSeK8WWBqG/c1IAMVDa0NWrJeOJhSziE+ta3B0m
|
||||
bHAPBY6vh0iB3lLdRlbUOPbC6R1TpxMOs+6Vbs2+OTifFpvOVymEoZq/nroyg68P
|
||||
vn5uCKogwWA7o8EArf/UTlIwWJmH9bgILdZKld4wMel2HQg16RDzm+mEXAJi52a/
|
||||
FC+fgfphdxltmUJ+rqOyR4AHULjaTWUQqTIB6sdlzgmES1nXAiE71zX//KFqomar
|
||||
O60SPPk3C1bs0x5DsvmGJa8SIfDhyd+D7NPyqwEKqrZsaotYGklNkfqxa6pa8mrc
|
||||
ejxquW1PK4FvBk26+osu5a90Jih0PcQM7DUMMr2WHdTiMSXWAiK2ToYF8Itt25Qv
|
||||
Cd0CsSYw9CJkXNr1u1+mObheaY9QYOmztnSJLy4ZO2JsMhqNwuAueIcwmhXOREq7
|
||||
kzlnGMgJcuSeAS/OBNj8Zgx0c7QQ0kzc+YmnOCsqoMtPsu/CsXJ4iJiM3Tki/2jT
|
||||
bywrTiQwE6R3a/87GREOREX+WLicZBWX3k9/4tBL5XSe1p5wPpuIRQUDvAGNfNHP
|
||||
JN7kujDF4SehilF1qtvCygAwvxHFDj+EwhXKNDKJzoZZIM15rAk3k92n2j6nz1qH
|
||||
a3xOU05yydOlO6F6w51I1QoDddmkzCRNB0TeO3D6rekHsCK1aDWmC+qRcm2ZFtVz
|
||||
sY6fdZN2NEmMQokIh9Opi1f8CSYSizPESMzdu2SF0xVO9n/IGIkn1ksK04O2BZo0
|
||||
X3LBPHLfCRsQNY1eF17bj07fYU2oPZKs/XzJiwxkqK6LFvpeAVaYrtg9fqRO/UVe
|
||||
QhUIj3BL550ocEpa15xLehLrmwzYiW5zwGjSHQ4EgZluGLCwyKGTh4QswEJRA9Rt
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE0DCCA7igAwIBAgIJAM5MuKJezXq0MA0GCSqGSIb3DQEBBQUAMIGgMQswCQYD
|
||||
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xGDAW
|
||||
BgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0KysxFjAU
|
||||
BgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3RlckB6
|
||||
YXBob3lkLmNvbTAeFw0xMTExMTUyMTIwMDZaFw0xMjExMTQyMTIwMDZaMIGgMQsw
|
||||
CQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28x
|
||||
GDAWBgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0Kysx
|
||||
FjAUBgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3Rl
|
||||
ckB6YXBob3lkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANR0
|
||||
tdwAnIB8I9qRZ7QbzEWY95RpM7GIn0u/9oH90PzdHiE0rXSkKT+yw3XUzH0iw5t0
|
||||
5dEwSC+srSP5Vm4cA6kXc94agVVaPW89tGcdP4fHptCruSrzQsDXELCPl5UUvMpA
|
||||
YUcGisdXYPN/EeOoqb9wKWxoW5mREsyyeWWS89fYN5qU/d0QpbSvEWghqLbL/ZS2
|
||||
hOlXT9LufOeA+vHiV1/T/h5xC7ecIH02YDQw1EnqxbPmkLPcWThztLS9FiufNDRM
|
||||
Rhcoaj2b9VDHvDwdbeA0T5v5qNdG34LaapYOelxzQMOtM0f9Dgqehodyxl2qm9mR
|
||||
lq432dlOEzDnVCPNHwECAwEAAaOCAQkwggEFMB0GA1UdDgQWBBTTPKfNMnKOykhv
|
||||
+vKS7vql5JsMyzCB1QYDVR0jBIHNMIHKgBTTPKfNMnKOykhv+vKS7vql5JsMy6GB
|
||||
pqSBozCBoDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQH
|
||||
EwdDaGljYWdvMRgwFgYDVQQKEw9aYXBob3lkIFN0dWRpb3MxFDASBgNVBAsTC1dl
|
||||
YlNvY2tldCsrMRYwFAYDVQQDEw1QZXRlciBUaG9yc29uMSQwIgYJKoZIhvcNAQkB
|
||||
FhV3ZWJtYXN0ZXJAemFwaG95ZC5jb22CCQDOTLiiXs16tDAMBgNVHRMEBTADAQH/
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQB+SH0s/hrv5VYqgX6SNLzxdSLvCVsUkCdTpxwY
|
||||
wOJ84XmYcXDMhKDtZqLtOtN6pfEwVusFlC9mkieuunztCnWNmsSG83RuljJPjFSi
|
||||
1d4Id4bKEQkQ4cfnjoHKivRrViWLnxuNnLzC6tpyGH/35kKWhhr6T58AXerFgVw3
|
||||
mHvLPTr1DuhdAZA0ZuvuseVAFFAjI3RetSySwHJE3ak8KswDVfLi6E3XxMVsIWTS
|
||||
/iFsC2WwoZQlljya2V/kRYIhu+uCdqJ01wunn2BvmURPSgr4GTBF0FQ9JGpNbXxM
|
||||
TAU7oQJgyFc5sCcuEgPTO0dWVQTvdZVgay4tkmduKDRkmJBF
|
||||
-----END CERTIFICATE-----
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAqxMGKZB8YNV8WQnbJWwwwmifc+PfVRtd1FN5v5aQSsf6dpjX3Zlh
|
||||
N1NmgecsQyg4u2EWe4Umta10QzCgYaxf6QdTCg7iprLzFNw7IvWYbQ6du12NMGDr
|
||||
hmwA6KQKwbTgPL6mSlSlcK2wTP2FzxDTNffFu10cB/6Fj4kdQjPG0c1Koz/z7OOq
|
||||
BuDElJLClS8rjp3z1xvrc7gX95dFa2KaKgOAYDkpe8tfHRhHfJeIVS/whH9hzx6r
|
||||
OBg+E5K9JyvayrUoKgPeptRKCqo8A4YevtMLpRxMup0nMUgAIv6+BGTwPAFpwgl/
|
||||
8UIVcvjh1v95PwGDM/Q8yvIBJznBYk/e2wIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
@@ -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()
|
||||
@@ -27,46 +63,92 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
}
|
||||
}
|
||||
|
||||
void on_http(server* s, websocketpp::connection_hdl hdl) {
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
con->set_body("Hello World!");
|
||||
con->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
// See https://wiki.mozilla.org/Security/Server_Side_TLS for more details about
|
||||
// the TLS modes. The code below demonstrates how to implement both the modern
|
||||
enum tls_mode {
|
||||
MOZILLA_INTERMEDIATE = 1,
|
||||
MOZILLA_MODERN = 2
|
||||
};
|
||||
|
||||
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;
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
std::cout << "using TLS mode: " << (mode == MOZILLA_MODERN ? "Mozilla Modern" : "Mozilla Intermediate") << std::endl;
|
||||
|
||||
context_ptr ctx = websocketpp::lib::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
if (mode == MOZILLA_MODERN) {
|
||||
// Modern disables TLSv1
|
||||
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(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`
|
||||
// Mozilla Intermediate suggests 1024 as the minimum size to use
|
||||
// Mozilla Modern suggests 2048 as the minimum size to use.
|
||||
ctx->use_tmp_dh_file("dh.pem");
|
||||
|
||||
std::string ciphers;
|
||||
|
||||
if (mode == MOZILLA_MODERN) {
|
||||
ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";
|
||||
} else {
|
||||
ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
|
||||
}
|
||||
|
||||
if (SSL_CTX_set_cipher_list(ctx->native_handle() , ciphers.c_str()) != 1) {
|
||||
std::cout << "Error setting cipher list" << std::endl;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
std::cout << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
server echo_server;
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
echo_server.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
echo_server.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
echo_server.set_http_handler(bind(&on_http,&echo_server,::_1));
|
||||
echo_server.set_tls_init_handler(bind(&on_tls_init,MOZILLA_INTERMEDIATE,::_1));
|
||||
|
||||
// Listen on port 9002
|
||||
echo_server.listen(9002);
|
||||
|
||||
// Listen on port 9002
|
||||
echo_server.listen(9002);
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,58 +1,55 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,A0ED66EF872A48A9
|
||||
|
||||
gXuvKojXzApVhhPVNdRliiajbC4PtwQG5c8TA7JADLgwOR7o9t6KtXEr37bDRpvB
|
||||
9aO9P+SJaK5OOp3XKPGthOdqv+tvCRTlmzmC8GjPLBX389DWT2xoGu7JkGwDtdSm
|
||||
rnF49Rlp5bfjpACk5xKNiKeDo1CWfeEJzw9Kto0g+5eMaEdors64oPzjXs3geA2g
|
||||
TxCJSHv9qSX6++pCLKKCUTbyzidAxV/Zb0AAubt5V40QKqX4HhSwwstFnTaX3tlb
|
||||
3QOdY+y04VIkM6d7qN5W8M7NzRkMpZ1qBpQcUMpkhQcRzWP2wub5AAff9D2GntRd
|
||||
4Dz1vn3u41U3Okdr0CNj+iH7byCzuokoAhk6ZQEN6WB+GTpGgfBXdtUZrfpb0MKm
|
||||
UNYP5AF2AmUqJRXhViTDVtu/V2tHF3LGuNT+W2Dz+spFZEq0byEO0N858eR0dikc
|
||||
6jOASvNQbSwD0+mkgBC1gXKKU3ngj2gpJUwljeACdWFd8N2egrZfyI05CmX7vPNC
|
||||
NXbs7k2buWNdjP4/D8IM+HDVidWzQa/kG/qokXKqllem9Egg37lUucwnP3cX2/Hw
|
||||
U2mfaBWzeZtqc+GqRp08rYIql+Reai3sUYlQMnNk01prVY47UQb+dxuqjaxGV5Xx
|
||||
Xkx0s2mfQnNRjL4S7Hjhqelufi6GpkCQ2EGsPpA+6K1ztZ0ame9Q2BE1SXeM/6vU
|
||||
rxT5nRrCxueyXAyQSGcqMX9//gSeK8WWBqG/c1IAMVDa0NWrJeOJhSziE+ta3B0m
|
||||
bHAPBY6vh0iB3lLdRlbUOPbC6R1TpxMOs+6Vbs2+OTifFpvOVymEoZq/nroyg68P
|
||||
vn5uCKogwWA7o8EArf/UTlIwWJmH9bgILdZKld4wMel2HQg16RDzm+mEXAJi52a/
|
||||
FC+fgfphdxltmUJ+rqOyR4AHULjaTWUQqTIB6sdlzgmES1nXAiE71zX//KFqomar
|
||||
O60SPPk3C1bs0x5DsvmGJa8SIfDhyd+D7NPyqwEKqrZsaotYGklNkfqxa6pa8mrc
|
||||
ejxquW1PK4FvBk26+osu5a90Jih0PcQM7DUMMr2WHdTiMSXWAiK2ToYF8Itt25Qv
|
||||
Cd0CsSYw9CJkXNr1u1+mObheaY9QYOmztnSJLy4ZO2JsMhqNwuAueIcwmhXOREq7
|
||||
kzlnGMgJcuSeAS/OBNj8Zgx0c7QQ0kzc+YmnOCsqoMtPsu/CsXJ4iJiM3Tki/2jT
|
||||
bywrTiQwE6R3a/87GREOREX+WLicZBWX3k9/4tBL5XSe1p5wPpuIRQUDvAGNfNHP
|
||||
JN7kujDF4SehilF1qtvCygAwvxHFDj+EwhXKNDKJzoZZIM15rAk3k92n2j6nz1qH
|
||||
a3xOU05yydOlO6F6w51I1QoDddmkzCRNB0TeO3D6rekHsCK1aDWmC+qRcm2ZFtVz
|
||||
sY6fdZN2NEmMQokIh9Opi1f8CSYSizPESMzdu2SF0xVO9n/IGIkn1ksK04O2BZo0
|
||||
X3LBPHLfCRsQNY1eF17bj07fYU2oPZKs/XzJiwxkqK6LFvpeAVaYrtg9fqRO/UVe
|
||||
QhUIj3BL550ocEpa15xLehLrmwzYiW5zwGjSHQ4EgZluGLCwyKGTh4QswEJRA9Rt
|
||||
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 CERTIFICATE-----
|
||||
MIIE0DCCA7igAwIBAgIJAM5MuKJezXq0MA0GCSqGSIb3DQEBBQUAMIGgMQswCQYD
|
||||
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xGDAW
|
||||
BgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0KysxFjAU
|
||||
BgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3RlckB6
|
||||
YXBob3lkLmNvbTAeFw0xMTExMTUyMTIwMDZaFw0xMjExMTQyMTIwMDZaMIGgMQsw
|
||||
CQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28x
|
||||
GDAWBgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0Kysx
|
||||
FjAUBgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3Rl
|
||||
ckB6YXBob3lkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANR0
|
||||
tdwAnIB8I9qRZ7QbzEWY95RpM7GIn0u/9oH90PzdHiE0rXSkKT+yw3XUzH0iw5t0
|
||||
5dEwSC+srSP5Vm4cA6kXc94agVVaPW89tGcdP4fHptCruSrzQsDXELCPl5UUvMpA
|
||||
YUcGisdXYPN/EeOoqb9wKWxoW5mREsyyeWWS89fYN5qU/d0QpbSvEWghqLbL/ZS2
|
||||
hOlXT9LufOeA+vHiV1/T/h5xC7ecIH02YDQw1EnqxbPmkLPcWThztLS9FiufNDRM
|
||||
Rhcoaj2b9VDHvDwdbeA0T5v5qNdG34LaapYOelxzQMOtM0f9Dgqehodyxl2qm9mR
|
||||
lq432dlOEzDnVCPNHwECAwEAAaOCAQkwggEFMB0GA1UdDgQWBBTTPKfNMnKOykhv
|
||||
+vKS7vql5JsMyzCB1QYDVR0jBIHNMIHKgBTTPKfNMnKOykhv+vKS7vql5JsMy6GB
|
||||
pqSBozCBoDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQH
|
||||
EwdDaGljYWdvMRgwFgYDVQQKEw9aYXBob3lkIFN0dWRpb3MxFDASBgNVBAsTC1dl
|
||||
YlNvY2tldCsrMRYwFAYDVQQDEw1QZXRlciBUaG9yc29uMSQwIgYJKoZIhvcNAQkB
|
||||
FhV3ZWJtYXN0ZXJAemFwaG95ZC5jb22CCQDOTLiiXs16tDAMBgNVHRMEBTADAQH/
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQB+SH0s/hrv5VYqgX6SNLzxdSLvCVsUkCdTpxwY
|
||||
wOJ84XmYcXDMhKDtZqLtOtN6pfEwVusFlC9mkieuunztCnWNmsSG83RuljJPjFSi
|
||||
1d4Id4bKEQkQ4cfnjoHKivRrViWLnxuNnLzC6tpyGH/35kKWhhr6T58AXerFgVw3
|
||||
mHvLPTr1DuhdAZA0ZuvuseVAFFAjI3RetSySwHJE3ak8KswDVfLi6E3XxMVsIWTS
|
||||
/iFsC2WwoZQlljya2V/kRYIhu+uCdqJ01wunn2BvmURPSgr4GTBF0FQ9JGpNbXxM
|
||||
TAU7oQJgyFc5sCcuEgPTO0dWVQTvdZVgay4tkmduKDRkmJBF
|
||||
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==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
|
||||
@@ -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")
|
||||
@@ -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::lib::error_code const & e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << 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;
|
||||
};
|
||||
@@ -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")
|
||||
@@ -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")
|
||||
@@ -18,17 +18,17 @@ typedef server::message_ptr message_ptr;
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Text Message Received: "+msg->get_payload());
|
||||
"Text Message Received: "+msg->get_payload());
|
||||
} else {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Binary Message Received: "+websocketpp::utility::to_hex(msg->get_payload()));
|
||||
"Binary Message Received: "+websocketpp::utility::to_hex(msg->get_payload()));
|
||||
}
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Echo Failed: "+e.message());
|
||||
"Echo Failed: "+e.message());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ int main() {
|
||||
server s;
|
||||
std::ofstream log;
|
||||
|
||||
try {
|
||||
try {
|
||||
// set up access channels to only log interesting things
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.set_access_channels(websocketpp::log::alevel::connect);
|
||||
@@ -82,12 +82,8 @@ int main() {
|
||||
}
|
||||
con->eof();
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::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;
|
||||
}
|
||||
log.close();
|
||||
}
|
||||
|
||||
@@ -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,7 +5,7 @@
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg) {
|
||||
void on_message(websocketpp::connection_hdl, server::message_ptr msg) {
|
||||
std::cout << msg->get_payload() << std::endl;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ int main() {
|
||||
server print_server;
|
||||
|
||||
print_server.set_message_handler(&on_message);
|
||||
print_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
print_server.set_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
print_server.init_asio();
|
||||
print_server.listen(9002);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
## Scratch client 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('scratch_client', ["scratch_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')
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
// **NOTE:** This file is a snapshot of the WebSocket++ utility client tutorial.
|
||||
// Additional related material can be found in the tutorials/utility_client
|
||||
// directory of the WebSocket++ repository.
|
||||
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
#include <websocketpp/common/memory.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
class connection_metadata {
|
||||
public:
|
||||
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
|
||||
|
||||
connection_metadata(int id, websocketpp::connection_hdl hdl, std::string uri)
|
||||
: m_id(id)
|
||||
, m_hdl(hdl)
|
||||
, m_status("Connecting")
|
||||
, m_uri(uri)
|
||||
, m_server("N/A")
|
||||
{}
|
||||
|
||||
void on_open(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Open";
|
||||
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
}
|
||||
|
||||
void on_fail(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Failed";
|
||||
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
m_error_reason = con->get_ec().message();
|
||||
}
|
||||
|
||||
void on_close(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Closed";
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
std::stringstream s;
|
||||
s << "close code: " << con->get_remote_close_code() << " ("
|
||||
<< websocketpp::close::status::get_string(con->get_remote_close_code())
|
||||
<< "), close reason: " << con->get_remote_close_reason();
|
||||
m_error_reason = s.str();
|
||||
}
|
||||
|
||||
websocketpp::connection_hdl get_hdl() const {
|
||||
return m_hdl;
|
||||
}
|
||||
|
||||
int get_id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
std::string get_status() const {
|
||||
return m_status;
|
||||
}
|
||||
|
||||
friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data);
|
||||
private:
|
||||
int m_id;
|
||||
websocketpp::connection_hdl m_hdl;
|
||||
std::string m_status;
|
||||
std::string m_uri;
|
||||
std::string m_server;
|
||||
std::string m_error_reason;
|
||||
};
|
||||
|
||||
std::ostream & operator<< (std::ostream & out, connection_metadata const & data) {
|
||||
out << "> URI: " << data.m_uri << "\n"
|
||||
<< "> Status: " << data.m_status << "\n"
|
||||
<< "> Remote Server: " << (data.m_server.empty() ? "None Specified" : data.m_server) << "\n"
|
||||
<< "> Error/close reason: " << (data.m_error_reason.empty() ? "N/A" : data.m_error_reason);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
class websocket_endpoint {
|
||||
public:
|
||||
websocket_endpoint () : m_next_id(0) {
|
||||
m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
m_endpoint.init_asio();
|
||||
m_endpoint.start_perpetual();
|
||||
|
||||
m_thread.reset(new websocketpp::lib::thread(&client::run, &m_endpoint));
|
||||
}
|
||||
|
||||
~websocket_endpoint() {
|
||||
m_endpoint.stop_perpetual();
|
||||
|
||||
for (con_list::const_iterator it = m_connection_list.begin(); it != m_connection_list.end(); ++it) {
|
||||
if (it->second->get_status() != "Open") {
|
||||
// Only close open connections
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "> Closing connection " << it->second->get_id() << std::endl;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
m_endpoint.close(it->second->get_hdl(), websocketpp::close::status::going_away, "", ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error closing connection " << it->second->get_id() << ": "
|
||||
<< ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_thread->join();
|
||||
}
|
||||
|
||||
int connect(std::string const & uri) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
client::connection_ptr con = m_endpoint.get_connection(uri, ec);
|
||||
|
||||
if (ec) {
|
||||
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int new_id = m_next_id++;
|
||||
connection_metadata::ptr metadata_ptr(new connection_metadata(new_id, con->get_handle(), uri));
|
||||
m_connection_list[new_id] = metadata_ptr;
|
||||
|
||||
con->set_open_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_open,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_fail_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_fail,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_close_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_close,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void close(int id, websocketpp::close::status::value code, std::string reason) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
con_list::iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
std::cout << "> No connection found with id " << id << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_endpoint.close(metadata_it->second->get_hdl(), code, reason, ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error initiating close: " << ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
connection_metadata::ptr get_metadata(int id) const {
|
||||
con_list::const_iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
return connection_metadata::ptr();
|
||||
} else {
|
||||
return metadata_it->second;
|
||||
}
|
||||
}
|
||||
private:
|
||||
typedef std::map<int,connection_metadata::ptr> con_list;
|
||||
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
|
||||
con_list m_connection_list;
|
||||
int m_next_id;
|
||||
};
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
websocket_endpoint endpoint;
|
||||
|
||||
while (!done) {
|
||||
std::cout << "Enter Command: ";
|
||||
std::getline(std::cin, input);
|
||||
|
||||
if (input == "quit") {
|
||||
done = true;
|
||||
} else if (input == "help") {
|
||||
std::cout
|
||||
<< "\nCommand List:\n"
|
||||
<< "connect <ws uri>\n"
|
||||
<< "close <connection id> [<close code:default=1000>] [<close reason>]\n"
|
||||
<< "show <connection id>\n"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else if (input.substr(0,7) == "connect") {
|
||||
int id = endpoint.connect(input.substr(8));
|
||||
if (id != -1) {
|
||||
std::cout << "> Created connection with id " << id << std::endl;
|
||||
}
|
||||
} else if (input.substr(0,5) == "close") {
|
||||
std::stringstream ss(input);
|
||||
|
||||
std::string cmd;
|
||||
int id;
|
||||
int close_code = websocketpp::close::status::normal;
|
||||
std::string reason;
|
||||
|
||||
ss >> cmd >> id >> close_code;
|
||||
std::getline(ss,reason);
|
||||
|
||||
endpoint.close(id, close_code, reason);
|
||||
} else if (input.substr(0,4) == "show") {
|
||||
int id = atoi(input.substr(5).c_str());
|
||||
|
||||
connection_metadata::ptr metadata = endpoint.get_metadata(id);
|
||||
if (metadata) {
|
||||
std::cout << *metadata << std::endl;
|
||||
} else {
|
||||
std::cout << "> Unknown connection id " << id << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "> Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
## Scratch server 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] + ['z']
|
||||
prgs += env_cpp11.Program('scratch_server', ["scratch_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs] + ['z']
|
||||
prgs += env.Program('scratch_server', ["scratch_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <websocketpp/config/debug_asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
|
||||
|
||||
struct deflate_config : public websocketpp::config::debug_core {
|
||||
typedef deflate_config type;
|
||||
typedef debug_core base;
|
||||
|
||||
typedef base::concurrency_type concurrency_type;
|
||||
|
||||
typedef base::request_type request_type;
|
||||
typedef base::response_type response_type;
|
||||
|
||||
typedef base::message_type message_type;
|
||||
typedef base::con_msg_manager_type con_msg_manager_type;
|
||||
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
typedef base::alog_type alog_type;
|
||||
typedef base::elog_type elog_type;
|
||||
|
||||
typedef base::rng_type rng_type;
|
||||
|
||||
struct transport_config : public base::transport_config {
|
||||
typedef type::concurrency_type concurrency_type;
|
||||
typedef type::alog_type alog_type;
|
||||
typedef type::elog_type elog_type;
|
||||
typedef type::request_type request_type;
|
||||
typedef type::response_type response_type;
|
||||
typedef websocketpp::transport::asio::basic_socket::endpoint
|
||||
socket_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
/// permessage_compress extension
|
||||
struct permessage_deflate_config {};
|
||||
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<deflate_config> server;
|
||||
|
||||
typedef server::message_ptr message_ptr;
|
||||
|
||||
// Define a callback to handle incoming messages
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
/*std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message (" << msg->get_payload().size() << "): " << msg->get_payload()
|
||||
<< std::endl;
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
if (argc > 1 && std::string(argv[1]) == "-d") {
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.set_error_channels(websocketpp::log::elevel::all);
|
||||
} else {
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::none);
|
||||
echo_server.set_error_channels(websocketpp::log::elevel::none);
|
||||
}
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,_1,_2));
|
||||
|
||||
// Listen on port 9002
|
||||
echo_server.listen(9002);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} 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")
|
||||
@@ -9,3 +9,4 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -43,13 +43,13 @@ void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
std::string uri = "ws://localhost:9001";
|
||||
std::string uri = "ws://localhost:9001";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
// We expect there to be a lot of errors, so suppress them
|
||||
sip_client.clear_access_channels(websocketpp::log::alevel::all);
|
||||
sip_client.clear_error_channels(websocketpp::log::elevel::all);
|
||||
@@ -69,7 +69,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
sip_client.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// Start the ASIO io_service run loop
|
||||
sip_client.run();
|
||||
|
||||
while(!received) {
|
||||
@@ -78,11 +78,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
std::cout << "done" << std::endl;
|
||||
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
@@ -42,11 +42,7 @@ int main() {
|
||||
s.start_accept();
|
||||
|
||||
s.run();
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
@@ -30,20 +30,20 @@ public:
|
||||
// Bind the handlers we are using
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::bind;
|
||||
m_client.set_open_handler(bind(&telemetry_client::on_open,this,::_1));
|
||||
m_client.set_close_handler(bind(&telemetry_client::on_close,this,::_1));
|
||||
m_client.set_fail_handler(bind(&telemetry_client::on_fail,this,::_1));
|
||||
m_client.set_open_handler(bind(&telemetry_client::on_open,this,_1));
|
||||
m_client.set_close_handler(bind(&telemetry_client::on_close,this,_1));
|
||||
m_client.set_fail_handler(bind(&telemetry_client::on_fail,this,_1));
|
||||
}
|
||||
|
||||
// This method will block until the connection is complete
|
||||
void run(const std::string & uri) {
|
||||
// Create a new connection to the given URI
|
||||
// Create a new connection to the given URI
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = m_client.get_connection(uri, ec);
|
||||
if (ec) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Get Connection Error: "+ec.message());
|
||||
return;
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Get Connection Error: "+ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab a handle for this connection so we can talk to it in a thread
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
|
||||
// The open handler will signal that we are ready to start sending telemetry
|
||||
void on_open(websocketpp::connection_hdl hdl) {
|
||||
void on_open(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection opened, starting telemetry!");
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
}
|
||||
|
||||
// The close handler will signal that we should stop sending telemetry
|
||||
void on_close(websocketpp::connection_hdl hdl) {
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection closed, stopping telemetry!");
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
}
|
||||
|
||||
// The fail handler will signal that we should stop sending telemetry
|
||||
void on_fail(websocketpp::connection_hdl hdl) {
|
||||
void on_fail(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection failed, stopping telemetry!");
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
// in this simple example, we'll stop the telemetry loop.
|
||||
if (ec) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Send Error: "+ec.message());
|
||||
"Send Error: "+ec.message());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (telemetry_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
@@ -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('telemetry_server', ["telemetry_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('telemetry_server', ["telemetry_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
@@ -0,0 +1,85 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebSocket++ Telemetry Client</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ws;
|
||||
var url;
|
||||
|
||||
function connect() {
|
||||
url = document.getElementById("server_url").value;
|
||||
|
||||
if ("WebSocket" in window) {
|
||||
ws = new WebSocket(url);
|
||||
} else if ("MozWebSocket" in window) {
|
||||
ws = new MozWebSocket(url);
|
||||
} else {
|
||||
document.getElementById("messages").innerHTML += "This Browser does not support WebSockets<br />";
|
||||
return;
|
||||
}
|
||||
ws.onopen = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: A connection to "+ws.url+" has been opened.<br />";
|
||||
|
||||
document.getElementById("server_url").disabled = true;
|
||||
document.getElementById("toggle_connect").innerHTML = "Disconnect";
|
||||
};
|
||||
|
||||
ws.onerror = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.<br />";
|
||||
console.log(e);
|
||||
};
|
||||
|
||||
ws.onclose = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed. ["+e.code+(e.reason != "" ? ","+e.reason : "")+"]<br />";
|
||||
cleanup_disconnect();
|
||||
};
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Server: "+e.data+"<br />";
|
||||
};
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
ws.close();
|
||||
cleanup_disconnect();
|
||||
}
|
||||
|
||||
function cleanup_disconnect() {
|
||||
document.getElementById("server_url").disabled = false;
|
||||
document.getElementById("toggle_connect").innerHTML = "Connect";
|
||||
}
|
||||
|
||||
function toggle_connect() {
|
||||
if (document.getElementById("server_url").disabled === false) {
|
||||
connect();
|
||||
} else {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body,html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
#controls {
|
||||
float:right;
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="controls">
|
||||
<div id="server">
|
||||
<input type="text" name="server_url" id="server_url" value="ws://localhost:9002" /><br />
|
||||
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="messages"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,203 @@
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* The telemetry server accepts connections and sends a message every second to
|
||||
* each client containing an integer count. This example can be used as the
|
||||
* basis for programs that expose a stream of telemetry data for logging,
|
||||
* dashboards, etc.
|
||||
*
|
||||
* This example uses the timer based concurrency method and is self contained
|
||||
* and singled threaded. Refer to telemetry client for an example of a similar
|
||||
* telemetry setup using threads rather than timers.
|
||||
*
|
||||
* This example also includes an example simple HTTP server that serves a web
|
||||
* dashboard displaying the count. This simple design is suitable for use
|
||||
* delivering a small number of files to a small number of clients. It is ideal
|
||||
* for cases like embedded dashboards that don't want the complexity of an extra
|
||||
* HTTP server to serve static files.
|
||||
*
|
||||
* This design *will* fall over under high traffic or DoS conditions. In such
|
||||
* cases you are much better off proxying to a real HTTP server for the http
|
||||
* requests.
|
||||
*/
|
||||
class telemetry_server {
|
||||
public:
|
||||
typedef websocketpp::connection_hdl connection_hdl;
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
telemetry_server() : m_count(0) {
|
||||
// set up access channels to only log interesting things
|
||||
m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.set_access_channels(websocketpp::log::alevel::access_core);
|
||||
m_endpoint.set_access_channels(websocketpp::log::alevel::app);
|
||||
|
||||
// Initialize the Asio transport policy
|
||||
m_endpoint.init_asio();
|
||||
|
||||
// Bind the handlers we are using
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::bind;
|
||||
m_endpoint.set_open_handler(bind(&telemetry_server::on_open,this,_1));
|
||||
m_endpoint.set_close_handler(bind(&telemetry_server::on_close,this,_1));
|
||||
m_endpoint.set_http_handler(bind(&telemetry_server::on_http,this,_1));
|
||||
}
|
||||
|
||||
void run(std::string docroot, uint16_t port) {
|
||||
std::stringstream ss;
|
||||
ss << "Running telemetry server on port "<< port <<" using docroot=" << docroot;
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,ss.str());
|
||||
|
||||
m_docroot = docroot;
|
||||
|
||||
// listen on specified port
|
||||
m_endpoint.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
m_endpoint.start_accept();
|
||||
|
||||
// Set the initial timer to start telemetry
|
||||
set_timer();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
try {
|
||||
m_endpoint.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void set_timer() {
|
||||
m_timer = m_endpoint.set_timer(
|
||||
1000,
|
||||
websocketpp::lib::bind(
|
||||
&telemetry_server::on_timer,
|
||||
this,
|
||||
websocketpp::lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void on_timer(websocketpp::lib::error_code const & ec) {
|
||||
if (ec) {
|
||||
// there was an error, stop telemetry
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Timer Error: "+ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream val;
|
||||
val << "count is " << m_count++;
|
||||
|
||||
// Broadcast count to all connections
|
||||
con_list::iterator it;
|
||||
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
|
||||
m_endpoint.send(*it,val.str(),websocketpp::frame::opcode::text);
|
||||
}
|
||||
|
||||
// set timer for next telemetry check
|
||||
set_timer();
|
||||
}
|
||||
|
||||
void on_http(connection_hdl hdl) {
|
||||
// Upgrade our connection handle to a full connection_ptr
|
||||
server::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
|
||||
|
||||
std::ifstream file;
|
||||
std::string filename = con->get_resource();
|
||||
std::string response;
|
||||
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,
|
||||
"http request1: "+filename);
|
||||
|
||||
if (filename == "/") {
|
||||
filename = m_docroot+"index.html";
|
||||
} else {
|
||||
filename = m_docroot+filename.substr(1);
|
||||
}
|
||||
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,
|
||||
"http request2: "+filename);
|
||||
|
||||
file.open(filename.c_str(), std::ios::in);
|
||||
if (!file) {
|
||||
// 404 error
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "<!doctype html><html><head>"
|
||||
<< "<title>Error 404 (Resource not found)</title><body>"
|
||||
<< "<h1>Error 404</h1>"
|
||||
<< "<p>The requested URL " << filename << " was not found on this server.</p>"
|
||||
<< "</body></head></html>";
|
||||
|
||||
con->set_body(ss.str());
|
||||
con->set_status(websocketpp::http::status_code::not_found);
|
||||
return;
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
response.reserve(file.tellg());
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
response.assign((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
con->set_body(response);
|
||||
con->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
m_connections.insert(hdl);
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
m_connections.erase(hdl);
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
server m_endpoint;
|
||||
con_list m_connections;
|
||||
server::timer_ptr m_timer;
|
||||
|
||||
std::string m_docroot;
|
||||
|
||||
// Telemetry data
|
||||
uint64_t m_count;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
telemetry_server s;
|
||||
|
||||
std::string docroot;
|
||||
uint16_t port = 9002;
|
||||
|
||||
if (argc == 1) {
|
||||
std::cout << "Usage: telemetry_server [documentroot] [port]" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc >= 2) {
|
||||
docroot = std::string(argv[1]);
|
||||
}
|
||||
|
||||
if (argc >= 3) {
|
||||
int i = atoi(argv[2]);
|
||||
if (i <= 0 || i > 65535) {
|
||||
std::cout << "invalid port" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
port = uint16_t(i);
|
||||
}
|
||||
|
||||
s.run(docroot, port);
|
||||
return 0;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -14,10 +14,10 @@ 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]
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
prgs += env_cpp11.Program('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
prgs += env.Program('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
|
||||
@@ -1,10 +1,75 @@
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
/*
|
||||
* 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 <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
struct deflate_config : public websocketpp::config::asio_client {
|
||||
typedef deflate_config type;
|
||||
typedef asio_client base;
|
||||
|
||||
typedef base::concurrency_type concurrency_type;
|
||||
|
||||
typedef base::request_type request_type;
|
||||
typedef base::response_type response_type;
|
||||
|
||||
typedef base::message_type message_type;
|
||||
typedef base::con_msg_manager_type con_msg_manager_type;
|
||||
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
typedef base::alog_type alog_type;
|
||||
typedef base::elog_type elog_type;
|
||||
|
||||
typedef base::rng_type rng_type;
|
||||
|
||||
struct transport_config : public base::transport_config {
|
||||
typedef type::concurrency_type concurrency_type;
|
||||
typedef type::alog_type alog_type;
|
||||
typedef type::elog_type elog_type;
|
||||
typedef type::request_type request_type;
|
||||
typedef type::response_type response_type;
|
||||
typedef websocketpp::transport::asio::basic_socket::endpoint
|
||||
socket_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
/// permessage_compress extension
|
||||
struct permessage_deflate_config {};
|
||||
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::client<deflate_config> client;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
@@ -28,16 +93,16 @@ void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Create a server endpoint
|
||||
// Create a server endpoint
|
||||
client c;
|
||||
|
||||
std::string uri = "ws://localhost:9001";
|
||||
std::string uri = "ws://localhost:9001";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
// We expect there to be a lot of errors, so suppress them
|
||||
c.clear_access_channels(websocketpp::log::alevel::all);
|
||||
c.clear_error_channels(websocketpp::log::elevel::all);
|
||||
@@ -52,7 +117,7 @@ int main(int argc, char* argv[]) {
|
||||
client::connection_ptr con = c.get_connection(uri+"/getCaseCount", ec);
|
||||
c.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// Start the ASIO io_service run loop
|
||||
c.run();
|
||||
|
||||
std::cout << "case count: " << case_count << std::endl;
|
||||
@@ -74,11 +139,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
std::cout << "done" << std::endl;
|
||||
|
||||
} catch (const std::exception & e) {
|
||||
} catch (websocketpp::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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
@@ -6,7 +6,6 @@ Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
@@ -15,10 +14,10 @@ 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]
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
prgs += env_cpp11.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
prgs += env.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* 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:
|
||||
@@ -25,37 +25,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
//#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/config/asio.hpp>
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <websocketpp/message_buffer/fixed.hpp>
|
||||
|
||||
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
//std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::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);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
struct testee_config : public websocketpp::config::asio {
|
||||
// pull default settings from our core config
|
||||
typedef websocketpp::config::asio core;
|
||||
@@ -67,11 +41,6 @@ struct testee_config : public websocketpp::config::asio {
|
||||
typedef core::con_msg_manager_type con_msg_manager_type;
|
||||
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
//typedef websocketpp::message_buffer::fixed::policy::message message_type;
|
||||
//typedef websocketpp::message_buffer::fixed::policy::con_msg_manager con_msg_manager_type;
|
||||
////typedef websocketpp::message_buffer::fixed::policy::con_msg_manager endpoint_msg_manager_type;
|
||||
//typedef websocketpp::message_buffer::fixed::policy::endpoint_msg_manager endpoint_msg_manager_type;
|
||||
|
||||
typedef core::alog_type alog_type;
|
||||
typedef core::elog_type elog_type;
|
||||
typedef core::rng_type rng_type;
|
||||
@@ -96,6 +65,12 @@ struct testee_config : public websocketpp::config::asio {
|
||||
websocketpp::log::elevel::none;
|
||||
static const websocketpp::log::level alog_level =
|
||||
websocketpp::log::alevel::none;
|
||||
|
||||
/// permessage_compress extension
|
||||
struct permessage_deflate_config {};
|
||||
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<testee_config> server;
|
||||
@@ -112,8 +87,13 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
}
|
||||
|
||||
void on_socket_init(websocketpp::connection_hdl, boost::asio::ip::tcp::socket & s) {
|
||||
boost::asio::ip::tcp::no_delay option(true);
|
||||
s.set_option(option);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
// Create a server endpoint
|
||||
// Create a server endpoint
|
||||
server testee_server;
|
||||
|
||||
short port = 9002;
|
||||
@@ -124,44 +104,42 @@ int main(int argc, char * argv[]) {
|
||||
num_threads = atoi(argv[2]);
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
// Total silence
|
||||
//testee_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||
//testee_server.clear_error_channels(websocketpp::log::alevel::all);
|
||||
testee_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||
testee_server.clear_error_channels(websocketpp::log::alevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
testee_server.init_asio();
|
||||
testee_server.set_reuse_addr(true);
|
||||
|
||||
// Register our message handler
|
||||
testee_server.set_message_handler(bind(&on_message,&testee_server,::_1,::_2));
|
||||
//testee_server.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
testee_server.set_socket_init_handler(bind(&on_socket_init,::_1,::_2));
|
||||
|
||||
|
||||
// Listen on port
|
||||
// Listen on specified port with extended listen backlog
|
||||
testee_server.set_listen_backlog(8192);
|
||||
testee_server.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
testee_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
// Start the ASIO io_service run loop
|
||||
if (num_threads == 1) {
|
||||
testee_server.run();
|
||||
} else {
|
||||
typedef websocketpp::lib::shared_ptr<websocketpp::lib::thread> thread_ptr;
|
||||
std::vector<thread_ptr> ts;
|
||||
for (size_t i = 0; i < num_threads; i++) {
|
||||
ts.push_back(thread_ptr(new websocketpp::lib::thread(&server::run, &testee_server)));
|
||||
ts.push_back(websocketpp::lib::make_shared<websocketpp::lib::thread>(&server::run, &testee_server));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_threads; i++) {
|
||||
ts[i]->join();
|
||||
}
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << "exception: " << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << "error code: " << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (utility_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples")
|
||||
|
||||
@@ -6,7 +6,6 @@ Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
@@ -15,10 +14,10 @@ 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]
|
||||
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] + [tls_libs]
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
Return('prgs')
|
||||
@@ -1,166 +1,325 @@
|
||||
/**
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
/*
|
||||
* Copyright (c) 2014, 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>
|
||||
// **NOTE:** This file is a snapshot of the WebSocket++ utility client tutorial.
|
||||
// Additional related material can be found in the tutorials/utility_client
|
||||
// directory of the WebSocket++ repository.
|
||||
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
#include <websocketpp/common/memory.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
|
||||
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_tls_client::message_type::ptr message_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
typedef client::connection_ptr connection_ptr;
|
||||
|
||||
|
||||
|
||||
class perftest {
|
||||
class connection_metadata {
|
||||
public:
|
||||
typedef perftest type;
|
||||
typedef std::chrono::duration<int,std::micro> dur_type;
|
||||
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
|
||||
|
||||
perftest () {
|
||||
m_endpoint.set_access_channels(websocketpp::log::alevel::none);
|
||||
m_endpoint.set_error_channels(websocketpp::log::elevel::none);
|
||||
connection_metadata(int id, websocketpp::connection_hdl hdl, std::string uri)
|
||||
: m_id(id)
|
||||
, m_hdl(hdl)
|
||||
, m_status("Connecting")
|
||||
, m_uri(uri)
|
||||
, m_server("N/A")
|
||||
{}
|
||||
|
||||
// Initialize ASIO
|
||||
m_endpoint.init_asio();
|
||||
void on_open(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Open";
|
||||
|
||||
// Register our handlers
|
||||
m_endpoint.set_tls_init_handler(bind(&type::on_tls_init,this,::_1));
|
||||
|
||||
m_endpoint.set_tcp_pre_init_handler(bind(&type::on_tcp_pre_init,this,::_1));
|
||||
m_endpoint.set_tcp_post_init_handler(bind(&type::on_tcp_post_init,this,::_1));
|
||||
m_endpoint.set_socket_init_handler(bind(&type::on_socket_init,this,::_1));
|
||||
m_endpoint.set_message_handler(bind(&type::on_message,this,::_1,::_2));
|
||||
m_endpoint.set_open_handler(bind(&type::on_open,this,::_1));
|
||||
m_endpoint.set_close_handler(bind(&type::on_close,this,::_1));
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
}
|
||||
|
||||
void start(std::string uri) {
|
||||
void on_fail(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Failed";
|
||||
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
m_error_reason = con->get_ec().message();
|
||||
}
|
||||
|
||||
void on_close(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Closed";
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
std::stringstream s;
|
||||
s << "close code: " << con->get_remote_close_code() << " ("
|
||||
<< websocketpp::close::status::get_string(con->get_remote_close_code())
|
||||
<< "), close reason: " << con->get_remote_close_reason();
|
||||
m_error_reason = s.str();
|
||||
}
|
||||
|
||||
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
|
||||
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
|
||||
m_messages.push_back("<< " + msg->get_payload());
|
||||
} else {
|
||||
m_messages.push_back("<< " + websocketpp::utility::to_hex(msg->get_payload()));
|
||||
}
|
||||
}
|
||||
|
||||
websocketpp::connection_hdl get_hdl() const {
|
||||
return m_hdl;
|
||||
}
|
||||
|
||||
int get_id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
std::string get_status() const {
|
||||
return m_status;
|
||||
}
|
||||
|
||||
void record_sent_message(std::string message) {
|
||||
m_messages.push_back(">> " + message);
|
||||
}
|
||||
|
||||
friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data);
|
||||
private:
|
||||
int m_id;
|
||||
websocketpp::connection_hdl m_hdl;
|
||||
std::string m_status;
|
||||
std::string m_uri;
|
||||
std::string m_server;
|
||||
std::string m_error_reason;
|
||||
std::vector<std::string> m_messages;
|
||||
};
|
||||
|
||||
std::ostream & operator<< (std::ostream & out, connection_metadata const & data) {
|
||||
out << "> URI: " << data.m_uri << "\n"
|
||||
<< "> Status: " << data.m_status << "\n"
|
||||
<< "> Remote Server: " << (data.m_server.empty() ? "None Specified" : data.m_server) << "\n"
|
||||
<< "> Error/close reason: " << (data.m_error_reason.empty() ? "N/A" : data.m_error_reason) << "\n";
|
||||
out << "> Messages Processed: (" << data.m_messages.size() << ") \n";
|
||||
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = data.m_messages.begin(); it != data.m_messages.end(); ++it) {
|
||||
out << *it << "\n";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
class websocket_endpoint {
|
||||
public:
|
||||
websocket_endpoint () : m_next_id(0) {
|
||||
m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
m_endpoint.init_asio();
|
||||
m_endpoint.start_perpetual();
|
||||
|
||||
m_thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_endpoint);
|
||||
}
|
||||
|
||||
~websocket_endpoint() {
|
||||
m_endpoint.stop_perpetual();
|
||||
|
||||
for (con_list::const_iterator it = m_connection_list.begin(); it != m_connection_list.end(); ++it) {
|
||||
if (it->second->get_status() != "Open") {
|
||||
// Only close open connections
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "> Closing connection " << it->second->get_id() << std::endl;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
m_endpoint.close(it->second->get_hdl(), websocketpp::close::status::going_away, "", ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error closing connection " << it->second->get_id() << ": "
|
||||
<< ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_thread->join();
|
||||
}
|
||||
|
||||
int connect(std::string const & uri) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
client::connection_ptr con = m_endpoint.get_connection(uri, ec);
|
||||
|
||||
if (ec) {
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message());
|
||||
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//con->set_proxy("http://humupdates.uchicago.edu:8443");
|
||||
int new_id = m_next_id++;
|
||||
connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(new_id, con->get_handle(), uri);
|
||||
m_connection_list[new_id] = metadata_ptr;
|
||||
|
||||
con->set_open_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_open,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_fail_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_fail,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_close_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_close,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_message_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_message,
|
||||
metadata_ptr,
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2
|
||||
));
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
m_start = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.run();
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void on_tcp_pre_init(websocketpp::connection_hdl hdl) {
|
||||
m_tcp_pre_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
void on_tcp_post_init(websocketpp::connection_hdl hdl) {
|
||||
m_tcp_post_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
void on_socket_init(websocketpp::connection_hdl hdl) {
|
||||
m_socket_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
void close(int id, websocketpp::close::status::value code, std::string reason) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
con_list::iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
std::cout << "> No connection found with id " << id << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_endpoint.close(metadata_it->second->get_hdl(), code, reason, ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error initiating close: " << ec.message() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void on_open(websocketpp::connection_hdl hdl) {
|
||||
m_open = std::chrono::high_resolution_clock::now();
|
||||
|
||||
client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
|
||||
|
||||
m_msg = con->get_message(websocketpp::frame::opcode::text,64);
|
||||
m_msg->append_payload(std::string(60,'*'));
|
||||
m_msg_count = 1;
|
||||
|
||||
//m_message_stamps.reserve(1000);
|
||||
|
||||
m_con_start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
m_endpoint.send(hdl, m_msg);
|
||||
//m_endpoint.send(hdl, "", websocketpp::frame::opcode::text);
|
||||
void send(int id, std::string message) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
con_list::iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
std::cout << "> No connection found with id " << id << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_endpoint.send(metadata_it->second->get_hdl(), message, websocketpp::frame::opcode::text, ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error sending message: " << ec.message() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
metadata_it->second->record_sent_message(message);
|
||||
}
|
||||
void on_message(websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
if (m_msg_count == 1000) {
|
||||
m_message = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.close(hdl,websocketpp::close::status::going_away,"");
|
||||
|
||||
connection_metadata::ptr get_metadata(int id) const {
|
||||
con_list::const_iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
return connection_metadata::ptr();
|
||||
} else {
|
||||
m_msg_count++;
|
||||
m_endpoint.send(hdl, m_msg);
|
||||
return metadata_it->second;
|
||||
}
|
||||
}
|
||||
void on_close(websocketpp::connection_hdl hdl) {
|
||||
m_close = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
|
||||
std::cout << "Socket Init: " << std::chrono::duration_cast<dur_type>(m_socket_init-m_start).count() << std::endl;
|
||||
std::cout << "TCP Pre Init: " << std::chrono::duration_cast<dur_type>(m_tcp_pre_init-m_start).count() << std::endl;
|
||||
std::cout << "TCP Post Init: " << std::chrono::duration_cast<dur_type>(m_tcp_post_init-m_start).count() << std::endl;
|
||||
std::cout << "Open: " << std::chrono::duration_cast<dur_type>(m_open-m_start).count() << std::endl;
|
||||
std::cout << "Start: " << std::chrono::duration_cast<dur_type>(m_con_start-m_start).count() << std::endl;
|
||||
std::cout << "Message: " << std::chrono::duration_cast<dur_type>(m_message-m_start).count() << std::endl;
|
||||
std::cout << "Close: " << std::chrono::duration_cast<dur_type>(m_close-m_start).count() << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Message: " << std::chrono::duration_cast<dur_type>(m_message-m_con_start).count() << std::endl;
|
||||
std::cout << "Close: " << std::chrono::duration_cast<dur_type>(m_close-m_message).count() << std::endl;
|
||||
}
|
||||
private:
|
||||
typedef std::map<int,connection_metadata::ptr> con_list;
|
||||
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
|
||||
client::message_ptr m_msg;
|
||||
size_t m_msg_count;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
std::chrono::high_resolution_clock::time_point m_tcp_pre_init;
|
||||
std::chrono::high_resolution_clock::time_point m_tcp_post_init;
|
||||
std::chrono::high_resolution_clock::time_point m_socket_init;
|
||||
|
||||
std::vector<std::chrono::high_resolution_clock::time_point> m_message_stamps;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point m_con_start;
|
||||
std::chrono::high_resolution_clock::time_point m_open;
|
||||
std::chrono::high_resolution_clock::time_point m_message;
|
||||
std::chrono::high_resolution_clock::time_point m_close;
|
||||
con_list m_connection_list;
|
||||
int m_next_id;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string uri = "wss://echo.websocket.org";
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
websocket_endpoint endpoint;
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
while (!done) {
|
||||
std::cout << "Enter Command: ";
|
||||
std::getline(std::cin, input);
|
||||
|
||||
try {
|
||||
perftest endpoint;
|
||||
endpoint.start(uri);
|
||||
} 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;
|
||||
if (input == "quit") {
|
||||
done = true;
|
||||
} else if (input == "help") {
|
||||
std::cout
|
||||
<< "\nCommand List:\n"
|
||||
<< "connect <ws uri>\n"
|
||||
<< "send <connection id> <message>\n"
|
||||
<< "close <connection id> [<close code:default=1000>] [<close reason>]\n"
|
||||
<< "show <connection id>\n"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else if (input.substr(0,7) == "connect") {
|
||||
int id = endpoint.connect(input.substr(8));
|
||||
if (id != -1) {
|
||||
std::cout << "> Created connection with id " << id << std::endl;
|
||||
}
|
||||
} else if (input.substr(0,4) == "send") {
|
||||
std::stringstream ss(input);
|
||||
|
||||
std::string cmd;
|
||||
int id;
|
||||
std::string message;
|
||||
|
||||
ss >> cmd >> id;
|
||||
std::getline(ss,message);
|
||||
|
||||
endpoint.send(id, message);
|
||||
} else if (input.substr(0,5) == "close") {
|
||||
std::stringstream ss(input);
|
||||
|
||||
std::string cmd;
|
||||
int id;
|
||||
int close_code = websocketpp::close::status::normal;
|
||||
std::string reason;
|
||||
|
||||
ss >> cmd >> id >> close_code;
|
||||
std::getline(ss,reason);
|
||||
|
||||
endpoint.close(id, close_code, reason);
|
||||
} else if (input.substr(0,4) == "show") {
|
||||
int id = atoi(input.substr(5).c_str());
|
||||
|
||||
connection_metadata::ptr metadata = endpoint.get_metadata(id);
|
||||
if (metadata) {
|
||||
std::cout << *metadata << std::endl;
|
||||
} else {
|
||||
std::cout << "> Unknown connection id " << id << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "> Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
WebSocket++ (0.3.0-alpha4)
|
||||
WebSocket++ (0.7.0)
|
||||
==========================
|
||||
|
||||
WebSocket++ is a header only C++ library that implements RFC6455 The WebSocket
|
||||
Protocol. It allows integrating WebSocket client and server functionality into
|
||||
C++ programs. It uses interchangeable network transport modules including one
|
||||
based on C++ iostreams and one based on Boost Asio.
|
||||
based on raw char buffers, one based on C++ iostreams, and one based on Asio
|
||||
(either via Boost or standalone). End users can write additional transport
|
||||
policies to support other networking or event libraries as needed.
|
||||
|
||||
Major Features
|
||||
==============
|
||||
@@ -13,7 +15,7 @@ Major Features
|
||||
* Message/event based interface
|
||||
* Supports secure WebSockets (TLS), IPv6, and explicit proxies.
|
||||
* Flexible dependency management (C++11 Standard Library or Boost)
|
||||
* Interchangeable network transport modules (iostream and Boost Asio)
|
||||
* Interchangeable network transport modules (raw, iostream, Asio, or custom)
|
||||
* Portable/cross platform (Posix/Windows, 32/64bit, Intel/ARM/PPC)
|
||||
* Thread-safe
|
||||
|
||||
@@ -31,6 +33,8 @@ http://www.zaphoyd.com/websocketpp/manual/
|
||||
**GitHub Repository**
|
||||
https://github.com/zaphoyd/websocketpp/
|
||||
|
||||
GitHub pull requests should be submitted to the `develop` branch.
|
||||
|
||||
**Announcements Mailing List**
|
||||
http://groups.google.com/group/websocketpp-announcements/
|
||||
|
||||
|
||||
+9
-10
@@ -16,24 +16,23 @@ Complete & Tested:
|
||||
- open_handler
|
||||
- close_handler
|
||||
- echo_server & echo_server_tls
|
||||
|
||||
Implimented, needs more testing
|
||||
- TLS support
|
||||
- External io_service support
|
||||
- TLS support
|
||||
- exception/error handling
|
||||
- Timeouts
|
||||
- Subprotocol negotiation
|
||||
- validate_handler
|
||||
- Hybi 00/Hixie 76 legacy protocol support
|
||||
- Outgoing Proxy Support
|
||||
- socket_init_handler
|
||||
- tls_init_handler
|
||||
- tcp_init_handler
|
||||
- exception/error handling
|
||||
- Subprotocol negotiation
|
||||
- Hybi 00/Hixie 76 legacy protocol support
|
||||
|
||||
Ongoing work
|
||||
- Performance tuning
|
||||
- Outgoing Proxy Support
|
||||
- PowerPC support
|
||||
- Visual Studio / Windows support
|
||||
- Timeouts
|
||||
- CMake build/install support
|
||||
|
||||
- validate_handler
|
||||
- http_handler
|
||||
|
||||
Future feature roadmap
|
||||
|
||||
@@ -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")
|
||||
+358
-43
@@ -30,6 +30,10 @@
|
||||
|
||||
#include "connection_tu2.hpp"
|
||||
|
||||
// Include special debugging transport
|
||||
//#include <websocketpp/config/minimal_client.hpp>
|
||||
#include <websocketpp/transport/debug/endpoint.hpp>
|
||||
|
||||
// NOTE: these tests currently test against hardcoded output values. I am not
|
||||
// sure how problematic this will be. If issues arise like order of headers the
|
||||
// output should be parsed by http::response and have values checked directly
|
||||
@@ -37,9 +41,9 @@
|
||||
BOOST_AUTO_TEST_CASE( basic_http_request ) {
|
||||
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
|
||||
std::string output = "HTTP/1.1 426 Upgrade Required\r\nServer: " +
|
||||
std::string(websocketpp::user_agent)+"\r\n\r\n";
|
||||
std::string(websocketpp::user_agent)+"\r\n\r\n";
|
||||
|
||||
std::string o2 = run_server_test(input);
|
||||
std::string o2 = run_server_test(input);
|
||||
|
||||
BOOST_CHECK(o2 == output);
|
||||
}
|
||||
@@ -79,17 +83,67 @@ struct stub_config : public websocketpp::config::core {
|
||||
typedef connection_extension connection_base;
|
||||
};
|
||||
|
||||
struct debug_config_client : public websocketpp::config::core {
|
||||
typedef debug_config_client type;
|
||||
|
||||
typedef core::concurrency_type concurrency_type;
|
||||
|
||||
typedef core::request_type request_type;
|
||||
typedef core::response_type response_type;
|
||||
|
||||
typedef core::message_type message_type;
|
||||
typedef core::con_msg_manager_type con_msg_manager_type;
|
||||
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
typedef core::alog_type alog_type;
|
||||
typedef core::elog_type elog_type;
|
||||
|
||||
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
|
||||
|
||||
struct transport_config {
|
||||
typedef type::concurrency_type concurrency_type;
|
||||
typedef type::elog_type elog_type;
|
||||
typedef type::alog_type alog_type;
|
||||
typedef type::request_type request_type;
|
||||
typedef type::response_type response_type;
|
||||
|
||||
/// Controls compile time enabling/disabling of thread syncronization
|
||||
/// code Disabling can provide a minor performance improvement to single
|
||||
/// threaded applications
|
||||
static bool const enable_multithreading = true;
|
||||
|
||||
/// Default timer values (in ms)
|
||||
static const long timeout_socket_pre_init = 5000;
|
||||
static const long timeout_proxy = 5000;
|
||||
static const long timeout_socket_post_init = 5000;
|
||||
static const long timeout_connect = 5000;
|
||||
static const long timeout_socket_shutdown = 5000;
|
||||
};
|
||||
|
||||
/// Transport Endpoint Component
|
||||
typedef websocketpp::transport::debug::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
typedef core::endpoint_base endpoint_base;
|
||||
typedef connection_extension connection_base;
|
||||
|
||||
static const websocketpp::log::level elog_level = websocketpp::log::elevel::none;
|
||||
static const websocketpp::log::level alog_level = websocketpp::log::alevel::none;
|
||||
};
|
||||
|
||||
struct connection_setup {
|
||||
connection_setup(bool server)
|
||||
: c(server,"",alog,elog,rng) {}
|
||||
connection_setup(bool p_is_server) : c(p_is_server, "", alog, elog, rng) {}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
stub_config::alog_type alog;
|
||||
stub_config::alog_type alog;
|
||||
stub_config::elog_type elog;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::connection<stub_config> c;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::connection<stub_config> c;
|
||||
};
|
||||
|
||||
typedef websocketpp::client<debug_config_client> debug_client;
|
||||
typedef websocketpp::server<debug_config_client> debug_server;
|
||||
|
||||
/*void echo_func(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
}*/
|
||||
@@ -105,12 +159,49 @@ 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) {
|
||||
*deferred = true;
|
||||
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
websocketpp::lib::error_code ec = con->defer_http_response();
|
||||
BOOST_CHECK_EQUAL(ec, websocketpp::lib::error_code());
|
||||
}
|
||||
|
||||
void check_on_fail(server* s, websocketpp::lib::error_code ec, bool & called,
|
||||
websocketpp::connection_hdl hdl)
|
||||
{
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
BOOST_CHECK_EQUAL(ec, con->get_ec());
|
||||
called = true;
|
||||
}
|
||||
|
||||
void on_open_print(server* s, websocketpp::connection_hdl hdl)
|
||||
{
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << con->get_uri() << std::endl;
|
||||
}
|
||||
|
||||
void fail_on_open(websocketpp::connection_hdl) {
|
||||
BOOST_CHECK(false);
|
||||
}
|
||||
void fail_on_http(websocketpp::connection_hdl) {
|
||||
BOOST_CHECK(false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( connection_extensions ) {
|
||||
@@ -128,8 +219,8 @@ BOOST_AUTO_TEST_CASE( basic_websocket_request ) {
|
||||
output+=websocketpp::user_agent;
|
||||
output+="\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
server s;
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
server s;
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
|
||||
BOOST_CHECK(run_server_test(s,input) == output);
|
||||
}
|
||||
@@ -140,19 +231,57 @@ BOOST_AUTO_TEST_CASE( http_request ) {
|
||||
output+=websocketpp::user_agent;
|
||||
output+="\r\n\r\n/foo/bar";
|
||||
|
||||
server s;
|
||||
s.set_http_handler(bind(&http_func,&s,::_1));
|
||||
server s;
|
||||
s.set_http_handler(bind(&http_func,&s,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( deferred_http_request ) {
|
||||
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
|
||||
std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: ";
|
||||
output+=websocketpp::user_agent;
|
||||
output+="\r\n\r\n/foo/bar";
|
||||
|
||||
server s;
|
||||
server::connection_ptr con;
|
||||
bool deferred = false;
|
||||
s.set_http_handler(bind(&defer_http_func,&s, &deferred,::_1));
|
||||
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
std::stringstream ostream;
|
||||
s.register_ostream(&ostream);
|
||||
|
||||
con = s.get_connection();
|
||||
con->start();
|
||||
|
||||
BOOST_CHECK(!deferred);
|
||||
BOOST_CHECK_EQUAL(ostream.str(), "");
|
||||
con->read_some(input.data(),input.size());
|
||||
BOOST_CHECK(deferred);
|
||||
BOOST_CHECK_EQUAL(ostream.str(), "");
|
||||
|
||||
con->set_body(con->get_resource());
|
||||
con->set_status(websocketpp::http::status_code::ok);
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
s.send_http_response(con->get_handle(),ec);
|
||||
BOOST_CHECK_EQUAL(ec, websocketpp::lib::error_code());
|
||||
BOOST_CHECK_EQUAL(ostream.str(), output);
|
||||
con->send_http_response(ec);
|
||||
BOOST_CHECK_EQUAL(ec, make_error_code(websocketpp::error::invalid_state));
|
||||
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
server s;
|
||||
s.set_user_agent("");
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
server s;
|
||||
s.set_user_agent("");
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
@@ -161,10 +290,10 @@ 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";
|
||||
|
||||
server s;
|
||||
s.set_user_agent("");
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
s.set_validate_handler(bind(&validate_set_ua,&s,::_1));
|
||||
server s;
|
||||
s.set_user_agent("");
|
||||
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
s.set_validate_handler(bind(&validate_set_ua,&s,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
@@ -174,42 +303,228 @@ BOOST_AUTO_TEST_CASE( basic_client_websocket ) {
|
||||
|
||||
//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";
|
||||
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";
|
||||
|
||||
std::stringstream output;
|
||||
std::stringstream output;
|
||||
|
||||
client e;
|
||||
e.set_access_channels(websocketpp::log::alevel::none);
|
||||
client e;
|
||||
e.set_access_channels(websocketpp::log::alevel::none);
|
||||
e.set_error_channels(websocketpp::log::elevel::none);
|
||||
e.set_user_agent("foo");
|
||||
e.register_ostream(&output);
|
||||
e.set_user_agent("foo");
|
||||
e.register_ostream(&output);
|
||||
|
||||
client::connection_ptr con;
|
||||
websocketpp::lib::error_code ec;
|
||||
con = e.get_connection(uri, ec);
|
||||
con->append_header("Foo","Bar");
|
||||
e.connect(con);
|
||||
client::connection_ptr con;
|
||||
websocketpp::lib::error_code ec;
|
||||
con = e.get_connection(uri, ec);
|
||||
con->append_header("Foo","Bar");
|
||||
e.connect(con);
|
||||
|
||||
BOOST_CHECK_EQUAL(ref, output.str());
|
||||
}
|
||||
|
||||
/*
|
||||
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";
|
||||
|
||||
// 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";
|
||||
|
||||
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";
|
||||
// After the handshake, add a single frame with a close message with message too big
|
||||
// error code.
|
||||
char frame1[4] = {char(0x88), 0x19, 0x03, char(0xf1)};
|
||||
output.append(frame1, 4);
|
||||
output.append("A message was too large");
|
||||
|
||||
BOOST_CHECK(run_server_test(input) == output);
|
||||
server s;
|
||||
s.set_user_agent("");
|
||||
s.set_validate_handler(bind(&validate_set_ua,&s,::_1));
|
||||
s.set_max_message_size(2);
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
|
||||
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_AUTO_TEST_CASE( websocket_fail_parse_error ) {
|
||||
std::string input = "asdf\r\n\r\n";
|
||||
|
||||
unsigned char frames[8] = {0x82,0x82,0xFF,0xFF,0xFF,0xFF,0xD5,0xD5};
|
||||
input.append(reinterpret_cast<char*>(frames),8);
|
||||
server s;
|
||||
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::http_parse_error);
|
||||
bool called = false;
|
||||
s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
|
||||
|
||||
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);
|
||||
run_server_test(s,input,false);
|
||||
BOOST_CHECK(called);
|
||||
}
|
||||
*/
|
||||
|
||||
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";
|
||||
|
||||
server s;
|
||||
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::invalid_version);
|
||||
bool called = false;
|
||||
s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
|
||||
|
||||
run_server_test(s,input,false);
|
||||
BOOST_CHECK(called);
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
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));
|
||||
|
||||
run_server_test(s,input,false);
|
||||
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";
|
||||
|
||||
// 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);
|
||||
// }
|
||||
|
||||
// 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));
|
||||
|
||||
// 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";
|
||||
|
||||
server s;
|
||||
websocketpp::lib::error_code ec = make_error_code(websocketpp::error::upgrade_required);
|
||||
bool called = false;
|
||||
s.set_fail_handler(bind(&check_on_fail,&s,ec,websocketpp::lib::ref(called),::_1));
|
||||
|
||||
run_server_test(s,input,false);
|
||||
BOOST_CHECK(called);
|
||||
}
|
||||
|
||||
// TODO: set max message size in client endpoint test case
|
||||
// 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( 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";
|
||||
|
||||
// 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_AUTO_TEST_CASE( client_handshake_timeout_race1 ) {
|
||||
debug_client c;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
debug_client::connection_ptr con = c.get_connection("ws://localhost:9002", ec);
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
// This test the case where a handshake times out immediately before the
|
||||
// handler that would have completed it gets invoked. This situation happens
|
||||
// when clients are connecting to overloaded servers and on servers that are
|
||||
// overloaded.
|
||||
c.connect(con);
|
||||
|
||||
con->expire_timer(websocketpp::lib::error_code());
|
||||
// Fullfil the write to simulate the write completing immediately after
|
||||
// timer expires
|
||||
con->fullfil_write();
|
||||
|
||||
BOOST_CHECK_EQUAL(con->get_ec(), make_error_code(websocketpp::error::open_handshake_timeout));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( client_handshake_timeout_race2 ) {
|
||||
debug_client c;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
debug_client::connection_ptr con = c.get_connection("ws://localhost:9002", ec);
|
||||
|
||||
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";
|
||||
|
||||
// This test the case where a handshake times out immediately before the
|
||||
// handler that would have completed it gets invoked. This situation happens
|
||||
// when clients are connecting to overloaded servers and on servers that are
|
||||
// overloaded.
|
||||
c.connect(con);
|
||||
con->fullfil_write();
|
||||
|
||||
con->expire_timer(websocketpp::lib::error_code());
|
||||
// Read valid handshake to simulate receiving the handshake response
|
||||
// immediately after the timer expires
|
||||
con->read_all(output.data(),output.size());
|
||||
|
||||
BOOST_CHECK_EQUAL(con->get_ec(), make_error_code(websocketpp::error::open_handshake_timeout));
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
debug_server::connection_ptr con = s.get_connection();
|
||||
con->start();
|
||||
|
||||
con->expire_timer(websocketpp::lib::error_code());
|
||||
// Read handshake immediately after timer expire
|
||||
con->read_all(input.data(), input.size());
|
||||
|
||||
BOOST_CHECK_EQUAL(con->get_ec(), make_error_code(websocketpp::error::open_handshake_timeout));
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
debug_server::connection_ptr con = s.get_connection();
|
||||
con->start();
|
||||
|
||||
con->read_all(input.data(), input.size());
|
||||
|
||||
con->expire_timer(websocketpp::lib::error_code());
|
||||
// Complete write immediately after timer expire
|
||||
con->fullfil_write();
|
||||
|
||||
BOOST_CHECK_EQUAL(con->get_ec(), make_error_code(websocketpp::error::open_handshake_timeout));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -31,27 +31,32 @@ void echo_func(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
}
|
||||
|
||||
std::string run_server_test(std::string input) {
|
||||
std::string run_server_test(std::string input, bool log) {
|
||||
server test_server;
|
||||
return run_server_test(test_server,input);
|
||||
return run_server_test(test_server,input,log);
|
||||
}
|
||||
|
||||
std::string run_server_test(server & s, std::string input) {
|
||||
std::string run_server_test(server & s, std::string input, bool log) {
|
||||
server::connection_ptr con;
|
||||
std::stringstream output;
|
||||
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.clear_error_channels(websocketpp::log::elevel::all);
|
||||
if (log) {
|
||||
s.set_access_channels(websocketpp::log::alevel::all);
|
||||
s.set_error_channels(websocketpp::log::elevel::all);
|
||||
} else {
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.clear_error_channels(websocketpp::log::elevel::all);
|
||||
}
|
||||
|
||||
s.register_ostream(&output);
|
||||
s.register_ostream(&output);
|
||||
|
||||
con = s.get_connection();
|
||||
con->start();
|
||||
con = s.get_connection();
|
||||
con->start();
|
||||
|
||||
std::stringstream channel;
|
||||
std::stringstream channel;
|
||||
|
||||
channel << input;
|
||||
channel >> *con;
|
||||
channel << input;
|
||||
channel >> *con;
|
||||
|
||||
return output.str();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
// Test Environment:
|
||||
// server, no TLS, no locks, iostream based transport
|
||||
#include <websocketpp/config/debug.hpp>
|
||||
#include <websocketpp/config/core.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
@@ -46,5 +47,5 @@ using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
void echo_func(server* s, websocketpp::connection_hdl hdl, message_ptr msg);
|
||||
std::string run_server_test(std::string input);
|
||||
std::string run_server_test(server & s, std::string input);
|
||||
std::string run_server_test(std::string input, bool log = false);
|
||||
std::string run_server_test(server & s, std::string input, bool log = false);
|
||||
|
||||
@@ -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()
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* 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:
|
||||
@@ -57,6 +57,35 @@ BOOST_AUTO_TEST_CASE( initialize_server_asio_external ) {
|
||||
s.init_asio(&ios);
|
||||
}
|
||||
|
||||
#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
BOOST_AUTO_TEST_CASE( move_construct_server_core ) {
|
||||
websocketpp::server<websocketpp::config::core> s1;
|
||||
|
||||
websocketpp::server<websocketpp::config::core> s2(std::move(s1));
|
||||
}
|
||||
|
||||
/*
|
||||
// temporary disable because library doesn't pass
|
||||
BOOST_AUTO_TEST_CASE( emplace ) {
|
||||
std::stringstream out1;
|
||||
std::stringstream out2;
|
||||
|
||||
std::vector<websocketpp::server<websocketpp::config::asio_tls>> v;
|
||||
|
||||
v.emplace_back();
|
||||
v.emplace_back();
|
||||
|
||||
v[0].get_alog().set_ostream(&out1);
|
||||
v[0].get_alog().set_ostream(&out2);
|
||||
|
||||
v[0].get_alog().write(websocketpp::log::alevel::app,"devel0");
|
||||
v[1].get_alog().write(websocketpp::log::alevel::app,"devel1");
|
||||
BOOST_CHECK( out1.str().size() > 0 );
|
||||
BOOST_CHECK( out2.str().size() > 0 );
|
||||
}*/
|
||||
|
||||
#endif // _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
|
||||
struct endpoint_extension {
|
||||
endpoint_extension() : extension_value(5) {}
|
||||
|
||||
@@ -94,8 +123,33 @@ struct stub_config : public websocketpp::config::core {
|
||||
BOOST_AUTO_TEST_CASE( endpoint_extensions ) {
|
||||
websocketpp::server<stub_config> s;
|
||||
|
||||
BOOST_CHECK( s.extension_value == 5 );
|
||||
BOOST_CHECK( s.extension_method() == 5 );
|
||||
BOOST_CHECK_EQUAL( s.extension_value, 5 );
|
||||
BOOST_CHECK_EQUAL( s.extension_method(), 5 );
|
||||
|
||||
BOOST_CHECK( s.is_server() == true );
|
||||
BOOST_CHECK( s.is_server() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( listen_after_listen_failure ) {
|
||||
using websocketpp::transport::asio::error::make_error_code;
|
||||
using websocketpp::transport::asio::error::pass_through;
|
||||
|
||||
websocketpp::server<websocketpp::config::asio> server1;
|
||||
websocketpp::server<websocketpp::config::asio> server2;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
server1.init_asio();
|
||||
server2.init_asio();
|
||||
|
||||
boost::asio::ip::tcp::endpoint ep1(boost::asio::ip::address::from_string("127.0.0.1"), 12345);
|
||||
boost::asio::ip::tcp::endpoint ep2(boost::asio::ip::address::from_string("127.0.0.1"), 23456);
|
||||
|
||||
server1.listen(ep1, ec);
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
server2.listen(ep1, ec);
|
||||
BOOST_REQUIRE_EQUAL(ec, make_error_code(pass_through));
|
||||
|
||||
server2.listen(ep2, ec);
|
||||
BOOST_CHECK(!ec);
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2013, 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:
|
||||
@@ -100,10 +100,10 @@ BOOST_AUTO_TEST_CASE( negotiation_invalid_attr ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "");
|
||||
}
|
||||
|
||||
// Negotiate s2c_no_context_takeover
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_invalid ) {
|
||||
// Negotiate server_no_context_takeover
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_invalid ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_no_context_takeover"] = "foo";
|
||||
v.attr["server_no_context_takeover"] = "foo";
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( !v.exts.is_enabled() );
|
||||
@@ -111,30 +111,30 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_invalid ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["server_no_context_takeover"].clear();
|
||||
|
||||
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; s2c_no_context_takeover");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_server_initiated ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_server_initiated ) {
|
||||
ext_vars v;
|
||||
|
||||
v.exts.enable_s2c_no_context_takeover();
|
||||
v.exts.enable_server_no_context_takeover();
|
||||
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; s2c_no_context_takeover");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover");
|
||||
}
|
||||
|
||||
// Negotiate c2s_no_context_takeover
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_invalid ) {
|
||||
// Negotiate client_no_context_takeover
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_invalid ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_no_context_takeover"] = "foo";
|
||||
v.attr["client_no_context_takeover"] = "foo";
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( !v.exts.is_enabled() );
|
||||
@@ -142,29 +142,29 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_invalid ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["client_no_context_takeover"].clear();
|
||||
|
||||
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; c2s_no_context_takeover");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_server_initiated ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_server_initiated ) {
|
||||
ext_vars v;
|
||||
|
||||
v.exts.enable_c2s_no_context_takeover();
|
||||
v.exts.enable_client_no_context_takeover();
|
||||
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; c2s_no_context_takeover");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover");
|
||||
}
|
||||
|
||||
|
||||
// Negotiate s2c_max_window_bits
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) {
|
||||
// Negotiate server_max_window_bits
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_invalid ) {
|
||||
ext_vars v;
|
||||
|
||||
std::vector<std::string> values;
|
||||
@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) {
|
||||
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = values.begin(); it != values.end(); ++it) {
|
||||
v.attr["s2c_max_window_bits"] = *it;
|
||||
v.attr["server_max_window_bits"] = *it;
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( !v.exts.is_enabled() );
|
||||
@@ -184,16 +184,16 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) {
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_valid ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_valid ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_max_window_bits"] = "8";
|
||||
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; s2c_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
|
||||
v.attr["s2c_max_window_bits"] = "15";
|
||||
v.attr["server_max_window_bits"] = "15";
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
@@ -201,21 +201,21 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_valid ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( invalid_set_s2c_max_window_bits ) {
|
||||
BOOST_AUTO_TEST_CASE( invalid_set_server_max_window_bits ) {
|
||||
ext_vars v;
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(7,pmd_mode::decline);
|
||||
v.ec = v.exts.set_server_max_window_bits(7,pmd_mode::decline);
|
||||
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(16,pmd_mode::decline);
|
||||
v.ec = v.exts.set_server_max_window_bits(16,pmd_mode::decline);
|
||||
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_decline ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_max_window_bits"] = "8";
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::decline);
|
||||
v.ec = v.exts.set_server_max_window_bits(15,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() );
|
||||
@@ -223,44 +223,44 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_decline ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_accept ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_max_window_bits"] = "8";
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::accept);
|
||||
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; s2c_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_largest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_max_window_bits"] = "8";
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::largest);
|
||||
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; s2c_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_smallest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
|
||||
ext_vars v;
|
||||
v.attr["s2c_max_window_bits"] = "8";
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::smallest);
|
||||
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; s2c_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
}
|
||||
|
||||
// Negotiate s2c_max_window_bits
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) {
|
||||
// Negotiate server_max_window_bits
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_invalid ) {
|
||||
ext_vars v;
|
||||
|
||||
std::vector<std::string> values;
|
||||
@@ -270,7 +270,7 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) {
|
||||
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = values.begin(); it != values.end(); ++it) {
|
||||
v.attr["c2s_max_window_bits"] = *it;
|
||||
v.attr["client_max_window_bits"] = *it;
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( !v.exts.is_enabled() );
|
||||
@@ -279,43 +279,43 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) {
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_valid ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["c2s_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() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
|
||||
v.attr["c2s_max_window_bits"] = "8";
|
||||
v.attr["client_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; c2s_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
|
||||
v.attr["c2s_max_window_bits"] = "15";
|
||||
v.attr["client_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() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( invalid_set_c2s_max_window_bits ) {
|
||||
BOOST_AUTO_TEST_CASE( invalid_set_client_max_window_bits ) {
|
||||
ext_vars v;
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(7,pmd_mode::decline);
|
||||
v.ec = v.exts.set_client_max_window_bits(7,pmd_mode::decline);
|
||||
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(16,pmd_mode::decline);
|
||||
v.ec = v.exts.set_client_max_window_bits(16,pmd_mode::decline);
|
||||
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_decline ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_max_window_bits"] = "8";
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(8,pmd_mode::decline);
|
||||
v.ec = v.exts.set_client_max_window_bits(8,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() );
|
||||
@@ -323,40 +323,40 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_decline ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_accept ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_max_window_bits"] = "8";
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::accept);
|
||||
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; c2s_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_largest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_max_window_bits"] = "8";
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::largest);
|
||||
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; c2s_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_smallest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
|
||||
ext_vars v;
|
||||
v.attr["c2s_max_window_bits"] = "8";
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::smallest);
|
||||
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; c2s_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
}
|
||||
|
||||
|
||||
@@ -364,180 +364,286 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_smallest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["c2s_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() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; s2c_no_context_takeover; c2s_no_context_takeover");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["server_no_context_takeover"].clear();
|
||||
v.attr["server_max_window_bits"] = "10";
|
||||
|
||||
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; s2c_no_context_takeover; s2c_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; server_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
v.attr["server_no_context_takeover"].clear();
|
||||
v.attr["client_max_window_bits"] = "10";
|
||||
|
||||
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; s2c_no_context_takeover; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["client_no_context_takeover"].clear();
|
||||
v.attr["server_max_window_bits"] = "10";
|
||||
|
||||
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; c2s_no_context_takeover; s2c_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; server_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated5 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
v.attr["client_no_context_takeover"].clear();
|
||||
v.attr["client_max_window_bits"] = "10";
|
||||
|
||||
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; c2s_no_context_takeover; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated6 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
v.attr["server_max_window_bits"] = "10";
|
||||
v.attr["client_max_window_bits"] = "10";
|
||||
|
||||
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; s2c_max_window_bits=10; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=10; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
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);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; s2c_no_context_takeover; c2s_no_context_takeover; s2c_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; server_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
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);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; s2c_no_context_takeover; c2s_no_context_takeover; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
v.attr["server_no_context_takeover"].clear();
|
||||
v.attr["server_max_window_bits"] = "10";
|
||||
v.attr["client_max_window_bits"] = "10";
|
||||
|
||||
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; s2c_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
v.attr["client_no_context_takeover"].clear();
|
||||
v.attr["server_max_window_bits"] = "10";
|
||||
v.attr["client_max_window_bits"] = "10";
|
||||
|
||||
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; c2s_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) {
|
||||
ext_vars v;
|
||||
|
||||
v.attr["s2c_no_context_takeover"] = "";
|
||||
v.attr["c2s_no_context_takeover"] = "";
|
||||
v.attr["s2c_max_window_bits"] = "10";
|
||||
v.attr["c2s_max_window_bits"] = "10";
|
||||
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";
|
||||
|
||||
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; s2c_no_context_takeover; c2s_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10");
|
||||
}
|
||||
|
||||
// Compression
|
||||
/*
|
||||
BOOST_AUTO_TEST_CASE( compress_data ) {
|
||||
ext_vars v;
|
||||
|
||||
std::string in = "Hello";
|
||||
std::string out;
|
||||
std::string in2;
|
||||
std::string out2;
|
||||
std::string compress_in = "Hello";
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
v.exts.init();
|
||||
v.exts.init(true);
|
||||
|
||||
v.ec = v.exts.compress(in,out);
|
||||
|
||||
std::cout << "in : " << websocketpp::utility::to_hex(in) << std::endl;
|
||||
v.ec = v.exts.compress(compress_in,compress_out);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl;
|
||||
|
||||
in2 = out;
|
||||
|
||||
v.ec = v.exts.decompress(reinterpret_cast<const uint8_t *>(in2.data()),in2.size(),out2);
|
||||
|
||||
v.ec = v.exts.decompress(reinterpret_cast<const uint8_t *>(compress_out.data()),compress_out.size(),decompress_out);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out2) << std::endl;
|
||||
BOOST_CHECK_EQUAL( out, out2 );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( compress_data_multiple ) {
|
||||
ext_vars v;
|
||||
|
||||
v.exts.init(true);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
std::string compress_in = "Hello";
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
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);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( compress_data_large ) {
|
||||
ext_vars v;
|
||||
|
||||
std::string compress_in(600,'*');
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
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);
|
||||
|
||||
v.exts.negotiate(alist);
|
||||
v.exts.init(true);
|
||||
|
||||
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);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) {
|
||||
ext_vars v;
|
||||
|
||||
std::string compress_in = "Hello";
|
||||
std::string compress_out1;
|
||||
std::string compress_out2;
|
||||
std::string decompress_out;
|
||||
|
||||
websocketpp::http::attribute_list alist;
|
||||
|
||||
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.compress(compress_in,compress_out1);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.decompress(
|
||||
reinterpret_cast<const uint8_t *>(compress_out1.data()),
|
||||
compress_out1.size(),
|
||||
decompress_out
|
||||
);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
|
||||
decompress_out.clear();
|
||||
|
||||
v.ec = v.exts.compress(compress_in,compress_out2);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.decompress(
|
||||
reinterpret_cast<const uint8_t *>(compress_out2.data()),
|
||||
compress_out2.size(),
|
||||
decompress_out
|
||||
);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
|
||||
BOOST_CHECK_EQUAL( compress_out1, compress_out2 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( compress_empty ) {
|
||||
ext_vars v;
|
||||
|
||||
std::string compress_in;
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
v.exts.init(true);
|
||||
|
||||
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.clear();
|
||||
decompress_out.clear();
|
||||
|
||||
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);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( compress_in, decompress_out );
|
||||
}
|
||||
|
||||
/// @todo: more compression tests
|
||||
/**
|
||||
* - compress at different compression levels
|
||||
*/
|
||||
|
||||
// Decompression
|
||||
BOOST_AUTO_TEST_CASE( decompress_data ) {
|
||||
ext_vars v;
|
||||
|
||||
uint8_t in[12] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff};
|
||||
uint8_t in[11] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff};
|
||||
std::string out;
|
||||
std::string reference = "Hello";
|
||||
|
||||
v.exts.init();
|
||||
v.exts.init(true);
|
||||
|
||||
v.ec = v.exts.decompress(in,12,out);
|
||||
v.ec = v.exts.decompress(in,11,out);
|
||||
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl;
|
||||
BOOST_CHECK( false );
|
||||
BOOST_CHECK_EQUAL( out, reference );
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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")
|
||||
+334
-126
@@ -28,6 +28,7 @@
|
||||
#define BOOST_TEST_MODULE http_parser
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <websocketpp/http/request.hpp>
|
||||
@@ -54,24 +55,24 @@ BOOST_AUTO_TEST_CASE( is_token_char ) {
|
||||
|
||||
// numbers
|
||||
for (int i = 0x30; i < 0x3a; i++) {
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
}
|
||||
|
||||
// upper
|
||||
for (int i = 0x41; i < 0x5b; i++) {
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
}
|
||||
|
||||
// lower
|
||||
for (int i = 0x61; i < 0x7b; i++) {
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
}
|
||||
|
||||
// invalid characters
|
||||
|
||||
// lower unprintable
|
||||
for (int i = 0; i < 33; i++) {
|
||||
BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
}
|
||||
|
||||
// misc
|
||||
@@ -95,7 +96,7 @@ BOOST_AUTO_TEST_CASE( is_token_char ) {
|
||||
|
||||
// upper unprintable and out of ascii range
|
||||
for (int i = 127; i < 256; i++) {
|
||||
BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
|
||||
}
|
||||
|
||||
// is not
|
||||
@@ -114,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());
|
||||
@@ -126,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;
|
||||
@@ -146,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() );
|
||||
}
|
||||
|
||||
@@ -184,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;
|
||||
@@ -208,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 ";
|
||||
@@ -355,6 +356,28 @@ BOOST_AUTO_TEST_CASE( extract_parameters ) {
|
||||
BOOST_CHECK_EQUAL( a.find("bar")->second, "a \"b\" c" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( strip_lws ) {
|
||||
std::string test1 = "foo";
|
||||
std::string test2 = " foo ";
|
||||
std::string test3 = "foo ";
|
||||
std::string test4 = " foo";
|
||||
std::string test5 = " foo ";
|
||||
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" );
|
||||
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test3), "foo" );
|
||||
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test4), "foo" );
|
||||
BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test5), "foo" );
|
||||
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 ) {
|
||||
websocketpp::http::parser::parser r;
|
||||
|
||||
@@ -387,14 +410,14 @@ 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;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -409,9 +432,9 @@ BOOST_AUTO_TEST_CASE( blank_request ) {
|
||||
bool exception = false;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
@@ -426,9 +449,9 @@ BOOST_AUTO_TEST_CASE( bad_request_no_host ) {
|
||||
bool exception = false;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
@@ -444,10 +467,10 @@ BOOST_AUTO_TEST_CASE( basic_request ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -459,6 +482,62 @@ BOOST_AUTO_TEST_CASE( basic_request ) {
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_request_with_body ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 5\r\n\r\nabcdef";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK_EQUAL( pos, 65 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
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_AUTO_TEST_CASE( basic_request_with_body_split ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 6\r\n\r\nabc";
|
||||
std::string raw2 = "def";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK_EQUAL( pos, 66 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "6" );
|
||||
BOOST_CHECK_EQUAL( r.get_body(), "abcdef" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( trailing_body_characters ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
@@ -468,9 +547,33 @@ BOOST_AUTO_TEST_CASE( trailing_body_characters ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 41 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( trailing_body_characters_beyond_max_lenth ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
|
||||
raw.append(websocketpp::http::max_header_size,'*');
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -492,11 +595,11 @@ BOOST_AUTO_TEST_CASE( basic_split1 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -518,11 +621,11 @@ BOOST_AUTO_TEST_CASE( basic_split2 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -537,17 +640,18 @@ BOOST_AUTO_TEST_CASE( basic_split2 ) {
|
||||
BOOST_AUTO_TEST_CASE( max_header_len ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
std::string raw(websocketpp::http::max_header_size+1,'*');
|
||||
std::string raw(websocketpp::http::max_header_size-1,'*');
|
||||
raw += "\r\n";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (const websocketpp::http::exception& e) {
|
||||
if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
|
||||
exception = true;
|
||||
}
|
||||
if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
|
||||
exception = true;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
@@ -563,17 +667,38 @@ BOOST_AUTO_TEST_CASE( max_header_len_split ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw2.c_str(),raw2.size());
|
||||
} catch (const websocketpp::http::exception& e) {
|
||||
if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
|
||||
exception = true;
|
||||
}
|
||||
if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
|
||||
exception = true;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( max_body_len ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
r.set_max_body_size(5);
|
||||
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 6\r\n\r\nabcdef";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (websocketpp::http::exception const & e) {
|
||||
exception = true;
|
||||
BOOST_CHECK_EQUAL(e.m_error_code,websocketpp::http::status_code::request_entity_too_large);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(r.get_max_body_size(),5);
|
||||
BOOST_CHECK( exception == true );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( firefox_full_request ) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
@@ -583,9 +708,9 @@ BOOST_AUTO_TEST_CASE( firefox_full_request ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
@@ -616,9 +741,9 @@ BOOST_AUTO_TEST_CASE( bad_method ) {
|
||||
bool exception = false;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
@@ -632,9 +757,9 @@ BOOST_AUTO_TEST_CASE( bad_header_name ) {
|
||||
bool exception = false;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
@@ -649,18 +774,18 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 41 );
|
||||
BOOST_CHECK_EQUAL( pos, 41 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.0" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.0" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( new_http_version1 ) {
|
||||
@@ -672,18 +797,18 @@ BOOST_AUTO_TEST_CASE( new_http_version1 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 42 );
|
||||
BOOST_CHECK_EQUAL( pos, 42 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.12" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.12" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( new_http_version2 ) {
|
||||
@@ -695,18 +820,18 @@ BOOST_AUTO_TEST_CASE( new_http_version2 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 43 );
|
||||
BOOST_CHECK_EQUAL( pos, 43 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/12.12" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/12.12" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
}
|
||||
|
||||
/* commented out due to not being implemented yet
|
||||
@@ -720,13 +845,13 @@ BOOST_AUTO_TEST_CASE( new_http_version3 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == true );
|
||||
}
|
||||
}*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE( header_whitespace1 ) {
|
||||
websocketpp::http::parser::request r;
|
||||
@@ -737,18 +862,18 @@ BOOST_AUTO_TEST_CASE( header_whitespace1 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 43 );
|
||||
BOOST_CHECK_EQUAL( pos, 43 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( header_whitespace2 ) {
|
||||
@@ -760,19 +885,19 @@ BOOST_AUTO_TEST_CASE( header_whitespace2 ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 40 );
|
||||
BOOST_CHECK_EQUAL( pos, 40 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Host") == "www.example.com" );
|
||||
}*/
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( header_aggregation ) {
|
||||
websocketpp::http::parser::request r;
|
||||
@@ -783,18 +908,18 @@ BOOST_AUTO_TEST_CASE( header_aggregation ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
pos = r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 61 );
|
||||
BOOST_CHECK_EQUAL( pos, 61 );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_method() == "GET" );
|
||||
BOOST_CHECK( r.get_uri() == "/" );
|
||||
BOOST_CHECK( r.get_header("Foo") == "bar, bat" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET" );
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Foo"), "bar, bat" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( wikipedia_example_response ) {
|
||||
@@ -806,22 +931,105 @@ BOOST_AUTO_TEST_CASE( wikipedia_example_response ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 159 );
|
||||
BOOST_CHECK_EQUAL( pos, 159 );
|
||||
BOOST_CHECK( r.headers_ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_status_code() == websocketpp::http::status_code::switching_protocols );
|
||||
BOOST_CHECK( r.get_status_msg() == "Switching Protocols" );
|
||||
BOOST_CHECK( r.get_header("Upgrade") == "websocket" );
|
||||
BOOST_CHECK( r.get_header("Connection") == "Upgrade" );
|
||||
BOOST_CHECK( r.get_header("Sec-WebSocket-Accept") == "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
|
||||
BOOST_CHECK( r.get_header("Sec-WebSocket-Protocol") == "chat" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
|
||||
BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing ) {
|
||||
websocketpp::http::parser::response r;
|
||||
|
||||
std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
|
||||
raw += "a";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK_EQUAL( pos, 159 );
|
||||
BOOST_CHECK( r.headers_ready() == true );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
|
||||
BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing_large ) {
|
||||
websocketpp::http::parser::response r;
|
||||
|
||||
std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
|
||||
raw.append(websocketpp::http::max_header_size,'*');
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK_EQUAL( pos, 159 );
|
||||
BOOST_CHECK( r.headers_ready() == true );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
|
||||
BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( response_with_non_standard_lws ) {
|
||||
websocketpp::http::parser::response r;
|
||||
|
||||
std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept:HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
|
||||
|
||||
bool exception = false;
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK_EQUAL( pos, 158 );
|
||||
BOOST_CHECK( r.headers_ready() );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
|
||||
BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( plain_http_response ) {
|
||||
@@ -833,28 +1041,28 @@ BOOST_AUTO_TEST_CASE( plain_http_response ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
pos += r.consume(raw.c_str(),raw.size());
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK( exception == false );
|
||||
BOOST_CHECK( pos == 405 );
|
||||
BOOST_CHECK_EQUAL( pos, 405 );
|
||||
BOOST_CHECK( r.headers_ready() == true );
|
||||
BOOST_CHECK( r.ready() == true );
|
||||
BOOST_CHECK( r.get_version() == "HTTP/1.1" );
|
||||
BOOST_CHECK( r.get_status_code() == websocketpp::http::status_code::ok );
|
||||
BOOST_CHECK( r.get_status_msg() == "OK" );
|
||||
BOOST_CHECK( r.get_header("Date") == "Thu, 10 May 2012 11:59:25 GMT" );
|
||||
BOOST_CHECK( r.get_header("Server") == "Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch" );
|
||||
BOOST_CHECK( r.get_header("Last-Modified") == "Tue, 30 Mar 2010 17:41:28 GMT" );
|
||||
BOOST_CHECK( r.get_header("ETag") == "\"16799d-55-4830823a78200\"" );
|
||||
BOOST_CHECK( r.get_header("Accept-Ranges") == "bytes" );
|
||||
BOOST_CHECK( r.get_header("Content-Length") == "85" );
|
||||
BOOST_CHECK( r.get_header("Vary") == "Accept-Encoding" );
|
||||
BOOST_CHECK( r.get_header("Content-Type") == "text/html" );
|
||||
BOOST_CHECK( r.get_body() == "<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>" );
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
|
||||
BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::ok );
|
||||
BOOST_CHECK_EQUAL( r.get_status_msg(), "OK" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Date"), "Thu, 10 May 2012 11:59:25 GMT" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Server"), "Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Last-Modified"), "Tue, 30 Mar 2010 17:41:28 GMT" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("ETag"), "\"16799d-55-4830823a78200\"" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Accept-Ranges"), "bytes" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "85" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Vary"), "Accept-Encoding" );
|
||||
BOOST_CHECK_EQUAL( r.get_header("Content-Type"), "text/html" );
|
||||
BOOST_CHECK_EQUAL( r.get_body(), "<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( parse_istream ) {
|
||||
@@ -868,10 +1076,10 @@ BOOST_AUTO_TEST_CASE( parse_istream ) {
|
||||
size_t pos = 0;
|
||||
|
||||
try {
|
||||
pos += r.consume(s);
|
||||
pos += r.consume(s);
|
||||
} catch (std::exception &e) {
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
exception = true;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL( exception, false );
|
||||
@@ -889,7 +1097,7 @@ BOOST_AUTO_TEST_CASE( write_request_basic ) {
|
||||
r.set_method("GET");
|
||||
r.set_uri("/");
|
||||
|
||||
BOOST_CHECK( r.raw() == raw );
|
||||
BOOST_CHECK_EQUAL( r.raw(), raw );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( write_request_with_header ) {
|
||||
@@ -902,7 +1110,7 @@ BOOST_AUTO_TEST_CASE( write_request_with_header ) {
|
||||
r.set_uri("/");
|
||||
r.replace_header("Host","http://example.com");
|
||||
|
||||
BOOST_CHECK( r.raw() == raw );
|
||||
BOOST_CHECK_EQUAL( r.raw(), raw );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( write_request_with_body ) {
|
||||
@@ -917,5 +1125,5 @@ BOOST_AUTO_TEST_CASE( write_request_with_body ) {
|
||||
r.replace_header("Content-Type","application/x-www-form-urlencoded");
|
||||
r.set_body("licenseID=string&content=string¶msXML=string");
|
||||
|
||||
BOOST_CHECK( r.raw() == raw );
|
||||
BOOST_CHECK_EQUAL( r.raw(), raw );
|
||||
}
|
||||
|
||||
+79
-79
@@ -31,111 +31,111 @@
|
||||
|
||||
class scoped_timer {
|
||||
public:
|
||||
scoped_timer(std::string i) : m_id(i),m_start(std::chrono::steady_clock::now()) {
|
||||
std::cout << "Clock " << i << ": ";
|
||||
}
|
||||
~scoped_timer() {
|
||||
std::chrono::nanoseconds time_taken = std::chrono::steady_clock::now()-m_start;
|
||||
scoped_timer(std::string i) : m_id(i),m_start(std::chrono::steady_clock::now()) {
|
||||
std::cout << "Clock " << i << ": ";
|
||||
}
|
||||
~scoped_timer() {
|
||||
std::chrono::nanoseconds time_taken = std::chrono::steady_clock::now()-m_start;
|
||||
|
||||
//nanoseconds_per_test
|
||||
//nanoseconds_per_test
|
||||
|
||||
//tests_per_second
|
||||
//tests_per_second
|
||||
|
||||
//1000000000.0/(double(time_taken.count())/1000.0)
|
||||
//1000000000.0/(double(time_taken.count())/1000.0)
|
||||
|
||||
std::cout << 1000000000.0/(double(time_taken.count())/1000.0) << std::endl;
|
||||
std::cout << 1000000000.0/(double(time_taken.count())/1000.0) << std::endl;
|
||||
|
||||
//std::cout << (1.0/double(time_taken.count())) * double(1000000000*1000) << std::endl;
|
||||
}
|
||||
//std::cout << (1.0/double(time_taken.count())) * double(1000000000*1000) << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_id;
|
||||
std::chrono::steady_clock::time_point m_start;
|
||||
std::string m_id;
|
||||
std::chrono::steady_clock::time_point m_start;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
|
||||
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
|
||||
|
||||
std::string firefox = "GET / HTTP/1.1\r\nHost: localhost:5000\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive, Upgrade\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Origin: http://zaphoyd.com\r\nSec-WebSocket-Key: pFik//FxwFk0riN4ZiPFjQ==\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n";
|
||||
std::string firefox = "GET / HTTP/1.1\r\nHost: localhost:5000\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive, Upgrade\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Origin: http://zaphoyd.com\r\nSec-WebSocket-Key: pFik//FxwFk0riN4ZiPFjQ==\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string firefox1 = "GET / HTTP/1.1\r\nHost: localhost:5000\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\n";
|
||||
std::string firefox1 = "GET / HTTP/1.1\r\nHost: localhost:5000\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\n";
|
||||
|
||||
std::string firefox2 = "Accept-Encoding: gzip, deflate\r\nConnection: keep-alive, Upgrade\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Origin: http://zaphoyd.com\r\nSec-WebSocket-Key: pFik//FxwFk0riN4ZiPFjQ==\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n";
|
||||
std::string firefox2 = "Accept-Encoding: gzip, deflate\r\nConnection: keep-alive, Upgrade\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Origin: http://zaphoyd.com\r\nSec-WebSocket-Key: pFik//FxwFk0riN4ZiPFjQ==\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
{
|
||||
scoped_timer timer("Simplest 1 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
{
|
||||
scoped_timer timer("Simplest 1 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
try {
|
||||
r.consume(raw.c_str(),raw.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
scoped_timer timer("FireFox, 1 chop, consume old");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
{
|
||||
scoped_timer timer("FireFox, 1 chop, consume old");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
try {
|
||||
r.consume2(firefox.c_str(),firefox.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
try {
|
||||
r.consume2(firefox.c_str(),firefox.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
scoped_timer timer("FireFox, 1 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
{
|
||||
scoped_timer timer("FireFox, 1 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
try {
|
||||
r.consume(firefox.c_str(),firefox.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
try {
|
||||
r.consume(firefox.c_str(),firefox.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
{
|
||||
scoped_timer timer("FireFox, 2 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
{
|
||||
scoped_timer timer("FireFox, 2 chop");
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
websocketpp::http::parser::request r;
|
||||
|
||||
try {
|
||||
r.consume(firefox1.c_str(),firefox1.size());
|
||||
r.consume(firefox2.c_str(),firefox2.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
try {
|
||||
r.consume(firefox1.c_str(),firefox1.size());
|
||||
r.consume(firefox2.c_str(),firefox2.size());
|
||||
} catch (...) {
|
||||
std::cout << "exception" << std::endl;
|
||||
}
|
||||
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r.ready()) {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
+65
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <websocketpp/concurrency/none.hpp>
|
||||
#include <websocketpp/concurrency/basic.hpp>
|
||||
|
||||
typedef websocketpp::log::basic<websocketpp::concurrency::basic,websocketpp::log::alevel> basic_access_log_type;
|
||||
|
||||
BOOST_AUTO_TEST_CASE( is_token_char ) {
|
||||
typedef websocketpp::log::basic<websocketpp::concurrency::none,websocketpp::log::elevel> error_log;
|
||||
|
||||
@@ -79,3 +81,65 @@ BOOST_AUTO_TEST_CASE( basic_concurrency ) {
|
||||
//std::cout << "|" << out.str() << "|" << std::endl;
|
||||
BOOST_CHECK( out.str().size() > 0 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( copy_constructor ) {
|
||||
std::stringstream out;
|
||||
|
||||
basic_access_log_type logger1(0xffffffff,&out);
|
||||
basic_access_log_type logger2(logger1);
|
||||
|
||||
logger2.set_channels(0xffffffff);
|
||||
logger2.write(websocketpp::log::alevel::devel,"devel");
|
||||
BOOST_CHECK( out.str().size() > 0 );
|
||||
}
|
||||
|
||||
#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
BOOST_AUTO_TEST_CASE( move_constructor ) {
|
||||
std::stringstream out;
|
||||
|
||||
basic_access_log_type logger1(0xffffffff,&out);
|
||||
basic_access_log_type logger2(std::move(logger1));
|
||||
|
||||
logger2.set_channels(0xffffffff);
|
||||
logger2.write(websocketpp::log::alevel::devel,"devel");
|
||||
BOOST_CHECK( out.str().size() > 0 );
|
||||
}
|
||||
|
||||
// Emplace requires move assignment, which logger doesn't support right now
|
||||
// due to const members. This is pretty irritating and will probably result in
|
||||
// the const members being removed. For now though this test will fail to
|
||||
// compile
|
||||
/*BOOST_AUTO_TEST_CASE( emplace ) {
|
||||
std::stringstream out1;
|
||||
std::stringstream out2;
|
||||
|
||||
std::vector<basic_access_log_type> v;
|
||||
|
||||
v.emplace_back(websocketpp::log::level(0xffffffff),&out1);
|
||||
v.emplace_back(websocketpp::log::level(0xffffffff),&out2);
|
||||
|
||||
v[0].set_channels(0xffffffff);
|
||||
v[1].set_channels(0xffffffff);
|
||||
v[0].write(websocketpp::log::alevel::devel,"devel");
|
||||
v[1].write(websocketpp::log::alevel::devel,"devel");
|
||||
BOOST_CHECK( out1.str().size() > 0 );
|
||||
BOOST_CHECK( out2.str().size() > 0 );
|
||||
}*/
|
||||
#endif // #ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
|
||||
// As long as there are const member variables these can't exist
|
||||
// These remain commented as they are useful for testing the deleted operators
|
||||
/*BOOST_AUTO_TEST_CASE( copy_assign ) {
|
||||
basic_access_log_type logger1;
|
||||
basic_access_log_type logger2;
|
||||
|
||||
logger2 = logger1;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( move_assign ) {
|
||||
basic_access_log_type logger1;
|
||||
basic_access_log_type logger2;
|
||||
|
||||
logger2 = std::move(logger1);
|
||||
}*/
|
||||
|
||||
@@ -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")
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -35,62 +35,62 @@
|
||||
|
||||
template <template <class> class con_msg_manager>
|
||||
struct stub {
|
||||
typedef websocketpp::lib::shared_ptr<stub> ptr;
|
||||
typedef websocketpp::lib::shared_ptr<stub> ptr;
|
||||
|
||||
typedef con_msg_manager<stub> con_msg_man_type;
|
||||
typedef typename con_msg_man_type::ptr con_msg_man_ptr;
|
||||
typedef typename con_msg_man_type::weak_ptr con_msg_man_weak_ptr;
|
||||
typedef con_msg_manager<stub> con_msg_man_type;
|
||||
typedef typename con_msg_man_type::ptr con_msg_man_ptr;
|
||||
typedef typename con_msg_man_type::weak_ptr con_msg_man_weak_ptr;
|
||||
|
||||
stub(con_msg_man_ptr manager, websocketpp::frame::opcode::value op, size_t size = 128)
|
||||
: m_opcode(op)
|
||||
, m_manager(manager)
|
||||
, m_size(size) {}
|
||||
stub(con_msg_man_ptr manager, websocketpp::frame::opcode::value op, size_t size = 128)
|
||||
: m_opcode(op)
|
||||
, m_manager(manager)
|
||||
, m_size(size) {}
|
||||
|
||||
bool recycle() {
|
||||
con_msg_man_ptr shared = m_manager.lock();
|
||||
bool recycle() {
|
||||
con_msg_man_ptr shared = m_manager.lock();
|
||||
|
||||
if (shared) {
|
||||
return shared->recycle(this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (shared) {
|
||||
return shared->recycle(this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
websocketpp::frame::opcode::value m_opcode;
|
||||
con_msg_man_weak_ptr m_manager;
|
||||
size_t m_size;
|
||||
websocketpp::frame::opcode::value m_opcode;
|
||||
con_msg_man_weak_ptr m_manager;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_get_message ) {
|
||||
typedef stub<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
typedef stub<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
|
||||
con_msg_man_type::ptr manager(new con_msg_man_type());
|
||||
message_type::ptr msg = manager->get_message(websocketpp::frame::opcode::TEXT,512);
|
||||
con_msg_man_type::ptr manager(new con_msg_man_type());
|
||||
message_type::ptr msg = manager->get_message(websocketpp::frame::opcode::TEXT,512);
|
||||
|
||||
BOOST_CHECK(msg);
|
||||
BOOST_CHECK(msg->m_opcode == websocketpp::frame::opcode::TEXT);
|
||||
BOOST_CHECK(msg->m_manager.lock() == manager);
|
||||
BOOST_CHECK(msg->m_size == 512);
|
||||
BOOST_CHECK(msg);
|
||||
BOOST_CHECK(msg->m_opcode == websocketpp::frame::opcode::TEXT);
|
||||
BOOST_CHECK(msg->m_manager.lock() == manager);
|
||||
BOOST_CHECK(msg->m_size == 512);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_get_manager ) {
|
||||
typedef stub<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
typedef websocketpp::message_buffer::alloc::endpoint_msg_manager
|
||||
<con_msg_man_type> endpoint_manager_type;
|
||||
typedef stub<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
typedef websocketpp::message_buffer::alloc::endpoint_msg_manager
|
||||
<con_msg_man_type> endpoint_manager_type;
|
||||
|
||||
endpoint_manager_type em;
|
||||
con_msg_man_type::ptr manager = em.get_manager();
|
||||
message_type::ptr msg = manager->get_message(websocketpp::frame::opcode::TEXT,512);
|
||||
endpoint_manager_type em;
|
||||
con_msg_man_type::ptr manager = em.get_manager();
|
||||
message_type::ptr msg = manager->get_message(websocketpp::frame::opcode::TEXT,512);
|
||||
|
||||
BOOST_CHECK(msg);
|
||||
BOOST_CHECK(msg->m_opcode == websocketpp::frame::opcode::TEXT);
|
||||
BOOST_CHECK(msg->m_manager.lock() == manager);
|
||||
BOOST_CHECK(msg->m_size == 512);
|
||||
BOOST_CHECK(msg);
|
||||
BOOST_CHECK(msg->m_opcode == websocketpp::frame::opcode::TEXT);
|
||||
BOOST_CHECK(msg->m_manager.lock() == manager);
|
||||
BOOST_CHECK(msg->m_size == 512);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -35,38 +35,38 @@
|
||||
|
||||
template <typename message>
|
||||
struct stub {
|
||||
typedef websocketpp::lib::weak_ptr<stub> weak_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<stub> ptr;
|
||||
typedef websocketpp::lib::weak_ptr<stub> weak_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<stub> ptr;
|
||||
|
||||
stub() : recycled(false) {}
|
||||
stub() : recycled(false) {}
|
||||
|
||||
bool recycle(message * msg) {
|
||||
this->recycled = true;
|
||||
return false;
|
||||
}
|
||||
bool recycle(message *) {
|
||||
this->recycled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool recycled;
|
||||
bool recycled;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_size_check ) {
|
||||
typedef websocketpp::message_buffer::message<stub> message_type;
|
||||
typedef stub<message_type> stub_type;
|
||||
typedef websocketpp::message_buffer::message<stub> message_type;
|
||||
typedef stub<message_type> stub_type;
|
||||
|
||||
stub_type::ptr s(new stub_type());
|
||||
message_type::ptr msg(new message_type(s,websocketpp::frame::opcode::TEXT,500));
|
||||
stub_type::ptr s(new stub_type());
|
||||
message_type::ptr msg(new message_type(s,websocketpp::frame::opcode::TEXT,500));
|
||||
|
||||
BOOST_CHECK(msg->get_payload().capacity() >= 500);
|
||||
BOOST_CHECK(msg->get_payload().capacity() >= 500);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( recycle ) {
|
||||
typedef websocketpp::message_buffer::message<stub> message_type;
|
||||
typedef stub<message_type> stub_type;
|
||||
typedef websocketpp::message_buffer::message<stub> message_type;
|
||||
typedef stub<message_type> stub_type;
|
||||
|
||||
stub_type::ptr s(new stub_type());
|
||||
message_type::ptr msg(new message_type(s,websocketpp::frame::opcode::TEXT,500));
|
||||
stub_type::ptr s(new stub_type());
|
||||
message_type::ptr msg(new message_type(s,websocketpp::frame::opcode::TEXT,500));
|
||||
|
||||
BOOST_CHECK(s->recycled == false);
|
||||
BOOST_CHECK(msg->recycle() == false);
|
||||
BOOST_CHECK(s->recycled == true);
|
||||
BOOST_CHECK(s->recycled == false);
|
||||
BOOST_CHECK(msg->recycle() == false);
|
||||
BOOST_CHECK(s->recycled == true);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
bool exception;
|
||||
|
||||
try {
|
||||
u = p.get_uri(r);
|
||||
u = p.get_uri(r);
|
||||
} catch (const websocketpp::uri_exception& e) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK(exception == false);
|
||||
@@ -147,9 +147,9 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
BOOST_CHECK(!p.validate_handshake(r));
|
||||
|
||||
try {
|
||||
u = p.get_uri(r);
|
||||
u = p.get_uri(r);
|
||||
} catch (const websocketpp::uri_exception& e) {
|
||||
exception = true;
|
||||
exception = true;
|
||||
}
|
||||
|
||||
BOOST_CHECK(exception == true);
|
||||
|
||||
@@ -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 )
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Peter Thorson. All rights reserved.
|
||||
* Copyright (c) 2014, 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:
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user