Compare commits

..

925 Commits

Author SHA1 Message Date
Peter Thorson 9161119b4d bump version to alpha2 2013-06-09 17:24:24 -05:00
Peter Thorson 7db60e3429 fix poor server handling of double close frames fixes #259 2013-06-09 17:03:14 -05:00
Peter Thorson 3c0b8a81b0 Fix handling of spurious frames after close. Fixes #258 2013-06-09 16:41:04 -05:00
Peter Thorson b812fd001b Change default HTTP response error code to 426
Changes default HTTP response error code when no http_handler is
defined from 500/Internal Server Error to 426/Upgrade Required
2013-06-09 16:20:53 -05:00
Peter Thorson 3a43986d9e add documentation & normalize code style 2013-06-09 14:58:32 -05:00
Peter Thorson 64b1b52297 adds documentation on locations of version info 2013-06-09 11:07:19 -05:00
Peter Thorson dc048ed021 test use of doxygen todo command 2013-06-09 11:05:48 -05:00
Peter Thorson 60b167bcb7 updates changelog 2013-06-09 09:27:08 -05:00
Peter Thorson e680ca1ef4 add comment + TODO regarding VSPP warning 2013-06-09 09:25:30 -05:00
Peter Thorson 21d79e28c6 maybe fix markdown # escape? 2013-06-09 09:20:31 -05:00
Peter Thorson d25a254e81 remove logger dynamic allocation 2013-06-09 09:20:04 -05:00
Peter Thorson 3e144cfd75 Merge pull request #257 from zaphoyd/experimental
merge last bit of changes from experimental to master
2013-06-09 07:15:12 -07:00
Peter Thorson a5bb90807b Merge pull request #252 from breyed/visual-studio
Fixed Visual Studio 2012 warnings and formatting
2013-06-09 07:05:53 -07:00
Peter Thorson 096a7dbaa8 escape # in readme 2013-06-09 08:58:15 -05:00
Peter Thorson 577591aaa1 readme updates 2013-06-09 08:55:53 -05:00
Peter Thorson a401a4448d update version information to 0.3.0-alpha1 2013-06-09 08:46:54 -05:00
Peter Thorson ace76f54f9 update docs for 0.3.x in master branch fixes #197 2013-06-09 08:31:05 -05:00
Peter Thorson 1eaa1b790f update travis for 0.3.x in master 2013-06-09 08:30:03 -05:00
Peter Thorson c2a5f0bfa1 Merge pull request #255 from zaphoyd/0.3.x-cmake
merge final bits of 0.3.x-cmake into experimental
2013-06-09 06:13:59 -07:00
Peter Thorson b71b224860 Merge branch 'experimental' into 0.3.x-cmake 2013-06-09 08:13:02 -05:00
Peter Thorson be1d9fd64e Merge pull request #248 from resiprocate/0.3.x-cmake
Fix typo, add sip_client example (SIP over WebSockets)
2013-06-09 05:59:37 -07:00
Peter Thorson bcac77306f Merge pull request #254 from breyed/boost-config
Automatically configure platform via Boost.Config
2013-06-09 05:56:52 -07:00
Peter Thorson dd563c6647 corrects TCP close behavior references #227 fixes #25
Per RFC6455 clients prefer to wait for servers to initiate TCP close.
timers ensure that clients don't wait forever. Servers close TCP
immediately.
2013-06-09 07:36:55 -05:00
Peter Thorson 0ab1333a2f add transport integration helper handlers delay and close 2013-06-09 07:34:10 -05:00
Peter Thorson b9c66e9a7f transport integration test formatting cleanup 2013-06-09 07:33:48 -05:00
Peter Thorson 56e81cb6eb impliment close handshake timeouts references #226 2013-06-09 07:33:30 -05:00
Peter Thorson c228f70a9f complete handshake timeout references #226 2013-06-08 18:32:23 -05:00
Peter Thorson f35918ce6e split log_fail_result from log_close_result 2013-06-08 18:32:23 -05:00
Peter Thorson 33a0d89633 add transport integration dummy TCP client
client connects and never sends anything. the client ends on EOF
2013-06-08 18:32:23 -05:00
Peter Thorson bf582aa2c1 add unit test for server open handshake timeout 2013-06-08 18:32:23 -05:00
Peter Thorson 88c553f1fc silence unit tests 2013-06-08 18:32:23 -05:00
Peter Thorson 96270a9f3d add test for client opening handshake 2013-06-08 18:32:23 -05:00
Peter Thorson c6381a2311 start client handshake timer 2013-06-08 18:32:22 -05:00
Peter Thorson cff8604148 cancel handshake timers when handshake is complete 2013-06-08 18:32:22 -05:00
Peter Thorson dfcd8a2967 set detailed error code on terminate 2013-06-08 18:32:22 -05:00
Peter Thorson 593c26f087 fix devel debug comment 2013-06-08 18:32:22 -05:00
Peter Thorson 408639a0b5 whitespace 2013-06-08 18:32:22 -05:00
Peter Thorson b591e9fa7e add handshake timeout handlers 2013-06-08 18:32:22 -05:00
Peter Thorson f2486d4aef add handshake timer & associated handlers 2013-06-08 18:32:22 -05:00
Peter Thorson 1892e0f13b remove unused code 2013-06-08 18:32:22 -05:00
Peter Thorson 8ee6a4a64b set state to closing after we send our close frame 2013-06-08 18:32:22 -05:00
Peter Thorson c86601f123 add methods to retrieve WebSocket close codes & reasons 2013-06-08 18:32:22 -05:00
Peter Thorson 0f02119d48 adds new error codes for handshake timeouts 2013-06-08 18:32:22 -05:00
Peter Thorson 196523ba42 adds a machine readable internal error code
To be used for storing detailed error codes for why connections failed
or were closed
2013-06-08 18:32:22 -05:00
Peter Thorson 4a94a7c518 Merge pull request #253 from breyed/spelling
fixed spelling, including "experimental" in API
2013-06-08 09:19:41 -07:00
breyed e68d492ed2 Fixed Visual Studio 2012 warnings
Fixed daylight savings time formatting problem on Windows
2013-06-08 11:07:02 -05:00
breyed 808a8ce0a9 fixed spelling, including "experimental" in API 2013-06-08 11:03:11 -05:00
breyed cd8e1a25bb fixed comment at end of include guard 2013-06-08 10:34:09 -05:00
breyed 2352f09c68 Automatically configure platform via Boost.Config 2013-06-08 10:26:55 -05:00
Peter Thorson 55fa61feb1 Merge remote-tracking branch 'origin/0.3.x-cmake' into experimental 2013-06-08 09:29:53 -05:00
Peter Thorson 17083a4d4e Merge pull request #251 from jefferai/0.3.x-cmake
Add missing condition_variable include
2013-06-06 06:21:09 -07:00
Jeff Mitchell 2b6b4862ce Add missing condition_variable include 2013-06-05 14:12:13 -04:00
Daniel Pocock de4ad9e7f3 Add README for sip_client 2013-05-31 16:59:06 +02:00
Daniel Pocock 45e305b5c2 Fixes for sip_client new 0.3 API 2013-05-31 16:56:27 +02:00
Daniel Pocock 3dd3fd28d4 Correct the Via header for WS transport 2013-05-31 16:45:17 +02:00
Daniel Pocock 1dfa629ae4 Sending a SIP OPTIONS message 2013-05-31 15:45:34 +02:00
Daniel Pocock a549f2b99e Renaming contents of sip_client from echo_client 2013-05-31 14:47:41 +02:00
Daniel Pocock ca108ac693 Add examples/sip_client based on examples/echo_client 2013-05-31 14:45:54 +02:00
Daniel Pocock 7d513e1e11 Fix typo 2013-05-31 14:40:52 +02:00
Peter Thorson 2e2a8e4346 documentation and reorganization 2013-05-30 23:30:04 -05:00
Peter Thorson 808179551f remove dead code 2013-05-30 23:29:48 -05:00
Peter Thorson 38a565888f adds documentation 2013-05-30 18:05:34 -05:00
Peter Thorson dcb13d58be updates hybi00 to use new md5 header 2013-05-30 17:56:57 -05:00
Peter Thorson e8aa1e0e12 consolodates md5 code 2013-05-30 17:50:10 -05:00
Peter Thorson fcac7071eb adds documentation 2013-05-30 13:32:45 -05:00
Peter Thorson ea36bf1cf7 removes unused files 2013-05-30 13:32:33 -05:00
Peter Thorson 245978fd86 remove unneeded dependencies 2013-05-29 09:22:27 -05:00
Peter Thorson 6e0411020c fix broken package name 2013-05-29 09:17:17 -05:00
Peter Thorson ad2ff8ca0a fix travis script? 2013-05-29 09:15:37 -05:00
Peter Thorson 7e6d4212a5 only load boost libraries that we need to improve test times 2013-05-29 09:09:03 -05:00
Peter Thorson 7ca4f37c2c stop the server after the last connection ends and let the server thread clean up 2013-05-29 09:07:48 -05:00
Peter Thorson 370bd93182 remove exception suppression, test framework will catch these 2013-05-29 09:07:19 -05:00
Peter Thorson d9e3f626e2 use custom config so we can play with timer duration values 2013-05-29 09:06:46 -05:00
Peter Thorson b43717cd43 Merge branch 'experimental' of github.com:zaphoyd/websocketpp into experimental 2013-05-29 08:48:31 -05:00
Peter Thorson e4c4cf2018 updates readme and roadmap 2013-05-29 08:48:22 -05:00
Peter Thorson f0f346dabe experimental dual core travis build 2013-05-29 08:48:08 -05:00
Peter Thorson a29132e6f4 Merge pull request #245 from jefferai/0.3.x-cmake
Overload get_connection to allow passing in an already-constructed uri_p...
2013-05-28 10:39:59 -07:00
Jeff Mitchell 0a7aaa2632 Overload get_connection to allow passing in an already-constructed uri_ptr. This avoid the need for using the regex, which GCC does not implement yet. 2013-05-28 13:15:01 -04:00
Peter Thorson 10a8af1ac3 adds pong timer support and new full stack automated integration testing for it 2013-05-26 22:04:28 -05:00
Peter Thorson 5677b5f400 adds dummy timer support + tests to iostream transport 2013-05-26 20:02:08 -05:00
Peter Thorson f10e2d9b21 Merge pull request #240 from jefferai/0.3.x-cmake
Needs to be uppercase Version for case-sensitive systems
2013-05-26 12:36:27 -07:00
Peter Thorson ec8b73cad4 clarifies the purpose of utility client and removes contradictory comments references #242 2013-05-24 22:14:06 -07:00
Jeff Mitchell ca6aa12fbc Add websocketpp_found variable 2013-05-20 16:50:34 -04:00
Jeff Mitchell 2aea85a773 Needs to be uppercase Version for case-sensitive systems 2013-05-20 10:24:29 -04:00
Peter Thorson 2c09846722 Merge pull request #239 from zaphoyd/experimental
updates cmake branch with latest changes
2013-05-18 05:05:00 -07:00
Peter Thorson 8f8bbb99e9 adds more unit tests for http requests 2013-05-18 06:56:49 -05:00
Peter Thorson d7e5235036 extract URI for HTTP connections also 2013-05-18 06:54:56 -05:00
Peter Thorson dd534ace64 switches processor to use new free get_uri function 2013-05-18 06:54:32 -05:00
Peter Thorson 065dd26779 adds free processor extract uri from request utility method 2013-05-18 06:53:46 -05:00
Peter Thorson 8c6b049e99 adds better support for custom URI schemes 2013-05-18 06:53:17 -05:00
Peter Thorson f988315ea8 updates broadcast_server to use common/thread rather than hardcoding boost thread 2013-05-16 10:31:02 -05:00
Peter Thorson 4474868372 adds unique_lock and condition_variable to common thread tools 2013-05-16 10:30:38 -05:00
Peter Thorson 5c4719080c Merge pull request #236 from jefferai/0.3.x-cmake
CMake fixes/enhancements
2013-05-15 06:40:02 -07:00
Jeff Mitchell 980fa8db67 Create -config and -configversion files so find_package in other
CMake-using applications works to include websocketpp. Also, a lot of
cleanup.
2013-05-15 08:23:37 -04:00
Peter Thorson f3faf404dd merge from experimental 2013-05-14 15:22:22 -05:00
Peter Thorson a2a02ba063 adds a debug log statement 2013-05-14 15:14:57 -05:00
Peter Thorson 3c015ca356 Merge pull request #232 from jefferai/0.3.x-cmake
Actually recursively install header files.
2013-05-13 07:06:33 -07:00
Peter Thorson 19edfe3c60 adds tests for TLS timers 2013-05-13 09:05:31 -05:00
Peter Thorson a8f649892f renames mock logger to stub logger 2013-05-13 09:03:12 -05:00
Peter Thorson 27d5ec3394 adds Doxygen file 2013-05-13 07:53:41 -05:00
Peter Thorson d8310780ac adds documentation 2013-05-13 07:50:43 -05:00
Peter Thorson a77d92e99a switches the order of error and access log paramters to be consistent with the rest of the library 2013-05-13 07:50:29 -05:00
Jeff Mitchell e88b30e94d Don't use Doxygen in the standard cmake build dir 2013-05-12 10:26:31 -04:00
Jeff Mitchell c6f3ce4d39 Actually recursively install header files. 2013-05-11 18:51:44 -04:00
Peter Thorson 4a4c763d18 Merge pull request #231 from zaphoyd/experimental
bring cmake branch in line with experimental
2013-05-11 13:57:46 -07:00
Peter Thorson ae207afb10 Merge pull request #230 from jefferai/0.3.x-cmake
Add basic Doxyfile
2013-05-11 13:51:06 -07:00
Peter Thorson 0d7677b1b1 use travis for all 0.3.x branches 2013-05-11 15:50:47 -05:00
Peter Thorson c3d484f1ea preliminary work on unit tests for timers 2013-05-11 15:49:48 -05:00
Peter Thorson 0a4995bce5 adds missing include files 2013-05-11 15:48:32 -05:00
Peter Thorson 8f7843094d edits for consistency 2013-05-11 15:48:21 -05:00
Peter Thorson 738822813f Adds an empty mock logger 2013-05-11 15:47:56 -05:00
Jeff Mitchell c3fb69833c Add basic Doxyfile 2013-05-11 16:09:23 -04:00
Peter Thorson 5bd0332d19 return error code by value rather than reference 2013-05-11 09:43:09 -05:00
Peter Thorson cb5955ccc5 defines timers before using them 2013-05-11 09:40:19 -05:00
Peter Thorson 2f050cf412 updates socket policy error handling 2013-05-11 09:36:42 -05:00
Peter Thorson 67edd83a7c adds post_init (tls) and shutdown timers references #226 2013-05-11 07:11:00 -05:00
Peter Thorson c8f603ed1c simplify tls async shutdown 2013-05-11 07:09:59 -05:00
Peter Thorson d37dd26f43 rename config constants for consistency 2013-05-11 07:09:42 -05:00
Peter Thorson 3ac8a99cec fixes some typos 2013-05-10 17:18:33 -05:00
Peter Thorson 58fd1b80c2 refactors dns resolve timer to be more robust and adds connect timer 2013-05-10 17:17:13 -05:00
Peter Thorson 43ba642b53 removes timeouts from socket policy (moving them a level up) 2013-05-10 17:13:46 -05:00
Peter Thorson 4e06c837ff adds post/pre init and connect timeout values to default configs 2013-05-10 17:07:52 -05:00
Peter Thorson b23c7fd93a define NOMINMAX to fix VCPP warnings references #203
reported by KHeresy
2013-05-10 16:08:46 -05:00
Peter Thorson 8966c88d2f add platform specific preprocessor settings section 2013-05-10 16:04:43 -05:00
Peter Thorson e2462ec30b use endpoint set_timer rather than connection 2013-05-10 16:02:33 -05:00
Peter Thorson 4adfc452d0 adds more robust proxy timeout behavior 2013-05-10 08:43:37 -05:00
Peter Thorson 80990aaec9 adds travis build status to readme 2013-05-10 07:08:59 -05:00
Peter Thorson 34327a69c6 disable travis ci clang build on ubuntu until scons can be fixed 2013-05-09 20:03:25 -05:00
Peter Thorson 92ff87c144 install boost libraries, not just headers 2013-05-09 19:55:39 -05:00
Peter Thorson 0ec7c187b8 libs not plural 2013-05-09 19:49:51 -05:00
Peter Thorson 6780d15bee invalid yml! 2013-05-09 19:47:15 -05:00
Peter Thorson e4467487e0 travis ci update 2013-05-09 19:46:06 -05:00
Peter Thorson 257149e9db experimental travis-ci support references #171 2013-05-09 19:43:35 -05:00
Peter Thorson d83c2913b2 add user manual to readme 2013-05-09 19:43:35 -05:00
Peter Thorson 16999a14c7 fixes some silly mistakes references #229 2013-05-09 16:35:39 -05:00
Peter Thorson 4d0a1c98a9 optimization level 2/3 fails to pass unit tests. need to investigate 2013-05-09 16:34:47 -05:00
Peter Thorson 49a866dc8e test line breaks 2013-05-09 07:18:30 -05:00
Peter Thorson 837b9f82ae update readme 2013-05-09 07:16:15 -05:00
Peter Thorson e9553268fd update email 2013-05-09 07:14:02 -05:00
Peter Thorson 11a4fc4132 fix spacing 2013-05-09 07:13:23 -05:00
Peter Thorson 80ea946938 fix italic formatting 2013-05-09 07:12:45 -05:00
Peter Thorson 273c8e82b0 updates non-code supporting documentation 2013-05-09 07:11:59 -05:00
Peter Thorson 98c8c2ae5c Merge pull request #228 from zaphoyd/experimental
Merge experimental into 0.3.x-cmake
2013-05-09 04:35:11 -07:00
Peter Thorson 7a0a987f57 Merge pull request #225 from jefferai/0.3.x-cmake
More CMake updates
2013-05-09 04:32:59 -07:00
Peter Thorson d85ea32851 adds timer support to asio endpoints, impliments dns resolve timer references #226 2013-05-08 08:52:52 -05:00
Peter Thorson b408ab876e adds method to set proxy timeout duration at runtime 2013-05-07 20:45:28 -05:00
Peter Thorson 747bc55bcf adds documentation and error handling to proxy methods 2013-05-07 20:45:04 -05:00
Peter Thorson fd46083c4a updates frame unit tests to use more specific checks 2013-05-07 20:34:17 -05:00
Peter Thorson 5d0d1379b6 adds timer support for asio transport and adds proxy connect timeout references #226 2013-05-07 17:49:02 -05:00
Peter Thorson 175cab8d22 updates configs to add default timer wait times references #226 2013-05-07 17:46:41 -05:00
Peter Thorson bda4cf3a46 updates derived configs to also derive transport_config from base 2013-05-07 17:46:17 -05:00
Peter Thorson 96158ee8b5 print get connection errors 2013-05-07 13:07:36 -05:00
Peter Thorson 215c9bcdab adds better debugging options for the scons build system 2013-05-07 13:07:35 -05:00
Jeff Mitchell 92651f1f14 Affect the install location for headers only; honor the normal/given install prefix otherwise. 2013-05-07 12:47:33 -04:00
Jeff Mitchell 693fa27fed Make finding boost conditional upon examples being built; remove building when possible by only using header versions of files 2013-05-07 12:38:41 -04:00
Peter Thorson 8e40c53f97 adds new async terminate interface which significantly improves error handling 2013-05-07 09:38:26 -05:00
Peter Thorson 6bd62edb43 removes unused code & updates naming conventions 2013-05-07 09:37:37 -05:00
Peter Thorson 75af01cda4 updates asio transport base unit tests for new interface 2013-05-07 09:35:48 -05:00
Peter Thorson 42ca501f76 adds async_shutdown interface to transport connections 2013-05-07 09:35:13 -05:00
Peter Thorson 7d8f1ea163 revert ignore of TLS short read references #224 2013-05-07 07:02:17 -05:00
Peter Thorson b0cf22c66b Merge pull request #222 from jefferai/0.3.x-cmake
Fix a number of CMake-related issues
2013-05-06 12:09:56 -07:00
Jeff Mitchell 0aba4f3695 Fix a number of CMake problems: clang detection, shared library support, etc. 2013-05-06 13:12:02 -04:00
Jeff Mitchell 5c9de71415 Merge remote-tracking branch 'upstream/experimental' into 0.3.x-cmake 2013-05-06 13:09:40 -04:00
Peter Thorson 4807d54155 corrects visual studio 2008 temporary overflow debug warning references #221 2013-05-06 08:23:40 -05:00
Peter Thorson 3304647c3f removes stray space from proxy auth header references #132 2013-05-06 08:22:03 -05:00
Peter Thorson b2fbb7b8ba registers missing handlers 2013-05-05 19:09:03 -05:00
Peter Thorson f6f4befe46 adds new tls_short_read transport error 2013-05-05 19:06:55 -05:00
Peter Thorson dc7872d647 test ignoring TLS short reads 2013-05-05 18:57:17 -05:00
Peter Thorson 844334efbb fixes perftest constructor call 2013-05-05 18:47:30 -05:00
Peter Thorson 2dcc87a7d3 fixes incorrect duration type 2013-05-05 18:46:30 -05:00
Peter Thorson 0ff8bbfbb7 adds proper close status 2013-05-05 18:43:33 -05:00
Peter Thorson 971482e0b8 typos 2013-05-05 18:42:00 -05:00
Peter Thorson b4edb1be06 some stuff for performance testing 2013-05-05 18:38:10 -05:00
Peter Thorson 3da5bb6b2c don't block on SSL shutdown 2013-05-05 18:09:16 -05:00
Peter Thorson b1f9e9b069 send absolute authority to proxy init 2013-05-05 17:28:25 -05:00
Peter Thorson 3fcc3b6b75 adds the ability to get the absolute authority of a uri 2013-05-05 17:28:03 -05:00
Peter Thorson 03e6f6dd11 ugh tabs 2013-05-05 17:16:13 -05:00
Peter Thorson b29a2f3456 removes old code 2013-05-05 17:12:13 -05:00
Peter Thorson adb0eedc24 splits transport init into pre-and post proxy steps 2013-05-05 16:14:38 -05:00
Peter Thorson cb40f81978 adjusts how remote endpoint logging is printed 2013-05-05 15:15:53 -05:00
Peter Thorson 24f6943336 fixes more typos 2013-05-05 15:13:45 -05:00
Peter Thorson ced601f8d7 fixes some typos 2013-05-05 15:12:34 -05:00
Peter Thorson c1e0545d58 adds debug logging for the connect and dns resolve seps 2013-05-05 12:18:23 -05:00
Peter Thorson d908c1afd2 update copyright dates and fix whitespace that doesn't match projec style 2013-05-05 11:23:31 -05:00
Peter Thorson 3c9f3206c5 tls support for utility client 2013-05-04 14:25:21 -05:00
Peter Thorson 2fa6e6f4d4 security policy socket_init handler now uses tls socket stream type rather than raw socket 2013-05-04 14:25:11 -05:00
Peter Thorson 8dad7aba45 propogate handle setting through to the security policy 2013-05-04 14:24:24 -05:00
Peter Thorson c559e0a623 connection initialization errors are properly logged and propogated 2013-05-04 11:52:52 -05:00
Peter Thorson 6561a9be20 adds security policy interface documentation 2013-05-04 11:52:13 -05:00
Peter Thorson 54fdf1af72 adds transport policy interface documentation 2013-05-04 11:51:55 -05:00
Peter Thorson 5440ecfcb7 adjusts variable names to match coding style 2013-05-04 11:50:52 -05:00
Peter Thorson d44131397e Merge pull request #219 from jonnenauha/cmake_prebuild_system
Cmake prebuild system against 0.3.x-cmake
2013-05-03 19:06:53 -07:00
unknown 1e6c1f9807 Merge remote-tracking branch 'upstream/0.3.x-cmake' into cmake_prebuild_system
Conflicts:
	websocketpp/endpoint.hpp
