Compare commits
305 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1dfc144eac | |||
| 7f19b6ea95 | |||
| 5b99feef7f | |||
| 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 | |||
| dc313effa5 | |||
| 6300e090ad | |||
| 45dfcbec3c | |||
| 39dbe3a4e0 | |||
| 13f6da6f81 | |||
| ac5d7ea5af | |||
| 6f7ecc59cd | |||
| f7cea42c92 | |||
| 9efb12e59b | |||
| bcd82bd6f4 | |||
| 8f042d95ec | |||
| 0278ba7895 | |||
| 41c37cfd93 | |||
| 4bea90f555 | |||
| ce0300e6dc | |||
| f20b2e573f | |||
| 650e4c336b | |||
| 31c761a0a9 | |||
| 681c2331a1 | |||
| d55f28fe4b | |||
| a8d4a9a66a | |||
| 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 | |||
| 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 |
+10
@@ -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,9 @@ examples/wsperf/wsperf_client
|
||||
*.out
|
||||
|
||||
*.log
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.user
|
||||
install
|
||||
|
||||
+2
-1
@@ -2,7 +2,7 @@ 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
|
||||
env:
|
||||
global:
|
||||
- BOOST_INCLUDES=/usr/include
|
||||
@@ -14,6 +14,7 @@ branches:
|
||||
- permessage-deflate
|
||||
- experimental
|
||||
- 0.3.x-cmake
|
||||
- develop
|
||||
notifications:
|
||||
recipients:
|
||||
- travis@zaphoyd.com
|
||||
|
||||
+13
-6
@@ -9,7 +9,7 @@ project (websocketpp)
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
set (WEBSOCKETPP_MAJOR_VERSION 0)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 3)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 6)
|
||||
set (WEBSOCKETPP_PATCH_VERSION 0)
|
||||
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})
|
||||
|
||||
@@ -70,7 +70,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
############ 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 +87,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 +111,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 +133,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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -32,9 +32,7 @@ PROJECT_NAME = "websocketpp"
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
|
||||
PROJECT_NUMBER = "0.3.0-alpha4"
|
||||
|
||||
PROJECT_NUMBER = "0.6.0"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer
|
||||
@@ -974,7 +972,7 @@ HTML_COLORSTYLE_GAMMA = 148
|
||||
# page will contain the date and time when the page was generated. Setting
|
||||
# this to NO can help when comparing the output of multiple runs.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_TIMESTAMP = NO
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
|
||||
+35
-5
@@ -79,6 +79,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:
|
||||
@@ -98,11 +100,28 @@ else:
|
||||
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
|
||||
@@ -128,7 +147,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 +161,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 +180,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/'
|
||||
@@ -209,6 +229,7 @@ echo_server = SConscript('#/examples/echo_server/SConscript',variant_dir = build
|
||||
# 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)
|
||||
@@ -222,9 +243,18 @@ testee_client = SConscript('#/examples/testee_client/SConscript',variant_dir = b
|
||||
# utility_client
|
||||
utility_client = SConscript('#/examples/utility_client/SConscript',variant_dir = builddir + 'utility_client',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)
|
||||
|
||||
if not env['PLATFORM'].startswith('win'):
|
||||
# iostream_server
|
||||
iostream_server = SConscript('#/examples/iostream_server/SConscript',variant_dir = builddir + 'iostream_server',duplicate = 0)
|
||||
|
||||
+205
-9
@@ -1,12 +1,208 @@
|
||||
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.6.0
|
||||
- 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 +269,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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
/*#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
@@ -34,7 +35,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,17 +60,13 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +90,7 @@ public:
|
||||
// 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));
|
||||
m_actions.push(action(MESSAGE,hdl,msg));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
@@ -111,13 +109,13 @@ public:
|
||||
lock.unlock();
|
||||
|
||||
if (a.type == SUBSCRIBE) {
|
||||
unique_lock<mutex> lock(m_connection_lock);
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.insert(a.hdl);
|
||||
} else if (a.type == UNSUBSCRIBE) {
|
||||
unique_lock<mutex> lock(m_connection_lock);
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.erase(a.hdl);
|
||||
} else if (a.type == MESSAGE) {
|
||||
unique_lock<mutex> lock(m_connection_lock);
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
|
||||
con_list::iterator it;
|
||||
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
|
||||
@@ -129,7 +127,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 +139,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,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,166 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
|
||||
//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,10 @@
|
||||
|
||||
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 ()
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+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;*/
|
||||
}
|
||||
|
||||
@@ -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,10 +35,10 @@ 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);
|
||||
@@ -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,15 @@
|
||||
|
||||
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 ()
|
||||
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-----
|
||||
@@ -0,0 +1,8 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAqxMGKZB8YNV8WQnbJWwwwmifc+PfVRtd1FN5v5aQSsf6dpjX3Zlh
|
||||
N1NmgecsQyg4u2EWe4Umta10QzCgYaxf6QdTCg7iprLzFNw7IvWYbQ6du12NMGDr
|
||||
hmwA6KQKwbTgPL6mSlSlcK2wTP2FzxDTNffFu10cB/6Fj4kdQjPG0c1Koz/z7OOq
|
||||
BuDElJLClS8rjp3z1xvrc7gX95dFa2KaKgOAYDkpe8tfHRhHfJeIVS/whH9hzx6r
|
||||
OBg+E5K9JyvayrUoKgPeptRKCqo8A4YevtMLpRxMup0nMUgAIv6+BGTwPAFpwgl/
|
||||
8UIVcvjh1v95PwGDM/Q8yvIBJznBYk/e2wIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
@@ -27,46 +27,89 @@ 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) {
|
||||
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<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
if (mode == MOZILLA_MODERN) {
|
||||
// Modern disables TLSv1
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::no_tlsv1 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
} else {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
}
|
||||
ctx->set_password_callback(bind(&get_password));
|
||||
ctx->use_certificate_chain_file("server.pem");
|
||||
ctx->use_private_key_file("server.pem", boost::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-----
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,10 @@
|
||||
|
||||
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 ()
|
||||
@@ -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,204 @@
|
||||
#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;
|
||||
typedef websocketpp::lib::lock_guard<websocketpp::lib::mutex> scoped_lock;
|
||||
|
||||
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_uri()->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;
|
||||
}
|
||||
@@ -28,16 +28,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 +52,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 +74,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -39,12 +39,13 @@ struct testee_config : public websocketpp::config::asio {
|
||||
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 core::rng_type rng_type;
|
||||
typedef core::endpoint_base endpoint_base;
|
||||
|
||||
static bool const enable_multithreading = false;
|
||||
static bool const enable_multithreading = true;
|
||||
|
||||
struct transport_config : public core::transport_config {
|
||||
typedef core::concurrency_type concurrency_type;
|
||||
@@ -53,7 +54,7 @@ struct testee_config : public websocketpp::config::asio {
|
||||
typedef core::request_type request_type;
|
||||
typedef core::response_type response_type;
|
||||
|
||||
static bool const enable_multithreading = false;
|
||||
static bool const enable_multithreading = true;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
@@ -79,41 +80,59 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
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
|
||||
server testee_server;
|
||||
|
||||
try {
|
||||
short port = 9002;
|
||||
size_t num_threads = 1;
|
||||
|
||||
if (argc == 3) {
|
||||
port = atoi(argv[1]);
|
||||
num_threads = atoi(argv[2]);
|
||||
}
|
||||
|
||||
try {
|
||||
// Total silence
|
||||
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_socket_init_handler(bind(&on_socket_init,::_1,::_2));
|
||||
|
||||
// Listen on port 9002
|
||||
testee_server.listen(9002);
|
||||
// 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
|
||||
testee_server.run();
|
||||
// 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(websocketpp::lib::make_shared<websocketpp::lib::thread>(&server::run, &testee_server));
|
||||
}
|
||||
|
||||
/*websocketpp::lib::thread t1(&server::run, &testee_server);
|
||||
websocketpp::lib::thread t2(&server::run, &testee_server);
|
||||
for (size_t i = 0; i < num_threads; i++) {
|
||||
ts[i]->join();
|
||||
}
|
||||
}
|
||||
|
||||
t1.join();
|
||||
t2.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,11 @@
|
||||
|
||||
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 ()
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -1,126 +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::all);
|
||||
m_endpoint.set_error_channels(websocketpp::log::elevel::all);
|
||||
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_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));
|
||||
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_socket_init(websocketpp::connection_hdl hdl) {
|
||||
m_socket_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
m_tls_init = std::chrono::high_resolution_clock::now();
|
||||
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();
|
||||
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) {
|
||||
m_message = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.close(hdl,websocketpp::close::status::going_away,"");
|
||||
}
|
||||
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 << "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;
|
||||
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:
|
||||
client m_endpoint;
|
||||
typedef std::map<int,connection_metadata::ptr> con_list;
|
||||
|
||||
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;
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
|
||||
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.6.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
|
||||
|
||||
+342
-32
@@ -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());
|
||||
}*/
|
||||
@@ -113,6 +167,38 @@ void http_func(server* s, websocketpp::connection_hdl hdl) {
|
||||
con->set_status(websocketpp::http::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 ) {
|
||||
connection_setup env(true);
|
||||
|
||||
@@ -128,8 +214,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 +226,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 +285,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,25 +298,126 @@ 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";
|
||||
|
||||
// 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");
|
||||
|
||||
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( websocket_fail_parse_error ) {
|
||||
std::string input = "asdf\r\n\r\n";
|
||||
|
||||
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));
|
||||
|
||||
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 ) {
|
||||
@@ -205,11 +430,96 @@ BOOST_AUTO_TEST_CASE( user_reject_origin ) {
|
||||
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);
|
||||
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**";
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+325
-119
@@ -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
|
||||
@@ -355,6 +356,26 @@ 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 ";
|
||||
|
||||
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_AUTO_TEST_CASE( case_insensitive_headers ) {
|
||||
websocketpp::http::parser::parser r;
|
||||
|
||||
@@ -392,9 +413,9 @@ BOOST_AUTO_TEST_CASE( blank_consume ) {
|
||||
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 +430,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 +447,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 +465,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 +480,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 +545,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 +593,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 +619,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 +638,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 +665,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 +706,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 +739,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 +755,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 +772,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 +795,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 +818,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 +843,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 +860,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 +883,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 +906,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 +929,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 +1039,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 +1074,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 +1095,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 +1108,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 +1123,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;
|
||||
}
|
||||
|
||||
+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);
|
||||
}*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
+19
-17
@@ -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:
|
||||
@@ -38,13 +38,15 @@
|
||||
#include <websocketpp/message_buffer/alloc.hpp>
|
||||
|
||||
struct stub_config {
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_type;
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_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_manager_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_manager_type;
|
||||
|
||||
static const size_t max_message_size = 16000000;
|
||||
};
|
||||
|
||||
struct processor_setup {
|
||||
@@ -53,16 +55,16 @@ struct processor_setup {
|
||||
, p(false,server,msg_manager) {}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::request_type req;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::request_type req;
|
||||
stub_config::response_type res;
|
||||
websocketpp::processor::hybi00<stub_config> p;
|
||||
websocketpp::processor::hybi00<stub_config> p;
|
||||
};
|
||||
|
||||
typedef stub_config::message_type::ptr message_ptr;
|
||||
|
||||
BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
|
||||
|
||||
@@ -94,7 +96,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
|
||||
|
||||
@@ -107,7 +109,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
|
||||
|
||||
@@ -120,7 +122,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\n\r\n";
|
||||
|
||||
@@ -133,7 +135,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
|
||||
|
||||
@@ -146,7 +148,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
websocketpp::uri_ptr u;
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nOrigin: http://example.com\r\nSec-WebSocket-Key1: 3e6b263 4 17 80\r\nSec-WebSocket-Key2: 17 9 G`ZD9 2 2b 7X 3 /r90\r\n\r\n";
|
||||
@@ -162,7 +164,7 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_subprotocols ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::vector<std::string> subps;
|
||||
|
||||
|
||||
+27
-25
@@ -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:
|
||||
@@ -40,16 +40,18 @@
|
||||
#include <websocketpp/random/none.hpp>
|
||||
|
||||
struct stub_config {
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_type;
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_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_manager_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_manager_type;
|
||||
|
||||
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
|
||||
|
||||
static const size_t max_message_size = 16000000;
|
||||
|
||||
/// Extension related config
|
||||
static const bool enable_extensions = false;
|
||||
|
||||
@@ -65,10 +67,10 @@ struct stub_config {
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -99,10 +101,10 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -117,10 +119,10 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -135,10 +137,10 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -153,10 +155,10 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -171,10 +173,10 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi07<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
|
||||
+26
-24
@@ -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:
|
||||
@@ -40,16 +40,18 @@
|
||||
#include <websocketpp/random/none.hpp>
|
||||
|
||||
struct stub_config {
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_type;
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_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_manager_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_manager_type;
|
||||
|
||||
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
|
||||
|
||||
static const size_t max_message_size = 16000000;
|
||||
|
||||
/// Extension related config
|
||||
static const bool enable_extensions = false;
|
||||
|
||||
@@ -65,10 +67,10 @@ struct stub_config {
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -99,10 +101,10 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -117,10 +119,10 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -135,10 +137,10 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -153,10 +155,10 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
@@ -171,10 +173,10 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
stub_config::request_type r;
|
||||
stub_config::request_type r;
|
||||
stub_config::response_type response;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
websocketpp::processor::hybi08<stub_config> p(false,true,msg_manager,rng);
|
||||
websocketpp::uri_ptr u;
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
+205
-173
@@ -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:
|
||||
@@ -43,13 +43,13 @@
|
||||
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
|
||||
|
||||
struct stub_config {
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_type;
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_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_manager_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_manager_type;
|
||||
|
||||
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
|
||||
|
||||
@@ -60,17 +60,18 @@ struct stub_config {
|
||||
typedef websocketpp::extensions::permessage_deflate::disabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
|
||||
static const size_t max_message_size = 16000000;
|
||||
static const bool enable_extensions = false;
|
||||
};
|
||||
|
||||
struct stub_config_ext {
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_type;
|
||||
typedef websocketpp::http::parser::request request_type;
|
||||
typedef websocketpp::http::parser::response response_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_manager_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_manager_type;
|
||||
|
||||
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
|
||||
|
||||
@@ -81,6 +82,7 @@ struct stub_config_ext {
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled
|
||||
<permessage_deflate_config> permessage_deflate_type;
|
||||
|
||||
static const size_t max_message_size = 16000000;
|
||||
static const bool enable_extensions = true;
|
||||
};
|
||||
|
||||
@@ -95,11 +97,11 @@ struct processor_setup {
|
||||
, p(false,server,msg_manager,rng) {}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::request_type req;
|
||||
con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::request_type req;
|
||||
stub_config::response_type res;
|
||||
websocketpp::processor::hybi13<stub_config> p;
|
||||
websocketpp::processor::hybi13<stub_config> p;
|
||||
};
|
||||
|
||||
struct processor_setup_ext {
|
||||
@@ -108,15 +110,15 @@ struct processor_setup_ext {
|
||||
, p(false,server,msg_manager,rng) {}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::request_type req;
|
||||
con_msg_manager_type::ptr msg_manager;
|
||||
stub_config::rng_type rng;
|
||||
stub_config::request_type req;
|
||||
stub_config::response_type res;
|
||||
websocketpp::processor::hybi13<stub_config_ext> p;
|
||||
websocketpp::processor::hybi13<stub_config_ext> p;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
|
||||
|
||||
@@ -143,7 +145,7 @@ BOOST_AUTO_TEST_CASE( exact_match ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
|
||||
|
||||
@@ -155,7 +157,7 @@ BOOST_AUTO_TEST_CASE( non_get_method ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
|
||||
|
||||
@@ -167,7 +169,7 @@ BOOST_AUTO_TEST_CASE( old_http_version ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( missing_handshake_key1 ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
|
||||
|
||||
@@ -191,7 +193,7 @@ BOOST_AUTO_TEST_CASE( missing_handshake_key2 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
|
||||
|
||||
@@ -218,243 +220,243 @@ BOOST_AUTO_TEST_CASE( bad_host ) {
|
||||
// 0x81 0x80
|
||||
|
||||
BOOST_AUTO_TEST_CASE( frame_empty_binary_unmasked ) {
|
||||
uint8_t frame[2] = {0x82, 0x00};
|
||||
uint8_t frame[2] = {0x82, 0x00};
|
||||
|
||||
// all in one chunk
|
||||
processor_setup env1(false);
|
||||
// all in one chunk
|
||||
processor_setup env1(false);
|
||||
|
||||
size_t ret1 = env1.p.consume(frame,2,env1.ec);
|
||||
size_t ret1 = env1.p.consume(frame,2,env1.ec);
|
||||
|
||||
BOOST_CHECK_EQUAL( ret1, 2 );
|
||||
BOOST_CHECK( !env1.ec );
|
||||
BOOST_CHECK_EQUAL( env1.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( ret1, 2 );
|
||||
BOOST_CHECK( !env1.ec );
|
||||
BOOST_CHECK_EQUAL( env1.p.ready(), true );
|
||||
|
||||
// two separate chunks
|
||||
processor_setup env2(false);
|
||||
// two separate chunks
|
||||
processor_setup env2(false);
|
||||
|
||||
BOOST_CHECK_EQUAL( env2.p.consume(frame,1,env2.ec), 1 );
|
||||
BOOST_CHECK( !env2.ec );
|
||||
BOOST_CHECK_EQUAL( env2.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env2.p.consume(frame,1,env2.ec), 1 );
|
||||
BOOST_CHECK( !env2.ec );
|
||||
BOOST_CHECK_EQUAL( env2.p.ready(), false );
|
||||
|
||||
BOOST_CHECK_EQUAL( env2.p.consume(frame+1,1,env2.ec), 1 );
|
||||
BOOST_CHECK( !env2.ec );
|
||||
BOOST_CHECK_EQUAL( env2.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env2.p.consume(frame+1,1,env2.ec), 1 );
|
||||
BOOST_CHECK( !env2.ec );
|
||||
BOOST_CHECK_EQUAL( env2.p.ready(), true );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( frame_small_binary_unmasked ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[4] = {0x82, 0x02, 0x2A, 0x2A};
|
||||
uint8_t frame[4] = {0x82, 0x02, 0x2A, 0x2A};
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,4,env.ec), 4 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,4,env.ec), 4 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
|
||||
message_ptr foo = env.p.get_message();
|
||||
message_ptr foo = env.p.get_message();
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload(), "**" );
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( frame_extended_binary_unmasked ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
|
||||
frame[0] = 0x82;
|
||||
frame[1] = 0x7E;
|
||||
frame[2] = 0x00;
|
||||
frame[3] = 0x7E;
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
|
||||
frame[0] = 0x82;
|
||||
frame[1] = 0x7E;
|
||||
frame[2] = 0x00;
|
||||
frame[3] = 0x7E;
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,130,env.ec), 130 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,130,env.ec), 130 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
|
||||
message_ptr foo = env.p.get_message();
|
||||
message_ptr foo = env.p.get_message();
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( frame_jumbo_binary_unmasked ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,130,env.ec), 130 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,130,env.ec), 130 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
|
||||
message_ptr foo = env.p.get_message();
|
||||
message_ptr foo = env.p.get_message();
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( control_frame_too_large ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[130] = {0x88, 0x7E, 0x00, 0x7E};
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
uint8_t frame[130] = {0x88, 0x7E, 0x00, 0x7E};
|
||||
std::fill_n(frame+4,126,0x2A);
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,130,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::control_too_big );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,130,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::control_too_big );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( rsv_bits_used ) {
|
||||
uint8_t frame[3][2] = {{0x90, 0x00},
|
||||
{0xA0, 0x00},
|
||||
{0xC0, 0x00}};
|
||||
uint8_t frame[3][2] = {{0x90, 0x00},
|
||||
{0xA0, 0x00},
|
||||
{0xC0, 0x00}};
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
processor_setup env(false);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
processor_setup env(false);
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame[i],2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::invalid_rsv_bit );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame[i],2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::invalid_rsv_bit );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( reserved_opcode_used ) {
|
||||
uint8_t frame[10][2] = {{0x83, 0x00},
|
||||
{0x84, 0x00},
|
||||
{0x85, 0x00},
|
||||
{0x86, 0x00},
|
||||
{0x87, 0x00},
|
||||
{0x8B, 0x00},
|
||||
{0x8C, 0x00},
|
||||
{0x8D, 0x00},
|
||||
{0x8E, 0x00},
|
||||
{0x8F, 0x00}};
|
||||
uint8_t frame[10][2] = {{0x83, 0x00},
|
||||
{0x84, 0x00},
|
||||
{0x85, 0x00},
|
||||
{0x86, 0x00},
|
||||
{0x87, 0x00},
|
||||
{0x8B, 0x00},
|
||||
{0x8C, 0x00},
|
||||
{0x8D, 0x00},
|
||||
{0x8E, 0x00},
|
||||
{0x8F, 0x00}};
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
processor_setup env(false);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
processor_setup env(false);
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame[i],2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::invalid_opcode );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame[i],2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::invalid_opcode );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( fragmented_control_message ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[2] = {0x08, 0x00};
|
||||
uint8_t frame[2] = {0x08, 0x00};
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::fragmented_control );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::fragmented_control );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( fragmented_binary_message ) {
|
||||
processor_setup env0(false);
|
||||
processor_setup env1(false);
|
||||
processor_setup env0(false);
|
||||
processor_setup env1(false);
|
||||
|
||||
uint8_t frame0[6] = {0x02, 0x01, 0x2A, 0x80, 0x01, 0x2A};
|
||||
uint8_t frame1[8] = {0x02, 0x01, 0x2A, 0x89, 0x00, 0x80, 0x01, 0x2A};
|
||||
uint8_t frame0[6] = {0x02, 0x01, 0x2A, 0x80, 0x01, 0x2A};
|
||||
uint8_t frame1[8] = {0x02, 0x01, 0x2A, 0x89, 0x00, 0x80, 0x01, 0x2A};
|
||||
|
||||
// read fragmented message in one chunk
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0,6,env0.ec), 6 );
|
||||
// read fragmented message in one chunk
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0,6,env0.ec), 6 );
|
||||
BOOST_CHECK( !env0.ec );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
|
||||
// read fragmented message in two chunks
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0,3,env0.ec), 3 );
|
||||
// read fragmented message in two chunks
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0,3,env0.ec), 3 );
|
||||
BOOST_CHECK( !env0.ec );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0+3,3,env0.ec), 3 );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame0+3,3,env0.ec), 3 );
|
||||
BOOST_CHECK( !env0.ec );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
|
||||
// read fragmented message with control message in between
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame1,8,env0.ec), 5 );
|
||||
// read fragmented message with control message in between
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame1,8,env0.ec), 5 );
|
||||
BOOST_CHECK( !env0.ec );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_opcode(), websocketpp::frame::opcode::PING);
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame1+5,3,env0.ec), 3 );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_opcode(), websocketpp::frame::opcode::PING);
|
||||
BOOST_CHECK_EQUAL( env0.p.consume(frame1+5,3,env0.ec), 3 );
|
||||
BOOST_CHECK( !env0.ec );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env0.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message()->get_payload(), "**" );
|
||||
|
||||
// read lone continuation frame
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env0.p.consume(frame0+3,3,env0.ec), 0);
|
||||
BOOST_CHECK_EQUAL( env0.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env0.p.consume(frame0+3,3,env0.ec), 0);
|
||||
BOOST_CHECK_EQUAL( env0.ec, websocketpp::processor::error::invalid_continuation );
|
||||
|
||||
// read two start frames in a row
|
||||
BOOST_CHECK_EQUAL( env1.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env1.p.consume(frame0,3,env1.ec), 3);
|
||||
BOOST_CHECK_EQUAL( env1.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env1.p.consume(frame0,3,env1.ec), 3);
|
||||
BOOST_CHECK( !env1.ec );
|
||||
BOOST_CHECK_GT( env1.p.consume(frame0,3,env1.ec), 0);
|
||||
BOOST_CHECK_GT( env1.p.consume(frame0,3,env1.ec), 0);
|
||||
BOOST_CHECK_EQUAL( env1.ec, websocketpp::processor::error::invalid_continuation );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( unmasked_client_frame ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
uint8_t frame[2] = {0x82, 0x00};
|
||||
uint8_t frame[2] = {0x82, 0x00};
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::masking_required );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,2,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::masking_required );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( masked_server_frame ) {
|
||||
processor_setup env(false);
|
||||
processor_setup env(false);
|
||||
|
||||
uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
|
||||
uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,8,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::masking_forbidden );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_GT( env.p.consume(frame,8,env.ec), 0 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::masking_forbidden );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( frame_small_binary_masked ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
|
||||
uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
|
||||
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,8,env.ec), 8 );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame,8,env.ec), 8 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "**" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( masked_fragmented_binary_message ) {
|
||||
processor_setup env(true);
|
||||
|
||||
uint8_t frame0[14] = {0x02, 0x81, 0xAB, 0x23, 0x98, 0x45, 0x81,
|
||||
0x80, 0x81, 0xB8, 0x34, 0x12, 0xFF, 0x92};
|
||||
uint8_t frame0[14] = {0x02, 0x81, 0xAB, 0x23, 0x98, 0x45, 0x81,
|
||||
0x80, 0x81, 0xB8, 0x34, 0x12, 0xFF, 0x92};
|
||||
|
||||
// read fragmented message in one chunk
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame0,14,env.ec), 14 );
|
||||
// read fragmented message in one chunk
|
||||
BOOST_CHECK_EQUAL( env.p.get_message(), message_ptr() );
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame0,14,env.ec), 14 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "**" );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "**" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( prepare_data_frame ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
|
||||
message_ptr in = env.msg_manager->get_message();
|
||||
message_ptr out = env.msg_manager->get_message();
|
||||
@@ -489,6 +491,36 @@ BOOST_AUTO_TEST_CASE( prepare_data_frame ) {
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( single_frame_message_too_large ) {
|
||||
processor_setup env(true);
|
||||
|
||||
env.p.set_max_message_size(3);
|
||||
|
||||
uint8_t frame0[10] = {0x82, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
|
||||
|
||||
// read message that is one byte too large
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame0,10,env.ec), 6 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::message_too_big );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( multiple_frame_message_too_large ) {
|
||||
processor_setup env(true);
|
||||
|
||||
env.p.set_max_message_size(4);
|
||||
|
||||
uint8_t frame0[8] = {0x02, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
|
||||
uint8_t frame1[9] = {0x80, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
|
||||
|
||||
// read first message frame with size under the limit
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame0,8,env.ec), 8 );
|
||||
BOOST_CHECK( !env.ec );
|
||||
|
||||
// read second message frame that puts the size over the limit
|
||||
BOOST_CHECK_EQUAL( env.p.consume(frame1,9,env.ec), 6 );
|
||||
BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::message_too_big );
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( client_handshake_request ) {
|
||||
processor_setup env(false);
|
||||
@@ -606,7 +638,7 @@ BOOST_AUTO_TEST_CASE( extension_negotiation_unknown ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_subprotocols_empty ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
std::vector<std::string> subps;
|
||||
|
||||
BOOST_CHECK( !env.p.extract_subprotocols(env.req,subps) );
|
||||
@@ -614,7 +646,7 @@ BOOST_AUTO_TEST_CASE( extract_subprotocols_empty ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_subprotocols_one ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
std::vector<std::string> subps;
|
||||
|
||||
env.req.replace_header("Sec-WebSocket-Protocol","foo");
|
||||
@@ -625,7 +657,7 @@ BOOST_AUTO_TEST_CASE( extract_subprotocols_one ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_subprotocols_multiple ) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
std::vector<std::string> subps;
|
||||
|
||||
env.req.replace_header("Sec-WebSocket-Protocol","foo,bar");
|
||||
@@ -637,7 +669,7 @@ BOOST_AUTO_TEST_CASE( extract_subprotocols_multiple ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_subprotocols_invalid) {
|
||||
processor_setup env(true);
|
||||
processor_setup env(true);
|
||||
std::vector<std::string> subps;
|
||||
|
||||
env.req.replace_header("Sec-WebSocket-Protocol","foo,bar,,,,");
|
||||
|
||||
@@ -132,4 +132,4 @@ BOOST_AUTO_TEST_CASE( version_non_numeric ) {
|
||||
r.consume(handshake.c_str(),handshake.size());
|
||||
|
||||
BOOST_CHECK(websocketpp::processor::get_websocket_version(r) == -1);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ Import('polyfill_libs')
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','random'],env) + [platform_libs]
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','random','system'],env) + [platform_libs]
|
||||
|
||||
objs = env.Object('random_none_boost.o', ["none.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('random_device_boost.o', ["random_device.cpp"], LIBS = BOOST_LIBS)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
@@ -130,8 +130,8 @@ BOOST_AUTO_TEST_CASE( connect_con ) {
|
||||
|
||||
// TODO: more tests related to reading the HTTP response
|
||||
std::stringstream channel2;
|
||||
channel2 << "e\r\n\r\n";
|
||||
channel2 >> *con;
|
||||
channel2 << "e\r\n\r\n";
|
||||
channel2 >> *con;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( select_subprotocol ) {
|
||||
@@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE( select_subprotocol ) {
|
||||
|
||||
con->select_subprotocol("foo",ec);
|
||||
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::server_only) );
|
||||
BOOST_CHECK_THROW( con->select_subprotocol("foo") , websocketpp::lib::error_code );
|
||||
BOOST_CHECK_THROW( con->select_subprotocol("foo") , websocketpp::exception );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( add_subprotocols_invalid ) {
|
||||
@@ -158,11 +158,11 @@ BOOST_AUTO_TEST_CASE( add_subprotocols_invalid ) {
|
||||
|
||||
con->add_subprotocol("",ec);
|
||||
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::invalid_subprotocol) );
|
||||
BOOST_CHECK_THROW( con->add_subprotocol("") , websocketpp::lib::error_code );
|
||||
BOOST_CHECK_THROW( con->add_subprotocol("") , websocketpp::exception );
|
||||
|
||||
con->add_subprotocol("foo,bar",ec);
|
||||
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::invalid_subprotocol) );
|
||||
BOOST_CHECK_THROW( con->add_subprotocol("foo,bar") , websocketpp::lib::error_code );
|
||||
BOOST_CHECK_THROW( con->add_subprotocol("foo,bar") , websocketpp::exception );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( add_subprotocols ) {
|
||||
|
||||
+38
-38
@@ -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:
|
||||
@@ -67,19 +67,19 @@ std::string run_server_test(server& s, std::string input) {
|
||||
server::connection_ptr con;
|
||||
std::stringstream output;
|
||||
|
||||
s.register_ostream(&output);
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.register_ostream(&output);
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/* handler library*/
|
||||
@@ -121,8 +121,8 @@ BOOST_AUTO_TEST_CASE( basic_websocket_request ) {
|
||||
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE( invalid_websocket_version ) {
|
||||
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
//s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
//s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
@@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE( unimplemented_websocket_version ) {
|
||||
|
||||
std::string output = "HTTP/1.1 400 Bad Request\r\nSec-WebSocket-Version: 0,7,8,13\r\nServer: test\r\n\r\n";
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
@@ -154,11 +154,11 @@ BOOST_AUTO_TEST_CASE( list_subprotocol_empty ) {
|
||||
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string subprotocol;
|
||||
std::string subprotocol;
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&subprotocol,::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&subprotocol,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
BOOST_CHECK_EQUAL(subprotocol, "");
|
||||
@@ -169,13 +169,13 @@ BOOST_AUTO_TEST_CASE( list_subprotocol_one ) {
|
||||
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string validate;
|
||||
std::string open;
|
||||
std::string validate;
|
||||
std::string open;
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
BOOST_CHECK_EQUAL(validate, "foo,");
|
||||
@@ -187,13 +187,13 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_one ) {
|
||||
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string validate;
|
||||
std::string open;
|
||||
std::string validate;
|
||||
std::string open;
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"foo",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"foo",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
BOOST_CHECK_EQUAL(validate, "foo,");
|
||||
@@ -205,17 +205,17 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_invalid ) {
|
||||
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: foo\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string validate;
|
||||
std::string open;
|
||||
std::string validate;
|
||||
std::string open;
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"foo2",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"foo2",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
|
||||
std::string o;
|
||||
std::string o;
|
||||
|
||||
BOOST_CHECK_THROW(o = run_server_test(s,input), websocketpp::lib::error_code);
|
||||
BOOST_CHECK_THROW(o = run_server_test(s,input), websocketpp::exception);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( accept_subprotocol_two ) {
|
||||
@@ -223,13 +223,13 @@ BOOST_AUTO_TEST_CASE( accept_subprotocol_two ) {
|
||||
|
||||
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nSec-WebSocket-Protocol: bar\r\nServer: test\r\nUpgrade: websocket\r\n\r\n";
|
||||
|
||||
std::string validate;
|
||||
std::string open;
|
||||
std::string validate;
|
||||
std::string open;
|
||||
|
||||
server s;
|
||||
server s;
|
||||
s.set_user_agent("test");
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"bar",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
s.set_validate_handler(bind(&validate_func_subprotocol,&s,&validate,"bar",::_1));
|
||||
s.set_open_handler(bind(&open_func_subprotocol,&s,&open,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
BOOST_CHECK_EQUAL(validate, "foo,bar,");
|
||||
|
||||
@@ -11,7 +11,7 @@ Import('tls_libs')
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','random'],env) + [platform_libs] + [tls_libs]
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','random','chrono'],env) + [platform_libs] + [tls_libs]
|
||||
|
||||
objs = env.Object('boost_integration.o', ["integration.cpp"], LIBS = BOOST_LIBS)
|
||||
prgs = env.Program('test_boost_integration', ["boost_integration.o"], LIBS = BOOST_LIBS)
|
||||
|
||||
@@ -11,7 +11,7 @@ Import('tls_libs')
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread'],env) + [platform_libs] + [tls_libs]
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','chrono'],env) + [platform_libs] + [tls_libs]
|
||||
|
||||
objs = env.Object('base_boost.o', ["base.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('timers_boost.o', ["timers.cpp"], LIBS = BOOST_LIBS)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
@@ -107,7 +107,7 @@ struct config {
|
||||
|
||||
// Mock context that does no validation
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl) {
|
||||
return context_ptr(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
}
|
||||
|
||||
|
||||
+205
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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,8 +30,11 @@
|
||||
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/config/core.hpp>
|
||||
#include <websocketpp/config/core_client.hpp>
|
||||
#include <websocketpp/config/asio.hpp>
|
||||
#include <websocketpp/config/asio_client.hpp>
|
||||
#include <websocketpp/config/debug_asio.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
@@ -77,9 +80,57 @@ struct config : public websocketpp::config::asio_client {
|
||||
static const long timeout_pong = 500;
|
||||
};
|
||||
|
||||
struct config_tls : public websocketpp::config::asio_tls_client {
|
||||
typedef config type;
|
||||
typedef websocketpp::config::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;
|
||||
|
||||
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 websocketpp::log::level elog_level = websocketpp::log::elevel::all;
|
||||
//static const websocketpp::log::level alog_level = websocketpp::log::alevel::all;
|
||||
|
||||
/// Length of time before an opening handshake is aborted
|
||||
static const long timeout_open_handshake = 500;
|
||||
/// Length of time before a closing handshake is aborted
|
||||
static const long timeout_close_handshake = 500;
|
||||
/// Length of time to wait for a pong after a ping
|
||||
static const long timeout_pong = 500;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<config> server;
|
||||
typedef websocketpp::client<config> client;
|
||||
|
||||
typedef websocketpp::server<config_tls> server_tls;
|
||||
typedef websocketpp::client<config_tls> client_tls;
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::core> iostream_server;
|
||||
typedef websocketpp::client<websocketpp::config::core_client> iostream_client;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
@@ -103,6 +154,7 @@ void run_server(server * s, int port, bool log = false) {
|
||||
}
|
||||
|
||||
s->init_asio();
|
||||
s->set_reuse_addr(true);
|
||||
|
||||
s->listen(port);
|
||||
s->start_accept();
|
||||
@@ -117,9 +169,11 @@ void run_client(client & c, std::string uri, bool log = false) {
|
||||
c.clear_access_channels(websocketpp::log::alevel::all);
|
||||
c.clear_error_channels(websocketpp::log::elevel::all);
|
||||
}
|
||||
c.init_asio();
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
c.init_asio(ec);
|
||||
c.set_reuse_addr(true);
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
client::connection_ptr con = c.get_connection(uri,ec);
|
||||
BOOST_CHECK( !ec );
|
||||
c.connect(con);
|
||||
@@ -127,6 +181,14 @@ void run_client(client & c, std::string uri, bool log = false) {
|
||||
c.run();
|
||||
}
|
||||
|
||||
void run_client_and_mark(client * c, bool * flag, websocketpp::lib::mutex * mutex) {
|
||||
c->run();
|
||||
BOOST_CHECK( true );
|
||||
websocketpp::lib::lock_guard<websocketpp::lib::mutex> lock(*mutex);
|
||||
*flag = true;
|
||||
BOOST_CHECK( true );
|
||||
}
|
||||
|
||||
void run_time_limited_client(client & c, std::string uri, long timeout,
|
||||
bool log)
|
||||
{
|
||||
@@ -211,11 +273,12 @@ void run_dummy_client(std::string port) {
|
||||
}
|
||||
}
|
||||
|
||||
bool on_ping(websocketpp::connection_hdl, std::string payload) {
|
||||
bool on_ping(server * s, websocketpp::connection_hdl, std::string) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,"got ping");
|
||||
return false;
|
||||
}
|
||||
|
||||
void cancel_on_open(server * s, websocketpp::connection_hdl hdl) {
|
||||
void cancel_on_open(server * s, websocketpp::connection_hdl) {
|
||||
s->stop_listening();
|
||||
}
|
||||
|
||||
@@ -229,28 +292,30 @@ void stop_on_close(server * s, websocketpp::connection_hdl hdl) {
|
||||
template <typename T>
|
||||
void ping_on_open(T * c, std::string payload, websocketpp::connection_hdl hdl) {
|
||||
typename T::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
con->ping(payload);
|
||||
websocketpp::lib::error_code ec;
|
||||
con->ping(payload,ec);
|
||||
BOOST_CHECK_EQUAL(ec, websocketpp::lib::error_code());
|
||||
}
|
||||
|
||||
void fail_on_pong(websocketpp::connection_hdl hdl, std::string payload) {
|
||||
void fail_on_pong(websocketpp::connection_hdl, std::string) {
|
||||
BOOST_FAIL( "expected no pong handler" );
|
||||
}
|
||||
|
||||
void fail_on_pong_timeout(websocketpp::connection_hdl hdl, std::string payload) {
|
||||
void fail_on_pong_timeout(websocketpp::connection_hdl, std::string) {
|
||||
BOOST_FAIL( "expected no pong timeout" );
|
||||
}
|
||||
|
||||
void req_pong(std::string expected_payload, websocketpp::connection_hdl hdl,
|
||||
void req_pong(std::string expected_payload, websocketpp::connection_hdl,
|
||||
std::string payload)
|
||||
{
|
||||
BOOST_CHECK_EQUAL( expected_payload, payload );
|
||||
}
|
||||
|
||||
void fail_on_open(websocketpp::connection_hdl hdl) {
|
||||
void fail_on_open(websocketpp::connection_hdl) {
|
||||
BOOST_FAIL( "expected no open handler" );
|
||||
}
|
||||
|
||||
void delay(websocketpp::connection_hdl hdl, long duration) {
|
||||
void delay(websocketpp::connection_hdl, long duration) {
|
||||
sleep(duration);
|
||||
}
|
||||
|
||||
@@ -320,7 +385,7 @@ BOOST_AUTO_TEST_CASE( pong_timeout ) {
|
||||
server s;
|
||||
client c;
|
||||
|
||||
s.set_ping_handler(on_ping);
|
||||
s.set_ping_handler(bind(&on_ping, &s,::_1,::_2));
|
||||
s.set_close_handler(bind(&stop_on_close,&s,::_1));
|
||||
|
||||
c.set_fail_handler(bind(&check_ec<client>,&c,
|
||||
@@ -333,7 +398,7 @@ BOOST_AUTO_TEST_CASE( pong_timeout ) {
|
||||
websocketpp::lib::error_code(),::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,6));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
run_client(c, "http://localhost:9005",false);
|
||||
@@ -351,7 +416,7 @@ BOOST_AUTO_TEST_CASE( client_open_handshake_timeout ) {
|
||||
websocketpp::error::open_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_dummy_server,9005));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,6));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
sthread.detach();
|
||||
tthread.detach();
|
||||
|
||||
@@ -368,7 +433,7 @@ BOOST_AUTO_TEST_CASE( server_open_handshake_timeout ) {
|
||||
websocketpp::error::open_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,6));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
run_dummy_client("9005");
|
||||
@@ -391,10 +456,10 @@ BOOST_AUTO_TEST_CASE( client_self_initiated_close_handshake_timeout ) {
|
||||
websocketpp::error::close_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,6));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
run_client(c, "http://localhost:9005",false);
|
||||
run_client(c, "http://localhost:9005", false);
|
||||
|
||||
sthread.join();
|
||||
}
|
||||
@@ -423,10 +488,130 @@ BOOST_AUTO_TEST_CASE( server_self_initiated_close_handshake_timeout ) {
|
||||
c.set_open_handler(bind(&delay,::_1,1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,6));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
run_client(c, "http://localhost:9005",false);
|
||||
|
||||
sthread.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( client_runs_out_of_work ) {
|
||||
client c;
|
||||
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,3));
|
||||
tthread.detach();
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
c.init_asio(ec);
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
c.run();
|
||||
|
||||
// This test checks that an io_service with no work ends immediately.
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( client_is_perpetual ) {
|
||||
client c;
|
||||
bool flag = false;
|
||||
websocketpp::lib::mutex mutex;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
c.init_asio(ec);
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
c.start_perpetual();
|
||||
|
||||
websocketpp::lib::thread cthread(websocketpp::lib::bind(&run_client_and_mark,&c,&flag,&mutex));
|
||||
|
||||
sleep(1);
|
||||
|
||||
{
|
||||
// Checks that the thread hasn't exited yet
|
||||
websocketpp::lib::lock_guard<websocketpp::lib::mutex> lock(mutex);
|
||||
BOOST_CHECK( !flag );
|
||||
}
|
||||
|
||||
c.stop_perpetual();
|
||||
|
||||
sleep(1);
|
||||
|
||||
{
|
||||
// Checks that the thread has exited
|
||||
websocketpp::lib::lock_guard<websocketpp::lib::mutex> lock(mutex);
|
||||
BOOST_CHECK( flag );
|
||||
}
|
||||
|
||||
cthread.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( client_failed_connection ) {
|
||||
client c;
|
||||
|
||||
run_time_limited_client(c,"http://localhost:9005", 5, false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( stop_listening ) {
|
||||
server s;
|
||||
client c;
|
||||
|
||||
// the first connection stops the server from listening
|
||||
s.set_open_handler(bind(&cancel_on_open,&s,::_1));
|
||||
|
||||
// client immediately closes after opening a connection
|
||||
c.set_open_handler(bind(&close<client>,&c,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,5));
|
||||
tthread.detach();
|
||||
|
||||
run_client(c, "http://localhost:9005",false);
|
||||
|
||||
sthread.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( pause_reading ) {
|
||||
iostream_server s;
|
||||
std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
|
||||
char buffer[2] = { char(0x81), char(0x80) };
|
||||
|
||||
// suppress output (it needs a place to go to avoid error but we don't care what it is)
|
||||
std::stringstream null_output;
|
||||
s.register_ostream(&null_output);
|
||||
|
||||
iostream_server::connection_ptr con = s.get_connection();
|
||||
con->start();
|
||||
|
||||
// read handshake, should work
|
||||
BOOST_CHECK_EQUAL( con->read_some(handshake.data(), handshake.length()), handshake.length());
|
||||
|
||||
// pause reading and try again. The first read should work, the second should return 0
|
||||
// the first read was queued already after the handshake so it will go through because
|
||||
// reading wasn't paused when it was queued. The byte it reads wont be enough to
|
||||
// complete the frame so another read will be requested. This one wont actually happen
|
||||
// because the connection is paused now.
|
||||
con->pause_reading();
|
||||
BOOST_CHECK_EQUAL( con->read_some(buffer, 1), 1);
|
||||
BOOST_CHECK_EQUAL( con->read_some(buffer+1, 1), 0);
|
||||
// resume reading and try again. Should work this time because the resume should have
|
||||
// re-queued a read.
|
||||
con->resume_reading();
|
||||
BOOST_CHECK_EQUAL( con->read_some(buffer+1, 1), 1);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( server_connection_cleanup ) {
|
||||
server_tls s;
|
||||
}
|
||||
|
||||
#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
BOOST_AUTO_TEST_CASE( move_construct_transport ) {
|
||||
server s1;
|
||||
|
||||
server s2(std::move(s1));
|
||||
}
|
||||
#endif // _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
@@ -58,11 +58,12 @@ struct stub_con : public iostream_con {
|
||||
typedef websocketpp::lib::shared_ptr<type> ptr;
|
||||
typedef iostream_con::timer_ptr timer_ptr;
|
||||
|
||||
stub_con(bool is_server, config::alog_type &a, config::elog_type & e)
|
||||
stub_con(bool is_server, config::alog_type & a, config::elog_type & e)
|
||||
: iostream_con(is_server,a,e)
|
||||
// Set the error to a known code that is unused by the library
|
||||
// This way we can easily confirm that the handler was run at all.
|
||||
, ec(websocketpp::error::make_error_code(websocketpp::error::test))
|
||||
, indef_read_total(0)
|
||||
{}
|
||||
|
||||
/// Get a shared pointer to this component
|
||||
@@ -94,7 +95,7 @@ struct stub_con : public iostream_con {
|
||||
}
|
||||
|
||||
void async_read_at_least(size_t num_bytes, char *buf, size_t len)
|
||||
{
|
||||
{
|
||||
iostream_con::async_read_at_least(
|
||||
num_bytes,
|
||||
buf,
|
||||
@@ -107,37 +108,85 @@ struct stub_con : public iostream_con {
|
||||
);
|
||||
}
|
||||
|
||||
void handle_op(const websocketpp::lib::error_code& e) {
|
||||
void handle_op(websocketpp::lib::error_code const & e) {
|
||||
ec = e;
|
||||
}
|
||||
|
||||
void async_read_indef(size_t num_bytes, char *buf, size_t len)
|
||||
{
|
||||
indef_read_size = num_bytes;
|
||||
indef_read_buf = buf;
|
||||
indef_read_len = len;
|
||||
|
||||
indef_read();
|
||||
}
|
||||
|
||||
void indef_read() {
|
||||
iostream_con::async_read_at_least(
|
||||
indef_read_size,
|
||||
indef_read_buf,
|
||||
indef_read_len,
|
||||
websocketpp::lib::bind(
|
||||
&stub_con::handle_indef,
|
||||
type::get_shared(),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void handle_indef(websocketpp::lib::error_code const & e, size_t amt_read) {
|
||||
ec = e;
|
||||
indef_read_total += amt_read;
|
||||
|
||||
indef_read();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
iostream_con::async_shutdown(
|
||||
websocketpp::lib::bind(
|
||||
&stub_con::handle_async_shutdown,
|
||||
type::get_shared(),
|
||||
websocketpp::lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void handle_async_shutdown(websocketpp::lib::error_code const & e) {
|
||||
ec = e;
|
||||
}
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
size_t indef_read_size;
|
||||
char * indef_read_buf;
|
||||
size_t indef_read_len;
|
||||
size_t indef_read_total;
|
||||
};
|
||||
|
||||
// Stubs
|
||||
config::alog_type a;
|
||||
config::elog_type e;
|
||||
config::alog_type alogger;
|
||||
config::elog_type elogger;
|
||||
|
||||
BOOST_AUTO_TEST_CASE( const_methods ) {
|
||||
iostream_con::ptr con(new iostream_con(true,a,e));
|
||||
iostream_con::ptr con(new iostream_con(true,alogger,elogger));
|
||||
|
||||
BOOST_CHECK( con->is_secure() == false );
|
||||
BOOST_CHECK( con->get_remote_endpoint() == "iostream transport" );
|
||||
BOOST_CHECK( !con->is_secure() );
|
||||
BOOST_CHECK_EQUAL( con->get_remote_endpoint(), "iostream transport" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( write_before_ostream_set ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
BOOST_AUTO_TEST_CASE( write_before_output_method_set ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
con->write("foo");
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::transport::iostream::error::output_stream_required) );
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
con->write(bufs);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::transport::iostream::error::output_stream_required) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::iostream::error::output_stream_required) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
BOOST_AUTO_TEST_CASE( async_write_ostream ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
std::stringstream output;
|
||||
|
||||
@@ -146,13 +195,55 @@ BOOST_AUTO_TEST_CASE( async_write ) {
|
||||
con->write("foo");
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( output.str() == "foo" );
|
||||
BOOST_CHECK_EQUAL( output.str(), "foo" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_0 ) {
|
||||
websocketpp::lib::error_code write_handler(std::string & o, websocketpp::connection_hdl, char const * buf, size_t len) {
|
||||
o += std::string(buf,len);
|
||||
return websocketpp::lib::error_code();
|
||||
}
|
||||
|
||||
websocketpp::lib::error_code vector_write_handler(std::string & o, websocketpp::connection_hdl, std::vector<websocketpp::transport::buffer> const & bufs) {
|
||||
std::vector<websocketpp::transport::buffer>::const_iterator it;
|
||||
for (it = bufs.begin(); it != bufs.end(); it++) {
|
||||
o += std::string((*it).buf, (*it).len);
|
||||
}
|
||||
|
||||
return websocketpp::lib::error_code();
|
||||
}
|
||||
|
||||
websocketpp::lib::error_code write_handler_error(websocketpp::connection_hdl, char const *, size_t) {
|
||||
return make_error_code(websocketpp::transport::error::general);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_handler ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
std::string output;
|
||||
|
||||
con->set_write_handler(websocketpp::lib::bind(
|
||||
&write_handler,
|
||||
websocketpp::lib::ref(output),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2,
|
||||
websocketpp::lib::placeholders::_3
|
||||
));
|
||||
con->write("foo");
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL(output, "foo");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_handler_error ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
con->set_write_handler(&write_handler_error);
|
||||
con->write("foo");
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::error::general) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_0_ostream ) {
|
||||
std::stringstream output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->register_ostream(&output);
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
@@ -160,13 +251,34 @@ BOOST_AUTO_TEST_CASE( async_write_vector_0 ) {
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( output.str() == "" );
|
||||
BOOST_CHECK_EQUAL( output.str(), "" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_1 ) {
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_0_write_handler ) {
|
||||
std::string output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
con->set_write_handler(websocketpp::lib::bind(
|
||||
&write_handler,
|
||||
websocketpp::lib::ref(output),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2,
|
||||
websocketpp::lib::placeholders::_3
|
||||
));
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( output, "" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_1_ostream ) {
|
||||
std::stringstream output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->register_ostream(&output);
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
@@ -178,13 +290,37 @@ BOOST_AUTO_TEST_CASE( async_write_vector_1 ) {
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( output.str() == "foo" );
|
||||
BOOST_CHECK_EQUAL( output.str(), "foo" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_2 ) {
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_1_write_handler ) {
|
||||
std::string output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->set_write_handler(websocketpp::lib::bind(
|
||||
&write_handler,
|
||||
websocketpp::lib::ref(output),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2,
|
||||
websocketpp::lib::placeholders::_3
|
||||
));
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
|
||||
std::string foo = "foo";
|
||||
|
||||
bufs.push_back(websocketpp::transport::buffer(foo.data(),foo.size()));
|
||||
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( output, "foo" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_2_ostream ) {
|
||||
std::stringstream output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->register_ostream(&output);
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
@@ -198,92 +334,143 @@ BOOST_AUTO_TEST_CASE( async_write_vector_2 ) {
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( output.str() == "foobar" );
|
||||
BOOST_CHECK_EQUAL( output.str(), "foobar" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_2_write_handler ) {
|
||||
std::string output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->set_write_handler(websocketpp::lib::bind(
|
||||
&write_handler,
|
||||
websocketpp::lib::ref(output),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2,
|
||||
websocketpp::lib::placeholders::_3
|
||||
));
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
|
||||
std::string foo = "foo";
|
||||
std::string bar = "bar";
|
||||
|
||||
bufs.push_back(websocketpp::transport::buffer(foo.data(),foo.size()));
|
||||
bufs.push_back(websocketpp::transport::buffer(bar.data(),bar.size()));
|
||||
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( output, "foobar" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_write_vector_2_vector_write_handler ) {
|
||||
std::string output;
|
||||
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
con->set_vector_write_handler(websocketpp::lib::bind(
|
||||
&vector_write_handler,
|
||||
websocketpp::lib::ref(output),
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2
|
||||
));
|
||||
|
||||
std::vector<websocketpp::transport::buffer> bufs;
|
||||
|
||||
std::string foo = "foo";
|
||||
std::string bar = "bar";
|
||||
|
||||
bufs.push_back(websocketpp::transport::buffer(foo.data(),foo.size()));
|
||||
bufs.push_back(websocketpp::transport::buffer(bar.data(),bar.size()));
|
||||
|
||||
con->write(bufs);
|
||||
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( output, "foobar" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least_too_much ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[10];
|
||||
|
||||
con->async_read_at_least(11,buf,10);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::transport::iostream::error::invalid_num_bytes) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::iostream::error::invalid_num_bytes) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least_double_read ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[10];
|
||||
|
||||
con->async_read_at_least(5,buf,10);
|
||||
con->async_read_at_least(5,buf,10);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::transport::iostream::error::double_read) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::iostream::error::double_read) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[10];
|
||||
|
||||
memset(buf,'x',10);
|
||||
|
||||
con->async_read_at_least(5,buf,10);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
std::stringstream channel;
|
||||
channel << "abcd";
|
||||
channel >> *con;
|
||||
BOOST_CHECK( channel.tellg() == -1 );
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
channel << "abcd";
|
||||
channel >> *con;
|
||||
BOOST_CHECK_EQUAL( channel.tellg(), -1 );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
std::stringstream channel2;
|
||||
channel2 << "e";
|
||||
channel2 >> *con;
|
||||
BOOST_CHECK( channel2.tellg() == -1 );
|
||||
channel2 << "e";
|
||||
channel2 >> *con;
|
||||
BOOST_CHECK_EQUAL( channel2.tellg(), -1 );
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( std::string(buf,10) == "abcdexxxxx" );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdexxxxx" );
|
||||
|
||||
std::stringstream channel3;
|
||||
channel3 << "f";
|
||||
channel3 >> *con;
|
||||
BOOST_CHECK( channel3.tellg() == 0 );
|
||||
channel3 << "f";
|
||||
channel3 >> *con;
|
||||
BOOST_CHECK_EQUAL( channel3.tellg(), 0 );
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( std::string(buf,10) == "abcdexxxxx" );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdexxxxx" );
|
||||
con->async_read_at_least(1,buf+5,5);
|
||||
channel3 >> *con;
|
||||
BOOST_CHECK( channel3.tellg() == -1 );
|
||||
BOOST_CHECK_EQUAL( channel3.tellg(), -1 );
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( std::string(buf,10) == "abcdefxxxx" );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdefxxxx" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least2 ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[10];
|
||||
|
||||
memset(buf,'x',10);
|
||||
|
||||
con->async_read_at_least(5,buf,5);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
std::stringstream channel;
|
||||
channel << "abcdefg";
|
||||
channel >> *con;
|
||||
BOOST_CHECK( channel.tellg() == 5 );
|
||||
channel << "abcdefg";
|
||||
channel >> *con;
|
||||
BOOST_CHECK_EQUAL( channel.tellg(), 5 );
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( std::string(buf,10) == "abcdexxxxx" );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdexxxxx" );
|
||||
|
||||
con->async_read_at_least(1,buf+5,5);
|
||||
channel >> *con;
|
||||
BOOST_CHECK( channel.tellg() == -1 );
|
||||
channel >> *con;
|
||||
BOOST_CHECK_EQUAL( channel.tellg(), -1 );
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK( std::string(buf,10) == "abcdefgxxx" );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdefgxxx" );
|
||||
}
|
||||
|
||||
void timer_callback_stub(const websocketpp::lib::error_code & ec) {}
|
||||
void timer_callback_stub(websocketpp::lib::error_code const &) {}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( set_timer ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
stub_con::timer_ptr tp = con->set_timer(1000,timer_callback_stub);
|
||||
|
||||
@@ -291,13 +478,13 @@ BOOST_AUTO_TEST_CASE( set_timer ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least_read_some ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[10];
|
||||
memset(buf,'x',10);
|
||||
|
||||
con->async_read_at_least(5,buf,5);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
char input[10] = "abcdefg";
|
||||
BOOST_CHECK_EQUAL(con->read_some(input,5), 5);
|
||||
@@ -314,33 +501,94 @@ BOOST_AUTO_TEST_CASE( async_read_at_least_read_some ) {
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "abcdefgxxx" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least_read_some_indef ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[20];
|
||||
memset(buf,'x',20);
|
||||
|
||||
con->async_read_indef(5,buf,5);
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
// here we expect to return early from read some because the outstanding
|
||||
// read was for 5 bytes and we were called with 10.
|
||||
char input[11] = "aaaaabbbbb";
|
||||
BOOST_CHECK_EQUAL(con->read_some(input,10), 5);
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "aaaaaxxxxx" );
|
||||
BOOST_CHECK_EQUAL( con->indef_read_total, 5 );
|
||||
|
||||
// A subsequent read should read 5 more because the indef read refreshes
|
||||
// itself. The new read will start again at the beginning of the buffer.
|
||||
BOOST_CHECK_EQUAL(con->read_some(input+5,5), 5);
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "bbbbbxxxxx" );
|
||||
BOOST_CHECK_EQUAL( con->indef_read_total, 10 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( async_read_at_least_read_all ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
char buf[20];
|
||||
memset(buf,'x',20);
|
||||
|
||||
con->async_read_indef(5,buf,5);
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
|
||||
char input[11] = "aaaaabbbbb";
|
||||
BOOST_CHECK_EQUAL(con->read_all(input,10), 10);
|
||||
BOOST_CHECK( !con->ec );
|
||||
BOOST_CHECK_EQUAL( std::string(buf,10), "bbbbbxxxxx" );
|
||||
BOOST_CHECK_EQUAL( con->indef_read_total, 10 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( eof_flag ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
char buf[10];
|
||||
con->async_read_at_least(5,buf,5);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
con->eof();
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::error::eof) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( fatal_error_flag ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
char buf[10];
|
||||
con->async_read_at_least(5,buf,5);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
con->fatal_error();
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::error::pass_through) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( shutdown ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
con->shutdown();
|
||||
BOOST_CHECK_EQUAL( con->ec, websocketpp::lib::error_code() );
|
||||
}
|
||||
|
||||
websocketpp::lib::error_code sd_handler(websocketpp::connection_hdl) {
|
||||
return make_error_code(websocketpp::transport::error::general);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( shutdown_handler ) {
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
con->set_shutdown_handler(&sd_handler);
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
con->shutdown();
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::transport::error::general) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( shared_pointer_memory_cleanup ) {
|
||||
stub_con::ptr con(new stub_con(true,a,e));
|
||||
stub_con::ptr con(new stub_con(true,alogger,elogger));
|
||||
|
||||
BOOST_CHECK_EQUAL(con.use_count(), 1);
|
||||
|
||||
char buf[10];
|
||||
memset(buf,'x',10);
|
||||
con->async_read_at_least(5,buf,5);
|
||||
BOOST_CHECK( con->ec == make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL( con->ec, make_error_code(websocketpp::error::test) );
|
||||
BOOST_CHECK_EQUAL(con.use_count(), 2);
|
||||
|
||||
char input[10] = "foo";
|
||||
|
||||
@@ -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:
|
||||
@@ -35,7 +35,7 @@
|
||||
BOOST_AUTO_TEST_CASE( placeholder ) {}
|
||||
|
||||
/*BOOST_AUTO_TEST_CASE( blank_error ) {
|
||||
websocketpp::lib::error_code ec;
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
BOOST_CHECK( !ec );
|
||||
}*/
|
||||
|
||||
@@ -16,11 +16,13 @@ objs = env.Object('uri_boost.o', ["uri.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('utilities_boost.o', ["utilities.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('close_boost.o', ["close.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('sha1_boost.o', ["sha1.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('error_boost.o', ["error.cpp"], LIBS = BOOST_LIBS)
|
||||
prgs = env.Program('test_uri_boost', ["uri_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_utility_boost', ["utilities_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_frame', ["frame.cpp"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_close_boost', ["close_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_sha1_boost', ["sha1_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_error_boost', ["error_boost.o"], LIBS = BOOST_LIBS)
|
||||
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
@@ -28,9 +30,11 @@ if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
objs += env_cpp11.Object('uri_stl.o', ["uri.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('close_stl.o', ["close.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('sha1_stl.o', ["sha1.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('error_stl.o', ["error.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_utility_stl', ["utilities_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_uri_stl', ["uri_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_close_stl', ["close_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_sha1_stl', ["sha1_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_error_stl', ["error_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
|
||||
Return('prgs')
|
||||
|
||||
+60
-60
@@ -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:
|
||||
@@ -37,89 +37,89 @@
|
||||
using namespace websocketpp;
|
||||
|
||||
BOOST_AUTO_TEST_CASE( reserved_values ) {
|
||||
BOOST_CHECK( !close::status::reserved(999) );
|
||||
BOOST_CHECK( close::status::reserved(1004) );
|
||||
BOOST_CHECK( close::status::reserved(1014) );
|
||||
BOOST_CHECK( close::status::reserved(1016) );
|
||||
BOOST_CHECK( close::status::reserved(2999) );
|
||||
BOOST_CHECK( !close::status::reserved(1000) );
|
||||
BOOST_CHECK( !close::status::reserved(999) );
|
||||
BOOST_CHECK( close::status::reserved(1004) );
|
||||
BOOST_CHECK( close::status::reserved(1014) );
|
||||
BOOST_CHECK( close::status::reserved(1016) );
|
||||
BOOST_CHECK( close::status::reserved(2999) );
|
||||
BOOST_CHECK( !close::status::reserved(1000) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( invalid_values ) {
|
||||
BOOST_CHECK( close::status::invalid(0) );
|
||||
BOOST_CHECK( close::status::invalid(999) );
|
||||
BOOST_CHECK( !close::status::invalid(1000) );
|
||||
BOOST_CHECK( close::status::invalid(1005) );
|
||||
BOOST_CHECK( close::status::invalid(1006) );
|
||||
BOOST_CHECK( close::status::invalid(1015) );
|
||||
BOOST_CHECK( !close::status::invalid(2999) );
|
||||
BOOST_CHECK( !close::status::invalid(3000) );
|
||||
BOOST_CHECK( close::status::invalid(5000) );
|
||||
BOOST_CHECK( close::status::invalid(0) );
|
||||
BOOST_CHECK( close::status::invalid(999) );
|
||||
BOOST_CHECK( !close::status::invalid(1000) );
|
||||
BOOST_CHECK( close::status::invalid(1005) );
|
||||
BOOST_CHECK( close::status::invalid(1006) );
|
||||
BOOST_CHECK( close::status::invalid(1015) );
|
||||
BOOST_CHECK( !close::status::invalid(2999) );
|
||||
BOOST_CHECK( !close::status::invalid(3000) );
|
||||
BOOST_CHECK( close::status::invalid(5000) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( value_extraction ) {
|
||||
lib::error_code ec;
|
||||
std::string payload = "oo";
|
||||
lib::error_code ec;
|
||||
std::string payload = "oo";
|
||||
|
||||
// Value = 1000
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xe8);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::normal );
|
||||
BOOST_CHECK( !ec );
|
||||
// Value = 1000
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xe8);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::normal );
|
||||
BOOST_CHECK( !ec );
|
||||
|
||||
// Value = 1004
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xec);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == 1004 );
|
||||
BOOST_CHECK( ec == error::reserved_close_code );
|
||||
// Value = 1004
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xec);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == 1004 );
|
||||
BOOST_CHECK( ec == error::reserved_close_code );
|
||||
|
||||
// Value = 1005
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xed);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status );
|
||||
BOOST_CHECK( ec == error::invalid_close_code );
|
||||
// Value = 1005
|
||||
payload[0] = 0x03;
|
||||
payload[1] = char(0xed);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status );
|
||||
BOOST_CHECK( ec == error::invalid_close_code );
|
||||
|
||||
// Value = 3000
|
||||
payload[0] = 0x0b;
|
||||
payload[1] = char(0xb8);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == 3000 );
|
||||
BOOST_CHECK( !ec );
|
||||
// Value = 3000
|
||||
payload[0] = 0x0b;
|
||||
payload[1] = char(0xb8);
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == 3000 );
|
||||
BOOST_CHECK( !ec );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_empty ) {
|
||||
lib::error_code ec;
|
||||
std::string payload = "";
|
||||
lib::error_code ec;
|
||||
std::string payload = "";
|
||||
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status );
|
||||
BOOST_CHECK( !ec );
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status );
|
||||
BOOST_CHECK( !ec );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_short ) {
|
||||
lib::error_code ec;
|
||||
std::string payload = "0";
|
||||
lib::error_code ec;
|
||||
std::string payload = "0";
|
||||
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::protocol_error );
|
||||
BOOST_CHECK( ec == error::bad_close_code );
|
||||
BOOST_CHECK( close::extract_code(payload,ec) == close::status::protocol_error );
|
||||
BOOST_CHECK( ec == error::bad_close_code );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extract_reason ) {
|
||||
lib::error_code ec;
|
||||
std::string payload = "00Foo";
|
||||
lib::error_code ec;
|
||||
std::string payload = "00Foo";
|
||||
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "Foo" );
|
||||
BOOST_CHECK( !ec );
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "Foo" );
|
||||
BOOST_CHECK( !ec );
|
||||
|
||||
payload = "";
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
|
||||
BOOST_CHECK( !ec );
|
||||
payload = "";
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
|
||||
BOOST_CHECK( !ec );
|
||||
|
||||
payload = "00";
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
|
||||
BOOST_CHECK( !ec );
|
||||
payload = "00";
|
||||
BOOST_CHECK( close::extract_reason(payload,ec) == "" );
|
||||
BOOST_CHECK( !ec );
|
||||
|
||||
payload = "000";
|
||||
payload[2] = char(0xFF);
|
||||
payload = "000";
|
||||
payload[2] = char(0xFF);
|
||||
|
||||
close::extract_reason(payload,ec);
|
||||
BOOST_CHECK( ec == error::invalid_utf8 );
|
||||
close::extract_reason(payload,ec);
|
||||
BOOST_CHECK( ec == error::invalid_utf8 );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
//#define BOOST_TEST_DYN_LINK
|
||||
#define BOOST_TEST_MODULE error
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <websocketpp/error.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE( constructing_exceptions ) {
|
||||
websocketpp::lib::error_code test_ec = websocketpp::error::make_error_code(websocketpp::error::test);
|
||||
websocketpp::lib::error_code general_ec = websocketpp::error::make_error_code(websocketpp::error::general);
|
||||
|
||||
websocketpp::exception b("foo");
|
||||
websocketpp::exception c("foo",test_ec);
|
||||
websocketpp::exception d("");
|
||||
websocketpp::exception e("",test_ec);
|
||||
|
||||
BOOST_CHECK_EQUAL(b.what(),"foo");
|
||||
BOOST_CHECK_EQUAL(b.code(),general_ec);
|
||||
|
||||
BOOST_CHECK_EQUAL(c.what(),"foo");
|
||||
BOOST_CHECK_EQUAL(c.code(),test_ec);
|
||||
|
||||
BOOST_CHECK_EQUAL(d.what(),"Generic error");
|
||||
BOOST_CHECK_EQUAL(d.code(),general_ec);
|
||||
|
||||
BOOST_CHECK_EQUAL(e.what(),"Test Error");
|
||||
BOOST_CHECK_EQUAL(e.code(),test_ec);
|
||||
}
|
||||
|
||||
+302
-302
@@ -37,98 +37,98 @@
|
||||
using namespace websocketpp;
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_bits ) {
|
||||
frame::basic_header h1(0x00,0x00); // all false
|
||||
frame::basic_header h2(0xF0,0x80); // all true
|
||||
frame::basic_header h1(0x00,0x00); // all false
|
||||
frame::basic_header h2(0xF0,0x80); // all true
|
||||
|
||||
// Read Values
|
||||
BOOST_CHECK( frame::get_fin(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv1(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv3(h1) == false );
|
||||
BOOST_CHECK( frame::get_masked(h1) == false );
|
||||
// Read Values
|
||||
BOOST_CHECK( frame::get_fin(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv1(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv3(h1) == false );
|
||||
BOOST_CHECK( frame::get_masked(h1) == false );
|
||||
|
||||
BOOST_CHECK( frame::get_fin(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv1(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv2(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv3(h2) == true );
|
||||
BOOST_CHECK( frame::get_masked(h2) == true );
|
||||
BOOST_CHECK( frame::get_fin(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv1(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv2(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv3(h2) == true );
|
||||
BOOST_CHECK( frame::get_masked(h2) == true );
|
||||
|
||||
// Set Values
|
||||
frame::set_fin(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0x80 );
|
||||
// Set Values
|
||||
frame::set_fin(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0x80 );
|
||||
|
||||
frame::set_rsv1(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xC0 );
|
||||
frame::set_rsv1(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xC0 );
|
||||
|
||||
frame::set_rsv2(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xE0 );
|
||||
frame::set_rsv2(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xE0 );
|
||||
|
||||
frame::set_rsv3(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xF0 );
|
||||
frame::set_rsv3(h1,true);
|
||||
BOOST_CHECK( h1.b0 == 0xF0 );
|
||||
|
||||
frame::set_masked(h1,true);
|
||||
BOOST_CHECK( h1.b1 == 0x80 );
|
||||
frame::set_masked(h1,true);
|
||||
BOOST_CHECK( h1.b1 == 0x80 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_constructors ) {
|
||||
// Read Values
|
||||
frame::basic_header h1(frame::opcode::TEXT,12,true,false);
|
||||
BOOST_CHECK( frame::get_opcode(h1) == frame::opcode::TEXT );
|
||||
BOOST_CHECK( frame::get_basic_size(h1) == 12 );
|
||||
BOOST_CHECK( frame::get_fin(h1) == true );
|
||||
BOOST_CHECK( frame::get_rsv1(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv3(h1) == false );
|
||||
BOOST_CHECK( frame::get_masked(h1) == false );
|
||||
// Read Values
|
||||
frame::basic_header h1(frame::opcode::TEXT,12,true,false);
|
||||
BOOST_CHECK( frame::get_opcode(h1) == frame::opcode::TEXT );
|
||||
BOOST_CHECK( frame::get_basic_size(h1) == 12 );
|
||||
BOOST_CHECK( frame::get_fin(h1) == true );
|
||||
BOOST_CHECK( frame::get_rsv1(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h1) == false );
|
||||
BOOST_CHECK( frame::get_rsv3(h1) == false );
|
||||
BOOST_CHECK( frame::get_masked(h1) == false );
|
||||
|
||||
frame::basic_header h2(frame::opcode::BINARY,0,false,false,false,true);
|
||||
BOOST_CHECK( frame::get_opcode(h2) == frame::opcode::BINARY );
|
||||
BOOST_CHECK( frame::get_basic_size(h2) == 0 );
|
||||
BOOST_CHECK( frame::get_fin(h2) == false );
|
||||
BOOST_CHECK( frame::get_rsv1(h2) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv3(h2) == false );
|
||||
BOOST_CHECK( frame::get_masked(h2) == false );
|
||||
frame::basic_header h2(frame::opcode::BINARY,0,false,false,false,true);
|
||||
BOOST_CHECK( frame::get_opcode(h2) == frame::opcode::BINARY );
|
||||
BOOST_CHECK( frame::get_basic_size(h2) == 0 );
|
||||
BOOST_CHECK( frame::get_fin(h2) == false );
|
||||
BOOST_CHECK( frame::get_rsv1(h2) == false );
|
||||
BOOST_CHECK( frame::get_rsv2(h2) == true );
|
||||
BOOST_CHECK( frame::get_rsv3(h2) == false );
|
||||
BOOST_CHECK( frame::get_masked(h2) == false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_size ) {
|
||||
frame::basic_header h1(0x00,0x00); // length 0
|
||||
frame::basic_header h2(0x00,0x01); // length 1
|
||||
frame::basic_header h3(0x00,0x7D); // length 125
|
||||
frame::basic_header h4(0x00,0x7E); // length 126
|
||||
frame::basic_header h5(0x00,0x7F); // length 127
|
||||
frame::basic_header h6(0x00,0x80); // length 0, mask bit set
|
||||
frame::basic_header h1(0x00,0x00); // length 0
|
||||
frame::basic_header h2(0x00,0x01); // length 1
|
||||
frame::basic_header h3(0x00,0x7D); // length 125
|
||||
frame::basic_header h4(0x00,0x7E); // length 126
|
||||
frame::basic_header h5(0x00,0x7F); // length 127
|
||||
frame::basic_header h6(0x00,0x80); // length 0, mask bit set
|
||||
|
||||
BOOST_CHECK( frame::get_basic_size(h1) == 0 );
|
||||
BOOST_CHECK( frame::get_basic_size(h2) == 1 );
|
||||
BOOST_CHECK( frame::get_basic_size(h3) == 125 );
|
||||
BOOST_CHECK( frame::get_basic_size(h4) == 126 );
|
||||
BOOST_CHECK( frame::get_basic_size(h5) == 127 );
|
||||
BOOST_CHECK( frame::get_basic_size(h6) == 0 );
|
||||
BOOST_CHECK( frame::get_basic_size(h1) == 0 );
|
||||
BOOST_CHECK( frame::get_basic_size(h2) == 1 );
|
||||
BOOST_CHECK( frame::get_basic_size(h3) == 125 );
|
||||
BOOST_CHECK( frame::get_basic_size(h4) == 126 );
|
||||
BOOST_CHECK( frame::get_basic_size(h5) == 127 );
|
||||
BOOST_CHECK( frame::get_basic_size(h6) == 0 );
|
||||
|
||||
/*frame::set_basic_size(h1,1);
|
||||
BOOST_CHECK( h1.b1 == 0x01 );
|
||||
/*frame::set_basic_size(h1,1);
|
||||
BOOST_CHECK( h1.b1 == 0x01 );
|
||||
|
||||
frame::set_basic_size(h1,125);
|
||||
BOOST_CHECK( h1.b1 == 0x7D );
|
||||
frame::set_basic_size(h1,125);
|
||||
BOOST_CHECK( h1.b1 == 0x7D );
|
||||
|
||||
frame::set_basic_size(h1,126);
|
||||
BOOST_CHECK( h1.b1 == 0x7E );
|
||||
frame::set_basic_size(h1,126);
|
||||
BOOST_CHECK( h1.b1 == 0x7E );
|
||||
|
||||
frame::set_basic_size(h1,127);
|
||||
BOOST_CHECK( h1.b1 == 0x7F );
|
||||
frame::set_basic_size(h1,127);
|
||||
BOOST_CHECK( h1.b1 == 0x7F );
|
||||
|
||||
frame::set_basic_size(h1,0);
|
||||
BOOST_CHECK( h1.b1 == 0x00 );*/
|
||||
frame::set_basic_size(h1,0);
|
||||
BOOST_CHECK( h1.b1 == 0x00 );*/
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_header_length ) {
|
||||
frame::basic_header h1(0x82,0x00); // short binary frame, unmasked
|
||||
frame::basic_header h2(0x82,0x80); // short binary frame, masked
|
||||
frame::basic_header h3(0x82,0x7E); // medium binary frame, unmasked
|
||||
frame::basic_header h4(0x82,0xFE); // medium binary frame, masked
|
||||
frame::basic_header h5(0x82,0x7F); // jumbo binary frame, unmasked
|
||||
frame::basic_header h6(0x82,0xFF); // jumbo binary frame, masked
|
||||
frame::basic_header h1(0x82,0x00); // short binary frame, unmasked
|
||||
frame::basic_header h2(0x82,0x80); // short binary frame, masked
|
||||
frame::basic_header h3(0x82,0x7E); // medium binary frame, unmasked
|
||||
frame::basic_header h4(0x82,0xFE); // medium binary frame, masked
|
||||
frame::basic_header h5(0x82,0x7F); // jumbo binary frame, unmasked
|
||||
frame::basic_header h6(0x82,0xFF); // jumbo binary frame, masked
|
||||
|
||||
BOOST_CHECK( frame::get_header_len(h1) == 2);
|
||||
BOOST_CHECK( frame::get_header_len(h2) == 6);
|
||||
@@ -139,127 +139,127 @@ BOOST_AUTO_TEST_CASE( basic_header_length ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( basic_opcode ) {
|
||||
frame::basic_header h1(0x00,0x00);
|
||||
frame::basic_header h1(0x00,0x00);
|
||||
|
||||
BOOST_CHECK( is_control(frame::opcode::CONTINUATION) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::TEXT) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::BINARY) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::CLOSE) == true);
|
||||
BOOST_CHECK( is_control(frame::opcode::PING) == true);
|
||||
BOOST_CHECK( is_control(frame::opcode::PONG) == true);
|
||||
BOOST_CHECK( is_control(frame::opcode::CONTINUATION) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::TEXT) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::BINARY) == false);
|
||||
BOOST_CHECK( is_control(frame::opcode::CLOSE) == true);
|
||||
BOOST_CHECK( is_control(frame::opcode::PING) == true);
|
||||
BOOST_CHECK( is_control(frame::opcode::PONG) == true);
|
||||
|
||||
BOOST_CHECK( frame::get_opcode(h1) == frame::opcode::CONTINUATION );
|
||||
BOOST_CHECK( frame::get_opcode(h1) == frame::opcode::CONTINUATION );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extended_header_basics ) {
|
||||
frame::extended_header h1;
|
||||
uint8_t h1_solution[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
frame::extended_header h1;
|
||||
uint8_t h1_solution[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
frame::extended_header h2(uint16_t(255));
|
||||
uint8_t h2_solution[12] = {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
frame::extended_header h2(uint16_t(255));
|
||||
uint8_t h2_solution[12] = {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
frame::extended_header h3(uint16_t(256),htonl(0x8040201));
|
||||
uint8_t h3_solution[12] = {0x01, 0x00, 0x08, 0x04, 0x02, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
frame::extended_header h3(uint16_t(256),htonl(0x8040201));
|
||||
uint8_t h3_solution[12] = {0x01, 0x00, 0x08, 0x04, 0x02, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
frame::extended_header h4(uint64_t(0x0807060504030201LL));
|
||||
uint8_t h4_solution[12] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
|
||||
0x02, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
frame::extended_header h4(uint64_t(0x0807060504030201LL));
|
||||
uint8_t h4_solution[12] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
|
||||
0x02, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
frame::extended_header h5(uint64_t(0x0807060504030201LL),htonl(0x8040201));
|
||||
uint8_t h5_solution[12] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
|
||||
0x02, 0x01, 0x08, 0x04, 0x02, 0x01};
|
||||
frame::extended_header h5(uint64_t(0x0807060504030201LL),htonl(0x8040201));
|
||||
uint8_t h5_solution[12] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
|
||||
0x02, 0x01, 0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
BOOST_CHECK( std::equal(h1_solution,h1_solution+12,h1.bytes) );
|
||||
BOOST_CHECK( std::equal(h2_solution,h2_solution+12,h2.bytes) );
|
||||
BOOST_CHECK( std::equal(h3_solution,h3_solution+12,h3.bytes) );
|
||||
BOOST_CHECK( std::equal(h4_solution,h4_solution+12,h4.bytes) );
|
||||
BOOST_CHECK( std::equal(h5_solution,h5_solution+12,h5.bytes) );
|
||||
BOOST_CHECK( std::equal(h1_solution,h1_solution+12,h1.bytes) );
|
||||
BOOST_CHECK( std::equal(h2_solution,h2_solution+12,h2.bytes) );
|
||||
BOOST_CHECK( std::equal(h3_solution,h3_solution+12,h3.bytes) );
|
||||
BOOST_CHECK( std::equal(h4_solution,h4_solution+12,h4.bytes) );
|
||||
BOOST_CHECK( std::equal(h5_solution,h5_solution+12,h5.bytes) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( extended_header_extractors ) {
|
||||
frame::basic_header h1(0x00,0x7E);
|
||||
frame::extended_header e1(uint16_t(255));
|
||||
BOOST_CHECK( get_extended_size(e1) == 255 );
|
||||
BOOST_CHECK( get_payload_size(h1,e1) == 255 );
|
||||
BOOST_CHECK( get_masking_key_offset(h1) == 2 );
|
||||
BOOST_CHECK( get_masking_key(h1,e1).i == 0 );
|
||||
frame::basic_header h1(0x00,0x7E);
|
||||
frame::extended_header e1(uint16_t(255));
|
||||
BOOST_CHECK( get_extended_size(e1) == 255 );
|
||||
BOOST_CHECK( get_payload_size(h1,e1) == 255 );
|
||||
BOOST_CHECK( get_masking_key_offset(h1) == 2 );
|
||||
BOOST_CHECK( get_masking_key(h1,e1).i == 0 );
|
||||
|
||||
frame::basic_header h2(0x00,0x7F);
|
||||
frame::extended_header e2(uint64_t(0x0807060504030201LL));
|
||||
BOOST_CHECK( get_jumbo_size(e2) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_payload_size(h2,e2) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_masking_key_offset(h2) == 8 );
|
||||
BOOST_CHECK( get_masking_key(h2,e2).i == 0 );
|
||||
frame::basic_header h2(0x00,0x7F);
|
||||
frame::extended_header e2(uint64_t(0x0807060504030201LL));
|
||||
BOOST_CHECK( get_jumbo_size(e2) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_payload_size(h2,e2) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_masking_key_offset(h2) == 8 );
|
||||
BOOST_CHECK( get_masking_key(h2,e2).i == 0 );
|
||||
|
||||
frame::basic_header h3(0x00,0xFE);
|
||||
frame::extended_header e3(uint16_t(255),0x08040201);
|
||||
BOOST_CHECK( get_extended_size(e3) == 255 );
|
||||
BOOST_CHECK( get_payload_size(h3,e3) == 255 );
|
||||
BOOST_CHECK( get_masking_key_offset(h3) == 2 );
|
||||
BOOST_CHECK( get_masking_key(h3,e3).i == 0x08040201 );
|
||||
frame::basic_header h3(0x00,0xFE);
|
||||
frame::extended_header e3(uint16_t(255),0x08040201);
|
||||
BOOST_CHECK( get_extended_size(e3) == 255 );
|
||||
BOOST_CHECK( get_payload_size(h3,e3) == 255 );
|
||||
BOOST_CHECK( get_masking_key_offset(h3) == 2 );
|
||||
BOOST_CHECK( get_masking_key(h3,e3).i == 0x08040201 );
|
||||
|
||||
frame::basic_header h4(0x00,0xFF);
|
||||
frame::extended_header e4(uint64_t(0x0807060504030201LL),0x08040201);
|
||||
BOOST_CHECK( get_jumbo_size(e4) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_payload_size(h4,e4) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_masking_key_offset(h4) == 8 );
|
||||
BOOST_CHECK( get_masking_key(h4,e4).i == 0x08040201 );
|
||||
frame::basic_header h4(0x00,0xFF);
|
||||
frame::extended_header e4(uint64_t(0x0807060504030201LL),0x08040201);
|
||||
BOOST_CHECK( get_jumbo_size(e4) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_payload_size(h4,e4) == 0x0807060504030201LL );
|
||||
BOOST_CHECK( get_masking_key_offset(h4) == 8 );
|
||||
BOOST_CHECK( get_masking_key(h4,e4).i == 0x08040201 );
|
||||
|
||||
frame::basic_header h5(0x00,0x7D);
|
||||
frame::extended_header e5;
|
||||
BOOST_CHECK( get_payload_size(h5,e5) == 125 );
|
||||
frame::basic_header h5(0x00,0x7D);
|
||||
frame::extended_header e5;
|
||||
BOOST_CHECK( get_payload_size(h5,e5) == 125 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( header_preparation ) {
|
||||
frame::basic_header h1(0x81,0xFF); //
|
||||
frame::extended_header e1(uint64_t(0xFFFFFLL),htonl(0xD5FB70EE));
|
||||
std::string p1 = prepare_header(h1, e1);
|
||||
uint8_t s1[14] = {0x81, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
|
||||
0xD5, 0xFB, 0x70, 0xEE};
|
||||
frame::basic_header h1(0x81,0xFF); //
|
||||
frame::extended_header e1(uint64_t(0xFFFFFLL),htonl(0xD5FB70EE));
|
||||
std::string p1 = prepare_header(h1, e1);
|
||||
uint8_t s1[14] = {0x81, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
|
||||
0xD5, 0xFB, 0x70, 0xEE};
|
||||
|
||||
BOOST_CHECK( p1.size() == 14);
|
||||
BOOST_CHECK( std::equal(p1.begin(),p1.end(),reinterpret_cast<char*>(s1)) );
|
||||
BOOST_CHECK( p1.size() == 14);
|
||||
BOOST_CHECK( std::equal(p1.begin(),p1.end(),reinterpret_cast<char*>(s1)) );
|
||||
|
||||
frame::basic_header h2(0x81,0x7E); //
|
||||
frame::extended_header e2(uint16_t(255));
|
||||
std::string p2 = prepare_header(h2, e2);
|
||||
uint8_t s2[4] = {0x81, 0x7E, 0x00, 0xFF};
|
||||
frame::basic_header h2(0x81,0x7E); //
|
||||
frame::extended_header e2(uint16_t(255));
|
||||
std::string p2 = prepare_header(h2, e2);
|
||||
uint8_t s2[4] = {0x81, 0x7E, 0x00, 0xFF};
|
||||
|
||||
BOOST_CHECK( p2.size() == 4);
|
||||
BOOST_CHECK( std::equal(p2.begin(),p2.end(),reinterpret_cast<char*>(s2)) );
|
||||
BOOST_CHECK( p2.size() == 4);
|
||||
BOOST_CHECK( std::equal(p2.begin(),p2.end(),reinterpret_cast<char*>(s2)) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( prepare_masking_key ) {
|
||||
frame::masking_key_type key;
|
||||
frame::masking_key_type key;
|
||||
|
||||
key.i = htonl(0x12345678);
|
||||
key.i = htonl(0x12345678);
|
||||
|
||||
if (sizeof(size_t) == 8) {
|
||||
BOOST_CHECK(
|
||||
frame::prepare_masking_key(key) == lib::net::htonll(0x1234567812345678LL)
|
||||
);
|
||||
} else {
|
||||
BOOST_CHECK( frame::prepare_masking_key(key) == htonl(0x12345678) );
|
||||
}
|
||||
if (sizeof(size_t) == 8) {
|
||||
BOOST_CHECK(
|
||||
frame::prepare_masking_key(key) == lib::net::_htonll(0x1234567812345678LL)
|
||||
);
|
||||
} else {
|
||||
BOOST_CHECK( frame::prepare_masking_key(key) == htonl(0x12345678) );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( prepare_masking_key2 ) {
|
||||
frame::masking_key_type key;
|
||||
frame::masking_key_type key;
|
||||
|
||||
key.i = htonl(0xD5FB70EE);
|
||||
key.i = htonl(0xD5FB70EE);
|
||||
|
||||
// One call
|
||||
if (sizeof(size_t) == 8) {
|
||||
BOOST_CHECK(
|
||||
frame::prepare_masking_key(key) == lib::net::htonll(0xD5FB70EED5FB70EELL)
|
||||
);
|
||||
} else {
|
||||
BOOST_CHECK( frame::prepare_masking_key(key) == htonl(0xD5FB70EE) );
|
||||
}
|
||||
// One call
|
||||
if (sizeof(size_t) == 8) {
|
||||
BOOST_CHECK(
|
||||
frame::prepare_masking_key(key) == lib::net::_htonll(0xD5FB70EED5FB70EELL)
|
||||
);
|
||||
} else {
|
||||
BOOST_CHECK( frame::prepare_masking_key(key) == htonl(0xD5FB70EE) );
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out a way to run/test both 4 and 8 byte versions.
|
||||
@@ -282,241 +282,241 @@ BOOST_AUTO_TEST_CASE( circshift ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( block_byte_mask ) {
|
||||
uint8_t input[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
uint8_t input[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t output[15];
|
||||
uint8_t output[15];
|
||||
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
byte_mask(input,input+15,output,key);
|
||||
byte_mask(input,input+15,output,key);
|
||||
|
||||
BOOST_CHECK( std::equal(output,output+15,masked) );
|
||||
BOOST_CHECK( std::equal(output,output+15,masked) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( block_byte_mask_inplace ) {
|
||||
uint8_t buffer[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
uint8_t buffer[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
byte_mask(buffer,buffer+15,key);
|
||||
byte_mask(buffer,buffer+15,key);
|
||||
|
||||
BOOST_CHECK( std::equal(buffer,buffer+15,masked) );
|
||||
BOOST_CHECK( std::equal(buffer,buffer+15,masked) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( block_word_mask ) {
|
||||
uint8_t input[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
uint8_t input[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t output[15];
|
||||
uint8_t output[15];
|
||||
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
word_mask_exact(input,output,15,key);
|
||||
word_mask_exact(input,output,15,key);
|
||||
|
||||
BOOST_CHECK( std::equal(output,output+15,masked) );
|
||||
BOOST_CHECK( std::equal(output,output+15,masked) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( block_word_mask_inplace ) {
|
||||
uint8_t buffer[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
uint8_t buffer[15] = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[15] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
word_mask_exact(buffer,15,key);
|
||||
word_mask_exact(buffer,15,key);
|
||||
|
||||
BOOST_CHECK( std::equal(buffer,buffer+15,masked) );
|
||||
BOOST_CHECK( std::equal(buffer,buffer+15,masked) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( continuous_word_mask ) {
|
||||
uint8_t input[16];
|
||||
uint8_t output[16];
|
||||
uint8_t input[16];
|
||||
uint8_t output[16];
|
||||
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x00};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
frame::word_mask_circ(input,output,15,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
frame::word_mask_circ(input,output,15,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
|
||||
pkey_temp = frame::word_mask_circ(input,output,7,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+7,masked) );
|
||||
BOOST_CHECK( pkey_temp == frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::word_mask_circ(input,output,7,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+7,masked) );
|
||||
BOOST_CHECK( pkey_temp == frame::circshift_prepared_key(pkey,3) );
|
||||
|
||||
pkey_temp = frame::word_mask_circ(input+7,output+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::word_mask_circ(input+7,output+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( continuous_byte_mask ) {
|
||||
uint8_t input[16];
|
||||
uint8_t output[16];
|
||||
uint8_t input[16];
|
||||
uint8_t output[16];
|
||||
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x00};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
frame::byte_mask_circ(input,output,15,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
frame::byte_mask_circ(input,output,15,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(input,16,0x00);
|
||||
std::fill_n(output,16,0x00);
|
||||
|
||||
pkey_temp = frame::byte_mask_circ(input,output,7,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+7,masked) );
|
||||
BOOST_CHECK( pkey_temp == frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::byte_mask_circ(input,output,7,pkey);
|
||||
BOOST_CHECK( std::equal(output,output+7,masked) );
|
||||
BOOST_CHECK( pkey_temp == frame::circshift_prepared_key(pkey,3) );
|
||||
|
||||
pkey_temp = frame::byte_mask_circ(input+7,output+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::byte_mask_circ(input+7,output+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(output,output+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( continuous_word_mask_inplace ) {
|
||||
uint8_t buffer[16];
|
||||
uint8_t buffer[16];
|
||||
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x00};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
frame::word_mask_circ(buffer,15,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
frame::word_mask_circ(buffer,15,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
|
||||
pkey_temp = frame::word_mask_circ(buffer,7,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+7,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::word_mask_circ(buffer,7,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+7,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
|
||||
pkey_temp = frame::word_mask_circ(buffer+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::word_mask_circ(buffer+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( continuous_byte_mask_inplace ) {
|
||||
uint8_t buffer[16];
|
||||
uint8_t buffer[16];
|
||||
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
uint8_t masked[16] = {0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
0x00, 0x01, 0x02, 0x00};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0x00;
|
||||
key.c[1] = 0x01;
|
||||
key.c[2] = 0x02;
|
||||
key.c[3] = 0x03;
|
||||
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
frame::byte_mask_circ(buffer,15,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
// One call
|
||||
size_t pkey,pkey_temp;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
frame::byte_mask_circ(buffer,15,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
// calls not split on word boundaries
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
std::fill_n(buffer,16,0x00);
|
||||
|
||||
pkey_temp = frame::byte_mask_circ(buffer,7,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+7,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::byte_mask_circ(buffer,7,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+7,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
|
||||
pkey_temp = frame::byte_mask_circ(buffer+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
pkey_temp = frame::byte_mask_circ(buffer+7,8,pkey_temp);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+16,masked) );
|
||||
BOOST_CHECK_EQUAL( pkey_temp, frame::circshift_prepared_key(pkey,3) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( continuous_word_mask2 ) {
|
||||
uint8_t buffer[12] = {0xA6, 0x15, 0x97, 0xB9,
|
||||
uint8_t buffer[12] = {0xA6, 0x15, 0x97, 0xB9,
|
||||
0x81, 0x50, 0xAC, 0xBA,
|
||||
0x9C, 0x1C, 0x9F, 0xF4};
|
||||
|
||||
@@ -524,15 +524,15 @@ BOOST_AUTO_TEST_CASE( continuous_word_mask2 ) {
|
||||
0x6F, 0x20, 0x57, 0x6F,
|
||||
0x72, 0x6C, 0x64, 0x21};
|
||||
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0xEE;
|
||||
key.c[1] = 0x70;
|
||||
key.c[2] = 0xFB;
|
||||
key.c[3] = 0xD5;
|
||||
frame::masking_key_type key;
|
||||
key.c[0] = 0xEE;
|
||||
key.c[1] = 0x70;
|
||||
key.c[2] = 0xFB;
|
||||
key.c[3] = 0xD5;
|
||||
|
||||
// One call
|
||||
size_t pkey;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
frame::word_mask_circ(buffer,12,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+12,unmasked) );
|
||||
// One call
|
||||
size_t pkey;
|
||||
pkey = frame::prepare_masking_key(key);
|
||||
frame::word_mask_circ(buffer,12,pkey);
|
||||
BOOST_CHECK( std::equal(buffer,buffer+12,unmasked) );
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -229,6 +229,13 @@ BOOST_AUTO_TEST_CASE( uri_valid_v6_mixed_case ) {
|
||||
BOOST_CHECK_EQUAL( uri.get_resource(), "/" );
|
||||
}
|
||||
|
||||
// Valid URI with a v6 address with mixed case
|
||||
BOOST_AUTO_TEST_CASE( uri_invalid_no_scheme ) {
|
||||
websocketpp::uri uri("myserver.com");
|
||||
|
||||
BOOST_CHECK( !uri.get_valid() );
|
||||
}
|
||||
|
||||
// Invalid IPv6 literal
|
||||
/*BOOST_AUTO_TEST_CASE( uri_invalid_v6_nonhex ) {
|
||||
websocketpp::uri uri("wss://[g::1]:9000/");
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Broadcast Tutorial
|
||||
==================
|
||||
|
||||
This tutorial will dig into some more nitty gritty details on how to build high
|
||||
scalability, high performance websocket servers for broadcast like workflows.
|
||||
|
||||
Will go into features like:
|
||||
- minimizing work done in handlers
|
||||
- using asio thread pool mode
|
||||
- teaming multiple endpoints
|
||||
- setting accept queue depth
|
||||
- tuning compile time buffer sizes
|
||||
- prepared messages
|
||||
- flow control
|
||||
- basic operating system level tuning, particularly increasing file descriptor limits.
|
||||
- measuring performance with wsperf / autobahn
|
||||
- tuning permessage-deflate compression settings
|
||||
@@ -1,45 +0,0 @@
|
||||
WebSocket++ (0.3.0-alpha3)
|
||||
==========================
|
||||
|
||||
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.
|
||||
|
||||
Major Features
|
||||
==============
|
||||
* Full support for RFC6455
|
||||
* Partial support for Hixie 76 / Hybi 00, 07-17 draft specs (server only)
|
||||
* 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)
|
||||
* Portable/cross platform (Posix/Windows, 32/64bit, Intel/ARM/PPC)
|
||||
* Thread-safe
|
||||
|
||||
Get Involved
|
||||
============
|
||||
|
||||
[](https://travis-ci.org/zaphoyd/websocketpp)
|
||||
|
||||
**Project Website**
|
||||
http://www.zaphoyd.com/websocketpp/
|
||||
|
||||
**User Manual**
|
||||
http://www.zaphoyd.com/websocketpp/manual/
|
||||
|
||||
**GitHub Repository**
|
||||
https://github.com/zaphoyd/websocketpp/
|
||||
|
||||
**Announcements Mailing List**
|
||||
http://groups.google.com/group/websocketpp-announcements/
|
||||
|
||||
**IRC Channel**
|
||||
#websocketpp (freenode)
|
||||
|
||||
**Discussion / Development / Support Mailing List / Forum**
|
||||
http://groups.google.com/group/websocketpp/
|
||||
|
||||
Author
|
||||
======
|
||||
Peter Thorson - websocketpp@zaphoyd.com
|
||||
@@ -2,7 +2,7 @@ Chat Tutorial
|
||||
=============
|
||||
|
||||
Goals of this tutorial:
|
||||
- Impliment a realtime websocket chat server
|
||||
- Implement a realtime websocket chat server
|
||||
|
||||
|
||||
Server
|
||||
@@ -11,65 +11,3 @@ Server
|
||||
- Subprotocol
|
||||
- Origin restrictions
|
||||
- HTTP statistics page
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Hi all,
|
||||
|
||||
I am working on some tutorials for WebSocket++ and was wondering if anyone here has specific features or concepts that they feel would be particularly useful to have covered? Anything that you wish there was a tutorial for now or wished there had been when you were first setting up your WebSocket++ application?
|
||||
|
||||
Best,
|
||||
|
||||
Peter
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Major Features
|
||||
==============
|
||||
* Full support for RFC6455
|
||||
* Partial support for Hixie 76 / Hybi 00, 07-17 draft specs (server only)
|
||||
* 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)
|
||||
* Portable/cross platform (Posix/Windows, 32/64bit, Intel/ARM/PPC)
|
||||
* Thread-safe
|
||||
|
||||
Get Involved
|
||||
============
|
||||
|
||||
[](https://travis-ci.org/zaphoyd/websocketpp)
|
||||
|
||||
**Project Website**
|
||||
http://www.zaphoyd.com/websocketpp/
|
||||
|
||||
**User Manual**
|
||||
http://www.zaphoyd.com/websocketpp/manual/
|
||||
|
||||
**GitHub Repository**
|
||||
https://github.com/zaphoyd/websocketpp/
|
||||
|
||||
**Announcements Mailing List**
|
||||
http://groups.google.com/group/websocketpp-announcements/
|
||||
|
||||
**IRC Channel**
|
||||
#websocketpp (freenode)
|
||||
|
||||
**Discussion / Development / Support Mailing List / Forum**
|
||||
http://groups.google.com/group/websocketpp/
|
||||
|
||||
Author
|
||||
======
|
||||
Peter Thorson - websocketpp@zaphoyd.com
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 <iostream>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 <iostream>
|
||||
#include <string>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 <iostream>
|
||||
#include <string>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
class websocket_endpoint {
|
||||
public:
|
||||
websocket_endpoint () {
|
||||
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);
|
||||
}
|
||||
private:
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
};
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
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 = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_endpoint);
|
||||
}
|
||||
|
||||
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 = 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
|
||||
));
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
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"
|
||||
<< "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) == "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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a
|
||||
|
||||
clang++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_thread.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_random.a
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/Documents/websocketpp/ -I/Users/zaphoyd/Documents/boost_1_53_0_libcpp/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/Documents/boost_1_53_0_libcpp/stage/lib/libboost_system.a
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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 = 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) {
|
||||
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
||||
));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a
|
||||
|
||||
clang++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_thread.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_random.a
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/Documents/websocketpp/ -I/Users/zaphoyd/Documents/boost_1_53_0_libcpp/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/Documents/boost_1_53_0_libcpp/stage/lib/libboost_system.a
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
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) {
|
||||
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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"
|
||||
<< "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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a
|
||||
|
||||
clang++ -I/Users/zaphoyd/software/websocketpp/ -I/Users/zaphoyd/software/boost_1_55_0/ step4.cpp /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_system.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_thread.a /Users/zaphoyd/software/boost_1_55_0/stage/lib/libboost_random.a
|
||||
|
||||
clang++ -std=c++11 -stdlib=libc++ -I/Users/zaphoyd/Documents/websocketpp/ -I/Users/zaphoyd/Documents/boost_1_53_0_libcpp/ -D_WEBSOCKETPP_CPP11_STL_ step4.cpp /Users/zaphoyd/Documents/boost_1_53_0_libcpp/stage/lib/libboost_system.a
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,863 @@
|
||||
Utility Client Example Application
|
||||
==================================
|
||||
|
||||
Chapter 1: Initial Setup & Basics
|
||||
---------------------------------
|
||||
|
||||
Setting up the basic types, opening and closing connections, sending and receiving messages.
|
||||
|
||||
### Step 1
|
||||
|
||||
A basic program loop that prompts the user for a command and then processes it. In this tutorial we will modify this program to perform tasks and retrieve data from a remote server over a WebSocket connection.
|
||||
|
||||
#### Build
|
||||
`clang++ step1.cpp`
|
||||
|
||||
#### Code so far
|
||||
|
||||
*note* A code snapshot for each step is present next to this tutorial file in the git repository.
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2
|
||||
|
||||
_Add WebSocket++ includes and set up an endpoint type._
|
||||
|
||||
WebSocket++ includes two major object types. The endpoint and the connection. The
|
||||
endpoint creates and launches new connections and maintains default settings for
|
||||
those connections. Endpoints also manage any shared network resources.
|
||||
|
||||
The connection stores information specific to each WebSocket session.
|
||||
|
||||
> **Note:** Once a connection is launched, there is no link between the endpoint and the connection. All default settings are copied into the new connection by the endpoint. Changing default settings on an endpoint will only affect future connections.
|
||||
Connections do not maintain a link back to their associated endpoint. Endpoints do not maintain a list of outstanding connections. If your application needs to iterate over all connections it will need to maintain a list of them itself.
|
||||
|
||||
WebSocket++ endpoints are built by combining an endpoint role with an endpoint config. There are two different types of endpoint roles, one each for the client and server roles in a WebSocket session. This is a client tutorial so we will use the client role `websocketpp::client` which is provided by the `<websocketpp/client.hpp>` header.
|
||||
|
||||
> ###### Terminology: Endpoint Config
|
||||
> WebSocket++ endpoints have a group of settings that may be configured at compile time via the `config` template parameter. A config is a struct that contains types and static constants that are used to produce an endpoint with specific properties. Depending on which config is being used the endpoint will have different methods available and may have additional third party dependencies.
|
||||
|
||||
The endpoint role takes a template parameter called `config` that is used to configure the behavior of endpoint at compile time. For this example we are going to use a default config provided by the library called `asio_client`, provided by `<websocketpp/config/asio_no_tls_client.hpp>`. This is a client config that uses boost::asio to provide network transport and does not support TLS based security. Later on we will discuss how to introduce TLS based security into a WebSocket++ application, more about the other stock configs, and how to build your own custom configs.
|
||||
|
||||
Combine a config with an endpoint role to produce a fully configured endpoint. This type will be used frequently so I would recommend a typedef here.
|
||||
|
||||
`typedef websocketpp::client<websocketpp::config::asio_client> client`
|
||||
|
||||
#### Build
|
||||
Adding WebSocket++ has added a few dependencies to our program that must be addressed in the build system. Firstly, the WebSocket++ and Boost library headers must be in the include search path of your build system. How exactly this is done depends on where you have the WebSocket++ headers installed and what build system you are using.
|
||||
|
||||
In addition to the new headers, boost::asio depends on the `boost_system` shared library. This will need to be added (either as a static or dynamic) to the linker. Refer to your build environment documentation for instructions on linking to shared libraries.
|
||||
|
||||
`clang++ step2.cpp -lboost_system`
|
||||
|
||||
#### Code so far
|
||||
```cpp
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Step 3
|
||||
|
||||
_Create endpoint wrapper object that handles initialization and setting up the background thread._
|
||||
|
||||
In order to process user input while network processing occurs in the background we are going to use a separate thread for the WebSocket++ processing loop. This leaves the main thread free to process foreground user input. In order to enable simple RAII style resource management for our thread and endpoint we will use a wrapper object that configures them both in its constructor.
|
||||
|
||||
> ###### Terminology: websocketpp::lib namespace
|
||||
> WebSocket++ is designed to be used with a C++11 standard library. As this is not universally available in popular build systems the Boost libraries may be used as polyfills for the C++11 standard library in C++98 build environments. The `websocketpp::lib` namespace is used by the library and its associated examples to abstract away the distinctions between the two. `websocketpp::lib::shared_ptr` will evaluate to `std::shared_ptr` in a C++11 environment and `boost::shared_ptr` otherwise.
|
||||
>
|
||||
> This tutorial uses the `websocketpp::lib` wrappers because it doesn't know what the build environment of the reader is. For your applications, unless you are interested in similar portability, are free to use the boost or std versions of these types directly.
|
||||
>
|
||||
>[TODO: link to more information about websocketpp::lib namespace and C++11 setup]
|
||||
|
||||
Within the `websocket_endpoint` constructor several things happen:
|
||||
|
||||
First, we set the endpoint logging behavior to silent by clearing all of the access and error logging channels. [TODO: link to more information about logging]
|
||||
```cpp
|
||||
m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.clear_error_channels(websocketpp::log::elevel::all);
|
||||
```
|
||||
|
||||
Next, we initialize the transport system underlying the endpoint and set it to perpetual mode. In perpetual mode the endpoint's processing loop will not exit automatically when it has no connections. This is important because we want this endpoint to remain active while our application is running and process requests for new WebSocket connections on demand as we need them. Both of these methods are specific to the asio transport. They will not be necessary or present in endpoints that use a non-asio config.
|
||||
```cpp
|
||||
m_endpoint.init_asio();
|
||||
m_endpoint.start_perpetual();
|
||||
```
|
||||
|
||||
Finally, we launch a thread to run the `run` method of our client endpoint. While the endpoint is running it will process connection tasks (read and deliver incoming messages, frame and send outgoing messages, etc). Because it is running in perpetual mode, when there are no connections active it will wait for a new connection.
|
||||
```cpp
|
||||
m_thread.reset(new websocketpp::lib::thread(&client::run, &m_endpoint));
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
Now that our client endpoint template is actually instantiated a few more linker dependencies will show up. In particular, WebSocket clients require a cryptographically secure random number generator. WebSocket++ is able to use either `boost_random` or the C++11 standard library <random> for this purpose. Because this example also uses threads, if we do not have C++11 std::thread available we will need to include `boost_thread`.
|
||||
|
||||
##### Clang (C++98 & boost)
|
||||
`clang++ step3.cpp -lboost_system -lboost_random -lboost_thread`
|
||||
|
||||
##### Clang (C++11)
|
||||
`clang++ -std=c++0x -stdlib=libc++ step3.cpp -lboost_system -D_WEBSOCKETPP_CPP11_STL_`
|
||||
|
||||
##### G++ (C++98 & Boost)
|
||||
`g++ step3.cpp -lboost_system -lboost_random -lboost_thread`
|
||||
|
||||
##### G++ v4.6+ (C++11)
|
||||
`g++ -std=c++0x step3.cpp -lboost_system -D_WEBSOCKETPP_CPP11_STL_`
|
||||
|
||||
#### Code so far
|
||||
|
||||
```cpp
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
#include <websocketpp/common/memory.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
class websocket_endpoint {
|
||||
public:
|
||||
websocket_endpoint () {
|
||||
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));
|
||||
}
|
||||
private:
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
};
|
||||
|
||||
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"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4
|
||||
|
||||
_Opening WebSocket connections_
|
||||
|
||||
This step adds two new commands to utility_client. The ability to open a new connection and the ability to view information about a previously opened connection. Every connection that gets opened will be assigned an integer connection id that the user of the program can use to interact with that connection.
|
||||
|
||||
#### New Connection Metadata Object
|
||||
|
||||
In order to track information about each connection a `connection_metadata` object is defined. This object stores the numeric connection id and a number of fields that will be filled in as the connection is processed. Initially this includes the state of the connection (opening, open, failed, closed, etc), the original URI connected to, an identifying value from the server, and a description of the reason for connection failure/closure. Future steps will add more information to this metadata object.
|
||||
|
||||
#### Update `websocket_endpoint`
|
||||
|
||||
The `websocket_endpoint` object has gained some new data members and methods. It now tracks a mapping between connection IDs and their associated metadata as well as the next sequential ID number to hand out. The `connect()` method initiates a new connection. The `get_metadata` method retrieves metadata given an ID.
|
||||
|
||||
#### The connect method
|
||||
A new WebSocket connection is initiated via a three step process. First, a connection request is created by `endpoint::get_connection(uri)`. Next, the connection request is configured. Lastly, the connection request is submitted back to the endpoint via `endpoint::connect()` which adds it to the queue of new connections to make.
|
||||
|
||||
> ###### Terminology `connection_ptr`
|
||||
> WebSocket++ keeps track of connection related resources using a reference counted shared pointer. The type of this pointer is `endpoint::connection_ptr`. A `connection_ptr` allows direct access to information about the connection and allows changing connection settings. Because of this direct access and their internal resource management role within the library it is not safe for end applications to use `connection_ptr` except in the specific circumstances detailed below.
|
||||
>
|
||||
> **When is it safe to use `connection_ptr`?**
|
||||
> - After `endpoint::get_connection(...)` and before `endpoint::connect()`: `get_connection` returns a `connection_ptr`. It is safe to use this pointer to configure your new connection. Once you submit the connection to `connect` you may no longer use the `connection_ptr` and should discard it immediately for optimal memory management.
|
||||
> - During a handler: WebSocket++ allows you to register hooks / callbacks / event handlers for specific events that happen during a connection's lifetime. During the invocation of one of these handlers the library guarantees that it is safe to use a `connection_ptr` for the connection associated with the currently running handler.
|
||||
|
||||
> ###### Terminology `connection_hdl`
|
||||
> Because of the limited thread safety of the `connection_ptr` the library also provides a more flexible connection identifier, the `connection_hdl`. The `connection_hdl` has type `websocketpp::connection_hdl` and it is defined in `<websocketpp/common/connection_hdl.hpp>`. Note that unlike `connection_ptr` this is not dependent on the type or config of the endpoint. Code that simply stores or transmits `connection_hdl` but does not use them can include only the header above and can treat its hdls like values.
|
||||
>
|
||||
> Connection handles are not used directly. They are used by endpoint methods to identify the target of the desired action. For example, the endpoint method that sends a new message will take as a parameter the hdl of the connection to send the message to.
|
||||
>
|
||||
> **When is it safe to use `connection_hdl`?**
|
||||
> `connection_hdl`s may be used at any time from any thread. They may be copied and stored in containers. Deleting a hdl will not affect the connection in any way. Handles may be upgraded to a `connection_ptr` during a handler call by using `endpoint::get_con_from_hdl()`. The resulting `connection_ptr` is safe to use for the duration of that handler invocation.
|
||||
>
|
||||
> **`connection_hdl` FAQs**
|
||||
> - `connection_hdl`s are guaranteed to be unique within a program. Multiple endpoints in a single program will always create connections with unique handles.
|
||||
> - Using a `connection_hdl` with a different endpoint than the one that created its associated connection will result in undefined behavior.
|
||||
> - Using a `connection_hdl` whose associated connection has been closed or deleted is safe. The endpoint will return a specific error saying the operation couldn't be completed because the associated connection doesn't exist.
|
||||
> [TODO: more here? link to a connection_hdl FAQ elsewhere?]
|
||||
|
||||
`websocket_endpoint::connect()` begins by calling `endpoint::get_connection()` using a uri passed as a parameter. Additionally, an error output value is passed to capture any errors that might occur during. If an error does occur an error notice is printed along with a descriptive message and the -1 / 'invalid' value is returned as the new ID.
|
||||
|
||||
> ###### Terminology: `error handling: exceptions vs error_code`
|
||||
> WebSocket++ uses the error code system defined by the C++11 `<system_error>` library. It can optionally fall back to a similar system provided by the Boost libraries. All user facing endpoint methods that can fail take an `error_code` in an output parameter and store the error that occured there before returning. An empty/default constructed value is returned in the case of success.
|
||||
>
|
||||
> **Exception throwing varients**
|
||||
> All user facing endpoint methods that take and use an `error_code` parameter have a version that throws an exception instead. These methods are identical in function and signature except for the lack of the final ec parameter. The type of the exception thrown is `websocketpp::exception`. This type derives from `std::exception` so it can be caught by catch blocks grabbing generic `std::exception`s. The `websocketpp::exception::code()` method may be used to extract the machine readable `error_code` value from an exception.
|
||||
>
|
||||
> For clarity about error handling the utility_client example uses exclusively the exception free varients of these methods. Your application may choose to use either.
|
||||
|
||||
If connection creation succeeds, the next sequential connection ID is generated and a `connection_metadata` object is inserted into the connection list under that ID. Initially the metadata object stores the connection ID, the `connection_hdl`, and the URI the connection was opened to.
|
||||
|
||||
```cpp
|
||||
int new_id = m_next_id++;
|
||||
metadata_ptr metadata(new connection_metadata(new_id, con->get_handle(), uri));
|
||||
m_connection_list[new_id] = metadata;
|
||||
```
|
||||
|
||||
Next, the connection request is configured. For this step the only configuration we will do is setting up a few default handlers. Later on we will return and demonstrate some more detailed configuration that can happen here (setting user agents, origin, proxies, custom headers, subprotocols, etc).
|
||||
|
||||
> ###### Terminology: Registering handlers
|
||||
> WebSocket++ provides a number of execution points where you can register to have a handler run. Which of these points are available to your endpoint will depend on its config. TLS handlers will not exist on non-TLS endpoints for example. A complete list of handlers can be found at http://www.zaphoyd.com/websocketpp/manual/reference/handler-list.
|
||||
>
|
||||
> Handlers can be registered at the endpoint level and at the connection level. Endpoint handlers are copied into new connections as they are created. Changing an endpoint handler will affect only future connections. Handlers registered at the connection level will be bound to that specific connection only.
|
||||
>
|
||||
> The signature of handler binding methods is the same for endpoints and connections. The format is: `set_*_handler(...)`. Where * is the name of the handler. For example, `set_open_handler(...)` will set the handler to be called when a new connection is open. `set_fail_handler(...)` will set the handler to be called when a connection fails to connect.
|
||||
>
|
||||
> All handlers take one argument, a callable type that can be converted to a `std::function` with the correct count and type of arguments. You can pass free functions, functors, and Lambdas with matching argument lists as handlers. In addition, you can use `std::bind` (or `boost::bind`) to register functions with non-matching argument lists. This is useful for passing additional parameters not present in the handler signature or member functions that need to carry a 'this' pointer.
|
||||
>
|
||||
> The function signature of each handler can be looked up in the list above in the manual. In general, all handlers include the `connection_hdl` identifying which connection this even is associated with as the first parameter. Some handlers (such as the message handler) include additional parameters. Most handlers have a void return value but some (`validate`, `ping`, `tls_init`) do not. The specific meanings of the return values are documented in the handler list linked above.
|
||||
|
||||
`utility_client` registers an open and a fail handler. We will use these to track whether each connection was successfully opened or failed. If it successfully opens, we will gather some information from the opening handshake and store it with our connection metadata.
|
||||
|
||||
In this example we are going to set connection specific handlers that are bound directly to the metadata object associated with our connection. This allows us to avoid performing a lookup in each handler to find the metadata object we plan to update which is a bit more efficient.
|
||||
|
||||
Lets look at the parameters being sent to bind in detail:
|
||||
|
||||
```cpp
|
||||
con->set_open_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_open,
|
||||
metadata,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
```
|
||||
|
||||
`&connection_metadata::on_open` is the address of the `on_open` member function of the `connection_metadata` class. `metadata_ptr` is a pointer to the `connection_metadata` object associated with this class. It will be used as the object on which the `on_open` member function will be called. `&m_endpoint` is the address of the endpoint in use. This parameter will be passed as-is to the `on_open` method. Lastly, `websocketpp::lib::placeholders::_1` is a placeholder indicating that the bound function should take one additional argument to be filled in at a later time. WebSocket++ will fill in this placeholder with the `connection_hdl` when it invokes the handler.
|
||||
|
||||
Finally, we call `endpoint::connect()` on our configured connection request and return the new connection ID.
|
||||
|
||||
#### Handler Member Functions
|
||||
|
||||
The open handler we registered, `connection_metadata::on_open`, sets the status metadata field to "Open" and retrieves the value of the "Server" header from the remote endpoint's HTTP response and stores it in the metadata object. Servers often set an identifying string in this header.
|
||||
|
||||
The fail handler we registered, `connection_metadata::on_fail`, sets the status metadata field to "Failed", the server field similarly to `on_open`, and retrieves the error code describing why the connection failed. The human readable message associated with that error code is saved to the metadata object.
|
||||
|
||||
#### New Commands
|
||||
|
||||
Two new commands have been set up. "connect [uri]" will pass the URI to the `websocket_endpoint` connect method and report an error or the connection ID of the new connection. "show [connection id]" will retrieve and print out the metadata associated with that connection. The help text has been updated accordingly.
|
||||
|
||||
```cpp
|
||||
} 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) == "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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
There are no changes to the build instructions from step 3
|
||||
|
||||
#### Run
|
||||
|
||||
```
|
||||
Enter Command: connect not a websocket uri
|
||||
> Connect initialization error: invalid uri
|
||||
Enter Command: show 0
|
||||
> Unknown connection id 0
|
||||
Enter Command: connect ws://echo.websocket.org
|
||||
> Created connection with id 0
|
||||
Enter Command: show 0
|
||||
> URI: ws://echo.websocket.org
|
||||
> Status: Open
|
||||
> Remote Server: Kaazing Gateway
|
||||
> Error/close reason: N/A
|
||||
Enter Command: connect ws://wikipedia.org
|
||||
> Created connection with id 1
|
||||
Enter Command: show 1
|
||||
> URI: ws://wikipedia.org
|
||||
> Status: Failed
|
||||
> Remote Server: Apache
|
||||
> Error/close reason: Invalid HTTP status.
|
||||
```
|
||||
|
||||
#### Code so far
|
||||
|
||||
```cpp
|
||||
#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();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
));
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
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"
|
||||
<< "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) == "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;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5
|
||||
|
||||
_Closing connections_
|
||||
|
||||
This step adds a command that allows you to close a WebSocket connection and adjusts the quit command so that it cleanly closes all outstanding connections before quitting.
|
||||
|
||||
#### Getting connection close information out of WebSocket++
|
||||
|
||||
> ###### Terminology: WebSocket close codes & reasons
|
||||
> The WebSocket close handshake involves an exchange of optional machine readable close codes and human readable reason strings. Each endpoint sends independent close details. The codes are short integers. The reasons are UTF8 text strings of at most 125 characters. More details about valid close code ranges and the meaning of each code can be found at https://tools.ietf.org/html/rfc6455#section-7.4
|
||||
|
||||
The `websocketpp::close::status` namespace contains named constants for all of the IANA defined close codes. It also includes free functions to determine whether a value is reserved or invalid and to convert a code to a human readable text representation.
|
||||
|
||||
During the close handler call WebSocket++ connections offer the following methods for accessing close handshake information:
|
||||
|
||||
- `connection::get_remote_close_code()`: Get the close code as reported by the remote endpoint
|
||||
- `connection::get_remote_close_reason()`: Get the close reason as reported by the remote endpoint
|
||||
- `connection::get_local_close_code()`: Get the close code that this endpoint sent.
|
||||
- `connection::get_local_close_reason()`: Get the close reason that this endpoint sent.
|
||||
- `connection::get_ec()`: Get a more detailed/specific WebSocket++ `error_code` indicating what library error (if any) ultimately resulted in the connection closure.
|
||||
|
||||
*Note:* there are some special close codes that will report a code that was not actually sent on the wire. For example 1005/"no close code" indicates that the endpoint omitted a close code entirely and 1006/"abnormal close" indicates that there was a problem that resulted in the connection closing without having performed a close handshake.
|
||||
|
||||
#### Add close handler
|
||||
|
||||
The `connection_metadata::on_close` method is added. This method retrieves the close code and reason from the closing handshake and stores it in the local error reason field.
|
||||
|
||||
```cpp
|
||||
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();
|
||||
}
|
||||
```
|
||||
|
||||
Similarly to `on_open` and `on_fail`, `websocket_endpoint::connect` registers this close handler when a new connection is made.
|
||||
|
||||
#### Add close method to `websocket_endpoint`
|
||||
|
||||
This method starts by looking up the given connection ID in the connection list. Next a close request is sent to the connection's handle with the specified WebSocket close code. This is done by calling `endpoint::close`. This is a thread safe method that is used to asynchronously dispatch a close signal to the connection with the given handle. When the operation is complete the connection's close handler will be triggered.
|
||||
|
||||
```cpp
|
||||
void close(int id, websocketpp::close::status::value code) {
|
||||
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, "", ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error initiating close: " << ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Add close option to the command loop and help message
|
||||
|
||||
A close option is added to the command loop. It takes a connection ID and optionally a close code and a close reason. If no code is specified the default of 1000/Normal is used. If no reason is specified, none is sent. The `endpoint::close` method will do some error checking and abort the close request if you try and send an invalid code or a reason with invalid UTF8 formatting. Reason strings longer than 125 characters will be truncated.
|
||||
|
||||
An entry is also added to the help system to describe how the new command may be used.
|
||||
|
||||
```cpp
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
#### Close all outstanding connections in `websocket_endpoint` destructor
|
||||
|
||||
Until now quitting the program left outstanding connections and the WebSocket++ network thread in a lurch. Now that we have a method of closing connections we can clean this up properly.
|
||||
|
||||
The destructor for `websocket_endpoint` now stops perpetual mode (so the run thread exits after the last connection is closed) and iterates through the list of open connections and requests a clean close for each. Finally, the run thread is joined which causes the program to wait until those connection closes complete.
|
||||
|
||||
```cpp
|
||||
~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();
|
||||
}
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
There are no changes to the build instructions from step 4
|
||||
|
||||
#### Run
|
||||
|
||||
```
|
||||
Enter Command: connect ws://localhost:9002
|
||||
> Created connection with id 0
|
||||
Enter Command: close 0 1001 example message
|
||||
Enter Command: show 0
|
||||
> URI: ws://localhost:9002
|
||||
> Status: Closed
|
||||
> Remote Server: WebSocket++/0.4.0
|
||||
> Error/close reason: close code: 1001 (Going away), close reason: example message
|
||||
Enter Command: connect ws://localhost:9002
|
||||
> Created connection with id 1
|
||||
Enter Command: close 1 1006
|
||||
> Error initiating close: Invalid close code used
|
||||
Enter Command: quit
|
||||
> Closing connection 1
|
||||
```
|
||||
|
||||
### Step 6
|
||||
|
||||
_Sending and receiving messages_
|
||||
|
||||
This step adds a command to send a message on a given connection and updates the show command to print a transcript of all sent and received messages for that connection.
|
||||
|
||||
> ###### Terminology: WebSocket message types (opcodes)
|
||||
> WebSocket messages have types indicated by their opcode. The protocol currently specifies two different opcodes for data messages, text and binary. Text messages represent UTF8 text and will be validated as such. Binary messages represent raw binary bytes and are passed through directly with no validation.
|
||||
>
|
||||
> WebSocket++ provides the values `websocketpp::frame::opcode::text` and `websocketpp::frame::opcode::binary` that can be used to direct how outgoing messages should be sent and to check how incoming messages are formatted.
|
||||
|
||||
#### Sending Messages
|
||||
|
||||
Messages are sent using `endpoint::send`. This is a thread safe method that may be called from anywhere to queue a message for sending on the specified connection. There are three send overloads for use with different scenarios.
|
||||
|
||||
Each method takes a `connection_hdl` to indicate which connection to send the message on as well as a `frame::opcode::value` to indicate which opcode to label the message as. All overloads are also available with an exception free varient that fills in a a status/error code instead of throwing.
|
||||
|
||||
The first overload, `connection_hdl hdl, std::string const & payload, frame::opcode::value op`, takes a `std::string`. The string contents are copied into an internal buffer and can be safely modified after calling send.
|
||||
|
||||
The second overload, `connection_hdl hdl, void const * payload, size_t len, frame::opcode::value op`, takes a void * buffer and length. The buffer contents are copied and can be safely modified after calling send.
|
||||
|
||||
The third overload, `connection_hdl hdl, message_ptr msg`, takes a WebSocket++ `message_ptr`. This overload allows a message to be constructed in place before the call to send. It also may allow a single message buffer to be sent multiple times, including to multiple connections, without copying. Whether or not this actually happens depends on other factors such as whether compression is enabled. The contents of the message buffer may not be safely modified after being sent.
|
||||
|
||||
> ###### Terminology: Outgoing WebSocket message queueing & flow control
|
||||
> In many configurations, such as when the Asio based transport is in use, WebSocket++ is an asynchronous system. As such the `endpoint::send` method may return before any bytes are actually written to the outgoing socket. In cases where send is called multiple times in quick succession messages may be coalesced and sent in the same operation or even the same TCP packet. When this happens the message boundaries are preserved (each call to send will produce a separate message).
|
||||
>
|
||||
> In the case of applications that call send from inside a handler this means that no messages will be written to the socket until that handler returns. If you are planning to send many messages in this manor or need a message to be written on the wire before continuing you should look into using multiple threads or the built in timer/interrupt handler functionality.
|
||||
>
|
||||
> If the outgoing socket link is slow messages may build up in this queue. You can use `connection::get_buffered_amount` to query the current size of the written message queue to decide if you want to change your sending behavior.
|
||||
|
||||
#### Add send method to `websocket_endpoint`
|
||||
|
||||
Like the close method, send will start by looking up the given connection ID in the connection list. Next a send request is sent to the connection's handle with the specified WebSocket message and the text opcode. Finally, we record the sent message with our connection metadata object so later our show connection command can print a list of messages sent.
|
||||
|
||||
```cpp
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
#### Add send option to the command loop and help message
|
||||
|
||||
A send option is added to the command loop. It takes a connection ID and a text message to send. An entry is also added to the help system to describe how the new command may be used.
|
||||
|
||||
```cpp
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
#### Add glue to `connection_metadata` for storing sent messages
|
||||
|
||||
In order to store messages sent on this connection some code is added to `connection_metadata`. This includes a new data member `std::vector<std::string> m_messages` to keep track of all messages sent and received as well as a method for adding a sent message in that list:
|
||||
|
||||
```cpp
|
||||
void record_sent_message(std::string message) {
|
||||
m_messages.push_back(">> " + message);
|
||||
}
|
||||
```
|
||||
|
||||
Finally the connection metadata output operator is updated to also print a list of processed messages:
|
||||
|
||||
```cpp
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
#### Receiving Messages
|
||||
|
||||
Messages are received by registering a message handler. This handler will be called once per message received and its signature is `void on_message(websocketpp::connection_hdl hdl, endpoint::message_ptr msg)`. The `connection_hdl`, like the similar parameter from the other handlers is a handle for the connection that the message was received on. The `message_ptr` is a pointer to an object that can be queried for the message payload, opcode, and other metadata. Note that the message_ptr type, as well as its underlying message type, is dependent on how your endpoint is configured and may be different for different configs.
|
||||
|
||||
#### Add a message handler to method to `connection_metadata`
|
||||
|
||||
The message receiving behave that we are implementing will be to collect all messages sent and received and to print them in order when the show connection command is run. The sent messages are already being added to that list. Now we add a message handler that pushes received messages to the list as well. Text messages are pushed as-is. Binary messages are first converted to printable hexadecimal format.
|
||||
|
||||
```cpp
|
||||
void on_message(websocketpp::connection_hdl 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()));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In order to have this handler called when new messages are received we also register it with our connection. Note that unlike most other handlers, the message handler has two parameters and thus needs two placeholders.
|
||||
|
||||
```cpp
|
||||
con->set_message_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_message,
|
||||
metadata_ptr,
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2
|
||||
));
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
There are no changes to the build instructions from step 5
|
||||
|
||||
#### Run
|
||||
|
||||
In this example run we are connecting to the WebSocket++ example echo_server. This server will repeat any message we send back to it. You can also try testing this with the echo server at `ws://echo.websocket.org` with similar results.
|
||||
|
||||
```
|
||||
Enter Command: connect ws://localhost:9002
|
||||
> Created connection with id 0
|
||||
Enter Command: send 0 example message
|
||||
Enter Command: show 0
|
||||
> URI: ws://localhost:9002
|
||||
> Status: Open
|
||||
> Remote Server: WebSocket++/0.4.0
|
||||
> Error/close reason: N/A
|
||||
> Messages Processed: (2)
|
||||
>> example message
|
||||
<< example message
|
||||
```
|
||||
|
||||
### Step 7
|
||||
|
||||
_Using TLS / Secure WebSockets_
|
||||
|
||||
- Change the includes
|
||||
- link to the new library dependencies
|
||||
- Switch the config
|
||||
- add the `tls_init_handler`
|
||||
- configure the SSL context for desired security level
|
||||
- mixing secure and non-secure connections in one application.
|
||||
|
||||
Chapter 2: Intermediate Features
|
||||
--------------------------------
|
||||
|
||||
### Step 8
|
||||
|
||||
_Intermediate level features_
|
||||
|
||||
- Subprotocol negotiation
|
||||
- Setting and reading custom headers
|
||||
- Ping and Pong
|
||||
- Proxies?
|
||||
- Setting user agent
|
||||
- Setting Origin
|
||||
- Timers and security
|
||||
- Close behavior
|
||||
- Send one message to all connections
|
||||
|
||||
|
||||
### Misc stuff not sure if it should be included here or elsewhere?
|
||||
|
||||
core websocket++ control flow.
|
||||
A handshake, followed by a split into 2 independent control strands
|
||||
- Handshake
|
||||
-- use information specified before the call to endpoint::connect to construct a WebSocket handshake request.
|
||||
-- Pass the WebSocket handshake request to the transport policy. The transport policy determines how to get these bytes to the endpoint playing the server role. Depending on which transport policy your endpoint uses this method will be different.
|
||||
-- Receive a handshake response from the underlying transport. This is parsed and checked for conformance to RFC6455. If the validation fails, the fail handler is called. Otherwise the open handler is called.
|
||||
- At this point control splits into two separate strands. One that reads new bytes from the transport policy on the incoming channle, the other that accepts new messages from the local application for framing and writing to the outgoing transport channel.
|
||||
- Read strand
|
||||
-- Read and process new bytes from transport
|
||||
-- If the bytes contain at least one complete message dispatch each message by calling the appropriate handler. This is either the message handler for data messages, or ping/pong/close handlers for each respective control message. If no handler is registered for a particular message it is ignored.
|
||||
-- Ask the transport layer for more bytes
|
||||
- Write strand
|
||||
-- Wait for messages from the application
|
||||
-- Perform error checking on message input,
|
||||
-- Frame message per RFC6455
|
||||
-- Queue message for sending
|
||||
-- Pass all outstanding messages to the transport policy for output
|
||||
-- When there are no messages left to send, return to waiting
|
||||
|
||||
Important observations
|
||||
Handlers run in line with library processing which has several implications applications should be aware of:
|
||||
@@ -45,6 +45,11 @@ static std::string const base64_chars =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
/// Test whether a character is a valid base64 character
|
||||
/**
|
||||
* @param c The character to test
|
||||
* @return true if c is a valid base64 character
|
||||
*/
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (c == 43 || // +
|
||||
(c >= 47 && c <= 57) || // /-9
|
||||
@@ -52,17 +57,21 @@ static inline bool is_base64(unsigned char c) {
|
||||
(c >= 97 && c <= 122)); // a-z
|
||||
}
|
||||
|
||||
inline std::string base64_encode(unsigned char const * bytes_to_encode, unsigned
|
||||
int in_len)
|
||||
{
|
||||
/// Encode a char buffer into a base64 string
|
||||
/**
|
||||
* @param input The input data
|
||||
* @param len The length of input in bytes
|
||||
* @return A base64 encoded string representing input
|
||||
*/
|
||||
inline std::string base64_encode(unsigned char const * input, size_t len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
while (len--) {
|
||||
char_array_3[i++] = *(input++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
|
||||
@@ -97,25 +106,38 @@ inline std::string base64_encode(unsigned char const * bytes_to_encode, unsigned
|
||||
while((i++ < 3)) {
|
||||
ret += '=';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string base64_encode(std::string const & data) {
|
||||
return base64_encode(reinterpret_cast<const unsigned char *>(data.data()),data.size());
|
||||
/// Encode a string into a base64 string
|
||||
/**
|
||||
* @param input The input data
|
||||
* @return A base64 encoded string representing input
|
||||
*/
|
||||
inline std::string base64_encode(std::string const & input) {
|
||||
return base64_encode(
|
||||
reinterpret_cast<const unsigned char *>(input.data()),
|
||||
input.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline std::string base64_decode(std::string const & encoded_string) {
|
||||
size_t in_len = encoded_string.size();
|
||||
/// Decode a base64 encoded string into a string of raw bytes
|
||||
/**
|
||||
* @param input The base64 encoded input data
|
||||
* @return A string representing the decoded raw bytes
|
||||
*/
|
||||
inline std::string base64_decode(std::string const & input) {
|
||||
size_t in_len = input.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
while (in_len-- && ( input[in_] != '=') && is_base64(input[in_])) {
|
||||
char_array_4[i++] = input[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++) {
|
||||
char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));
|
||||
|
||||
@@ -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:
|
||||
|
||||
+80
-1
@@ -1,6 +1,6 @@
|
||||
|
||||
/*
|
||||
* 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:
|
||||
@@ -51,6 +51,26 @@ namespace status {
|
||||
/// A blank value for internal use.
|
||||
static value const blank = 0;
|
||||
|
||||
/// Close the connection without a WebSocket close handshake.
|
||||
/**
|
||||
* This special value requests that the WebSocket connection be closed
|
||||
* without performing the WebSocket closing handshake. This does not comply
|
||||
* with RFC6455, but should be safe to do if necessary. This could be useful
|
||||
* for clients that need to disconnect quickly and cannot afford the
|
||||
* complete handshake.
|
||||
*/
|
||||
static value const omit_handshake = 1;
|
||||
|
||||
/// Close the connection with a forced TCP drop.
|
||||
/**
|
||||
* This special value requests that the WebSocket connection be closed by
|
||||
* forcibly dropping the TCP connection. This will leave the other side of
|
||||
* the connection with a broken connection and some expensive timeouts. this
|
||||
* should not be done except in extreme cases or in cases of malicious
|
||||
* remote endpoints.
|
||||
*/
|
||||
static value const force_tcp_drop = 2;
|
||||
|
||||
/// Normal closure, meaning that the purpose for which the connection was
|
||||
/// established has been fulfilled.
|
||||
static value const normal = 1000;
|
||||
@@ -130,6 +150,21 @@ namespace status {
|
||||
* illegal on the wire.
|
||||
*/
|
||||
static value const tls_handshake = 1015;
|
||||
|
||||
/// A generic subprotocol error
|
||||
/**
|
||||
* Indicates that a subprotocol error occurred. Typically this involves
|
||||
* receiving a message that is not formatted as a valid message for the
|
||||
* subprotocol in use.
|
||||
*/
|
||||
static value const subprotocol_error = 3000;
|
||||
|
||||
/// A invalid subprotocol data
|
||||
/**
|
||||
* Indicates that data was received that violated the specification of the
|
||||
* subprotocol in use.
|
||||
*/
|
||||
static value const invalid_subprotocol_data = 3001;
|
||||
|
||||
/// First value in range reserved for future protocol use
|
||||
static value const rsv_start = 1016;
|
||||
@@ -179,6 +214,50 @@ namespace status {
|
||||
code == policy_violation || code == message_too_big ||
|
||||
code == internal_endpoint_error);
|
||||
}
|
||||
|
||||
/// Return a human readable interpretation of a WebSocket close code
|
||||
/**
|
||||
* See https://tools.ietf.org/html/rfc6455#section-7.4 for more details.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*
|
||||
* @param [in] code The code to look up.
|
||||
* @return A human readable interpretation of the code.
|
||||
*/
|
||||
inline std::string get_string(value code) {
|
||||
switch (code) {
|
||||
case normal:
|
||||
return "Normal close";
|
||||
case going_away:
|
||||
return "Going away";
|
||||
case protocol_error:
|
||||
return "Protocol error";
|
||||
case unsupported_data:
|
||||
return "Unsupported data";
|
||||
case no_status:
|
||||
return "No status set";
|
||||
case abnormal_close:
|
||||
return "Abnormal close";
|
||||
case invalid_payload:
|
||||
return "Invalid payload";
|
||||
case policy_violation:
|
||||
return "Policy violoation";
|
||||
case message_too_big:
|
||||
return "Message too big";
|
||||
case extension_required:
|
||||
return "Extension required";
|
||||
case internal_endpoint_error:
|
||||
return "Internal endpoint error";
|
||||
case tls_handshake:
|
||||
return "TLS handshake failure";
|
||||
case subprotocol_error:
|
||||
return "Generic subprotocol error";
|
||||
case invalid_subprotocol_data:
|
||||
return "Invalid subprotocol data";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
} // namespace status
|
||||
|
||||
/// Type used to convert close statuses between integer and wire representations
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WEBSOCKETPP_COMMON_ASIO_HPP
|
||||
#define WEBSOCKETPP_COMMON_ASIO_HPP
|
||||
|
||||
// This file goes to some length to preserve compatibility with versions of
|
||||
// boost older than 1.49 (where the first modern steady_timer timer based on
|
||||
// boost/std chrono was introduced.
|
||||
//
|
||||
// For the versions older than 1.49, the deadline_timer is used instead. this
|
||||
// brings in dependencies on boost date_time and it has a different interface
|
||||
// that is normalized by the `lib::asio::is_neg` and `lib::asio::milliseconds`
|
||||
// wrappers provided by this file.
|
||||
//
|
||||
// The primary reason for this continued support is that boost 1.48 is the
|
||||
// default and not easily changeable version of boost supplied by the package
|
||||
// manager of popular Linux distributions like Ubuntu 12.04 LTS. Once the need
|
||||
// for this has passed this should be cleaned up and simplified.
|
||||
|
||||
#ifdef ASIO_STANDALONE
|
||||
#include <asio/version.hpp>
|
||||
|
||||
#if (ASIO_VERSION/100000) == 1 && ((ASIO_VERSION/100)%1000) < 8
|
||||
static_assert(false, "The minimum version of standalone Asio is 1.8.0");
|
||||
#endif
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asio/steady_timer.hpp>
|
||||
#include <websocketpp/common/chrono.hpp>
|
||||
#else
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// See note above about boost <1.49 compatibility. If we are running on
|
||||
// boost > 1.48 pull in the steady timer and chrono library
|
||||
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <websocketpp/common/chrono.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#endif
|
||||
|
||||
namespace websocketpp {
|
||||
namespace lib {
|
||||
|
||||
#ifdef ASIO_STANDALONE
|
||||
namespace asio {
|
||||
using namespace ::asio;
|
||||
// Here we assume that we will be using std::error_code with standalone
|
||||
// Asio. This is probably a good assumption, but it is possible in rare
|
||||
// cases that local Asio versions would be used.
|
||||
using std::errc;
|
||||
|
||||
// See note above about boost <1.49 compatibility. Because we require
|
||||
// a standalone Asio version of 1.8+ we are guaranteed to have
|
||||
// steady_timer available. By convention we require the chrono library
|
||||
// (either boost or std) for use with standalone Asio.
|
||||
template <typename T>
|
||||
bool is_neg(T duration) {
|
||||
return duration.count() < 0;
|
||||
}
|
||||
inline lib::chrono::milliseconds milliseconds(long duration) {
|
||||
return lib::chrono::milliseconds(duration);
|
||||
}
|
||||
} // namespace asio
|
||||
|
||||
#else
|
||||
namespace asio {
|
||||
using namespace boost::asio;
|
||||
|
||||
// See note above about boost <1.49 compatibility
|
||||
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
|
||||
// Using boost::asio >=1.49 so we use chrono and steady_timer
|
||||
template <typename T>
|
||||
bool is_neg(T duration) {
|
||||
return duration.count() < 0;
|
||||
}
|
||||
inline lib::chrono::milliseconds milliseconds(long duration) {
|
||||
return lib::chrono::milliseconds(duration);
|
||||
}
|
||||
#else
|
||||
// Using boost::asio <1.49 we pretend a deadline timer is a steady
|
||||
// timer and wrap the negative detection and duration conversion
|
||||
// appropriately.
|
||||
typedef boost::asio::deadline_timer steady_timer;
|
||||
|
||||
template <typename T>
|
||||
bool is_neg(T duration) {
|
||||
return duration.is_negative();
|
||||
}
|
||||
inline boost::posix_time::time_duration milliseconds(long duration) {
|
||||
return boost::posix_time::milliseconds(duration);
|
||||
}
|
||||
#endif
|
||||
|
||||
using boost::system::error_code;
|
||||
namespace errc = boost::system::errc;
|
||||
} // namespace asio
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace lib
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif // WEBSOCKETPP_COMMON_ASIO_HPP
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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,13 +25,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
#define WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
#ifndef WEBSOCKETPP_COMMON_ASIO_SSL_HPP
|
||||
#define WEBSOCKETPP_COMMON_ASIO_SSL_HPP
|
||||
|
||||
class echo_handler : public server::handler {
|
||||
void on_message(connection_ptr con, std::string msg) {
|
||||
con->write(msg);
|
||||
}
|
||||
};
|
||||
#ifdef ASIO_STANDALONE
|
||||
#include <asio/asio/ssl.hpp>
|
||||
#else
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
|
||||
#endif // WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
#endif // WEBSOCKETPP_COMMON_ASIO_SSL_HPP
|
||||
@@ -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:
|
||||
@@ -28,7 +28,12 @@
|
||||
#ifndef WEBSOCKETPP_COMMON_CHRONO_HPP
|
||||
#define WEBSOCKETPP_COMMON_CHRONO_HPP
|
||||
|
||||
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
|
||||
#include <websocketpp/common/cpp11.hpp>
|
||||
|
||||
// If we've determined that we're in full C++11 mode and the user hasn't
|
||||
// explicitly disabled the use of C++11 functional header, then prefer it to
|
||||
// boost.
|
||||
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
|
||||
#ifndef _WEBSOCKETPP_CPP11_CHRONO_
|
||||
#define _WEBSOCKETPP_CPP11_CHRONO_
|
||||
#endif
|
||||
@@ -44,9 +49,9 @@ namespace websocketpp {
|
||||
namespace lib {
|
||||
|
||||
#ifdef _WEBSOCKETPP_CPP11_CHRONO_
|
||||
using std::chrono::system_clock;
|
||||
namespace chrono = std::chrono;
|
||||
#else
|
||||
using boost::chrono::system_clock;
|
||||
namespace chrono = boost::chrono;
|
||||
#endif
|
||||
|
||||
} // namespace lib
|
||||
|
||||
@@ -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,7 +34,7 @@ namespace websocketpp {
|
||||
|
||||
/// A handle to uniquely identify a connection.
|
||||
/**
|
||||
* This type uniquely identifies a connection. It is implimented as a weak
|
||||
* This type uniquely identifies a connection. It is implemented as a weak
|
||||
* pointer to the connection in question. This provides uniqueness across
|
||||
* multiple endpoints and ensures that IDs never conflict or run out.
|
||||
*
|
||||
|
||||
@@ -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:
|
||||
@@ -40,10 +40,34 @@
|
||||
#define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
|
||||
#endif
|
||||
|
||||
// The code below attempts to use information provided by the build system or
|
||||
// user supplied defines to selectively enable C++11 language and library
|
||||
// features. In most cases features that are targeted individually may also be
|
||||
// selectively disabled via an associated _WEBSOCKETPP_NOXXX_ define.
|
||||
|
||||
#ifdef _WEBSOCKETPP_CPP11_STL_
|
||||
// This flag indicates that all of the C++11 language features are available
|
||||
// to us.
|
||||
#if defined(_WEBSOCKETPP_CPP11_STL_) || __cplusplus >= 201103L || defined(_WEBSOCKETPP_CPP11_STRICT_)
|
||||
// This check tests for blanket c++11 coverage. It can be activated in one
|
||||
// of three ways. Either the compiler itself reports that it is a full
|
||||
// C++11 compiler via the __cplusplus macro or the user/build system
|
||||
// supplies one of the two preprocessor defines below:
|
||||
|
||||
// This is defined to allow other WebSocket++ common headers to enable
|
||||
// C++11 features when they are detected by this file rather than
|
||||
// duplicating the above logic in every common header.
|
||||
#define _WEBSOCKETPP_CPP11_INTERNAL_
|
||||
|
||||
// _WEBSOCKETPP_CPP11_STRICT_
|
||||
//
|
||||
// This define reports to WebSocket++ that 100% of the language and library
|
||||
// features of C++11 are available. Using this define on a non-C++11
|
||||
// compiler will result in problems.
|
||||
|
||||
// _WEBSOCKETPP_CPP11_STL_
|
||||
//
|
||||
// This define enables *most* C++11 options that were implemented early on
|
||||
// by compilers. It is typically used for compilers that have many, but not
|
||||
// all C++11 features. It should be safe to use on GCC 4.7-4.8 and perhaps
|
||||
// earlier.
|
||||
#ifndef _WEBSOCKETPP_NOEXCEPT_TOKEN_
|
||||
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
|
||||
#endif
|
||||
@@ -53,7 +77,25 @@
|
||||
#ifndef _WEBSOCKETPP_INITIALIZER_LISTS_
|
||||
#define _WEBSOCKETPP_INITIALIZER_LISTS_
|
||||
#endif
|
||||
#ifndef _WEBSOCKETPP_NULLPTR_TOKEN_
|
||||
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
|
||||
#endif
|
||||
#ifndef _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
#define _WEBSOCKETPP_MOVE_SEMANTICS_
|
||||
#endif
|
||||
#ifndef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
|
||||
#define _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
// GCC as of version 4.9 (latest) does not support std::put_time yet.
|
||||
// so ignore it
|
||||
#define _WEBSOCKETPP_PUTTIME_
|
||||
#endif
|
||||
#else
|
||||
// In the absence of a blanket define, try to use compiler versions or
|
||||
// feature testing macros to selectively enable what we can.
|
||||
|
||||
// Test for noexcept
|
||||
#ifndef _WEBSOCKETPP_NOEXCEPT_TOKEN_
|
||||
#ifdef _WEBSOCKETPP_NOEXCEPT_
|
||||
@@ -90,6 +132,25 @@
|
||||
#if __has_feature(cxx_generalized_initializers) && !defined(_WEBSOCKETPP_INITIALIZER_LISTS_)
|
||||
#define _WEBSOCKETPP_INITIALIZER_LISTS_
|
||||
#endif
|
||||
|
||||
// Test for nullptr
|
||||
#ifndef _WEBSOCKETPP_NULLPTR_TOKEN_
|
||||
#ifdef _WEBSOCKETPP_NULLPTR_
|
||||
// build system says we have nullptr
|
||||
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
|
||||
#else
|
||||
#if __has_feature(cxx_nullptr)
|
||||
// clang feature detect says we have nullptr
|
||||
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
|
||||
#elif _MSC_VER >= 1600
|
||||
// Visual Studio version that has nullptr
|
||||
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
|
||||
#else
|
||||
// assume we don't have nullptr
|
||||
#define _WEBSOCKETPP_NULLPTR_TOKEN_ 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // WEBSOCKETPP_COMMON_CPP11_HPP
|
||||
|
||||
@@ -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:
|
||||
@@ -28,19 +28,37 @@
|
||||
#ifndef WEBSOCKETPP_COMMON_FUNCTIONAL_HPP
|
||||
#define WEBSOCKETPP_COMMON_FUNCTIONAL_HPP
|
||||
|
||||
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
|
||||
#include <websocketpp/common/cpp11.hpp>
|
||||
|
||||
// If we've determined that we're in full C++11 mode and the user hasn't
|
||||
// explicitly disabled the use of C++11 functional header, then prefer it to
|
||||
// boost.
|
||||
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
|
||||
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
|
||||
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
|
||||
// the use of C++11 functional header then prefer it to boost.
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
|
||||
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
|
||||
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _WEBSOCKETPP_CPP11_FUNCTIONAL_
|
||||
#include <functional>
|
||||
#else
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace websocketpp {
|
||||
namespace lib {
|
||||
|
||||
@@ -49,6 +67,18 @@ namespace lib {
|
||||
using std::bind;
|
||||
using std::ref;
|
||||
namespace placeholders = std::placeholders;
|
||||
|
||||
// There are some cases where a C++11 compiler balks at using std::ref
|
||||
// but a C++03 compiler using boost function requires boost::ref. As such
|
||||
// lib::ref is not useful in these cases. Instead this macro allows the use
|
||||
// of boost::ref in the case of a boost compile or no reference wrapper at
|
||||
// all in the case of a C++11 compile
|
||||
#define _WEBSOCKETPP_REF(x) x
|
||||
|
||||
template <typename T>
|
||||
void clear_function(T & x) {
|
||||
x = nullptr;
|
||||
}
|
||||
#else
|
||||
using boost::function;
|
||||
using boost::bind;
|
||||
@@ -57,6 +87,15 @@ namespace lib {
|
||||
/// \todo this feels hacky, is there a better way?
|
||||
using ::_1;
|
||||
using ::_2;
|
||||
using ::_3;
|
||||
}
|
||||
|
||||
// See above definition for more details on what this is and why it exists
|
||||
#define _WEBSOCKETPP_REF(x) boost::ref(x)
|
||||
|
||||
template <typename T>
|
||||
void clear_function(T & x) {
|
||||
x.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+70
-70
@@ -34,7 +34,7 @@
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
@@ -45,12 +45,12 @@
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
@@ -80,9 +80,9 @@ typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
@@ -94,7 +94,7 @@ inline void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes)
|
||||
/* Finish the message and return the digest. */
|
||||
inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define ZSW_MD5_BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
@@ -169,8 +169,8 @@ inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) {
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if ZSW_MD5_BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
@@ -183,51 +183,51 @@ static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) {
|
||||
|
||||
{
|
||||
#if ZSW_MD5_BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static int const w = 1;
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static int const w = 1;
|
||||
|
||||
if (*((md5_byte_t const *)&w)) /* dynamic little-endian */
|
||||
if (*((md5_byte_t const *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (md5_byte_t const *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (md5_word_t const *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
std::memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (md5_byte_t const *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (md5_word_t const *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
std::memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if ZSW_MD5_BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if ZSW_MD5_BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -361,71 +361,71 @@ void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes) {
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : static_cast<int>(nbytes));
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : static_cast<int>(nbytes));
|
||||
|
||||
std::memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
std::memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
std::memcpy(pms->buf, p, left);
|
||||
std::memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) {
|
||||
static md5_byte_t const pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
|
||||
// some convenience c++ functions
|
||||
inline std::string md5_hash_string(std::string const & s) {
|
||||
char digest[16];
|
||||
char digest[16];
|
||||
|
||||
md5_state_t state;
|
||||
md5_state_t state;
|
||||
|
||||
md5_init(&state);
|
||||
md5_append(&state, (md5_byte_t const *)s.c_str(), s.size());
|
||||
md5_finish(&state, (md5_byte_t *)digest);
|
||||
md5_init(&state);
|
||||
md5_append(&state, (md5_byte_t const *)s.c_str(), s.size());
|
||||
md5_finish(&state, (md5_byte_t *)digest);
|
||||
|
||||
std::string ret;
|
||||
ret.resize(16);
|
||||
std::copy(digest,digest+16,ret.begin());
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
@@ -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:
|
||||
@@ -28,16 +28,32 @@
|
||||
#ifndef WEBSOCKETPP_COMMON_MEMORY_HPP
|
||||
#define WEBSOCKETPP_COMMON_MEMORY_HPP
|
||||
|
||||
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
|
||||
#include <websocketpp/common/cpp11.hpp>
|
||||
|
||||
// If we've determined that we're in full C++11 mode and the user hasn't
|
||||
// explicitly disabled the use of C++11 memory header, then prefer it to
|
||||
// boost.
|
||||
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
|
||||
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#define _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
|
||||
// the use of C++11 functional header then prefer it to boost.
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
|
||||
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#define _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#include <memory>
|
||||
#else
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
@@ -51,6 +67,7 @@ namespace lib {
|
||||
using std::weak_ptr;
|
||||
using std::enable_shared_from_this;
|
||||
using std::static_pointer_cast;
|
||||
using std::make_shared;
|
||||
|
||||
typedef std::unique_ptr<unsigned char[]> unique_ptr_uchar_array;
|
||||
#else
|
||||
@@ -58,6 +75,7 @@ namespace lib {
|
||||
using boost::weak_ptr;
|
||||
using boost::enable_shared_from_this;
|
||||
using boost::static_pointer_cast;
|
||||
using boost::make_shared;
|
||||
|
||||
typedef boost::scoped_array<unsigned char> unique_ptr_uchar_array;
|
||||
#endif
|
||||
|
||||
@@ -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:
|
||||
@@ -29,20 +29,22 @@
|
||||
#define WEBSOCKETPP_COMMON_NETWORK_HPP
|
||||
|
||||
// For ntohs and htons
|
||||
#if defined(WIN32)
|
||||
#if defined(_WIN32)
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
//#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <websocketpp/common/stdint.hpp>
|
||||
|
||||
namespace websocketpp {
|
||||
namespace lib {
|
||||
namespace net {
|
||||
|
||||
inline bool is_little_endian() {
|
||||
short int val = 0x1;
|
||||
char *ptr = (char*)&val;
|
||||
char *ptr = reinterpret_cast<char *>(&val);
|
||||
return (ptr[0] == 1);
|
||||
}
|
||||
|
||||
@@ -50,7 +52,18 @@ inline bool is_little_endian() {
|
||||
#define TYP_SMLE 1
|
||||
#define TYP_BIGE 2
|
||||
|
||||
inline uint64_t htonll(uint64_t src) {
|
||||
/// Convert 64 bit value to network byte order
|
||||
/**
|
||||
* This method is prefixed to avoid conflicts with operating system level
|
||||
* macros for this functionality.
|
||||
*
|
||||
* TODO: figure out if it would be beneficial to use operating system level
|
||||
* macros for this.
|
||||
*
|
||||
* @param src The integer in host byte order
|
||||
* @return src converted to network byte order
|
||||
*/
|
||||
inline uint64_t _htonll(uint64_t src) {
|
||||
static int typ = TYP_INIT;
|
||||
unsigned char c;
|
||||
union {
|
||||
@@ -71,8 +84,19 @@ inline uint64_t htonll(uint64_t src) {
|
||||
return x.ull;
|
||||
}
|
||||
|
||||
inline uint64_t ntohll(uint64_t src) {
|
||||
return htonll(src);
|
||||
/// Convert 64 bit value to host byte order
|
||||
/**
|
||||
* This method is prefixed to avoid conflicts with operating system level
|
||||
* macros for this functionality.
|
||||
*
|
||||
* TODO: figure out if it would be beneficial to use operating system level
|
||||
* macros for this.
|
||||
*
|
||||
* @param src The integer in network byte order
|
||||
* @return src converted to host byte order
|
||||
*/
|
||||
inline uint64_t _ntohll(uint64_t src) {
|
||||
return _htonll(src);
|
||||
}
|
||||
|
||||
} // net
|
||||
|
||||
@@ -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:
|
||||
@@ -33,9 +33,14 @@
|
||||
* don't fit somewhere else better.
|
||||
*/
|
||||
|
||||
#if defined(WIN32) && !defined(NOMINMAX)
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
// don't define min and max macros that conflict with std::min and std::max
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
// Bump up the variadic parameter max for Visual Studio 2012
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1700
|
||||
#define _VARIADIC_MAX 8
|
||||
#endif
|
||||
|
||||
#endif // WEBSOCKETPP_COMMON_PLATFORMS_HPP
|
||||
|
||||
@@ -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:
|
||||
@@ -28,12 +28,28 @@
|
||||
#ifndef WEBSOCKETPP_COMMON_RANDOM_DEVICE_HPP
|
||||
#define WEBSOCKETPP_COMMON_RANDOM_DEVICE_HPP
|
||||
|
||||
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_RANDOM_DEVICE_
|
||||
#include <websocketpp/common/cpp11.hpp>
|
||||
|
||||
// If we've determined that we're in full C++11 mode and the user hasn't
|
||||
// explicitly disabled the use of C++11 random header, then prefer it to
|
||||
// boost.
|
||||
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_RANDOM_DEVICE_
|
||||
#ifndef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
|
||||
#define _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
|
||||
// the use of C++11 random header then prefer it to boost.
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
|
||||
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#define _WEBSOCKETPP_CPP11_MEMORY_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
|
||||
#include <random>
|
||||
#else
|
||||
|
||||
@@ -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:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user