diff --git a/examples/concurrent_server/Makefile b/examples/concurrent_server/Makefile
new file mode 100644
index 0000000000..abccf29bd7
--- /dev/null
+++ b/examples/concurrent_server/Makefile
@@ -0,0 +1,27 @@
+BOOST_LIB_PATH ?= /usr/local/lib
+BOOST_INCLUDE_PATH ?= /usr/local/include
+CPP11 ?=
+
+CFLAGS = -O2 $(CPP11) -I$(BOOST_INCLUDE_PATH)
+LDFLAGS = -L$(BOOST_LIB_PATH)
+
+CXX ?= c++
+SHARED ?= "1"
+
+ifeq ($(SHARED), 1)
+ LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_program_options -lboost_thread -lpthread -lwebsocketpp
+else
+ LDFLAGS := $(LDFLAGS) ../../libwebsocketpp.a $(BOOST_LIB_PATH)/libboost_system.a $(BOOST_LIB_PATH)/libboost_date_time.a $(BOOST_LIB_PATH)/libboost_regex.a $(BOOST_LIB_PATH)/libboost_thread.a -lpthread
+endif
+
+concurrent_server: concurrent_server.o
+ $(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
+
+%.o: %.cpp
+ $(CXX) -c $(CFLAGS) -o $@ $^
+
+# cleanup by removing generated files
+#
+.PHONY: clean
+clean:
+ rm -f *.o concurrent_server
diff --git a/examples/concurrent_server/concurrent_client.html b/examples/concurrent_server/concurrent_client.html
new file mode 100644
index 0000000000..dc36396a24
--- /dev/null
+++ b/examples/concurrent_server/concurrent_client.html
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/concurrent_server/concurrent_server.cpp b/examples/concurrent_server/concurrent_server.cpp
new file mode 100644
index 0000000000..6373c981e6
--- /dev/null
+++ b/examples/concurrent_server/concurrent_server.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "../../src/websocketpp.hpp"
+
+#include
+#include
+#include
+
+#include
+
+using websocketpp::server;
+
+struct request {
+ server::handler::connection_ptr con;
+ int value;
+};
+
+class request_coordinator {
+public:
+ void add_request(const request& r) {
+ boost::unique_lock lock(m_lock);
+ m_requests.push(r);
+ lock.unlock();
+ m_cond.notify_one();
+ }
+
+ void get_request(request& value) {
+ boost::unique_lock lock(m_lock);
+
+ while (m_requests.empty()) {
+ m_cond.wait(lock);
+ }
+
+ value = m_requests.front();
+ m_requests.pop();
+ }
+private:
+ std::queue m_requests;
+ boost::mutex m_lock;
+ boost::condition_variable m_cond;
+};
+
+class concurrent_server_handler : public server::handler {
+public:
+ concurrent_server_handler(request_coordinator& c) : m_coordinator(c) {}
+
+ void on_message(connection_ptr con,message_ptr msg) {
+ int value = atoi(msg->get_payload().c_str());
+
+ if (value == 0) {
+ con->send("Invalid sleep value.");
+ } else {
+ request r;
+ r.con = con;
+ r.value = value;
+ m_coordinator.add_request(r);
+ }
+ }
+private:
+ request_coordinator& m_coordinator;
+};
+
+
+
+void process_requests(request_coordinator* coordinator);
+
+void process_requests(request_coordinator* coordinator) {
+ request r;
+
+ while (1) {
+ coordinator->get_request(r);
+
+ std::stringstream response;
+ response << "Sleeping for " << r.value << " milliseconds!";
+ r.con->send(response.str());
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(r.value));
+
+ response.str("");
+ response << "Done sleeping for " << r.value << " milliseconds!";
+ r.con->send(response.str());
+ }
+}
+
+int main(int argc, char* argv[]) {
+ unsigned short port = 9002;
+
+ if (argc == 2) {
+ port = atoi(argv[1]);
+
+ if (port == 0) {
+ std::cout << "Unable to parse port input " << argv[1] << std::endl;
+ return 1;
+ }
+ }
+
+ try {
+ request_coordinator rc;
+
+ server::handler::ptr h(new concurrent_server_handler(rc));
+ server echo_endpoint(h);
+
+ echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
+ echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
+
+ echo_endpoint.elog().set_level(websocketpp::log::elevel::ERROR);
+ echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
+
+ boost::thread t1(boost::bind(&process_requests, &rc));
+ boost::thread t2(boost::bind(&process_requests, &rc));
+
+ std::cout << "Starting WebSocket sleep server on port " << port << std::endl;
+ echo_endpoint.listen(port);
+ } catch (std::exception& e) {
+ std::cerr << "Exception: " << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/websocketpp.xcodeproj/project.pbxproj b/websocketpp.xcodeproj/project.pbxproj
index 6519735211..cafc928f6d 100644
--- a/websocketpp.xcodeproj/project.pbxproj
+++ b/websocketpp.xcodeproj/project.pbxproj
@@ -8,6 +8,14 @@
/* Begin PBXBuildFile section */
B613878F145CA61300ED9B19 /* libboost_date_time.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBE1434AF6A0029A1B1 /* libboost_date_time.dylib */; };
+ B61A51C914DC273F00456432 /* concurrent_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B61A51B814DC207600456432 /* concurrent_server.cpp */; };
+ B61A51CA14DC274F00456432 /* libwebsocketpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1C721434A8280029A1B1 /* libwebsocketpp.dylib */; };
+ B61A51CB14DC276300456432 /* libboost_date_time.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBE1434AF6A0029A1B1 /* libboost_date_time.dylib */; };
+ B61A51CC14DC276300456432 /* libboost_program_options.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6FE8CEB145A0F1900B32547 /* libboost_program_options.dylib */; };
+ B61A51CD14DC276300456432 /* libboost_random.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B682888C1437464A002BA48B /* libboost_random.dylib */; };
+ B61A51CE14DC276300456432 /* libboost_regex.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBF1434AF6A0029A1B1 /* libboost_regex.dylib */; };
+ B61A51CF14DC276300456432 /* libboost_system.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBC1434AE070029A1B1 /* libboost_system.dylib */; };
+ B61A51D014DC276300456432 /* libboost_thread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B682888E14374689002BA48B /* libboost_thread.dylib */; };
B62A5A7214775ECF005F9EB0 /* libwebsocketpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1C721434A8280029A1B1 /* libwebsocketpp.dylib */; };
B653A715148A607D004D7BD9 /* hybi_header.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B653A714148A607D004D7BD9 /* hybi_header.hpp */; };
B653A716148A607D004D7BD9 /* hybi_header.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B653A714148A607D004D7BD9 /* hybi_header.hpp */; };
@@ -118,6 +126,15 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ B61A51BD14DC271900456432 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
B66388491487D73200DDAE13 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -217,6 +234,10 @@
B61387A5145D849E00ED9B19 /* constants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = constants.hpp; path = src/http/constants.hpp; sourceTree = ""; };
B61387A6145D849E00ED9B19 /* parser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = parser.hpp; path = src/http/parser.hpp; sourceTree = ""; };
B61387B61462B35700ED9B19 /* logger.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = logger.hpp; path = src/logger/logger.hpp; sourceTree = ""; };
+ B61A51B714DC207600456432 /* concurrent_client.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = concurrent_client.html; sourceTree = ""; };
+ B61A51B814DC207600456432 /* concurrent_server.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = concurrent_server.cpp; sourceTree = ""; };
+ B61A51B914DC207600456432 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; };
+ B61A51BF14DC271900456432 /* concurrent_server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = concurrent_server; sourceTree = BUILT_PRODUCTS_DIR; };
B62A5A511473EBB0005F9EB0 /* connection.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = connection.hpp; path = src/connection.hpp; sourceTree = ""; };
B62A5A521473EBB0005F9EB0 /* endpoint.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = endpoint.hpp; path = src/endpoint.hpp; sourceTree = ""; };
B62A5A561473EBE8005F9EB0 /* client.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = client.hpp; path = src/roles/client.hpp; sourceTree = ""; };
@@ -326,6 +347,20 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ B61A51BC14DC271900456432 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B61A51CB14DC276300456432 /* libboost_date_time.dylib in Frameworks */,
+ B61A51CC14DC276300456432 /* libboost_program_options.dylib in Frameworks */,
+ B61A51CD14DC276300456432 /* libboost_random.dylib in Frameworks */,
+ B61A51CE14DC276300456432 /* libboost_regex.dylib in Frameworks */,
+ B61A51CF14DC276300456432 /* libboost_system.dylib in Frameworks */,
+ B61A51D014DC276300456432 /* libboost_thread.dylib in Frameworks */,
+ B61A51CA14DC274F00456432 /* libwebsocketpp.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
B66388481487D73200DDAE13 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -470,6 +505,17 @@
name = logger;
sourceTree = "";
};
+ B61A51B614DC207600456432 /* concurrent_server */ = {
+ isa = PBXGroup;
+ children = (
+ B61A51B714DC207600456432 /* concurrent_client.html */,
+ B61A51B814DC207600456432 /* concurrent_server.cpp */,
+ B61A51B914DC207600456432 /* Makefile */,
+ );
+ name = concurrent_server;
+ path = examples/concurrent_server;
+ sourceTree = "";
+ };
B62A5A541473EBB9005F9EB0 /* roles */ = {
isa = PBXGroup;
children = (
@@ -669,6 +715,7 @@
B6732471148FB0FC00FC2B04 /* fuzzing_client */,
B67324891491A16500FC2B04 /* broadcast_server */,
B67324A21491A7F100FC2B04 /* stress_client */,
+ B61A51BF14DC271900456432 /* concurrent_server */,
);
name = Products;
sourceTree = "";
@@ -745,6 +792,7 @@
B6DF1CC61435ED380029A1B1 /* examples */ = {
isa = PBXGroup;
children = (
+ B61A51B614DC207600456432 /* concurrent_server */,
B673249A1491A50000FC2B04 /* stress_client */,
B673248114919D6600FC2B04 /* broadcast_server_tls */,
B6732469148FB0C400FC2B04 /* fuzzing_client */,
@@ -861,6 +909,23 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ B61A51BE14DC271900456432 /* concurrent_server */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B61A51C614DC271900456432 /* Build configuration list for PBXNativeTarget "concurrent_server" */;
+ buildPhases = (
+ B61A51BB14DC271900456432 /* Sources */,
+ B61A51BC14DC271900456432 /* Frameworks */,
+ B61A51BD14DC271900456432 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = concurrent_server;
+ productName = concurrent_server;
+ productReference = B61A51BF14DC271900456432 /* concurrent_server */;
+ productType = "com.apple.product-type.tool";
+ };
B663884A1487D73200DDAE13 /* echo_server_tls */ = {
isa = PBXNativeTarget;
buildConfigurationList = B66388521487D73300DDAE13 /* Build configuration list for PBXNativeTarget "echo_server_tls" */;
@@ -1081,11 +1146,20 @@
B6732470148FB0FC00FC2B04 /* fuzzing_client */,
B67324881491A16500FC2B04 /* broadcast_server */,
B67324A11491A7F100FC2B04 /* stress_client */,
+ B61A51BE14DC271900456432 /* concurrent_server */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
+ B61A51BB14DC271900456432 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B61A51C914DC273F00456432 /* concurrent_server.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
B66388471487D73200DDAE13 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1203,6 +1277,44 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
+ B61A51C714DC271900456432 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ B61A51C814DC271900456432 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
B66388531487D73300DDAE13 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1659,6 +1771,14 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ B61A51C614DC271900456432 /* Build configuration list for PBXNativeTarget "concurrent_server" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B61A51C714DC271900456432 /* Debug */,
+ B61A51C814DC271900456432 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
B66388521487D73300DDAE13 /* Build configuration list for PBXNativeTarget "echo_server_tls" */ = {
isa = XCConfigurationList;
buildConfigurations = (