mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Squashed 'src/websocketpp/' content from commit 875d420
git-subtree-dir: src/websocketpp git-subtree-split: 875d420952d2c47d38de15952a401f00773cdffc
This commit is contained in:
6
examples/CMakeLists.txt
Normal file
6
examples/CMakeLists.txt
Normal 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 ()
|
||||
88
examples/associative_storage/associative_storage.cpp
Normal file
88
examples/associative_storage/associative_storage.cpp
Normal file
@@ -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
examples/broadcast_server/SConscript
Normal file
23
examples/broadcast_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
159
examples/broadcast_server/broadcast_server.cpp
Normal file
159
examples/broadcast_server/broadcast_server.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#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, connection_hdl h, server::message_ptr m)
|
||||
: type(t), hdl(h), 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,hdl,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> con_lock(m_connection_lock);
|
||||
m_connections.insert(a.hdl);
|
||||
} else if (a.type == UNSUBSCRIBE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.erase(a.hdl);
|
||||
} else if (a.type == MESSAGE) {
|
||||
unique_lock<mutex> con_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_instance;
|
||||
|
||||
// Start a thread to run the processing loop
|
||||
thread t(bind(&broadcast_server::process_messages,&server_instance));
|
||||
|
||||
// Run the asio loop with the main thread
|
||||
server_instance.run(9002);
|
||||
|
||||
t.join();
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
24
examples/debug_client/SConscript
Normal file
24
examples/debug_client/SConscript
Normal file
@@ -0,0 +1,24 @@
|
||||
## Debug client example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
152
examples/debug_client/debug_client.cpp
Normal file
152
examples/debug_client/debug_client.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_client.hpp>
|
||||
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_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) {
|
||||
m_socket_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl) {
|
||||
m_tls_init = std::chrono::high_resolution_clock::now();
|
||||
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::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) {
|
||||
m_message = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.close(hdl,websocketpp::close::status::going_away,"");
|
||||
}
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
m_close = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << "Socket Init: " << std::chrono::duration_cast<dur_type>(m_socket_init-m_start).count() << std::endl;
|
||||
std::cout << "TLS Init: " << std::chrono::duration_cast<dur_type>(m_tls_init-m_start).count() << std::endl;
|
||||
std::cout << "Open: " << std::chrono::duration_cast<dur_type>(m_open-m_start).count() << std::endl;
|
||||
std::cout << "Message: " << std::chrono::duration_cast<dur_type>(m_message-m_start).count() << std::endl;
|
||||
std::cout << "Close: " << std::chrono::duration_cast<dur_type>(m_close-m_start).count() << std::endl;
|
||||
}
|
||||
private:
|
||||
client m_endpoint;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
std::chrono::high_resolution_clock::time_point m_socket_init;
|
||||
std::chrono::high_resolution_clock::time_point m_tls_init;
|
||||
std::chrono::high_resolution_clock::time_point m_open;
|
||||
std::chrono::high_resolution_clock::time_point m_message;
|
||||
std::chrono::high_resolution_clock::time_point m_close;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string uri = "wss://echo.websocket.org";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
perftest endpoint;
|
||||
endpoint.start(uri);
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
||||
10
examples/debug_server/CMakeLists.txt
Normal file
10
examples/debug_server/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (debug_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
23
examples/debug_server/SConscript
Normal file
23
examples/debug_server/SConscript
Normal file
@@ -0,0 +1,23 @@
|
||||
## Debug server example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
92
examples/debug_server/debug_server.cpp
Normal file
92
examples/debug_server/debug_server.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/debug_asio_no_tls.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::debug_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) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
echo_server.set_reuse_addr(true);
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
|
||||
// Listen on port 9012
|
||||
echo_server.listen(9012);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
||||
18
examples/dev/SConscript
Normal file
18
examples/dev/SConscript
Normal 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
examples/dev/main.cpp
Normal file
200
examples/dev/main.cpp
Normal 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 = websocketpp::lib::make_shared<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;*/
|
||||
}
|
||||
10
examples/echo_server/CMakeLists.txt
Normal file
10
examples/echo_server/CMakeLists.txt
Normal 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
examples/echo_server/SConscript
Normal file
23
examples/echo_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
37
examples/echo_server/echo_handler.hpp
Normal file
37
examples/echo_server/echo_handler.hpp
Normal 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
|
||||
60
examples/echo_server/echo_server.cpp
Normal file
60
examples/echo_server/echo_server.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#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) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
15
examples/echo_server_both/CMakeLists.txt
Normal file
15
examples/echo_server_both/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (echo_server_both)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
endif()
|
||||
24
examples/echo_server_both/SConscript
Normal file
24
examples/echo_server_both/SConscript
Normal file
@@ -0,0 +1,24 @@
|
||||
## Combo plain+tls echo server
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
86
examples/echo_server_both/echo_server_both.cpp
Normal file
86
examples/echo_server_both/echo_server_both.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <websocketpp/config/asio.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// define types for two different server endpoints, one for each config we are
|
||||
// using
|
||||
typedef websocketpp::server<websocketpp::config::asio> server_plain;
|
||||
typedef websocketpp::server<websocketpp::config::asio_tls> server_tls;
|
||||
|
||||
// alias some of the bind related functions as they are a bit long
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// type of the ssl context pointer is long so alias it
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
|
||||
// The shared on_message handler takes a template parameter so the function can
|
||||
// resolve any endpoint dependent types like message_ptr or connection_ptr
|
||||
template <typename EndpointType>
|
||||
void on_message(EndpointType* s, websocketpp::connection_hdl hdl,
|
||||
typename EndpointType::message_ptr msg)
|
||||
{
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// No change to TLS init methods from echo_server_tls
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
ctx->set_password_callback(bind(&get_password));
|
||||
ctx->use_certificate_chain_file("server.pem");
|
||||
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// set up an external io_service to run both endpoints on. This is not
|
||||
// strictly necessary, but simplifies thread management a bit.
|
||||
boost::asio::io_service ios;
|
||||
|
||||
// set up plain endpoint
|
||||
server_plain endpoint_plain;
|
||||
// initialize asio with our external io_service rather than an internal one
|
||||
endpoint_plain.init_asio(&ios);
|
||||
endpoint_plain.set_message_handler(
|
||||
bind(&on_message<server_plain>,&endpoint_plain,::_1,::_2));
|
||||
endpoint_plain.listen(80);
|
||||
endpoint_plain.start_accept();
|
||||
|
||||
// set up tls endpoint
|
||||
server_tls endpoint_tls;
|
||||
endpoint_tls.init_asio(&ios);
|
||||
endpoint_tls.set_message_handler(
|
||||
bind(&on_message<server_tls>,&endpoint_tls,::_1,::_2));
|
||||
// TLS endpoint has an extra handler for the tls init
|
||||
endpoint_tls.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
// tls endpoint listens on a different port
|
||||
endpoint_tls.listen(443);
|
||||
endpoint_tls.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop running both endpoints
|
||||
ios.run();
|
||||
}
|
||||
58
examples/echo_server_both/server.pem
Normal file
58
examples/echo_server_both/server.pem
Normal 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-----
|
||||
15
examples/echo_server_tls/CMakeLists.txt
Normal file
15
examples/echo_server_tls/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (echo_server_tls)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
endif()
|
||||
24
examples/echo_server_tls/SConscript
Normal file
24
examples/echo_server_tls/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('echo_server_tls', ["echo_server_tls.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
72
examples/echo_server_tls/echo_server_tls.cpp
Normal file
72
examples/echo_server_tls/echo_server_tls.cpp
Normal file
@@ -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 = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::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
examples/echo_server_tls/server.pem
Normal file
58
examples/echo_server_tls/server.pem
Normal 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-----
|
||||
87
examples/enriched_storage/enriched_storage.cpp
Normal file
87
examples/enriched_storage/enriched_storage.cpp
Normal file
@@ -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);
|
||||
}
|
||||
42
examples/handler_switch/handler_switch.cpp
Normal file
42
examples/handler_switch/handler_switch.cpp
Normal file
@@ -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
examples/iostream_server/SConscript
Normal file
23
examples/iostream_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('iostream_server', ["iostream_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
93
examples/iostream_server/iostream_server.cpp
Normal file
93
examples/iostream_server/iostream_server.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#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;
|
||||
con->eof();
|
||||
} else {
|
||||
char a;
|
||||
while(std::cin.get(a)) {
|
||||
con->read_some(&a,1);
|
||||
}
|
||||
con->eof();
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
10
examples/print_server/CMakeLists.txt
Normal file
10
examples/print_server/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (print_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
23
examples/print_server/SConscript
Normal file
23
examples/print_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
22
examples/print_server/print_server.cpp
Normal file
22
examples/print_server/print_server.cpp
Normal 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, 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();
|
||||
}
|
||||
51
examples/simple_broadcast_server/simple_broadcast_server.cpp
Normal file
51
examples/simple_broadcast_server/simple_broadcast_server.cpp
Normal file
@@ -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
examples/sip_client/CMakeLists.txt
Normal file
11
examples/sip_client/CMakeLists.txt
Normal 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
examples/sip_client/README.txt
Normal file
22
examples/sip_client/README.txt
Normal 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
examples/sip_client/SConscript
Normal file
23
examples/sip_client/SConscript
Normal file
@@ -0,0 +1,23 @@
|
||||
## SIP 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 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','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
88
examples/sip_client/sip_client.cpp
Normal file
88
examples/sip_client/sip_client.cpp
Normal 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
examples/subprotocol_server/SConscript
Normal file
23
examples/subprotocol_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('subprotocol_server', ["subprotocol_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
52
examples/subprotocol_server/subprotocol_server.cpp
Normal file
52
examples/subprotocol_server/subprotocol_server.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
10
examples/telemetry_client/CMakeLists.txt
Normal file
10
examples/telemetry_client/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (telemetry_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
23
examples/telemetry_client/SConscript
Normal file
23
examples/telemetry_client/SConscript
Normal 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','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('telemetry_client', ["telemetry_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
156
examples/telemetry_client/telemetry_client.cpp
Normal file
156
examples/telemetry_client/telemetry_client.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
bool wait = false;
|
||||
|
||||
{
|
||||
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) {
|
||||
wait = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
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);
|
||||
}
|
||||
11
examples/testee_client/CMakeLists.txt
Normal file
11
examples/testee_client/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (testee_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
23
examples/testee_client/SConscript
Normal file
23
examples/testee_client/SConscript
Normal file
@@ -0,0 +1,23 @@
|
||||
## Autobahn test 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('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
84
examples/testee_client/testee_client.cpp
Normal file
84
examples/testee_client/testee_client.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
|
||||
|
||||
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[]) {
|
||||
// Create a server endpoint
|
||||
client c;
|
||||
|
||||
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
|
||||
c.clear_access_channels(websocketpp::log::alevel::all);
|
||||
c.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
c.init_asio();
|
||||
|
||||
// Register our handlers
|
||||
c.set_message_handler(bind(&on_message,&c,::_1,::_2));
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = c.get_connection(uri+"/getCaseCount", ec);
|
||||
c.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
c.run();
|
||||
|
||||
std::cout << "case count: " << case_count << std::endl;
|
||||
|
||||
for (int i = 1; i <= case_count; i++) {
|
||||
c.reset();
|
||||
|
||||
std::stringstream url;
|
||||
|
||||
url << uri << "/runCase?case=" << i << "&agent="
|
||||
<< websocketpp::user_agent;
|
||||
|
||||
con = c.get_connection(url.str(), ec);
|
||||
|
||||
c.connect(con);
|
||||
|
||||
c.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;
|
||||
}
|
||||
}
|
||||
23
examples/testee_server/SConscript
Normal file
23
examples/testee_server/SConscript
Normal 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'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
142
examples/testee_server/testee_server.cpp
Normal file
142
examples/testee_server/testee_server.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct testee_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::endpoint_base endpoint_base;
|
||||
|
||||
static bool const enable_multithreading = true;
|
||||
|
||||
struct transport_config : public core::transport_config {
|
||||
typedef core::concurrency_type concurrency_type;
|
||||
typedef core::elog_type elog_type;
|
||||
typedef core::alog_type alog_type;
|
||||
typedef core::request_type request_type;
|
||||
typedef core::response_type response_type;
|
||||
|
||||
static bool const enable_multithreading = true;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
static const websocketpp::log::level elog_level =
|
||||
websocketpp::log::elevel::none;
|
||||
static const websocketpp::log::level alog_level =
|
||||
websocketpp::log::alevel::none;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<testee_config> 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());
|
||||
}
|
||||
|
||||
void on_socket_init(websocketpp::connection_hdl, boost::asio::ip::tcp::socket & s) {
|
||||
boost::asio::ip::tcp::no_delay option(true);
|
||||
s.set_option(option);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
// Create a server endpoint
|
||||
server testee_server;
|
||||
|
||||
short port = 9002;
|
||||
size_t num_threads = 1;
|
||||
|
||||
if (argc == 3) {
|
||||
port = atoi(argv[1]);
|
||||
num_threads = atoi(argv[2]);
|
||||
}
|
||||
|
||||
try {
|
||||
// Total silence
|
||||
testee_server.clear_access_channels(websocketpp::log::alevel::all);
|
||||
testee_server.clear_error_channels(websocketpp::log::alevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
testee_server.init_asio();
|
||||
testee_server.set_reuse_addr(true);
|
||||
|
||||
// Register our message handler
|
||||
testee_server.set_message_handler(bind(&on_message,&testee_server,::_1,::_2));
|
||||
testee_server.set_socket_init_handler(bind(&on_socket_init,::_1,::_2));
|
||||
|
||||
// Listen on specified port with extended listen backlog
|
||||
testee_server.set_listen_backlog(8192);
|
||||
testee_server.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
testee_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
if (num_threads == 1) {
|
||||
testee_server.run();
|
||||
} else {
|
||||
typedef websocketpp::lib::shared_ptr<websocketpp::lib::thread> thread_ptr;
|
||||
std::vector<thread_ptr> ts;
|
||||
for (size_t i = 0; i < num_threads; i++) {
|
||||
ts.push_back(websocketpp::lib::make_shared<websocketpp::lib::thread>(&server::run, &testee_server));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_threads; i++) {
|
||||
ts[i]->join();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << "exception: " << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << "error code: " << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
||||
11
examples/utility_client/CMakeLists.txt
Normal file
11
examples/utility_client/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (utility_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
||||
23
examples/utility_client/SConscript
Normal file
23
examples/utility_client/SConscript
Normal file
@@ -0,0 +1,23 @@
|
||||
## Utility 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('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
||||
270
examples/utility_client/utility_client.cpp
Normal file
270
examples/utility_client/utility_client.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// **NOTE:** This file is a snapshot of the WebSocket++ utility client tutorial.
|
||||
// Additional related material can be found in the tutorials/utility_client
|
||||
// directory of the WebSocket++ repository.
|
||||
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
#include <websocketpp/common/memory.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
class connection_metadata {
|
||||
public:
|
||||
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
|
||||
|
||||
connection_metadata(int id, websocketpp::connection_hdl hdl, std::string uri)
|
||||
: m_id(id)
|
||||
, m_hdl(hdl)
|
||||
, m_status("Connecting")
|
||||
, m_uri(uri)
|
||||
, m_server("N/A")
|
||||
{}
|
||||
|
||||
void on_open(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Open";
|
||||
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
}
|
||||
|
||||
void on_fail(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Failed";
|
||||
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
m_server = con->get_response_header("Server");
|
||||
m_error_reason = con->get_ec().message();
|
||||
}
|
||||
|
||||
void on_close(client * c, websocketpp::connection_hdl hdl) {
|
||||
m_status = "Closed";
|
||||
client::connection_ptr con = c->get_con_from_hdl(hdl);
|
||||
std::stringstream s;
|
||||
s << "close code: " << con->get_remote_close_code() << " ("
|
||||
<< websocketpp::close::status::get_string(con->get_remote_close_code())
|
||||
<< "), close reason: " << con->get_remote_close_reason();
|
||||
m_error_reason = s.str();
|
||||
}
|
||||
|
||||
websocketpp::connection_hdl get_hdl() const {
|
||||
return m_hdl;
|
||||
}
|
||||
|
||||
int get_id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
std::string get_status() const {
|
||||
return m_status;
|
||||
}
|
||||
|
||||
friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data);
|
||||
private:
|
||||
int m_id;
|
||||
websocketpp::connection_hdl m_hdl;
|
||||
std::string m_status;
|
||||
std::string m_uri;
|
||||
std::string m_server;
|
||||
std::string m_error_reason;
|
||||
};
|
||||
|
||||
std::ostream & operator<< (std::ostream & out, connection_metadata const & data) {
|
||||
out << "> URI: " << data.m_uri << "\n"
|
||||
<< "> Status: " << data.m_status << "\n"
|
||||
<< "> Remote Server: " << (data.m_server.empty() ? "None Specified" : data.m_server) << "\n"
|
||||
<< "> Error/close reason: " << (data.m_error_reason.empty() ? "N/A" : data.m_error_reason);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
class websocket_endpoint {
|
||||
public:
|
||||
websocket_endpoint () : m_next_id(0) {
|
||||
m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
m_endpoint.init_asio();
|
||||
m_endpoint.start_perpetual();
|
||||
|
||||
m_thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_endpoint);
|
||||
}
|
||||
|
||||
~websocket_endpoint() {
|
||||
m_endpoint.stop_perpetual();
|
||||
|
||||
for (con_list::const_iterator it = m_connection_list.begin(); it != m_connection_list.end(); ++it) {
|
||||
if (it->second->get_status() != "Open") {
|
||||
// Only close open connections
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "> Closing connection " << it->second->get_id() << std::endl;
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
m_endpoint.close(it->second->get_hdl(), websocketpp::close::status::going_away, "", ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error closing connection " << it->second->get_id() << ": "
|
||||
<< ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
m_thread->join();
|
||||
}
|
||||
|
||||
int connect(std::string const & uri) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
client::connection_ptr con = m_endpoint.get_connection(uri, ec);
|
||||
|
||||
if (ec) {
|
||||
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int new_id = m_next_id++;
|
||||
connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(new_id, con->get_handle(), uri);
|
||||
m_connection_list[new_id] = metadata_ptr;
|
||||
|
||||
con->set_open_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_open,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_fail_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_fail,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
con->set_close_handler(websocketpp::lib::bind(
|
||||
&connection_metadata::on_close,
|
||||
metadata_ptr,
|
||||
&m_endpoint,
|
||||
websocketpp::lib::placeholders::_1
|
||||
));
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void close(int id, websocketpp::close::status::value code, std::string reason) {
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
con_list::iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
std::cout << "> No connection found with id " << id << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_endpoint.close(metadata_it->second->get_hdl(), code, reason, ec);
|
||||
if (ec) {
|
||||
std::cout << "> Error initiating close: " << ec.message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
connection_metadata::ptr get_metadata(int id) const {
|
||||
con_list::const_iterator metadata_it = m_connection_list.find(id);
|
||||
if (metadata_it == m_connection_list.end()) {
|
||||
return connection_metadata::ptr();
|
||||
} else {
|
||||
return metadata_it->second;
|
||||
}
|
||||
}
|
||||
private:
|
||||
typedef std::map<int,connection_metadata::ptr> con_list;
|
||||
|
||||
client m_endpoint;
|
||||
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
|
||||
|
||||
con_list m_connection_list;
|
||||
int m_next_id;
|
||||
};
|
||||
|
||||
int main() {
|
||||
bool done = false;
|
||||
std::string input;
|
||||
websocket_endpoint endpoint;
|
||||
|
||||
while (!done) {
|
||||
std::cout << "Enter Command: ";
|
||||
std::getline(std::cin, input);
|
||||
|
||||
if (input == "quit") {
|
||||
done = true;
|
||||
} else if (input == "help") {
|
||||
std::cout
|
||||
<< "\nCommand List:\n"
|
||||
<< "connect <ws uri>\n"
|
||||
<< "close <connection id> [<close code:default=1000>] [<close reason>]\n"
|
||||
<< "show <connection id>\n"
|
||||
<< "help: Display this help text\n"
|
||||
<< "quit: Exit the program\n"
|
||||
<< std::endl;
|
||||
} else if (input.substr(0,7) == "connect") {
|
||||
int id = endpoint.connect(input.substr(8));
|
||||
if (id != -1) {
|
||||
std::cout << "> Created connection with id " << id << std::endl;
|
||||
}
|
||||
} else if (input.substr(0,5) == "close") {
|
||||
std::stringstream ss(input);
|
||||
|
||||
std::string cmd;
|
||||
int id;
|
||||
int close_code = websocketpp::close::status::normal;
|
||||
std::string reason = "";
|
||||
|
||||
ss >> cmd >> id >> close_code;
|
||||
std::getline(ss,reason);
|
||||
|
||||
endpoint.close(id, close_code, reason);
|
||||
} else if (input.substr(0,4) == "show") {
|
||||
int id = atoi(input.substr(5).c_str());
|
||||
|
||||
connection_metadata::ptr metadata = endpoint.get_metadata(id);
|
||||
if (metadata) {
|
||||
std::cout << *metadata << std::endl;
|
||||
} else {
|
||||
std::cout << "> Unknown connection id " << id << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "> Unrecognized Command" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user