2013-05-04 02:07:17 +03:00
Peter Thorson b6a741ed23 fixes utility client tls settings 2013-05-03 17:12:51 -05:00
Peter Thorson 8906f19caa fixes asio tls client config name 2013-05-03 17:12:43 -05:00
Peter Thorson 28eecb80e0 adds utility client example 2013-05-03 17:08:05 -05:00
Peter Thorson 64f7e24b4d read proxy info from the right socket 2013-05-03 14:32:35 -05:00
Peter Thorson 380116b3df un-breaks VCPP and doesn't seem to affect anything else 2013-05-03 11:20:42 -05:00
Jonne Nauha db0a2eb7f5 Fix stdint.hpp for <=VC9. 2013-05-03 11:20:08 -05:00
Peter Thorson cde8a9e204 wites proxy connect to next layer 2013-05-03 08:41:50 -05:00
Peter Thorson 84283db1e5 adds wrapper for getting the next layer of the socket stack to tls and basic templates 2013-05-03 08:41:38 -05:00
Peter Thorson 14e80a4ff1 detab 2013-05-03 08:33:43 -05:00
Peter Thorson 0cba06bd67 fixes error namespacing 2013-05-03 08:33:12 -05:00
Peter Thorson 05fb9aadb1 detab 2013-05-03 08:32:59 -05:00
Peter Thorson 87da82698f re-orders methods properly 2013-05-03 08:32:52 -05:00
Peter Thorson 2cebf3a30b adds proxy basic auth support references #132 2013-05-03 08:00:41 -05:00
Peter Thorson 8f35121445 write proxy connect to the raw socket references #132 2013-05-03 07:59:47 -05:00
Peter Thorson 1e2762e648 adds error handling to proxy initiation 2013-05-03 07:57:08 -05:00
Peter Thorson d9d3804e5f adds convenience method to base64 encode strings 2013-05-03 07:56:09 -05:00
Peter Thorson 5be8ecca87 impliments hybi00 close frames references #195 2013-05-02 19:28:29 -05:00
Peter Thorson b06ba38fce removes debug printing 2013-05-02 19:26:13 -05:00
Peter Thorson 24774fc124 adds a bunch of explicit casts where signedness or truncation occurs references #218 2013-05-01 08:24:02 -05:00
Peter Thorson 0905b7d4e9 switches static to reinterpret_cast references #218 2013-05-01 07:00:37 -05:00
Peter Thorson 754651c9eb readme status update 2013-05-01 06:42:05 -05:00
Peter Thorson 04bbb4aa43 cleans up acceptor on destruction of endpoint transport component references #217 2013-05-01 06:23:11 -05:00
Peter Thorson b0b7f5e586 explicitly casts assignments with differing signedness references #218 2013-05-01 06:18:21 -05:00
Peter Thorson 371aa07180 fixes SConscript name comment 2013-05-01 06:10:16 -05:00
Peter Thorson c13ec1beb7 adds set(none) as alias for clear all references #207 2013-04-30 17:53:07 -05:00
Peter Thorson 00c29e42ac disable circshift test for a bit 2013-04-30 17:43:48 -05:00
Peter Thorson 40c10ff6e7 potential endianness fix 2013-04-30 17:42:36 -05:00
Peter Thorson df8d7f3f0d unit test fix 2013-04-30 17:21:16 -05:00
Peter Thorson f110b0bc65 potential solution for PPC masking bug 2013-04-30 17:14:34 -05:00
Peter Thorson 568743e587 fixes bug in unit test 2013-04-30 17:14:22 -05:00
Peter Thorson 54a9ed6e24 Fixes isystem flag 2013-04-30 17:14:11 -05:00
Peter Thorson 5ee8000b12 updates readme progress report 2013-04-29 16:58:53 -05:00
Peter Thorson be07587659 removes expensive development logging from non-debug builds 2013-04-29 13:06:17 -05:00
Peter Thorson 865da6dba2 allow end user dynamic tests 2013-04-29 13:03:25 -05:00
Peter Thorson 4b99ad7ed4 Merge pull request #216 from oberstet/experimental
add testee server
2013-04-28 11:11:12 -07:00
Tobias Oberstein d4f2b6083d logging: total silence 2013-04-28 20:06:28 +02:00
Tobias Oberstein eeb6d778ff add testee server 2013-04-28 19:54:25 +02:00
Peter Thorson 2c3892bb56 Merge pull request #215 from oberstet/experimental
some Windows build fixes
2013-04-28 08:15:32 -07:00
Tobias Oberstein 53a7a67d80 some Windows build fixes 2013-04-28 17:09:09 +02:00
Peter Thorson a500ec144f allow proxies to work with secure websockets 2013-04-27 22:15:21 -05:00
Peter Thorson 5d71935441 completes basic client proxy support references #132 2013-04-27 13:58:33 -05:00
Peter Thorson 2a71b89bbc better debug messages 2013-04-27 13:57:44 -05:00
Peter Thorson ea7ac38ed7 bugfixes and tests for new http istream consume 2013-04-27 13:55:25 -05:00
Peter Thorson aaaa2b4a65 updates uri unit tests to allow http schemes 2013-04-27 13:54:57 -05:00
Peter Thorson bb702c6589 update URI to be able to store and manipulate HTTP URIs 2013-04-27 13:15:41 -05:00
Peter Thorson de1ceff418 initial work on client proxy support references #132 2013-04-26 08:56:18 -05:00
Peter Thorson ca8716ae53 remove unused code 2013-04-26 08:55:56 -05:00
Peter Thorson 64eb09db06 initial work on istream input for http parsers 2013-04-26 08:55:36 -05:00
Peter Thorson 1bbb0cba7f readme update 2013-04-26 08:55:04 -05:00
Peter Thorson 1f194ea327 hybi00 unit test bugfix 2013-04-26 08:54:58 -05:00
Peter Thorson e6c0a7b506 refactor configs to remove duplicate code and add http processor types to transport config 2013-04-26 08:54:40 -05:00
Peter Thorson f46b305df8 fixes typo, references #213 2013-04-26 06:15:42 -05:00
Peter Thorson fe28f29ab4 updates readme 2013-04-25 19:48:47 -05:00
Peter Thorson d9d6338cc2 adds some additional debugging output 2013-04-25 18:55:21 -05:00
Peter Thorson 5e50387596 adjusts some hybi00 handshake settings 2013-04-25 18:54:48 -05:00
Peter Thorson b4c2bfd13a adds hybi00 frame read code + tests 2013-04-25 08:52:21 -05:00
Peter Thorson 66a3db1740 note that hybi13 processor needs incoming message buffer validation 2013-04-25 08:51:57 -05:00
Peter Thorson 34a9d47b9c adds error type for no incoming message buffers 2013-04-25 08:51:25 -05:00
Peter Thorson d4be2a9b4d more frame writing unit tests 2013-04-25 06:36:09 -05:00
Peter Thorson 6095b90cc1 adds hybi00 support for writing messages 2013-04-25 06:27:36 -05:00
Peter Thorson 285069b178 final cleanup 2013-04-24 07:47:58 -05:00
Peter Thorson 6359f3bb0a clean up 2013-04-24 07:25:42 -05:00
Peter Thorson 94919f125c character by character experiment 2013-04-24 07:21:58 -05:00
Peter Thorson e304deacad typo 2013-04-24 07:03:36 -05:00
Peter Thorson 0bc908674a flush logger output 2013-04-24 07:02:39 -05:00
Peter Thorson d1e05df4fa some logging 2013-04-24 07:00:39 -05:00
Peter Thorson 1081fcb6ef tests with iostream_server 2013-04-24 06:56:59 -05:00
Peter Thorson 948d9a487f fixes missing return value 2013-04-23 21:15:17 -05:00
Peter Thorson d40321333a additional documentation and cleanup 2013-04-23 13:37:51 -05:00
Peter Thorson 04244da3f9 small logic cleanup 2013-04-23 13:28:54 -05:00
Peter Thorson fbdc122774 adds an fail handler to telemetry client 2013-04-23 13:23:53 -05:00
Peter Thorson 04f4aab1a9 default connection close status is the abnormal close rather than 0 2013-04-23 13:23:15 -05:00
Peter Thorson 5c9be64230 pass through endpoint errors are now filed under info rather than devel 2013-04-23 13:23:02 -05:00
Peter Thorson 648c387048 adds some explanatory comments 2013-04-23 12:41:35 -05:00
Peter Thorson 72b3def6d6 tabs to spaces 2013-04-23 12:35:05 -05:00
Peter Thorson f51960e8ff adds telemetry client example 2013-04-23 12:33:25 -05:00
Peter Thorson c68e2207c2 adds print server example 2013-04-23 12:33:18 -05:00
Peter Thorson b9ec2d5ae9 removes raw debugging output 2013-04-23 12:33:05 -05:00
Peter Thorson c2fe98c9a4 cleans up session::state values 2013-04-23 12:32:45 -05:00
Peter Thorson a10a5a7bcd adds lib::thread 2013-04-23 12:32:13 -05:00
Peter Thorson 5f87341e9e adds file based logging to iostream server 2013-04-23 10:03:56 -05:00
Peter Thorson 6fe8d8a4f9 ignore log files 2013-04-23 10:03:31 -05:00
Peter Thorson 1421403603 adds ability to set arbitrary stream for logging 2013-04-23 10:03:24 -05:00
Peter Thorson 30d3c8a895 removes cout statement 2013-04-23 10:03:04 -05:00
Peter Thorson 07a4394ba6 new iostream example 2013-04-23 09:26:57 -05:00
Peter Thorson e7483e82ac adds manual input options for iostream transport 2013-04-23 09:26:50 -05:00
Peter Thorson cd8b467225 expected EOF after clean close no longer triggers fatal error references #209 2013-04-20 09:30:02 -05:00
Peter Thorson d987f7b0d5 user agent strings in connect logging are now properly quoted 2013-04-20 08:56:45 -05:00
Peter Thorson 91250fcd54 adds a string_replace_all utility function 2013-04-20 08:56:19 -05:00
Peter Thorson 466c9bd626 removes redundant code from echo_server 2013-04-20 08:34:58 -05:00
Peter Thorson 72b5fada72 adds close result logging 2013-04-20 08:34:28 -05:00
Peter Thorson ea3426868c adds asio transport eof error detection 2013-04-20 08:33:53 -05:00
Peter Thorson f877098f7c fixes debug config 2013-04-20 08:33:27 -05:00
Peter Thorson 4c1abab02b removes unneeded dependencies and makes base64 validation more strict references #209 2013-04-20 07:44:06 -05:00
Peter Thorson 98171d525e adds C++ namespaces to <cstring> methods references #209 2013-04-20 07:30:52 -05:00
Peter Thorson 4ada7f9b0b updates asio transport endpoint with a few more io_service convenience pass through methods references #211 2013-04-20 07:25:34 -05:00
Peter Thorson 4bc4518df0 Fixes send buffer going out of scope, references #209 2013-04-16 11:26:13 -05:00
Peter Thorson 16f28ea671 adds debug/devel configs 2013-04-12 08:13:28 -05:00
Peter Thorson 894124c042 improves error reporting and adds remote endpoint address to connection open logging 2013-04-12 08:13:18 -05:00
Peter Thorson b12bff7d5d impliments get_remote_endpoint for asio transport 2013-04-12 08:12:45 -05:00
Peter Thorson b38e41e459 some test work on removing uri regex dependency 2013-04-12 08:12:21 -05:00
Peter Thorson 6a37bf3a43 update copyright date 2013-04-12 08:11:48 -05:00
Peter Thorson 5e595d7fe6 adds error logging config settings to clients 2013-04-12 08:11:36 -05:00
Peter Thorson c8fada14f7 adds configurable static logging channels 2013-04-08 09:44:32 -05:00
Peter Thorson 1e97e3dcf5 adds connection client methods for adding subprotocols to the handshake request 2013-04-07 12:18:03 -05:00
Peter Thorson a9b30b6b07 updates processors to support writing handshake requests with subprotocols 2013-04-07 12:17:10 -05:00
Peter Thorson bfbb4a94db adds an example to demonstrate subprotocol negotiation 2013-04-06 15:30:58 -05:00
Peter Thorson 51caf0517e adds support for retrieving headers from the request and response objects 2013-04-06 15:30:35 -05:00
Peter Thorson d47327d2a6 updates readme progress list 2013-04-06 12:12:35 -05:00
Peter Thorson 0c9c121160 moves subprotocol extraction into the processor 2013-04-06 12:10:39 -05:00
Peter Thorson ddd1a95460 refactors hybi00 unit tests to remove duplicate code and use more specific BOOST checks 2013-04-06 12:10:16 -05:00
Peter Thorson 17fcb3f8be adds subprotocol selection to connection 2013-04-06 11:09:41 -05:00
Peter Thorson 8f812aafd5 adds subprotocol processing to handshake processors 2013-04-06 11:09:11 -05:00
Peter Thorson 6d1b956aff adds preliminary server side subprotocol negotiation 2013-04-05 21:10:19 -05:00
Peter Thorson 10db03d710 more work on subprotocol tests 2013-04-05 09:30:15 -05:00
Peter Thorson 9f0649cb91 adds integration tests for the server role 2013-04-05 08:29:17 -05:00
Peter Thorson 8c7c31362d Adds storage and getter for negotiated subprotocol 2013-04-05 08:28:54 -05:00
Peter Thorson 1f450fd034 refactors connection testing to extract more common functionality 2013-04-05 08:28:13 -05:00
Peter Thorson 9ebd169675 fixes a crash when strftime overflowed buffer #205 2013-04-05 07:29:20 -05:00
Peter Thorson c937f71b49 changes extension permessage-compress to permessage-deflate per latest draft spec 2013-04-04 08:18:39 -05:00
Peter Thorson dff7a57e3d updates HTTP parser to use an ordered list of parameters rather than unordered
order matters as far as websocket extension negotation goes
2013-04-04 08:18:05 -05:00
Jonne Nauha df4d7167fd CMake continued: Try to detect g++, clang, windows and osx and setup appropriate defines and build flags. Improve so that each setup can define platform, boost and ssl libs. I tried to copy everything that I could from the scons scripts, probably some of this can be removed (might be automated from cmake already), left todo:s for that. Added building simple examples, more to follow. NOTE: This has only been tested on windows. 2013-04-03 01:56:10 +03:00
Jonne Nauha 75b2497f2b Fix intrusive_ptr template init on windows. The second template argument should probably be removed if its not neccesary for other platforms. I did not find boost documentation for what the second argument actually does, but in the meanwhile ifdeffed so that builds on windows (yes its ugly). Fixes #198 (with a semi hack). 2013-04-03 01:52:22 +03:00
Jonne Nauha 834e3e4fae Fix stdint.hpp for <=VC9. 2013-04-03 01:48:35 +03:00
Jonne Nauha e039a57ee0 CMake prebuild system: Initial commit that has most of the basics down. Only tested on windows atm. TODO: Properly support examples, tests and cpp11 defines to build websocketpp in different setups. 2013-04-01 17:48:47 +03:00
Peter Thorson 73e877f1b8 removes unused headers to avoid confusion references #202 2013-04-01 08:43:43 -05:00
Peter Thorson 7739d4fe72 updates readme 2013-03-31 21:43:22 -05:00
Peter Thorson a8e3ae47dd more readme updates 2013-03-31 21:35:11 -05:00
Peter Thorson dcdeb96c62 readme updates 2013-03-31 21:21:39 -05:00
Peter Thorson f38acd5784 impliments the autobahn echo client spec to allow autobahn test suite to test the client 2013-03-31 21:20:14 -05:00
Peter Thorson 800028d1a9 Changes HTTP response parser behavior to only read response bodies when a content length header is present 2013-03-31 21:16:33 -05:00
Peter Thorson 8587647657 Adds echo_client example 2013-03-31 15:12:57 -05:00
Peter Thorson babe00bc60 adds default client configs 2013-03-31 15:12:09 -05:00
Peter Thorson 35dbc8c8aa adds asio async connect and resolve functionality 2013-03-31 15:11:58 -05:00
Peter Thorson 7a1e9a2f59 fixes connection client bug where it would wait for the HTTP body to be read when there wasn't one 2013-03-31 15:11:39 -05:00
Peter Thorson e7e0c05e9a async_connect requires uri as a parameter now 2013-03-31 15:11:05 -05:00
Peter Thorson 4d78ba6daf fixes typo 2013-03-31 15:10:09 -05:00
Peter Thorson 859689bdf7 removes extraneous debug code 2013-03-31 15:09:59 -05:00
Peter Thorson 439efa0895 adds getter for connection uri part 2 2013-03-31 15:09:42 -05:00
Peter Thorson 2d35726edb adds getter for connection URI 2013-03-31 15:09:17 -05:00
Peter Thorson 7efcf1b047 processors now generate correct random masking keys 2013-03-31 15:08:43 -05:00
Peter Thorson 8a083528a2 finishes client handshake processing 2013-03-31 12:38:47 -05:00
Peter Thorson 13ec782a4f lots of tests 2013-03-31 12:37:59 -05:00
Peter Thorson aec59a1eb9 adds client handshake request generation and server response validation 2013-03-31 12:37:43 -05:00
Peter Thorson 6659846b2e extracts a method for processing handshake keys 2013-03-31 12:37:20 -05:00
Peter Thorson 45198eb4c6 major overhaul to processor unit tests to reduce duplicated code 2013-03-31 10:49:31 -05:00
Peter Thorson c5842802e2 turns on error reporting by default 2013-03-31 09:24:53 -05:00
Peter Thorson f423d051ee adds a new processor error code 2013-03-31 09:24:31 -05:00
Peter Thorson 1475e30930 updates http constants to match the code style of the rest of the library 2013-03-31 09:24:15 -05:00
Peter Thorson 46fb7e6645 adds more logic for reading client handshake responses 2013-03-30 22:41:57 -05:00
Peter Thorson ddddef5444 updates to unit tests to support new connection and processor api that includes RNG 2013-03-30 20:12:37 -05:00
Peter Thorson 67c740e264 adds HTTP request sending to connections 2013-03-30 19:55:40 -05:00
Peter Thorson cb6c396a6b adds handshake request processing to hybi13 and 00 processors 2013-03-30 19:55:04 -05:00
Peter Thorson f494c72006 adds RNG support for endpoints, connections, and processors 2013-03-30 19:54:26 -05:00
Peter Thorson 39c278a871 Adds the ability to detect and use constexpr to the C++11 common header 2013-03-30 17:49:56 -05:00
Peter Thorson b5b2fb9e0a adds default client version to core config 2013-03-30 17:49:35 -05:00
Peter Thorson 837d9eef9f Fixes a member variable that was not initialized before use 2013-03-30 17:48:35 -05:00
Peter Thorson 26d601e7c4 impliments async connect for iostream transport 2013-03-30 07:57:10 -05:00
Peter Thorson 3eef03d31e disables termination of connections that return bad handles 2013-03-30 07:56:50 -05:00
Peter Thorson 924bb1a050 adds client endpoint connection methods 2013-03-30 07:55:05 -05:00
Peter Thorson f2d939ab37 moves transport endpoing base types into the right file 2013-03-30 07:54:36 -05:00
Peter Thorson 8ced80b2ed adds method to retrieve connection handle from iostream connections 2013-03-30 07:53:45 -05:00
Peter Thorson 1ddd43ccb0 client get_connection now sets URI 2013-03-30 07:05:31 -05:00
Peter Thorson 7afcd866a0 adds the ability to set a connection URI outside of the server handshake 2013-03-30 07:05:08 -05:00
Peter Thorson afd5646ca5 adds more client functionality and associated tests 2013-03-28 22:58:54 -05:00
Peter Thorson 0b0106a97f adds is_secure method to transport endpoint 2013-03-28 22:58:39 -05:00
Peter Thorson 4f00240a3b adds preliminary foundations for client support 2013-03-28 22:43:55 -05:00
Peter Thorson e2489001cf adds connection dependencies 2013-03-28 22:43:23 -05:00
Peter Thorson 842c5749fc adds more error codes 2013-03-28 22:43:07 -05:00
Peter Thorson ef857ea831 splits basic logger from log constants 2013-03-28 22:42:51 -05:00
Peter Thorson e54c890b4b adds role unit test modules 2013-03-28 22:41:51 -05:00
Peter Thorson dfd61f8504 updates copyright dates 2013-03-28 22:41:23 -05:00
Peter Thorson 91c1e59ec4 fixes a legacy/hybi00 handshake processing bug on 32 bit x86 2013-03-28 08:23:59 -05:00
Peter Thorson ff04d307e5 Updates readme 2013-03-19 11:29:41 -05:00
Peter Thorson 45092c9633 adds get_io_service to asio transport 2013-03-17 22:57:27 -05:00
Peter Thorson ceea7f7be9 adds additional C++11 library blacklist defines 2013-03-17 22:10:08 -05:00
Peter Thorson 59d7efd1ba updates iostream unit tests 2013-03-17 21:48:43 -05:00
Peter Thorson 16c7d42bed adds boost_system for mutex dependency 2013-03-17 21:46:12 -05:00
Peter Thorson 3822384105 testing new scons g++ config 2013-03-17 21:43:12 -05:00
Peter Thorson f3810fa45e testing with regex common header 2013-03-17 21:41:09 -05:00
Peter Thorson a547ee5a7a adds logging of connection opening results 2013-03-17 20:13:51 -05:00
Peter Thorson 0236f0c722 adds lots of iostream transport unit tests 2013-03-17 18:28:46 -05:00
Peter Thorson d5d5a3330d adds logger test case with real concurrency primitives 2013-03-17 18:28:29 -05:00
Peter Thorson caa828defe adds lots of documentation to iostream transport 2013-03-17 18:27:54 -05:00
Peter Thorson 51633781e3 fixes missing dependency on the logger 2013-03-17 18:27:42 -05:00
Peter Thorson c73df1f3b5 fixes uninitialized m_output_stream variable 2013-03-17 18:27:21 -05:00
Peter Thorson 8e6bdfe42f impliments get_remote_endpoint for iostream transport 2013-03-17 18:26:46 -05:00
Peter Thorson 8e2b424887 fixes handling for zero length reads and reads to zero length buffers 2013-03-17 18:26:16 -05:00
Peter Thorson 940108b2a8 fixes a bug in scatter gather writes with lengths other than 1 2013-03-17 18:25:35 -05:00
Peter Thorson 2584aed3d9 Fixes a bug in back to back iostream reads 2013-03-17 18:24:36 -05:00
Peter Thorson 727328cc9a updates output_stream member variable name to be consistent with WebSocket++ style 2013-03-17 18:24:07 -05:00
Peter Thorson f7c36c46e9 adds new unit testing utility error code 2013-03-17 18:22:27 -05:00
Peter Thorson 7db9817d20 adds more transport documentation 2013-03-17 18:22:02 -05:00
Peter Thorson 56f5472c88 terminate test 2013-03-16 20:59:03 -05:00
Peter Thorson f51a650027 Enables C++11 STL random usage on g++ 2013-03-16 09:02:39 -05:00
Peter Thorson 8e23bbf5b2 adds missing iostream include to random test 2013-03-15 07:56:55 -05:00
Peter Thorson 54ef4db3a1 adds example code for enriched and associative storage 2013-03-10 13:22:53 -05:00
Peter Thorson b3a07d0978 adds overridable connection base class 2013-03-10 08:47:58 -05:00
Peter Thorson 117a76f1f9 updates gitignore 2013-03-08 08:47:45 -06:00
Peter Thorson e5758d7b58 adds code from some of the manual examples 2013-03-08 08:47:28 -06:00
Peter Thorson 213451370d adds an overload of get_con_from_hdl that throws 2013-03-08 08:45:40 -06:00
Peter Thorson 6f34b0f062 adds functional support for std::ref 2013-03-08 08:44:55 -06:00
Peter Thorson ee847e37fb adds more tests for endpoint base classes 2013-03-06 09:10:05 -06:00
Peter Thorson c7e0647626 fixes typo 2013-03-06 08:33:20 -06:00
Peter Thorson 37b1c65904 impliments a user overridable endpoint base class and associated tests 2013-03-06 08:33:11 -06:00
Peter Thorson 40abb49483 adds tests related to request bodies 2013-03-03 17:34:53 -06:00
Peter Thorson a6ce671c56 moves body to parser rather than response since requests can have bodies too. 2013-03-03 17:34:41 -06:00
Peter Thorson aaff9a5f49 makes none the default RNG to avoid requiring random_device in server configs 2013-03-03 17:34:03 -06:00
Peter Thorson 14b2012328 Adds RNG unit tests 2013-03-02 20:47:30 -06:00
Peter Thorson 8b7fe18a85 updates config to add RNG policy 2013-03-02 20:47:23 -06:00
Peter Thorson fbe991d9c2 updates boost random headers 2013-03-02 20:47:11 -06:00
Peter Thorson b373a388e7 completes int_generator policies 2013-03-02 20:47:01 -06:00
Peter Thorson ea4e66e14b additional iostream thread safety 2013-03-02 20:46:36 -06:00
Peter Thorson 8ec273e363 makes a cast explicit 2013-03-02 12:21:27 -06:00
Peter Thorson 45b3ed51ff moves some typedefs to public from protected 2013-03-01 17:28:12 -06:00
Peter Thorson 447c398479 fixes issue where close handler would be called twice 2013-02-24 16:29:53 -06:00
Peter Thorson ce95137ef5 Removes more implicit casts 2013-02-17 07:44:41 -06:00
Peter Thorson 78b52be803 removes force casting from int to bool 2013-02-17 07:13:09 -06:00
Peter Thorson e4f6aafb04 fixes some more visual studio warnings 2013-02-16 12:48:07 -06:00
Peter Thorson 9e19765bdf Fixes MSVC++ C4800 error (converting char to bool) 2013-02-16 12:41:07 -06:00
Peter Thorson 5c01b272fe changes generic to general because generic is a reserved word in visual studio 2013-02-16 12:31:32 -06:00
Peter Thorson e0abafbd71 moves stdint header to common includes 2013-02-08 08:48:39 -06:00
Peter Thorson f529ff2fbc updates connection test build dependency 2013-02-08 08:43:55 -06:00
Peter Thorson ddfc0566f5 adds timer support 2013-02-02 13:10:06 -06:00
Peter Thorson faaa8eb03e initial work on timer support 2013-02-02 10:54:30 -06:00
Peter Thorson 7d76532165 adds some documentation examples 2013-02-02 10:54:30 -06:00
Peter Thorson 6861398648 adds lowercase synonyms for some constants 2013-02-02 10:54:30 -06:00
Peter Thorson 3a92ff981a Merge pull request #183 from eandre/experimental
Added missing 'inline' directives
2013-02-01 15:43:45 -08:00
Peter Thorson 780847bf43 cleans up handle_accept error paths 2013-02-01 09:11:43 -06:00
Peter Thorson 99bc0abffc updates write_flag code to be robust and exception/thread safe 2013-02-01 08:59:57 -06:00
Peter Thorson 8d050767e1 fixes warning 2013-02-01 08:59:35 -06:00
Peter Thorson 45813db04d simplifies sending close frames 2013-02-01 07:55:42 -06:00
Peter Thorson 5ea7ee328e adds state check to connection::close 2013-02-01 07:50:13 -06:00
Peter Thorson 662b4333aa updates close adaptor to proper connection interface 2013-02-01 07:50:03 -06:00
Peter Thorson d0cbb07d5c adds documentation and adaptors for connection::close 2013-02-01 07:41:04 -06:00
Peter Thorson b999051959 adds raw array based send adaptors to endpoint 2013-02-01 07:26:20 -06:00
Peter Thorson 7ffbe8bfd8 moves bad_connection error handling into get_con_from_hdl 2013-02-01 07:25:44 -06:00
Peter Thorson 30134f8545 moves adaptor functions into endpoint_impl 2013-02-01 07:19:11 -06:00
Peter Thorson 30412282ee Updates constructor field order 2013-02-01 07:18:06 -06:00
Peter Thorson aa9644f2a8 fixes typo 2013-02-01 07:13:09 -06:00
Peter Thorson 1bfe86d795 Adds raw array send method to connection 2013-02-01 07:09:02 -06:00
Peter Thorson 5b9afc0309 updates message buffer's set and append payload methods to allow both std::string and raw array input 2013-02-01 07:02:38 -06:00
Peter Thorson 4063440895 temporary logging test changes 2013-01-31 20:30:02 -06:00
Peter Thorson c88cdaf2f4 updates buffer size to a more efficient default 2013-01-31 20:29:08 -06:00
Peter Thorson 6925a68f95 temporary fix for outgoing frame corruption issue #references 179 2013-01-31 08:41:37 -06:00
Peter Thorson 4928f84feb removes un-thread-safe access to cout 2013-01-31 08:40:46 -06:00
Peter Thorson b4903dad0b adds an application level logging level 2013-01-31 08:40:16 -06:00
Peter Thorson 7fe9eb592f refines endpoint logging interface 2013-01-31 08:39:57 -06:00
Peter Thorson 080fd42a0b updates readme 2013-01-27 10:39:55 -06:00
Peter Thorson 1979502a05 adds default logging settings to echo_server and catches more setup exceptions 2013-01-27 10:37:47 -06:00
Peter Thorson fa85811c07 adds some logger tests 2013-01-27 10:37:14 -06:00
Peter Thorson c83f8f485a adds pass through logging adaptor to endpoint 2013-01-27 10:36:19 -06:00
Peter Thorson 0bb60df7fc adds a typedef for logging levels 2013-01-27 10:35:57 -06:00
Peter Thorson 375108aabf Switches cout based logging to logging policy 2013-01-27 08:20:08 -06:00
Peter Thorson 37b6b5fb3c updates tests for logger 2013-01-27 08:19:32 -06:00
Peter Thorson 389e5925d7 splits asio/asio_no_tls up a bit better, adds logging information to configs 2013-01-27 08:19:19 -06:00
Peter Thorson a5d3555f96 whitespace 2013-01-27 08:18:10 -06:00
Andre Eriksson d6edaac02b Added missing 'inline' directives 2013-01-26 09:12:38 +01:00
Peter Thorson 6ab39622e5 adds basic logger class, with tests, and updates configs to include it 2013-01-20 20:24:26 -06:00
Peter Thorson 278909aad6 adds common chrono header 2013-01-20 20:23:47 -06:00
Peter Thorson 295c51c2c5 updates copyright year 2013-01-20 20:23:37 -06:00
Peter Thorson 9b142e3edc adds common/thread header and updates concurrency policies to use it 2013-01-20 20:23:22 -06:00
Peter Thorson 18fef37837 additional work on the broadcast server example 2013-01-20 14:31:54 -06:00
Peter Thorson 44e47267e9 initial work on broadcast_server example 2013-01-20 11:05:30 -06:00
Peter Thorson 290b719048 inlines appropriate functions to work when included in multiple translation units. fixes #178 2013-01-20 09:02:17 -06:00
Peter Thorson 7b2ed75e46 moves network related utility functions into network header 2013-01-20 08:57:51 -06:00
Peter Thorson c76771b323 splits connection test into two translation units 2013-01-20 08:56:38 -06:00
Peter Thorson 9a7631b2da updates endpoint concurrency features 2013-01-20 08:56:11 -06:00
Peter Thorson eb1603177f updates close to include network header 2013-01-10 08:47:16 -06:00
Peter Thorson 931bd92782 adds a common header to organize platform specific network related includes 2013-01-10 08:45:51 -06:00
Peter Thorson 8dbcb79eb5 Update BOOSTROOT build env variable to have consistant naming 2013-01-10 07:08:03 -06:00
Peter Thorson eb706ab7bd disable dev test application by default since it has some extra unwanted dependencies 2013-01-10 07:07:38 -06:00
Peter Thorson e1a333e4f3 include missing header 2013-01-10 07:07:08 -06:00
Peter Thorson cbaee8b4d5 notes about initialization 2013-01-09 09:15:26 -06:00
Peter Thorson f0006864dc updates readme 2013-01-09 09:14:53 -06:00
Peter Thorson 5d7e32fa10 rearranges some stuff 2013-01-09 08:05:43 -06:00
Peter Thorson 43ad5ee342 adds endpoint initialization tests 2013-01-09 07:20:35 -06:00
Peter Thorson 58dd020753 simplifies init_asio signature 2013-01-09 07:20:21 -06:00
Peter Thorson 4edc446b01 fixes a bug cleaning up external io_services 2013-01-09 07:20:05 -06:00
Peter Thorson 107b60dd01 adds endpoint unit test suite 2013-01-09 07:07:01 -06:00
Peter Thorson 7ab2d2c937 removed unnecessary typenames 2013-01-09 07:06:50 -06:00
Peter Thorson 1b83d5e855 better debug printing 2013-01-09 07:06:38 -06:00
Peter Thorson 0e6e41d1c4 adds some more status info to the readme 2013-01-09 06:15:04 -06:00
Peter Thorson a81a266c53 updates TLS code to new handler system 2013-01-09 06:14:39 -06:00
Peter Thorson a3e2e31e91 removes more dead code 2013-01-08 07:49:34 -06:00
Peter Thorson 4f914f8477 updates tests and echo server to new handler interface 2013-01-08 07:48:32 -06:00
Peter Thorson b315f9f684 adds send adaptor functions to endpoints 2013-01-08 07:47:59 -06:00
Peter Thorson a3acc4a1cf removes all old style handler code 2013-01-08 06:43:47 -06:00
Peter Thorson 31cc4af4f4 cleanup 2013-01-08 06:33:06 -06:00
Peter Thorson ef8898afef adds support for message_handler 2013-01-08 06:33:02 -06:00
Peter Thorson 8df37fffbc Updates on_http and validate handlers to use new handler interface 2013-01-07 17:14:29 -06:00
Peter Thorson e7b87e5d54 Updates on_ping, on_pong, and on_pong_timeout handlers to new interface 2013-01-07 16:53:14 -06:00
Peter Thorson 235b567b59 Updates on_close and on_fail to use new handler style 2013-01-07 12:45:09 -06:00
Peter Thorson ebfb8b8e2f Removes handler_interface from all transport code 2013-01-07 12:30:41 -06:00
Peter Thorson 6a4173578e Removes handler_interface types from socket components 2013-01-07 12:27:17 -06:00
Peter Thorson fe582e90e0 updates connection and endpoint to use new component styles 2013-01-07 12:23:21 -06:00
Peter Thorson 8b890d755b Updates asio transport components to new styles 2013-01-07 12:22:46 -06:00
Peter Thorson 052abf06ad Updates asio socket components to new styles 2013-01-07 12:22:16 -06:00
Peter Thorson e339e0f5c6 Updates server role with new component style 2013-01-07 12:21:28 -06:00
Peter Thorson 7aa7f3af80 Updates iostream transport to new component style 2013-01-07 12:20:41 -06:00
Peter Thorson f9c62ee778 Updates configs for new socket API 2013-01-07 12:18:37 -06:00
Peter Thorson f5d4cbe143 updates asio on_tcp_init callback to new api 2013-01-06 10:10:35 -06:00
Peter Thorson ce7b09767a adds documentation 2013-01-06 10:10:18 -06:00
Peter Thorson 2ad049055c updates echo_server to use new interrupt API 2013-01-06 09:59:55 -06:00
Peter Thorson 05f9faebf5 updates interrupt functionality to latest API spec 2013-01-06 09:59:38 -06:00
Peter Thorson 5949c58d2e updates transport accept loop to use connection_hdl and not be a template function 2013-01-06 09:19:08 -06:00
Peter Thorson a48c788ecc asio transport connection now recieves connection hdl 2013-01-06 09:17:09 -06:00
Peter Thorson 9ca476ae22 iostream connection now receives connection hdl 2013-01-06 09:16:49 -06:00
Peter Thorson 7bbfaa78bc connection forwards handle to transport 2013-01-06 09:16:11 -06:00
Peter Thorson db6b32b90b const correctness 2013-01-06 09:15:55 -06:00
Peter Thorson 77422dec25 better qualifies subclass typedefs 2013-01-06 09:15:20 -06:00
Peter Thorson d705a805eb adds ability to retrieve connection_hdl and some docs 2013-01-06 08:53:58 -06:00
Peter Thorson 9253e4fca2 adds a pointer type 2013-01-06 08:50:25 -06:00
Peter Thorson b5a5fd6fe3 adds a pointer type 2013-01-06 08:50:15 -06:00
Peter Thorson 266ceafa26 connects interrupt's error handling 2013-01-06 08:49:55 -06:00
Peter Thorson 21eb1bbd35 adds a convenience function to retrieve connection pointers from handles 2013-01-06 08:49:36 -06:00
Peter Thorson 853c46a0f5 clarifies source of request_type redefinition 2013-01-06 06:45:35 -06:00
Peter Thorson a6002daddd fixes security category make_error_code 2013-01-06 06:43:20 -06:00
Peter Thorson 448588ac5c fixes missing return value 2013-01-06 06:42:55 -06:00
Peter Thorson 2af6ccb7a7 Adds initial readme 2013-01-06 06:12:59 -06:00
Peter Thorson f10f8a4ce0 Initial commit from private 0.3 repository 2013-01-06 06:09:15 -06:00
Peter Thorson 5809440f1a Updates multithreaded non-forked listen methods to not prematurely close the endpoint. references #168 2013-01-04 07:06:54 -06:00
Peter Thorson 4799525445 removes endpoint state change that breaks multi-threaded servers references #168 2013-01-04 06:28:44 -06:00
Peter Thorson 0c4d239aeb fixes formatting 2012-12-19 06:45:46 -06:00
Peter Thorson 43970572f5 version bump 2012-12-19 06:36:28 -06:00
Peter Thorson 6a1dccc8cb corrects an infinite loop when the acceptor is closed in thread pool mode references #168 2012-12-19 06:26:28 -06:00
Peter Thorson 6aa11a7fac Updates user agent/version string 2012-12-11 07:45:20 -06:00
Peter Thorson 0318700c00 m_requested_subprotocols wasn't getting populated. fixes #155
Thank you to robagar for finding this bug and jeffjcrowe for supplying
a patch
2012-12-11 07:07:25 -06:00
Peter Thorson 27a6d6f4d3 Close acceptor on stop_listen. fixes #161 2012-12-11 06:53:43 -06:00
Peter Thorson ce1c1d3a76 removes unnecessary check fixes #163 2012-12-11 06:42:50 -06:00
Peter Thorson 1c8ba9954e Adjusts ordering guarantees on message sending references #149 2012-10-12 07:56:05 -05:00
Peter Thorson 52ce31bea4 updates the order of endpoint and handler construction #references 147 2012-10-12 06:36:23 -05:00
Peter Thorson 47a3c060ee Revert "Fix Compiler Warning on using std::copy: no point using STL routines inside low-level C-style code"
This reverts commit 5dfe48b043.
2012-10-12 06:31:18 -05:00
Peter Thorson d80d9afd88 preliminary work on a fix to the ARM aliasing issues 2012-10-12 06:29:42 -05:00
Peter Thorson 25322aac0d adds missing virtual destructor 2012-10-12 06:29:42 -05:00
Peter Thorson 10ac9c41ec removes unused varaible from wsperf 2012-10-12 06:29:42 -05:00
Peter Thorson 492ada4788 updates SConstruct compile flags for posix and darwin 2012-10-12 06:29:41 -05:00
Peter Thorson b73f1526b6 Merge pull request #148 from NNemec/master
Various small changes of general interest
2012-10-12 04:29:12 -07:00
Norbert Nemec 34a10b0916 split server::listen interface into start_listen and stop_listen, allowing the controlling thread to continue running asynchronously. (Legacy interface provided) 2012-10-09 15:08:25 +02:00
Norbert Nemec db0a43a228 Disable warning C4355 for plain.hpp similar to server.hpp (beware: this hides a real design problem) 2012-10-09 14:06:20 +02:00
Norbert Nemec dbdb150021 clarify interface by correct argument names 2012-10-09 14:00:07 +02:00
Norbert Nemec 5dfe48b043 Fix Compiler Warning on using std::copy: no point using STL routines inside low-level C-style code 2012-10-09 13:59:52 +02:00
Norbert Nemec 3e3b5a0bb8 fix compiler issue 2012-10-09 12:15:17 +02:00
Norbert Nemec 54b1931963 Fix compiler issue: boost/cstdint.hpp contains the types inside boost:: namespace. <stdint.h> should be available by default. vcpp2008 has its own workaround. 2012-10-09 12:15:03 +02:00
Norbert Nemec c2f83814dc Update vcpp2008 project files and use common.vsprops for configuring external dependencies (i.e. boost) 2012-10-09 12:11:01 +02:00
Peter Thorson dd9899c34b Adds virtual destructors to handler interfaces fixes #136 2012-09-24 07:47:14 -05:00
Peter Thorson a17a27dd5c updates set_handler to by synchronous fixes #139 2012-09-24 07:41:25 -05:00
Peter Thorson 546846af19 Merge pull request #141 from 422053362/patch-1
Workaround for windows min and max macros with std::min and std::max
2012-09-24 05:12:01 -07:00
422053362 12245fd745 Update src/roles/client.hpp
sometimes it cause error。
 I have check the function "uniform_int_distribution" ,
 the right way to construct is
 boost::random::uniform_int_distribution<>(
                (std::numeric_limits<int32_t>::min)(),
                (std::numeric_limits<int32_t>::max)()
             )
not 
 boost::random::uniform_int_distribution<>(
                std::numeric_limits<int32_t>::min(),
                std::numeric_limits<int32_t>::max()
             )
maybe sometimes the second way would not cause error,but sometimes it dose.so I modified.
2012-09-23 05:33:57 +08:00
Peter Thorson 16aaa00a1c Fixes an issue where http handler callback is called before building the URI #references #118
Thank you ShuminHuang for filing this bug
2012-08-04 09:59:41 -05:00
Peter Thorson 4b3ca1911b Merge pull request #131 from jrosser/fixes
Small fixes for compiling on Ubuntu 12.04
2012-08-04 07:44:12 -07:00
Peter Thorson 925b4cdd68 Merge pull request #124 from oberstet/master
minor thing
2012-08-04 07:36:10 -07:00
Jonathan Rosser 6f0722b04e fix build of fuzzing_client
this seems fairly fundamental - does nothing else use this and fail?
2012-07-31 13:01:04 +01:00
Jonathan Rosser 3ecec05364 fix stress_client warning and compile error 2012-07-31 13:00:53 +01:00
Jonathan Rosser a0040da1d7 add another missing linkage against pthreads 2012-07-31 09:44:27 +01:00
Jonathan Rosser 159b9d3a88 fix missing boost_thread from some examples 2012-07-29 08:47:16 +01:00
Jonathan Rosser b7009335fe fix usage of C99 macros in C++ 2012-07-26 11:29:10 +01:00
Tobias Oberstein 44bacdb323 does away with VC++ warning: C4309 - truncation of constant value 2012-07-18 14:09:39 +02:00
Peter Thorson 3208b1b493 fixes telemetry server bug references #121 2012-07-11 08:47:45 -05:00
Peter Thorson 1f8113bbd6 adds telemetry server example 2012-07-11 08:20:37 -05:00
Peter Thorson 87d76a3995 Fixes a frame read issue with hybi00 references #101 2012-07-10 07:25:27 -05:00
Peter Thorson 84e021e679 updates makefile for wsperf stress test 2012-06-28 06:52:11 -05:00
Peter Thorson 8d9f55ad23 Merge pull request #117 from dasty/master
Just fixing compilation issue for people who use makefile
2012-06-28 04:39:15 -07:00
Peter Thorson 9716a2269c Merge pull request #113 from pmarques/master
Compiler error due to ambiguous methods resolution
2012-06-28 04:36:40 -07:00
Radek Dostal 125142a7d1 $(CXX) linker should not be run for build of object files
Signed-off-by: Radek Dostal <rd@radekdostal.com>
2012-06-18 18:57:51 +02:00
Peter Thorson f78b9df4ad disable file descriptor limits by default to not confuse windows 2012-06-07 13:46:18 -05:00
Peter Thorson 241a28cbd7 javascript reference clients for message_test and stress_test 2012-06-07 13:44:56 -05:00
Peter Thorson 61be3c182c stress_test now supports message sending & stats 2012-06-07 13:44:56 -05:00
Peter Thorson a3b7546d65 Merge pull request #116 from oberstet/master
make win build and warn free
2012-06-07 05:57:20 -07:00
Peter Thorson 0cd1c58505 stress_test parameter parsing 2012-06-07 06:09:24 -05:00
Peter Thorson 674042f576 preliminary support for thousands of connections on darwin and linux 2012-06-07 06:09:02 -05:00
Peter Thorson 0b10e9c0a3 adds extract string support for wscmd 2012-06-07 06:07:42 -05:00
Tobias Oberstein 9838895d39 slight adjust 2012-06-07 12:55:07 +02:00
Tobias Oberstein 19173e9584 some minor things (make win build warn free) 2012-06-07 12:49:55 +02:00
Peter Thorson b58cf53353 some windows fixes 2012-06-05 08:39:08 -05:00
Peter Thorson 2d12256c7c adds handshake delay and test doneness check 2012-06-05 08:26:06 -05:00
Peter Thorson 1d3942622a this can cause crazy runaway reconnects, need to rethink 2012-06-05 08:25:52 -05:00
Peter Thorson 002e75891e adds preliminary stress_test mode to wsperf 2012-06-04 08:47:37 -05:00
Peter Thorson 2f6565565b adds client on_handshake_init callback 2012-06-04 08:47:37 -05:00
Peter Thorson 232fd1ebf6 Merge pull request #115 from beeftaco/master
Updated project and solution files for better Windows compatibility
2012-05-29 04:06:41 -07:00
beeftaco 469c97c7d9 Updated compatibility for VS2010 2012-05-28 11:47:34 -07:00
Patrick F. Marques 8e091853cc Correction of compiler error due to ambiguous "call conversionS" 2012-05-03 10:40:57 +01:00
Peter Thorson 899b7e3bea defines CPP11 friend fix for Visual Studio 2012-04-22 15:22:40 -05:00
Peter Thorson 9ba194a7f9 fixes #103 2012-04-13 08:47:48 -05:00
Peter Thorson e928f4a566 adds preliminary machine readable connection failure information 2012-04-13 08:34:22 -05:00
Peter Thorson 31a9f9a9bc potential fixes for hixie76 handshakes, references #101 2012-04-13 07:38:15 -05:00
Peter Thorson 7875f03f76 adds WS handshake timeout 2012-04-13 07:36:00 -05:00
Peter Thorson 419178dead adds hook for on_handshake_init 2012-04-13 07:35:29 -05:00
Peter Thorson a4bca13636 generic timeout support 2012-04-13 07:34:50 -05:00
Peter Thorson 8d846000bf adds on_tcp_init hook and TLS handshake timeout 2012-04-13 07:34:22 -05:00
Peter Thorson dc3be3d658 adds on_tcp_init hook 2012-04-13 07:34:11 -05:00
Peter Thorson 75ef3defe9 adds header needed on unix 2012-04-13 07:33:52 -05:00
Peter Thorson 0eedb6e8b6 moves JS libraries into "vendor" folder to escape Linguist 2012-04-13 07:33:30 -05:00
Peter Thorson 04f8413f7d Merge pull request #104 from jdale88/master
Compiler fixes for VS2010
2012-04-12 19:25:01 -07:00
Jamie Dale 42afb69ede Compiler fixes for VS2010.
This fixes some errors caused by Windows defining things like min and max, as well as a number of warnings about type conversion, unused parameters, inability to generate assignment operators, and constant conditions.

All type conversions were assumed to be intentional, and static_casts have been added to remove the compiler warnings.

