Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 43970572f5 | |||
| 6a1dccc8cb | |||
| 6aa11a7fac | |||
| 0318700c00 | |||
| 27a6d6f4d3 | |||
| ce1c1d3a76 | |||
| 1c8ba9954e | |||
| 52ce31bea4 | |||
| 47a3c060ee | |||
| d80d9afd88 | |||
| 25322aac0d | |||
| 10ac9c41ec | |||
| 492ada4788 | |||
| b73f1526b6 | |||
| 34a10b0916 | |||
| db0a43a228 | |||
| dbdb150021 | |||
| 5dfe48b043 | |||
| 3e3b5a0bb8 | |||
| 54b1931963 | |||
| c2f83814dc | |||
| dd9899c34b | |||
| a17a27dd5c | |||
| 546846af19 | |||
| 12245fd745 | |||
| 16aaa00a1c | |||
| 4b3ca1911b | |||
| 925b4cdd68 | |||
| 6f0722b04e | |||
| 3ecec05364 | |||
| a0040da1d7 | |||
| 159b9d3a88 | |||
| b7009335fe | |||
| 44bacdb323 | |||
| 3208b1b493 | |||
| 1f8113bbd6 | |||
| 87d76a3995 | |||
| 84e021e679 | |||
| 8d9f55ad23 | |||
| 9716a2269c | |||
| 125142a7d1 | |||
| f78b9df4ad | |||
| 241a28cbd7 | |||
| 61be3c182c | |||
| a3b7546d65 | |||
| 0cd1c58505 | |||
| 674042f576 | |||
| 0b10e9c0a3 | |||
| 9838895d39 | |||
| 19173e9584 | |||
| b58cf53353 | |||
| 2d12256c7c | |||
| 1d3942622a | |||
| 002e75891e | |||
| 2f6565565b | |||
| 232fd1ebf6 | |||
| 469c97c7d9 | |||
| 8e091853cc | |||
| 899b7e3bea | |||
| 9ba194a7f9 | |||
| e928f4a566 | |||
| 31a9f9a9bc | |||
| 7875f03f76 | |||
| 419178dead | |||
| a4bca13636 | |||
| 8d846000bf | |||
| dc3be3d658 | |||
| 75ef3defe9 | |||
| 0eedb6e8b6 | |||
| 04f8413f7d | |||
| 42afb69ede | |||
| af23ead5fc | |||
| dc1e432cdf | |||
| 7c4c359ef9 | |||
| 1512598e3f | |||
| 9bc3220b5e | |||
| 8129787625 | |||
| 14802c7afc | |||
| 64156eff9f | |||
| 4e7b899dc7 | |||
| ea19f1e501 | |||
| f3fc8a2466 | |||
| 6c9d814392 | |||
| eb79122da9 | |||
| bb2154613c | |||
| 5f3fbc9593 | |||
| b2f57039ae | |||
| 0c90670176 | |||
| b8ddddfe01 | |||
| 0f95459ac4 | |||
| 368a0f3726 | |||
| 3017830e77 | |||
| edf244daf7 | |||
| 2109723b34 | |||
| 9348aa4c21 | |||
| 6ca0b49ae0 | |||
| 517852cd95 | |||
| d20a2f6fef | |||
| 461fe64242 | |||
| 892fdd2456 | |||
| 3cef677c31 | |||
| 2f6a014a2e | |||
| 59efe59466 | |||
| 9d221c6a84 | |||
| 60c2f8efb2 | |||
| b5cd8488ce | |||
| 8e73e436d0 | |||
| 14562aa8bc | |||
| ae12a9ee52 | |||
| 41cd2ac01e | |||
| 76296fe2dd | |||
| 9cdc8e7009 | |||
| 6fabf34630 | |||
| f6fd0f4fb2 | |||
| 09c541185d | |||
| c6bb4912b2 | |||
| 3994731df8 | |||
| 6b32481a87 | |||
| 2fa84a07f0 | |||
| 1a0796d315 | |||
| 002b8a2c35 |
@@ -28,7 +28,7 @@
|
||||
# It's authors were Jonathan Wallace and Bernhard Fluehmann.
|
||||
|
||||
|
||||
objects = network_utilities.o sha1.o base64.o md5.o uri.o hybi_header.o data.o
|
||||
objects = network_utilities.o sha1.o base64.o md5.o uri.o hybi_header.o hybi_util.o data.o
|
||||
|
||||
BOOST_PREFIX ?= /usr/local
|
||||
BOOST_LIB_PATH ?= $(BOOST_PREFIX)/lib
|
||||
@@ -76,7 +76,7 @@ CXX ?= c++
|
||||
AR ?= ar
|
||||
PIC ?= PIC
|
||||
BUILD_TYPE ?= default
|
||||
SHARED ?= 1
|
||||
SHARED ?= 0
|
||||
|
||||
|
||||
# Internal Variables
|
||||
@@ -150,22 +150,25 @@ endif
|
||||
|
||||
# Compile object files
|
||||
$(objdir)/sha1.o: $(srcdir)/sha1/sha1.cpp
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/base64.o: $(srcdir)/base64/base64.cpp
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/hybi_header.o: $(srcdir)/processors/hybi_header.cpp
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/hybi_util.o: $(srcdir)/processors/hybi_util.cpp
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/data.o: $(srcdir)/messages/data.cpp
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/md5.o: $(srcdir)/md5/md5.c
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
$(objdir)/%.o: $(srcdir)/%.cpp
|
||||
$(CXX) $< -o $@ $(CXXFLAGS)
|
||||
$(CXX) $< -c -o $@ $(CXXFLAGS)
|
||||
|
||||
ifeq ($(SHARED),1)
|
||||
install: banner install_headers $(lib_target)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
import os, sys
|
||||
env = Environment(ENV = os.environ)
|
||||
|
||||
#env["CXX"] = "clang++"
|
||||
|
||||
## Boost
|
||||
##
|
||||
## Note: You need to either set BOOSTROOT to the root of a stock Boost distribution
|
||||
@@ -59,9 +61,13 @@ if env['PLATFORM'].startswith('win'):
|
||||
elif env['PLATFORM'] == 'posix':
|
||||
env.Append(CPPDEFINES = ['NDEBUG'])
|
||||
env.Append(CCFLAGS = ['-Wall', '-fno-strict-aliasing'])
|
||||
env.Append(CCFLAGS = ['-O3', '-fomit-frame-pointer', '-march=core2'])
|
||||
env.Append(CCFLAGS = ['-O3', '-fomit-frame-pointer'])
|
||||
#env['LINKFLAGS'] = ''
|
||||
elif env['PLATFORM'] == 'darwin':
|
||||
env.Append(CPPDEFINES = ['NDEBUG'])
|
||||
env.Append(CCFLAGS = ['-Wall', '-Wcast-align'])
|
||||
env.Append(CCFLAGS = ['-O3', '-fomit-frame-pointer'])
|
||||
#env['LINKFLAGS'] = ''
|
||||
|
||||
|
||||
if env['PLATFORM'].startswith('win'):
|
||||
env['LIBPATH'] = env['BOOST_LIBS']
|
||||
@@ -72,11 +78,15 @@ else:
|
||||
|
||||
platform_libs = []
|
||||
tls_libs = []
|
||||
tls_build = False
|
||||
|
||||
if env['PLATFORM'] == 'posix':
|
||||
platform_libs = ['pthread', 'rt']
|
||||
tls_libs = ['ssl', 'crypto']
|
||||
tls_build = True
|
||||
elif env['PLATFORM'] == 'darwin':
|
||||
tls_libs = ['ssl', 'crypto']
|
||||
tls_build = True
|
||||
elif env['PLATFORM'].startswith('win'):
|
||||
# Win/VC++ supports autolinking. nothing to do.
|
||||
pass
|
||||
@@ -110,9 +120,10 @@ echo_server = SConscript('#/examples/echo_server/SConscript',
|
||||
variant_dir = builddir + 'echo_server',
|
||||
duplicate = 0)
|
||||
|
||||
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',
|
||||
variant_dir = builddir + 'echo_server_tls',
|
||||
duplicate = 0)
|
||||
if tls_build:
|
||||
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',
|
||||
variant_dir = builddir + 'echo_server_tls',
|
||||
duplicate = 0)
|
||||
|
||||
echo_client = SConscript('#/examples/echo_client/SConscript',
|
||||
variant_dir = builddir + 'echo_client',
|
||||
@@ -130,4 +141,6 @@ concurrent_server = SConscript('#/examples/concurrent_server/SConscript',
|
||||
variant_dir = builddir + 'concurrent_server',
|
||||
duplicate = 0)
|
||||
|
||||
|
||||
telemetry_server = SConscript('#/examples/telemetry_server/SConscript',
|
||||
variant_dir = builddir + 'telemetry_server',
|
||||
duplicate = 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
BOOST_LIBS=boost_system boost_date_time boost_regex
|
||||
BOOST_LIBS=boost_system boost_date_time boost_regex boost_thread
|
||||
|
||||
include ../common.mk
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>WebSocket++ Broadcast Admin</title>
|
||||
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="flot/excanvas.min.js"></script><![endif]-->
|
||||
<script language="javascript" type="text/javascript" src="flot/jquery.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="flot/jquery.flot.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="md5.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="vendor/flot/jquery.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="vendor/flot/jquery.flot.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="vendor/md5.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 916 B |
|
Before Width: | Height: | Size: 891 B After Width: | Height: | Size: 891 B |
|
Before Width: | Height: | Size: 897 B After Width: | Height: | Size: 897 B |
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 916 B |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -2,6 +2,8 @@ BOOST_LIBS=boost_system boost_thread boost_regex boost_random
|
||||
|
||||
include ../common.mk
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -lpthread
|
||||
|
||||
chat_client: chat_client.o chat_client_handler.o
|
||||
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Import('platform_libs')
|
||||
|
||||
localenv = env.Clone ()
|
||||
|
||||
sources = ["chat_client","chat_client_handler.cpp"]
|
||||
sources = ["chat_client.cpp","chat_client_handler.cpp"]
|
||||
|
||||
LIBS = [wslib, platform_libs] + boostlibs(['system',
|
||||
'date_time',
|
||||
|
||||
@@ -52,8 +52,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
try {
|
||||
chat_client_handler_ptr handler(new chat_client_handler());
|
||||
client::connection_ptr con;
|
||||
client endpoint(handler);
|
||||
client::connection_ptr con;
|
||||
|
||||
endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
|
||||
endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
|
||||
@@ -63,14 +63,14 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
con = endpoint.get_connection(uri);
|
||||
|
||||
con->add_request_header("User Agent","WebSocket++/0.2.0 WebSocket++Chat/0.2.0");
|
||||
con->add_request_header("User-Agent","WebSocket++/0.2.0 WebSocket++Chat/0.2.0");
|
||||
con->add_subprotocol("com.zaphoyd.websocketpp.chat");
|
||||
|
||||
con->set_origin("http://zaphoyd.com");
|
||||
|
||||
endpoint.connect(con);
|
||||
|
||||
boost::thread t(boost::bind(&client::run, &endpoint));
|
||||
boost::thread t(boost::bind(&client::run, &endpoint, false));
|
||||
|
||||
char line[512];
|
||||
while (std::cin.getline(line, 512)) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="jquery-1.6.3.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/jquery-1.6.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="jquery-1.6.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ws;
|
||||
var url;
|
||||
|
||||
$(document).ready(init);
|
||||
|
||||
function init() {
|
||||
$(document).keypress(function(event) {
|
||||
if ( event.which == 13 ) {
|
||||
event.preventDefault();
|
||||
send();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function connect() {
|
||||
url = $("#server_url").val();
|
||||
console.log(url);
|
||||
|
||||
if ("WebSocket" in window) {
|
||||
ws = new WebSocket(url);
|
||||
} else if ("MozWebSocket" in window) {
|
||||
ws = new MozWebSocket(url);
|
||||
} else {
|
||||
chat_message("This Browser does not support WebSockets");
|
||||
return;
|
||||
}
|
||||
ws.onopen = function(e) {
|
||||
chat_message("A connection to "+url+" has been opened.");
|
||||
|
||||
$("#server_url").attr("disabled",true);
|
||||
$("#toggle_connect").html("Disconnect");
|
||||
};
|
||||
|
||||
ws.onerror = function(e) {
|
||||
chat_message("An error occured, see console log for more details.");
|
||||
console.log(e);
|
||||
};
|
||||
|
||||
ws.onclose = function(e) {
|
||||
chat_message("The connection to "+url+" was closed.");
|
||||
};
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data);
|
||||
|
||||
if (message.type == "msg") {
|
||||
chat_message(message.value,message.sender);
|
||||
} else if (message.type == "participants") {
|
||||
var o = "<ul>";
|
||||
for (var p in message.value) {
|
||||
o += "<li>"+message.value[p]+"</li>";
|
||||
}
|
||||
o += "</ul>";
|
||||
$("#participants").html(o);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function chat_message(message,sender) {
|
||||
if (arguments.length == 1) {
|
||||
sender = "";
|
||||
}
|
||||
|
||||
var style;
|
||||
|
||||
if (sender == "") {
|
||||
style = "client";
|
||||
} else if (sender == "server") {
|
||||
style = "server";
|
||||
sender = "["+sender+"]";
|
||||
} else {
|
||||
style = "message";
|
||||
sender = "["+sender+"]";
|
||||
}
|
||||
|
||||
$("#messages").append("<span class='"+style+"'><span class='sender'>"+sender+"</span> <span class='msg'>"+message+"</span></span><br />");
|
||||
$("#messages").prop({ scrollTop: $("#messages").prop("scrollHeight") });
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
ws.close();
|
||||
$("#server_url").removeAttr("disabled");
|
||||
$("#toggle_connect").html("Connect");
|
||||
$("#participants").html("");
|
||||
}
|
||||
|
||||
function toggle_connect() {
|
||||
if ($("#server_url").attr("disabled") != "disabled") {
|
||||
connect();
|
||||
} else {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
function send() {
|
||||
if (ws === undefined || ws.readyState != 1) {
|
||||
chat_message("Websocket is not avaliable for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
ws.send($("#msg").val());
|
||||
$("#msg").val("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body,html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
background-color: #999;
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
|
||||
}
|
||||
|
||||
#controls {
|
||||
padding: 4px;
|
||||
float:right;
|
||||
width: 300px;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#messages {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#messages .client {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
#messages .server {
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
#messages .message {
|
||||
color: white;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="controls">
|
||||
<div id="server">
|
||||
<input type="text" name="server_url" id="server_url" value="ws://thor-websocket.zaphoyd.net:9000/chat" />
|
||||
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
|
||||
</div>
|
||||
|
||||
<div id="message_input"><input type="text" name="msg" id="msg" value="Hello World!" />
|
||||
<button onclick="send();">Send</button></div>
|
||||
<h3>Chat Participants</h3>
|
||||
<div id="participants"></div>
|
||||
</div>
|
||||
<div id="messages"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -139,40 +139,53 @@ void process_requests(request_coordinator* coordinator) {
|
||||
}
|
||||
}
|
||||
|
||||
// concurrent server takes two arguments. A port to bind to and a number of
|
||||
// worker threads to create. The thread count must be an integer greater than
|
||||
// or equal to zero.
|
||||
// usage: <port> <thread_pool_threads> <worker_threads>
|
||||
//
|
||||
// num_threads=0 Standard non-threaded WebSocket++ mode. Handlers will block
|
||||
// i/o operations and other handlers.
|
||||
// num_threads=1 One thread processes requests serially the other handles i/o
|
||||
// This allows new connections and requests to be made while the
|
||||
// processing thread is busy, but does allow long jobs to
|
||||
// monopolize the processor increasing request latency.
|
||||
// num_threads>1 Multiple processing threads will work on the single queue of
|
||||
// requests provided by the i/o thread. This enables out of order
|
||||
// completion of requests. The number of threads can be tuned
|
||||
// based on hardware concurrency available and expected load and
|
||||
// job length.
|
||||
// port = port to listen on
|
||||
// thread_pool_threads = number of threads in the pool running io_service.run()
|
||||
// worker_threads = number of threads in the sleep work pool.
|
||||
//
|
||||
// thread_pool_threads determines the number of threads that process i/o handlers. This
|
||||
// must be at least one. Handlers and callbacks for individual connections are always
|
||||
// serially executed within that connection. An i/o thread pool will not improve
|
||||
// performance in cases where number of connections < number of threads in pool.
|
||||
//
|
||||
// worker_threads=0 Standard non-threaded WebSocket++ mode. Handlers will block
|
||||
// i/o operations within their own connection.
|
||||
// worker_threads=1 A single work thread processes requests serially separate from the i/o
|
||||
// thread(s). This allows new connections and requests to be made while the
|
||||
// processing thread is busy, but does allow long jobs to
|
||||
// monopolize the processor increasing request latency.
|
||||
// worker_threads>1 Multiple work threads will work on the single queue of
|
||||
// requests provided by the i/o thread(s). This enables out of order
|
||||
// completion of requests. The number of threads can be tuned
|
||||
// based on hardware concurrency available and expected load and
|
||||
// job length.
|
||||
int main(int argc, char* argv[]) {
|
||||
unsigned short port = 9002;
|
||||
unsigned short num_threads = 2;
|
||||
size_t worker_threads = 2;
|
||||
size_t pool_threads = 2;
|
||||
|
||||
try {
|
||||
if (argc == 2) {
|
||||
if (argc >= 2) {
|
||||
std::stringstream buffer(argv[1]);
|
||||
buffer >> port;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
if (argc >= 3) {
|
||||
std::stringstream buffer(argv[2]);
|
||||
buffer >> num_threads;
|
||||
buffer >> pool_threads;
|
||||
}
|
||||
|
||||
|
||||
if (argc >= 4) {
|
||||
std::stringstream buffer(argv[3]);
|
||||
buffer >> worker_threads;
|
||||
}
|
||||
|
||||
request_coordinator rc;
|
||||
|
||||
server::handler::ptr h;
|
||||
if (num_threads == 0) {
|
||||
if (worker_threads == 0) {
|
||||
h = server::handler::ptr(new server_handler());
|
||||
} else {
|
||||
h = server::handler::ptr(new concurrent_server_handler(rc));
|
||||
@@ -187,13 +200,20 @@ int main(int argc, char* argv[]) {
|
||||
echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
|
||||
|
||||
std::list<boost::shared_ptr<boost::thread> > threads;
|
||||
|
||||
for (int i = 0; i < num_threads; i++) {
|
||||
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&process_requests, &rc))));
|
||||
if (worker_threads > 0) {
|
||||
for (size_t i = 0; i < worker_threads; i++) {
|
||||
threads.push_back(
|
||||
boost::shared_ptr<boost::thread>(
|
||||
new boost::thread(boost::bind(&process_requests, &rc))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Starting WebSocket sleep server on port " << port << " with " << num_threads << " processing threads." << std::endl;
|
||||
echo_endpoint.listen(port);
|
||||
std::cout << "Starting WebSocket sleep server on port " << port
|
||||
<< " with thread pool size " << pool_threads << " and "
|
||||
<< worker_threads << " worker threads." << std::endl;
|
||||
echo_endpoint.listen(port,pool_threads);
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -70,9 +70,7 @@ int main(int argc, char* argv[]) {
|
||||
endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
|
||||
|
||||
con = endpoint.connect(uri+"getCaseCount");
|
||||
|
||||
con->add_request_header("User Agent","WebSocket++/0.2.0-dev");
|
||||
|
||||
|
||||
endpoint.run();
|
||||
|
||||
std::cout << "case count: " << boost::dynamic_pointer_cast<echo_client_handler>(handler)->m_case_count << std::endl;
|
||||
|
||||
@@ -2,6 +2,8 @@ BOOST_LIBS=boost_system boost_date_time boost_thread boost_regex boost_random
|
||||
|
||||
include ../common.mk
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -lpthread
|
||||
|
||||
fuzzing_client: fuzzing_client.o
|
||||
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
BOOST_LIBS=boost_system boost_date_time boost_regex
|
||||
BOOST_LIBS=boost_system boost_date_time boost_regex boost_thread
|
||||
|
||||
include ../common.mk
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ private:
|
||||
m_msg_stats.clear();
|
||||
}
|
||||
|
||||
int m_connections_max;
|
||||
int m_connections_cur;
|
||||
unsigned int m_connections_max;
|
||||
unsigned int m_connections_cur;
|
||||
std::map<std::string,size_t> m_msg_stats;
|
||||
boost::shared_ptr<boost::asio::deadline_timer> m_timer;
|
||||
};
|
||||
@@ -150,14 +150,16 @@ int main(int argc, char* argv[]) {
|
||||
int num_connections = 100;
|
||||
int batch_size = 25;
|
||||
int delay_ms = 16;
|
||||
|
||||
if (argc != 5) {
|
||||
std::cout << "Usage: `echo_client test_url num_connections batch_size delay_ms`" << std::endl;
|
||||
} else {
|
||||
uri = argv[1];
|
||||
num_connections = atoi(argv[2]);
|
||||
batch_size = atoi(argv[3]);
|
||||
delay_ms = atoi(argv[4]);
|
||||
|
||||
if (argc > 1) {
|
||||
if (argc != 5) {
|
||||
std::cout << "Usage: `echo_client test_url num_connections batch_size delay_ms`" << std::endl;
|
||||
} else {
|
||||
uri = argv[1];
|
||||
num_connections = atoi(argv[2]);
|
||||
batch_size = atoi(argv[3]);
|
||||
delay_ms = atoi(argv[4]);
|
||||
}
|
||||
}
|
||||
|
||||
// 12288 is max OS X limit without changing kernal settings
|
||||
@@ -209,7 +211,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
connections.insert(endpoint.connect(uri));
|
||||
|
||||
boost::thread t(boost::bind(&plain_endpoint_type::run, &endpoint));
|
||||
boost::thread t(boost::bind(&plain_endpoint_type::run, &endpoint, false));
|
||||
|
||||
std::cout << "launching " << num_connections << " connections to " << uri << " in batches of " << batch_size << std::endl;
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
BOOST_LIBS=boost_system boost_date_time boost_program_options boost_thread boost_regex
|
||||
|
||||
include ../common.mk
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -lpthread
|
||||
|
||||
telemetry_server: telemetry_server.o
|
||||
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c $(CFLAGS) -o $@ $^
|
||||
|
||||
# cleanup by removing generated files
|
||||
#
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o telemetry_server
|
||||
@@ -0,0 +1,20 @@
|
||||
## telemetry_server
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('boostlibs')
|
||||
Import('wslib')
|
||||
Import('platform_libs')
|
||||
|
||||
localenv = env.Clone ()
|
||||
|
||||
sources = ["telemetry_server.cpp"]
|
||||
|
||||
LIBS = [wslib, platform_libs] + boostlibs(['system',
|
||||
'date_time',
|
||||
'regex',
|
||||
'thread'])
|
||||
|
||||
prg = localenv.Program('telemetry_server', sources, LIBS = LIBS)
|
||||
|
||||
Return('prg')
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../src/websocketpp.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
|
||||
#include <boost/functional.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using websocketpp::server;
|
||||
|
||||
/// Thread body. Counts up indefinitely, one increment per second. After each
|
||||
/// it calls the handler back asking it to broadcast the new value. The handler
|
||||
/// callback returns whether or not the handler would like the telemetry thread
|
||||
/// to stop. If callback returns true the telemetry loop ands end the thread
|
||||
/// exits.
|
||||
void generate_telemetry(boost::function<bool(const std::string&)> callback) {
|
||||
size_t value = 0;
|
||||
|
||||
for (;;) {
|
||||
// do some work
|
||||
value++;
|
||||
|
||||
// broadcast state
|
||||
std::stringstream m;
|
||||
m << value;
|
||||
|
||||
if (callback(m.str())) {
|
||||
break;
|
||||
}
|
||||
|
||||
// wait
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
|
||||
class telemetry_server_handler : public server::handler {
|
||||
public:
|
||||
typedef telemetry_server_handler type;
|
||||
typedef boost::shared_ptr<type> ptr;
|
||||
|
||||
telemetry_server_handler() : m_done(false),m_value(0) {
|
||||
boost::function<bool(const std::string&)> callback = boost::bind(&type::on_tick,this,_1);
|
||||
|
||||
// start a thread that will generate telemetry independently and call
|
||||
// this handler back when it has new data to send.
|
||||
m_telemetry_thread.reset(new boost::thread(
|
||||
boost::bind(
|
||||
&generate_telemetry,
|
||||
callback
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
// If the handler is going away set done to true and wait for the thread
|
||||
// to exit.
|
||||
~telemetry_server_handler() {
|
||||
{
|
||||
boost::lock_guard<boost::mutex> guard(m_mutex);
|
||||
m_done = true;
|
||||
}
|
||||
m_telemetry_thread->join();
|
||||
}
|
||||
|
||||
/// Function that we pass to the telemetry thread to broadcast the new
|
||||
/// state. It returns the global "are we done" value so we can control when
|
||||
/// the thread stops running.
|
||||
bool on_tick(const std::string& msg) {
|
||||
boost::lock_guard<boost::mutex> guard(m_mutex);
|
||||
|
||||
std::set<connection_ptr>::iterator it;
|
||||
|
||||
for (it = m_connections.begin(); it != m_connections.end(); it++) {
|
||||
(*it)->send(msg);
|
||||
}
|
||||
|
||||
return m_done;
|
||||
}
|
||||
|
||||
// register a new client
|
||||
void on_open(connection_ptr con) {
|
||||
boost::lock_guard<boost::mutex> guard(m_mutex);
|
||||
m_connections.insert(con);
|
||||
}
|
||||
|
||||
// remove an exiting client
|
||||
void on_close(connection_ptr con) {
|
||||
boost::lock_guard<boost::mutex> guard(m_mutex);
|
||||
m_connections.erase(con);
|
||||
}
|
||||
private:
|
||||
bool m_done;
|
||||
size_t m_value;
|
||||
std::set<connection_ptr> m_connections;
|
||||
|
||||
boost::mutex m_mutex; // guards m_connections
|
||||
boost::shared_ptr<boost::thread> m_telemetry_thread;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
unsigned short port = 9007;
|
||||
|
||||
if (argc == 2) {
|
||||
port = atoi(argv[1]);
|
||||
|
||||
if (port == 0) {
|
||||
std::cout << "Unable to parse port input " << argv[1] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
server::handler::ptr handler(new telemetry_server_handler());
|
||||
server endpoint(handler);
|
||||
|
||||
endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
|
||||
endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
|
||||
|
||||
endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
|
||||
endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);
|
||||
|
||||
endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
|
||||
endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
|
||||
|
||||
std::cout << "Starting WebSocket telemetry server on port " << port << std::endl;
|
||||
endpoint.listen(port);
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ ifneq ($(OS), Darwin)
|
||||
LDFLAGS := $(LDFLAGS) -lrt -lpthread
|
||||
endif
|
||||
|
||||
wsperf: wsperf.o request.o case.o generic.o wscmd.o
|
||||
wsperf: wsperf.o request.o case.o generic.o wscmd.o stress_aggregate.o stress_handler.o
|
||||
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
|
||||
@@ -12,15 +12,17 @@ sources = ["wsperf.cpp",
|
||||
"request.cpp",
|
||||
"case.cpp",
|
||||
"generic.cpp",
|
||||
"stress_handler.cpp",
|
||||
"stress_aggregate.cpp",
|
||||
"wscmd.cpp"]
|
||||
|
||||
LIBS = [wslib, platform_libs] + boostlibs(['system',
|
||||
'date_time',
|
||||
'regex',
|
||||
'thread',
|
||||
'random',
|
||||
'chrono',
|
||||
'program_options'])
|
||||
LIBS = [wslib] + boostlibs(['system',
|
||||
'date_time',
|
||||
'regex',
|
||||
'thread',
|
||||
'random',
|
||||
'chrono',
|
||||
'program_options']) + [platform_libs]
|
||||
|
||||
prg = localenv.Program('wsperf', sources, LIBS = LIBS)
|
||||
|
||||
|
||||
@@ -72,7 +72,11 @@ public:
|
||||
|
||||
void on_timer(connection_ptr con,const boost::system::error_code& error);
|
||||
|
||||
void on_close(connection_ptr con) {}
|
||||
void on_close(connection_ptr con) {
|
||||
con->alog()->at(websocketpp::log::alevel::DEVEL)
|
||||
<< "case_handler::on_close"
|
||||
<< websocketpp::log::endl;
|
||||
}
|
||||
void on_fail(connection_ptr con);
|
||||
|
||||
const std::string& get_data() const;
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
Frequently asked questions
|
||||
--------------------------
|
||||
|
||||
Q: How much data can Flot cope with?
|
||||
|
||||
A: Flot will happily draw everything you send to it so the answer
|
||||
depends on the browser. The excanvas emulation used for IE (built with
|
||||
VML) makes IE by far the slowest browser so be sure to test with that
|
||||
if IE users are in your target group.
|
||||
|
||||
1000 points is not a problem, but as soon as you start having more
|
||||
points than the pixel width, you should probably start thinking about
|
||||
downsampling/aggregation as this is near the resolution limit of the
|
||||
chart anyway. If you downsample server-side, you also save bandwidth.
|
||||
|
||||
|
||||
Q: Flot isn't working when I'm using JSON data as source!
|
||||
|
||||
A: Actually, Flot loves JSON data, you just got the format wrong.
|
||||
Double check that you're not inputting strings instead of numbers,
|
||||
like [["0", "-2.13"], ["5", "4.3"]]. This is most common mistake, and
|
||||
the error might not show up immediately because Javascript can do some
|
||||
conversion automatically.
|
||||
|
||||
|
||||
Q: Can I export the graph?
|
||||
|
||||
A: This is a limitation of the canvas technology. There's a hook in
|
||||
the canvas object for getting an image out, but you won't get the tick
|
||||
labels. And it's not likely to be supported by IE. At this point, your
|
||||
best bet is probably taking a screenshot, e.g. with PrtScn.
|
||||
|
||||
|
||||
Q: The bars are all tiny in time mode?
|
||||
|
||||
A: It's not really possible to determine the bar width automatically.
|
||||
So you have to set the width with the barWidth option which is NOT in
|
||||
pixels, but in the units of the x axis (or the y axis for horizontal
|
||||
bars). For time mode that's milliseconds so the default value of 1
|
||||
makes the bars 1 millisecond wide.
|
||||
|
||||
|
||||
Q: Can I use Flot with libraries like Mootools or Prototype?
|
||||
|
||||
A: Yes, Flot supports it out of the box and it's easy! Just use jQuery
|
||||
instead of $, e.g. call jQuery.plot instead of $.plot and use
|
||||
jQuery(something) instead of $(something). As a convenience, you can
|
||||
put in a DOM element for the graph placeholder where the examples and
|
||||
the API documentation are using jQuery objects.
|
||||
|
||||
Depending on how you include jQuery, you may have to add one line of
|
||||
code to prevent jQuery from overwriting functions from the other
|
||||
libraries, see the documentation in jQuery ("Using jQuery with other
|
||||
libraries") for details.
|
||||
|
||||
|
||||
Q: Flot doesn't work with [insert name of Javascript UI framework]!
|
||||
|
||||
A: The only non-standard thing used by Flot is the canvas tag;
|
||||
otherwise it is simply a series of absolute positioned divs within the
|
||||
placeholder tag you put in. If this is not working, it's probably
|
||||
because the framework you're using is doing something weird with the
|
||||
DOM, or you're using it the wrong way.
|
||||
|
||||
A common problem is that there's display:none on a container until the
|
||||
user does something. Many tab widgets work this way, and there's
|
||||
nothing wrong with it - you just can't call Flot inside a display:none
|
||||
container as explained in the README so you need to hold off the Flot
|
||||
call until the container is actually displayed (or use
|
||||
visibility:hidden instead of display:none or move the container
|
||||
off-screen).
|
||||
|
||||
If you find there's a specific thing we can do to Flot to help, feel
|
||||
free to submit a bug report. Otherwise, you're welcome to ask for help
|
||||
on the forum/mailing list, but please don't submit a bug report to
|
||||
Flot.
|
||||
@@ -1,22 +0,0 @@
|
||||
Copyright (c) 2007-2009 IOLA and Ole Laursen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,9 +0,0 @@
|
||||
# Makefile for generating minified files
|
||||
|
||||
.PHONY: all
|
||||
|
||||
# we cheat and process all .js files instead of an exhaustive list
|
||||
all: $(patsubst %.js,%.min.js,$(filter-out %.min.js,$(wildcard *.js)))
|
||||
|
||||
%.min.js: %.js
|
||||
yui-compressor $< -o $@
|
||||