The server code should now build cleanly with level 4 warnings enabled (as used in my project), and the client code should build cleanly with level 3 warnings enabled (as used by the WebSocket++ projects).
2012-04-12 19:31:12 +01:00
Peter Thorson af23ead5fc removes more duplicate javascript libraries 2012-04-10 09:09:07 -05:00
Peter Thorson dc1e432cdf removes second bundled copy of slot 2012-04-10 09:03:11 -05:00
Peter Thorson 7c4c359ef9 disable experimental support for client thread pool by default 2012-04-10 08:54:51 -05:00
Peter Thorson 1512598e3f logging robustness changes 2012-04-10 08:26:23 -05:00
Peter Thorson 9bc3220b5e message processor performance improvements 2012-04-10 08:25:46 -05:00
Peter Thorson 8129787625 to_hex for char* 2012-04-10 08:24:54 -05:00
Peter Thorson 14802c7afc wsperf logging and preliminary stress_test work 2012-04-10 08:24:39 -05:00
Peter Thorson 64156eff9f updates build system files 2012-04-10 08:22:30 -05:00
Peter Thorson 4e7b899dc7 new wsperf module files 2012-04-10 08:21:57 -05:00
Peter Thorson ea19f1e501 masking utility functions and unit tests 2012-04-10 08:21:35 -05:00
Peter Thorson f3fc8a2466 cleans up and documents some hixie 76 issues references #101 2012-04-07 10:15:28 -05:00
Peter Thorson 6c9d814392 fixes #78 2012-04-07 10:06:36 -05:00
Peter Thorson eb79122da9 update Xcode project 2012-04-07 10:03:32 -05:00
Peter Thorson bb2154613c removes some debug code 2012-04-07 10:02:53 -05:00
Peter Thorson 5f3fbc9593 Merge branch 'master' of github.com:zaphoyd/websocketpp 2012-03-28 09:51:05 -05:00
Peter Thorson b2f57039ae fixes user agent header typo, fixes #100 2012-03-28 09:50:26 -05:00
Peter Thorson 0c90670176 fixes wsperf build on g++ 4.6 2012-03-27 08:15:41 -05:00
Peter Thorson b8ddddfe01 masking optimizations off by default 2012-03-25 14:33:00 -05:00
Peter Thorson 0f95459ac4 preliminary masking code performance improvements 2012-03-25 08:40:29 -05:00
Peter Thorson 368a0f3726 fixes mutex support in const methods 2012-03-25 08:39:39 -05:00
Peter Thorson 3017830e77 clean up legacy code 2012-03-23 13:44:24 -05:00
Peter Thorson edf244daf7 better detached connection error handling 2012-03-23 13:44:03 -05:00
Peter Thorson 2109723b34 adds thread pool support to concurrent_server example 2012-03-21 22:46:38 -06:00
Peter Thorson 9348aa4c21 adds thread pool support to server 2012-03-21 22:37:04 -06:00
Peter Thorson 6ca0b49ae0 more concurrency cleanup, misc features 2012-03-21 21:57:58 -06:00
Peter Thorson 517852cd95 adds silent close option 2012-03-21 21:57:20 -06:00
Peter Thorson d20a2f6fef hybi processor silent close frame 2012-03-21 21:56:51 -06:00
Peter Thorson 461fe64242 async handle_read_frame in server 2012-03-21 21:56:23 -06:00
Peter Thorson 892fdd2456 updates defaults 2012-03-21 21:56:01 -06:00
Peter Thorson 3cef677c31 docs and concurrency clean up 2012-03-19 16:20:27 -06:00
Peter Thorson 2f6a014a2e docs and cleanup 2012-03-19 16:19:44 -06:00
Peter Thorson 59efe59466 wrap async calls with strand 2012-03-19 15:53:49 -06:00
Peter Thorson 9d221c6a84 updates some todos 2012-03-19 15:53:17 -06:00
Peter Thorson 60c2f8efb2 lots of new constants 2012-03-19 15:50:11 -06:00
Peter Thorson b5cd8488ce update chat client for new API 2012-03-19 15:49:51 -06:00
Peter Thorson 8e73e436d0 WS++ very fast fail on utf8 fixes 2012-03-18 16:41:54 -05:00
Peter Thorson 14562aa8bc enable angle by default 2012-03-18 16:41:30 -05:00
Peter Thorson ae12a9ee52 C++ style copy and set 2012-03-18 14:33:13 -05:00
Peter Thorson 41cd2ac01e Merge pull request #95 from blindmatrix/76296fe2dd49c55d85f818005ea9bb6901807c79
Fixed compile-time warnings
2012-03-18 11:42:21 -07:00
Sven Almgren 76296fe2dd Fixed broken conversion 2012-03-15 16:15:41 +01:00
Sven Almgren 9cdc8e7009 Merge branch 'master' of https://github.com/zaphoyd/websocketpp 2012-03-15 15:15:50 +01:00
Sven Almgren 6fabf34630 Removed some nonstrict-alias code 2012-03-15 15:15:19 +01:00
Peter Thorson f6fd0f4fb2 Merge pull request #93 from oberstet/master
Build fixes
2012-03-15 06:33:06 -07:00
Tobias Oberstein 09c541185d disable TLS build on Win .. needs OpenSSL dev .. 2012-03-15 14:27:25 +01:00
Tobias Oberstein c6bb4912b2 fix scons build 2012-03-15 14:11:21 +01:00
Peter Thorson 3994731df8 Merge branch 'master' of github.com:zaphoyd/websocketpp 2012-03-15 07:37:31 -05:00
Peter Thorson 6b32481a87 make static library default 2012-03-15 07:36:29 -05:00
Peter Thorson 2fa84a07f0 Merge pull request #92 from blindmatrix/master
Removed extra comma in header (and more stuff)
2012-03-15 05:36:08 -07:00
Sven Almgren 1a0796d315 Removed duplicate variable in assignment (m_state = m_state = X) 2012-03-15 12:57:34 +01:00
Sven Almgren 002b8a2c35 Removed extra comma, as -pedantic complains 2012-03-15 11:56:34 +01:00
Peter Thorson 26462c17d8 new makefile bug fix for static builds 2012-03-14 07:33:11 -05:00
Peter Thorson 4bf1d63741 Merge pull request #89 from blindmatrix/policy-refactor
centralized makefiles for examples
2012-03-14 05:26:59 -07:00
Sven Almgren 36e76ac246 Merged upstream and resolved confilicts 2012-03-14 13:15:01 +01:00
Sven Almgren f085cc63b6 Centralized makefiles for examples 2012-03-14 12:52:55 +01:00
Sven Almgren 844f34bb3a Removed binary from source tree 2012-03-14 12:51:06 +01:00
Peter Thorson 3f7664ab97 Merge pull request #87 from blindmatrix/policy-refactor
Policy refactor: Updates to makefiles
2012-03-14 04:50:29 -07:00
Peter Thorson 35691eca17 adds more scons targets 2012-03-14 06:39:18 -05:00
Sven Almgren 6d206c0e9f Hide generated shared SO files 2012-03-14 12:36:46 +01:00
Sven Almgren 5b9cab14ff Removed quotes from SHARED and BUILD_TYPE defaults 2012-03-14 12:33:51 +01:00
Sven Almgren b985f5aa4b Fixed if-statement for running ldconfig on newer Ubuntu 2012-03-14 12:31:58 +01:00
Peter Thorson 046c2dea91 scons build supports echo_client, chat_server, chat_client 2012-03-14 06:28:10 -05:00
Peter Thorson 6471b95a40 Xcode project update 2012-03-14 06:27:34 -05:00
Peter Thorson 7fca59a99b fixes example server bugs and logging levels 2012-03-14 06:27:28 -05:00
Peter Thorson 576b6e43ad unix makefile updates 2012-03-14 06:27:10 -05:00
Peter Thorson 02dd3f8193 removes legacy files 2012-03-14 06:26:55 -05:00
Sven Almgren f9d21d80b6 Make sure lib-directory exists before copying files on install 2012-03-14 12:09:04 +01:00
Sven Almgren 3d2078c372 Added new variable to specify base of boost library (BOOST_PREFIX) 2012-03-14 11:59:13 +01:00
Peter Thorson a0eeb7fb71 removes legacy code 2012-03-14 05:54:22 -05:00
Peter Thorson 8e2c82e098 connection destructor fix 2012-03-12 10:48:18 -05:00
Peter Thorson f32ddff367 concurrency review part 1 2012-03-12 10:03:54 -05:00
Peter Thorson a3001a4c7c concurrency fixes 2012-03-11 20:42:22 -05:00
Peter Thorson 6380f56384 wsperf blocking mode 2012-03-11 17:02:14 -05:00
Peter Thorson cfc491ffce fixes some concurrency bugs 2012-03-11 13:19:53 -05:00
Peter Thorson a76e662192 reset request coordinator after connection failure 2012-03-11 12:44:38 -05:00
Peter Thorson 3c043a402f log level tweaks 2012-03-11 08:37:05 -05:00
Peter Thorson 294b416ec9 adds wsperf silent mode and client auto-reconnect 2012-03-11 08:26:34 -05:00
Peter Thorson 6e7589787b test_start message indicates which thread will run test 2012-03-11 08:05:14 -05:00
Peter Thorson 46c3a0b29d cleans up concurrent_handler adds num_workers to welcome 2012-03-11 07:55:20 -05:00
Peter Thorson 7c1f9d702e wsperf bug fixes 2012-03-10 18:39:57 -06:00
Peter Thorson 4903edbe30 wsperf won't set a timer when timeout=0 2012-03-10 16:19:37 -06:00
Peter Thorson 338ac2a574 updates wsperf to use library UA constant 2012-03-10 11:22:35 -06:00
Peter Thorson d1b552691a adds websocketpp::USER_AGENT constant 2012-03-10 11:22:25 -06:00
Peter Thorson cedfddd8ed updates wsperf.cfg with new options 2012-03-10 11:21:57 -06:00
Peter Thorson c0fc773071 adds welcome message to wsperf, lots of wsperf cleanup 2012-03-10 11:06:59 -06:00
Peter Thorson 5e8ed9f64f adds welcome message to wsperf, lots of wsperf cleanup 2012-03-10 11:06:22 -06:00
Peter Thorson 7042091a61 adds client mode and program options to wsperf 2012-03-10 09:10:01 -06:00
Peter Thorson 0360e6669a Merge branch 'policy-refactor' of github.com:zaphoyd/websocketpp into policy-refactor 2012-03-09 08:40:00 -06:00
Peter Thorson 6fd7a091e0 update chat_client to new API 2012-03-09 08:34:52 -06:00
Peter Thorson d21df34a87 fixes some client api issues 2012-03-09 08:32:40 -06:00
Peter Thorson ead6f8853c Merge pull request #81 from oberstet/policy-refactor2
Various build things
2012-03-08 10:45:37 -08:00
Tobias Oberstein 16a4ba98b4 refactor build for tree of scons makefiles, fix out of source build, correct target handling 2012-03-08 17:55:13 +01:00
Tobias Oberstein ae2dac32f0 make away warn 2012-03-08 17:15:37 +01:00
Tobias Oberstein 57630721f6 fix newlines at file ends, more aggressive optim. 2012-03-08 17:09:25 +01:00
Tobias Oberstein 48ac9e7042 use std::limits instead of macros, reorder includes, fix build 2012-03-08 16:55:23 +01:00
Tobias Oberstein 95a861c33b merge 2012-03-08 15:39:48 +01:00
Peter Thorson 1d9e0caeb6 adds namespace to network utilities, fixes #80 2012-03-08 08:29:50 -06:00
Peter Thorson a11e66d3f5 scons updates 2012-03-08 07:56:58 -06:00
Peter Thorson f506c185a8 fixes or silences some VCPP warnings 2012-03-08 07:55:41 -06:00
Tobias Oberstein 4c5421e3fa Basically rewrite SConstruct. VC++ builds without warns. Still needs variant dir / targets fixed. 2012-03-07 17:14:21 +01:00
Tobias Oberstein aac25f9532 Fix/silence warnings on vc++ 2012-03-07 15:58:02 +01:00
Tobias Oberstein f4b910d2c3 Merge remote branch 'peter/policy-refactor' into policy-refactor2 2012-03-07 15:47:50 +01:00
Peter Thorson b9fd0d99ad fixes data types for 32 bit systems 2012-03-07 08:37:12 -06:00
Tobias Oberstein 0832ab5e82 make vc build work again 2012-03-07 15:19:07 +01:00
Peter Thorson 69fb256087 some temporary fixes for windows builds 2012-03-07 08:13:46 -06:00
Peter Thorson 9512891f24 missed one ERROR rename in example 2012-03-07 08:01:19 -06:00
Peter Thorson edfb6308e6 updates vcpp2010 project 2012-03-07 08:01:03 -06:00
Peter Thorson accff169d8 experimental scons build file 2012-03-07 08:00:49 -06:00
Peter Thorson 8a5f84dd99 merges Tobias' statistics changes 2012-03-06 20:23:23 -06:00
Peter Thorson c3026e4e93 renames ERROR for better cross platform support 2012-03-06 19:04:43 -06:00
Peter Thorson 322f5116cb finishes wsperf refactoring 2012-03-06 18:55:05 -06:00
Peter Thorson fea76ad02c wsperf refactoring 2012-03-06 09:31:06 -06:00
Peter Thorson 301edcd948 wsperf bug fixes, adds Xcode target 2012-03-06 07:10:40 -06:00
Peter Thorson 133a313b02 better wsperf error message on connection fail 2012-03-05 11:40:49 -06:00
Peter Thorson 6e768d5816 client properly fires on_fail on connection failure references #69 2012-03-05 11:40:29 -06:00
Peter Thorson 0a386077dc removes binaries 2012-03-05 09:50:37 -06:00
Peter Thorson f7e7ad876b machine readable message types 2012-03-05 09:50:07 -06:00
Peter Thorson 3c433c4668 fixes wsperf avg and KBps starting values 2012-03-05 09:44:21 -06:00
Peter Thorson 623d9a1f98 corrected some stdint issues 2012-03-05 09:43:55 -06:00
Peter Thorson 827f8b657f includes token in output, fixes makefile 2012-03-05 09:24:02 -06:00
Peter Thorson 86eeba1124 slight optimization 2012-03-05 08:39:45 -06:00
Peter Thorson 5ff3a6292f adds preliminary wsperf example code 2012-03-05 08:34:42 -06:00
Peter Thorson 7c2e7d31c0 updates fuzzing_client makefile 2012-02-29 08:32:42 -06:00
Peter Thorson 363ff2f736 re-enables 9.1.x and 9.2.x tests in fuzzing client 2012-02-29 06:34:53 -06:00
Peter Thorson 93ac2e0a01 removes old api code 2012-02-29 06:33:43 -06:00
Peter Thorson 986905e80c chat server example updated to latest API 2012-02-24 08:03:47 -06:00
Peter Thorson 3ec229c223 minor echo server updates 2012-02-24 08:03:16 -06:00
Peter Thorson 2fba5ca478 uses union instead of reinterpret_cast 2012-02-24 07:36:29 -06:00
Peter Thorson f0365ba42e masking_key casting fix to resolve aliasing warnings #references 72 2012-02-20 06:56:41 -06:00
Peter Thorson c2cbe7110d newlines at end of all files #references #72 2012-02-20 06:41:09 -06:00
Peter Thorson 9e93420728 adds policy refactor headers to Makefile install. fixes #71 2012-02-20 06:34:53 -06:00
Peter Thorson e94825bb41 adjust listen locking, fixes #66 2012-02-13 07:06:15 -06:00
Peter Thorson 84884ff9cd fixes #55 2012-02-13 06:57:15 -06:00
Peter Thorson eec4882775 example updates 2012-02-13 06:56:58 -06:00
Peter Thorson 1d80eb6a88 ignore binaries 2012-02-13 06:56:47 -06:00
Peter Thorson 5239ce10dc ignore binaries 2012-02-03 19:54:53 -06:00
Peter Thorson 841a9d911d removes binaries 2012-02-03 19:54:15 -06:00
Peter Thorson 6793b61b5d refined and documented the concurrent_server example references #62 2012-02-03 19:53:25 -06:00
Peter Thorson 8271525d4b Adds concurrent_server example 2012-02-03 09:26:08 -06:00
Peter Thorson 5065ff2615 preliminary work on endpoint/connection concurrency support fixes #63 2012-02-03 09:25:56 -06:00
Peter Thorson 30455f985f begins work on endpoint state detection 2012-02-03 07:10:13 -06:00
Peter Thorson 65689610e7 client uses local resolver, fixes #60 2012-02-03 07:08:37 -06:00
Peter Thorson 4e021d1584 adds additional, more flexible, sever listen overloads fixes #59 2012-02-03 07:04:30 -06:00
Peter Thorson e43c6fa6ec adds SIZE_MAX definition 2012-02-02 07:16:14 -06:00
Peter Thorson 7e213d152e preliminary fix for async_write of stack data in server role. references #51 2012-01-31 10:45:29 -06:00
Peter Thorson 7ab7588c28 regex is no longer static, allows multi-threaded uri parsing. Fixes #54 2012-01-31 09:34:46 -06:00
Peter Thorson f1e66bd425 initial fixes for custom logging, references #56 2012-01-31 09:23:07 -06:00
Peter Thorson f501903d36 fixes shared library building 2012-01-31 09:17:57 -06:00
Peter Thorson cdb1beb947 fixes a crash when sending messages to hybi00 clients 2012-01-31 09:14:44 -06:00
Peter Thorson c4cab70702 libstdc++ and libc++ both work now 2012-01-31 09:14:00 -06:00
Peter Thorson 23a2747e04 experimental c++11 build settings 2012-01-31 09:13:02 -06:00
Peter Thorson 011a8f2ced additional experimental c++11 and libc++ support 2012-01-31 09:12:35 -06:00
Peter Thorson 6826a6665c debugging code 2012-01-25 08:56:45 -06:00
Peter Thorson 41412cebd9 some workarounds for a potential libc++ bug 2012-01-25 08:55:54 -06:00
Peter Thorson 67a2cbcbed fixes an async write from stack issue references #51 2012-01-25 08:11:46 -06:00
Peter Thorson 95da9c45c8 preliminary c++11 and libc++ build support 2012-01-25 08:10:37 -06:00
Peter Thorson 6377358c0b experimenting with weak pointers references #53 2012-01-24 21:28:47 -06:00
Peter Thorson f19d11a002 fixes character processing bug when using LLVM libc++ 2012-01-24 09:16:50 -06:00
Peter Thorson 4e6676ccca adds virtual destructors where appropriate 2012-01-24 09:08:54 -06:00
Peter Thorson 02b48a8dbb tweaks echo server default error logging 2012-01-20 08:02:03 -06:00
Peter Thorson 4b06fedd02 initial testing with shared_const_buffer references #51 2012-01-20 08:01:34 -06:00
Peter Thorson 45c67502cb typo 2012-01-20 08:00:37 -06:00
Peter Thorson 3d38726970 updates broadcast server example for new convenience headers 2012-01-20 08:00:10 -06:00
Peter Thorson 23a44d8112 client properly logs successful connections. 2012-01-20 07:23:25 -06:00
Peter Thorson 035e08de11 server error logging additions and fixes 2012-01-20 07:22:35 -06:00
Peter Thorson 6600f91bfa additional client cleanup 2012-01-20 06:41:01 -06:00
Peter Thorson a89cb776a1 improves client connect error handling. Fixes #52 2012-01-20 06:30:22 -06:00
Peter Thorson 100ba9825f updates 9.7/9.8 to better match AutoBahn 0.4.10 2012-01-19 09:30:31 -06:00
Peter Thorson bed6a41c50 updates makefiles for linux 2012-01-19 08:07:43 -06:00
Peter Thorson 64441f6487 adds fail notification to fuzzing client 2012-01-19 08:07:34 -06:00
Peter Thorson 15cd82d1b3 fuzzing client fully implements 9.1.x, 9.2.x, 9.7.x, 9.8.x 2012-01-18 18:19:18 -06:00
Peter Thorson 7cb31d1b2b bugfix 2012-01-18 13:55:52 -06:00
Peter Thorson 4beebe3bc1 fixes a windows/VC++ compile issue, references #50 2012-01-18 07:13:07 -06:00
Peter Thorson 048e57baa5 fixes a crash while closing all connections, references #50 2012-01-18 07:06:59 -06:00
Peter Thorson 5ec97306cf documentation updates 2012-01-17 19:40:47 -06:00
Peter Thorson 01516318d6 updates basic examples to use new convenience typedefs 2012-01-17 09:43:00 -06:00
Peter Thorson 63c50a520b adds convenience typedefs 2012-01-17 09:40:10 -06:00
Peter Thorson 72a80bd87b some fixes for windows compiling references #50 2012-01-17 09:38:51 -06:00
Peter Thorson 5b660a78e5 updates name of ssl.hpp to tls.hpp 2012-01-17 09:35:44 -06:00
Peter Thorson aaf2c7fa0a formatting and documentation fixes 2012-01-16 11:44:32 -06:00
Peter Thorson 656dbfa3ec sets listen limit back to non-debug value
High values leave the server open to DoS attacks.
2012-01-16 11:20:10 -06:00
Peter Thorson 609e6f3eaf better hixie 76 fix 2012-01-16 11:18:16 -06:00
Peter Thorson 4568ad8d40 fixes pixie 76 handshake bug 2012-01-16 11:15:16 -06:00
Peter Thorson 9d422107ab adjusts whitespace 2012-01-16 11:14:51 -06:00
Peter Thorson 2525de2545 changes for compiling on windows fixes #49 2012-01-14 08:23:50 -06:00
Peter Thorson d93eeabc4c updates fuzzing examples for latest policy-refactor build 2012-01-13 08:41:55 -06:00
Peter Thorson e8cd60e3a8 resolves member function name conflict 2012-01-13 08:41:43 -06:00
Peter Thorson a1b5c503b2 removes debugging statement 2012-01-13 08:41:21 -06:00
Peter Thorson befdd002d2 adds close_all(), run(), and stop() methods to endpoint
This is the beginning of more robust support for all of the io_service
operations, run, stop, reset that properly clean up existing
connections. close_all also allows the server to be shut down
gracefully.
2012-01-13 08:19:20 -06:00
Peter Thorson e4a97f6233 server will end accept loop when create_connection returns NULL 2012-01-13 08:17:42 -06:00
Peter Thorson 3523052529 server policy delegates calls to run to endpoint 2012-01-13 08:16:50 -06:00
Peter Thorson 5704270138 adds internal endpoint logging flag 2012-01-13 08:16:14 -06:00
Peter Thorson 6fc8c588ff calling close while a connection is connecting will now abort the connection 2012-01-13 08:15:58 -06:00
Peter Thorson a17a4deb4b normalizes whitespace and sets up gitattributes to preserve fixes #43 fixes #46 2012-01-12 09:57:06 -06:00
Peter Thorson 75a3f8b068 updates gitignore 2012-01-12 09:55:41 -06:00
Peter Thorson 38b5b561e7 cleans up example code 2012-01-11 17:34:23 -06:00
Peter Thorson 00d40215e2 are clear() and resize(0) different? 2012-01-11 12:31:00 -06:00
Peter Thorson c4ca07ace5 bug fixes #47 2012-01-11 12:30:42 -06:00
Peter Thorson 9de65a10d4 very simple speed testing harness 2012-01-11 12:20:51 -06:00
Peter Thorson 1c0e1b0d2b better IPv6 literal URI parsing 2012-01-11 12:20:12 -06:00
Peter Thorson 69716bf4cd ignore binaries 2012-01-11 12:19:33 -06:00
Peter Thorson cd60832468 better IPv6 literal parsing tests 2012-01-11 12:19:20 -06:00
Peter Thorson 0e92bb207a ipv6 and uri parking fixes 2012-01-11 10:12:57 -06:00
Peter Thorson aaf5f51c35 exposes is_server through connection objects 2012-01-08 20:21:47 -06:00
Peter Thorson 83eaf70f57 whitespace issue 2012-01-08 20:21:29 -06:00
Peter Thorson a53a5e3a10 bug fix and process frame api simplification 2012-01-08 20:20:53 -06:00
Peter Thorson 1ecf0a2e6a payload valuation and gcc warning fixes 2012-01-08 20:20:17 -06:00
Peter Thorson 7ef6ea4ee3 updates connection to use control message pool 2012-01-08 20:19:41 -06:00
Peter Thorson 76fc0d6c6f adds a separate message pool for control messages 2012-01-08 20:18:52 -06:00
Peter Thorson 548ea142ff adds to_hex debug utility function 2012-01-08 20:18:24 -06:00
Peter Thorson 12bc3432f4 adds a generic exception class for application errors 2012-01-08 20:17:40 -06:00
Peter Thorson eb88c53d81 updates API version that the stress client uses 2012-01-08 20:17:11 -06:00
Peter Thorson 992456ae42 updates API version used by echo client example 2012-01-08 20:16:52 -06:00
Peter Thorson f6b68fe431 updates API version used by broadcast server example 2012-01-08 20:16:39 -06:00
Peter Thorson 14ada3a3a3 cleans up debugging code 2012-01-06 17:08:59 -06:00
Peter Thorson 93efa1ae97 write queue passes autobahn tests 2012-01-06 15:20:08 -06:00
Peter Thorson 50abd0b426 lots of bug fixes 2012-01-06 12:53:46 -06:00
Peter Thorson fe7a51bb32 intrusive pointer test 2012-01-06 09:35:02 -06:00
Peter Thorson fa7cd63706 work on write queue/flow control 2012-01-03 06:22:42 -06:00
Peter Thorson 3ff8775c1c updates broadcast admn. adds asks, wscmd support 2011-12-28 08:59:25 -06:00
Peter Thorson 17b779a1c4 updates stress client to use wscmd instead on json 2011-12-28 08:58:38 -06:00
Peter Thorson 28c32cf3cf send a scatter gather buffer list instead of string 2011-12-28 08:58:10 -06:00
Peter Thorson 9145a43e47 tabs to spaces 2011-12-28 07:52:10 -06:00
Peter Thorson a848d1dde5 more unfinished header writing work 2011-12-26 11:45:41 -06:00
Peter Thorson f933519e2b unfinished header writing work 2011-12-23 06:09:23 -06:00
Peter Thorson d19ee815b8 unfinished send api work 2011-12-21 17:22:28 -06:00
Peter Thorson 4d03909d58 lots of misc fixes, mostly broadcast server related 2011-12-21 08:23:03 -06:00
Peter Thorson 3405a91e56 begins work on wscommand processing 2011-12-17 08:35:37 -06:00
Peter Thorson 5131f30d5a makefile fixes for ubuntu 2011-12-17 08:34:42 -06:00
Peter Thorson 9c1473ee91 stress client measures handshake speed 2011-12-15 07:02:43 -06:00
Peter Thorson 241985c2ee use nanosleep rather than sleep 2011-12-15 06:47:40 -06:00
Peter Thorson 217a81add8 more efficient broadcast_admin connection counting 2011-12-15 06:47:29 -06:00
Peter Thorson 57fb71d61d ignore unsolicited acks 2011-12-14 20:17:08 -06:00
Peter Thorson 10b28259f5 work on acknowledging broadcasted messages 2011-12-14 19:55:10 -06:00
Peter Thorson 3e9dc3f9df begins work to track broadcast message acks 2011-12-14 15:09:00 -06:00
Peter Thorson 9e14fba2f7 md5_hash_string now works with arbitrary length strings 2011-12-14 15:08:03 -06:00
Peter Thorson 190cf42231 disables expensive debug log statement 2011-12-14 11:18:08 -06:00
Peter Thorson b4afdb44e8 adjusts payload size reserve settings 2011-12-14 09:38:58 -06:00
Peter Thorson b67f1c41b6 misc config defaults and comments 2011-12-13 09:54:36 -06:00
Peter Thorson ebf0fa614c major work on the broadcast admin and stress client 2011-12-11 14:05:08 -06:00
Peter Thorson e7d3879df4 fixes stress client makefile 2011-12-10 11:34:58 -06:00
Peter Thorson a21d2a6be8 better error handling for FD limit detection 2011-12-10 07:29:28 -06:00
Peter Thorson 07cf4c9318 header fixes for warnings 2011-12-10 07:16:13 -06:00
Peter Thorson 47095fb73c stress client takes uri and connection amounts as arguments 2011-12-10 07:16:04 -06:00
Peter Thorson 649bd4ca36 broadcast server now has a javascript admin console 2011-12-10 07:15:43 -06:00
Peter Thorson e6f1ae286f more header rearranging for Ubuntu 2011-12-10 06:10:44 -06:00
Peter Thorson b219344245 header fixes 2011-12-09 20:03:18 -06:00
Peter Thorson 794dcf7b6c removes binaries 2011-12-09 20:00:24 -06:00
Peter Thorson 00a86b572e hack to link on ubuntu 2011-12-09 19:59:31 -06:00
Peter Thorson 730e46d5bf stress client updates to allow using more FDs 2011-12-09 19:28:20 -06:00
Peter Thorson dc55e67052 adds some code to broadcast server to allow it to increase its file descriptor limits on unix systems 2011-12-09 17:54:51 -06:00
Peter Thorson d89beda042 experimental fix for server running out of FDs 2011-12-09 17:54:17 -06:00
Peter Thorson 8c0ffeaf91 fixes for network errors discovered with new connection stress test example 2011-12-09 09:40:15 -06:00
Peter Thorson 0e9b0b99cf restructures fuzzing client to be more generic 2011-12-08 09:25:06 -06:00
Peter Thorson f92a5f5e8b adds set_handler to endpoint and connection 2011-12-08 09:24:47 -06:00
Peter Thorson 0660d4e87a temporary fix for static class constant in uri 2011-12-08 09:23:59 -06:00
Peter Thorson 008732f654 ignore binaries 2011-12-08 09:23:28 -06:00
Peter Thorson 25514a1476 some server fixes, addition of a fuzzing server and client example.
The fuzzing server and client are intended to mimic the Autobahn
versions and implement only the 9.* tests to enable performance testing
of implementations faster than AB
2011-12-07 09:17:38 -06:00
Peter Thorson 689c136298 policy refactor echo client passes all autobahn tests 2011-12-06 22:14:30 -06:00
Peter Thorson 0f5302d400 major work on echo client 2011-12-06 18:15:24 -06:00
Peter Thorson f1a724e0d4 more client work 2011-12-06 08:45:59 -06:00
Peter Thorson 695b8a4d30 adds get_port_str to URI 2011-12-06 08:44:34 -06:00
Peter Thorson efd5b8d8b1 preliminary cleanup for client role 2011-12-05 17:12:06 -06:00
Peter Thorson 14f0fe09f1 begins work on echo client 2011-12-05 14:41:34 -06:00
Peter Thorson f9a13dd5ff updates TLS example to use new read interface 2011-12-04 17:54:08 -06:00
Peter Thorson 51a03e401a tests disabling Nagle 2011-12-04 17:53:06 -06:00
Peter Thorson 7d11168c6b moves legacy files out to legacy folder, updates Xcode project 2011-12-04 09:13:26 -06:00
Peter Thorson b0978aa442 makefile and project updates 2011-12-04 08:44:18 -06:00
Peter Thorson ce9aa352e2 updates echo server example to use new read interface 2011-12-04 08:44:06 -06:00
Peter Thorson a637edd607 re-applies hybi_legacy support to server policy 2011-12-04 08:43:52 -06:00
Peter Thorson 8db1165331 updates connection to new processor read interface 2011-12-04 08:43:29 -06:00
Peter Thorson 42201b6161 updates hybi_legacy processor to new read interface 2011-12-04 08:43:14 -06:00
Peter Thorson b92d5853fb updates hybi processor to new read interface 2011-12-04 08:42:55 -06:00
Peter Thorson 302aaf2799 updates processor read interface 2011-12-04 08:42:25 -06:00
Peter Thorson 8b473530da connection socket policies now provide is_secure method 2011-12-04 08:41:35 -06:00
Peter Thorson 94d412ccc9 variable size and signedness fixes 2011-12-04 08:40:38 -06:00
Peter Thorson 6bbee85106 temporary fix until this file goes away entirely 2011-12-04 08:39:49 -06:00
Peter Thorson e67ec67b4b major restructuring 2011-12-04 08:39:19 -06:00
Peter Thorson 193ca13f93 fixes exceptions, refactors masking 2011-12-04 08:37:56 -06:00
Peter Thorson cc7170ddec fixes md5 bug 2011-12-04 08:28:39 -06:00
Peter Thorson 7b77f77171 changes the type of the URI port consts 2011-12-04 08:10:03 -06:00
Peter Thorson 280d6522be deletes more old files 2011-12-02 08:44:01 -06:00
Peter Thorson 88fb43d799 removes old files 2011-12-02 08:43:25 -06:00
Peter Thorson 991f37298a lots of work on the new read message queue 2011-12-02 08:43:07 -06:00
Peter Thorson b3f06b0cbd preliminary work on performance improvements to the message processing system 2011-12-01 17:55:05 -06:00
Peter Thorson c0887e0f3e updates Xcode project for new echo_server_tls target 2011-12-01 17:54:31 -06:00
Peter Thorson 82ddecd524 removes spurious xcode generated files 2011-12-01 17:54:06 -06:00
Peter Thorson 0c9f2768c7 fixes formatting 2011-12-01 17:52:58 -06:00
Peter Thorson e8fd5f69e4 adjusts some debugging code and fixes the TLS shutdown delay issue 2011-12-01 17:52:43 -06:00
Peter Thorson 9fd0d2f5bd ignore binaries 2011-12-01 17:50:46 -06:00
Peter Thorson fbc506292d splits echo_server example into separate plain and tls versions 2011-11-30 09:16:21 -06:00
Peter Thorson 309f62b273 bug fix - replaces include with forward declaration 2011-11-30 09:15:16 -06:00
Peter Thorson db37cb5278 handler typedef bugfix 2011-11-29 18:05:36 -06:00
Peter Thorson fabe61df86 adds handler and handler_ptr types to endpoint_traits as well as release documentation to entire file 2011-11-29 18:04:02 -06:00
Peter Thorson fb2fa0da94 adds handler data member to connections 2011-11-29 18:03:10 -06:00
Peter Thorson d2984b43da adjusts server handler interface to allow being a base class for endpoint handler 2011-11-29 18:02:41 -06:00
Peter Thorson ae854ca778 updates socket policies to expose handler interfaces, moves TLS context into connection 2011-11-29 18:01:39 -06:00
Peter Thorson 1cf694ec0a updates echo server for new TLS handler interface 2011-11-29 18:00:30 -06:00
Peter Thorson cb0222c06f updates library for new URI api 2011-11-29 09:38:32 -06:00
Peter Thorson 0e71fae008 updates makefiles and Xcode project 2011-11-29 09:38:03 -06:00
Peter Thorson 0b190adc90 Xcode project update 2011-11-29 06:55:30 -06:00
Peter Thorson dffc49cce8 playing around with logging APIs 2011-11-29 06:55:30 -06:00
Peter Thorson 0e0fd97b83 preliminary work to allow specifying custom paths to boost install 2011-11-28 08:40:04 -06:00
Peter Thorson 7d7e8e853a implements new URI processing interface and corrects associated unit tests 2011-11-28 08:39:11 -06:00
Peter Thorson 8e9d08489c corrects connection friend declaration bug 2011-11-28 08:37:09 -06:00
Peter Thorson e848e9bd2b messes with friends 2011-11-19 09:15:55 -06:00
Peter Thorson cb49e04474 many tweaks 2011-11-19 09:05:05 -06:00
Peter Thorson 7a0f9f3073 updates echo_server example 2011-11-19 01:18:28 -06:00
Peter Thorson 221693f975 merges all of the policy-refactor changes into one library. Policy refactor branch now passes all autobahn server tests except a few edge close behavior cases. 2011-11-19 00:52:38 -06:00
Peter Thorson 50efb8f996 moves public connection/session interface into the appropriate places 2011-11-18 08:46:05 -06:00
Peter Thorson 4fbcb13649 removes a bunch of debug code, adds friend setup, adds role specific connection policy, begins work to integrate http parser 2011-11-17 18:08:06 -06:00
Peter Thorson 3c86891ed7 refactors socket interface to use callbacks rather than CRTP 2011-11-17 08:56:19 -06:00
Peter Thorson 14f9f5d764 stupid git stuff 2011-11-16 09:13:59 -06:00
Peter Thorson 25504243d2 splitting out policy refactor into final files and namespaces 2011-11-16 09:06:28 -06:00
Peter Thorson dfb30b157a merge with new ssl and policy code 2011-11-15 20:09:58 -06:00
Peter Thorson d5ea5ed7d7 lots of policy testing 2011-11-15 17:51:44 -06:00
Peter Thorson 1ab2a8191f breaks a bunch of stuff 2011-11-14 09:21:21 -06:00
Peter Thorson 40a42dd637 misc fixes 2011-11-13 20:46:54 -06:00
Peter Thorson 4ed86a7c30 api tweaks, origin and uri detection behaviors. chat server updated for new apis 2011-11-13 07:12:37 -06:00
Peter Thorson 74aa325591 re-adds utf8 validation, passes all autobahn tests except edge close cases (reading invalid wire codes) starts working on chat server example update 2011-11-11 16:21:38 -06:00
Peter Thorson 0767a6ef18 fixes close behavior 2011-11-11 10:32:34 -06:00
Peter Thorson 6df22f5d70 first (partially) working copy of the refactored branch 2011-11-10 20:02:43 -06:00
Peter Thorson 3e7d71c9a1 refactoring 2011-11-10 09:09:36 -06:00
Peter Thorson 24b5ac278c more refactoring 2011-11-09 17:09:24 -06:00
Peter Thorson d2aaec6c78 refactoring to match new interfaces 2011-11-08 17:37:20 -06:00
Peter Thorson 02de3ebcdc sketches out some of the new interfaces 2011-11-08 08:27:00 -06:00
Peter Thorson 2bccdb21cb Adds hybi 00 handshake support, begins work on hybi 00 frame support 2011-11-07 17:28:28 -06:00
Peter Thorson 63eece760e refactors logging 2011-11-07 09:02:42 -06:00
Peter Thorson d6a59f459c http parser and logger work 2011-11-05 11:01:01 -05:00
Peter Thorson 7ff1e6a546 more refactoring! 2011-10-30 09:12:23 -05:00
Peter Thorson d806bea762 more work, compiles and passes tests now 2011-10-30 07:43:59 -05:00
Peter Thorson 95fe9d8966 more work 2011-10-29 12:39:23 -05:00
Peter Thorson 86da9f503c started policy-refactor branch 2011-10-28 17:09:36 -05:00
Peter Thorson b48733747e Merge branch 'master' of https://github.com/zaphoyd/websocketpp 2011-10-28 10:08:47 -05:00
Peter Thorson 67f83351d0 Xcode update 2011-10-28 10:08:44 -05:00
Peter Thorson a119700d67 Merge branch 'master' of github.com:zaphoyd/websocketpp 2011-10-28 09:36:37 -05:00
Peter Thorson 329c6b4d20 Xcode update 2011-10-28 09:36:34 -05:00
Peter Thorson 7ee3fe5653 Merge pull request #40 from zaphoyd/network-streaming
merges Network streaming branch into master
2011-10-28 07:28:52 -07:00
246 changed files with 29438 additions and 8805 deletions
+18
View File
@@ -0,0 +1,18 @@
# Lineendings
*.sln eol=crlf
*.vcproj eol=crlf
*.vcxproj* eol=crfl
# Whitespace rules
# strict (no trailing, no tabs)
*.cpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
*.hpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
*.c whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
*.h whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
# normal (no trailing)
*.sql whitespace=trailing-space,space-before-tab,cr-at-eol
*.txt whitespace=trailing-space,space-before-tab,cr-at-eol
# special files which must ignore whitespace
*.patch whitespace=-trailing-space
+56
View File
@@ -1,3 +1,7 @@
# make .git* files visible to git
!.gitignore
!.gitattributes
.DS_Store
#vim stuff
@@ -6,8 +10,32 @@
*.o
*.so
*.so.?
*.so.?.?.?
*.a
*.dylib
lib/*
# CMake
*.cmake
*.dir
CMakeFiles
INSTALL.*
ZERO_CHECK.*
CMakeCache.txt
install_manifest.txt
# Windows/Visual Studio
*.vcproj*
*.sln
*.suo
*.ncb
*/Debug/*
*/*/Debug/*
*/Release/*
*/*/Release/*
*/RelWithDebInfo/*
*/*/RelWithDebInfo/*
objs_shared/
objs_static/
@@ -22,3 +50,31 @@ libwebsocketpp.dylib.0.1.0
websocketpp.xcodeproj/xcuserdata/*
websocketpp.xcodeproj/project.xcworkspace/xcuserdata/*
policy_based_notes.hpp
examples/echo_server_tls/echo_server_tls
examples/fuzzing_client/fuzzing_client
examples/stress_client/stress_client
examples/broadcast_server_tls/broadcast_server
test/basic/perf
examples/echo_server_tls/echo_server_tls
examples/concurrent_server/concurrent_server
examples/fuzzing_server_tls/fuzzing_server
examples/wsperf/wsperf
.sconsign.dblite
build/
doxygen/
examples/wsperf/wsperf_client
*.out
*.log
+22
View File
@@ -0,0 +1,22 @@
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
env:
global:
- BOOST_INCLUDES=/usr/include
- BOOST_LIBS=/usr/lib
script: scons -j 2 && scons test
branches:
only:
- master
- permessage-deflate
- experimental
- 0.3.x-cmake
notifications:
recipients:
- travis@zaphoyd.com
email:
on_success: change
on_failure: always
+237
View File
@@ -0,0 +1,237 @@
############ Setup project and cmake
# Project name
project (websocketpp)
# Minimum cmake requirement. We should require a quite recent
# cmake for the dependency find macros etc. to be up to date.
cmake_minimum_required (VERSION 2.6)
set (WEBSOCKETPP_MAJOR_VERSION 0)
set (WEBSOCKETPP_MINOR_VERSION 3)
set (WEBSOCKETPP_PATCH_VERSION 0)
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})
set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
if (WIN32 AND NOT CYGWIN)
set (DEF_INSTALL_CMAKE_DIR cmake)
else ()
set (DEF_INSTALL_CMAKE_DIR lib/cmake/websocketpp)
endif ()
set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
# Make relative paths absolute (needed later on)
foreach (p INCLUDE CMAKE)
set (var INSTALL_${p}_DIR)
if (NOT IS_ABSOLUTE "${${var}}")
set (${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif ()
endforeach ()
# Set CMake library search policy
if (COMMAND cmake_policy)
cmake_policy (SET CMP0003 NEW)
cmake_policy (SET CMP0005 NEW)
endif ()
# Disable unnecessary build types
set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "Configurations" FORCE)
# Include our cmake macros
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include (CMakeHelpers)
############ Paths
set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp)
set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR})
set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin)
set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib)
# CMake install step prefix. I assume linux users want the prefix to
# be the default /usr or /usr/local so this is only adjusted on Windows.
# - Windows: Build the INSTALL project in your solution file.
# - Linux/OSX: make install.
if (MSVC)
set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install")
endif ()
############ Build customization
# Override from command line "CMake -D<OPTION>=TRUE/FALSE/0/1/ON/OFF"
option (ENABLE_CPP11 "Build websocketpp with CPP11 features enabled." TRUE)
option (BUILD_EXAMPLES "Build websocketpp examples." FALSE)
option (BUILD_TESTS "Build websocketpp tests." FALSE)
if (BUILD_TESTS OR BUILD_EXAMPLES)
############ Compiler specific setup
set (WEBSOCKETPP_PLATFORM_LIBS "")
set (WEBSOCKETPP_PLATFORM_TSL_LIBS "")
set (WEBSOCKETPP_BOOST_LIBS "")
# VC9 and C++11 reasoning
if (ENABLE_CPP11 AND MSVC AND MSVC90)
message("* Detected Visual Studio 9 2008, disabling C++11 support.")
set (ENABLE_CPP11 FALSE)
endif ()
# Detect clang. Not officially reported by cmake.
execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-v" ERROR_VARIABLE CXX_VER_STDERR)
if ("${CXX_VER_STDERR}" MATCHES ".*clang.*")
set (CMAKE_COMPILER_IS_CLANGXX 1)
endif ()
# C++11 defines
if (ENABLE_CPP11)
add_definitions (-D_WEBSOCKETPP_CPP11_STL_)
endif ()
# Visual studio
if (MSVC)
set (WEBSOCKETPP_BOOST_LIBS system thread regex)
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL /Gy /GF /Ox /Ob2 /Ot /Oi /MP /arch:SSE2 /fp:fast")
set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /INCREMENTAL:NO /OPT:REF /OPT:ICF")
add_definitions (/W3 /wd4996 /wd4995 /wd4355)
add_definitions (-DUNICODE -D_UNICODE)
add_definitions (-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
add_definitions (-DNOMINMAX)
endif ()
# g++
if (CMAKE_COMPILER_IS_GNUCXX)
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
set (WEBSOCKETPP_BOOST_LIBS system thread regex)
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 ()
# Try to detect version. Note: Not tested!
execute_process (COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" STRGREATER "4.4.0")
message("* C++11 support partially enabled due to GCC version ${GCC_VERSION}")
set (WEBSOCKETPP_BOOST_LIBS system thread regex)
add_definitions (-D_WEBSOCKETPP_NO_CPP11_REGEX_)
endif ()
endif ()
# clang
if (CMAKE_COMPILER_IS_CLANGXX)
if (NOT APPLE)
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
else()
set (WEBSOCKETPP_PLATFORM_LIBS pthread)
endif()
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
set (WEBSOCKETPP_BOOST_LIBS system thread regex)
set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x -stdlib=libc++") # todo: is libc++ really needed here?
if (NOT APPLE)
add_definitions (-DNDEBUG -Wall -Wno-padded) # todo: should we use CMAKE_C_FLAGS for these?
endif ()
endif ()
# OSX, can override above.
if (APPLE)
add_definitions (-DNDEBUG -Wall)
endif ()
if (BUILD_EXAMPLES)
list (APPEND WEBSOCKETPP_BOOST_LIBS random)
endif()
############ Dependencies
# Set BOOST_ROOT env variable or pass with cmake -DBOOST_ROOT=path.
# BOOST_ROOT can also be defined by a previous run from cmake cache.
if (NOT "$ENV{BOOST_ROOT_CPP11}" STREQUAL "")
# Scons documentation for BOOST_ROOT_CPP11:
# "look for optional second boostroot compiled with clang's libc++ STL library
# this prevents warnings/errors when linking code built with two different
# incompatible STL libraries."
file (TO_CMAKE_PATH "$ENV{BOOST_ROOT_CPP11}" BOOST_ROOT)
set (BOOST_ROOT ${BOOST_ROOT} CACHE PATH "BOOST_ROOT dependency path" FORCE)
endif ()
if ("${BOOST_ROOT}" STREQUAL "")
file (TO_CMAKE_PATH "$ENV{BOOST_ROOT}" BOOST_ROOT)
# Cache BOOST_ROOT for runs that do not define $ENV{BOOST_ROOT}.
set (BOOST_ROOT ${BOOST_ROOT} CACHE PATH "BOOST_ROOT dependency path" FORCE)
endif ()
message ("* Configuring Boost")
message (STATUS "-- Using BOOST_ROOT")
message (STATUS " " ${BOOST_ROOT})
if (MSVC)
set (Boost_USE_MULTITHREADED TRUE)
set (Boost_USE_STATIC_LIBS TRUE)
else ()
set (Boost_USE_MULTITHREADED FALSE)
set (Boost_USE_STATIC_LIBS FALSE)
endif ()
set (Boost_FIND_REQUIRED TRUE)
set (Boost_FIND_QUIETLY TRUE)
set (Boost_DEBUG FALSE)
set (Boost_USE_MULTITHREADED TRUE)
set (Boost_ADDITIONAL_VERSIONS "1.39.0" "1.40.0" "1.41.0" "1.42.0" "1.43.0" "1.44.0" "1.46.1") # todo: someone who knows better spesify these!
find_package (Boost 1.39.0 COMPONENTS "${WEBSOCKETPP_BOOST_LIBS}")
if (Boost_FOUND)
# Boost is a project wide global dependency.
include_directories (${Boost_INCLUDE_DIRS})
link_directories (${Boost_LIBRARY_DIRS})
# Pretty print status
message (STATUS "-- Include Directories")
foreach (include_dir ${Boost_INCLUDE_DIRS})
message (STATUS " " ${include_dir})
endforeach ()
message (STATUS "-- Library Directories")
foreach (library_dir ${Boost_LIBRARY_DIRS})
message (STATUS " " ${library_dir})
endforeach ()
message (STATUS "-- Libraries")
foreach (boost_lib ${Boost_LIBRARIES})
message (STATUS " " ${boost_lib})
endforeach ()
message ("")
else ()
message (FATAL_ERROR "Failed to find required dependency: boost")
endif ()
endif()
############ Add projects
# Add main library
add_subdirectory (websocketpp)
# Add examples
if (BUILD_EXAMPLES)
add_subdirectory (examples)
endif ()
# Add tests
if (BUILD_TESTS)
add_subdirectory (test)
endif ()
print_used_build_config()
export (PACKAGE websocketpp)
configure_file (websocketpp-config.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake" @ONLY)
configure_file (websocketpp-configVersion.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake" @ONLY)
# Install the websocketpp-config.cmake and websocketpp-configVersion.cmake
install (FILES
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2011, Peter Thorson. All rights reserved.
Copyright (c) 2013, Peter Thorson. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+1871
View File
File diff suppressed because it is too large Load Diff
-201
View File
@@ -1,201 +0,0 @@
################################################################################
#
# Copyright (c) 2011, 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.
#
# This Makefile was derived from a similar one included in the libjson project
# It's authors were Jonathan Wallace and Bernhard Fluehmann.
objects = websocket_server_session.o websocket_client_session.o websocket_session.o websocket_server.o websocket_client.o websocket_frame.o \
network_utilities.o sha1.o base64.o
libs = -lboost_system -lboost_date_time -lboost_regex -lboost_random
OS=$(shell uname)
# Defaults
ifeq ($(OS), Darwin)
cxxflags_default = -c -O2 -DNDEBUG
else
cxxflags_default = -c -O2 -DNDEBUG
endif
cxxflags_small = -c
cxxflags_debug = -c -g
cxxflags_shared = -f$(PIC)
libname = libwebsocketpp
libname_hdr = websocketpp
libname_debug = $(libname)
suffix_shared = so
suffix_shared_darwin = dylib
suffix_static = a
major_version = 0
minor_version = 1.0
objdir = objs
# Variables
prefix ?= /usr/local
exec_prefix ?= $(prefix)
libdir ?= lib
includedir ?= include
srcdir ?= src
CXX ?= c++
AR ?= ar
PIC ?= PIC
BUILD_TYPE ?= "default"
SHARED ?= "1"
# Internal Variables
inst_path = $(exec_prefix)/$(libdir)
include_path = $(prefix)/$(includedir)
# BUILD_TYPE specific settings
ifeq ($(BUILD_TYPE), debug)
CXXFLAGS = $(cxxflags_debug)
libname := $(libname_debug)
else
CXXFLAGS ?= $(cxxflags_default)
endif
# SHARED specific settings
ifeq ($(SHARED), 1)
ifeq ($(OS), Darwin)
libname_shared = $(libname).$(suffix_shared_darwin)
else
libname_shared = $(libname).$(suffix_shared)
endif
libname_shared_major_version = $(libname_shared).$(major_version)
lib_target = $(libname_shared_major_version).$(minor_version)
objdir := $(objdir)_shared
CXXFLAGS := $(CXXFLAGS) $(cxxflags_shared)
else
lib_target = $(libname).$(suffix_static)
objdir := $(objdir)_static
endif
# Phony targets
.PHONY: all banner installdirs install install_headers clean uninstall \
uninstall_headers
# Targets
all: $(lib_target)
@echo "============================================================"
@echo "Done"
@echo "============================================================"
banner:
@echo "============================================================"
@echo "libwebsocketpp version: "$(major_version).$(minor_version) "target: "$(target) "OS: "$(OS)
@echo "============================================================"
installdirs: banner
mkdir -p $(objdir)
# Libraries
ifeq ($(SHARED),1)
$(lib_target): banner installdirs $(addprefix $(objdir)/, $(objects))
@echo "Link "
cd $(objdir) ; \
if test "$(OS)" = "Darwin" ; then \
$(CXX) -dynamiclib $(libs) -Wl,-dylib_install_name -Wl,$(libname_shared_major_version) -o $@ $(objects) ; \
else \
$(CXX) -shared $(libs) -Wl,-soname,$(libname_shared_major_version) -o $@ $(objects) ; \
fi ; \
mv -f $@ ../
@echo "Link: Done"
else
$(lib_target): banner installdirs $(addprefix $(objdir)/, $(objects))
@echo "Archive"
cd $(objdir) ; \
$(AR) -cvq $@ $(objects) ; \
mv -f $@ ../
@echo "Archive: Done"
endif
# Compile object files
$(objdir)/sha1.o: $(srcdir)/sha1/sha1.cpp
$(CXX) $< -o $@ $(CXXFLAGS)
$(objdir)/base64.o: $(srcdir)/base64/base64.cpp
$(CXX) $< -o $@ $(CXXFLAGS)
$(objdir)/%.o: $(srcdir)/%.cpp
$(CXX) $< -o $@ $(CXXFLAGS)
ifeq ($(SHARED),1)
install: banner install_headers $(lib_target)
@echo "Install shared library"
cp -f ./$(lib_target) $(inst_path)
cd $(inst_path) ; \
ln -sf $(lib_target) $(libname_shared_major_version) ; \
ln -sf $(libname_shared_major_version) $(libname_shared)
ifneq ($(OS),Darwin)
ldconfig
endif
@echo "Install shared library: Done."
else
install: banner install_headers $(lib_target)
@echo "Install static library"
cp -f ./$(lib_target) $(inst_path)
@echo "Install static library: Done."
endif
install_headers: banner
@echo "Install header files"
mkdir -p $(include_path)/$(libname_hdr)
# cp -f ./*.hpp $(include_path)/$(libname_hdr)
cp -f ./$(srcdir)/*.hpp $(include_path)/$(libname_hdr)
mkdir -p $(include_path)/$(libname_hdr)/base64
cp -f ./$(srcdir)/base64/base64.h $(include_path)/$(libname_hdr)/base64
mkdir -p $(include_path)/$(libname_hdr)/sha1
cp -f ./$(srcdir)/sha1/sha1.h $(include_path)/$(libname_hdr)/sha1
chmod -R a+r $(include_path)/$(libname_hdr)
find $(include_path)/$(libname_hdr) -type d -exec chmod a+x {} \;
@echo "Install header files: Done."
clean: banner
@echo "Clean library and object folder"
rm -rf $(objdir)
rm -f $(lib_target)
@echo "Clean library and object folder: Done"
ifeq ($(SHARED),1)
uninstall: banner uninstall_headers
@echo "Uninstall shared library"
rm -f $(inst_path)/$(libname_shared)
rm -f $(inst_path)/$(libname_shared_major_version)
rm -f $(inst_path)/$(lib_target)
ldconfig
@echo "Uninstall shared library: Done"
else
uninstall: banner uninstall_headers
@echo "Uninstall static library"
rm -f $(inst_path)/$(lib_target)
@echo "Uninstall static library: Done"
endif
uninstall_headers: banner
@echo "Uninstall header files"
rm -rf $(include_path)/$(libname)
@echo "Uninstall header files: Done"
+272
View File
@@ -0,0 +1,272 @@
import os, sys, commands
env = Environment(ENV = os.environ)
# figure out a better way to configure this
if os.environ.has_key('CXX'):
env['CXX'] = os.environ['CXX']
if os.environ.has_key('DEBUG'):
env['DEBUG'] = os.environ['DEBUG']
if os.environ.has_key('CXXFLAGS'):
#env['CXXFLAGS'] = os.environ['CXXFLAGS']
env.Append(CXXFLAGS = os.environ['CXXFLAGS'])
if os.environ.has_key('LINKFLAGS'):
#env['LDFLAGS'] = os.environ['LDFLAGS']
env.Append(LINKFLAGS = os.environ['LINKFLAGS'])
## Boost
##
## Note: You need to either set BOOSTROOT to the root of a stock Boost distribution
## or set BOOST_INCLUDES and BOOST_LIBS if Boost comes with your OS distro e.g. and
## needs BOOST_INCLUDES=/usr/include/boost and BOOST_LIBS=/usr/lib like Ubuntu.
##
if os.environ.has_key('BOOSTROOT'):
os.environ['BOOST_ROOT'] = os.environ['BOOSTROOT']
if os.environ.has_key('BOOST_ROOT'):
env['BOOST_INCLUDES'] = os.environ['BOOST_ROOT']
env['BOOST_LIBS'] = os.path.join(os.environ['BOOST_ROOT'], 'stage', 'lib')
elif os.environ.has_key('BOOST_INCLUDES') and os.environ.has_key('BOOST_LIBS'):
env['BOOST_INCLUDES'] = os.environ['BOOST_INCLUDES']
env['BOOST_LIBS'] = os.environ['BOOST_LIBS']
else:
raise SCons.Errors.UserError, "Neither BOOST_ROOT, nor BOOST_INCLUDES + BOOST_LIBS was set!"
if os.environ.has_key('WSPP_ENABLE_CPP11'):
env['WSPP_ENABLE_CPP11'] = True
else:
env['WSPP_ENABLE_CPP11'] = False
boost_linkshared = False
def boostlibs(libnames,localenv):
if localenv['PLATFORM'].startswith('win'):
# Win/VC++ supports autolinking. nothing to do.
# http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#auto-linking
return []
else:
libs = []
prefix = localenv['SHLIBPREFIX'] if boost_linkshared else localenv['LIBPREFIX']
suffix = localenv['SHLIBSUFFIX'] if boost_linkshared else localenv['LIBSUFFIX']
for name in libnames:
lib = File(os.path.join(localenv['BOOST_LIBS'], '%sboost_%s%s' % (prefix, name, suffix)))
libs.append(lib)
return libs
if env['PLATFORM'].startswith('win'):
env.Append(CPPDEFINES = ['WIN32',
'NDEBUG',
'WIN32_LEAN_AND_MEAN',
'_WIN32_WINNT=0x0600',
'_CONSOLE',
'BOOST_TEST_DYN_LINK',
'NOMINMAX',
'_WEBSOCKETPP_CPP11_MEMORY_',
'_WEBSOCKETPP_CPP11_FUNCTIONAL_'])
arch_flags = '/arch:SSE2'
opt_flags = '/Ox /Oi /fp:fast'
warn_flags = '/W3 /wd4996 /wd4995 /wd4355'
env['CCFLAGS'] = '%s /EHsc /GR /GS- /MD /nologo %s %s' % (warn_flags, arch_flags, opt_flags)
env['LINKFLAGS'] = '/INCREMENTAL:NO /MANIFEST /NOLOGO /OPT:REF /OPT:ICF /MACHINE:X86'
elif env['PLATFORM'] == 'posix':
if env.has_key('DEBUG'):
env.Append(CCFLAGS = ['-g', '-O0'])
else:
env.Append(CPPDEFINES = ['NDEBUG'])
env.Append(CCFLAGS = ['-O1', '-fomit-frame-pointer'])
env.Append(CCFLAGS = ['-Wall'])
#env['LINKFLAGS'] = ''
elif env['PLATFORM'] == 'darwin':
if env.has_key('DEBUG'):
env.Append(CCFLAGS = ['-g', '-O0'])
else:
env.Append(CPPDEFINES = ['NDEBUG'])
env.Append(CCFLAGS = ['-O1', '-fomit-frame-pointer'])
env.Append(CCFLAGS = ['-Wall'])
#env['LINKFLAGS'] = ''
if env['PLATFORM'].startswith('win'):
#env['LIBPATH'] = env['BOOST_LIBS']
pass
else:
env['LIBPATH'] = ['/usr/lib',
'/usr/local/lib'] #, env['BOOST_LIBS']
# Compiler specific warning flags
if env['CXX'].startswith('g++'):
#env.Append(CCFLAGS = ['-Wconversion'])
env.Append(CCFLAGS = ['-Wcast-align'])
elif env['CXX'].startswith('clang++'):
#env.Append(CCFLAGS = ['-Wcast-align'])
#env.Append(CCFLAGS = ['-Wglobal-constructors'])
#env.Append(CCFLAGS = ['-Wconversion'])
env.Append(CCFLAGS = ['-Wno-padded'])
# Wpadded
# Wsign-conversion
platform_libs = []
tls_libs = []
tls_build = False
if env['PLATFORM'] == 'posix':
platform_libs = ['pthread', 'rt']
tls_libs = ['ssl', 'crypto']
tls_build = True
elif env['PLATFORM'] == 'darwin':
tls_libs = ['ssl', 'crypto']
tls_build = True
elif env['PLATFORM'].startswith('win'):
# Win/VC++ supports autolinking. nothing to do.
pass
## Append WebSocket++ path
env.Append(CPPPATH = ['#'])
##### Set up C++11 environment
polyfill_libs = [] # boost libraries used as drop in replacements for incomplete
# C++11 STL implementations
env_cpp11 = env.Clone ()
if env_cpp11['CXX'].startswith('g++'):
# TODO: check g++ version
# g++ STL lacks support for <regex>
GCC_VERSION = commands.getoutput(env_cpp11['CXX'] + ' -dumpversion')
if GCC_VERSION > "4.4.0":
print "C++11 build environment partially enabled"
env_cpp11.Append(WSPP_CPP11_ENABLED = "true",CXXFLAGS = ['-std=c++0x'],TOOLSET = ['g++'],CPPDEFINES = ['_WEBSOCKETPP_CPP11_STL_','_WEBSOCKETPP_NO_CPP11_REGEX_'])
# libstdc++ does not yet support <regex>
# boost regex is a drop in replacement
polyfill_libs += boostlibs(['regex'],env_cpp11)
else:
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_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
# this prevents warnings/errors when linking code built with two different
# incompatible STL libraries.
if os.environ.has_key('BOOST_ROOT_CPP11'):
env_cpp11['BOOST_INCLUDES'] = os.environ['BOOST_ROOT_CPP11']
env_cpp11['BOOST_LIBS'] = os.path.join(os.environ['BOOST_ROOT_CPP11'], 'stage', 'lib')
elif os.environ.has_key('BOOST_INCLUDES_CPP11') and os.environ.has_key('BOOST_LIBS_CPP11'):
env_cpp11['BOOST_INCLUDES'] = os.environ['BOOST_INCLUDES_CPP11']
env_cpp11['BOOST_LIBS'] = os.environ['BOOST_LIBS_CPP11']
else:
print "C++11 build environment disabled"
# 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['CXX'].startswith('g++') or env['CXX'].startswith('clang'):
env.Append(CPPFLAGS = '-isystem ' + env['BOOST_INCLUDES'])
else:
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'])
else:
env_cpp11.Append(CPPPATH = [env_cpp11['BOOST_INCLUDES']])
env_cpp11.Append(LIBPATH = [env_cpp11['BOOST_LIBS']])
releasedir = 'build/release/'
debugdir = 'build/debug/'
testdir = 'build/test/'
builddir = releasedir
Export('env')
Export('env_cpp11')
Export('platform_libs')
Export('boostlibs')
Export('tls_libs')
Export('polyfill_libs')
## END OF CONFIG !!
## TARGETS:
if not env['PLATFORM'].startswith('win'):
# Unit tests, add test folders with SConscript files to to_test list.
to_test = ['utility','http','logger','random','processors','message_buffer','extension','transport/iostream','transport/asio','roles','endpoint','connection','transport'] #,'http','processors','connection'
for t in to_test:
new_tests = SConscript('#/test/'+t+'/SConscript',variant_dir = testdir + t, duplicate = 0)
for a in new_tests:
new_alias = Alias('test', [a], a.abspath)
AlwaysBuild(new_alias)
# Main test application
#main = SConscript('#/examples/dev/SConscript',variant_dir = builddir + 'dev',duplicate = 0)
# testee_server
testee_server = SConscript('#/examples/testee_server/SConscript',variant_dir = builddir + 'testee_server',duplicate = 0)
# echo_server
echo_server = SConscript('#/examples/echo_server/SConscript',variant_dir = builddir + 'echo_server',duplicate = 0)
# echo_server_tls
if not env['PLATFORM'].startswith('win'):
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',variant_dir = builddir + 'echo_server_tls',duplicate = 0)
# broadcast_server
broadcast_server = SConscript('#/examples/broadcast_server/SConscript',variant_dir = builddir + 'broadcast_server',duplicate = 0)
# echo_client
echo_client = SConscript('#/examples/echo_client/SConscript',variant_dir = builddir + 'echo_client',duplicate = 0)
# utility_client
utility_client = SConscript('#/examples/utility_client/SConscript',variant_dir = builddir + 'utility_client',duplicate = 0)
# subprotocol_server
subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',variant_dir = builddir + 'subprotocol_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)
# telemetry_client
telemetry_client = SConscript('#/examples/telemetry_client/SConscript',variant_dir = builddir + 'telemetry_client',duplicate = 0)
# print_server
print_server = SConscript('#/examples/print_server/SConscript',variant_dir = builddir + 'print_server',duplicate = 0)
#
#wsperf = SConscript('#/examples/wsperf/SConscript',
# variant_dir = builddir + 'wsperf',
# duplicate = 0)
#echo_server = SConscript('#/examples/echo_server/SConscript',
# variant_dir = builddir + 'echo_server',
# duplicate = 0)
#if tls_build:
# echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',
# variant_dir = builddir + 'echo_server_tls',
# duplicate = 0)
#echo_client = SConscript('#/examples/echo_client/SConscript',
# variant_dir = builddir + 'echo_client',
# duplicate = 0)
#chat_client = SConscript('#/examples/chat_client/SConscript',
# variant_dir = builddir + 'chat_client',
# duplicate = 0)
#chat_server = SConscript('#/examples/chat_server/SConscript',
# variant_dir = builddir + 'chat_server',
# duplicate = 0)
#concurrent_server = SConscript('#/examples/concurrent_server/SConscript',
# variant_dir = builddir + 'concurrent_server',
# duplicate = 0)
+16
View File
@@ -0,0 +1,16 @@
0.3.0-alpha2 - 2013-06-09
- Fixes a regression that caused servers being sent two close frames in a row
to end a connection uncleanly. #259
- Fixes a regression that caused spurious frames following a legitimate close
frames to erroneously trigger handlers. #258
- Changes default HTTP response error code when no http_handler is defined from
500/Internal Server Error to 426/Upgrade Required
- Removes timezone from logger timestamp to work around issues with the Windows
implimentation of strftime. Thank you breyed for testing and code. #257
- Switches integer literals to char literals to improve VCPP compatibility.
Thank you breyed for testing and code. #257
- Adds MSVCPP warning suppression for the bundled SHA1 library. Thank you breyed
for testing and code. #257
0.3.0-alpha1 - 2013-06-09
- Initial Release
+74
View File
@@ -0,0 +1,74 @@
# Print build configuration
macro (print_used_build_config)
message ("\n=========== Used Build Configuration =============\n")
message (STATUS "ENABLE_CPP11 = " ${ENABLE_CPP11})
message (STATUS "BUILD_EXAMPLES = " ${BUILD_EXAMPLES})
message (STATUS "BUILD_TESTS = " ${BUILD_TESTS})
message ("")
message (STATUS "WEBSOCKETPP_ROOT = " ${WEBSOCKETPP_ROOT})
message (STATUS "WEBSOCKETPP_BIN = " ${WEBSOCKETPP_BIN})
message (STATUS "WEBSOCKETPP_LIB = " ${WEBSOCKETPP_LIB})
message (STATUS "Install prefix = " ${CMAKE_INSTALL_PREFIX})
message ("")
message (STATUS "WEBSOCKETPP_BOOST_LIBS = ${WEBSOCKETPP_BOOST_LIBS}")
message (STATUS "WEBSOCKETPP_PLATFORM_LIBS = ${WEBSOCKETPP_PLATFORM_LIBS}")
message (STATUS "WEBSOCKETPP_PLATFORM_TSL_LIBS = ${WEBSOCKETPP_PLATFORM_TSL_LIBS}")
message ("")
endmacro ()
# Adds the given folder_name into the source files of the current project.
# Use this macro when your module contains .cpp and .h files in several subdirectories.
# Your sources variable needs to be WSPP_SOURCE_FILES and headers variable WSPP_HEADER_FILES.
macro(add_source_folder folder_name)
file(GLOB H_FILES_IN_FOLDER_${folder_name} ${folder_name}/*.hpp ${folder_name}/*.h)
file(GLOB CPP_FILES_IN_FOLDER_${folder_name} ${folder_name}/*.cpp ${folder_name}/*.c)
source_group("Header Files\\${folder_name}" FILES ${H_FILES_IN_FOLDER_${folder_name}})
source_group("Source Files\\${folder_name}" FILES ${CPP_FILES_IN_FOLDER_${folder_name}})
set(WSPP_HEADER_FILES ${WSPP_HEADER_FILES} ${H_FILES_IN_FOLDER_${folder_name}})
set(WSPP_SOURCE_FILES ${WSPP_SOURCE_FILES} ${CPP_FILES_IN_FOLDER_${folder_name}})
endmacro()
# Initialize target.
macro (init_target NAME)
set (TARGET_NAME ${NAME})
message ("** " ${TARGET_NAME})
# Include our own module path. This makes #include "x.h"
# work in project subfolders to include the main directory headers.
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
endmacro ()
# Build executable for executables
macro (build_executable TARGET_NAME)
set (TARGET_LIB_TYPE "EXECUTABLE")
message (STATUS "-- Build Type:")
message (STATUS " " ${TARGET_LIB_TYPE})
add_executable (${TARGET_NAME} ${ARGN})
include_directories (${WEBSOCKETPP_ROOT} ${WEBSOCKETPP_INCLUDE})
set_target_properties (${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${WEBSOCKETPP_BIN})
set_target_properties (${TARGET_NAME} PROPERTIES DEBUG_POSTFIX d)
endmacro ()
# Finalize target for all types
macro (final_target)
if ("${TARGET_LIB_TYPE}" STREQUAL "EXECUTABLE")
install (TARGETS ${TARGET_NAME}
RUNTIME DESTINATION "bin"
CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES})
endif ()
# install headers, directly from current source dir and look for subfolders with headers
file (GLOB_RECURSE TARGET_INSTALL_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.hpp)
foreach (hppfile ${TARGET_INSTALL_HEADERS})
get_filename_component (currdir ${hppfile} PATH)
install (FILES ${hppfile} DESTINATION "include/${TARGET_NAME}/${currdir}")
endforeach()
endmacro ()
macro (link_boost)
target_link_libraries (${TARGET_NAME} ${Boost_LIBRARIES})
endmacro ()
+52
View File
@@ -0,0 +1,52 @@
#include <set>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
class broadcast_server {
public:
broadcast_server() {
m_server.init_asio();
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
}
void on_open(connection_hdl hdl) {
m_connections.insert(hdl);
}
void on_close(connection_hdl hdl) {
m_connections.erase(hdl);
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
for (auto it : m_connections) {
m_server.send(it,msg);
}
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
server m_server;
con_list m_connections;
};
int main() {
broadcast_server server;
server.run(9002);
}
+65
View File
@@ -0,0 +1,65 @@
#include <functional>
#include <mutex>
#include <set>
#include <thread>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
class count_server {
public:
count_server() : m_count(0) {
m_server.init_asio();
m_server.set_open_handler(bind(&count_server::on_open,this,_1));
m_server.set_close_handler(bind(&count_server::on_close,this,_1));
}
void on_open(connection_hdl hdl) {
std::lock_guard<std::mutex> lock(m_mutex);
m_connections.insert(hdl);
}
void on_close(connection_hdl hdl) {
std::lock_guard<std::mutex> lock(m_mutex);
m_connections.erase(hdl);
}
void count() {
while (1) {
sleep(1);
m_count++;
std::stringstream ss;
ss << m_count;
std::lock_guard<std::mutex> lock(m_mutex);
for (auto it : m_connections) {
m_server.send(it,ss.str(),websocketpp::frame::opcode::text);
}
}
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
int m_count;
server m_server;
con_list m_connections;
std::mutex m_mutex;
};
int main() {
count_server server;
std::thread t(std::bind(&count_server::count,&server));
server.run(9002);
}
+6
View File
@@ -0,0 +1,6 @@
file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
foreach (SUBDIR ${SDIRS})
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt")
add_subdirectory (${SUBDIR})
endif ()
endforeach ()
@@ -0,0 +1,88 @@
#include <iostream>
#include <map>
#include <exception>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
struct connection_data {
int sessionid;
std::string name;
};
class print_server {
public:
print_server() : m_next_sessionid(1) {
m_server.init_asio();
m_server.set_open_handler(bind(&print_server::on_open,this,::_1));
m_server.set_close_handler(bind(&print_server::on_close,this,::_1));
m_server.set_message_handler(bind(&print_server::on_message,this,::_1,::_2));
}
void on_open(connection_hdl hdl) {
connection_data data;
data.sessionid = m_next_sessionid++;
data.name = "";
m_connections[hdl] = data;
}
void on_close(connection_hdl hdl) {
connection_data& data = get_data_from_hdl(hdl);
std::cout << "Closing connection " << data.name
<< " with sessionid " << data.sessionid << std::endl;
m_connections.erase(hdl);
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
connection_data& data = get_data_from_hdl(hdl);
if (data.name == "") {
data.name = msg->get_payload();
std::cout << "Setting name of connection with sessionid "
<< data.sessionid << " to " << data.name << std::endl;
} else {
std::cout << "Got a message from connection " << data.name
<< " with sessionid " << data.sessionid << std::endl;
}
}
connection_data& get_data_from_hdl(connection_hdl hdl) {
auto it = m_connections.find(hdl);
if (it == m_connections.end()) {
// this connection is not in the list. This really shouldn't happen
// and probably means something else is wrong.
throw std::invalid_argument("No data available for session");
}
return it->second;
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
typedef std::map<connection_hdl,connection_data,std::owner_less<connection_hdl>> con_list;
int m_next_sessionid;
server m_server;
con_list m_connections;
};
int main() {
print_server server;
server.run(9002);
}
+23
View File
@@ -0,0 +1,23 @@
## Broadcast 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('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','thread','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,158 @@
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
/*#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>*/
#include <websocketpp/common/thread.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
using websocketpp::lib::thread;
using websocketpp::lib::mutex;
using websocketpp::lib::unique_lock;
using websocketpp::lib::condition_variable;
/* on_open insert connection_hdl into channel
* on_close remove connection_hdl from channel
* on_message queue send to all channels
*/
enum action_type {
SUBSCRIBE,
UNSUBSCRIBE,
MESSAGE
};
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_type type;
websocketpp::connection_hdl hdl;
server::message_ptr msg;
};
class broadcast_server {
public:
broadcast_server() {
// Initialize Asio Transport
m_server.init_asio();
// Register handler callbacks
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
}
void run(uint16_t port) {
// listen on specified port
m_server.listen(port);
// Start the server accept loop
m_server.start_accept();
// Start the ASIO io_service run loop
try {
m_server.run();
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
} catch (websocketpp::lib::error_code e) {
std::cout << e.message() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
void on_open(connection_hdl hdl) {
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_open" << std::endl;
m_actions.push(action(SUBSCRIBE,hdl));
lock.unlock();
m_action_cond.notify_one();
}
void on_close(connection_hdl hdl) {
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_close" << std::endl;
m_actions.push(action(UNSUBSCRIBE,hdl));
lock.unlock();
m_action_cond.notify_one();
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
// queue message up for sending by processing thread
unique_lock<mutex> lock(m_action_lock);
//std::cout << "on_message" << std::endl;
m_actions.push(action(MESSAGE,msg));
lock.unlock();
m_action_cond.notify_one();
}
void process_messages() {
while(1) {
unique_lock<mutex> lock(m_action_lock);
while(m_actions.empty()) {
m_action_cond.wait(lock);
}
action a = m_actions.front();
m_actions.pop();
lock.unlock();
if (a.type == SUBSCRIBE) {
unique_lock<mutex> lock(m_connection_lock);
m_connections.insert(a.hdl);
} else if (a.type == UNSUBSCRIBE) {
unique_lock<mutex> lock(m_connection_lock);
m_connections.erase(a.hdl);
} else if (a.type == MESSAGE) {
unique_lock<mutex> lock(m_connection_lock);
con_list::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
m_server.send(*it,a.msg);
}
} else {
// undefined.
}
}
}
private:
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
server m_server;
con_list m_connections;
std::queue<action> m_actions;
mutex m_action_lock;
mutex m_connection_lock;
condition_variable m_action_cond;
};
int main() {
try {
broadcast_server server;
// Start a thread to run the processing loop
thread t(bind(&broadcast_server::process_messages,&server));
// Run the asio loop with the main thread
server.run(9002);
t.join();
} catch (std::exception & e) {
std::cout << e.what() << std::endl;
}
}
-23
View File
@@ -1,23 +0,0 @@
CFLAGS = -O2
LDFLAGS =
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_thread -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_thread -lboost_date_time -lboost_regex -lboost_random ../../libwebsocketpp.a
endif
chat_client: chat_client.o chat_client_handler.o
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o chat_client
-177
View File
@@ -1,177 +0,0 @@
<!doctype html>
<html>
<head>
<script type="text/javascript" src="jquery-1.6.3.min.js"></script>
</head>
<body>
<script type="text/javascript">
var ws;
var url;
$(document).ready(init);
function init() {
$(document).keypress(function(event) {
if ( event.which == 13 ) {
event.preventDefault();
send();
}
});
}
function connect() {
url = $("#server_url").val();
console.log(url);
if ("WebSocket" in window) {
ws = new WebSocket(url);
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
} else {
chat_message("This Browser does not support WebSockets");
return;
}
ws.onopen = function(e) {
chat_message("A connection to "+url+" has been opened.");
$("#server_url").attr("disabled",true);
$("#toggle_connect").html("Disconnect");
};
ws.onerror = function(e) {
chat_message("An error occured, see console log for more details.");
console.log(e);
};
ws.onclose = function(e) {
chat_message("The connection to "+url+" was closed.");
};
ws.onmessage = function(e) {
var message = JSON.parse(e.data);
if (message.type == "msg") {
chat_message(message.value,message.sender);
} else if (message.type == "participants") {
var o = "<ul>";
for (var p in message.value) {
o += "<li>"+message.value[p]+"</li>";
}
o += "</ul>";
$("#participants").html(o);
}
};
}
function chat_message(message,sender) {
if (arguments.length == 1) {
sender = "";
}
var style;
if (sender == "") {
style = "client";
} else if (sender == "server") {
style = "server";
sender = "["+sender+"]";
} else {
style = "message";
sender = "["+sender+"]";
}
$("#messages").append("<span class='"+style+"'><span class='sender'>"+sender+"</span> <span class='msg'>"+message+"</span></span><br />");
$("#messages").prop({ scrollTop: $("#messages").prop("scrollHeight") });
}
function disconnect() {
ws.close();
$("#server_url").removeAttr("disabled");
$("#toggle_connect").html("Connect");
$("#participants").html("");
}
function toggle_connect() {
if ($("#server_url").attr("disabled") != "disabled") {
connect();
} else {
disconnect();
}
}
function send() {
if (ws === undefined || ws.readyState != 1) {
chat_message("Websocket is not avaliable for writing");
return;
}
ws.send($("#msg").val());
$("#msg").val("");
}
</script>
<style>
body,html {
margin: 0px;
padding: 0px;
height: 100%;
background-color: #999;
font-family: sans-serif;
font-size: 14px;
}
h3 {
}
#controls {
padding: 4px;
float:right;
width: 300px;
}
input {
width: 200px;
}
#messages {
height: 100%;
overflow: auto;
background-color: black;
}
#messages .client {
color: #ccc;
}
#messages .server {
color: yellow;
}
#messages .message {
color: white;
}
</style>
<div id="controls">
<div id="server">
<input type="text" name="server_url" id="server_url" value="ws://thor-websocket.zaphoyd.net:9000/chat" />
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
</div>
<div id="message_input"><input type="text" name="msg" id="msg" value="Hello World!" />
<button onclick="send();">Send</button></div>
<h3>Chat Participants</h3>
<div id="participants"></div>
</div>
<div id="messages"></div>
</body>
</html>
@@ -1,171 +0,0 @@
/*
* Copyright (c) 2011, 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 "chat_client_handler.hpp"
#include <boost/algorithm/string/replace.hpp>
using websocketchat::chat_client_handler;
using websocketpp::client_session_ptr;
void chat_client_handler::on_open(session_ptr s) {
// not sure if anything needs to happen here.
m_session = s;
std::cout << "Successfully connected" << std::endl;
}
void chat_client_handler::on_close(session_ptr s) {
// not sure if anything needs to happen here either.
m_session = client_session_ptr();
std::cout << "client was disconnected" << std::endl;
}
void chat_client_handler::on_message(session_ptr s,const std::string &msg) {
//std::cout << "message from server: " << msg << std::endl;
decode_server_msg(msg);
}
// CLIENT API
// client api methods will be called from outside the io_service.run thread
// they need to be careful to not touch unsyncronized member variables.
void chat_client_handler::send(const std::string &msg) {
if (!m_session) {
std::cerr << "Error: no connected session" << std::endl;
return;
}
m_session->io_service().post(boost::bind(&chat_client_handler::do_send, this, msg));
}
void chat_client_handler::close() {
if (!m_session) {
std::cerr << "Error: no connected session" << std::endl;
return;
}
m_session->io_service().post(boost::bind(&chat_client_handler::do_close,this));
}
// END CLIENT API
void chat_client_handler::do_send(const std::string &msg) {
if (!m_session) {
std::cerr << "Error: no connected session" << std::endl;
return;
}
// check for local commands
if (msg == "/list") {
std::cout << "list all participants" << std::endl;
} else if (msg == "/close") {
do_close();
} else {
m_session->send(msg);
}
}
void chat_client_handler::do_close() {
if (!m_session) {
std::cerr << "Error: no connected session" << std::endl;
return;
}
m_session->close(websocketpp::session::CLOSE_STATUS_GOING_AWAY,"");
}
// {"type":"participants","value":[<participant>,...]}
// {"type":"msg","sender":"<sender>","value":"<msg>" }
void chat_client_handler::decode_server_msg(const std::string &msg) {
// for messages of type participants, erase and rebuild m_participants
// for messages of type msg, print out message
// NOTE: The chat server was written with the intention of the client having a built in
// JSON parser. To keep external dependencies low for this demonstration chat client I am
// parsing the server messages by hand.
std::string::size_type start = 9;
std::string::size_type end;
if (msg.substr(0,start) != "{\"type\":\"") {
// ignore
std::cout << "invalid message" << std::endl;
return;
}
if (msg.substr(start,15) == "msg\",\"sender\":\"") {
// parse message
std::string sender;
std::string message;
start += 15;
end = msg.find("\"",start);
while (end != std::string::npos) {
if (msg[end-1] == '\\') {
sender += msg.substr(start,end-start-1) + "\"";
start = end+1;
end = msg.find("\"",start);
} else {
sender += msg.substr(start,end-start);
start = end;
break;
}
}
if (msg.substr(start,11) != "\",\"value\":\"") {
std::cout << "invalid message" << std::endl;
return;
}
start += 11;
end = msg.find("\"",start);
while (end != std::string::npos) {
if (msg[end-1] == '\\') {
message += msg.substr(start,end-start-1) + "\"";
start = end+1;
end = msg.find("\"",start);
} else {
message += msg.substr(start,end-start);
start = end;
break;
}
}
std::cout << "[" << sender << "] " << message << std::endl;
} else if (msg.substr(start,23) == "participants\",\"value\":[") {
// parse participants
std::cout << "participants message" << std::endl;
} else {
// unknown message type
std::cout << "unknown message" << std::endl;
}
}
@@ -1,94 +0,0 @@
/*
* Copyright (c) 2011, 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 CHAT_CLIENT_HANDLER_HPP
#define CHAT_CLIENT_HANDLER_HPP
// com.zaphoyd.websocketpp.chat protocol
//
// client messages:
// alias [UTF8 text, 16 characters max]
// msg [UTF8 text]
//
// server messages:
// {"type":"msg","sender":"<sender>","value":"<msg>" }
// {"type":"participants","value":[<participant>,...]}
#include <boost/shared_ptr.hpp>
#include "../../src/websocketpp.hpp"
#include "../../src/websocket_connection_handler.hpp"
#include <map>
#include <string>
#include <queue>
using websocketpp::session_ptr;
namespace websocketchat {
class chat_client_handler : public websocketpp::connection_handler {
public:
chat_client_handler() {}
virtual ~chat_client_handler() {}
// ignored for clients?
void validate(session_ptr s) {}
// connection to chat room complete
void on_open(session_ptr s);
// connection to chat room closed
void on_close(session_ptr s);
// got a new message from server
void on_message(session_ptr s,const std::string &msg);
// ignore messages
void on_message(session_ptr s,const std::vector<unsigned char> &data) {}
// CLIENT API
void send(const std::string &msg);
void close();
private:
// Client API internal
void do_send(const std::string &msg);
void do_close();
void decode_server_msg(const std::string &msg);
// list of other chat participants
std::set<std::string> m_participants;
std::queue<std::string> m_msg_queue;
session_ptr m_session;
};
typedef boost::shared_ptr<chat_client_handler> chat_client_handler_ptr;
}
#endif // CHAT_CLIENT_HANDLER_HPP
File diff suppressed because one or more lines are too long
-23
View File
@@ -1,23 +0,0 @@
CFLAGS = -O2
LDFLAGS =
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options ../../libwebsocketpp.a
endif
chat_server: chat_server.o chat.o
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o chat_server
-192
View File
@@ -1,192 +0,0 @@
/*
* Copyright (c) 2011, 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 "chat.hpp"
#include <boost/algorithm/string/replace.hpp>
using websocketchat::chat_server_handler;
using websocketpp::session_ptr;
void chat_server_handler::validate(session_ptr client) {
std::stringstream err;
// We only know about the chat resource
if (client->get_resource() != "/chat") {
err << "Request for unknown resource " << client->get_resource();
throw(websocketpp::handshake_error(err.str(),404));
}
// Require specific origin example
if (client->get_origin() != "http://zaphoyd.com") {
err << "Request from unrecognized origin: " << client->get_origin();
throw(websocketpp::handshake_error(err.str(),403));
}
}
void chat_server_handler::on_open(session_ptr client) {
std::cout << "client " << client << " joined the lobby." << std::endl;
m_connections.insert(std::pair<session_ptr,std::string>(client,get_con_id(client)));
// send user list and signon message to all clients
send_to_all(serialize_state());
client->send(encode_message("server","Welcome, use the /alias command to set a name, /help for a list of other commands."));
send_to_all(encode_message("server",m_connections[client]+" has joined the chat."));
}
void chat_server_handler::on_close(session_ptr client) {
std::map<session_ptr,std::string>::iterator it = m_connections.find(client);
if (it == m_connections.end()) {
// this client has already disconnected, we can ignore this.
// this happens during certain types of disconnect where there is a
// deliberate "soft" disconnection preceeding the "hard" socket read
// fail or disconnect ack message.
return;
}
std::cout << "client " << client << " left the lobby." << std::endl;
const std::string alias = it->second;
m_connections.erase(it);
// send user list and signoff message to all clients
send_to_all(serialize_state());
send_to_all(encode_message("server",alias+" has left the chat."));
}
void chat_server_handler::on_message(session_ptr client,const std::string &msg) {
std::cout << "message from client " << client << ": " << msg << std::endl;
// check for special command messages
if (msg == "/help") {
// print command list
client->send(encode_message("server","avaliable commands:<br />&nbsp;&nbsp;&nbsp;&nbsp;/help - show this help<br />&nbsp;&nbsp;&nbsp;&nbsp;/alias foo - set alias to foo",false));
return;
}
if (msg.substr(0,7) == "/alias ") {
std::string response;
std::string alias;
if (msg.size() == 7) {
response = "You must enter an alias.";
client->send(encode_message("server",response));
return;
} else {
alias = msg.substr(7);
}
response = m_connections[client] + " is now known as "+alias;
// store alias pre-escaped so we don't have to do this replacing every time this
// user sends a message
// escape JSON characters
boost::algorithm::replace_all(alias,"\\","\\\\");
boost::algorithm::replace_all(alias,"\"","\\\"");
// escape HTML characters
boost::algorithm::replace_all(alias,"&","&amp;");
boost::algorithm::replace_all(alias,"<","&lt;");
boost::algorithm::replace_all(alias,">","&gt;");
m_connections[client] = alias;
// set alias
send_to_all(serialize_state());
send_to_all(encode_message("server",response));
return;
}
// catch other slash commands
if (msg[0] == '/') {
client->send(encode_message("server","unrecognized command"));
return;
}
// create JSON message to send based on msg
send_to_all(encode_message(m_connections[client],msg));
}
// {"type":"participants","value":[<participant>,...]}
std::string chat_server_handler::serialize_state() {
std::stringstream s;
s << "{\"type\":\"participants\",\"value\":[";
std::map<session_ptr,std::string>::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); it++) {
s << "\"" << (*it).second << "\"";
if (++it != m_connections.end()) {
s << ",";
}
it--;
}
s << "]}";
return s.str();
}
// {"type":"msg","sender":"<sender>","value":"<msg>" }
std::string chat_server_handler::encode_message(std::string sender,std::string msg,bool escape) {
std::stringstream s;
// escape JSON characters
boost::algorithm::replace_all(msg,"\\","\\\\");
boost::algorithm::replace_all(msg,"\"","\\\"");
// escape HTML characters
if (escape) {
boost::algorithm::replace_all(msg,"&","&amp;");
boost::algorithm::replace_all(msg,"<","&lt;");
boost::algorithm::replace_all(msg,">","&gt;");
}
s << "{\"type\":\"msg\",\"sender\":\"" << sender
<< "\",\"value\":\"" << msg << "\"}";
return s.str();
}
std::string chat_server_handler::get_con_id(session_ptr s) {
std::stringstream endpoint;
endpoint << s->socket().remote_endpoint();
return endpoint.str();
}
void chat_server_handler::send_to_all(std::string data) {
std::map<session_ptr,std::string>::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); it++) {
(*it).first->send(data);
}
}
-83
View File
@@ -1,83 +0,0 @@
/*
* Copyright (c) 2011, 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 CHAT_HPP
#define CHAT_HPP
// com.zaphoyd.websocketpp.chat protocol
//
// client messages:
// alias [UTF8 text, 16 characters max]
// msg [UTF8 text]
//
// server messages:
// {"type":"msg","sender":"<sender>","value":"<msg>" }
// {"type":"participants","value":[<participant>,...]}
#include <boost/shared_ptr.hpp>
#include "../../src/websocketpp.hpp"
#include "../../src/websocket_connection_handler.hpp"
#include <map>
#include <string>
#include <vector>
namespace websocketchat {
class chat_server_handler : public websocketpp::connection_handler {
public:
chat_server_handler() {}
virtual ~chat_server_handler() {}
void validate(websocketpp::session_ptr client);
// add new connection to the lobby
void on_open(websocketpp::session_ptr client);
// someone disconnected from the lobby, remove them
void on_close(websocketpp::session_ptr client);
void on_message(websocketpp::session_ptr client,const std::string &msg);
// lobby will ignore binary messages
void on_message(websocketpp::session_ptr client,
const std::vector<unsigned char> &data) {}
private:
std::string serialize_state();
std::string encode_message(std::string sender,std::string msg,bool escape = true);
std::string get_con_id(websocketpp::session_ptr s);
void send_to_all(std::string data);
// list of outstanding connections
std::map<websocketpp::session_ptr,std::string> m_connections;
};
typedef boost::shared_ptr<chat_server_handler> chat_server_handler_ptr;
}
#endif // CHAT_HPP
-177
View File
@@ -1,177 +0,0 @@
<!doctype html>
<html>
<head>
<script type="text/javascript" src="jquery-1.6.3.min.js"></script>
</head>
<body>
<script type="text/javascript">
var ws;
var url;
$(document).ready(init);
function init() {
$(document).keypress(function(event) {
if ( event.which == 13 ) {
event.preventDefault();
send();
}
});
}
function connect() {
url = $("#server_url").val();
console.log(url);
if ("WebSocket" in window) {
ws = new WebSocket(url);
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
} else {
chat_message("This Browser does not support WebSockets");
return;
}
ws.onopen = function(e) {
chat_message("A connection to "+url+" has been opened.");
$("#server_url").attr("disabled",true);
$("#toggle_connect").html("Disconnect");
};
ws.onerror = function(e) {
chat_message("An error occured, see console log for more details.");
console.log(e);
};
ws.onclose = function(e) {
chat_message("The connection to "+url+" was closed.");
};
ws.onmessage = function(e) {
var message = JSON.parse(e.data);
if (message.type == "msg") {
chat_message(message.value,message.sender);
} else if (message.type == "participants") {
var o = "<ul>";
for (var p in message.value) {
o += "<li>"+message.value[p]+"</li>";
}
o += "</ul>";
$("#participants").html(o);
}
};
}
function chat_message(message,sender) {
if (arguments.length == 1) {
sender = "";
}
var style;
if (sender == "") {
style = "client";
} else if (sender == "server") {
style = "server";
sender = "["+sender+"]";
} else {
style = "message";
sender = "["+sender+"]";
}
$("#messages").append("<span class='"+style+"'><span class='sender'>"+sender+"</span> <span class='msg'>"+message+"</span></span><br />");
$("#messages").prop({ scrollTop: $("#messages").prop("scrollHeight") });
}
function disconnect() {
ws.close();
$("#server_url").removeAttr("disabled");
$("#toggle_connect").html("Connect");
$("#participants").html("");
}
function toggle_connect() {
if ($("#server_url").attr("disabled") != "disabled") {
connect();
} else {
disconnect();
}
}
function send() {
if (ws === undefined || ws.readyState != 1) {
chat_message("Websocket is not avaliable for writing");
return;
}
ws.send($("#msg").val());
$("#msg").val("");
}
</script>
<style>
body,html {
margin: 0px;
padding: 0px;
height: 100%;
background-color: #999;
font-family: sans-serif;
font-size: 14px;
}
h3 {
}
#controls {
padding: 4px;
float:right;
width: 300px;
}
input {
width: 200px;
}
#messages {
height: 100%;
overflow: auto;
background-color: black;
}
#messages .client {
color: #ccc;
}
#messages .server {
color: yellow;
}
#messages .message {
color: white;
}
</style>
<div id="controls">
<div id="server">
<input type="text" name="server_url" id="server_url" value="ws://thor-websocket.zaphoyd.net:9000/chat" />
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
</div>
<div id="message_input"><input type="text" name="msg" id="msg" value="Hello World!" />
<button onclick="send();">Send</button></div>
<h3>Chat Participants</h3>
<div id="participants"></div>
</div>
<div id="messages"></div>
</body>
</html>
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
## Main development example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env_cpp11 = env_cpp11.Clone ()
prgs = []
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system','timer','chrono'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('main', ["main.cpp"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+200
View File
@@ -0,0 +1,200 @@
//#ifndef _WEBSOCKETPP_CPP11_STL_
// #define _WEBSOCKETPP_CPP11_STL_
//#endif
#include <random>
#include <boost/timer/timer.hpp>
#include <websocketpp/config/core.hpp>
//#include <websocketpp/security/none.hpp>
//#include <websocketpp/concurrency/none.hpp>
//#include <websocketpp/concurrency/stl.hpp>
//#include <websocketpp/transport/iostream.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
#include <sstream>
//typedef websocketpp::concurrency::stl concurrency;
//typedef websocketpp::transport::iostream<concurrency> transport;
//typedef websocketpp::server<concurrency,transport> server;
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;
}
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_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_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;
con_msg_man_type::ptr manager(new con_msg_man_type());
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;
std::random_device dev;
key.i = 0x12345678;
double m = 18094238402394.0824923;
/*std::cout << "Some Math" << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < foo; i++) {
m /= 1.001;
}
}*/
std::cout << m << std::endl;
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');
}
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);
}
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 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);
}
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;
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;
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);
}
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;
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;
/*server::handler::ptr h(new handler());
server test_server(h);
server::connection_ptr con;
std::stringstream output;
test_server.register_ostream(&output);
con = test_server.get_connection();
con->start();
//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 input2;
input2 << "messageabc2";
input2 >> *con;
std::stringstream input3;
input3 << "messageabc3";
input3 >> *con;
std::stringstream input4;
input4 << "close";
input4 >> *con;
std::cout << "connection output:" << std::endl;
std::cout << output.str() << std::endl;*/
}
+11
View File
@@ -0,0 +1,11 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (echo_client)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
-23
View File
@@ -1,23 +0,0 @@
CFLAGS = -O2
LDFLAGS =
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_thread -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_thread -lboost_date_time -lboost_regex -lboost_random -lboost_program_options ../../libwebsocketpp.a
endif
echo_client: echo_client.o echo_client_handler.o
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o echo_client
+23
View File
@@ -0,0 +1,23 @@
## Main development example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is available build using that, otherwise use boost
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+71 -79
View File
@@ -1,90 +1,82 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <websocketpp/config/asio_no_tls_client.hpp>
#include "echo_client_handler.hpp"
#include "../../src/websocketpp.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <websocketpp/client.hpp>
#include <iostream>
using boost::asio::ip::tcp;
using namespace websocketecho;
typedef websocketpp::client<websocketpp::config::asio_client> client;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
int case_count = 0;
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
client::connection_ptr con = c->get_con_from_hdl(hdl);
if (con->get_resource() == "/getCaseCount") {
std::cout << "Detected " << msg->get_payload() << " test cases." << std::endl;
case_count = atoi(msg->get_payload().c_str());
} else {
c->send(hdl, msg->get_payload(), msg->get_opcode());
}
}
int main(int argc, char* argv[]) {
std::string uri;
// Create a server endpoint
client echo_client;
/*if (argc != 2) {
std::cout << "Usage: `echo_client test_url`" << std::endl;
} else {
uri = argv[1];
}*/
std::string uri = "ws://localhost:9001";
echo_client_handler_ptr c(new echo_client_handler());
try {
boost::asio::io_service io_service;
websocketpp::client_ptr client(new websocketpp::client(io_service,c));
client->init();
client->set_header("User Agent","WebSocket++/2011-10-27");
client->connect("ws://localhost:9001/getCaseCount");
io_service.run();
std::cout << "case count: " << c->m_case_count << std::endl;
for (int i = 1; i <= c->m_case_count; i++) {
io_service.reset();
client->set_alog_level(websocketpp::ALOG_OFF);
client->set_elog_level(websocketpp::LOG_OFF);
client->init();
client->set_header("User Agent","WebSocket++/2011-10-27");
std::stringstream url;
url << "ws://localhost:9001/runCase?case=" << i << "&agent=\"WebSocket++Snapshot/2011-10-27\"";
client->connect(url.str());
io_service.run();
}
std::cout << "done" << std::endl;
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
if (argc == 2) {
uri = argv[1];
}
return 0;
try {
// We expect there to be a lot of errors, so suppress them
echo_client.clear_access_channels(websocketpp::log::alevel::all);
echo_client.clear_error_channels(websocketpp::log::elevel::all);
// Initialize ASIO
echo_client.init_asio();
// Register our handlers
echo_client.set_message_handler(bind(&on_message,&echo_client,::_1,::_2));
websocketpp::lib::error_code ec;
client::connection_ptr con = echo_client.get_connection(uri+"/getCaseCount", ec);
echo_client.connect(con);
// Start the ASIO io_service run loop
echo_client.run();
std::cout << "case count: " << case_count << std::endl;
for (int i = 1; i <= case_count; i++) {
echo_client.reset();
std::stringstream url;
url << uri << "/runCase?case=" << i << "&agent=WebSocketpp/0.3.0-alpha2";
con = echo_client.get_connection(url.str(), ec);
echo_client.connect(con);
echo_client.run();
}
std::cout << "done" << std::endl;
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
} catch (websocketpp::lib::error_code e) {
std::cout << e.message() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
+10
View File
@@ -0,0 +1,10 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (echo_server)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
-23
View File
@@ -1,23 +0,0 @@
CFLAGS = -O2
LDFLAGS =
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options ../../libwebsocketpp.a
endif
echo_server: echo_server.o echo.o
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o echo_server
+23
View File
@@ -0,0 +1,23 @@
## Main development example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is available build using that, otherwise use boost
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
-94
View File
@@ -1,94 +0,0 @@
<!doctype html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
var ws;
var url;
function connect() {
url = document.getElementById("server_url").value;
console.log(url);
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.<br />";
};
ws.onmessage = function(e) {
document.getElementById("messages").innerHTML += "Server: "+e.data+"<br />";
};
}
function disconnect() {
ws.close();
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();
}
}
function send() {
if (ws === undefined || ws.readyState != 1) {
document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing<br />";
return;
}
ws.send(document.getElementById("msg").value);
document.getElementById("msg").value = "";
}
</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:5000" />
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
</div>
<div id="message_input"><input type="text" name="msg" id="msg" value="Hello World!" />
<button onclick="send();">Send</button></div>
</div>
<div id="messages"></div>
</body>
</html>
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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_ECHO_SERVER_HANDLER_HPP
#define WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
class echo_handler : public server::handler {
void on_message(connection_ptr con, std::string msg) {
con->write(msg);
}
};
#endif // WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
+52 -82
View File
@@ -1,90 +1,60 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <websocketpp/config/asio_no_tls.hpp>
#include "echo.hpp"
#include "../../src/websocketpp.hpp"
#include <boost/asio.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
using boost::asio::ip::tcp;
typedef websocketpp::server<websocketpp::config::asio> server;
int main(int argc, char* argv[]) {
std::string host = "localhost";
short port = 9002;
std::string full_host;
if (argc == 3) {
// TODO: input validation?
host = argv[1];
port = atoi(argv[2]);
}
std::stringstream temp;
temp << host << ":" << port;
full_host = temp.str();
websocketecho::echo_server_handler_ptr echo_handler(new websocketecho::echo_server_handler());
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;
// 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 {
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v6(), port);
websocketpp::server_ptr server(
new websocketpp::server(io_service,endpoint,echo_handler)
);
//server->parse_command_line(argc, argv);
// setup server settings
//server->set_alog_level(websocketpp::ALOG_OFF);
//server->set_elog_level(websocketpp::LOG_OFF);
server->add_host(host);
server->add_host(full_host);
// bump up max message size to maximum since we may be using the echo
// server to test performance and protocol extremes.
server->set_max_message_size(websocketpp::frame::PAYLOAD_64BIT_LIMIT);
// start the server
server->start_accept();
std::cout << "Starting echo server on " << full_host << std::endl;
// start asio
io_service.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
// 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();
// Register our message handler
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
// Listen on port 9002
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
// Start the ASIO io_service run loop
echo_server.run();
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
} catch (websocketpp::lib::error_code e) {
std::cout << e.message() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
## Main development 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('echo_server_tls', ["echo_server_tls.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env.Program('echo_server_tls', ["echo_server_tls.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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_ECHO_SERVER_HANDLER_HPP
#define WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
class echo_handler : public server::handler {
void on_message(connection_ptr con, std::string msg) {
con->write(msg);
}
};
#endif // WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
@@ -0,0 +1,72 @@
#include <websocketpp/config/asio.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
typedef websocketpp::server<websocketpp::config::asio_tls> 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 websocketpp::config::asio::message_type::ptr message_ptr;
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " 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;
}
}
std::string get_password() {
return "test";
}
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
try {
ctx->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::single_dh_use);
ctx->set_password_callback(bind(&get_password));
ctx->use_certificate_chain_file("server.pem");
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
return ctx;
}
int main() {
// Create a server endpoint
server echo_server;
// Initialize 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));
// Listen on port 9002
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
// Start the ASIO io_service run loop
echo_server.run();
}
+58
View File
@@ -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,87 @@
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
struct connection_data {
int sessionid;
std::string name;
};
struct custom_config : public websocketpp::config::asio {
// pull default settings from our core config
typedef websocketpp::config::asio core;
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 core::rng_type rng_type;
typedef core::transport_type transport_type;
typedef core::endpoint_base endpoint_base;
// Set a custom connection_base class
typedef connection_data connection_base;
};
typedef websocketpp::server<custom_config> server;
typedef server::connection_ptr connection_ptr;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
class print_server {
public:
print_server() : m_next_sessionid(1) {
m_server.init_asio();
m_server.set_open_handler(bind(&print_server::on_open,this,::_1));
m_server.set_close_handler(bind(&print_server::on_close,this,::_1));
m_server.set_message_handler(bind(&print_server::on_message,this,::_1,::_2));
}
void on_open(connection_hdl hdl) {
connection_ptr con = m_server.get_con_from_hdl(hdl);
con->sessionid = m_next_sessionid++;
}
void on_close(connection_hdl hdl) {
connection_ptr con = m_server.get_con_from_hdl(hdl);
std::cout << "Closing connection " << con->name
<< " with sessionid " << con->sessionid << std::endl;
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
connection_ptr con = m_server.get_con_from_hdl(hdl);
if (con->name == "") {
con->name = msg->get_payload();
std::cout << "Setting name of connection with sessionid "
<< con->sessionid << " to " << con->name << std::endl;
} else {
std::cout << "Got a message from connection " << con->name
<< " with sessionid " << con->sessionid << std::endl;
}
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
int m_next_sessionid;
server m_server;
};
int main() {
print_server server;
server.run(9002);
}
@@ -0,0 +1,42 @@
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
using websocketpp::lib::ref;
void custom_on_msg(server & s, connection_hdl hdl, server::message_ptr msg) {
std::cout << "Message sent to custom handler" << std::endl;
}
void default_on_msg(server & s, connection_hdl hdl, server::message_ptr msg) {
std::cout << "Message sent to default handler" << std::endl;
if (msg->get_payload() == "upgrade") {
// Upgrade our connection_hdl to a full connection_ptr
server::connection_ptr con = s.get_con_from_hdl(hdl);
// Change the on message handler for this connection only to
// custom_on_mesage
con->set_message_handler(bind(&custom_on_msg,ref(s),::_1,::_2));
std::cout << "Upgrading connection to custom handler" << std::endl;
}
}
int main() {
server s;
s.set_message_handler(bind(&default_on_msg,ref(s),::_1,::_2));
s.init_asio();
s.listen(9002);
s.start_accept();
s.run();
}
+23
View File
@@ -0,0 +1,23 @@
## iostream 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('iostream_server', ["iostream_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('iostream_server', ["iostream_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,91 @@
#include <websocketpp/config/core.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
#include <fstream>
typedef websocketpp::server<websocketpp::config::core> 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;
// Define a callback to handle incoming messages
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());
} else {
s->get_alog().write(websocketpp::log::alevel::app,
"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());
}
}
int main() {
server s;
std::ofstream log;
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);
s.set_access_channels(websocketpp::log::alevel::disconnect);
s.set_access_channels(websocketpp::log::alevel::app);
// Log to a file rather than stdout, as we are using stdout for real
// output
log.open("output.log");
s.get_alog().set_ostream(&log);
s.get_elog().set_ostream(&log);
// print all output to stdout
s.register_ostream(&std::cout);
// Register our message handler
s.set_message_handler(bind(&on_message,&s,::_1,::_2));
server::connection_ptr con = s.get_connection();
con->start();
// C++ iostream's don't support the idea of asynchronous i/o. As such
// there are two input strategies demonstrated here. Buffered I/O will
// read from stdin in chunks until EOF. This works very well for
// replaying canned connections as would be done in automated testing.
//
// If the server is being used live however, assuming input is being
// piped from elsewhere in realtime, this strategy will result in small
// messages being buffered forever. The non-buffered strategy below
// reads characters from stdin one at a time. This is inefficient and
// for more serious uses should be replaced with a platform specific
// asyncronous i/o technique like select, poll, IOCP, etc
bool buffered_io = false;
if (buffered_io) {
std::cin >> *con;
} else {
char a;
while(std::cin.get(a)) {
con->readsome(&a,1);
}
}
} 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;
}
log.close();
}
+23
View File
@@ -0,0 +1,23 @@
## Print 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('print_server', ["print_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+22
View File
@@ -0,0 +1,22 @@
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg) {
std::cout << msg->get_payload() << std::endl;
}
int main() {
server print_server;
print_server.set_message_handler(&on_message);
print_server.init_asio();
print_server.listen(9002);
print_server.start_accept();
print_server.run();
}
@@ -0,0 +1,51 @@
#include <set>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
class broadcast_server {
public:
broadcast_server() {
m_server.init_asio();
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
}
void on_open(connection_hdl hdl) {
m_connections.insert(hdl);
}
void on_close(connection_hdl hdl) {
m_connections.erase(hdl);
}
void on_message(connection_hdl hdl, server::message_ptr msg) {
for (auto it : m_connections) {
m_server.send(it,msg);
}
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
server m_server;
con_list m_connections;
};
int main() {
broadcast_server server;
server.run(9002);
}
+11
View File
@@ -0,0 +1,11 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)
init_target (sip_client)
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
link_boost ()
final_target ()
+22
View File
@@ -0,0 +1,22 @@
Checkout the project from git
At the top level, run cmake:
cmake -G 'Unix Makefiles' \
-D BUILD_EXAMPLES=ON \
-D WEBSOCKETPP_ROOT=/tmp/cm1 \
-D ENABLE_CPP11=OFF .
and then make the example:
make -C examples/sip_client
Now run it:
bin/sip_client ws://ws-server:80
It has been tested against the repro SIP proxy from reSIProcate
http://www.resiprocate.org/WebRTC_and_SIP_Over_WebSockets
+23
View File
@@ -0,0 +1,23 @@
## Main development example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is avaliable build using that, otherwise use boost
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+88
View File
@@ -0,0 +1,88 @@
#include <condition_variable>
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream>
#include <boost/thread/thread.hpp>
typedef websocketpp::client<websocketpp::config::asio_client> client;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
// Create a server endpoint
client sip_client;
bool received;
void on_open(client* c, websocketpp::connection_hdl hdl) {
// now it is safe to use the connection
std::cout << "connection ready" << std::endl;
received=false;
// Send a SIP OPTIONS message to the server:
std::string SIP_msg="OPTIONS sip:carol@chicago.com SIP/2.0\r\nVia: SIP/2.0/WS df7jal23ls0d.invalid;rport;branch=z9hG4bKhjhs8ass877\r\nMax-Forwards: 70\r\nTo: <sip:carol@chicago.com>\r\nFrom: Alice <sip:alice@atlanta.com>;tag=1928301774\r\nCall-ID: a84b4c76e66710\r\nCSeq: 63104 OPTIONS\r\nContact: <sip:alice@pc33.atlanta.com>\r\nAccept: application/sdp\r\nContent-Length: 0\r\n\r\n";
sip_client.send(hdl, SIP_msg.c_str(), websocketpp::frame::opcode::text);
}
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
client::connection_ptr con = sip_client.get_con_from_hdl(hdl);
std::cout << "Received a reply:" << std::endl;
fwrite(msg->get_payload().c_str(), msg->get_payload().size(), 1, stdout);
received=true;
}
int main(int argc, char* argv[]) {
std::string uri = "ws://localhost:9001";
if (argc == 2) {
uri = argv[1];
}
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);
// Initialize ASIO
sip_client.init_asio();
// Register our handlers
sip_client.set_open_handler(bind(&on_open,&sip_client,::_1));
sip_client.set_message_handler(bind(&on_message,&sip_client,::_1,::_2));
websocketpp::lib::error_code ec;
client::connection_ptr con = sip_client.get_connection(uri, ec);
// Specify the SIP subprotocol:
con->add_subprotocol("sip");
sip_client.connect(con);
// Start the ASIO io_service run loop
sip_client.run();
while(!received) {
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
std::cout << "done" << std::endl;
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
} catch (websocketpp::lib::error_code e) {
std::cout << e.message() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
+23
View File
@@ -0,0 +1,23 @@
## Main development example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is available build using that, otherwise use boost
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('subprotocol_server', ["subprotocol_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('subprotocol_server', ["subprotocol_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,52 @@
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
using websocketpp::lib::ref;
bool validate(server & s, connection_hdl hdl) {
server::connection_ptr con = s.get_con_from_hdl(hdl);
std::cout << "Cache-Control: " << con->get_request_header("Cache-Control") << std::endl;
const std::vector<std::string> & subp_requests = con->get_requested_subprotocols();
std::vector<std::string>::const_iterator it;
for (it = subp_requests.begin(); it != subp_requests.end(); ++it) {
std::cout << "Requested: " << *it << std::endl;
}
if (subp_requests.size() > 0) {
con->select_subprotocol(subp_requests[0]);
}
return true;
}
int main() {
try {
server s;
s.set_validate_handler(bind(&validate,ref(s),::_1));
s.init_asio();
s.listen(9005);
s.start_accept();
s.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;
}
}
+23
View File
@@ -0,0 +1,23 @@
## Telemetry client example
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
prgs = []
# if a C++11 environment is available build using that, otherwise use boost
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('telemetry_client', ["telemetry_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('telemetry_client', ["telemetry_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
@@ -0,0 +1,150 @@
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
// This header pulls in the WebSocket++ abstracted thread support that will
// select between boost::thread and std::thread based on how the build system
// is configured.
#include <websocketpp/common/thread.hpp>
/**
* The telemetry client connects to a WebSocket server and sends a message every
* second containing an integer count. This example can be used as the basis for
* programs where a client connects and pushes data for logging, stress/load
* testing, etc.
*/
class telemetry_client {
public:
typedef websocketpp::client<websocketpp::config::asio_client> client;
typedef websocketpp::lib::lock_guard<websocketpp::lib::mutex> scoped_lock;
telemetry_client() : m_open(false),m_done(false) {
// set up access channels to only log interesting things
m_client.clear_access_channels(websocketpp::log::alevel::all);
m_client.set_access_channels(websocketpp::log::alevel::connect);
m_client.set_access_channels(websocketpp::log::alevel::disconnect);
m_client.set_access_channels(websocketpp::log::alevel::app);
// Initialize the Asio transport policy
m_client.init_asio();
// 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));
}
// This method will block until the connection is complete
void run(const std::string & 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;
}
// Grab a handle for this connection so we can talk to it in a thread
// safe manor after the event loop starts.
m_hdl = con->get_handle();
// Queue the connection. No DNS queries or network connections will be
// made until the io_service event loop is run.
m_client.connect(con);
// Create a thread to run the ASIO io_service event loop
websocketpp::lib::thread asio_thread(&client::run, &m_client);
// Create a thread to run the telemetry loop
websocketpp::lib::thread telemetry_thread(&telemetry_client::telemetry_loop,this);
asio_thread.join();
telemetry_thread.join();
}
// The open handler will signal that we are ready to start sending telemetry
void on_open(websocketpp::connection_hdl hdl) {
m_client.get_alog().write(websocketpp::log::alevel::app,
"Connection opened, starting telemetry!");
scoped_lock guard(m_lock);
m_open = true;
}
// The close handler will signal that we should stop sending telemetry
void on_close(websocketpp::connection_hdl hdl) {
m_client.get_alog().write(websocketpp::log::alevel::app,
"Connection closed, stopping telemetry!");
scoped_lock guard(m_lock);
m_done = true;
}
// The fail handler will signal that we should stop sending telemetry
void on_fail(websocketpp::connection_hdl hdl) {
m_client.get_alog().write(websocketpp::log::alevel::app,
"Connection failed, stopping telemetry!");
scoped_lock guard(m_lock);
m_done = true;
}
void telemetry_loop() {
uint64_t count = 0;
std::stringstream val;
websocketpp::lib::error_code ec;
while(1) {
{
scoped_lock guard(m_lock);
// If the connection has been closed, stop generating telemetry
if (m_done) {break;}
// If the connection hasn't been opened yet wait a bit and retry
if (!m_open) {
sleep(1);
continue;
}
}
val.str("");
val << "count is " << count++;
m_client.get_alog().write(websocketpp::log::alevel::app, val.str());
m_client.send(m_hdl,val.str(),websocketpp::frame::opcode::text,ec);
// The most likely error that we will get is that the connection is
// not in the right state. Usually this means we tried to send a
// message to a connection that was closed or in the process of
// closing. While many errors here can be easily recovered from,
// 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());
break;
}
sleep(1);
}
}
private:
client m_client;
websocketpp::connection_hdl m_hdl;
websocketpp::lib::mutex m_lock;
bool m_open;
bool m_done;
};
int main(int argc, char* argv[]) {
telemetry_client c;
std::string uri = "ws://localhost:9002";
if (argc == 2) {
uri = argv[1];
}
c.run(uri);
}
+23
View File
@@ -0,0 +1,23 @@
## Autobahn Testee Server
##
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('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+76
View File
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
typedef websocketpp::server<websocketpp::config::asio> 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;
// Define a callback to handle incoming messages
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
server testee_server;
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();
// Register our message handler
testee_server.set_message_handler(bind(&on_message,&testee_server,::_1,::_2));
// Listen on port 9002
testee_server.listen(9002);
// Start the server accept loop
testee_server.start_accept();
// Start the ASIO io_service run loop
testee_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;
}
}
+24
View File
@@ -0,0 +1,24 @@
## Utility 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('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
Return('prgs')
+126
View File
@@ -0,0 +1,126 @@
/**
* 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_tls_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));
}
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 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;
}
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 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;
}
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;
}
}
+45
View File
@@ -0,0 +1,45 @@
WebSocket++ (0.3.0-alpha1)
==========================
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
============
[![Build Status](https://travis-ci.org/zaphoyd/websocketpp.png)](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
-299
View File
@@ -1,299 +0,0 @@
How to use this library
WebSocket++ is a C++ websocket server library implimented using the Boost Asio networking stack. It is designed to provide a simple interface
Built on Asio's proactor asyncronious event loop.
Building a program using WebSocket++ has two parts
1. Impliment a connection handler.
This is done by subclassing websocketpp::connection_handler. Each websocket connection is attached to a connection handler. The handler impliments the following methods:
validate:
Called after the client handshake is recieved but before the connection is accepted. Allows cookie authentication, origin checking, subprotocol negotiation, etc
connect:
Called when the connection has been established and writes are allowed.
disconnect:
Called when the connection has been disconnected
message: text and binary variants
Called when a new websocket message is recieved.
The handler has access to the following websocket session api:
get_header
returns the value of an HTTP header sent by the client during the handshake
get_request
returns the resource requested by the client in the handshake
set_handler:
pass responsibility for this connection to another connection handler
set_http_error:
reject the connection with a specific HTTP error
add_header
adds an HTTP header to the server handshake
set_subprotocol
selects a subprotocol for the connection
send: text and binary varients
send a websocket message
ping:
send a ping
2. Start Asio's event loop with a TCP endpoint and your connection handler
There are two example programs in the examples directory that demonstrate this use pattern. One is a trivial stateless echo server, the other is a simple web based chat client. Both include example javascript clients. The echo server is suitable for use with automated testing suites such as the Autobahn test suite.
By default, a single connection handler object is used for all connections. If needs require, that default handler can either store per-connection state itself or create new handlers and pass off responsibility for the connection to them.
How to build this library
Build static library
make
Build and install in system include directories
make install
Avaliable flags:
- SHARED=1: build a shared instead of static library.
- DEBUG=1: build library with no optimizations, suitable for debugging. Debug library
is called libwebsocketpp_dbg
- CXX=*: uses * as the c++ compiler instead of system default
Build tested on
- Mac OS X 10.7 with apple gcc 4.2, macports gcc 4.6, apple llvm/clang, boost 1.47
- Fedora 15, gcc 4.6, boost 1.46
- Ubunutu server, gcc, boost 1.42
Outstanding issues
- Acknowledgement details
- Subprotocol negotiation interface
- check draft 14 issues
- session.cpp - add_header. Decide what should happen with multiple calls to
add header with the same key
- multiple headers of the same value
- Better exception model
- closing handshake reason/ error codes?
- tests for opening/closing handshake
- tests for utf8
- utf8 streaming validation
- more easily configurable frame size limit
- Better system of handling server wide defaults (like hosts, frame limits, etc)
To check
- double check bugs in autobahn (sending wrong localhost:9000 header) not
- checking masking in the 9.x tests
Unimplimented features
- SSL
- frame or streaming based api
- client features
- extension negotiation interface
Acknowledgements
- Boost Asio and other libraries
- base64 library
- sha1 library
- htonll discussion
- build/makefile from libjson
- Autobahn test suite
- testing by Keith Brisson
API spec notes
## Server API ##
websocketpp.hpp
create a websocketpp::server_ptr initialized to a new websocketpp::server object
the server constructor will need three things.
- A boost::asio::io_service object to use to manage its async operations
- A boost::asio::ip::tcp::endpoint to listen to for new connections
- An object that impliments the websocketpp::connection_handler interface to provide callback functions (See Handler API)
After construction the server object will be in the initialization state. At this time you can set up server config options either via calling individual set option commands or by loading them in a batch from a config file.
The only required option is that at least one host value must be set. Incoming websocket connections must specify a host value that they wish to connect to and if the server object does not have that host value in it's list of canonical hosts it will reject the connection.
[note about settings that can be changed live?]
Once the server has been configured the way you want, call the start_accept() method. This will add the first async call to your io_service. If your io_service was already running, the server will start accepting connections immediately. If not you will need to call io_service.run() to start it.
Once the server has started it will accept new connections. A new session object will be created for each connection accepted. The session will perform the websocket handshake and if it is successful begin reading frames. The session will continue reading frames until an error occurs or a connection close frame is seen. The session will notify the handler that it was initilized with (see Handler API) as necessary. The Session API defines how a handler (or other part of the end application) can interact with the session (to get information about the session, send messages back to the client, etc)
## Client API ##
include websocketpp.hpp
create a websocketpp::client_ptr initialized to a new websocketpp::client object
the client constructor will need:
- A boost::asio::io_service object to use to manage its async operations
- An object that impliments the websocketpp::connection_handler interface to privde callback functions (See Handler API)
After construction, the client object will be in the initialization state. At this time you can set up client config options either via calling individual set options commands or by loading them in a batch from a config file.
Opening a new connection:
Per the websocket spec, a client can only have one connection in the connecting state at a time. Client method new_session() will create a new session and return a shared pointer to it. After this point new_session will throw an exception if you attempt to call it again before the most recently created session has either successfully connected or failed to connect. new_session()
- call websocketpp::client::new_session(). This will return a session_ptr
## Handler API ##
The handler API defines the interface that a websocketpp session will use to communicate information about the session state and new messages to your application.
A client or server must be initialized with a default handler that will be used for all sessions. The default handler may pass a session off to another handler as necessary.
A handler must impliment the following methods:
- validate(session_ptr)
- on_fail(session_ptr)
- on_open(session_ptr)
- on_close(session_ptr)
- on_message(session_ptr,const std::vector<unsigned char> &)
- on_message(session_ptr,const std::string &)
validate will be called after a websocket handshake has been received and before it is accepted. It provides a handler the ability to refuse a connection based on application specific logic (ex: restrict domains or negotiate subprotocols). To reject the connection throw a handshake_error. Validate is never called for client sessions. To refuse a client session (ex: if you do not like the set of extensions/subprotocols the server chose) you can close the connection immediately in the on_open member function.
on_fail is called whenever a session is terminated or failed before it was successfully established. This happens if there is an error during the handshake process or if the server refused the connection.
on_fail will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out.
on_open is called after the websocket session has been successfully established and is in the OPEN state. The session is now avaliable to send messages and will begin reading frames and calling the on_message/on_close/on_error callbacks. A client may reject the connection by closing the session at this point.
on_close is called whenever an open session is closed for any reason. This can be due to either endpoint requesting a connection close or an error occuring. Information about why the session was closed can be extracted from the session itself.
on_close will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out.
on_message (binary version) will be called when a binary message is recieved. Message data is passed as a vector of bytes (unsigned char). data will not be avaliable after this callback ends so the handler must either completely process the message or copy it somewhere else for processing later.
TODO: Notes about thread safety
## Session API ##
The Session API allows a handler to look up information about a session as well as interact with that session (send messages, close the connection, etc)
Session pointers are returned with every handler callback as well as every call to websocketpp::client::connect.
Handler Interface:
- set_handler(connection_handler_ptr)
Handshake Interface:
For the client these methods are valid after the server's handshake has been received. This is guaranteed to be the case by the time `on_open` is called.
For the server these methods are valid after the client's handshake has been received. This is guaranteed to be the case by the time `validate` is called.
- const std::string& get_subprotocol() const;
- const std::string& get_resource() const;
- const std::string& get_origin() const;
- std::string get_client_header(const std::string&) const;
- std::string get_server_header(const std::string&) const;
- const std::vector<std::string>& get_extensions() const;
- unsigned int get_version() const;
Frame Interface
- void send(const std::string &);
- void send(const std::vector<unsigned char> &);
- void ping(const std::string &);
- void pong(const std::string &);
These methods are valid only for open connections. They will throw an exception if called from any other state.
WebSocket++ does not queue messages. As such only one send operation can be occuring at once.
TODO: failure behavior. OPTIONS:
- send will throw a `session_busy` exception if busy
- send will return true/false
- a callback could be defined letting the handler know that it is safe to write again.
Session Interface
- void close(uint16_t status,const std::string &reason);
- bool is_server() const;
--------------------------------
screwing around with a policy based refactoring
--------------------------------
template<class WebSocketRole,class Logger>
class endpoint : public WebSocketRole, Logger {
public:
endpoint(connection_handler_ptr);
size_t get_connected_client_count() const;
void set_endpoint(const tcp::endpoint& endpoint); // asio::bind
private:
std::list<session_ptr> m_connections;
connection_handler_ptr m_handler;
boost::asio::io_service m_io_service;
tcp::acceptor m_acceptor;
}
class server_interface {
public:
void add_host(const std::string &host);
void remove_host(const std::string &host);
bool validate_host(const std::string &host) const;
void set_max_message_size(uint64_t size);
bool validate_message_size(uint64_t size) const;
void start() {
// start_accept()
// io_service.run()
}
private:
void start_accept();
void handle_accept(session_ptr session, const boost::system::error_code&)
std::set<std::string> m_hosts;
uint64_t m_max_message_size;
}
class client_interface {
public:
session_ptr connect(const std::string &url);
protected:
private:
}
template<class HandshakePolicy>
class session : public HandshakePolicy {
public:
session();
private:
}
namespace websocketpp {
namespace handshake {
/* a handshake policy must define:
void on_connect();
bool is_server() const;
*/
class server {
}
class client {
}
} // handshake
} // websocketpp
+41
View File
@@ -0,0 +1,41 @@
Complete & Tested:
- Server and client roles pass all Autobahn v0.5.9 test suite tests strictly
- Streaming UTF8 validation
- random number generation
- iostream based transport
- C++11 support
- LLVM/Clang support
- GCC support
- 64 bit support
- 32 bit support
- Logging
- Client role
Implimented, needs more testing
- TLS support
- echo_server & echo_server_tls
- External io_service support
- socket_init_handler
- tls_init_handler
- message_handler
- ping_handler
- pong_handler
- tcp_init_handler
- exception/error handling
- Subprotocol negotiation
- Hybi 00/Hixie 76 legacy protocol support
- Performance tuning
- Outgoing Proxy Support
- PowerPC support
- Visual Studio / Windows support
- Timeouts
- CMake build/install support
- open_handler
- close_handler
- validate_handler
- http_handler
Future feature roadmap
- Extension support
- permessage_compress extension
- Message buffer pool
-175
View File
@@ -1,175 +0,0 @@
/*
* Copyright (c) 2011, 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 "network_utilities.hpp"
uint64_t htonll(uint64_t src) {
static int typ = TYP_INIT;
unsigned char c;
union {
uint64_t ull;
unsigned char c[8];
} x;
if (typ == TYP_INIT) {
x.ull = 0x01;
typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE;
}
if (typ == TYP_BIGE)
return src;
x.ull = src;
c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c;
c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c;
c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c;
c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c;
return x.ull;
}
uint64_t ntohll(uint64_t src) {
return htonll(src);
}
std::string lookup_http_error_string(int code) {
switch (code) {
case 400:
return "Bad Request";
case 401:
return "Unauthorized";
case 403:
return "Forbidden";
case 404:
return "Not Found";
case 405:
return "Method Not Allowed";
case 406:
return "Not Acceptable";
case 407:
return "Proxy Authentication Required";
case 408:
return "Request Timeout";
case 409:
return "Conflict";
case 410:
return "Gone";
case 411:
return "Length Required";
case 412:
return "Precondition Failed";
case 413:
return "Request Entity Too Large";
case 414:
return "Request-URI Too Long";
case 415:
return "Unsupported Media Type";
case 416:
return "Requested Range Not Satisfiable";
case 417:
return "Expectation Failed";
case 500:
return "Internal Server Error";
case 501:
return "Not Implimented";
case 502:
return "Bad Gateway";
case 503:
return "Service Unavailable";
case 504:
return "Gateway Timeout";
case 505:
return "HTTP Version Not Supported";
default:
return "Unknown";
}
}
std::string lookup_ws_close_status_string(uint16_t code) {
switch (code) {
case 1000:
return "Normal closure";
case 1001:
return "Going away";
case 1002:
return "Protocol error";
case 1003:
return "Unacceptable data";
case 1004:
return "Reserved";
case 1005:
return "No status received";
case 1006:
return "Abnormal closure";
case 1007:
return "Invalid message data";
case 1008:
return "Policy Violation";
case 1009:
return "Message too large";
case 1010:
return "Missing required extensions";
default:
return "Unknown";
}
}
bool websocketpp::ws_uri::parse(const std::string& uri) {
boost::cmatch what;
static const boost::regex expression("(ws|wss)://([^/:\\[]+|\\[[0-9:]+\\])(:\\d{1,5})?(/[^#]*)?");
// TODO: should this split resource into path/query?
if (boost::regex_match(uri.c_str(), what, expression)) {
if (what[1] == "wss") {
secure = true;
} else {
secure = false;
}
host = what[2];
if (what[3] == "") {
port = (secure ? 443 : 80);
} else {
unsigned int t_port = atoi(std::string(what[3]).substr(1).c_str());
if (t_port > 65535) {
return false;
}
port = atoi(std::string(what[3]).substr(1).c_str());
}
if (what[4] == "") {
resource = "/";
} else {
resource = what[4];
}
return true;
} else {
return false;
}
}
-200
View File
@@ -1,200 +0,0 @@
/*
* Copyright (c) 2011, 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 "websocket_client.hpp"
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using websocketpp::client;
using boost::asio::ip::tcp;
client::client(boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc)
: m_elog_level(LOG_OFF),
m_alog_level(ALOG_OFF),
m_state(CLIENT_STATE_NULL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_resolver(io_service),
m_def_con_handler(defc) {}
void client::init() {
// TODO: sanity check whether the session buffer size bound could be reduced
m_client_session = client_session_ptr(
new client_session(
shared_from_this(),
m_io_service,
m_def_con_handler,
m_max_message_size*2
)
);
m_state = CLIENT_STATE_INITIALIZED;
}
void client::connect(const std::string& uri) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("connect can only be called after init and before a connection has been established");
}
m_client_session->set_uri(uri);
std::stringstream port;
port << m_client_session->get_port();
tcp::resolver::query query(m_client_session->get_host(),
port.str());
tcp::resolver::iterator iterator = m_resolver.resolve(query);
boost::asio::async_connect(m_client_session->socket(),
iterator,boost::bind(&client::handle_connect,
this,
boost::asio::placeholders::error));
m_state = CLIENT_STATE_CONNECTING;
}
void client::add_subprotocol(const std::string& p) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("add_protocol can only be called after init and before connect");
}
m_client_session->add_subprotocol(p);
}
void client::set_header(const std::string& key,const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_header can only be called after init and before connect");
}
m_client_session->set_header(key,val);
}
void client::set_origin(const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_origin can only be called after init and before connect");
}
m_client_session->set_origin(val);
}
void client::set_max_message_size(uint64_t val) {
if (val > frame::PAYLOAD_64BIT_LIMIT) {
std::stringstream err;
err << "Invalid maximum message size: " << val;
// TODO: Figure out what the ideal error behavior for this method.
// Options:
// Throw exception
// Log error and set value to maximum allowed
// Log error and leave value at whatever it was before
log(err.str(),LOG_WARN);
//throw client_error(err.str());
}
m_max_message_size = val;
}
bool client::test_elog_level(uint16_t level) {
return (level >= m_elog_level);
}
void client::set_elog_level(uint16_t level) {
std::stringstream msg;
msg << "Error logging level changing from "
<< m_elog_level << " to " << level;
log(msg.str(),LOG_INFO);
m_elog_level = level;
}
bool client::test_alog_level(uint16_t level) {
return ((level & m_alog_level) != 0);
}
void client::set_alog_level(uint16_t level) {
if (test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being set";
access_log(msg.str(),ALOG_INFO);
m_alog_level |= level;
}
void client::unset_alog_level(uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being unset";
access_log(msg.str(),ALOG_INFO);
m_alog_level &= ~level;
}
bool client::validate_message_size(uint64_t val) {
if (val > m_max_message_size) {
return false;
}
return true;
}
void client::log(std::string msg,uint16_t level) {
if (!test_elog_level(level)) {
return;
}
std::cerr << "[Error Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void client::access_log(std::string msg,uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::cout << "[Access Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void client::handle_connect(const boost::system::error_code& error) {
if (!error) {
std::stringstream err;
err << "Successful Connection ";
log(err.str(),LOG_ERROR);
std::cout << boost::posix_time::to_iso_extended_string(boost::posix_time::microsec_clock::local_time()) << " TCP established" << std::endl;
m_state = CLIENT_STATE_CONNECTED;
m_client_session->on_connect();
} else {
std::stringstream err;
err << "An error occurred while establishing a connection: " << error;
log(err.str(),LOG_ERROR);
throw client_error(err.str());
}
}
-135
View File
@@ -1,135 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_CLIENT_HPP
#define WEBSOCKET_CLIENT_HPP
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <set>
namespace websocketpp {
class client;
typedef boost::shared_ptr<client> client_ptr;
}
#include "websocketpp.hpp"
#include "websocket_client_session.hpp"
#include "websocket_connection_handler.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class client_error : public std::exception {
public:
client_error(const std::string& msg)
: m_msg(msg) {}
~client_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
private:
std::string m_msg;
};
class client : public boost::enable_shared_from_this<client> {
public:
static const uint16_t CLIENT_STATE_NULL = 0;
static const uint16_t CLIENT_STATE_INITIALIZED = 1;
static const uint16_t CLIENT_STATE_CONNECTING = 2;
static const uint16_t CLIENT_STATE_CONNECTED = 3;
client(boost::asio::io_service& io_service,
connection_handler_ptr defc);
// INTERFACE FOR LOCAL APPLICATIONS
// initializes the session. Methods that affect the opening handshake
// such as add_protocol and set_header must be called after init and
// before connect.
void init();
// starts the connection process. Should be called before
// io_service.run(), connection process will not start until run() has
// been called.
void connect(const std::string& url);
// Adds a protocol to the opening handshake.
// Must be called before connect
void add_subprotocol(const std::string& p);
// Sets the value of the given HTTP header to be sent during the
// opening handshake. Must be called before connect
void set_header(const std::string& key,const std::string& val);
void set_origin(const std::string& val);
void set_max_message_size(uint64_t val);
// Test methods determine if a message of the given level should be
// written. elog shows all values above the level set. alog shows only
// the values explicitly set.
bool test_elog_level(uint16_t level);
void set_elog_level(uint16_t level);
bool test_alog_level(uint16_t level);
void set_alog_level(uint16_t level);
void unset_alog_level(uint16_t level);
// INTERFACE FOR SESSIONS
// Check if message size is within server's acceptable parameters
bool validate_message_size(uint64_t val);
// write to the server's logs
void log(std::string msg,uint16_t level = LOG_ERROR);
void access_log(std::string msg,uint16_t level);
private:
// if no errors starts the session's read loop and returns to the
// start_accept phase.
void handle_connect(const boost::system::error_code& error);
private:
uint16_t m_elog_level;
uint16_t m_alog_level;
uint16_t m_state;
std::set<std::string> m_hosts;
uint64_t m_max_message_size;
boost::asio::io_service& m_io_service;
tcp::resolver m_resolver;
client_session_ptr m_client_session;
connection_handler_ptr m_def_con_handler;
};
}
#endif // WEBSOCKET_CLIENT_HPP
-350
View File
@@ -1,350 +0,0 @@
/*
* Copyright (c) 2011, 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.hpp"
#include "websocket_client_session.hpp"
#include "websocket_frame.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using websocketpp::client_session;
client_session::client_session (websocketpp::client_ptr c,
boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc,
uint64_t buf_size)
: session(io_service,defc,buf_size),m_client(c) {}
void client_session::on_connect() {
// TODO: section 4.1: Figure out if we have another connection to this
// host/port pending.
write_handshake();
}
void client_session::set_uri(const std::string& uri) {
if (!m_uri.parse(uri)) {
throw client_error("Invalid WebSocket URI");
}
if (m_uri.secure) {
throw client_error("wss / secure connections are not supported at this time");
}
m_resource = m_uri.resource;
std::stringstream l;
l << "parsed websocket url: secure: " << m_uri.secure << " host: " << m_uri.host
<< " port (final): " << m_uri.port << " resource " << m_uri.resource;
log(l.str(),LOG_DEBUG);
}
bool client_session::get_secure() const {
return m_uri.secure;
}
std::string client_session::get_host() const{
return m_uri.host;
}
uint16_t client_session::get_port() const {
return m_uri.port;
}
void client_session::set_header(const std::string &key,const std::string &val) {
// TODO: prevent use of reserved headers
m_client_headers[key] = val;
}
void client_session::set_origin(const std::string& val) {
// TODO: input validation
m_client_origin = val;
}
void client_session::add_subprotocol(const std::string &val) {
// TODO: input validation
m_client_subprotocols.push_back(val);
}
void client_session::add_extension(const std::string& val) {
// TODO: input validation
m_client_extensions.push_back(val);
}
void client_session::read_handshake() {
boost::asio::async_read_until(
m_socket,
m_buf,
"\r\n\r\n",
boost::bind(
&session::handle_read_handshake,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void client_session::handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) {
if (e) {
log_error("Error reading server handshake",e);
drop_tcp();
return;
}
// parse server handshake
std::istream response_stream(&m_buf);
std::string header;
std::string::size_type end;
// get status line
std::getline(response_stream, header);
if (header[header.size()-1] == '\r') {
header.erase(header.end()-1);
m_server_http_request = header;
m_raw_server_handshake += header+"\n";
}
// get headers
while (std::getline(response_stream, header) && header != "\r") {
if (header[header.size()-1] != '\r') {
continue; // ignore malformed header lines?
} else {
header.erase(header.end()-1);
}
end = header.find(": ",0);
if (end != std::string::npos) {
std::string h = header.substr(0,end);
if (get_server_header(h) == "") {
m_server_headers[h] = header.substr(end+2);
} else {
m_server_headers[h] += ", " + header.substr(end+2);
}
}
m_raw_server_handshake += header+"\n";
}
// temporary debugging
if (m_buf.size() > 0) {
std::stringstream foo;
foo << "bytes left over: " << m_buf.size();
access_log(foo.str(), ALOG_HANDSHAKE);
}
m_client->access_log(m_raw_server_handshake,ALOG_HANDSHAKE);
// handshake error checking
try {
std::stringstream err;
std::string h;
// TODO: allow versions greater than 1.1
if (m_server_http_request.substr(0,9) != "HTTP/1.1 ") {
err << "Websocket handshake has invalid HTTP version: "
<< m_server_http_request.substr(0,9);
throw(handshake_error(err.str(),400));
}
// check the HTTP version
if (m_server_http_request.substr(9,3) != "101") {
err << "Websocket handshake ended with status "
<< m_server_http_request.substr(9);
// TODO: check version header for other supported versions.
throw(handshake_error(err.str(),400));
}
// verify the presence of required headers
h = get_server_header("Upgrade");
if (h == "") {
throw(handshake_error("Required Upgrade header is missing",400));
} else if (!boost::iequals(h,"websocket")) {
err << "Upgrade header was \"" << h << "\" instead of \"websocket\"";
throw(handshake_error(err.str(),400));
}
h = get_server_header("Connection");
if (h == "") {
throw(handshake_error("Required Connection header is missing",400));
} else if (!boost::ifind_first(h,"upgrade")) {
err << "Connection header, \"" << h
<< "\", does not contain required token \"upgrade\"";
throw(handshake_error(err.str(),400));
}
if (get_server_header("Sec-WebSocket-Accept") == "") {
throw(handshake_error("Required Sec-WebSocket-Key header is missing",400));
} else {
// TODO: make a helper function for this.
std::string server_key = m_client_key;
server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1 sha;
uint32_t message_digest[5];
sha.Reset();
sha << server_key.c_str();
if (!sha.Result(message_digest)) {
m_client->log("Error computing handshake sha1 hash.",LOG_ERROR);
// TODO: close behavior
return;
}
// convert sha1 hash bytes to network byte order because this sha1
// library works on ints rather than bytes
for (int i = 0; i < 5; i++) {
message_digest[i] = htonl(message_digest[i]);
}
server_key = base64_encode(
reinterpret_cast<const unsigned char*>(message_digest),20);
if (server_key != get_server_header("Sec-WebSocket-Accept")) {
m_client->log("Server key does not match",LOG_ERROR);
// TODO: close behavior
return;
}
}
} catch (const handshake_error& e) {
std::stringstream err;
err << "Caught handshake exception: " << e.what();
m_client->access_log(e.what(),ALOG_HANDSHAKE);
m_client->log(err.str(),LOG_ERROR);
// TODO: close behavior
return;
}
log_open_result();
m_state = STATE_OPEN;
if (m_local_interface) {
m_local_interface->on_open(shared_from_this());
}
reset_message();
read_frame();
}
void client_session::write_handshake() {
// generate client handshake.
std::string client_handshake;
client_handshake += "GET "+m_resource+" HTTP/1.1\r\n";
set_header("Upgrade","websocket");
set_header("Connection","Upgrade");
set_header("Sec-WebSocket-Version","13");
set_header("Host",m_uri.host);
if (m_client_origin != "") {
set_header("Origin",m_client_origin);
}
// TODO: generate proper key
m_client_key = "XO4pxrIMLnK1CEVQP9untQ==";
int32_t raw_key[4];
boost::random::random_device rng;
boost::random::variate_generator<boost::random::random_device&, boost::random::uniform_int_distribution<> > gen(rng, boost::random::uniform_int_distribution<>(INT32_MIN,INT32_MAX));
for (int i = 0; i < 4; i++) {
raw_key[i] = gen();
}
m_client_key = base64_encode(reinterpret_cast<unsigned char const*>(raw_key), 16);
m_client->access_log("Client key chosen: "+m_client_key, ALOG_HANDSHAKE);
set_header("Sec-WebSocket-Key",m_client_key);
set_header("User Agent","WebSocket++/2011-09-25");
header_list::iterator it;
for (it = m_client_headers.begin(); it != m_client_headers.end(); it++) {
client_handshake += it->first + ": " + it->second + "\r\n";
}
client_handshake += "\r\n";
m_raw_client_handshake = client_handshake;
// start async write to handle_write_handshake
boost::asio::async_write(
m_socket,
boost::asio::buffer(m_raw_client_handshake),
boost::bind(
&session::handle_write_handshake,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
void client_session::handle_write_handshake(const boost::system::error_code& error) {
if (error) {
log_error("Error writing handshake",error);
drop_tcp();
return;
}
read_handshake();
}
void client_session::log(const std::string& msg, uint16_t level) const {
m_client->log(msg,level);
}
void client_session::access_log(const std::string& msg, uint16_t level) const {
m_client->access_log(msg,level);
}
-135
View File
@@ -1,135 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_CLIENT_SESSION_HPP
#define WEBSOCKET_CLIENT_SESSION_HPP
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
#include <exception>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace websocketpp {
class client_session;
typedef boost::shared_ptr<client_session> client_session_ptr;
}
#include "websocket_session.hpp"
#include "websocket_client.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class client_session : public session {
public:
client_session (client_ptr c,
boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size);
/*** CLIENT INTERFACE ***/
// This function is called when a tcp connection has been established and
// the connection is ready to start the opening handshake.
void on_connect();
/*** HANDSHAKE INTERFACE ***/
void set_uri(const std::string& url);
bool get_secure() const;
std::string get_host() const;
uint16_t get_port() const;
// Set an HTTP header for the outgoing client handshake.
void set_header(const std::string& key,const std::string& val);
// adds a subprotocol. This will result in the appropriate
// Sec-WebSocket-Protocol header being sent with the opening connection.
// Values will be sent in the order they were added. Servers interpret this
// order as the preferred order.
void add_subprotocol(const std::string &val);
// Sets the origin value that will be sent to the server
void set_origin(const std::string &val);
// Adds an extension to the extension list. Extensions are sent in the
// order added
void add_extension(const std::string& val);
/*** SESSION INTERFACE ***/
// see session
bool is_server() const {return false;}
void log(const std::string& msg, uint16_t level) const;
void access_log(const std::string& msg, uint16_t level) const;
protected:
// Opening handshake processors and callbacks.
virtual void write_handshake();
virtual void handle_write_handshake(const boost::system::error_code& e);
virtual void read_handshake();
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred);
private:
protected:
ws_uri m_uri;
// url parts
bool m_secure;
std::string m_host;
uint16_t m_port;
// handshake stuff
std::string m_client_key;
// connection resources
client_ptr m_client;
private:
};
}
#endif // WEBSOCKET_CLIENT_SESSION_HPP
-113
View File
@@ -1,113 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_CONNECTION_HANDLER_HPP
#define WEBSOCKET_CONNECTION_HANDLER_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
namespace websocketpp {
class connection_handler;
typedef boost::shared_ptr<connection_handler> connection_handler_ptr;
}
#include "websocket_session.hpp"
namespace websocketpp {
class connection_handler {
public:
// validate will be called after a websocket handshake has been received and
// before it is accepted. It provides a handler the ability to refuse a
// connection based on application specific logic (ex: restrict domains or
// negotiate subprotocols). To reject the connection throw a handshake_error
//
// Validate is never called for client sessions. To refuse a client session
// (ex: if you do not like the set of extensions/subprotocols the server
// chose) you can close the connection immediately in the on_open method.
//
// handshake_error parameters:
// log_message - error message to send to server log
// http_error_code - numeric HTTP error code to return to the client
// http_error_msg - (optional) string HTTP error code to return to the
// client (useful for returning non-standard error codes)
virtual void validate(session_ptr session) {};
// on_open is called after the websocket session has been successfully
// established and is in the OPEN state. The session is now avaliable to
// send messages and will begin reading frames and calling the on_message/
// on_close/on_error callbacks. A client may reject the connection by
// closing the session at this point.
virtual void on_open(session_ptr session) = 0;
// on_close is called whenever an open session is closed for any reason.
// This can be due to either endpoint requesting a connection close or an
// error occuring. Information about why the session was closed can be
// extracted from the session itself.
//
// on_close will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_close(session_ptr session) = 0;
// on_message (binary version) will be called when a binary message is
// recieved. Message data is passed as a vector of bytes (unsigned char).
// data will not be avaliable after this callback ends so the handler must
// either completely process the message or copy it somewhere else for
// processing later.
virtual void on_message(session_ptr session,
const std::vector<unsigned char> &data) = 0;
// on_message (text version). Identical to on_message except the data
// parameter is a string interpreted as UTF-8. WebSocket++ guarantees that
// this string is valid UTF-8.
virtual void on_message(session_ptr session,const std::string &msg) = 0;
// #### optional error cases ####
// on_fail is called whenever a session is terminated or failed before it
// was successfully established. This happens if there is an error during
// the handshake process or if the server refused the connection.
//
// on_fail will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_fail(session_ptr session) {};
// experimental
virtual void on_ping_timeout(session_ptr session) {}
};
}
#endif // WEBSOCKET_CONNECTION_HANDLER_HPP
-586
View File
@@ -1,586 +0,0 @@
/*
* Copyright (c) 2011, 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 "websocket_frame.hpp"
#include "websocket_server.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <iostream>
#include <algorithm>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
using websocketpp::frame;
uint8_t frame::get_state() const {
return m_state;
}
uint64_t frame::get_bytes_needed() const {
return m_bytes_needed;
}
void frame::reset() {
m_state = STATE_BASIC_HEADER;
m_bytes_needed = BASIC_HEADER_LENGTH;
m_degraded = false;
m_payload.empty();
memset(m_header,0,MAX_HEADER_LENGTH);
}
// Method invariant: One of the following must always be true even in the case
// of exceptions.
// - m_bytes_needed > 0
// - m-state = STATE_READY
void frame::consume(std::istream &s) {
try {
switch (m_state) {
case STATE_BASIC_HEADER:
s.read(&m_header[BASIC_HEADER_LENGTH-m_bytes_needed],m_bytes_needed);
m_bytes_needed -= s.gcount();
if (m_bytes_needed == 0) {
process_basic_header();
validate_basic_header();
if (m_bytes_needed > 0) {
m_state = STATE_EXTENDED_HEADER;
} else {
process_extended_header();
if (m_bytes_needed == 0) {
m_state = STATE_READY;
process_payload();
} else {
m_state = STATE_PAYLOAD;
}
}
}
break;
case STATE_EXTENDED_HEADER:
s.read(&m_header[get_header_len()-m_bytes_needed],m_bytes_needed);
m_bytes_needed -= s.gcount();
if (m_bytes_needed == 0) {
process_extended_header();
if (m_bytes_needed == 0) {
m_state = STATE_READY;
process_payload();
} else {
m_state = STATE_PAYLOAD;
}
}
break;
case STATE_PAYLOAD:
s.read(reinterpret_cast<char *>(&m_payload[m_payload.size()-m_bytes_needed]),
m_bytes_needed);
m_bytes_needed -= s.gcount();
if (m_bytes_needed == 0) {
m_state = STATE_READY;
process_payload();
}
break;
case STATE_RECOVERY:
// Recovery state discards all bytes that are not the first byte
// of a close frame.
do {
s.read(reinterpret_cast<char *>(&m_header[0]),1);
//std::cout << std::hex << int(static_cast<unsigned char>(m_header[0])) << " ";
if (int(static_cast<unsigned char>(m_header[0])) == 0x88) {
//(BPB0_FIN && CONNECTION_CLOSE)
m_bytes_needed--;
m_state = STATE_BASIC_HEADER;
break;
}
} while (s.gcount() > 0);
//std::cout << std::endl;
break;
default:
break;
}
/*if (s.gcount() == 0) {
throw frame_error("consume read zero bytes",FERR_FATAL_SESSION_ERROR);
}*/
} catch (const frame_error& e) {
// After this point all non-close frames must be considered garbage,
// including the current one. Reset it and put the reading frame into
// a recovery state.
if (m_degraded == true) {
throw frame_error("An error occurred while trying to gracefully recover from a less serious frame error.",FERR_FATAL_SESSION_ERROR);
} else {
reset();
m_state = STATE_RECOVERY;
m_degraded = true;
throw e;
}
}
}
char* frame::get_header() {
return m_header;
}
char* frame::get_extended_header() {
return m_header+BASIC_HEADER_LENGTH;
}
unsigned int frame::get_header_len() const {
unsigned int temp = 2;
if (get_masked()) {
temp += 4;
}
if (get_basic_size() == 126) {
temp += 2;
} else if (get_basic_size() == 127) {
temp += 8;
}
return temp;
}
char* frame::get_masking_key() {
if (m_state != STATE_READY) {
throw frame_error("attempted to get masking_key before reading full header");
}
return m_masking_key;
}
// get and set header bits
bool frame::get_fin() const {
return ((m_header[0] & BPB0_FIN) == BPB0_FIN);
}
void frame::set_fin(bool fin) {
if (fin) {
m_header[0] |= BPB0_FIN;
} else {
m_header[0] &= (0xFF ^ BPB0_FIN);
}
}
// get and set reserved bits
bool frame::get_rsv1() const {
return ((m_header[0] & BPB0_RSV1) == BPB0_RSV1);
}
void frame::set_rsv1(bool b) {
if (b) {
m_header[0] |= BPB0_RSV1;
} else {
m_header[0] &= (0xFF ^ BPB0_RSV1);
}
}
bool frame::get_rsv2() const {
return ((m_header[0] & BPB0_RSV2) == BPB0_RSV2);
}
void frame::set_rsv2(bool b) {
if (b) {
m_header[0] |= BPB0_RSV2;
} else {
m_header[0] &= (0xFF ^ BPB0_RSV2);
}
}
bool frame::get_rsv3() const {
return ((m_header[0] & BPB0_RSV3) == BPB0_RSV3);
}
void frame::set_rsv3(bool b) {
if (b) {
m_header[0] |= BPB0_RSV3;
} else {
m_header[0] &= (0xFF ^ BPB0_RSV3);
}
}
frame::opcode frame::get_opcode() const {
return frame::opcode(m_header[0] & BPB0_OPCODE);
}
void frame::set_opcode(frame::opcode op) {
if (op > 0x0F) {
throw frame_error("invalid opcode",FERR_PROTOCOL_VIOLATION);
}
if (get_basic_size() > BASIC_PAYLOAD_LIMIT &&
is_control()) {
throw frame_error("control frames can't have large payloads",FERR_PROTOCOL_VIOLATION);
}
m_header[0] &= (0xFF ^ BPB0_OPCODE); // clear op bits
m_header[0] |= op; // set op bits
}
bool frame::get_masked() const {
return ((m_header[1] & BPB1_MASK) == BPB1_MASK);
}
void frame::set_masked(bool masked) {
if (masked) {
m_header[1] |= BPB1_MASK;
generate_masking_key();
} else {
m_header[1] &= (0xFF ^ BPB1_MASK);
clear_masking_key();
}
}
uint8_t frame::get_basic_size() const {
return m_header[1] & BPB1_PAYLOAD;
}
size_t frame::get_payload_size() const {
if (m_state != STATE_READY && m_state != STATE_PAYLOAD) {
// problem
throw frame_error("attempted to get payload size before reading full header");
}
return m_payload.size();
}
uint16_t frame::get_close_status() const {
if (get_payload_size() == 0) {
return close::status::NO_STATUS;
} else if (get_payload_size() >= 2) {
char val[2];
val[0] = m_payload[0];
val[1] = m_payload[1];
uint16_t code = ntohs(*(
reinterpret_cast<uint16_t*>(&val[0])
));
return code;
} else {
return close::status::PROTOCOL_ERROR;
}
}
std::string frame::get_close_msg() const {
if (get_payload_size() > 2) {
uint32_t state = utf8_validator::UTF8_ACCEPT;
uint32_t codep = 0;
validate_utf8(&state,&codep,2);
if (state != utf8_validator::UTF8_ACCEPT) {
throw frame_error("Invalid UTF-8 Data",
frame::FERR_PAYLOAD_VIOLATION);
}
return std::string(m_payload.begin()+2,m_payload.end());
} else {
return std::string();
}
}
std::vector<unsigned char> &frame::get_payload() {
return m_payload;
}
void frame::set_payload(const std::vector<unsigned char> source) {
set_payload_helper(source.size());
std::copy(source.begin(),source.end(),m_payload.begin());
}
void frame::set_payload(const std::string source) {
set_payload_helper(source.size());
std::copy(source.begin(),source.end(),m_payload.begin());
}
bool frame::is_control() const {
return (get_opcode() > MAX_FRAME_OPCODE);
}
void frame::set_payload_helper(size_t s) {
if (s > max_payload_size) {
throw frame_error("requested payload is over implimentation defined limit",FERR_MSG_TOO_BIG);
}
// limits imposed by the websocket spec
if (s > BASIC_PAYLOAD_LIMIT &&
get_opcode() > MAX_FRAME_OPCODE) {
throw frame_error("control frames can't have large payloads",FERR_PROTOCOL_VIOLATION);
}
if (s <= BASIC_PAYLOAD_LIMIT) {
m_header[1] = s;
} else if (s <= PAYLOAD_16BIT_LIMIT) {
m_header[1] = BASIC_PAYLOAD_16BIT_CODE;
// this reinterprets the second pair of bytes in m_header as a
// 16 bit int and writes the payload size there as an integer
// in network byte order
*reinterpret_cast<uint16_t*>(&m_header[BASIC_HEADER_LENGTH]) = htons(s);
} else if (s <= PAYLOAD_64BIT_LIMIT) {
m_header[1] = BASIC_PAYLOAD_64BIT_CODE;
*reinterpret_cast<uint64_t*>(&m_header[BASIC_HEADER_LENGTH]) = htonll(s);
} else {
throw frame_error("payload size limit is 63 bits",FERR_PROTOCOL_VIOLATION);
}
m_payload.resize(s);
}
void frame::set_status(uint16_t status,const std::string message) {
// check for valid statuses
if (close::status::invalid(status)) {
std::stringstream err;
err << "Status code " << status << " is invalid";
throw frame_error(err.str());
}
if (close::status::reserved(status)) {
std::stringstream err;
err << "Status code " << status << " is reserved";
throw frame_error(err.str());
}
m_payload.resize(2+message.size());
char val[2];
*reinterpret_cast<uint16_t*>(&val[0]) = htons(status);
m_header[1] = message.size()+2;
m_payload[0] = val[0];
m_payload[1] = val[1];
std::copy(message.begin(),message.end(),m_payload.begin()+2);
}
std::string frame::print_frame() const {
std::stringstream f;
unsigned int len = get_header_len();
f << "frame: ";
// print header
for (unsigned int i = 0; i < len; i++) {
f << std::hex << (unsigned short)m_header[i] << " ";
}
// print message
if (m_payload.size() > 50) {
f << "[payload of " << m_payload.size() << " bytes]";
} else {
std::vector<unsigned char>::const_iterator it;
for (it = m_payload.begin(); it != m_payload.end(); it++) {
f << *it;
}
}
return f.str();
}
void frame::process_basic_header() {
m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH;
}
void frame::process_extended_header() {
uint8_t s = get_basic_size();
uint64_t payload_size;
int mask_index = BASIC_HEADER_LENGTH;
if (s <= BASIC_PAYLOAD_LIMIT) {
payload_size = s;
} else if (s == BASIC_PAYLOAD_16BIT_CODE) {
// reinterpret the second two bytes as a 16 bit integer in network
// byte order. Convert to host byte order and store locally.
payload_size = ntohs(*(
reinterpret_cast<uint16_t*>(&m_header[BASIC_HEADER_LENGTH])
));
if (payload_size < s) {
std::stringstream err;
err << "payload length not minimally encoded. Using 16 bit form for payload size: " << payload_size;
m_bytes_needed = payload_size;
throw frame_error(err.str(),
FERR_PROTOCOL_VIOLATION);
}
mask_index += 2;
} else if (s == BASIC_PAYLOAD_64BIT_CODE) {
// reinterpret the second eight bytes as a 64 bit integer in
// network byte order. Convert to host byte order and store.
payload_size = ntohll(*(
reinterpret_cast<uint64_t*>(&m_header[BASIC_HEADER_LENGTH])
));
if (payload_size <= PAYLOAD_16BIT_LIMIT) {
m_bytes_needed = payload_size;
throw frame_error("payload length not minimally encoded",
FERR_PROTOCOL_VIOLATION);
}
mask_index += 8;
} else {
// shouldn't be here
throw frame_error("invalid get_basic_size in process_extended_header");
}
if (get_masked() == 0) {
clear_masking_key();
} else {
// TODO: use this copy line (needs testing)
// std::copy(m_header[mask_index],m_header[mask_index+4],m_masking_key);
m_masking_key[0] = m_header[mask_index+0];
m_masking_key[1] = m_header[mask_index+1];
m_masking_key[2] = m_header[mask_index+2];
m_masking_key[3] = m_header[mask_index+3];
}
if (payload_size > max_payload_size) {
// TODO: frame/message size limits
throw server_error("got frame with payload greater than maximum frame buffer size.");
}
m_payload.resize(payload_size);
m_bytes_needed = payload_size;
}
void frame::process_payload() {
if (get_masked()) {
char *masking_key = &m_header[get_header_len()-4];
for (uint64_t i = 0; i < m_payload.size(); i++) {
m_payload[i] = (m_payload[i] ^ masking_key[i%4]);
}
}
}
void frame::process_payload2() {
// unmask payload one byte at a time
//uint64_t key = (*((uint32_t*)m_masking_key;)) << 32;
//key += *((uint32_t*)m_masking_key);
// might need to switch byte order
uint32_t key = *((uint32_t*)m_masking_key);
// 4
uint64_t i = 0;
uint64_t s = (m_payload.size() / 4);
std::cout << "s: " << s << std::endl;
// chunks of 4
for (i = 0; i < s; i+=4) {
((uint32_t*)(&m_payload[0]))[i] = (((uint32_t*)(&m_payload[0]))[i] ^ key);
}
// finish the last few
for (i = s; i < m_payload.size(); i++) {
m_payload[i] = (m_payload[i] ^ m_masking_key[i%4]);
}
}
void frame::validate_utf8(uint32_t* state,uint32_t* codep, size_t offset) const {
for (size_t i = offset; i < m_payload.size(); i++) {
using utf8_validator::decode;
if (decode(state,codep,m_payload[i]) == utf8_validator::UTF8_REJECT) {
throw frame_error("Invalid UTF-8 Data",FERR_PAYLOAD_VIOLATION);
}
}
}
void frame::validate_basic_header() const {
// check for control frame size
if (get_basic_size() > BASIC_PAYLOAD_LIMIT && is_control()) {
throw frame_error("Control Frame is too large",FERR_PROTOCOL_VIOLATION);
}
// check for reserved opcodes
if (get_rsv1() || get_rsv2() || get_rsv3()) {
throw frame_error("Reserved bit used",FERR_PROTOCOL_VIOLATION);
}
// check for reserved opcodes
opcode op = get_opcode();
if (op > 0x02 && op < 0x08) {
throw frame_error("Reserved opcode used",FERR_PROTOCOL_VIOLATION);
}
if (op > 0x0A) {
throw frame_error("Reserved opcode used",FERR_PROTOCOL_VIOLATION);
}
// check for fragmented control message
if (is_control() && !get_fin()) {
throw frame_error("Fragmented control message",FERR_PROTOCOL_VIOLATION);
}
}
void frame::generate_masking_key() {
//throw "masking key generation not implimented";
int32_t key = m_gen();
//m_masking_key[0] = reinterpret_cast<char*>(&key)[0];
//m_masking_key[1] = reinterpret_cast<char*>(&key)[1];
//m_masking_key[2] = reinterpret_cast<char*>(&key)[2];
//m_masking_key[3] = reinterpret_cast<char*>(&key)[3];
*(reinterpret_cast<int32_t *>(&m_header[get_header_len()-4])) = key;
//std::cout << "maskkey: " << m_masking_key << std::endl;
/* TODO: test and tune
boost::random::random_device rng;
boost::random::uniform_int_distribution<> mask(0,UINT32_MAX);
*(reinterpret_cast<uint32_t *>(m_masking_key)) = mask(rng);
*/
}
void frame::clear_masking_key() {
// this is a no-op as clearing the mask bit also changes the get_header_len
// method to not include these byte ranges. Whenever the masking bit is re-
// set a new key is generated anyways.
}
-203
View File
@@ -1,203 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_FRAME_HPP
#define WEBSOCKET_FRAME_HPP
#include "network_utilities.hpp"
#include <string>
#include <vector>
#include <cstring>
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
namespace websocketpp {
/* policies to abstract out
- random number generation
- utf8 validation
*/
class frame {
public:
enum opcode_s {
CONTINUATION_FRAME = 0x00,
TEXT_FRAME = 0x01,
BINARY_FRAME = 0x02,
CONNECTION_CLOSE = 0x08,
PING = 0x09,
PONG = 0x0A
};
typedef enum opcode_s opcode;
static const uint8_t MAX_FRAME_OPCODE = 0x07;
static const uint8_t STATE_BASIC_HEADER = 1;
static const uint8_t STATE_EXTENDED_HEADER = 2;
static const uint8_t STATE_PAYLOAD = 3;
static const uint8_t STATE_READY = 4;
static const uint8_t STATE_RECOVERY = 5;
static const uint16_t FERR_FATAL_SESSION_ERROR = 0; // force session end
static const uint16_t FERR_SOFT_SESSION_ERROR = 1; // should log and ignore
static const uint16_t FERR_PROTOCOL_VIOLATION = 2; // must end session
static const uint16_t FERR_PAYLOAD_VIOLATION = 3; // should end session
static const uint16_t FERR_INTERNAL_SERVER_ERROR = 4; // cleanly end session
static const uint16_t FERR_MSG_TOO_BIG = 5;
// basic payload byte flags
static const uint8_t BPB0_OPCODE = 0x0F;
static const uint8_t BPB0_RSV3 = 0x10;
static const uint8_t BPB0_RSV2 = 0x20;
static const uint8_t BPB0_RSV1 = 0x40;
static const uint8_t BPB0_FIN = 0x80;
static const uint8_t BPB1_PAYLOAD = 0x7F;
static const uint8_t BPB1_MASK = 0x80;
static const uint8_t BASIC_PAYLOAD_LIMIT = 0x7D; // 125
static const uint8_t BASIC_PAYLOAD_16BIT_CODE = 0x7E; // 126
static const uint16_t PAYLOAD_16BIT_LIMIT = 0xFFFF; // 2^16, 65535
static const uint8_t BASIC_PAYLOAD_64BIT_CODE = 0x7F; // 127
static const uint64_t PAYLOAD_64BIT_LIMIT = 0x7FFFFFFFFFFFFFFF; // 2^63
static const unsigned int BASIC_HEADER_LENGTH = 2;
static const unsigned int MAX_HEADER_LENGTH = 14;
static const uint8_t extended_header_length = 12;
static const uint64_t max_payload_size = 100000000; // 100MB
// create an empty frame for writing into
frame() : m_gen(m_rng,
boost::random::uniform_int_distribution<>(INT32_MIN,INT32_MAX)),m_degraded(false) {
reset();
}
uint8_t get_state() const;
uint64_t get_bytes_needed() const;
void reset();
void consume(std::istream &s);
// get pointers to underlying buffers
char* get_header();
char* get_extended_header();
unsigned int get_header_len() const;
char* get_masking_key();
// get and set header bits
bool get_fin() const;
void set_fin(bool fin);
bool get_rsv1() const;
void set_rsv1(bool b);
bool get_rsv2() const;
void set_rsv2(bool b);
bool get_rsv3() const;
void set_rsv3(bool b);
opcode get_opcode() const;
void set_opcode(opcode op);
bool get_masked() const;
void set_masked(bool masked);
uint8_t get_basic_size() const;
size_t get_payload_size() const;
uint16_t get_close_status() const;
std::string get_close_msg() const;
std::vector<unsigned char> &get_payload();
void set_payload(const std::vector<unsigned char> source);
void set_payload(const std::string source);
void set_payload_helper(size_t s);
void set_status(uint16_t status,const std::string message = "");
bool is_control() const;
std::string print_frame() const;
// reads basic header, sets and returns m_header_bits_needed
void process_basic_header();
void process_extended_header();
void process_payload();
void process_payload2(); // experiment with more efficient masking code.
void validate_utf8(uint32_t* state,uint32_t* codep,size_t offset = 0) const;
void validate_basic_header() const;
void generate_masking_key();
void clear_masking_key();
private:
uint8_t m_state;
uint64_t m_bytes_needed;
bool m_degraded;
char m_header[MAX_HEADER_LENGTH];
std::vector<unsigned char> m_payload;
char m_masking_key[4];
boost::random::random_device m_rng;
boost::random::variate_generator<boost::random::random_device&,
boost::random::uniform_int_distribution<> >
m_gen;
};
// Exception classes
class frame_error : public std::exception {
public:
frame_error(const std::string& msg,
uint16_t code = frame::FERR_FATAL_SESSION_ERROR)
: m_msg(msg),m_code(code) {}
~frame_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
uint16_t code() const throw() {
return m_code;
}
std::string m_msg;
uint16_t m_code;
};
}
#endif // WEBSOCKET_FRAME_HPP
-201
View File
@@ -1,201 +0,0 @@
/*
* Copyright (c) 2011, 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 "websocket_server.hpp"
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using websocketpp::server;
server::server(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint,
websocketpp::connection_handler_ptr defc)
: m_elog_level(LOG_ALL),
m_alog_level(ALOG_ALL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_acceptor(io_service, endpoint),
m_def_con_handler(defc),
m_desc("websocketpp::server") {
m_desc.add_options()
("help", "produce help message")
("host,h",po::value<std::vector<std::string> >()->multitoken()->composing(), "hostnames to listen on")
("port,p",po::value<int>(), "port to listen on")
;
}
void server::parse_command_line(int ac, char* av[]) {
po::store(po::parse_command_line(ac,av, m_desc),m_vm);
po::notify(m_vm);
if (m_vm.count("help") ) {
std::cout << m_desc << std::endl;
}
//m_vm["host"].as<std::string>();
const std::vector< std::string > &foo = m_vm["host"].as< std::vector<std::string> >();
for (int i = 0; i < foo.size(); i++) {
std::cout << foo[i] << std::endl;
}
//std::cout << m_vm["host"].as< std::vector<std::string> >() << std::endl;
}
void server::add_host(std::string host) {
m_hosts.insert(host);
}
void server::remove_host(std::string host) {
m_hosts.erase(host);
}
void server::set_max_message_size(uint64_t val) {
if (val > frame::PAYLOAD_64BIT_LIMIT) {
std::stringstream err;
err << "Invalid maximum message size: " << val;
// TODO: Figure out what the ideal error behavior for this method.
// Options:
// Throw exception
// Log error and set value to maximum allowed
// Log error and leave value at whatever it was before
log(err.str(),LOG_WARN);
//throw server_error(err.str());
}
m_max_message_size = val;
}
bool server::test_elog_level(uint16_t level) {
return (level >= m_elog_level);
}
void server::set_elog_level(uint16_t level) {
std::stringstream msg;
msg << "Error logging level changing from "
<< m_elog_level << " to " << level;
log(msg.str(),LOG_INFO);
m_elog_level = level;
}
bool server::test_alog_level(uint16_t level) {
return ((level & m_alog_level) != 0);
}
void server::set_alog_level(uint16_t level) {
if (test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being set";
access_log(msg.str(),ALOG_INFO);
m_alog_level |= level;
}
void server::unset_alog_level(uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being unset";
access_log(msg.str(),ALOG_INFO);
m_alog_level &= ~level;
}
bool server::validate_host(std::string host) {
if (m_hosts.find(host) == m_hosts.end()) {
return false;
}
return true;
}
bool server::validate_message_size(uint64_t val) {
if (val > m_max_message_size) {
return false;
}
return true;
}
void server::log(std::string msg,uint16_t level) {
if (!test_elog_level(level)) {
return;
}
std::cerr << "[Error Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void server::access_log(std::string msg,uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::cout << "[Access Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void server::start_accept() {
// TODO: sanity check whether the session buffer size bound could be reduced
server_session_ptr new_session(new server_session(shared_from_this(),
m_io_service,
m_def_con_handler,
m_max_message_size*2));
m_acceptor.async_accept(
new_session->socket(),
boost::bind(
&server::handle_accept,
this,
new_session,
boost::asio::placeholders::error
)
);
}
void server::handle_accept(websocketpp::server_session_ptr session,
const boost::system::error_code& error) {
if (!error) {
session->on_connect();
} else {
std::stringstream err;
err << "Error accepting socket connection: " << error;
log(err.str(),LOG_ERROR);
throw server_error(err.str());
}
this->start_accept();
}
-129
View File
@@ -1,129 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_SERVER_HPP
#define WEBSOCKET_SERVER_HPP
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <set>
namespace websocketpp {
class server;
typedef boost::shared_ptr<server> server_ptr;
}
#include "websocketpp.hpp"
#include "websocket_server_session.hpp"
#include "websocket_connection_handler.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class server_error : public std::exception {
public:
server_error(const std::string& msg)
: m_msg(msg) {}
~server_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
private:
std::string m_msg;
};
class server : public boost::enable_shared_from_this<server> {
public:
server(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint,
connection_handler_ptr defc);
// creates a new session object and connects the next websocket
// connection to it.
void start_accept();
// INTERFACE FOR LOCAL APPLICATIONS
// Add or remove a host string (host:port) to the list of acceptable
// hosts to accept websocket connections from. Additions/deletions here
// only affect new connections.
void add_host(std::string host);
void remove_host(std::string host);
void set_max_message_size(uint64_t val);
// Test methods determine if a message of the given level should be
// written. elog shows all values above the level set. alog shows only
// the values explicitly set.
bool test_elog_level(uint16_t level);
void set_elog_level(uint16_t level);
bool test_alog_level(uint16_t level);
void set_alog_level(uint16_t level);
void unset_alog_level(uint16_t level);
void parse_command_line(int ac, char* av[]);
// INTERFACE FOR SESSIONS
// Check if this server will respond to this host.
bool validate_host(std::string host);
// Check if message size is within server's acceptable parameters
bool validate_message_size(uint64_t val);
// write to the server's logs
void log(std::string msg,uint16_t level = LOG_ERROR);
void access_log(std::string msg,uint16_t level);
private:
// if no errors starts the session's read loop and returns to the
// start_accept phase.
void handle_accept(server_session_ptr session,
const boost::system::error_code& error);
private:
uint16_t m_elog_level;
uint16_t m_alog_level;
std::set<std::string> m_hosts;
uint64_t m_max_message_size;
boost::asio::io_service& m_io_service;
tcp::acceptor m_acceptor;
connection_handler_ptr m_def_con_handler;
po::options_description m_desc;
po::variables_map m_vm;
};
}
#endif // WEBSOCKET_SERVER_HPP
-362
View File
@@ -1,362 +0,0 @@
/*
* Copyright (c) 2011, 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.hpp"
#include "websocket_server_session.hpp"
#include "websocket_frame.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using websocketpp::server_session;
server_session::server_session(websocketpp::server_ptr s,
boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc,
uint64_t buf_size)
: session(io_service,defc,buf_size),m_server(s) {}
void server_session::on_connect() {
read_handshake();
}
void server_session::set_header(const std::string &key,const std::string &val) {
// TODO: prevent use of reserved headers;
m_server_headers[key] = val;
}
void server_session::select_subprotocol(const std::string& val) {
std::vector<std::string>::iterator it;
it = std::find(m_client_subprotocols.begin(),
m_client_subprotocols.end(),
val);
if (val != "" && it == m_client_subprotocols.end()) {
throw server_error("Attempted to choose a subprotocol not proposed by the client");
}
m_server_subprotocol = val;
}
void server_session::select_extension(const std::string& val) {
if (val == "") {
return;
}
std::vector<std::string>::iterator it;
it = std::find(m_client_extensions.begin(),
m_client_extensions.end(),
val);
if (it == m_client_extensions.end()) {
throw server_error("Attempted to choose an extension not proposed by the client");
}
m_server_extensions.push_back(val);
}
void server_session::read_handshake() {
m_timer.expires_from_now(boost::posix_time::seconds(5));
m_timer.async_wait(
boost::bind(
&session::handle_handshake_expired,
shared_from_this(),
boost::asio::placeholders::error
)
);
boost::asio::async_read_until(
m_socket,
m_buf,
"\r\n\r\n",
boost::bind(
&session::handle_read_handshake,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void server_session::handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) {
std::ostringstream line;
line << &m_buf;
m_raw_client_handshake += line.str();
access_log(m_raw_client_handshake,ALOG_HANDSHAKE);
std::vector<std::string> tokens;
std::string::size_type start = 0;
std::string::size_type end;
// Get request and parse headers
end = m_raw_client_handshake.find("\r\n",start);
while(end != std::string::npos) {
tokens.push_back(m_raw_client_handshake.substr(start, end - start));
start = end + 2;
end = m_raw_client_handshake.find("\r\n",start);
}
for (size_t i = 0; i < tokens.size(); i++) {
if (i == 0) {
m_client_http_request = tokens[i];
}
end = tokens[i].find(": ",0);
if (end != std::string::npos) {
std::string h = tokens[i].substr(0,end);
if (get_client_header(h) == "") {
m_client_headers[h] = tokens[i].substr(end+2);
} else {
m_client_headers[h] += ", " + tokens[i].substr(end+2);
}
}
}
// handshake error checking
try {
std::stringstream err;
std::string h;
// check the method
if (m_client_http_request.substr(0,4) != "GET ") {
err << "Websocket handshake has invalid method: "
<< m_client_http_request.substr(0,4);
throw(handshake_error(err.str(),400));
}
// check the HTTP version
// TODO: allow versions greater than 1.1
end = m_client_http_request.find(" HTTP/1.1",4);
if (end == std::string::npos) {
err << "Websocket handshake has invalid HTTP version";
throw(handshake_error(err.str(),400));
}
m_resource = m_client_http_request.substr(4,end-4);
// verify the presence of required headers
h = get_client_header("Host");
if (h == "") {
throw(handshake_error("Required Host header is missing",400));
} else if (!m_server->validate_host(h)) {
err << "Host " << h << " is not one of this server's names.";
throw(handshake_error(err.str(),400));
}
h = get_client_header("Upgrade");
if (h == "") {
throw(handshake_error("Required Upgrade header is missing",400));
} else if (!boost::iequals(h,"websocket")) {
err << "Upgrade header was " << h << " instead of \"websocket\"";
throw(handshake_error(err.str(),400));
}
h = get_client_header("Connection");
if (h == "") {
throw(handshake_error("Required Connection header is missing",400));
} else if (!boost::ifind_first(h,"upgrade")) {
err << "Connection header, \"" << h
<< "\", does not contain required token \"upgrade\"";
throw(handshake_error(err.str(),400));
}
if (get_client_header("Sec-WebSocket-Key") == "") {
throw(handshake_error("Required Sec-WebSocket-Key header is missing",400));
}
h = get_client_header("Sec-WebSocket-Version");
if (h == "") {
throw(handshake_error("Required Sec-WebSocket-Version header is missing",400));
} else {
m_version = atoi(h.c_str());
if (m_version != 7 && m_version != 8 && m_version != 13) {
err << "This server doesn't support WebSocket protocol version "
<< m_version;
throw(handshake_error(err.str(),400));
}
}
if (m_version < 13) {
h = get_client_header("Sec-WebSocket-Origin");
} else {
h = get_client_header("Origin");
}
if (h != "") {
m_client_origin = h;
}
// TODO: extract subprotocols
// TODO: extract extensions
// optional headers (delegated to the local interface)
if (m_local_interface) {
m_local_interface->validate(shared_from_this());
}
m_server_http_code = 101;
m_server_http_string = "Switching Protocols";
} catch (const handshake_error& e) {
std::stringstream err;
err << "Caught handshake exception: " << e.what();
access_log(e.what(),ALOG_HANDSHAKE);
log(err.str(),LOG_ERROR);
m_server_http_code = e.m_http_error_code;
m_server_http_string = e.m_http_error_msg;
}
write_handshake();
}
void server_session::write_handshake() {
std::stringstream h;
if (m_server_http_code == 101) {
std::string server_key = get_client_header("Sec-WebSocket-Key");
server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1 sha;
uint32_t message_digest[5];
sha.Reset();
sha << server_key.c_str();
if (sha.Result(message_digest)){
// convert sha1 hash bytes to network byte order because this sha1
// library works on ints rather than bytes
for (int i = 0; i < 5; i++) {
message_digest[i] = htonl(message_digest[i]);
}
server_key = base64_encode(
reinterpret_cast<const unsigned char*>(message_digest),20);
// set handshake accept headers
set_header("Sec-WebSocket-Accept",server_key);
set_header("Upgrade","websocket");
set_header("Connection","Upgrade");
} else {
log("Error computing handshake sha1 hash.",LOG_ERROR);
m_server_http_code = 500;
m_server_http_string = "";
}
}
// hardcoded server headers
set_header("Server","WebSocket++/2011-09-25");
h << "HTTP/1.1 " << m_server_http_code << " "
<< (m_server_http_string != "" ? m_server_http_string :
lookup_http_error_string(m_server_http_code))
<< "\r\n";
header_list::iterator it;
for (it = m_server_headers.begin(); it != m_server_headers.end(); it++) {
h << it->first << ": " << it->second << "\r\n";
}
h << "\r\n";
m_raw_server_handshake = h.str();
// start async write to handle_write_handshake
boost::asio::async_write(
m_socket,
boost::asio::buffer(m_raw_server_handshake),
boost::bind(
&session::handle_write_handshake,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
void server_session::handle_write_handshake(const boost::system::error_code& error) {
if (error) {
log_error("Error writing handshake response",error);
drop_tcp();
return;
}
log_open_result();
if (m_server_http_code != 101) {
std::stringstream err;
err << "Handshake ended with HTTP error: " << m_server_http_code << " "
<< (m_server_http_string != "" ? m_server_http_string : lookup_http_error_string(m_server_http_code));
log(err.str(),LOG_ERROR);
drop_tcp();
// TODO: tell client that connection failed.
return;
}
m_state = STATE_OPEN;
// stop the handshake timer
m_timer.cancel();
if (m_local_interface) {
m_local_interface->on_open(shared_from_this());
}
reset_message();
this->read_frame();
}
void server_session::log(const std::string& msg, uint16_t level) const {
m_server->log(msg,level);
}
void server_session::access_log(const std::string& msg, uint16_t level) const {
m_server->access_log(msg,level);
}
-118
View File
@@ -1,118 +0,0 @@
/*
* Copyright (c) 2011, 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 WEBSOCKET_SERVER_SESSION_HPP
#define WEBSOCKET_SERVER_SESSION_HPP
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
#include <exception>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace websocketpp {
class server_session;
typedef boost::shared_ptr<server_session> server_session_ptr;
}
#include "websocket_session.hpp"
#include "websocket_server.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class server_session : public session {
public:
server_session (server_ptr s,
boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size);
/*** SERVER INTERFACE ***/
// This function is called when a connection to a new client has been
// established and the server is ready to read the client handshake.
void on_connect();
/*** HANDSHAKE INTERFACE ***/
// Set an HTTP header for the outgoing server handshake response.
void set_header(const std::string& key, const std::string& val);
// Selects a subprotocol for the connection to use. val must be a value
// present in the client's opening handshake or the empty string for null.
void select_subprotocol(const std::string& val);
// Selects an extension from the list offered by the client. Each extension
// selected must have been offered by the client. Extensions will be used
// in the order that they were selected here.
void select_extension(const std::string& val);
/*** SESSION INTERFACE ***/
// see session
virtual bool is_server() const { return true;}
void log(const std::string& msg, uint16_t level) const;
void access_log(const std::string& msg, uint16_t level) const;
protected:
// Opening handshake processors and callbacks. These need to be defined in
virtual void write_handshake();
virtual void handle_write_handshake(const boost::system::error_code& e);
virtual void read_handshake();
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred);
private:
protected:
// connection resources
server_ptr m_server;
private:
};
}
#endif // WEBSOCKET_SERVER_SESSION_HPP
-738
View File
@@ -1,738 +0,0 @@
/*
* Copyright (c) 2011, 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.hpp"
#include "websocket_session.hpp"
#include "websocket_frame.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using websocketpp::session;
session::session (boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc,
uint64_t buf_size)
: m_state(STATE_CONNECTING),
m_writing(false),
m_local_close_code(CLOSE_STATUS_NO_STATUS),
m_remote_close_code(CLOSE_STATUS_NO_STATUS),
m_was_clean(false),
m_closed_by_me(false),
m_dropped_by_me(false),
m_socket(io_service),
m_io_service(io_service),
m_local_interface(defc),
m_timer(io_service,boost::posix_time::seconds(0)),
m_buf(buf_size), // maximum buffered (unconsumed) bytes from network
m_utf8_state(utf8_validator::UTF8_ACCEPT),
m_utf8_codepoint(0) {}
tcp::socket& session::socket() {
return m_socket;
}
boost::asio::io_service& session::io_service() {
return m_io_service;
}
void session::set_handler(websocketpp::connection_handler_ptr new_con) {
if (m_local_interface) {
// TODO: this should be another method and not reusing onclose
//m_local_interface->disconnect(shared_from_this(),4000,"Setting new connection handler");
}
m_local_interface = new_con;
m_local_interface->on_open(shared_from_this());
}
const std::string& session::get_subprotocol() const {
if (m_state == STATE_CONNECTING) {
log("Subprotocol is not avaliable before the handshake has completed.",LOG_WARN);
throw server_error("Subprotocol is not avaliable before the handshake has completed.");
}
return m_server_subprotocol;
}
const std::string& session::get_resource() const {
return m_resource;
}
const std::string& session::get_origin() const {
return m_client_origin;
}
std::string session::get_client_header(const std::string& key) const {
return get_header(key,m_client_headers);
}
std::string session::get_server_header(const std::string& key) const {
return get_header(key,m_server_headers);
}
std::string session::get_header(const std::string& key,
const websocketpp::header_list& list) const {
header_list::const_iterator h = list.find(key);
if (h == list.end()) {
return "";
} else {
return h->second;
}
}
const std::vector<std::string>& session::get_extensions() const {
return m_server_extensions;
}
unsigned int session::get_version() const {
return m_version;
}
void session::send(const std::string &msg) {
if (m_state != STATE_OPEN) {
log("Tried to send a message from a session that wasn't open",LOG_WARN);
return;
}
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::TEXT_FRAME);
m_write_frame.set_payload(msg);
write_frame();
}
void session::send(const std::vector<unsigned char> &data) {
if (m_state != STATE_OPEN) {
log("Tried to send a message from a session that wasn't open",LOG_WARN);
return;
}
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::BINARY_FRAME);
m_write_frame.set_payload(data);
write_frame();
}
// end user interface to close the connection
void session::close(uint16_t status,const std::string& msg) {
validate_app_close_status(status);
send_close(status,msg);
}
// TODO: clean this up, needs to be broken out into more specific methods
// This method initiates a clean disconnect with the given status code and reason
// it logs an error and is ignored if it is called from a state other than OPEN
// called by process_close when an initiate close method is received.
void session::send_close(uint16_t status,const std::string &message) {
if (m_state != STATE_OPEN) {
log("Tried to disconnect a session that wasn't open",LOG_WARN);
return;
}
m_state = STATE_CLOSING;
m_timer.expires_from_now(boost::posix_time::milliseconds(1000));
m_timer.async_wait(
boost::bind(
&session::handle_close_expired,
shared_from_this(),
boost::asio::placeholders::error
)
);
m_local_close_code = status;
m_local_close_msg = message;
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::CONNECTION_CLOSE);
// echo close value unless there is a good reason not to.
if (status == CLOSE_STATUS_NO_STATUS) {
m_write_frame.set_status(CLOSE_STATUS_NORMAL,"");
} else if (status == CLOSE_STATUS_ABNORMAL_CLOSE) {
// Internal implimentation error. There is no good close code for this.
m_write_frame.set_status(CLOSE_STATUS_POLICY_VIOLATION,message);
} else if (close::status::invalid(status)) {
m_write_frame.set_status(close::status::PROTOCOL_ERROR,"Status code is invalid");
} else if (close::status::reserved(status)) {
m_write_frame.set_status(close::status::PROTOCOL_ERROR,"Status code is reserved");
} else {
m_write_frame.set_status(status,message);
}
write_frame();
}
void session::ping(const std::string &msg) {
if (m_state != STATE_OPEN) {
log("Tried to send a ping from a session that wasn't open",LOG_WARN);
return;
}
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::PING);
m_write_frame.set_payload(msg);
write_frame();
}
void session::pong(const std::string &msg) {
if (m_state != STATE_OPEN) {
log("Tried to send a pong from a session that wasn't open",LOG_WARN);
return;
}
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::PONG);
m_write_frame.set_payload(msg);
write_frame();
}
void session::read_frame() {
// the initial read in the handshake may have read in the first frame.
// handle it (if it exists) before we read anything else.
handle_read_frame(boost::system::error_code());
}
// handle_read_frame reads and processes all socket read commands for the
// session by consuming the read buffer and then starting an async read with
// itself as the callback. The connection is over when this method returns.
void session::handle_read_frame(const boost::system::error_code& error) {
if (m_state != STATE_OPEN && m_state != STATE_CLOSING) {
log("handle_read_frame called in invalid state",LOG_ERROR);
return;
}
if (error) {
if (error == boost::asio::error::eof) {
// if this is a case where we are expecting eof, return, else log & drop
log_error("Recieved EOF",error);
//drop_tcp(false);
//m_state = STATE_CLOSED;
} else if (error == boost::asio::error::operation_aborted) {
// some other part of our client called shutdown on our socket.
// This is usually due to a write error. Everything should have
// already been logged and dropped so we just return here
return;
} else {
log_error("Error reading frame",error);
//drop_tcp(false);
m_state = STATE_CLOSED;
}
}
std::istream s(&m_buf);
while (m_buf.size() > 0 && m_state != STATE_CLOSED) {
try {
if (m_read_frame.get_bytes_needed() == 0) {
throw frame_error("have bytes that no frame needs",frame::FERR_FATAL_SESSION_ERROR);
}
// Consume will read bytes from s
// will throw a frame_error on error.
std::stringstream err;
err << "consuming. have: " << m_buf.size() << " bytes. Need: " << m_read_frame.get_bytes_needed() << " state: " << (int)m_read_frame.get_state();
log(err.str(),LOG_DEBUG);
m_read_frame.consume(s);
err.str("");
err << "consume complete, " << m_buf.size() << " bytes left, " << m_read_frame.get_bytes_needed() << " still needed, state: " << (int)m_read_frame.get_state();
log(err.str(),LOG_DEBUG);
if (m_read_frame.get_state() == frame::STATE_READY) {
// process frame and reset frame state for the next frame.
// will throw a frame_error on error. May set m_state to CLOSED,
// if so no more frames should be processed.
err.str("");
err << "processing frame " << m_buf.size();
log(err.str(),LOG_DEBUG);
m_timer.cancel();
process_frame();
}
} catch (const frame_error& e) {
std::stringstream err;
err << "Caught frame exception: " << e.what();
access_log(e.what(),ALOG_FRAME);
log(err.str(),LOG_ERROR);
// if the exception happened while processing.
// TODO: this is not elegant, perhaps separate frame read vs process
// exceptions need to be used.
if (m_read_frame.get_state() == frame::STATE_READY) {
m_read_frame.reset();
}
// process different types of frame errors
//
if (e.code() == frame::FERR_PROTOCOL_VIOLATION) {
send_close(CLOSE_STATUS_PROTOCOL_ERROR, e.what());
} else if (e.code() == frame::FERR_PAYLOAD_VIOLATION) {
send_close(CLOSE_STATUS_INVALID_PAYLOAD, e.what());
} else if (e.code() == frame::FERR_INTERNAL_SERVER_ERROR) {
send_close(CLOSE_STATUS_ABNORMAL_CLOSE, e.what());
} else if (e.code() == frame::FERR_SOFT_SESSION_ERROR) {
// ignore and continue processing frames
continue;
} else {
// Fatal error, forcibly end connection immediately.
log("Dropping TCP due to unrecoverable exception",LOG_DEBUG);
drop_tcp(true);
}
break;
}
}
if (error == boost::asio::error::eof) {
m_state = STATE_CLOSED;
}
// we have read everything, check if we should read more
if ((m_state == STATE_OPEN || m_state == STATE_CLOSING) && m_read_frame.get_bytes_needed() > 0) {
std::stringstream msg;
msg << "starting async read for " << m_read_frame.get_bytes_needed() << " bytes.";
log(msg.str(),LOG_DEBUG);
// TODO: set a timer here in case we don't want to read forever.
// Ex: when the frame is in a degraded state.
boost::asio::async_read(
m_socket,
m_buf,
boost::asio::transfer_at_least(m_read_frame.get_bytes_needed()),
boost::bind(
&session::handle_read_frame,
shared_from_this(),
boost::asio::placeholders::error
)
);
} else if (m_state == STATE_CLOSED) {
log_close_result();
if (m_local_interface) {
// TODO: make sure close code/msg are properly set.
m_local_interface->on_close(shared_from_this());
}
m_timer.cancel();
} else {
log("handle_read_frame called in invalid state",LOG_ERROR);
}
}
void session::process_frame () {
log("process_frame",LOG_DEBUG);
if (m_state == STATE_OPEN) {
switch (m_read_frame.get_opcode()) {
case frame::CONTINUATION_FRAME:
process_continuation();
break;
case frame::TEXT_FRAME:
process_text();
break;
case frame::BINARY_FRAME:
process_binary();
break;
case frame::CONNECTION_CLOSE:
log("process_close",LOG_DEBUG);
process_close();
break;
case frame::PING:
process_ping();
break;
case frame::PONG:
process_pong();
break;
default:
throw frame_error("Invalid Opcode",
frame::FERR_PROTOCOL_VIOLATION);
break;
}
} else if (m_state == STATE_CLOSING) {
if (m_read_frame.get_opcode() == frame::CONNECTION_CLOSE) {
process_close();
} else {
// Ignore all other frames in closing state
log("ignoring this frame",LOG_DEBUG);
}
} else {
// Recieved message before or after connection was opened/closed
throw frame_error("process_frame called from invalid state");
}
m_read_frame.reset();
}
void session::handle_write_frame (const boost::system::error_code& error) {
if (error) {
log_error("Error writing frame data",error);
drop_tcp(false);
}
access_log("handle_write_frame complete",ALOG_FRAME);
m_writing = false;
}
void session::handle_timer_expired (const boost::system::error_code& error) {
if (error) {
if (error == boost::asio::error::operation_aborted) {
log("timer was aborted",LOG_DEBUG);
//drop_tcp(false);
} else {
log("timer ended with error",LOG_DEBUG);
}
return;
}
log("timer ended without error",LOG_DEBUG);
}
void session::handle_handshake_expired (const boost::system::error_code& error) {
if (error) {
if (error != boost::asio::error::operation_aborted) {
log("Unexpected handshake timer error.",LOG_DEBUG);
drop_tcp(true);
}
return;
}
log("Handshake timed out",LOG_DEBUG);
drop_tcp(true);
}
// The error timer is set when we want to give the other endpoint some time to
// do something but don't want to wait forever. There is a special error code
// that represents the timer being canceled by us (because the other endpoint
// responded in time. All other cases should assume that the other endpoint is
// irrepairibly broken and drop the TCP connection.
void session::handle_error_timer_expired (const boost::system::error_code& error) {
if (error) {
if (error == boost::asio::error::operation_aborted) {
log("error timer was aborted",LOG_DEBUG);
//drop_tcp(false);
} else {
log("error timer ended with error",LOG_DEBUG);
drop_tcp(true);
}
return;
}
log("error timer ended without error",LOG_DEBUG);
drop_tcp(true);
}
void session::handle_close_expired (const boost::system::error_code& error) {
if (error) {
if (error == boost::asio::error::operation_aborted) {
log("timer was aborted",LOG_DEBUG);
//drop_tcp(false);
} else {
log("Unexpected close timer error.",LOG_DEBUG);
drop_tcp(false);
}
return;
}
if (m_state != STATE_CLOSED) {
log("close timed out",LOG_DEBUG);
drop_tcp(false);
}
}
void session::process_ping() {
access_log("Ping",ALOG_MISC_CONTROL);
// TODO: on_ping
// send pong
m_write_frame.set_fin(true);
m_write_frame.set_opcode(frame::PONG);
m_write_frame.set_payload(m_read_frame.get_payload());
write_frame();
}
void session::process_pong() {
access_log("Pong",ALOG_MISC_CONTROL);
// TODO: on_pong
}
void session::process_text() {
// this will throw an exception if validation fails at any point
m_read_frame.validate_utf8(&m_utf8_state,&m_utf8_codepoint);
// otherwise, treat as binary
process_binary();
}
void session::process_binary() {
if (m_fragmented) {
throw frame_error("Got a new message before the previous was finished.",
frame::FERR_PROTOCOL_VIOLATION);
}
m_current_opcode = m_read_frame.get_opcode();
if (m_read_frame.get_fin()) {
deliver_message();
reset_message();
} else {
m_fragmented = true;
extract_payload();
}
}
void session::process_continuation() {
if (!m_fragmented) {
throw frame_error("Got a continuation frame without an outstanding message.",
frame::FERR_PROTOCOL_VIOLATION);
}
if (m_current_opcode == frame::TEXT_FRAME) {
// this will throw an exception if validation fails at any point
m_read_frame.validate_utf8(&m_utf8_state,&m_utf8_codepoint);
}
extract_payload();
// check if we are done
if (m_read_frame.get_fin()) {
deliver_message();
reset_message();
}
}
void session::process_close() {
m_remote_close_code = m_read_frame.get_close_status();
m_remote_close_msg = m_read_frame.get_close_msg();
if (m_state == STATE_OPEN) {
log("process_close sending ack",LOG_DEBUG);
// This is the case where the remote initiated the close.
m_closed_by_me = false;
// send acknowledgement
// check if the remote close code
if (m_remote_close_code >= close::status::RSV_START) {
}
send_close(m_remote_close_code,m_remote_close_msg);
} else if (m_state == STATE_CLOSING) {
log("process_close got ack",LOG_DEBUG);
// this is an ack of our close message
m_closed_by_me = true;
} else {
throw frame_error("process_closed called from wrong state");
}
m_was_clean = true;
m_state = STATE_CLOSED;
}
void session::deliver_message() {
if (!m_local_interface) {
return;
}
if (m_current_opcode == frame::BINARY_FRAME) {
//log("Dispatching Binary Message",LOG_DEBUG);
if (m_fragmented) {
m_local_interface->on_message(shared_from_this(),m_current_message);
} else {
m_local_interface->on_message(shared_from_this(),
m_read_frame.get_payload());
}
} else if (m_current_opcode == frame::TEXT_FRAME) {
std::string msg;
// make sure the finished frame is valid utf8
// the streaming validator checks for bad codepoints as it goes. It
// doesn't know where the end of the message is though, so we need to
// check here to make sure the final message ends on a valid codepoint.
if (m_utf8_state != utf8_validator::UTF8_ACCEPT) {
throw frame_error("Invalid UTF-8 Data",
frame::FERR_PAYLOAD_VIOLATION);
}
if (m_fragmented) {
msg.append(m_current_message.begin(),m_current_message.end());
} else {
msg.append(
m_read_frame.get_payload().begin(),
m_read_frame.get_payload().end()
);
}
//log("Dispatching Text Message",LOG_DEBUG);
m_local_interface->on_message(shared_from_this(),msg);
} else {
// Not sure if this should be a fatal error or not
std::stringstream err;
err << "Attempted to deliver a message of unsupported opcode " << m_current_opcode;
throw frame_error(err.str(),frame::FERR_SOFT_SESSION_ERROR);
}
}
void session::extract_payload() {
std::vector<unsigned char> &msg = m_read_frame.get_payload();
m_current_message.resize(m_current_message.size()+msg.size());
std::copy(msg.begin(),msg.end(),m_current_message.end()-msg.size());
}
void session::write_frame() {
if (!is_server()) {
m_write_frame.set_masked(true); // client must mask frames
}
m_write_frame.process_payload();
std::vector<boost::asio::mutable_buffer> data;
data.push_back(
boost::asio::buffer(
m_write_frame.get_header(),
m_write_frame.get_header_len()
)
);
data.push_back(
boost::asio::buffer(m_write_frame.get_payload())
);
log("Write Frame: "+m_write_frame.print_frame(),LOG_DEBUG);
m_writing = true;
boost::asio::async_write(
m_socket,
data,
boost::bind(
&session::handle_write_frame,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
void session::reset_message() {
m_error = false;
m_fragmented = false;
m_current_message.clear();
m_utf8_state = utf8_validator::UTF8_ACCEPT;
m_utf8_codepoint = 0;
}
void session::log_close_result() {
std::stringstream msg;
msg << "[Connection " << this << "] "
<< (m_was_clean ? "Clean " : "Unclean ")
<< "close local:[" << m_local_close_code
<< (m_local_close_msg == "" ? "" : ","+m_local_close_msg)
<< "] remote:[" << m_remote_close_code
<< (m_remote_close_msg == "" ? "" : ","+m_remote_close_msg) << "]";
access_log(msg.str(),ALOG_DISCONNECT);
}
void session::log_open_result() {
std::stringstream msg;
msg << "[Connection " << this << "] "
<< m_socket.remote_endpoint()
<< " v" << m_version << " "
<< (get_client_header("User-Agent") == "" ? "NULL" : get_client_header("User-Agent"))
<< " " << m_resource << " " << m_server_http_code;
access_log(msg.str(),ALOG_HANDSHAKE);
}
// this is called when an async asio call encounters an error
void session::log_error(std::string msg,const boost::system::error_code& e) {
std::stringstream err;
err << "[Connection " << this << "] " << msg << " (" << e << ")";
log(err.str(),LOG_ERROR);
}
// validates status codes that the end application is allowed to use
bool session::validate_app_close_status(uint16_t status) {
if (status == CLOSE_STATUS_NORMAL) {
return true;
}
if (status >= 4000 && status < 5000) {
return true;
}
return false;
}
void session::drop_tcp(bool dropped_by_me) {
m_timer.cancel();
try {
if (m_socket.is_open()) {
m_socket.shutdown(tcp::socket::shutdown_both);
m_socket.close();
}
} catch (boost::system::system_error& e) {
if (e.code() == boost::asio::error::not_connected) {
// this means the socket was disconnected by the other side before
// we had a chance to. Ignore and continue.
} else {
throw e;
}
}
m_dropped_by_me = dropped_by_me;
m_state = STATE_CLOSED;
}
-328
View File
@@ -1,328 +0,0 @@
/*
* Copyright (c) 2011, 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.
*
*/
/*
Exit path mapping
In every path:
- If it is safe to close cleanly, close cleanly
- Write to the access log on clean close
- Write to the error log on unclean close and clean closes with a server error.
- If session state is open and a local client is connected, send on_close msg
- make sure the following bits are properly set:
- If we initiated the close by sending the first close frame or by dropping the TCP connection, set closed_by_me. If the other endpoint sent the first close method or we got an EOF while reading clear closed_by_me
- If we initiated the TCP connection drop set dropped_by_me. If we got EOF while reading clear dropped_by_me
- If we sent and received a close frame or we received and sent an acknowledgement close frame set was_clean to true.
- If we are the server we should drop TCP immediately
- If we are the client we should drop TCP immediately except in the case where we just recieved an acknowledgement close frame. In this case wait a certain period of time for the server EOF.
Questions:
- if the client rejects
Paths: (+ indicates path has been checked and implimented)
Server Handshake Paths
- Accept connection, read handshake, handshake is valid, write handshake, no errors. This is the correct path and leads to the frame reading paths
- Accept connection, connection is not in state open after a time out (due to no bytes being read or no CRLFCRLF being read). This needs a time out after which we drop TCP.
- Accept connection, read handshake, handshake is invalid. write HTTP error. drop TCP
- Accept connection, read handshake, handshake is valid, write handshake returns EOF. This means client rejected something about our response. We should drop and notify our client. (note alternative client handshake reject method is to accept the handshake then immediately send a close message with the non-acceptance reason)
- Accept connection, read handshake, handshake is valid, write handshake returns another error. We should drop and notify our client.
Client Handshake Paths
-
Server Frame Reading Paths
- async read returns EOF. Close our own socket and notify our local interface.
- async read returns another error
Timeouts:
- handshake timeout
- wait for close frame after error
- (client) wait for server to drop tcp after close handshake
- idle client timeout? API specifiable?
- wait for pong?
*/
#ifndef WEBSOCKET_SESSION_HPP
#define WEBSOCKET_SESSION_HPP
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
#include <exception>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace websocketpp {
class session;
typedef boost::shared_ptr<session> session_ptr;
class handshake_error;
}
#include "websocketpp.hpp"
#include "websocket_frame.hpp"
#include "websocket_connection_handler.hpp"
#include "base64/base64.h"
#include "sha1/sha1.h"
using boost::asio::ip::tcp;
namespace websocketpp {
typedef std::map<std::string,std::string> header_list;
class session : public boost::enable_shared_from_this<session> {
public:
friend class handshake_error;
static const uint8_t STATE_CONNECTING = 0;
static const uint8_t STATE_OPEN = 1;
static const uint8_t STATE_CLOSING = 2;
static const uint8_t STATE_CLOSED = 3;
static const uint16_t CLOSE_STATUS_NORMAL = 1000;
static const uint16_t CLOSE_STATUS_GOING_AWAY = 1001;
static const uint16_t CLOSE_STATUS_PROTOCOL_ERROR = 1002;
static const uint16_t CLOSE_STATUS_UNSUPPORTED_DATA = 1003;
static const uint16_t CLOSE_STATUS_NO_STATUS = 1005;
static const uint16_t CLOSE_STATUS_ABNORMAL_CLOSE = 1006;
static const uint16_t CLOSE_STATUS_INVALID_PAYLOAD = 1007;
static const uint16_t CLOSE_STATUS_POLICY_VIOLATION = 1008;
static const uint16_t CLOSE_STATUS_MESSAGE_TOO_BIG = 1009;
static const uint16_t CLOSE_STATUS_EXTENSION_REQUIRE = 1010;
static const uint16_t CLOSE_STATUS_MAXIMUM = 1011;
session (boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size);
tcp::socket& socket();
boost::asio::io_service& io_service();
/*** SERVER INTERFACE ***/
// This function is called to begin the session loop. This method and all
// that come after it are called as a result of an async event completing.
// if any method in this chain returns before adding a new async event the
// session will end.
virtual void on_connect() = 0;
// sets the internal connection handler of this connection to new_con.
// This is useful if you want to switch handler objects during a connection
// Example: a generic lobby handler could validate the handshake negotiate a
// sub protocol to talk to and then pass the connection off to a handler for
// that sub protocol.
void set_handler(connection_handler_ptr new_con);
/*** HANDSHAKE INTERFACE ***/
// Set session connection information (avaliable only before/during the
// opening handshake)
// Get session status (valid once the connection is open)
// returns the subprotocol that was negotiated during the opening handshake
// or the empty string if no subprotocol was requested.
const std::string& get_subprotocol() const;
const std::string& get_resource() const;
const std::string& get_origin() const;
std::string get_client_header(const std::string& key) const;
std::string get_server_header(const std::string& key) const;
const std::vector<std::string>& get_extensions() const;
unsigned int get_version() const;
/*** SESSION INTERFACE ***/
// send basic frame types
void send(const std::string &msg); // text
void send(const std::vector<unsigned char> &data); // binary
void ping(const std::string &msg);
void pong(const std::string &msg);
// initiate a connection close
void close(uint16_t status,const std::string &reason);
virtual bool is_server() const = 0;
// Opening handshake processors and callbacks. These need to be defined in
// derived classes.
virtual void handle_write_handshake(const boost::system::error_code& e) = 0;
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) = 0;
public: //protected:
virtual void write_handshake() = 0;
virtual void read_handshake() = 0;
void read_frame();
void handle_read_frame (const boost::system::error_code& error);
// write m_write_frame out to the socket.
void write_frame();
void handle_write_frame (const boost::system::error_code& error);
void handle_timer_expired(const boost::system::error_code& error);
void handle_handshake_expired(const boost::system::error_code& error);
void handle_close_expired(const boost::system::error_code& error);
void handle_error_timer_expired (const boost::system::error_code& error);
// helper functions for processing each opcode
void process_frame();
void process_ping();
void process_pong();
void process_text();
void process_binary();
void process_continuation();
void process_close();
// deliver message if we have a local interface attached
void deliver_message();
// copies the current read frame payload into the session so that the read
// frame can be cleared for the next read. This is done when fragmented
// messages are recieved.
void extract_payload();
// reset session for a new message
void reset_message();
// logging
virtual void log(const std::string& msg, uint16_t level) const = 0;
virtual void access_log(const std::string& msg, uint16_t level) const = 0;
void log_close_result();
void log_open_result();
void log_error(std::string msg,const boost::system::error_code& e);
// misc helpers
bool validate_app_close_status(uint16_t status);
void send_close(uint16_t status,const std::string& reason);
void drop_tcp(bool dropped_by_me = true);
private:
std::string get_header(const std::string& key,
const header_list& list) const;
protected:
// Immutable state about the current connection from the handshake
// Client handshake
std::string m_raw_client_handshake;
std::string m_client_http_request;
std::string m_resource;
std::string m_client_origin;
header_list m_client_headers;
std::vector<std::string> m_client_subprotocols;
std::vector<std::string> m_client_extensions;
unsigned int m_version;
// Server handshake
std::string m_raw_server_handshake;
std::string m_server_http_request;
header_list m_server_headers;
std::string m_server_subprotocol;
std::vector<std::string> m_server_extensions;
uint16_t m_server_http_code;
std::string m_server_http_string;
// Mutable connection state;
uint8_t m_state;
bool m_writing;
// Close state
uint16_t m_local_close_code;
std::string m_local_close_msg;
uint16_t m_remote_close_code;
std::string m_remote_close_msg;
bool m_was_clean;
bool m_closed_by_me;
bool m_dropped_by_me;
// Connection Resources
tcp::socket m_socket;
boost::asio::io_service& m_io_service;
connection_handler_ptr m_local_interface;
boost::asio::deadline_timer m_timer;
// Buffers
boost::asio::streambuf m_buf;
// current message state
uint32_t m_utf8_state;
uint32_t m_utf8_codepoint;
std::vector<unsigned char> m_current_message;
bool m_fragmented;
frame::opcode m_current_opcode;
// current frame state
frame m_read_frame;
// unorganized
frame m_write_frame;
bool m_error;
};
// Exception classes
class handshake_error : public std::exception {
public:
handshake_error(const std::string& msg,
int http_error,
const std::string& http_msg = "")
: m_msg(msg),m_http_error_code(http_error),m_http_error_msg(http_msg) {}
~handshake_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
std::string m_msg;
int m_http_error_code;
std::string m_http_error_msg;
};
}
#endif // WEBSOCKET_SESSION_HPP
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (c) 2011, 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.
*
* This Makefile was derived from a similar one included in the libjson project
* It's authors were Jonathan Wallace and Bernhard Fluehmann.
*/
#ifndef WEBSOCKETPP_HPP
#define WEBSOCKETPP_HPP
#include <stdint.h>
// Defaults
namespace websocketpp {
const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB
// System logging levels
static const uint16_t LOG_ALL = 0;
static const uint16_t LOG_DEBUG = 1;
static const uint16_t LOG_INFO = 2;
static const uint16_t LOG_WARN = 3;
static const uint16_t LOG_ERROR = 4;
static const uint16_t LOG_FATAL = 5;
static const uint16_t LOG_OFF = 6;
// Access logging controls
// Individual bits
static const uint16_t ALOG_CONNECT = 0x1;
static const uint16_t ALOG_DISCONNECT = 0x2;
static const uint16_t ALOG_MISC_CONTROL = 0x4;
static const uint16_t ALOG_FRAME = 0x8;
static const uint16_t ALOG_MESSAGE = 0x10;
static const uint16_t ALOG_INFO = 0x20;
static const uint16_t ALOG_HANDSHAKE = 0x40;
// Useful groups
static const uint16_t ALOG_OFF = 0x0;
static const uint16_t ALOG_CONTROL = ALOG_CONNECT
& ALOG_DISCONNECT
& ALOG_MISC_CONTROL;
static const uint16_t ALOG_ALL = 0xFFFF;
namespace close {
namespace status {
enum value {
INVALID_END = 999,
NORMAL = 1000,
GOING_AWAY = 1001,
PROTOCOL_ERROR = 1002,
UNSUPPORTED_DATA = 1003,
RSV_ADHOC_1 = 1004,
NO_STATUS = 1005,
ABNORMAL_CLOSE = 1006,
INVALID_PAYLOAD = 1007,
POLICY_VIOLATION = 1008,
MESSAGE_TOO_BIG = 1009,
EXTENSION_REQUIRE = 1010,
RSV_START = 1011,
RSV_END = 2999,
INVALID_START = 5000
};
inline bool reserved(uint16_t s) {
return ((s >= RSV_START && s <= RSV_END) ||
s == RSV_ADHOC_1);
}
inline bool invalid(uint16_t s) {
return ((s <= INVALID_END || s >= INVALID_START) ||
s == NO_STATUS ||
s == ABNORMAL_CLOSE);
}
}
}
}
#include "websocket_session.hpp"
#include "websocket_server_session.hpp"
#include "websocket_client_session.hpp"
#include "websocket_server.hpp"
#include "websocket_client.hpp"
#endif // WEBSOCKETPP_HPP
-23
View File
@@ -1,23 +0,0 @@
CFLAGS = -O2
LDFLAGS =
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_unit_test_framework -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_unit_test_framework ../../libwebsocketpp.a
endif
tests: parsing.cpp
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o tests
-166
View File
@@ -1,166 +0,0 @@
/*
* Copyright (c) 2011, 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 parsing
#include <boost/test/unit_test.hpp>
#include "../../src/websocketpp.hpp"
// Test a regular valid ws URI
BOOST_AUTO_TEST_CASE( uri_valid ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("ws://localhost:9000/chat") == true);
BOOST_CHECK( uri.secure == false );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/chat" );
}
// Valid URI with no port specified (unsecure)
BOOST_AUTO_TEST_CASE( uri_valid_no_port_unsecure ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("ws://localhost/chat") == true);
BOOST_CHECK( uri.secure == false );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 80 );
BOOST_CHECK( uri.resource == "/chat" );
}
// Valid URI with no port (secure)
BOOST_AUTO_TEST_CASE( uri_valid_no_port_secure ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://localhost/chat") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 443 );
BOOST_CHECK( uri.resource == "/chat" );
}
// Valid URI with no resource
BOOST_AUTO_TEST_CASE( uri_valid_no_resource ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("ws://localhost:9000") == true);
BOOST_CHECK( uri.secure == false );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/" );
}
// Valid URI IPv6 Literal
BOOST_AUTO_TEST_CASE( uri_valid_ipv6_literal ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://[::1]:9000/chat") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "[::1]");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/chat" );
}
// Valid URI with more complicated host
BOOST_AUTO_TEST_CASE( uri_valid_2 ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://thor-websocket.zaphoyd.net:88/") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "thor-websocket.zaphoyd.net");
BOOST_CHECK( uri.port == 88 );
BOOST_CHECK( uri.resource == "/" );
}
// Invalid URI (port too long)
BOOST_AUTO_TEST_CASE( uri_invalid_long_port ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://localhost:900000/chat") == false);
}
// INvalid URI (http method)
BOOST_AUTO_TEST_CASE( uri_invalid_http ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("http://localhost:9000/chat") == false);
}
// Valid URI IPv4 literal
BOOST_AUTO_TEST_CASE( uri_valid_ipv4_literal ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://127.0.0.1:9000/chat") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "127.0.0.1");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/chat" );
}
// Valid URI complicated resource path
BOOST_AUTO_TEST_CASE( uri_valid_3 ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://localhost:9000/chat/foo/bar") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/chat/foo/bar" );
}
// Invalid URI broken method separator
BOOST_AUTO_TEST_CASE( uri_invalid_method_separator ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss:/localhost:9000/chat") == false);
}
// Invalid URI port > 65535
BOOST_AUTO_TEST_CASE( uri_invalid_gt_16_bit_port ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss:/localhost:70000/chat") == false);
}
// Invalid URI includes uri fragment
BOOST_AUTO_TEST_CASE( uri_invalid_fragment ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss:/localhost:70000/chat#foo") == false);
}
// Valid URI complicated resource path with query
BOOST_AUTO_TEST_CASE( uri_valid_4 ) {
websocketpp::ws_uri uri;
BOOST_CHECK( uri.parse("wss://localhost:9000/chat/foo/bar?foo=bar") == true);
BOOST_CHECK( uri.secure == true );
BOOST_CHECK( uri.host == "localhost");
BOOST_CHECK( uri.port == 9000 );
BOOST_CHECK( uri.resource == "/chat/foo/bar?foo=bar" );
}
+25
View File
@@ -0,0 +1,25 @@
## connection unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','regex','system'],env) + [platform_libs]
objs = env.Object('connection_boost.o', ["connection.cpp"], LIBS = BOOST_LIBS)
objs = env.Object('connection_tu2_boost.o', ["connection_tu2.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_connection_boost', ["connection_boost.o","connection_tu2_boost.o"], LIBS = BOOST_LIBS)
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system'],env_cpp11) + [platform_libs] + [polyfill_libs]
objs += env_cpp11.Object('connection_stl.o', ["connection.cpp"], LIBS = BOOST_LIBS_CPP11)
objs += env_cpp11.Object('connection_tu2_stl.o', ["connection_tu2.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_connection_stl', ["connection_stl.o","connection_tu2_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+162
View File
@@ -0,0 +1,162 @@
/*
* Copyright (c) 2011, 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 connection
#include <boost/test/unit_test.hpp>
#include "connection_tu2.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
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 500 Internal Server Error\r\nServer: " +
std::string(websocketpp::user_agent)+"\r\n\r\n";
std::string o2 = run_server_test(input);
BOOST_CHECK(o2 == output);
}
struct connection_extension {
connection_extension() : extension_value(5) {}
int extension_method() {
return extension_value;
}
bool is_server() const {
return false;
}
int extension_value;
};
struct stub_config : public websocketpp::config::core {
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 core::rng_type rng_type;
typedef core::transport_type transport_type;
typedef core::endpoint_base endpoint_base;
typedef connection_extension connection_base;
};
struct connection_setup {
connection_setup(bool server)
: c(server,"",alog,elog,rng) {}
websocketpp::lib::error_code ec;
stub_config::alog_type alog;
stub_config::elog_type elog;
stub_config::rng_type rng;
websocketpp::connection<stub_config> c;
};
/*void echo_func(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
s->send(hdl, msg->get_payload(), msg->get_opcode());
}*/
void validate_func(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
s->send(hdl, msg->get_payload(), msg->get_opcode());
}
void http_func(server* s, websocketpp::connection_hdl hdl) {
server::connection_ptr con = s->get_con_from_hdl(hdl);
std::string res = con->get_resource();
con->set_body(res);
con->set_status(websocketpp::http::status_code::ok);
}
BOOST_AUTO_TEST_CASE( connection_extensions ) {
connection_setup env(true);
BOOST_CHECK( env.c.extension_value == 5 );
BOOST_CHECK( env.c.extension_method() == 5 );
BOOST_CHECK( env.c.is_server() == true );
}
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: ";
output+=websocketpp::user_agent;
output+="\r\nUpgrade: websocket\r\n\r\n";
server s;
s.set_message_handler(bind(&echo_func,&s,::_1,::_2));
BOOST_CHECK(run_server_test(s,input) == output);
}
BOOST_AUTO_TEST_CASE( 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;
s.set_http_handler(bind(&http_func,&s,::_1));
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
}
/*
BOOST_AUTO_TEST_CASE( user_reject_origin ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example2.com\r\n\r\n";
std::string output = "HTTP/1.1 403 Forbidden\r\nServer: "+websocketpp::USER_AGENT+"\r\n\r\n";
BOOST_CHECK(run_server_test(input) == output);
}
BOOST_AUTO_TEST_CASE( basic_text_message ) {
std::string input = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
unsigned char frames[8] = {0x82,0x82,0xFF,0xFF,0xFF,0xFF,0xD5,0xD5};
input.append(reinterpret_cast<char*>(frames),8);
std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: "+websocketpp::USER_AGENT+"\r\nUpgrade: websocket\r\n\r\n**";
BOOST_CHECK( run_server_test(input) == output);
}
*/
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * 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 "connection_tu2.hpp"
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) {
server test_server;
return run_server_test(test_server,input);
}
std::string run_server_test(server& s, std::string input) {
server::connection_ptr con;
std::stringstream output;
s.clear_access_channels(websocketpp::log::alevel::all);
s.clear_error_channels(websocketpp::log::elevel::all);
s.register_ostream(&output);
con = s.get_connection();
con->start();
std::stringstream channel;
channel << input;
channel >> *con;
return output.str();
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,32 +25,32 @@
*
*/
#include "echo_client_handler.hpp"
#include <iostream>
#include <sstream>
#include <boost/algorithm/string/replace.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
// Test Environment:
// server, no TLS, no locks, iostream based transport
#include <websocketpp/config/core.hpp>
#include <websocketpp/server.hpp>
using websocketecho::echo_client_handler;
using websocketpp::client_session_ptr;
typedef websocketpp::server<websocketpp::config::core> server;
typedef websocketpp::config::core::message_type::ptr message_ptr;
void echo_client_handler::on_open(session_ptr s) {
std::cout << " Successfully connected (handshake complete): " << s->get_resource() << std::endl;
}
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
void echo_client_handler::on_close(session_ptr s) {
std::cout << " client was disconnected (WS state is now CLOSED)" << std::endl;
}
void echo_client_handler::on_message(session_ptr s,const std::string &msg) {
if (s->get_resource() == "/getCaseCount") {
std::cout << "Detected " << msg << " test cases." << std::endl;
m_case_count = atoi(msg.c_str());
} else {
s->send(msg);
/*class echo_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;
}
}
};*/
void echo_client_handler::on_message(session_ptr s,
const std::vector<unsigned char> &data) {
s->send(data);
}
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);
+24
View File
@@ -0,0 +1,24 @@
## endpoint unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
Import('tls_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','regex','system'],env) + [platform_libs] + [tls_libs]
objs = env.Object('endpoint_boost.o', ["endpoint.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_endpoint_boost', ["endpoint_boost.o"], LIBS = BOOST_LIBS)
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
objs += env_cpp11.Object('endpoint_stl.o', ["endpoint.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_endpoint_stl', ["endpoint_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * 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 endpoint
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <sstream>
#include <websocketpp/config/asio.hpp>
#include <websocketpp/server.hpp>
BOOST_AUTO_TEST_CASE( construct_server_iostream ) {
websocketpp::server<websocketpp::config::core> s;
}
BOOST_AUTO_TEST_CASE( construct_server_asio_plain ) {
websocketpp::server<websocketpp::config::asio> s;
}
BOOST_AUTO_TEST_CASE( construct_server_asio_tls ) {
websocketpp::server<websocketpp::config::asio_tls> s;
}
BOOST_AUTO_TEST_CASE( initialize_server_asio ) {
websocketpp::server<websocketpp::config::asio> s;
s.init_asio();
}
BOOST_AUTO_TEST_CASE( initialize_server_asio_external ) {
websocketpp::server<websocketpp::config::asio> s;
boost::asio::io_service ios;
s.init_asio(&ios);
}
struct endpoint_extension {
endpoint_extension() : extension_value(5) {}
int extension_method() {
return extension_value;
}
bool is_server() const {
return false;
}
int extension_value;
};
struct stub_config : public websocketpp::config::core {
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 core::rng_type rng_type;
typedef core::transport_type transport_type;
typedef endpoint_extension endpoint_base;
};
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( s.is_server() == true );
}
+23
View File
@@ -0,0 +1,23 @@
## http unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','system','regex'],env) + [platform_libs]
objs = env.Object('extension_boost.o', ["extension.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_extension_boost', ["extension_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]
objs += env_cpp11.Object('extension_stl.o', ["extension.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_extension_stl', ["extension_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
@@ -24,18 +24,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
//#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE extension
#include <boost/test/unit_test.hpp>
#include "echo.hpp"
#include <string>
using websocketecho::echo_server_handler;
#include <websocketpp/extensions/extension.hpp>
void echo_server_handler::validate(websocketpp::session_ptr client) {}
void echo_server_handler::on_message(websocketpp::session_ptr client, const std::string &msg) {
client->send(msg);
}
void echo_server_handler::on_message(websocketpp::session_ptr client,
const std::vector<unsigned char> &data) {
client->send(data);
BOOST_AUTO_TEST_CASE( blank ) {
BOOST_CHECK( true );
}
+23
View File
@@ -0,0 +1,23 @@
## http unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','regex'],env) + [platform_libs]
objs = env.Object('parser_boost.o', ["parser.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_http_boost', ["parser_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]
objs += env_cpp11.Object('parser_stl.o', ["parser.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_http_stl', ["parser_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
BIN
View File
Binary file not shown.
+893
View File
@@ -0,0 +1,893 @@
/*
* Copyright (c) 2011, 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 http_parser
#include <boost/test/unit_test.hpp>
#include <string>
#include <websocketpp/http/request.hpp>
#include <websocketpp/http/response.hpp>
BOOST_AUTO_TEST_CASE( is_token_char ) {
// Valid characters
// misc
BOOST_CHECK( websocketpp::http::is_token_char('!') );
BOOST_CHECK( websocketpp::http::is_token_char('#') );
BOOST_CHECK( websocketpp::http::is_token_char('$') );
BOOST_CHECK( websocketpp::http::is_token_char('%') );
BOOST_CHECK( websocketpp::http::is_token_char('&') );
BOOST_CHECK( websocketpp::http::is_token_char('\'') );
BOOST_CHECK( websocketpp::http::is_token_char('*') );
BOOST_CHECK( websocketpp::http::is_token_char('+') );
BOOST_CHECK( websocketpp::http::is_token_char('-') );
BOOST_CHECK( websocketpp::http::is_token_char('.') );
BOOST_CHECK( websocketpp::http::is_token_char('^') );
BOOST_CHECK( websocketpp::http::is_token_char('_') );
BOOST_CHECK( websocketpp::http::is_token_char('`') );
BOOST_CHECK( websocketpp::http::is_token_char('~') );
// numbers
for (int i = 0x30; i < 0x3a; 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)) );
}
// lower
for (int i = 0x61; i < 0x7b; 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)) );
}
// misc
BOOST_CHECK( !websocketpp::http::is_token_char('(') );
BOOST_CHECK( !websocketpp::http::is_token_char(')') );
BOOST_CHECK( !websocketpp::http::is_token_char('<') );
BOOST_CHECK( !websocketpp::http::is_token_char('>') );
BOOST_CHECK( !websocketpp::http::is_token_char('@') );
BOOST_CHECK( !websocketpp::http::is_token_char(',') );
BOOST_CHECK( !websocketpp::http::is_token_char(';') );
BOOST_CHECK( !websocketpp::http::is_token_char(':') );
BOOST_CHECK( !websocketpp::http::is_token_char('\\') );
BOOST_CHECK( !websocketpp::http::is_token_char('"') );
BOOST_CHECK( !websocketpp::http::is_token_char('/') );
BOOST_CHECK( !websocketpp::http::is_token_char('[') );
BOOST_CHECK( !websocketpp::http::is_token_char(']') );
BOOST_CHECK( !websocketpp::http::is_token_char('?') );
BOOST_CHECK( !websocketpp::http::is_token_char('=') );
BOOST_CHECK( !websocketpp::http::is_token_char('{') );
BOOST_CHECK( !websocketpp::http::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)) );
}
// is not
BOOST_CHECK( !websocketpp::http::is_not_token_char('!') );
BOOST_CHECK( websocketpp::http::is_not_token_char('(') );
}
BOOST_AUTO_TEST_CASE( extract_token ) {
std::string d1 = "foo";
std::string d2 = " foo ";
std::pair<std::string,std::string::const_iterator> ret;
ret = websocketpp::http::parser::extract_token(d1.begin(),d1.end());
BOOST_CHECK( ret.first == "foo" );
BOOST_CHECK( ret.second == d1.begin()+3 );
ret = websocketpp::http::parser::extract_token(d2.begin(),d2.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.second == d2.begin()+0 );
ret = websocketpp::http::parser::extract_token(d2.begin()+1,d2.end());
BOOST_CHECK( ret.first == "foo" );
BOOST_CHECK( ret.second == d2.begin()+4 );
}
BOOST_AUTO_TEST_CASE( extract_quoted_string ) {
std::string d1 = "\"foo\"";
std::string d2 = "\"foo\\\"bar\\\"baz\"";
std::string d3 = "\"foo\" ";
std::string d4 = "";
std::string d5 = "foo";
std::pair<std::string,std::string::const_iterator> ret;
using websocketpp::http::parser::extract_quoted_string;
ret = extract_quoted_string(d1.begin(),d1.end());
BOOST_CHECK( ret.first == "foo" );
BOOST_CHECK( ret.second == d1.end() );
ret = extract_quoted_string(d2.begin(),d2.end());
BOOST_CHECK( ret.first == "foo\"bar\"baz" );
BOOST_CHECK( ret.second == d2.end() );
ret = extract_quoted_string(d3.begin(),d3.end());
BOOST_CHECK( ret.first == "foo" );
BOOST_CHECK( ret.second == d3.begin()+5 );
ret = extract_quoted_string(d4.begin(),d4.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.second == d4.begin() );
ret = extract_quoted_string(d5.begin(),d5.end());
BOOST_CHECK( ret.first == "" );
BOOST_CHECK( ret.second == d5.begin() );
}
BOOST_AUTO_TEST_CASE( extract_all_lws ) {
std::string d1 = " foo bar";
d1.append(1,char(9));
d1.append("baz\r\n d\r\n \r\n e\r\nf");
std::string::const_iterator ret;
ret = websocketpp::http::parser::extract_all_lws(d1.begin(),d1.end());
BOOST_CHECK( ret == d1.begin()+1 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+1,d1.end());
BOOST_CHECK( ret == d1.begin()+1 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+4,d1.end());
BOOST_CHECK( ret == d1.begin()+9 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+12,d1.end());
BOOST_CHECK( ret == d1.begin()+13 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+16,d1.end());
BOOST_CHECK( ret == d1.begin()+19 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+20,d1.end());
BOOST_CHECK( ret == d1.begin()+28 );
ret = websocketpp::http::parser::extract_all_lws(d1.begin()+29,d1.end());
BOOST_CHECK( ret == d1.begin()+29 );
}
BOOST_AUTO_TEST_CASE( extract_attributes_blank ) {
std::string s = "";
websocketpp::http::parser::attribute_list a;
std::string::const_iterator it;
it = websocketpp::http::parser::extract_attributes(s.begin(),s.end(),a);
BOOST_CHECK( it == s.begin() );
BOOST_CHECK_EQUAL( a.size(), 0 );
}
BOOST_AUTO_TEST_CASE( extract_attributes_simple ) {
std::string s = "foo";
websocketpp::http::parser::attribute_list a;
std::string::const_iterator it;
it = websocketpp::http::parser::extract_attributes(s.begin(),s.end(),a);
BOOST_CHECK( it == s.end() );
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("foo") != a.end() );
BOOST_CHECK_EQUAL( a.find("foo")->second, "" );
}
BOOST_AUTO_TEST_CASE( extract_parameters ) {
std::string s1 = "";
std::string s2 = "foo";
std::string s3 = " foo \r\nAbc";
std::string s4 = " \r\n foo ";
std::string s5 = "foo,bar";
std::string s6 = "foo;bar";
std::string s7 = "foo;baz,bar";
std::string s8 = "foo;bar;baz";
std::string s9 = "foo;bar=baz";
std::string s10 = "foo;bar=baz;boo";
std::string s11 = "foo;bar=baz;boo,bob";
std::string s12 = "foo;bar=\"a b c\"";
std::string s13 = "foo;bar=\"a \\\"b\\\" c\"";
std::string sx = "foo;bar=\"a \\\"b\\\" c\"";
websocketpp::http::parser::parameter_list p;
websocketpp::http::parser::attribute_list a;
std::string::const_iterator it;
using websocketpp::http::parser::extract_parameters;
it = extract_parameters(s1.begin(),s1.end(),p);
BOOST_CHECK( it == s1.begin() );
p.clear();
it = extract_parameters(s2.begin(),s2.end(),p);
BOOST_CHECK( it == s2.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
p.clear();
it = extract_parameters(s3.begin(),s3.end(),p);
BOOST_CHECK( it == s3.begin()+5 );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
p.clear();
it = extract_parameters(s4.begin(),s4.end(),p);
BOOST_CHECK( it == s4.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
p.clear();
it = extract_parameters(s5.begin(),s5.end(),p);
BOOST_CHECK( it == s5.end() );
BOOST_CHECK_EQUAL( p.size(), 2 );
BOOST_CHECK( p[0].first == "foo" );
BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
BOOST_CHECK( p[1].first == "bar" );
BOOST_CHECK_EQUAL( p[1].second.size(), 0 );
p.clear();
it = extract_parameters(s6.begin(),s6.end(),p);
BOOST_CHECK( it == s6.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "" );
p.clear();
it = extract_parameters(s7.begin(),s7.end(),p);
BOOST_CHECK( it == s7.end() );
BOOST_CHECK_EQUAL( p.size(), 2 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("baz") != a.end() );
BOOST_CHECK_EQUAL( a.find("baz")->second, "" );
BOOST_CHECK( p[1].first == "bar" );
a = p[1].second;
BOOST_CHECK_EQUAL( a.size(), 0 );
p.clear();
it = extract_parameters(s8.begin(),s8.end(),p);
BOOST_CHECK( it == s8.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 2 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "" );
BOOST_CHECK( a.find("baz") != a.end() );
BOOST_CHECK_EQUAL( a.find("baz")->second, "" );
p.clear();
it = extract_parameters(s9.begin(),s9.end(),p);
BOOST_CHECK( it == s9.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
p.clear();
it = extract_parameters(s10.begin(),s10.end(),p);
BOOST_CHECK( it == s10.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 2 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
BOOST_CHECK( a.find("boo") != a.end() );
BOOST_CHECK_EQUAL( a.find("boo")->second, "" );
p.clear();
it = extract_parameters(s11.begin(),s11.end(),p);
BOOST_CHECK( it == s11.end() );
BOOST_CHECK_EQUAL( p.size(), 2 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 2 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
BOOST_CHECK( a.find("boo") != a.end() );
BOOST_CHECK_EQUAL( a.find("boo")->second, "" );
a = p[1].second;
BOOST_CHECK_EQUAL( a.size(), 0 );
p.clear();
it = extract_parameters(s12.begin(),s12.end(),p);
BOOST_CHECK( it == s12.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "a b c" );
p.clear();
it = extract_parameters(s13.begin(),s13.end(),p);
BOOST_CHECK( it == s13.end() );
BOOST_CHECK_EQUAL( p.size(), 1 );
BOOST_CHECK( p[0].first == "foo" );
a = p[0].second;
BOOST_CHECK_EQUAL( a.size(), 1 );
BOOST_CHECK( a.find("bar") != a.end() );
BOOST_CHECK_EQUAL( a.find("bar")->second, "a \"b\" c" );
}
BOOST_AUTO_TEST_CASE( blank_consume ) {
websocketpp::http::parser::request r;
std::string raw = "";
bool exception = false;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( r.ready() == false );
}
BOOST_AUTO_TEST_CASE( blank_request ) {
websocketpp::http::parser::request r;
std::string raw = "\r\n\r\n";
bool exception = false;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == true );
BOOST_CHECK( r.ready() == false );
}
BOOST_AUTO_TEST_CASE( bad_request_no_host ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\n\r\n";
bool exception = false;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == true );
BOOST_CHECK( r.ready() == false );
}
BOOST_AUTO_TEST_CASE( basic_request ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\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( 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 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\na";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
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( basic_split1 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\n";
std::string raw2 = "Host: www.example.com\r\n\r\na";
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( 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( basic_split2 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r";
std::string raw2 = "\n\r\na";
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( 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( max_header_len ) {
websocketpp::http::parser::request r;
std::string raw(websocketpp::http::max_header_size+1,'*');
bool exception = false;
size_t pos = 0;
try {
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;
}
}
BOOST_CHECK( exception == true );
}
BOOST_AUTO_TEST_CASE( max_header_len_split ) {
websocketpp::http::parser::request r;
std::string raw(websocketpp::http::max_header_size-1,'*');
std::string raw2(2,'*');
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 (const websocketpp::http::exception& e) {
if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
exception = true;
}
}
BOOST_CHECK( exception == true );
}
BOOST_AUTO_TEST_CASE( firefox_full_request ) {
websocketpp::http::parser::request r;
std::string raw = "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";
bool exception = false;
size_t pos = 0;
try {
pos += r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( pos == 482 );
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") == "localhost:5000" );
BOOST_CHECK( r.get_header("User-Agent") == "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0" );
BOOST_CHECK( r.get_header("Accept") == "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" );
BOOST_CHECK( r.get_header("Accept-Language") == "en-us,en;q=0.5" );
BOOST_CHECK( r.get_header("Accept-Encoding") == "gzip, deflate" );
BOOST_CHECK( r.get_header("Connection") == "keep-alive, Upgrade" );
BOOST_CHECK( r.get_header("Sec-WebSocket-Version") == "8" );
BOOST_CHECK( r.get_header("Sec-WebSocket-Origin") == "http://zaphoyd.com" );
BOOST_CHECK( r.get_header("Sec-WebSocket-Key") == "pFik//FxwFk0riN4ZiPFjQ==" );
BOOST_CHECK( r.get_header("Pragma") == "no-cache" );
BOOST_CHECK( r.get_header("Cache-Control") == "no-cache" );
BOOST_CHECK( r.get_header("Upgrade") == "websocket" );
}
BOOST_AUTO_TEST_CASE( bad_method ) {
websocketpp::http::parser::request r;
std::string raw = "GE]T / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
bool exception = false;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == true );
}
BOOST_AUTO_TEST_CASE( bad_header_name ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHo]st: www.example.com\r\n\r\n";
bool exception = false;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == true );
}
BOOST_AUTO_TEST_CASE( old_http_version ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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_AUTO_TEST_CASE( new_http_version1 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.12\r\nHost: www.example.com\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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_AUTO_TEST_CASE( new_http_version2 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/12.12\r\nHost: www.example.com\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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" );
}
/* commented out due to not being implemented yet
BOOST_AUTO_TEST_CASE( new_http_version3 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTPS/12.12\r\nHost: www.example.com\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == true );
}
BOOST_AUTO_TEST_CASE( header_whitespace1 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com \r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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_AUTO_TEST_CASE( header_whitespace2 ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost:www.example.com\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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_AUTO_TEST_CASE( header_aggregation ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nFoo: bar\r\nFoo: bat\r\n\r\n";
bool exception = false;
size_t pos = 0;
try {
pos = r.consume(raw.c_str(),raw.size());
} catch (...) {
exception = true;
}
BOOST_CHECK( exception == false );
BOOST_CHECK( 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_AUTO_TEST_CASE( wikipedia_example_response ) {
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( 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_AUTO_TEST_CASE( plain_http_response ) {
websocketpp::http::parser::response r;
std::string raw = "HTTP/1.1 200 OK\r\nDate: Thu, 10 May 2012 11:59:25 GMT\r\nServer: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch\r\nLast-Modified: Tue, 30 Mar 2010 17:41:28 GMT\r\nETag: \"16799d-55-4830823a78200\"\r\nAccept-Ranges: bytes\r\nContent-Length: 85\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\n\r\n<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>";
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( 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_AUTO_TEST_CASE( parse_istream ) {
websocketpp::http::parser::response r;
std::stringstream s;
s << "HTTP/1.1 200 OK\r\nDate: Thu, 10 May 2012 11:59:25 GMT\r\nServer: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch\r\nLast-Modified: Tue, 30 Mar 2010 17:41:28 GMT\r\nETag: \"16799d-55-4830823a78200\"\r\nAccept-Ranges: bytes\r\nContent-Length: 85\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\n\r\n<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>";
bool exception = false;
size_t pos = 0;
try {
pos += r.consume(s);
} catch (std::exception &e) {
exception = true;
std::cout << e.what() << std::endl;
}
BOOST_CHECK_EQUAL( exception, false );
BOOST_CHECK_EQUAL( pos, 405 );
BOOST_CHECK_EQUAL( r.headers_ready(), true );
BOOST_CHECK_EQUAL( r.ready(), true );
}
BOOST_AUTO_TEST_CASE( write_request_basic ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\n\r\n";
r.set_version("HTTP/1.1");
r.set_method("GET");
r.set_uri("/");
BOOST_CHECK( r.raw() == raw );
}
BOOST_AUTO_TEST_CASE( write_request_with_header ) {
websocketpp::http::parser::request r;
std::string raw = "GET / HTTP/1.1\r\nHost: http://example.com\r\n\r\n";
r.set_version("HTTP/1.1");
r.set_method("GET");
r.set_uri("/");
r.replace_header("Host","http://example.com");
BOOST_CHECK( r.raw() == raw );
}
BOOST_AUTO_TEST_CASE( write_request_with_body ) {
websocketpp::http::parser::request r;
std::string raw = "POST / HTTP/1.1\r\nContent-Length: 48\r\nContent-Type: application/x-www-form-urlencoded\r\nHost: http://example.com\r\n\r\nlicenseID=string&content=string&paramsXML=string";
r.set_version("HTTP/1.1");
r.set_method("POST");
r.set_uri("/");
r.replace_header("Host","http://example.com");
r.replace_header("Content-Type","application/x-www-form-urlencoded");
r.set_body("licenseID=string&content=string&paramsXML=string");
BOOST_CHECK( r.raw() == raw );
}
+141
View File
@@ -0,0 +1,141 @@
/*
* Copyright (c) 2011, 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/http/parser.hpp>
#include <chrono>
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;
//nanoseconds_per_test
//tests_per_second
//1000000000.0/(double(time_taken.count())/1000.0)
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;
}
private:
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 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 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;
try {
r.consume(raw.c_str(),raw.size());
} catch (...) {
std::cout << "exception" << std::endl;
}
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;
try {
r.consume2(firefox.c_str(),firefox.size());
} catch (...) {
std::cout << "exception" << std::endl;
}
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;
try {
r.consume(firefox.c_str(),firefox.size());
} catch (...) {
std::cout << "exception" << std::endl;
}
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;
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;
}
}
}
return 0;
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@
## logger unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','regex','system'],env) + [platform_libs]
objs = env.Object('logger_basic_boost.o', ["basic.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('logger_basic_boost', ["logger_basic_boost.o"], LIBS = BOOST_LIBS)
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system'],env_cpp11) + [platform_libs] + [polyfill_libs]
objs += env_cpp11.Object('logger_basic_stl.o', ["basic.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('logger_basic_stl', ["logger_basic_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * 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 basic_log
#include <boost/test/unit_test.hpp>
#include <string>
#include <websocketpp/logger/basic.hpp>
#include <websocketpp/concurrency/none.hpp>
#include <websocketpp/concurrency/basic.hpp>
BOOST_AUTO_TEST_CASE( is_token_char ) {
typedef websocketpp::log::basic<websocketpp::concurrency::none,websocketpp::log::elevel> error_log;
error_log elog;
BOOST_CHECK( elog.static_test(websocketpp::log::elevel::info ) == true );
BOOST_CHECK( elog.static_test(websocketpp::log::elevel::warn ) == true );
BOOST_CHECK( elog.static_test(websocketpp::log::elevel::rerror ) == true );
BOOST_CHECK( elog.static_test(websocketpp::log::elevel::fatal ) == true );
elog.set_channels(websocketpp::log::elevel::info);
elog.write(websocketpp::log::elevel::info,"Information");
elog.write(websocketpp::log::elevel::warn,"A warning");
elog.write(websocketpp::log::elevel::rerror,"A error");
elog.write(websocketpp::log::elevel::fatal,"A critical error");
}
BOOST_AUTO_TEST_CASE( access_clear ) {
typedef websocketpp::log::basic<websocketpp::concurrency::none,websocketpp::log::alevel> access_log;
std::stringstream out;
access_log logger(0xffffffff,&out);
// clear all channels
logger.clear_channels(0xffffffff);
// writes shouldn't happen
logger.write(websocketpp::log::alevel::devel,"devel");
//std::cout << "|" << out.str() << "|" << std::endl;
BOOST_CHECK( out.str().size() == 0 );
}
BOOST_AUTO_TEST_CASE( basic_concurrency ) {
typedef websocketpp::log::basic<websocketpp::concurrency::basic,websocketpp::log::alevel> access_log;
std::stringstream out;
access_log logger(0xffffffff,&out);
logger.set_channels(0xffffffff);
logger.write(websocketpp::log::alevel::devel,"devel");
//std::cout << "|" << out.str() << "|" << std::endl;
BOOST_CHECK( out.str().size() > 0 );
}
+27
View File
@@ -0,0 +1,27 @@
## message_buffer unit tests
##
Import('env')
Import('env_cpp11')
Import('boostlibs')
Import('platform_libs')
Import('polyfill_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()
BOOST_LIBS = boostlibs(['unit_test_framework','system'],env) + [platform_libs]
objs = env.Object('message_boost.o', ["message.cpp"], LIBS = BOOST_LIBS)
objs += env.Object('alloc_boost.o', ["alloc.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_message_boost', ["message_boost.o"], LIBS = BOOST_LIBS)
prgs += env.Program('test_alloc_boost', ["alloc_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]
objs += env_cpp11.Object('message_stl.o', ["message.cpp"], LIBS = BOOST_LIBS_CPP11)
objs += env_cpp11.Object('alloc_stl.o', ["alloc.cpp"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_message_stl', ["message_stl.o"], LIBS = BOOST_LIBS_CPP11)
prgs += env_cpp11.Program('test_alloc_stl', ["alloc_stl.o"], LIBS = BOOST_LIBS_CPP11)
Return('prgs')
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2012, 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 message_buffer_alloc
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <string>
#include <websocketpp/message_buffer/alloc.hpp>
template <template <class> class con_msg_manager>
struct stub {
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;
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();
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;
};
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;
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_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;
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);
}

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