From a17a4deb4b1736ece8c9c1616bf6f19d999d8802 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 12 Jan 2012 09:57:06 -0600 Subject: [PATCH] normalizes whitespace and sets up gitattributes to preserve fixes #43 fixes #46 --- .gitattributes | 18 + .../broadcast_server_tls/broadcast_admin.html | 196 +-- .../broadcast_admin_handler.hpp | 12 +- .../broadcast_handler.hpp | 32 +- .../broadcast_server_tls.cpp | 104 +- examples/chat_client/chat_client.cpp | 70 +- examples/chat_client/chat_client.html | 214 +-- examples/chat_client/chat_client_handler.cpp | 206 +-- examples/chat_client/chat_client_handler.hpp | 58 +- examples/chat_server/chat.cpp | 262 ++-- examples/chat_server/chat.hpp | 40 +- examples/chat_server/chat_server.cpp | 64 +- examples/echo_client/echo_client.cpp | 118 +- examples/echo_client/echo_client_handler.cpp | 20 +- examples/echo_client/echo_client_handler.hpp | 30 +- examples/echo_server/echo.hpp | 34 +- examples/echo_server/echo_client.html | 110 +- examples/echo_server/echo_server.cpp | 50 +- examples/echo_server_tls/echo.hpp | 34 +- examples/echo_server_tls/echo_client.html | 110 +- examples/echo_server_tls/echo_server_tls.cpp | 138 +- examples/fuzzing_client/fuzzing_client.cpp | 420 +++--- examples/fuzzing_server_tls/echo_client.html | 110 +- .../fuzzing_server_tls/fuzzing_server_tls.cpp | 270 ++-- examples/stress_client/stress_client.cpp | 152 +- src/common.hpp | 126 +- src/connection.hpp | 1132 +++++++------- src/http/constants.hpp | 354 ++--- src/http/parser.hpp | 440 +++--- src/logger/logger.hpp | 210 ++- src/messages/control.hpp | 164 +-- src/messages/data.cpp | 8 +- src/messages/data.hpp | 30 +- src/network_utilities.cpp | 90 +- src/processors/hybi.hpp | 794 +++++----- src/processors/hybi_header.cpp | 270 ++-- src/processors/hybi_header.hpp | 62 +- src/processors/hybi_legacy.hpp | 478 +++--- src/processors/processor.hpp | 156 +- src/rng/blank_rng.hpp | 10 +- src/rng/boost_rng.cpp | 4 +- src/rng/boost_rng.hpp | 24 +- src/roles/client.hpp | 396 ++--- src/roles/server.hpp | 310 ++-- src/sockets/plain.hpp | 114 +- src/sockets/ssl.hpp | 198 +-- src/uri.cpp | 138 +- src/uri.hpp | 14 +- src/utf8_validator/utf8_validator.hpp | 72 +- src/websocket_frame.hpp | 1120 +++++++------- src/websocketpp.hpp | 8 +- test/basic/logging.cpp | 16 +- test/basic/parsing.cpp | 388 ++--- test/basic/uri_perf.cpp | 30 +- websocketpp.bbprojectd/Scratchpad.txt | 0 .../Unix Worksheet.worksheet | 0 websocketpp.bbprojectd/project.bbprojectdata | 342 +++++ .../zaphoyd.bbprojectsettings | 1301 +++++++++++++++++ 58 files changed, 6661 insertions(+), 5010 deletions(-) create mode 100644 .gitattributes create mode 100644 websocketpp.bbprojectd/Scratchpad.txt create mode 100644 websocketpp.bbprojectd/Unix Worksheet.worksheet create mode 100644 websocketpp.bbprojectd/project.bbprojectdata create mode 100644 websocketpp.bbprojectd/zaphoyd.bbprojectsettings diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..23741ecc5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,18 @@ +# Lineendings +*.sln eol=crlf +*.vcproj eol=crlf +*.vcxproj* eol=crfl + +# Whitespace rules +# strict (no trailing, no tabs) +*.cpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.hpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.c whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.h whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol + +# normal (no trailing) +*.sql whitespace=trailing-space,space-before-tab,cr-at-eol +*.txt whitespace=trailing-space,space-before-tab,cr-at-eol + +# special files which must ignore whitespace +*.patch whitespace=-trailing-space \ No newline at end of file diff --git a/examples/broadcast_server_tls/broadcast_admin.html b/examples/broadcast_server_tls/broadcast_admin.html index d36288521..cb352b5f0 100644 --- a/examples/broadcast_server_tls/broadcast_admin.html +++ b/examples/broadcast_server_tls/broadcast_admin.html @@ -1,11 +1,11 @@ - - WebSocket++ Broadcast Admin - - - + + WebSocket++ Broadcast Admin + + + @@ -27,52 +27,52 @@ var msgs = {}; function connect() { - url = document.getElementById("server_url").value; - - if ("WebSocket" in window) { - ws_client = new WebSocket(url); + url = document.getElementById("server_url").value; + + if ("WebSocket" in window) { + ws_client = new WebSocket(url); ws_admin = new WebSocket(url+"/admin"); - } else if ("MozWebSocket" in window) { - ws_client = new MozWebSocket(url); + } else if ("MozWebSocket" in window) { + ws_client = new MozWebSocket(url); ws_admin = new MozWebSocket(url+"/admin"); - } else { - $("#messages").innerHTML += "This Browser does not support WebSockets
"; - return; - } + } else { + $("#messages").innerHTML += "This Browser does not support WebSockets
"; + return; + } - ws_client.onopen = function(e) { - $("#messages").append("Client: A client connection to "+url+" has been opened.
"); - - $("#server_url").disabled = true; - $("#toggle_connect").html("Disconnect"); - }; + ws_client.onopen = function(e) { + $("#messages").append("Client: A client connection to "+url+" has been opened.
"); + + $("#server_url").disabled = true; + $("#toggle_connect").html("Disconnect"); + }; ws_admin.onopen = function(e) { - $("#messages").append("Client: An admin connection to "+url+"/admin has been opened.
"); - - $("#server_url").disabled = true; - $("#toggle_connect").html("Disconnect"); - }; - - ws_client.onerror = function(e) { - $("#messages").append("Client: An error occured on the client channel, see console log for more details.
"); - console.log(e); - }; + $("#messages").append("Client: An admin connection to "+url+"/admin has been opened.
"); + + $("#server_url").disabled = true; + $("#toggle_connect").html("Disconnect"); + }; + + ws_client.onerror = function(e) { + $("#messages").append("Client: An error occured on the client channel, see console log for more details.
"); + console.log(e); + }; ws_admin.onerror = function(e) { - $("#messages").append("Client: An error occured on the admin channel, see console log for more details.
"); - console.log(e); - }; - - ws_client.onclose = function(e) { - $("#messages").append("Client: The client connection to "+url+" was closed.
"); - clear_hud(); - }; + $("#messages").append("Client: An error occured on the admin channel, see console log for more details.
"); + console.log(e); + }; + + ws_client.onclose = function(e) { + $("#messages").append("Client: The client connection to "+url+" was closed.
"); + clear_hud(); + }; ws_admin.onclose = function(e) { - $("#messages").append("Client: The admin connection to "+url+"/admin was closed.
"); - clear_hud(); - }; - + $("#messages").append("Client: The admin connection to "+url+"/admin was closed.
"); + clear_hud(); + }; + ws_client.onmessage = function(e) { if (options.console_enabled) { if (e.data.length <= 126) { @@ -84,20 +84,20 @@ ws_client.send("ack:"+hex_md5(e.data)+"=1;"); } - ws_admin.onmessage = function(e) { + ws_admin.onmessage = function(e) { foo = JSON.parse(e.data); - - if (foo.type == "message") { - if (options.console_enabled) { + + if (foo.type == "message") { + if (options.console_enabled) { document.getElementById("messages").innerHTML += "Broadcasted Message: "+foo.value+"
"; } - } else if (foo.type == "error") { - if (options.console_enabled) { + } else if (foo.type == "error") { + if (options.console_enabled) { document.getElementById("messages").innerHTML += "Command Error: "+foo.value+"
"; } - } else if (foo.type == "con") { - document.getElementById("connected_clients").innerHTML = foo.value; - } else if (foo.type == "stats") { + } else if (foo.type == "con") { + document.getElementById("connected_clients").innerHTML = foo.value; + } else if (foo.type == "stats") { var msg_delta = 0; var data_delta = 0; @@ -131,10 +131,10 @@ $("#sent_messages").html(o); /*document.getElementById("messages_per_sec").innerHTML = foo.messages+"/s"; - document.getElementById("bytes_per_sec").innerHTML = format_data(foo.bytes)+"/s"; - document.getElementById("messages_sent").innerHTML = foo.messages_sent; + document.getElementById("bytes_per_sec").innerHTML = format_data(foo.bytes)+"/s"; + document.getElementById("messages_sent").innerHTML = foo.messages_sent; document.getElementById("messages_acked").innerHTML = foo.messages_acked; - document.getElementById("bytes_sent").innerHTML = format_data(foo.bytes_sent);*/ + document.getElementById("bytes_sent").innerHTML = format_data(foo.bytes_sent);*/ document.getElementById("admin_connections").innerHTML = foo.admin_connections; @@ -155,45 +155,45 @@ if (message_history.length > total_points) { message_history = message_history.slice(message_history.length-total_points); } - } else { - document.getElementById("messages").innerHTML += "Unrecognized Server Command.
"; - } - } + } else { + document.getElementById("messages").innerHTML += "Unrecognized Server Command.
"; + } + } } function clear_hud() { - document.getElementById("server_url").disabled = false; - document.getElementById("toggle_connect").innerHTML = "Connect"; - document.getElementById("connected_clients").innerHTML = "N/A"; + document.getElementById("server_url").disabled = false; + document.getElementById("toggle_connect").innerHTML = "Connect"; + document.getElementById("connected_clients").innerHTML = "N/A"; document.getElementById("admin_connections").innerHTML = "N/A"; - document.getElementById("messages_per_sec").innerHTML = "N/A"; - document.getElementById("bytes_per_sec").innerHTML = "N/A"; - document.getElementById("messages_sent").innerHTML = "N/A"; - document.getElementById("bytes_sent").innerHTML = "N/A"; + document.getElementById("messages_per_sec").innerHTML = "N/A"; + document.getElementById("bytes_per_sec").innerHTML = "N/A"; + document.getElementById("messages_sent").innerHTML = "N/A"; + document.getElementById("bytes_sent").innerHTML = "N/A"; document.getElementById("messages_acked").innerHTML = "N/A"; } - + function disconnect() { - ws_client.close(); + ws_client.close(); ws_admin.close(); } function toggle_connect() { - if (document.getElementById("server_url").disabled === false) { - connect(); - } else { - disconnect(); - } + if (document.getElementById("server_url").disabled === false) { + connect(); + } else { + disconnect(); + } } function broadcast() { - if (ws_client === undefined || ws_client.readyState != 1) { - $("#messages").append("Client: Client websocket is not avaliable for writing
"); - return; - } - - ws_client.send(document.getElementById("msg").value); - document.getElementById("msg").value = ""; + if (ws_client === undefined || ws_client.readyState != 1) { + $("#messages").append("Client: Client websocket is not avaliable for writing
"); + return; + } + + ws_client.send(document.getElementById("msg").value); + document.getElementById("msg").value = ""; } function send_command(command,args) { @@ -278,21 +278,21 @@
-
- - -
+
+ + +
-
-
- -

Stats

-

Server

+
+
+ +

Stats

+

Server

Connected Clients: N/A
Admin Clients: N/A
@@ -325,7 +325,7 @@

Messages

Messages Sent: N/A
Messages Acked: N/A
Messages Rate: N/A
-
+
diff --git a/examples/broadcast_server_tls/broadcast_admin_handler.hpp b/examples/broadcast_server_tls/broadcast_admin_handler.hpp index bf87c9d48..96518bd85 100644 --- a/examples/broadcast_server_tls/broadcast_admin_handler.hpp +++ b/examples/broadcast_server_tls/broadcast_admin_handler.hpp @@ -58,10 +58,10 @@ class admin_handler : public endpoint_type::handler { void on_open(connection_ptr connection) { if (!m_timer) { - m_timer.reset(new boost::asio::deadline_timer(connection->get_io_service(),boost::posix_time::seconds(0))); - m_timer->expires_from_now(boost::posix_time::milliseconds(250)); - m_timer->async_wait(boost::bind(&type::on_timer,this,boost::asio::placeholders::error)); - } + m_timer.reset(new boost::asio::deadline_timer(connection->get_io_service(),boost::posix_time::seconds(0))); + m_timer->expires_from_now(boost::posix_time::milliseconds(250)); + m_timer->async_wait(boost::bind(&type::on_timer,this,boost::asio::placeholders::error)); + } m_connections.insert(connection); } @@ -177,7 +177,7 @@ class admin_handler : public endpoint_type::handler { } m_timer->expires_from_now(boost::posix_time::milliseconds(250)); - m_timer->async_wait( + m_timer->async_wait( boost::bind( &type::on_timer, this, @@ -190,7 +190,7 @@ class admin_handler : public endpoint_type::handler { broadcast_handler_ptr m_broadcast_handler; std::set m_connections; - boost::posix_time::ptime m_epoch; + boost::posix_time::ptime m_epoch; boost::shared_ptr m_timer; }; diff --git a/examples/broadcast_server_tls/broadcast_handler.hpp b/examples/broadcast_server_tls/broadcast_handler.hpp index 080b546ed..d64bf5f58 100644 --- a/examples/broadcast_server_tls/broadcast_handler.hpp +++ b/examples/broadcast_server_tls/broadcast_handler.hpp @@ -53,7 +53,7 @@ struct msg { uint64_t time; std::string hash; - boost::posix_time::ptime time_sent; + boost::posix_time::ptime time_sent; }; typedef std::map msg_map; @@ -61,16 +61,16 @@ typedef std::map msg_map; template class handler : public endpoint_type::handler { public: - typedef handler type; + typedef handler type; typedef boost::shared_ptr ptr; - typedef typename endpoint_type::handler_ptr handler_ptr; + typedef typename endpoint_type::handler_ptr handler_ptr; typedef typename endpoint_type::connection_ptr connection_ptr; - handler() : m_nextid(0) {} - - void on_open(connection_ptr connection) { + handler() : m_nextid(0) {} + + void on_open(connection_ptr connection) { m_connections.insert(connection); - } + } // this dummy tls init function will cause all TLS connections to fail. // TLS handling for broadcast::handler is usually done by a lobby handler. @@ -83,14 +83,14 @@ class handler : public endpoint_type::handler { void on_load(connection_ptr connection, handler_ptr old_handler) { this->on_open(connection); m_lobby = old_handler; - } - - void on_close(connection_ptr connection) { - m_connections.erase(connection); - } - - void on_message(connection_ptr connection,message::data_ptr msg) { - wscmd::cmd command = wscmd::parse(msg->get_payload()); + } + + void on_close(connection_ptr connection) { + m_connections.erase(connection); + } + + void on_message(connection_ptr connection,message::data_ptr msg) { + wscmd::cmd command = wscmd::parse(msg->get_payload()); std::cout << "msg: " << msg->get_payload() << std::endl; @@ -189,7 +189,7 @@ class handler : public endpoint_type::handler { m_msgs.empty(); } private: - handler_ptr m_lobby; + handler_ptr m_lobby; int m_nextid; msg_map m_msgs; diff --git a/examples/broadcast_server_tls/broadcast_server_tls.cpp b/examples/broadcast_server_tls/broadcast_server_tls.cpp index e97a338fa..df128810b 100644 --- a/examples/broadcast_server_tls/broadcast_server_tls.cpp +++ b/examples/broadcast_server_tls/broadcast_server_tls.cpp @@ -45,13 +45,13 @@ typedef websocketpp::endpoint()); - tls_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - e.elog().set_level(websocketpp::log::elevel::ALL); - - std::cout << "Starting Secure WebSocket broadcast server on port " << port << std::endl; - e.listen(port); - } else { - plain_handler_ptr h(new websocketpp::broadcast::server_handler()); - plain_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - e.elog().set_level(websocketpp::log::elevel::ALL); - + if (argc == 2) { + // TODO: input validation? + port = atoi(argv[1]); + } + + if (argc == 3) { + // TODO: input validation? + port = atoi(argv[1]); + tls = !strcmp(argv[2],"-tls"); + } + + try { + if (tls) { + tls_handler_ptr h(new websocketpp::broadcast::server_handler()); + tls_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + e.elog().set_level(websocketpp::log::elevel::ALL); + + std::cout << "Starting Secure WebSocket broadcast server on port " << port << std::endl; + e.listen(port); + } else { + plain_handler_ptr h(new websocketpp::broadcast::server_handler()); + plain_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + e.elog().set_level(websocketpp::log::elevel::ALL); + //e.alog().set_level(websocketpp::log::alevel::DEVEL); - std::cout << "Starting WebSocket broadcast server on port " << port << std::endl; - e.listen(port); - } - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - - } - - return 0; + std::cout << "Starting WebSocket broadcast server on port " << port << std::endl; + e.listen(port); + } + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + + } + + return 0; } diff --git a/examples/chat_client/chat_client.cpp b/examples/chat_client/chat_client.cpp index 7223dad92..a2b3952c5 100644 --- a/examples/chat_client/chat_client.cpp +++ b/examples/chat_client/chat_client.cpp @@ -38,41 +38,41 @@ using boost::asio::ip::tcp; using namespace websocketchat; int main(int argc, char* argv[]) { - std::string uri; - - if (argc != 2) { - std::cout << "Usage: `chat_client ws_uri`" << std::endl; - } else { - uri = argv[1]; - } - - chat_client_handler_ptr c(new chat_client_handler()); - - try { - boost::asio::io_service io_service; - - websocketpp::client_ptr client(new websocketpp::client(io_service,c)); - - client->init(); + std::string uri; + + if (argc != 2) { + std::cout << "Usage: `chat_client ws_uri`" << std::endl; + } else { + uri = argv[1]; + } + + chat_client_handler_ptr c(new chat_client_handler()); + + try { + boost::asio::io_service io_service; + + websocketpp::client_ptr client(new websocketpp::client(io_service,c)); + + client->init(); - client->set_header("User Agent","WebSocket++/2011-09-25"); - client->add_subprotocol("com.zaphoyd.websocketpp.chat"); - - client->set_origin("http://zaphoyd.com"); + client->set_header("User Agent","WebSocket++/2011-09-25"); + client->add_subprotocol("com.zaphoyd.websocketpp.chat"); + + client->set_origin("http://zaphoyd.com"); - client->connect(uri); - - boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); - - char line[512]; - while (std::cin.getline(line, 512)) { - c->send(line); - } - - t.join(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + client->connect(uri); + + boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); + + char line[512]; + while (std::cin.getline(line, 512)) { + c->send(line); + } + + t.join(); + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/chat_client/chat_client.html b/examples/chat_client/chat_client.html index 3e7c08ad2..fe1e3584b 100644 --- a/examples/chat_client/chat_client.html +++ b/examples/chat_client/chat_client.html @@ -12,102 +12,102 @@ $(document).ready(init); function init() { - $(document).keypress(function(event) { - if ( event.which == 13 ) { - event.preventDefault(); - send(); - } - }); + $(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 = "
    "; - for (var p in message.value) { - o += "
  • "+message.value[p]+"
  • "; - } - o += "
"; - $("#participants").html(o); - } - }; + 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 = "
    "; + for (var p in message.value) { + o += "
  • "+message.value[p]+"
  • "; + } + o += "
"; + $("#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(""+sender+" "+message+"
"); - $("#messages").prop({ scrollTop: $("#messages").prop("scrollHeight") }); + 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(""+sender+" "+message+"
"); + $("#messages").prop({ scrollTop: $("#messages").prop("scrollHeight") }); } function disconnect() { - ws.close(); - $("#server_url").removeAttr("disabled"); - $("#toggle_connect").html("Connect"); - $("#participants").html(""); + ws.close(); + $("#server_url").removeAttr("disabled"); + $("#toggle_connect").html("Connect"); + $("#participants").html(""); } function toggle_connect() { - if ($("#server_url").attr("disabled") != "disabled") { - connect(); - } else { - disconnect(); - } + 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(""); + if (ws === undefined || ws.readyState != 1) { + chat_message("Websocket is not avaliable for writing"); + return; + } + + ws.send($("#msg").val()); + $("#msg").val(""); } @@ -117,12 +117,12 @@
-
- - -
- -
-
-

Chat Participants

-
+
+ + +
+ +
+
+

Chat Participants

+
diff --git a/examples/chat_client/chat_client_handler.cpp b/examples/chat_client/chat_client_handler.cpp index e16a5f471..8b890a9a1 100644 --- a/examples/chat_client/chat_client_handler.cpp +++ b/examples/chat_client/chat_client_handler.cpp @@ -33,24 +33,24 @@ using websocketchat::chat_client_handler; using websocketpp::client_session_ptr; void chat_client_handler::on_open(session_ptr s) { - // not sure if anything needs to happen here. - m_session = s; + // not sure if anything needs to happen here. + m_session = s; - std::cout << "Successfully connected" << std::endl; + std::cout << "Successfully connected" << std::endl; } void chat_client_handler::on_close(session_ptr s) { - // not sure if anything needs to happen here either. - - m_session = client_session_ptr(); + // not sure if anything needs to happen here either. + + m_session = client_session_ptr(); - std::cout << "client was disconnected" << std::endl; + std::cout << "client was disconnected" << std::endl; } void chat_client_handler::on_message(session_ptr s,const std::string &msg) { - //std::cout << "message from server: " << msg << std::endl; + //std::cout << "message from server: " << msg << std::endl; - decode_server_msg(msg); + decode_server_msg(msg); } // CLIENT API @@ -58,114 +58,114 @@ void chat_client_handler::on_message(session_ptr s,const std::string &msg) { // they need to be careful to not touch unsyncronized member variables. void chat_client_handler::send(const std::string &msg) { - if (!m_session) { - std::cerr << "Error: no connected session" << std::endl; - return; - } - m_session->io_service().post(boost::bind(&chat_client_handler::do_send, this, msg)); + if (!m_session) { + std::cerr << "Error: no connected session" << std::endl; + return; + } + m_session->io_service().post(boost::bind(&chat_client_handler::do_send, this, msg)); } void chat_client_handler::close() { - if (!m_session) { - std::cerr << "Error: no connected session" << std::endl; - return; - } - m_session->io_service().post(boost::bind(&chat_client_handler::do_close,this)); + if (!m_session) { + std::cerr << "Error: no connected session" << std::endl; + return; + } + m_session->io_service().post(boost::bind(&chat_client_handler::do_close,this)); } // END CLIENT API void chat_client_handler::do_send(const std::string &msg) { - if (!m_session) { - std::cerr << "Error: no connected session" << std::endl; - return; - } - - // check for local commands - if (msg == "/list") { - std::cout << "list all participants" << std::endl; - } else if (msg == "/close") { - do_close(); - } else { - m_session->send(msg); - } + if (!m_session) { + std::cerr << "Error: no connected session" << std::endl; + return; + } + + // check for local commands + if (msg == "/list") { + std::cout << "list all participants" << std::endl; + } else if (msg == "/close") { + do_close(); + } else { + m_session->send(msg); + } } void chat_client_handler::do_close() { - if (!m_session) { - std::cerr << "Error: no connected session" << std::endl; - return; - } - m_session->close(websocketpp::session::CLOSE_STATUS_GOING_AWAY,""); + if (!m_session) { + std::cerr << "Error: no connected session" << std::endl; + return; + } + m_session->close(websocketpp::session::CLOSE_STATUS_GOING_AWAY,""); } // {"type":"participants","value":[,...]} // {"type":"msg","sender":"","value":"" } void chat_client_handler::decode_server_msg(const std::string &msg) { - // for messages of type participants, erase and rebuild m_participants - // for messages of type msg, print out message - - // NOTE: The chat server was written with the intention of the client having a built in - // JSON parser. To keep external dependencies low for this demonstration chat client I am - // parsing the server messages by hand. - - std::string::size_type start = 9; - std::string::size_type end; - - if (msg.substr(0,start) != "{\"type\":\"") { - // ignore - std::cout << "invalid message" << std::endl; - return; - } - - - - if (msg.substr(start,15) == "msg\",\"sender\":\"") { - // parse message - std::string sender; - std::string message; - - start += 15; - - end = msg.find("\"",start); - while (end != std::string::npos) { - if (msg[end-1] == '\\') { - sender += msg.substr(start,end-start-1) + "\""; - start = end+1; - end = msg.find("\"",start); - } else { - sender += msg.substr(start,end-start); - start = end; - break; - } - } - - if (msg.substr(start,11) != "\",\"value\":\"") { - std::cout << "invalid message" << std::endl; - return; - } - - start += 11; - - end = msg.find("\"",start); - while (end != std::string::npos) { - if (msg[end-1] == '\\') { - message += msg.substr(start,end-start-1) + "\""; - start = end+1; - end = msg.find("\"",start); - } else { - message += msg.substr(start,end-start); - start = end; - break; - } - } - - std::cout << "[" << sender << "] " << message << std::endl; - } else if (msg.substr(start,23) == "participants\",\"value\":[") { - // parse participants - std::cout << "participants message" << std::endl; - } else { - // unknown message type - std::cout << "unknown message" << std::endl; - } + // for messages of type participants, erase and rebuild m_participants + // for messages of type msg, print out message + + // NOTE: The chat server was written with the intention of the client having a built in + // JSON parser. To keep external dependencies low for this demonstration chat client I am + // parsing the server messages by hand. + + std::string::size_type start = 9; + std::string::size_type end; + + if (msg.substr(0,start) != "{\"type\":\"") { + // ignore + std::cout << "invalid message" << std::endl; + return; + } + + + + if (msg.substr(start,15) == "msg\",\"sender\":\"") { + // parse message + std::string sender; + std::string message; + + start += 15; + + end = msg.find("\"",start); + while (end != std::string::npos) { + if (msg[end-1] == '\\') { + sender += msg.substr(start,end-start-1) + "\""; + start = end+1; + end = msg.find("\"",start); + } else { + sender += msg.substr(start,end-start); + start = end; + break; + } + } + + if (msg.substr(start,11) != "\",\"value\":\"") { + std::cout << "invalid message" << std::endl; + return; + } + + start += 11; + + end = msg.find("\"",start); + while (end != std::string::npos) { + if (msg[end-1] == '\\') { + message += msg.substr(start,end-start-1) + "\""; + start = end+1; + end = msg.find("\"",start); + } else { + message += msg.substr(start,end-start); + start = end; + break; + } + } + + std::cout << "[" << sender << "] " << message << std::endl; + } else if (msg.substr(start,23) == "participants\",\"value\":[") { + // parse participants + std::cout << "participants message" << std::endl; + } else { + // unknown message type + std::cout << "unknown message" << std::endl; + } } diff --git a/examples/chat_client/chat_client_handler.hpp b/examples/chat_client/chat_client_handler.hpp index 0b1f0e067..e9e966afe 100644 --- a/examples/chat_client/chat_client_handler.hpp +++ b/examples/chat_client/chat_client_handler.hpp @@ -53,39 +53,39 @@ namespace websocketchat { class chat_client_handler : public websocketpp::connection_handler { public: - chat_client_handler() {} - virtual ~chat_client_handler() {} - - // ignored for clients? - void validate(session_ptr s) {} - - // connection to chat room complete - void on_open(session_ptr s); + chat_client_handler() {} + virtual ~chat_client_handler() {} + + // ignored for clients? + void validate(session_ptr s) {} + + // connection to chat room complete + void on_open(session_ptr s); - // connection to chat room closed - void on_close(session_ptr s); - - // got a new message from server - void on_message(session_ptr s,const std::string &msg); - - // ignore messages - void on_message(session_ptr s,const std::vector &data) {} - - // CLIENT API - void send(const std::string &msg); - void close(); + // connection to chat room closed + void on_close(session_ptr s); + + // got a new message from server + void on_message(session_ptr s,const std::string &msg); + + // ignore messages + void on_message(session_ptr s,const std::vector &data) {} + + // CLIENT API + void send(const std::string &msg); + void close(); private: - // Client API internal - void do_send(const std::string &msg); - void do_close(); + // Client API internal + void do_send(const std::string &msg); + void do_close(); - void decode_server_msg(const std::string &msg); - - // list of other chat participants - std::set m_participants; - std::queue m_msg_queue; - session_ptr m_session; + void decode_server_msg(const std::string &msg); + + // list of other chat participants + std::set m_participants; + std::queue m_msg_queue; + session_ptr m_session; }; typedef boost::shared_ptr chat_client_handler_ptr; diff --git a/examples/chat_server/chat.cpp b/examples/chat_server/chat.cpp index 52d3e72eb..fdc9c78f2 100644 --- a/examples/chat_server/chat.cpp +++ b/examples/chat_server/chat.cpp @@ -34,160 +34,160 @@ using websocketpp::session::server_session_ptr; void chat_server_handler::validate(server_session_ptr session) { - std::stringstream err; - - // We only know about the chat resource - if (session->get_resource() != "/chat") { - err << "Request for unknown resource " << session->get_resource(); - throw(websocketpp::http::exception(err.str(),websocketpp::http::status_code::NOT_FOUND)); - } - - // Require specific origin example - if (session->get_origin() != "http://zaphoyd.com") { - err << "Request from unrecognized origin: " << session->get_origin(); - throw(websocketpp::http::exception(err.str(),websocketpp::http::status_code::FORBIDDEN)); - } + std::stringstream err; + + // We only know about the chat resource + if (session->get_resource() != "/chat") { + err << "Request for unknown resource " << session->get_resource(); + throw(websocketpp::http::exception(err.str(),websocketpp::http::status_code::NOT_FOUND)); + } + + // Require specific origin example + if (session->get_origin() != "http://zaphoyd.com") { + err << "Request from unrecognized origin: " << session->get_origin(); + throw(websocketpp::http::exception(err.str(),websocketpp::http::status_code::FORBIDDEN)); + } } void chat_server_handler::on_open(server_session_ptr session) { - std::cout << "client " << session << " joined the lobby." << std::endl; - m_connections.insert(std::pair(session,get_con_id(session))); + std::cout << "client " << session << " joined the lobby." << std::endl; + m_connections.insert(std::pair(session,get_con_id(session))); - // send user list and signon message to all clients - send_to_all(serialize_state()); - session->send(encode_message("server","Welcome, use the /alias command to set a name, /help for a list of other commands.")); - send_to_all(encode_message("server",m_connections[session]+" has joined the chat.")); + // send user list and signon message to all clients + send_to_all(serialize_state()); + session->send(encode_message("server","Welcome, use the /alias command to set a name, /help for a list of other commands.")); + send_to_all(encode_message("server",m_connections[session]+" has joined the chat.")); } void chat_server_handler::on_close(server_session_ptr session) { - std::map::iterator it = m_connections.find(session); - - if (it == m_connections.end()) { - // this client has already disconnected, we can ignore this. - // this happens during certain types of disconnect where there is a - // deliberate "soft" disconnection preceeding the "hard" socket read - // fail or disconnect ack message. - return; - } - - std::cout << "client " << session << " left the lobby." << std::endl; - - const std::string alias = it->second; - m_connections.erase(it); - - // send user list and signoff message to all clients - send_to_all(serialize_state()); - send_to_all(encode_message("server",alias+" has left the chat.")); + std::map::iterator it = m_connections.find(session); + + if (it == m_connections.end()) { + // this client has already disconnected, we can ignore this. + // this happens during certain types of disconnect where there is a + // deliberate "soft" disconnection preceeding the "hard" socket read + // fail or disconnect ack message. + return; + } + + std::cout << "client " << session << " left the lobby." << std::endl; + + const std::string alias = it->second; + m_connections.erase(it); + + // send user list and signoff message to all clients + send_to_all(serialize_state()); + send_to_all(encode_message("server",alias+" has left the chat.")); } void chat_server_handler::on_message(server_session_ptr session,websocketpp::utf8_string_ptr msg) { - std::cout << "message from client " << session << ": " << *msg << std::endl; - - - - // check for special command messages - if (*msg == "/help") { - // print command list - session->send(encode_message("server","avaliable commands:
    /help - show this help
    /alias foo - set alias to foo",false)); - return; - } - - if (msg->substr(0,7) == "/alias ") { - std::string response; - std::string alias; - - if (msg->size() == 7) { - response = "You must enter an alias."; - session->send(encode_message("server",response)); - return; - } else { - alias = msg->substr(7); - } - - response = m_connections[session] + " is now known as "+alias; - - // store alias pre-escaped so we don't have to do this replacing every time this - // user sends a message - - // escape JSON characters - boost::algorithm::replace_all(alias,"\\","\\\\"); - boost::algorithm::replace_all(alias,"\"","\\\""); - - // escape HTML characters - boost::algorithm::replace_all(alias,"&","&"); - boost::algorithm::replace_all(alias,"<","<"); - boost::algorithm::replace_all(alias,">",">"); - - m_connections[session] = alias; - - // set alias - send_to_all(serialize_state()); - send_to_all(encode_message("server",response)); - return; - } - - // catch other slash commands - if ((*msg)[0] == '/') { - session->send(encode_message("server","unrecognized command")); - return; - } - - // create JSON message to send based on msg - send_to_all(encode_message(m_connections[session],*msg)); + std::cout << "message from client " << session << ": " << *msg << std::endl; + + + + // check for special command messages + if (*msg == "/help") { + // print command list + session->send(encode_message("server","avaliable commands:
    /help - show this help
    /alias foo - set alias to foo",false)); + return; + } + + if (msg->substr(0,7) == "/alias ") { + std::string response; + std::string alias; + + if (msg->size() == 7) { + response = "You must enter an alias."; + session->send(encode_message("server",response)); + return; + } else { + alias = msg->substr(7); + } + + response = m_connections[session] + " is now known as "+alias; + + // store alias pre-escaped so we don't have to do this replacing every time this + // user sends a message + + // escape JSON characters + boost::algorithm::replace_all(alias,"\\","\\\\"); + boost::algorithm::replace_all(alias,"\"","\\\""); + + // escape HTML characters + boost::algorithm::replace_all(alias,"&","&"); + boost::algorithm::replace_all(alias,"<","<"); + boost::algorithm::replace_all(alias,">",">"); + + m_connections[session] = alias; + + // set alias + send_to_all(serialize_state()); + send_to_all(encode_message("server",response)); + return; + } + + // catch other slash commands + if ((*msg)[0] == '/') { + session->send(encode_message("server","unrecognized command")); + return; + } + + // create JSON message to send based on msg + send_to_all(encode_message(m_connections[session],*msg)); } // {"type":"participants","value":[,...]} std::string chat_server_handler::serialize_state() { - std::stringstream s; - - s << "{\"type\":\"participants\",\"value\":["; - - std::map::iterator it; - - for (it = m_connections.begin(); it != m_connections.end(); it++) { - s << "\"" << (*it).second << "\""; - if (++it != m_connections.end()) { - s << ","; - } - it--; - } - - s << "]}"; - - return s.str(); + std::stringstream s; + + s << "{\"type\":\"participants\",\"value\":["; + + std::map::iterator it; + + for (it = m_connections.begin(); it != m_connections.end(); it++) { + s << "\"" << (*it).second << "\""; + if (++it != m_connections.end()) { + s << ","; + } + it--; + } + + s << "]}"; + + return s.str(); } // {"type":"msg","sender":"","value":"" } std::string chat_server_handler::encode_message(std::string sender,std::string msg,bool escape) { - std::stringstream s; - - // escape JSON characters - boost::algorithm::replace_all(msg,"\\","\\\\"); - boost::algorithm::replace_all(msg,"\"","\\\""); - - // escape HTML characters - if (escape) { - boost::algorithm::replace_all(msg,"&","&"); - boost::algorithm::replace_all(msg,"<","<"); - boost::algorithm::replace_all(msg,">",">"); - } - - s << "{\"type\":\"msg\",\"sender\":\"" << sender - << "\",\"value\":\"" << msg << "\"}"; - - return s.str(); + std::stringstream s; + + // escape JSON characters + boost::algorithm::replace_all(msg,"\\","\\\\"); + boost::algorithm::replace_all(msg,"\"","\\\""); + + // escape HTML characters + if (escape) { + boost::algorithm::replace_all(msg,"&","&"); + boost::algorithm::replace_all(msg,"<","<"); + boost::algorithm::replace_all(msg,">",">"); + } + + s << "{\"type\":\"msg\",\"sender\":\"" << sender + << "\",\"value\":\"" << msg << "\"}"; + + return s.str(); } std::string chat_server_handler::get_con_id(server_session_ptr s) { - std::stringstream endpoint; - endpoint << s->get_endpoint(); - return endpoint.str(); + std::stringstream endpoint; + endpoint << s->get_endpoint(); + return endpoint.str(); } void chat_server_handler::send_to_all(std::string data) { - std::map::iterator it; - for (it = m_connections.begin(); it != m_connections.end(); it++) { - (*it).first->send(data); - } + std::map::iterator it; + for (it = m_connections.begin(); it != m_connections.end(); it++) { + (*it).first->send(data); + } } diff --git a/examples/chat_server/chat.hpp b/examples/chat_server/chat.hpp index 7c32020d4..7d6571feb 100644 --- a/examples/chat_server/chat.hpp +++ b/examples/chat_server/chat.hpp @@ -53,27 +53,27 @@ namespace websocketchat { class chat_server_handler : public server_handler { public: - void validate(server_session_ptr session); - - // add new connection to the lobby - void on_open(server_session_ptr session); - - // someone disconnected from the lobby, remove them - void on_close(server_session_ptr session); - - void on_message(server_session_ptr session,websocketpp::utf8_string_ptr msg); - - // lobby will ignore binary messages - void on_message(server_session_ptr session,websocketpp::binary_string_ptr data) {} + void validate(server_session_ptr session); + + // add new connection to the lobby + void on_open(server_session_ptr session); + + // someone disconnected from the lobby, remove them + void on_close(server_session_ptr session); + + void on_message(server_session_ptr session,websocketpp::utf8_string_ptr msg); + + // lobby will ignore binary messages + void on_message(server_session_ptr session,websocketpp::binary_string_ptr data) {} private: - std::string serialize_state(); - std::string encode_message(std::string sender,std::string msg,bool escape = true); - std::string get_con_id(server_session_ptr s); - - void send_to_all(std::string data); - - // list of outstanding connections - std::map m_connections; + std::string serialize_state(); + std::string encode_message(std::string sender,std::string msg,bool escape = true); + std::string get_con_id(server_session_ptr s); + + void send_to_all(std::string data); + + // list of outstanding connections + std::map m_connections; }; typedef boost::shared_ptr chat_server_handler_ptr; diff --git a/examples/chat_server/chat_server.cpp b/examples/chat_server/chat_server.cpp index 474197bda..a2409b4f8 100644 --- a/examples/chat_server/chat_server.cpp +++ b/examples/chat_server/chat_server.cpp @@ -36,36 +36,36 @@ using boost::asio::ip::tcp; using namespace websocketchat; int main(int argc, char* argv[]) { - short port = 9003; - - if (argc == 2) { - // TODO: input validation? - port = atoi(argv[2]); - } - - try { - // create an instance of our handler - server_handler_ptr default_handler(new chat_server_handler()); - - // create a server that listens on port `port` and uses our handler - websocketpp::basic_server_ptr server(new websocketpp::basic_server(port,default_handler)); - - server->elog().set_levels(websocketpp::log::elevel::DEVEL,websocketpp::log::elevel::FATAL); - - server->alog().set_level(websocketpp::log::alevel::ALL); - - // setup server settings - // Chat server should only be receiving small text messages, reduce max - // message size limit slightly to save memory, improve performance, and - // guard against DoS attacks. - //server->set_max_message_size(0xFFFF); // 64KiB - - std::cout << "Starting chat server on port " << port << std::endl; - - server->run(); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + short port = 9003; + + if (argc == 2) { + // TODO: input validation? + port = atoi(argv[2]); + } + + try { + // create an instance of our handler + server_handler_ptr default_handler(new chat_server_handler()); + + // create a server that listens on port `port` and uses our handler + websocketpp::basic_server_ptr server(new websocketpp::basic_server(port,default_handler)); + + server->elog().set_levels(websocketpp::log::elevel::DEVEL,websocketpp::log::elevel::FATAL); + + server->alog().set_level(websocketpp::log::alevel::ALL); + + // setup server settings + // Chat server should only be receiving small text messages, reduce max + // message size limit slightly to save memory, improve performance, and + // guard against DoS attacks. + //server->set_max_message_size(0xFFFF); // 64KiB + + std::cout << "Starting chat server on port " << port << std::endl; + + server->run(); + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/echo_client/echo_client.cpp b/examples/echo_client/echo_client.cpp index a9aad7302..84f5ecf97 100644 --- a/examples/echo_client/echo_client.cpp +++ b/examples/echo_client/echo_client.cpp @@ -36,72 +36,72 @@ typedef plain_endpoint_type::connection_ptr connection_ptr; class echo_client_handler : public plain_endpoint_type::handler { public: - typedef echo_client_handler type; - typedef plain_endpoint_type::connection_ptr connection_ptr; - - void on_message(connection_ptr connection,websocketpp::message::data::ptr msg) { - if (connection->get_resource() == "/getCaseCount") { - std::cout << "Detected " << msg->get_payload() << " test cases." << std::endl; - m_case_count = atoi(msg->get_payload().c_str()); - } else { - connection->send(msg->get_payload(),msg->get_opcode()); - } - } - - void http(connection_ptr connection) { - //connection->set_body("HTTP Response!!"); - } - - void on_fail(connection_ptr connection) { - std::cout << "connection failed" << std::endl; - } - - int m_case_count; + typedef echo_client_handler type; + typedef plain_endpoint_type::connection_ptr connection_ptr; + + void on_message(connection_ptr connection,websocketpp::message::data::ptr msg) { + if (connection->get_resource() == "/getCaseCount") { + std::cout << "Detected " << msg->get_payload() << " test cases." << std::endl; + m_case_count = atoi(msg->get_payload().c_str()); + } else { + connection->send(msg->get_payload(),msg->get_opcode()); + } + } + + void http(connection_ptr connection) { + //connection->set_body("HTTP Response!!"); + } + + void on_fail(connection_ptr connection) { + std::cout << "connection failed" << std::endl; + } + + int m_case_count; }; int main(int argc, char* argv[]) { - std::string uri = "ws://localhost:9001/"; - - if (argc > 2) { - std::cout << "Usage: `echo_client test_url`" << std::endl; - } else { - uri = argv[1]; - } - - try { - plain_handler_ptr handler(new echo_client_handler()); + std::string uri = "ws://localhost:9001/"; + + if (argc > 2) { + std::cout << "Usage: `echo_client test_url`" << std::endl; + } else { + uri = argv[1]; + } + + try { + plain_handler_ptr handler(new echo_client_handler()); connection_ptr connection; - plain_endpoint_type endpoint(handler); - - endpoint.alog().unset_level(websocketpp::log::alevel::ALL); - endpoint.elog().unset_level(websocketpp::log::elevel::ALL); - - connection = endpoint.connect(uri+"getCaseCount"); - + plain_endpoint_type endpoint(handler); + + endpoint.alog().unset_level(websocketpp::log::alevel::ALL); + endpoint.elog().unset_level(websocketpp::log::elevel::ALL); + + connection = endpoint.connect(uri+"getCaseCount"); + connection->add_request_header("User Agent","WebSocket++/0.2.0"); endpoint.run(); - - std::cout << "case count: " << boost::dynamic_pointer_cast(handler)->m_case_count << std::endl; - - for (int i = 1; i <= boost::dynamic_pointer_cast(handler)->m_case_count; i++) { - endpoint.reset(); - - std::stringstream url; - - url << uri << "/runCase?case=" << i << "&agent=\"WebSocket++/0.2.0\""; - + + std::cout << "case count: " << boost::dynamic_pointer_cast(handler)->m_case_count << std::endl; + + for (int i = 1; i <= boost::dynamic_pointer_cast(handler)->m_case_count; i++) { + endpoint.reset(); + + std::stringstream url; + + url << uri << "/runCase?case=" << i << "&agent=\"WebSocket++/0.2.0\""; + connection = endpoint.connect(url.str()); - - endpoint.run(); - } - - std::cout << "done" << std::endl; - - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + + endpoint.run(); + } + + std::cout << "done" << std::endl; + + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/echo_client/echo_client_handler.cpp b/examples/echo_client/echo_client_handler.cpp index b91b4d69f..4b0055cee 100644 --- a/examples/echo_client/echo_client_handler.cpp +++ b/examples/echo_client/echo_client_handler.cpp @@ -34,23 +34,23 @@ using websocketecho::echo_client_handler; using websocketpp::client_session_ptr; void echo_client_handler::on_open(session_ptr s) { - std::cout << " Successfully connected (handshake complete): " << s->get_resource() << std::endl; + std::cout << " Successfully connected (handshake complete): " << s->get_resource() << std::endl; } void echo_client_handler::on_close(session_ptr s) { - std::cout << " client was disconnected (WS state is now CLOSED)" << std::endl; + std::cout << " client was disconnected (WS state is now CLOSED)" << std::endl; } void echo_client_handler::on_message(session_ptr s,const std::string &msg) { - if (s->get_resource() == "/getCaseCount") { - std::cout << "Detected " << msg << " test cases." << std::endl; - m_case_count = atoi(msg.c_str()); - } else { - s->send(msg); - } + if (s->get_resource() == "/getCaseCount") { + std::cout << "Detected " << msg << " test cases." << std::endl; + m_case_count = atoi(msg.c_str()); + } else { + s->send(msg); + } } void echo_client_handler::on_message(session_ptr s, - const std::vector &data) { - s->send(data); + const std::vector &data) { + s->send(data); } \ No newline at end of file diff --git a/examples/echo_client/echo_client_handler.hpp b/examples/echo_client/echo_client_handler.hpp index 5610e08c3..05425f2b5 100644 --- a/examples/echo_client/echo_client_handler.hpp +++ b/examples/echo_client/echo_client_handler.hpp @@ -51,22 +51,22 @@ namespace websocketecho { class echo_client_handler : public websocketpp::connection_handler { public: - echo_client_handler() : m_case_count(0) {} - virtual ~echo_client_handler() {} - - // connection to chat room complete - void on_open(session_ptr s); + echo_client_handler() : m_case_count(0) {} + virtual ~echo_client_handler() {} + + // connection to chat room complete + void on_open(session_ptr s); - // connection to chat room closed - void on_close(session_ptr sn); - - // got a new message from server - void on_message(session_ptr s,const std::string &msg); - - // ignore messages - void on_message(session_ptr s,const std::vector &data); - - int m_case_count; + // connection to chat room closed + void on_close(session_ptr sn); + + // got a new message from server + void on_message(session_ptr s,const std::string &msg); + + // ignore messages + void on_message(session_ptr s,const std::vector &data); + + int m_case_count; }; typedef boost::shared_ptr echo_client_handler_ptr; diff --git a/examples/echo_server/echo.hpp b/examples/echo_server/echo.hpp index 48e8948d6..a6aac7a37 100644 --- a/examples/echo_server/echo.hpp +++ b/examples/echo_server/echo.hpp @@ -42,23 +42,23 @@ namespace websocketecho { class echo_server_handler : public server_handler { public: - // The echo server allows all domains is protocol free. - void validate(server_ptr session) {} - - // an echo server is stateless. - // The handler has no need to keep track of connected clients. - void on_fail(server_ptr session) {} - void on_open(server_ptr session) {} - void on_close(server_ptr session) {} - - // both text and binary messages are echoed back to the sending client. - void on_message(server_ptr session,websocketpp::utf8_string_ptr msg) { - std::cout << *msg << std::endl; - session->send(*msg); - } - void on_message(server_ptr session,websocketpp::binary_string_ptr data) { - session->send(*data); - } + // The echo server allows all domains is protocol free. + void validate(server_ptr session) {} + + // an echo server is stateless. + // The handler has no need to keep track of connected clients. + void on_fail(server_ptr session) {} + void on_open(server_ptr session) {} + void on_close(server_ptr session) {} + + // both text and binary messages are echoed back to the sending client. + void on_message(server_ptr session,websocketpp::utf8_string_ptr msg) { + std::cout << *msg << std::endl; + session->send(*msg); + } + void on_message(server_ptr session,websocketpp::binary_string_ptr data) { + session->send(*data); + } }; } diff --git a/examples/echo_server/echo_client.html b/examples/echo_server/echo_client.html index cd46a17a7..dc36396a2 100644 --- a/examples/echo_server/echo_client.html +++ b/examples/echo_server/echo_client.html @@ -9,84 +9,84 @@ var url; function connect() { - url = document.getElementById("server_url").value; - console.log(url); - - if ("WebSocket" in window) { - ws = new WebSocket(url); - } else if ("MozWebSocket" in window) { - ws = new MozWebSocket(url); - } else { - document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; - return; - } - ws.onopen = function(e) { - document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; - - document.getElementById("server_url").disabled = true; - document.getElementById("toggle_connect").innerHTML = "Disconnect"; - }; - - ws.onerror = function(e) { - document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; - console.log(e); - }; - - ws.onclose = function(e) { - document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; - }; - - ws.onmessage = function(e) { - document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; - }; + url = document.getElementById("server_url").value; + console.log(url); + + if ("WebSocket" in window) { + ws = new WebSocket(url); + } else if ("MozWebSocket" in window) { + ws = new MozWebSocket(url); + } else { + document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; + return; + } + ws.onopen = function(e) { + document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; + + document.getElementById("server_url").disabled = true; + document.getElementById("toggle_connect").innerHTML = "Disconnect"; + }; + + ws.onerror = function(e) { + document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; + console.log(e); + }; + + ws.onclose = function(e) { + document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; + }; + + ws.onmessage = function(e) { + document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; + }; } function disconnect() { - ws.close(); - document.getElementById("server_url").disabled = false; - document.getElementById("toggle_connect").innerHTML = "Connect"; + ws.close(); + document.getElementById("server_url").disabled = false; + document.getElementById("toggle_connect").innerHTML = "Connect"; } function toggle_connect() { - if (document.getElementById("server_url").disabled === false) { - connect(); - } else { - disconnect(); - } + if (document.getElementById("server_url").disabled === false) { + connect(); + } else { + disconnect(); + } } function send() { - if (ws === undefined || ws.readyState != 1) { - document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; - return; - } - - ws.send(document.getElementById("msg").value); - document.getElementById("msg").value = ""; + if (ws === undefined || ws.readyState != 1) { + document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; + return; + } + + ws.send(document.getElementById("msg").value); + document.getElementById("msg").value = ""; }
-
- - -
+
+ + +
-
-
+
+
diff --git a/examples/echo_server/echo_server.cpp b/examples/echo_server/echo_server.cpp index 779a11340..4da19ce3c 100644 --- a/examples/echo_server/echo_server.cpp +++ b/examples/echo_server/echo_server.cpp @@ -35,37 +35,37 @@ typedef endpoint_type::handler_ptr handler_ptr; class echo_server_handler : public endpoint_type::handler { public: - typedef endpoint_type::connection_ptr connection_ptr; - - void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { - connection->send(msg->get_payload(),msg->get_opcode()); - } + typedef endpoint_type::connection_ptr connection_ptr; + + void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { + connection->send(msg->get_payload(),msg->get_opcode()); + } }; int main(int argc, char* argv[]) { - unsigned short port = 9002; - - if (argc == 2) { - port = atoi(argv[1]); + unsigned short port = 9002; + + if (argc == 2) { + port = atoi(argv[1]); if (port == 0) { std::cout << "Unable to parse port input " << argv[1] << std::endl; return 1; } - } - - try { - handler_ptr h(new echo_server_handler()); - endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - e.elog().unset_level(websocketpp::log::elevel::ALL); - - std::cout << "Starting WebSocket echo server on port " << port << std::endl; - e.listen(port); - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + } + + try { + handler_ptr h(new echo_server_handler()); + endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + e.elog().unset_level(websocketpp::log::elevel::ALL); + + std::cout << "Starting WebSocket echo server on port " << port << std::endl; + e.listen(port); + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/echo_server_tls/echo.hpp b/examples/echo_server_tls/echo.hpp index 48e8948d6..a6aac7a37 100644 --- a/examples/echo_server_tls/echo.hpp +++ b/examples/echo_server_tls/echo.hpp @@ -42,23 +42,23 @@ namespace websocketecho { class echo_server_handler : public server_handler { public: - // The echo server allows all domains is protocol free. - void validate(server_ptr session) {} - - // an echo server is stateless. - // The handler has no need to keep track of connected clients. - void on_fail(server_ptr session) {} - void on_open(server_ptr session) {} - void on_close(server_ptr session) {} - - // both text and binary messages are echoed back to the sending client. - void on_message(server_ptr session,websocketpp::utf8_string_ptr msg) { - std::cout << *msg << std::endl; - session->send(*msg); - } - void on_message(server_ptr session,websocketpp::binary_string_ptr data) { - session->send(*data); - } + // The echo server allows all domains is protocol free. + void validate(server_ptr session) {} + + // an echo server is stateless. + // The handler has no need to keep track of connected clients. + void on_fail(server_ptr session) {} + void on_open(server_ptr session) {} + void on_close(server_ptr session) {} + + // both text and binary messages are echoed back to the sending client. + void on_message(server_ptr session,websocketpp::utf8_string_ptr msg) { + std::cout << *msg << std::endl; + session->send(*msg); + } + void on_message(server_ptr session,websocketpp::binary_string_ptr data) { + session->send(*data); + } }; } diff --git a/examples/echo_server_tls/echo_client.html b/examples/echo_server_tls/echo_client.html index cd46a17a7..dc36396a2 100644 --- a/examples/echo_server_tls/echo_client.html +++ b/examples/echo_server_tls/echo_client.html @@ -9,84 +9,84 @@ var url; function connect() { - url = document.getElementById("server_url").value; - console.log(url); - - if ("WebSocket" in window) { - ws = new WebSocket(url); - } else if ("MozWebSocket" in window) { - ws = new MozWebSocket(url); - } else { - document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; - return; - } - ws.onopen = function(e) { - document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; - - document.getElementById("server_url").disabled = true; - document.getElementById("toggle_connect").innerHTML = "Disconnect"; - }; - - ws.onerror = function(e) { - document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; - console.log(e); - }; - - ws.onclose = function(e) { - document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; - }; - - ws.onmessage = function(e) { - document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; - }; + url = document.getElementById("server_url").value; + console.log(url); + + if ("WebSocket" in window) { + ws = new WebSocket(url); + } else if ("MozWebSocket" in window) { + ws = new MozWebSocket(url); + } else { + document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; + return; + } + ws.onopen = function(e) { + document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; + + document.getElementById("server_url").disabled = true; + document.getElementById("toggle_connect").innerHTML = "Disconnect"; + }; + + ws.onerror = function(e) { + document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; + console.log(e); + }; + + ws.onclose = function(e) { + document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; + }; + + ws.onmessage = function(e) { + document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; + }; } function disconnect() { - ws.close(); - document.getElementById("server_url").disabled = false; - document.getElementById("toggle_connect").innerHTML = "Connect"; + ws.close(); + document.getElementById("server_url").disabled = false; + document.getElementById("toggle_connect").innerHTML = "Connect"; } function toggle_connect() { - if (document.getElementById("server_url").disabled === false) { - connect(); - } else { - disconnect(); - } + if (document.getElementById("server_url").disabled === false) { + connect(); + } else { + disconnect(); + } } function send() { - if (ws === undefined || ws.readyState != 1) { - document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; - return; - } - - ws.send(document.getElementById("msg").value); - document.getElementById("msg").value = ""; + if (ws === undefined || ws.readyState != 1) { + document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; + return; + } + + ws.send(document.getElementById("msg").value); + document.getElementById("msg").value = ""; }
-
- - -
+
+ + +
-
-
+
+
diff --git a/examples/echo_server_tls/echo_server_tls.cpp b/examples/echo_server_tls/echo_server_tls.cpp index 9d87014af..0001d643a 100644 --- a/examples/echo_server_tls/echo_server_tls.cpp +++ b/examples/echo_server_tls/echo_server_tls.cpp @@ -39,83 +39,83 @@ typedef tls_endpoint_type::handler_ptr tls_handler_ptr; template class echo_server_handler : public endpoint_type::handler { public: - typedef echo_server_handler type; - typedef typename endpoint_type::connection_ptr connection_ptr; - - std::string get_password() const { - return "test"; - } - - boost::shared_ptr on_tls_init() { - // create a tls context, init, and return. - boost::shared_ptr context(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1)); - try { - context->set_options(boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::single_dh_use); - context->set_password_callback(boost::bind(&type::get_password, this)); - context->use_certificate_chain_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/server.pem"); - context->use_private_key_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/server.pem", boost::asio::ssl::context::pem); - context->use_tmp_dh_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/dh512.pem"); - } catch (std::exception& e) { - std::cout << e.what() << std::endl; - } - return context; - } - - void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { - connection->send(msg->get_payload(),msg->get_opcode()); - } - - void http(connection_ptr connection) { - connection->set_body("HTTP Response!!"); - } + typedef echo_server_handler type; + typedef typename endpoint_type::connection_ptr connection_ptr; + + std::string get_password() const { + return "test"; + } + + boost::shared_ptr on_tls_init() { + // create a tls context, init, and return. + boost::shared_ptr context(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1)); + try { + context->set_options(boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use); + context->set_password_callback(boost::bind(&type::get_password, this)); + context->use_certificate_chain_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/server.pem"); + context->use_private_key_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/server.pem", boost::asio::ssl::context::pem); + context->use_tmp_dh_file("/Users/zaphoyd/Documents/ZS/websocketpp/src/ssl/dh512.pem"); + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } + return context; + } + + void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { + connection->send(msg->get_payload(),msg->get_opcode()); + } + + void http(connection_ptr connection) { + connection->set_body("HTTP Response!!"); + } }; int main(int argc, char* argv[]) { - unsigned short port = 9002; - bool tls = false; - - if (argc >= 2) { - port = atoi(argv[1]); + unsigned short port = 9002; + bool tls = false; + + if (argc >= 2) { + port = atoi(argv[1]); if (port == 0) { std::cout << "Unable to parse port input " << argv[1] << std::endl; return 1; } - } - - if (argc == 3) { - tls = !strcmp(argv[2],"-tls"); - } - - try { - if (tls) { - tls_handler_ptr h(new echo_server_handler()); - tls_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - e.elog().unset_level(websocketpp::log::elevel::ALL); - - std::cout << "Starting Secure WebSocket echo server on port " + } + + if (argc == 3) { + tls = !strcmp(argv[2],"-tls"); + } + + try { + if (tls) { + tls_handler_ptr h(new echo_server_handler()); + tls_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + e.elog().unset_level(websocketpp::log::elevel::ALL); + + std::cout << "Starting Secure WebSocket echo server on port " << port << std::endl; - e.listen(port); - } else { - plain_handler_ptr h(new echo_server_handler()); - plain_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - e.elog().unset_level(websocketpp::log::elevel::ALL); - - std::cout << "Starting WebSocket echo server on port " + e.listen(port); + } else { + plain_handler_ptr h(new echo_server_handler()); + plain_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + e.elog().unset_level(websocketpp::log::elevel::ALL); + + std::cout << "Starting WebSocket echo server on port " << port << std::endl; - e.listen(port); - } - - - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + e.listen(port); + } + + + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/fuzzing_client/fuzzing_client.cpp b/examples/fuzzing_client/fuzzing_client.cpp index 407424cd3..f44821a56 100644 --- a/examples/fuzzing_client/fuzzing_client.cpp +++ b/examples/fuzzing_client/fuzzing_client.cpp @@ -37,229 +37,229 @@ typedef plain_endpoint_type::connection_ptr connection_ptr; // base test case handler class test_case_handler : public plain_endpoint_type::handler { public: - typedef test_case_handler type; - typedef plain_endpoint_type::connection_ptr connection_ptr; - - virtual void end(connection_ptr connection) { - // test is over, give control back to controlling handler - boost::posix_time::time_period len(m_start_time,m_end_time); - - if (m_pass) { - std::cout << " passes in " << len.length() << std::endl; - } else { - std::cout << " fails in " << len.length() << std::endl; - } - - connection->close(websocketpp::close::status::NORMAL,""); - } + typedef test_case_handler type; + typedef plain_endpoint_type::connection_ptr connection_ptr; + + virtual void end(connection_ptr connection) { + // test is over, give control back to controlling handler + boost::posix_time::time_period len(m_start_time,m_end_time); + + if (m_pass) { + std::cout << " passes in " << len.length() << std::endl; + } else { + std::cout << " fails in " << len.length() << std::endl; + } + + connection->close(websocketpp::close::status::NORMAL,""); + } protected: - bool m_pass; - boost::posix_time::ptime m_start_time; - boost::posix_time::ptime m_end_time; + bool m_pass; + boost::posix_time::ptime m_start_time; + boost::posix_time::ptime m_end_time; }; // test class for 9.1.* and 9.2.* class test_9_1_X : public test_case_handler { -public: - test_9_1_X(int minor, int subtest) : m_minor(minor),m_subtest(subtest){ - // needs more C++11 intializer lists =( - m_test_sizes[0] = 65536; - m_test_sizes[1] = 262144; - m_test_sizes[2] = 1048576; - m_test_sizes[3] = 4194304; - m_test_sizes[4] = 8388608; - m_test_sizes[5] = 16777216; - } - - void on_open(connection_ptr connection) { - std::cout << "Test 9." << m_minor << "." << m_subtest; - - - - m_data.reserve(m_test_sizes[m_subtest-1]); - - if (m_minor == 1) { - fill_utf8(connection,true); - m_start_time = boost::posix_time::microsec_clock::local_time(); - connection->send(m_data,false); - } else if (m_minor == 2) { - fill_binary(connection,true); - m_start_time = boost::posix_time::microsec_clock::local_time(); - connection->send(m_data,true); - } else { - std::cout << " has unknown definition." << std::endl; - } - } - - // Just does random ascii right now. True random UTF8 with multi-byte stuff - // would probably be better - void fill_utf8(connection_ptr connection,bool random = true) { - if (random) { - uint32_t data; - for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { - if (i%4 == 0) { - data = uint32_t(connection->rand()); - } - - m_data.push_back(char(((reinterpret_cast(&data)[i%4])%95)+32)); - } - } else { - m_data.assign(m_test_sizes[m_subtest-1],'*'); - } - } - - void fill_binary(connection_ptr connection, bool random = true) { - if (random) { - int32_t data; - for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { - if (i%4 == 0) { - data = connection->rand(); - } - - m_data.push_back((reinterpret_cast(&data))[i%4]); - } - } else { - m_data.assign(m_test_sizes[m_subtest-1],'*'); - } - } - - void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { - m_end_time = boost::posix_time::microsec_clock::local_time(); - - // Check whether the echoed data matches exactly - m_pass = (msg->get_payload() == m_data); - - connection->recycle(msg); - this->end(connection); - } +public: + test_9_1_X(int minor, int subtest) : m_minor(minor),m_subtest(subtest){ + // needs more C++11 intializer lists =( + m_test_sizes[0] = 65536; + m_test_sizes[1] = 262144; + m_test_sizes[2] = 1048576; + m_test_sizes[3] = 4194304; + m_test_sizes[4] = 8388608; + m_test_sizes[5] = 16777216; + } + + void on_open(connection_ptr connection) { + std::cout << "Test 9." << m_minor << "." << m_subtest; + + + + m_data.reserve(m_test_sizes[m_subtest-1]); + + if (m_minor == 1) { + fill_utf8(connection,true); + m_start_time = boost::posix_time::microsec_clock::local_time(); + connection->send(m_data,false); + } else if (m_minor == 2) { + fill_binary(connection,true); + m_start_time = boost::posix_time::microsec_clock::local_time(); + connection->send(m_data,true); + } else { + std::cout << " has unknown definition." << std::endl; + } + } + + // Just does random ascii right now. True random UTF8 with multi-byte stuff + // would probably be better + void fill_utf8(connection_ptr connection,bool random = true) { + if (random) { + uint32_t data; + for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { + if (i%4 == 0) { + data = uint32_t(connection->rand()); + } + + m_data.push_back(char(((reinterpret_cast(&data)[i%4])%95)+32)); + } + } else { + m_data.assign(m_test_sizes[m_subtest-1],'*'); + } + } + + void fill_binary(connection_ptr connection, bool random = true) { + if (random) { + int32_t data; + for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { + if (i%4 == 0) { + data = connection->rand(); + } + + m_data.push_back((reinterpret_cast(&data))[i%4]); + } + } else { + m_data.assign(m_test_sizes[m_subtest-1],'*'); + } + } + + void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { + m_end_time = boost::posix_time::microsec_clock::local_time(); + + // Check whether the echoed data matches exactly + m_pass = (msg->get_payload() == m_data); + + connection->recycle(msg); + this->end(connection); + } private: - int m_minor; - int m_subtest; - size_t m_test_sizes[6]; - std::string m_data; + int m_minor; + int m_subtest; + size_t m_test_sizes[6]; + std::string m_data; }; // test class for 9.7.* and 9.8.* /*class test_9_7_X : public test_case_handler { -public: - test_9_1_X(int minor, int subtest) : m_minor(minor),m_subtest(subtest){ - // needs more C++11 intializer lists =( - m_test_sizes[0] = 65536; - m_test_sizes[1] = 262144; - m_test_sizes[2] = 1048576; - m_test_sizes[3] = 4194304; - m_test_sizes[4] = 8388608; - m_test_sizes[5] = 16777216; - } - - void on_open(connection_ptr connection) { - std::cout << "Test 9." << m_minor << "." << m_subtest; - - - - m_data.reserve(m_test_sizes[m_subtest-1]); - - if (m_minor == 1) { - fill_utf8(connection,true); - m_start_time = boost::posix_time::microsec_clock::local_time(); - connection->send(m_data,false); - } else if (m_minor == 2) { - fill_binary(connection,true); - m_start_time = boost::posix_time::microsec_clock::local_time(); - connection->send(m_data,true); - } else { - std::cout << " has unknown definition." << std::endl; - } - } - - // Just does random ascii right now. True random UTF8 with multi-byte stuff - // would probably be better - void fill_utf8(connection_ptr connection,bool random = true) { - if (random) { - uint32_t data; - for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { - if (i%4 == 0) { - data = uint32_t(connection->rand()); - } - - m_data.push_back(char(((reinterpret_cast(&data)[i%4])%95)+32)); - } - } else { - m_data.assign(m_test_sizes[m_subtest-1],'*'); - } - } - - void fill_binary(connection_ptr connection, bool random = true) { - if (random) { - int32_t data; - for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { - if (i%4 == 0) { - data = connection->rand(); - } - - m_data.push_back((reinterpret_cast(&data))[i%4]); - } - } else { - m_data.assign(m_test_sizes[m_subtest-1],'*'); - } - } - - void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { - m_end_time = boost::posix_time::microsec_clock::local_time(); - - // Check whether the echoed data matches exactly - m_pass = (msg->get_payload() == m_data); - - connection->recycle(msg); - this->end(connection); - } +public: + test_9_1_X(int minor, int subtest) : m_minor(minor),m_subtest(subtest){ + // needs more C++11 intializer lists =( + m_test_sizes[0] = 65536; + m_test_sizes[1] = 262144; + m_test_sizes[2] = 1048576; + m_test_sizes[3] = 4194304; + m_test_sizes[4] = 8388608; + m_test_sizes[5] = 16777216; + } + + void on_open(connection_ptr connection) { + std::cout << "Test 9." << m_minor << "." << m_subtest; + + + + m_data.reserve(m_test_sizes[m_subtest-1]); + + if (m_minor == 1) { + fill_utf8(connection,true); + m_start_time = boost::posix_time::microsec_clock::local_time(); + connection->send(m_data,false); + } else if (m_minor == 2) { + fill_binary(connection,true); + m_start_time = boost::posix_time::microsec_clock::local_time(); + connection->send(m_data,true); + } else { + std::cout << " has unknown definition." << std::endl; + } + } + + // Just does random ascii right now. True random UTF8 with multi-byte stuff + // would probably be better + void fill_utf8(connection_ptr connection,bool random = true) { + if (random) { + uint32_t data; + for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { + if (i%4 == 0) { + data = uint32_t(connection->rand()); + } + + m_data.push_back(char(((reinterpret_cast(&data)[i%4])%95)+32)); + } + } else { + m_data.assign(m_test_sizes[m_subtest-1],'*'); + } + } + + void fill_binary(connection_ptr connection, bool random = true) { + if (random) { + int32_t data; + for (int i = 0; i < m_test_sizes[m_subtest-1]; i++) { + if (i%4 == 0) { + data = connection->rand(); + } + + m_data.push_back((reinterpret_cast(&data))[i%4]); + } + } else { + m_data.assign(m_test_sizes[m_subtest-1],'*'); + } + } + + void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { + m_end_time = boost::posix_time::microsec_clock::local_time(); + + // Check whether the echoed data matches exactly + m_pass = (msg->get_payload() == m_data); + + connection->recycle(msg); + this->end(connection); + } private: - int m_minor; - int m_subtest; - size_t m_test_sizes[6]; - std::string m_data; + int m_minor; + int m_subtest; + size_t m_test_sizes[6]; + std::string m_data; };*/ int main(int argc, char* argv[]) { - std::string uri; - - - - if (argc != 2) { - uri = "ws://localhost:9002/"; - } else { - uri = argv[1]; - } - - std::vector tests; - - for (int i = 1; i <= 2; i++) { - for (int j = 1; j <= 6; j++) { - tests.push_back(plain_handler_ptr(new test_9_1_X(i,j))); - } - } - - try { - plain_endpoint_type endpoint(tests[0]); - - endpoint.alog().unset_level(websocketpp::log::alevel::ALL); - endpoint.elog().unset_level(websocketpp::log::elevel::ALL); - - for (int i = 0; i < tests.size(); i++) { - if (i > 0) { - endpoint.reset(); - endpoint.set_handler(tests[i]); - } - - endpoint.connect(uri); - endpoint.run(); - } + std::string uri; + + + + if (argc != 2) { + uri = "ws://localhost:9002/"; + } else { + uri = argv[1]; + } + + std::vector tests; + + for (int i = 1; i <= 2; i++) { + for (int j = 1; j <= 6; j++) { + tests.push_back(plain_handler_ptr(new test_9_1_X(i,j))); + } + } + + try { + plain_endpoint_type endpoint(tests[0]); + + endpoint.alog().unset_level(websocketpp::log::alevel::ALL); + endpoint.elog().unset_level(websocketpp::log::elevel::ALL); + + for (int i = 0; i < tests.size(); i++) { + if (i > 0) { + endpoint.reset(); + endpoint.set_handler(tests[i]); + } + + endpoint.connect(uri); + endpoint.run(); + } + + std::cout << "done" << std::endl; - std::cout << "done" << std::endl; - - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/fuzzing_server_tls/echo_client.html b/examples/fuzzing_server_tls/echo_client.html index cd46a17a7..dc36396a2 100644 --- a/examples/fuzzing_server_tls/echo_client.html +++ b/examples/fuzzing_server_tls/echo_client.html @@ -9,84 +9,84 @@ var url; function connect() { - url = document.getElementById("server_url").value; - console.log(url); - - if ("WebSocket" in window) { - ws = new WebSocket(url); - } else if ("MozWebSocket" in window) { - ws = new MozWebSocket(url); - } else { - document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; - return; - } - ws.onopen = function(e) { - document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; - - document.getElementById("server_url").disabled = true; - document.getElementById("toggle_connect").innerHTML = "Disconnect"; - }; - - ws.onerror = function(e) { - document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; - console.log(e); - }; - - ws.onclose = function(e) { - document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; - }; - - ws.onmessage = function(e) { - document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; - }; + url = document.getElementById("server_url").value; + console.log(url); + + if ("WebSocket" in window) { + ws = new WebSocket(url); + } else if ("MozWebSocket" in window) { + ws = new MozWebSocket(url); + } else { + document.getElementById("messages").innerHTML += "This Browser does not support WebSockets
"; + return; + } + ws.onopen = function(e) { + document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.
"; + + document.getElementById("server_url").disabled = true; + document.getElementById("toggle_connect").innerHTML = "Disconnect"; + }; + + ws.onerror = function(e) { + document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.
"; + console.log(e); + }; + + ws.onclose = function(e) { + document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.
"; + }; + + ws.onmessage = function(e) { + document.getElementById("messages").innerHTML += "Server: "+e.data+"
"; + }; } function disconnect() { - ws.close(); - document.getElementById("server_url").disabled = false; - document.getElementById("toggle_connect").innerHTML = "Connect"; + ws.close(); + document.getElementById("server_url").disabled = false; + document.getElementById("toggle_connect").innerHTML = "Connect"; } function toggle_connect() { - if (document.getElementById("server_url").disabled === false) { - connect(); - } else { - disconnect(); - } + if (document.getElementById("server_url").disabled === false) { + connect(); + } else { + disconnect(); + } } function send() { - if (ws === undefined || ws.readyState != 1) { - document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; - return; - } - - ws.send(document.getElementById("msg").value); - document.getElementById("msg").value = ""; + if (ws === undefined || ws.readyState != 1) { + document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing
"; + return; + } + + ws.send(document.getElementById("msg").value); + document.getElementById("msg").value = ""; }
-
- - -
+
+ + +
-
-
+
+
diff --git a/examples/fuzzing_server_tls/fuzzing_server_tls.cpp b/examples/fuzzing_server_tls/fuzzing_server_tls.cpp index 96377cc5e..8377d0cf6 100644 --- a/examples/fuzzing_server_tls/fuzzing_server_tls.cpp +++ b/examples/fuzzing_server_tls/fuzzing_server_tls.cpp @@ -41,142 +41,142 @@ typedef tls_endpoint_type::handler_ptr tls_handler_ptr; template class echo_server_handler : public endpoint_type::handler { public: - typedef echo_server_handler type; - typedef typename endpoint_type::connection_ptr connection_ptr; - - std::string get_password() const { - return "test"; - } - - boost::shared_ptr on_tls_init() { - // create a tls context, init, and return. - boost::shared_ptr context(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1)); - try { - context->set_options(boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::single_dh_use); - context->set_password_callback(boost::bind(&type::get_password, this)); - context->use_certificate_chain_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/server.pem"); - context->use_private_key_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/server.pem", boost::asio::ssl::context::pem); - context->use_tmp_dh_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/dh512.pem"); - } catch (std::exception& e) { - std::cout << e.what() << std::endl; - } - return context; - } - - void validate(connection_ptr connection) { - //std::cout << "state: " << connection->get_state() << std::endl; - - - - - } - - void on_open(connection_ptr connection) { - //std::cout << "connection opened" << std::endl; - // extract user agent - // start timer - start_time = boost::posix_time::microsec_clock::local_time(); - // send message - connection->send("abcd",true); - // stop - } - - void on_close(connection_ptr connection) { - //std::cout << "connection closed" << std::endl; - } - - void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { - //std::cout << "got message: " << *msg << std::endl; - //connection->send(msg->get_payload(),(msg->get_opcode() == websocketpp::frame::opcode::BINARY)); - - end_time = boost::posix_time::microsec_clock::local_time(); - - boost::posix_time::time_period len(start_time,end_time); - - if (msg->get_payload() == "abcd") { - std::cout << "Pass in " << len.length() << std::endl; - } else { - std::cout << "Fail in " << len.length() << std::endl; - } - - // stop timer - // check if message was valid - - connection->recycle(msg); - } - - void http(connection_ptr connection) { - connection->set_body("HTTP Response!!"); - } - - void on_fail(connection_ptr connection) { - std::cout << "connection failed" << std::endl; - } - - boost::posix_time::ptime start_time; - boost::posix_time::ptime end_time; + typedef echo_server_handler type; + typedef typename endpoint_type::connection_ptr connection_ptr; + + std::string get_password() const { + return "test"; + } + + boost::shared_ptr on_tls_init() { + // create a tls context, init, and return. + boost::shared_ptr context(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1)); + try { + context->set_options(boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use); + context->set_password_callback(boost::bind(&type::get_password, this)); + context->use_certificate_chain_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/server.pem"); + context->use_private_key_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/server.pem", boost::asio::ssl::context::pem); + context->use_tmp_dh_file("/Users/zaphoyd/Documents/websocketpp/src/ssl/dh512.pem"); + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } + return context; + } + + void validate(connection_ptr connection) { + //std::cout << "state: " << connection->get_state() << std::endl; + + + + + } + + void on_open(connection_ptr connection) { + //std::cout << "connection opened" << std::endl; + // extract user agent + // start timer + start_time = boost::posix_time::microsec_clock::local_time(); + // send message + connection->send("abcd",true); + // stop + } + + void on_close(connection_ptr connection) { + //std::cout << "connection closed" << std::endl; + } + + void on_message(connection_ptr connection,websocketpp::message::data_ptr msg) { + //std::cout << "got message: " << *msg << std::endl; + //connection->send(msg->get_payload(),(msg->get_opcode() == websocketpp::frame::opcode::BINARY)); + + end_time = boost::posix_time::microsec_clock::local_time(); + + boost::posix_time::time_period len(start_time,end_time); + + if (msg->get_payload() == "abcd") { + std::cout << "Pass in " << len.length() << std::endl; + } else { + std::cout << "Fail in " << len.length() << std::endl; + } + + // stop timer + // check if message was valid + + connection->recycle(msg); + } + + void http(connection_ptr connection) { + connection->set_body("HTTP Response!!"); + } + + void on_fail(connection_ptr connection) { + std::cout << "connection failed" << std::endl; + } + + boost::posix_time::ptime start_time; + boost::posix_time::ptime end_time; }; int main(int argc, char* argv[]) { - unsigned short port = 9002; - bool tls = false; - - if (argc == 2) { - // TODO: input validation? - port = atoi(argv[1]); - } - - if (argc == 3) { - // TODO: input validation? - port = atoi(argv[1]); - tls = !strcmp(argv[2],"-tls"); - } - - try { - if (tls) { - tls_handler_ptr h(new echo_server_handler()); - tls_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - //e.alog().set_level(websocketpp::log::alevel::CONNECT); - //e.alog().set_level(websocketpp::log::alevel::DISCONNECT); - //e.alog().set_level(websocketpp::log::alevel::DEVEL); - //e.alog().set_level(websocketpp::log::alevel::DEBUG_CLOSE); - //e.alog().unset_level(websocketpp::log::alevel::DEBUG_HANDSHAKE); - - e.elog().unset_level(websocketpp::log::elevel::ALL); - //e.elog().set_level(websocketpp::log::elevel::ERROR); - //e.elog().set_level(websocketpp::log::elevel::FATAL); - - std::cout << "Starting Secure WebSocket echo server on port " << port << std::endl; - e.listen(port); - } else { - plain_handler_ptr h(new echo_server_handler()); - plain_endpoint_type e(h); - - e.alog().unset_level(websocketpp::log::alevel::ALL); - //e.alog().set_level(websocketpp::log::alevel::CONNECT); - //e.alog().set_level(websocketpp::log::alevel::DISCONNECT); - //e.alog().unset_level(websocketpp::log::alevel::DEBUG_HANDSHAKE); - - e.elog().unset_level(websocketpp::log::elevel::ALL); - //e.elog().set_level(websocketpp::log::elevel::ERROR); - //e.elog().set_level(websocketpp::log::elevel::FATAL); - - // TODO: fix - //e.alog().set_level(websocketpp::log::alevel::CONNECT & websocketpp::log::alevel::DISCONNECT); - //e.elog().set_levels(websocketpp::log::elevel::ERROR,websocketpp::log::elevel::FATAL); - - std::cout << "Starting WebSocket echo server on port " << port << std::endl; - e.listen(port); - } - - - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + unsigned short port = 9002; + bool tls = false; + + if (argc == 2) { + // TODO: input validation? + port = atoi(argv[1]); + } + + if (argc == 3) { + // TODO: input validation? + port = atoi(argv[1]); + tls = !strcmp(argv[2],"-tls"); + } + + try { + if (tls) { + tls_handler_ptr h(new echo_server_handler()); + tls_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + //e.alog().set_level(websocketpp::log::alevel::CONNECT); + //e.alog().set_level(websocketpp::log::alevel::DISCONNECT); + //e.alog().set_level(websocketpp::log::alevel::DEVEL); + //e.alog().set_level(websocketpp::log::alevel::DEBUG_CLOSE); + //e.alog().unset_level(websocketpp::log::alevel::DEBUG_HANDSHAKE); + + e.elog().unset_level(websocketpp::log::elevel::ALL); + //e.elog().set_level(websocketpp::log::elevel::ERROR); + //e.elog().set_level(websocketpp::log::elevel::FATAL); + + std::cout << "Starting Secure WebSocket echo server on port " << port << std::endl; + e.listen(port); + } else { + plain_handler_ptr h(new echo_server_handler()); + plain_endpoint_type e(h); + + e.alog().unset_level(websocketpp::log::alevel::ALL); + //e.alog().set_level(websocketpp::log::alevel::CONNECT); + //e.alog().set_level(websocketpp::log::alevel::DISCONNECT); + //e.alog().unset_level(websocketpp::log::alevel::DEBUG_HANDSHAKE); + + e.elog().unset_level(websocketpp::log::elevel::ALL); + //e.elog().set_level(websocketpp::log::elevel::ERROR); + //e.elog().set_level(websocketpp::log::elevel::FATAL); + + // TODO: fix + //e.alog().set_level(websocketpp::log::alevel::CONNECT & websocketpp::log::alevel::DISCONNECT); + //e.elog().set_levels(websocketpp::log::elevel::ERROR,websocketpp::log::elevel::FATAL); + + std::cout << "Starting WebSocket echo server on port " << port << std::endl; + e.listen(port); + } + + + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/examples/stress_client/stress_client.cpp b/examples/stress_client/stress_client.cpp index 3529f8152..95cf17eb1 100644 --- a/examples/stress_client/stress_client.cpp +++ b/examples/stress_client/stress_client.cpp @@ -60,9 +60,9 @@ typedef plain_endpoint_type::connection_ptr connection_ptr; class stress_client_handler : public plain_endpoint_type::handler { public: - typedef stress_client_handler type; - typedef plain_endpoint_type::connection_ptr connection_ptr; - + typedef stress_client_handler type; + typedef plain_endpoint_type::connection_ptr connection_ptr; + stress_client_handler(int num_connections) : m_connections_max(num_connections), m_connections_cur(0) { @@ -71,10 +71,10 @@ class stress_client_handler : public plain_endpoint_type::handler { void on_open(connection_ptr connection) { if (!m_timer) { - m_timer.reset(new boost::asio::deadline_timer(connection->get_io_service(),boost::posix_time::seconds(0))); - m_timer->expires_from_now(boost::posix_time::milliseconds(250)); - m_timer->async_wait(boost::bind(&type::on_timer,this,connection,boost::asio::placeholders::error)); - } + m_timer.reset(new boost::asio::deadline_timer(connection->get_io_service(),boost::posix_time::seconds(0))); + m_timer->expires_from_now(boost::posix_time::milliseconds(250)); + m_timer->async_wait(boost::bind(&type::on_timer,this,connection,boost::asio::placeholders::error)); + } m_connections_cur++; @@ -87,19 +87,19 @@ class stress_client_handler : public plain_endpoint_type::handler { } } - void on_message(connection_ptr connection, websocketpp::message::data::ptr msg) { + void on_message(connection_ptr connection, websocketpp::message::data::ptr msg) { //std::cout << "got message of size: " << msg->get_payload().size() << std::endl; m_msg_stats[websocketpp::md5_hash_hex(msg->get_payload())]++; if (m_msg_stats[websocketpp::md5_hash_hex(msg->get_payload())] == m_connections_max) { send_stats_update(connection); } - } - - void on_fail(connection_ptr connection) { - std::cout << "connection failed" << std::endl; - } - + } + + void on_fail(connection_ptr connection) { + std::cout << "connection failed" << std::endl; + } + void on_timer(connection_ptr connection,const boost::system::error_code& error) { if (error) { std::cout << "on_timer error" << std::endl; @@ -109,14 +109,14 @@ class stress_client_handler : public plain_endpoint_type::handler { send_stats_update(connection); m_timer->expires_from_now(boost::posix_time::milliseconds(250)); - m_timer->async_wait(boost::bind(&type::on_timer,this,connection,boost::asio::placeholders::error)); + m_timer->async_wait(boost::bind(&type::on_timer,this,connection,boost::asio::placeholders::error)); } void on_close(connection_ptr connection) { m_timer->cancel(); } - boost::posix_time::ptime m_start_time; + boost::posix_time::ptime m_start_time; private: void send_stats_update(connection_ptr connection) { if (m_msg_stats.empty()) { @@ -146,24 +146,24 @@ class stress_client_handler : public plain_endpoint_type::handler { int main(int argc, char* argv[]) { - std::string uri = "ws://localhost:9002/"; - int num_connections = 100; - int batch_size = 25; + std::string uri = "ws://localhost:9002/"; + 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]); + + 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 + } + + // 12288 is max OS X limit without changing kernal settings const rlim_t ideal_size = 200+num_connections; rlim_t old_size; - rlim_t old_max; + rlim_t old_max; struct rlimit rl; int result; @@ -174,63 +174,63 @@ int main(int argc, char* argv[]) { old_size = rl.rlim_cur; old_max = rl.rlim_max; - + if (rl.rlim_cur < ideal_size) { std::cout << "Attempting to raise system file descriptor limit from " << rl.rlim_cur << " to " << ideal_size << std::endl; - rl.rlim_cur = ideal_size; + rl.rlim_cur = ideal_size; - if (rl.rlim_max < ideal_size) { - rl.rlim_max = ideal_size; - } - - result = setrlimit(RLIMIT_NOFILE, &rl); + if (rl.rlim_max < ideal_size) { + rl.rlim_max = ideal_size; + } + + result = setrlimit(RLIMIT_NOFILE, &rl); if (result == 0) { std::cout << "Success" << std::endl; - } else if (result == EPERM) { - std::cout << "Failed. This server will be limited to " << old_size << " concurrent connections. Error code: Insufficient permissions. Try running process as root. system max: " << old_max << std::endl; - } else { - std::cout << "Failed. This server will be limited to " << old_size << " concurrent connections. Error code: " << errno << " system max: " << old_max << std::endl; - } + } else if (result == EPERM) { + std::cout << "Failed. This server will be limited to " << old_size << " concurrent connections. Error code: Insufficient permissions. Try running process as root. system max: " << old_max << std::endl; + } else { + std::cout << "Failed. This server will be limited to " << old_size << " concurrent connections. Error code: " << errno << " system max: " << old_max << std::endl; + } } } - - try { - plain_handler_ptr handler(new stress_client_handler(num_connections)); - plain_endpoint_type endpoint(handler); - - endpoint.alog().unset_level(websocketpp::log::alevel::ALL); - endpoint.elog().set_level(websocketpp::log::elevel::ALL); - + + try { + plain_handler_ptr handler(new stress_client_handler(num_connections)); + plain_endpoint_type endpoint(handler); + + endpoint.alog().unset_level(websocketpp::log::alevel::ALL); + endpoint.elog().set_level(websocketpp::log::elevel::ALL); + //endpoint.alog().set_level(websocketpp::log::alevel::DEVEL); //endpoint.alog().set_level(websocketpp::log::alevel::DEBUG_CLOSE); - std::set connections; - - connections.insert(endpoint.connect(uri)); - - boost::thread t(boost::bind(&plain_endpoint_type::run, &endpoint)); - - std::cout << "launching " << num_connections << " connections to " << uri << " in batches of " << batch_size << std::endl; - + std::set connections; + + connections.insert(endpoint.connect(uri)); + + boost::thread t(boost::bind(&plain_endpoint_type::run, &endpoint)); + + std::cout << "launching " << num_connections << " connections to " << uri << " in batches of " << batch_size << std::endl; + boost::dynamic_pointer_cast(handler)->m_start_time = boost::posix_time::microsec_clock::local_time(); - for (int i = 0; i < num_connections-1; i++) { - if (i % batch_size == 0) { - //sleep(1); + for (int i = 0; i < num_connections-1; i++) { + if (i % batch_size == 0) { + //sleep(1); msleep(delay_ms); - } - connections.insert(endpoint.connect(uri)); - } - - std::cout << "complete" << std::endl; - - t.join(); - - std::cout << "done" << std::endl; - - } catch (std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; + } + connections.insert(endpoint.connect(uri)); + } + + std::cout << "complete" << std::endl; + + t.join(); + + std::cout << "done" << std::endl; + + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; } diff --git a/src/common.hpp b/src/common.hpp index d7f985cea..ea7ab291d 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -41,68 +41,68 @@ // Defaults namespace websocketpp { - typedef std::vector binary_string; - typedef boost::shared_ptr binary_string_ptr; - - typedef std::string utf8_string; - typedef boost::shared_ptr utf8_string_ptr; - - const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB - - const uint16_t DEFAULT_PORT = 80; - const uint16_t DEFAULT_SECURE_PORT = 443; - - inline uint16_t default_port(bool secure) { - return (secure ? DEFAULT_SECURE_PORT : DEFAULT_PORT); - } - - namespace session { - namespace state { - enum value { - CONNECTING = 0, - OPEN = 1, - CLOSING = 2, - CLOSED = 3 - }; - } - } - - namespace close { - namespace status { - enum value { - INVALID_END = 999, - NORMAL = 1000, - GOING_AWAY = 1001, - PROTOCOL_ERROR = 1002, - UNSUPPORTED_DATA = 1003, - RSV_ADHOC_1 = 1004, - NO_STATUS = 1005, - ABNORMAL_CLOSE = 1006, - INVALID_PAYLOAD = 1007, - POLICY_VIOLATION = 1008, - MESSAGE_TOO_BIG = 1009, - EXTENSION_REQUIRE = 1010, - INTERNAL_ENDPOINT_ERROR = 1011, - RSV_START = 1012, - RSV_END = 2999, - INVALID_START = 5000 - }; - - inline bool reserved(value s) { - return ((s >= RSV_START && s <= RSV_END) || - s == RSV_ADHOC_1); - } - - inline bool invalid(value s) { - return ((s <= INVALID_END || s >= INVALID_START) || - s == NO_STATUS || - s == ABNORMAL_CLOSE); - } - - // TODO functions for application ranges? - } // namespace status - } // namespace close - + typedef std::vector binary_string; + typedef boost::shared_ptr binary_string_ptr; + + typedef std::string utf8_string; + typedef boost::shared_ptr utf8_string_ptr; + + const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB + + const uint16_t DEFAULT_PORT = 80; + const uint16_t DEFAULT_SECURE_PORT = 443; + + inline uint16_t default_port(bool secure) { + return (secure ? DEFAULT_SECURE_PORT : DEFAULT_PORT); + } + + namespace session { + namespace state { + enum value { + CONNECTING = 0, + OPEN = 1, + CLOSING = 2, + CLOSED = 3 + }; + } + } + + namespace close { + namespace status { + enum value { + INVALID_END = 999, + NORMAL = 1000, + GOING_AWAY = 1001, + PROTOCOL_ERROR = 1002, + UNSUPPORTED_DATA = 1003, + RSV_ADHOC_1 = 1004, + NO_STATUS = 1005, + ABNORMAL_CLOSE = 1006, + INVALID_PAYLOAD = 1007, + POLICY_VIOLATION = 1008, + MESSAGE_TOO_BIG = 1009, + EXTENSION_REQUIRE = 1010, + INTERNAL_ENDPOINT_ERROR = 1011, + RSV_START = 1012, + RSV_END = 2999, + INVALID_START = 5000 + }; + + inline bool reserved(value s) { + return ((s >= RSV_START && s <= RSV_END) || + s == RSV_ADHOC_1); + } + + inline bool invalid(value s) { + return ((s <= INVALID_END || s >= INVALID_START) || + s == NO_STATUS || + s == ABNORMAL_CLOSE); + } + + // TODO functions for application ranges? + } // namespace status + } // namespace close + namespace frame { // Opcodes are 4 bits // See spec section 5.2 @@ -158,7 +158,7 @@ namespace websocketpp { } class exception : public std::exception { - public: + public: exception(const std::string& msg, error::value code = error::GENERIC) : m_msg(msg),m_code(code) {} diff --git a/src/connection.hpp b/src/connection.hpp index dc5bb0885..91057b4ec 100644 --- a/src/connection.hpp +++ b/src/connection.hpp @@ -55,88 +55,88 @@ class endpoint_base; template struct connection_traits; - + template < - typename endpoint, - template class role, - template class socket> + typename endpoint, + template class role, + template class socket> class connection : public role< connection >, public socket< connection >, public boost::enable_shared_from_this< connection > { public: - typedef connection_traits< connection > traits; - - // get types that we need from our traits class - typedef typename traits::type type; - typedef typename traits::role_type role_type; - typedef typename traits::socket_type socket_type; - - typedef endpoint endpoint_type; - - typedef typename endpoint_type::handler_ptr handler_ptr; - - // friends (would require C++11) this would enable connection::start to be - // protected instead of public. - //friend typename endpoint_traits::role_type; - //friend typename endpoint_traits::socket_type; - //friend class role; - //friend class socket; - - friend class role< connection >; - friend class socket< connection >; - - enum write_state { - IDLE = 0, - WRITING = 1, - INTURRUPT = 2 - }; - - enum read_state { - READING = 0, - WAITING = 1 - }; - - connection(endpoint_type& e,handler_ptr h) - : role_type(e), - socket_type(e), - m_endpoint(e), - m_handler(h), - m_timer(e.endpoint_base::m_io_service,boost::posix_time::seconds(0)), - m_state(session::state::CONNECTING), - m_write_buffer(0), - m_write_state(IDLE), - m_remote_close_code(close::status::ABNORMAL_CLOSE), - m_read_state(READING) - { - socket_type::init(); - - m_control_message = message::control_ptr(new message::control()); - } - - // SHOULD BE PROTECTED - void start() { - // initialize the socket. - socket_type::async_init( - boost::bind( - &type::handle_socket_init, - type::shared_from_this(), - boost::asio::placeholders::error - ) - ); - } - // END PROTECTED - - // Valid always - session::state::value get_state() const { - return m_state; - } - - // Valid for OPEN state + typedef connection_traits< connection > traits; + + // get types that we need from our traits class + typedef typename traits::type type; + typedef typename traits::role_type role_type; + typedef typename traits::socket_type socket_type; + + typedef endpoint endpoint_type; + + typedef typename endpoint_type::handler_ptr handler_ptr; + + // friends (would require C++11) this would enable connection::start to be + // protected instead of public. + //friend typename endpoint_traits::role_type; + //friend typename endpoint_traits::socket_type; + //friend class role; + //friend class socket; + + friend class role< connection >; + friend class socket< connection >; + + enum write_state { + IDLE = 0, + WRITING = 1, + INTURRUPT = 2 + }; + + enum read_state { + READING = 0, + WAITING = 1 + }; + + connection(endpoint_type& e,handler_ptr h) + : role_type(e), + socket_type(e), + m_endpoint(e), + m_handler(h), + m_timer(e.endpoint_base::m_io_service,boost::posix_time::seconds(0)), + m_state(session::state::CONNECTING), + m_write_buffer(0), + m_write_state(IDLE), + m_remote_close_code(close::status::ABNORMAL_CLOSE), + m_read_state(READING) + { + socket_type::init(); + + m_control_message = message::control_ptr(new message::control()); + } + + // SHOULD BE PROTECTED + void start() { + // initialize the socket. + socket_type::async_init( + boost::bind( + &type::handle_socket_init, + type::shared_from_this(), + boost::asio::placeholders::error + ) + ); + } + // END PROTECTED + + // Valid always + session::state::value get_state() const { + return m_state; + } + + // Valid for OPEN state /// convenience overload for sending a one off text message. - void send(const std::string& payload, frame::opcode::value op = frame::opcode::TEXT) { - websocketpp::message::data::ptr msg = get_control_message2(); + void send(const std::string& payload, frame::opcode::value op = frame::opcode::TEXT) { + websocketpp::message::data::ptr msg = get_control_message2(); if (!msg) { throw exception("Endpoint send queue is full",error::SEND_QUEUE_FULL); @@ -148,285 +148,285 @@ class connection msg->reset(op); msg->set_payload(payload); send(msg); - } + } void send(message::data_ptr msg) { m_processor->prepare_frame(msg); write_message(msg); } - void close(close::status::value code, const std::string& reason = "") { - // TODO: overloads without code or reason? - send_close(code, reason); - } - void ping(const std::string& payload) { - send_ping(payload); - } - void pong(const std::string& payload) { + void close(close::status::value code, const std::string& reason = "") { + // TODO: overloads without code or reason? + send_close(code, reason); + } + void ping(const std::string& payload) { + send_ping(payload); + } + void pong(const std::string& payload) { send_pong(payload); - } - - uint64_t buffered_amount() const { - return m_write_buffer; - } - - // Valid for CLOSED state - close::status::value get_local_close_code() const { - return m_local_close_code; - } - utf8_string get_local_close_reason() const { - return m_local_close_reason; - } - close::status::value get_remote_close_code() const { - return m_remote_close_code; - } - utf8_string get_remote_close_reason() const { - return m_remote_close_reason; - } - bool get_failed_by_me() const { - return m_failed_by_me; - } - bool get_dropped_by_me() const { - return m_dropped_by_me; - } - bool get_closed_by_me() const { - return m_closed_by_me; - } - - // flow control interface - message::data_ptr get_data_message() { - return m_endpoint.get_data_message(); - } - + } + + uint64_t buffered_amount() const { + return m_write_buffer; + } + + // Valid for CLOSED state + close::status::value get_local_close_code() const { + return m_local_close_code; + } + utf8_string get_local_close_reason() const { + return m_local_close_reason; + } + close::status::value get_remote_close_code() const { + return m_remote_close_code; + } + utf8_string get_remote_close_reason() const { + return m_remote_close_reason; + } + bool get_failed_by_me() const { + return m_failed_by_me; + } + bool get_dropped_by_me() const { + return m_dropped_by_me; + } + bool get_closed_by_me() const { + return m_closed_by_me; + } + + // flow control interface + message::data_ptr get_data_message() { + return m_endpoint.get_data_message(); + } + message::data_ptr get_control_message2() { - return m_endpoint.get_control_message(); - } - - message::control_ptr get_control_message() { - return m_control_message; - } - - - // stuff about switching handlers on the fly - // TODO: organize more - void set_handler(handler_ptr new_handler) { - - if (!new_handler) { + return m_endpoint.get_control_message(); + } + + message::control_ptr get_control_message() { + return m_control_message; + } + + + // stuff about switching handlers on the fly + // TODO: organize more + void set_handler(handler_ptr new_handler) { + + if (!new_handler) { m_endpoint.elog().at(log::elevel::FATAL) << "Tried to switch to a NULL handler." << log::endl; - terminate(true); + terminate(true); + return; + } + + handler_ptr old_handler = get_handler(); + + old_handler->on_unload(type::shared_from_this(),new_handler); + m_handler = new_handler; + new_handler->on_load(type::shared_from_this(),old_handler); + } + + // TODO: deprecated. will change to get_rng? + int32_t gen() { + return 0; + } + + typename endpoint::alogger_type& alog() { + return m_endpoint.alog(); + } +protected: + void handle_socket_init(const boost::system::error_code& error) { + if (error) { + m_endpoint.elog().at(log::elevel::ERROR) << "Connection initialization failed, error code: " << error << log::endl; + this->terminate(false); return; - } - - handler_ptr old_handler = get_handler(); - - old_handler->on_unload(type::shared_from_this(),new_handler); - m_handler = new_handler; - new_handler->on_load(type::shared_from_this(),old_handler); - } - - // TODO: deprecated. will change to get_rng? - int32_t gen() { - return 0; - } - - typename endpoint::alogger_type& alog() { - return m_endpoint.alog(); - } -protected: - void handle_socket_init(const boost::system::error_code& error) { - if (error) { - m_endpoint.elog().at(log::elevel::ERROR) << "Connection initialization failed, error code: " << error << log::endl; - this->terminate(false); - return; - } - - role_type::async_init(); - } -public: - void handle_read_frame(const boost::system::error_code& error) { - // check if state changed while we were waiting for a read. - if (m_state == session::state::CLOSED) { return; } - - if (error) { - if (error == boost::asio::error::eof) { - // got unexpected EOF - // TODO: log error + } + + role_type::async_init(); + } +public: + void handle_read_frame(const boost::system::error_code& error) { + // check if state changed while we were waiting for a read. + if (m_state == session::state::CLOSED) { return; } + + if (error) { + if (error == boost::asio::error::eof) { + // got unexpected EOF + // TODO: log error m_endpoint.elog().at(log::elevel::ERROR) << "Remote connection dropped unexpectedly" << log::endl; - terminate(false); - } else if (error == boost::asio::error::operation_aborted) { - // got unexpected abort (likely our server issued an abort on - // all connections on this io_service) - - // TODO: log error + terminate(false); + } else if (error == boost::asio::error::operation_aborted) { + // got unexpected abort (likely our server issued an abort on + // all connections on this io_service) + + // TODO: log error m_endpoint.elog().at(log::elevel::ERROR) << "Terminating due to abort: " << error << log::endl; - terminate(true); - } else { - // Other unexpected error - - // TODO: log error + terminate(true); + } else { + // Other unexpected error + + // TODO: log error m_endpoint.elog().at(log::elevel::ERROR) << "Terminating due to unknown error: " << error << log::endl; - terminate(false); - } - } - - // process data from the buffer just read into - std::istream s(&m_buf); - - while (m_state != session::state::CLOSED && m_buf.size() > 0) { - try { - m_processor->consume(s); - - if (m_processor->ready()) { - if (m_processor->is_control()) { - process_control(m_processor->get_control_message()); - } else { - process_data(m_processor->get_data_message()); - } - m_processor->reset(); - } - } catch (const processor::exception& e) { - if (m_processor->ready()) { - m_processor->reset(); - } - - switch(e.code()) { - case processor::error::PROTOCOL_VIOLATION: - send_close(close::status::PROTOCOL_ERROR, e.what()); - break; - case processor::error::PAYLOAD_VIOLATION: - send_close(close::status::INVALID_PAYLOAD, e.what()); - break; - case processor::error::INTERNAL_ENDPOINT_ERROR: - send_close(close::status::INTERNAL_ENDPOINT_ERROR, e.what()); - break; - case processor::error::SOFT_ERROR: - continue; - case processor::error::MESSAGE_TOO_BIG: - send_close(close::status::MESSAGE_TOO_BIG, e.what()); - break; - case processor::error::OUT_OF_MESSAGES: - // we need to wait for a message to be returned by the - // client. We exit the read loop. handle_read_frame - // will be restarted by recycle() - //m_read_state = WAITING; + terminate(false); + } + } + + // process data from the buffer just read into + std::istream s(&m_buf); + + while (m_state != session::state::CLOSED && m_buf.size() > 0) { + try { + m_processor->consume(s); + + if (m_processor->ready()) { + if (m_processor->is_control()) { + process_control(m_processor->get_control_message()); + } else { + process_data(m_processor->get_data_message()); + } + m_processor->reset(); + } + } catch (const processor::exception& e) { + if (m_processor->ready()) { + m_processor->reset(); + } + + switch(e.code()) { + case processor::error::PROTOCOL_VIOLATION: + send_close(close::status::PROTOCOL_ERROR, e.what()); + break; + case processor::error::PAYLOAD_VIOLATION: + send_close(close::status::INVALID_PAYLOAD, e.what()); + break; + case processor::error::INTERNAL_ENDPOINT_ERROR: + send_close(close::status::INTERNAL_ENDPOINT_ERROR, e.what()); + break; + case processor::error::SOFT_ERROR: + continue; + case processor::error::MESSAGE_TOO_BIG: + send_close(close::status::MESSAGE_TOO_BIG, e.what()); + break; + case processor::error::OUT_OF_MESSAGES: + // we need to wait for a message to be returned by the + // client. We exit the read loop. handle_read_frame + // will be restarted by recycle() + //m_read_state = WAITING; m_endpoint.wait(type::shared_from_this()); - return; - default: - // Fatal error, forcibly end connection immediately. - m_endpoint.elog().at(log::elevel::DEVEL) - << "Dropping TCP due to unrecoverable exception" - << log::endl; - terminate(true); - } - break; - - } - } - - // try and read more - if (m_state != session::state::CLOSED && - m_processor->get_bytes_needed() > 0) { - // TODO: read timeout timer? - - boost::asio::async_read( - socket_type::get_socket(), - m_buf, - boost::asio::transfer_at_least(m_processor->get_bytes_needed()), - boost::bind( - &type::handle_read_frame, - type::shared_from_this(), - boost::asio::placeholders::error - ) - ); - } - } -protected: - void process_data(message::data_ptr msg) { - get_handler()->on_message(type::shared_from_this(),msg); - } - - void process_control(message::control_ptr msg) { - bool response; - switch (msg->get_opcode()) { - case frame::opcode::PING: - response = get_handler()->on_ping(type::shared_from_this(), - msg->get_payload()); - if (response) { + return; + default: + // Fatal error, forcibly end connection immediately. + m_endpoint.elog().at(log::elevel::DEVEL) + << "Dropping TCP due to unrecoverable exception" + << log::endl; + terminate(true); + } + break; + + } + } + + // try and read more + if (m_state != session::state::CLOSED && + m_processor->get_bytes_needed() > 0) { + // TODO: read timeout timer? + + boost::asio::async_read( + socket_type::get_socket(), + m_buf, + boost::asio::transfer_at_least(m_processor->get_bytes_needed()), + boost::bind( + &type::handle_read_frame, + type::shared_from_this(), + boost::asio::placeholders::error + ) + ); + } + } +protected: + void process_data(message::data_ptr msg) { + get_handler()->on_message(type::shared_from_this(),msg); + } + + void process_control(message::control_ptr msg) { + bool response; + switch (msg->get_opcode()) { + case frame::opcode::PING: + response = get_handler()->on_ping(type::shared_from_this(), + msg->get_payload()); + if (response) { send_pong(msg->get_payload()); - } - break; - case frame::opcode::PONG: - get_handler()->on_pong(type::shared_from_this(), - msg->get_payload()); - // TODO: disable ping response timer - - break; - case frame::opcode::CLOSE: - m_remote_close_code = msg->get_close_code(); - m_remote_close_reason = msg->get_close_reason(); - - // check that the codes we got over the wire are valid - - if (m_state == session::state::OPEN) { - // other end is initiating - m_endpoint.elog().at(log::elevel::DEVEL) - << "sending close ack" << log::endl; - - // TODO: - send_close_ack(); - } else if (m_state == session::state::CLOSING) { - // ack of our close - m_endpoint.elog().at(log::elevel::DEVEL) - << "got close ack" << log::endl; - - terminate(false); - // TODO: start terminate timer (if client) - } - break; - default: - throw processor::exception("Invalid Opcode", - processor::error::PROTOCOL_VIOLATION); - break; - } - } - - void send_close(close::status::value code, const std::string& reason) { - if (m_state != session::state::OPEN) { - m_endpoint.elog().at(log::elevel::WARN) - << "Tried to disconnect a session that wasn't open" - << log::endl; - return; - } - - if (close::status::invalid(code)) { - m_endpoint.elog().at(log::elevel::WARN) - << "Tried to close a connection with invalid close code: " - << code << log::endl; - return; - } else if (close::status::reserved(code)) { - m_endpoint.elog().at(log::elevel::WARN) - << "Tried to close a connection with reserved close code: " - << code << log::endl; - return; - } - - m_state = session::state::CLOSING; - - m_closed_by_me = true; - - m_timer.expires_from_now(boost::posix_time::milliseconds(1000)); - m_timer.async_wait( - boost::bind( - &type::fail_on_expire, - type::shared_from_this(), - boost::asio::placeholders::error - ) - ); - - m_local_close_code = code; - m_local_close_reason = reason; - + } + break; + case frame::opcode::PONG: + get_handler()->on_pong(type::shared_from_this(), + msg->get_payload()); + // TODO: disable ping response timer + + break; + case frame::opcode::CLOSE: + m_remote_close_code = msg->get_close_code(); + m_remote_close_reason = msg->get_close_reason(); + + // check that the codes we got over the wire are valid + + if (m_state == session::state::OPEN) { + // other end is initiating + m_endpoint.elog().at(log::elevel::DEVEL) + << "sending close ack" << log::endl; + + // TODO: + send_close_ack(); + } else if (m_state == session::state::CLOSING) { + // ack of our close + m_endpoint.elog().at(log::elevel::DEVEL) + << "got close ack" << log::endl; + + terminate(false); + // TODO: start terminate timer (if client) + } + break; + default: + throw processor::exception("Invalid Opcode", + processor::error::PROTOCOL_VIOLATION); + break; + } + } + + void send_close(close::status::value code, const std::string& reason) { + if (m_state != session::state::OPEN) { + m_endpoint.elog().at(log::elevel::WARN) + << "Tried to disconnect a session that wasn't open" + << log::endl; + return; + } + + if (close::status::invalid(code)) { + m_endpoint.elog().at(log::elevel::WARN) + << "Tried to close a connection with invalid close code: " + << code << log::endl; + return; + } else if (close::status::reserved(code)) { + m_endpoint.elog().at(log::elevel::WARN) + << "Tried to close a connection with reserved close code: " + << code << log::endl; + return; + } + + m_state = session::state::CLOSING; + + m_closed_by_me = true; + + m_timer.expires_from_now(boost::posix_time::milliseconds(1000)); + m_timer.async_wait( + boost::bind( + &type::fail_on_expire, + type::shared_from_this(), + boost::asio::placeholders::error + ) + ); + + m_local_close_code = code; + m_local_close_reason = reason; + // TODO: optimize control messages and handle case where endpoint is // out of messages message::data_ptr msg = get_control_message2(); @@ -441,43 +441,43 @@ class connection } msg->reset(frame::opcode::CLOSE); - m_processor->prepare_close_frame(msg,code,reason); - write_message(msg); - - m_write_state = INTURRUPT; - } - - // send an acknowledgement close frame - void send_close_ack() { - // TODO: state should be OPEN - - // echo close value unless there is a good reason not to. - if (m_remote_close_code == close::status::NO_STATUS) { - m_local_close_code = close::status::NORMAL; - m_local_close_reason = ""; - } else if (m_remote_close_code == close::status::ABNORMAL_CLOSE) { - // TODO: can we possibly get here? This means send_close_ack was - // called after a connection ended without getting a close - // frame - throw "shouldn't be here"; - } else if (close::status::invalid(m_remote_close_code)) { - // TODO: shouldn't be able to get here now either - m_local_close_code = close::status::PROTOCOL_ERROR; - m_local_close_reason = "Status code is invalid"; - } else if (close::status::reserved(m_remote_close_code)) { - // TODO: shouldn't be able to get here now either - m_local_close_code = close::status::PROTOCOL_ERROR; - m_local_close_reason = "Status code is reserved"; - } else { - m_local_close_code = m_remote_close_code; - m_local_close_reason = m_remote_close_reason; - } - - // TODO: check whether we should cancel the current in flight write. - // if not canceled the close message will be sent as soon as the - // current write completes. - - + m_processor->prepare_close_frame(msg,code,reason); + write_message(msg); + + m_write_state = INTURRUPT; + } + + // send an acknowledgement close frame + void send_close_ack() { + // TODO: state should be OPEN + + // echo close value unless there is a good reason not to. + if (m_remote_close_code == close::status::NO_STATUS) { + m_local_close_code = close::status::NORMAL; + m_local_close_reason = ""; + } else if (m_remote_close_code == close::status::ABNORMAL_CLOSE) { + // TODO: can we possibly get here? This means send_close_ack was + // called after a connection ended without getting a close + // frame + throw "shouldn't be here"; + } else if (close::status::invalid(m_remote_close_code)) { + // TODO: shouldn't be able to get here now either + m_local_close_code = close::status::PROTOCOL_ERROR; + m_local_close_reason = "Status code is invalid"; + } else if (close::status::reserved(m_remote_close_code)) { + // TODO: shouldn't be able to get here now either + m_local_close_code = close::status::PROTOCOL_ERROR; + m_local_close_reason = "Status code is reserved"; + } else { + m_local_close_code = m_remote_close_code; + m_local_close_reason = m_remote_close_reason; + } + + // TODO: check whether we should cancel the current in flight write. + // if not canceled the close message will be sent as soon as the + // current write completes. + + // TODO: optimize control messages and handle case where endpoint is // out of messages message::data_ptr msg = get_control_message2(); @@ -492,13 +492,13 @@ class connection } msg->reset(frame::opcode::CLOSE); - m_processor->prepare_close_frame(msg, + m_processor->prepare_close_frame(msg, m_local_close_code, m_local_close_reason); - write_message(msg); - m_write_state = INTURRUPT; - } - + write_message(msg); + m_write_state = INTURRUPT; + } + void send_ping(const std::string& payload) { // TODO: optimize control messages and handle case where // endpoint is out of messages @@ -519,42 +519,42 @@ class connection write_message(control); } - void write_message(message::data_ptr msg) { - if (m_write_state == INTURRUPT) { - return; - } - - m_write_buffer += msg->get_payload().size(); - m_write_queue.push(msg); + void write_message(message::data_ptr msg) { + if (m_write_state == INTURRUPT) { + return; + } - write(); - } - - void write() { + m_write_buffer += msg->get_payload().size(); + m_write_queue.push(msg); + + write(); + } + + void write() { switch (m_write_state) { - case IDLE: - break; - case WRITING: - // already writing. write() will get called again by the write - // handler once it is ready. - return; - case INTURRUPT: - // clear the queue except for the last message - while (m_write_queue.size() > 1) { - m_write_buffer -= m_write_queue.front()->get_payload().size(); - m_write_queue.pop(); - } - break; - default: - // TODO: assert shouldn't be here - break; - } - - if (m_write_queue.size() > 0) { - if (m_write_state == IDLE) { - m_write_state = WRITING; - } - + case IDLE: + break; + case WRITING: + // already writing. write() will get called again by the write + // handler once it is ready. + return; + case INTURRUPT: + // clear the queue except for the last message + while (m_write_queue.size() > 1) { + m_write_buffer -= m_write_queue.front()->get_payload().size(); + m_write_queue.pop(); + } + break; + default: + // TODO: assert shouldn't be here + break; + } + + if (m_write_queue.size() > 0) { + if (m_write_state == IDLE) { + m_write_state = WRITING; + } + std::vector data; data.push_back(boost::asio::buffer(m_write_queue.front()->get_header())); @@ -562,74 +562,74 @@ class connection m_endpoint.alog().at(log::alevel::DEVEL) << "write header: " << to_hex(m_write_queue.front()->get_header()) << log::endl; - boost::asio::async_write( - socket_type::get_socket(), - data, - boost::bind( - &type::handle_write, - type::shared_from_this(), - boost::asio::placeholders::error - ) - ); - } else { - // if we are in an inturrupted state and had nothing else to write - // it is safe to terminate the connection. - if (m_write_state == INTURRUPT) { + boost::asio::async_write( + socket_type::get_socket(), + data, + boost::bind( + &type::handle_write, + type::shared_from_this(), + boost::asio::placeholders::error + ) + ); + } else { + // if we are in an inturrupted state and had nothing else to write + // it is safe to terminate the connection. + if (m_write_state == INTURRUPT) { m_endpoint.alog().at(log::alevel::DEBUG_CLOSE) << "Exit after inturrupt" << log::endl; - terminate(false); - } - } - } - - void handle_write(const boost::system::error_code& error) { + terminate(false); + } + } + } + + void handle_write(const boost::system::error_code& error) { if (error) { - if (error == boost::asio::error::operation_aborted) { - // previous write was aborted + if (error == boost::asio::error::operation_aborted) { + // previous write was aborted m_endpoint.alog().at(log::alevel::DEBUG_CLOSE) << "handle_write was called with operation_aborted error" << log::endl; - } else { - log_error("Error writing frame data",error); - terminate(false); - return; - } - } - - if (m_write_queue.size() == 0) { + } else { + log_error("Error writing frame data",error); + terminate(false); + return; + } + } + + if (m_write_queue.size() == 0) { m_endpoint.alog().at(log::alevel::DEBUG_CLOSE) << "handle_write called with empty queue" << log::endl; - return; - } - - m_write_buffer -= m_write_queue.front()->get_payload().size(); - m_write_queue.pop(); - - if (m_write_state == WRITING) { - m_write_state = IDLE; - } - - write(); - } - - // terminate cleans up a connection and removes it from the endpoint's - // connection list. - void terminate(bool failed_by_me) { - m_endpoint.alog().at(log::alevel::DEBUG_CLOSE) << "terminate called" << log::endl; - - if (m_state == session::state::CLOSED) { - // shouldn't be here - } - - // cancel the close timeout - m_timer.cancel(); - - - - // If this was a websocket connection notify the application handler - // about the close using either on_fail or on_close - if (role_type::get_version() != -1) { + return; + } + + m_write_buffer -= m_write_queue.front()->get_payload().size(); + m_write_queue.pop(); + + if (m_write_state == WRITING) { + m_write_state = IDLE; + } + + write(); + } + + // terminate cleans up a connection and removes it from the endpoint's + // connection list. + void terminate(bool failed_by_me) { + m_endpoint.alog().at(log::alevel::DEBUG_CLOSE) << "terminate called" << log::endl; + + if (m_state == session::state::CLOSED) { + // shouldn't be here + } + + // cancel the close timeout + m_timer.cancel(); + + + + // If this was a websocket connection notify the application handler + // about the close using either on_fail or on_close + if (role_type::get_version() != -1) { // TODO: note, calling shutdown on the ssl socket for an HTTP // connection seems to cause shutdown to block for a very long time. // NOT calling it for a websocket connection causes the connection // to time out. Behavior now is correct but I am not sure why. - m_dropped_by_me = socket_type::shutdown(); + m_dropped_by_me = socket_type::shutdown(); m_failed_by_me = failed_by_me; @@ -637,106 +637,106 @@ class connection m_state = session::state::CLOSED; if (old_state == session::state::CONNECTING) { - get_handler()->on_fail(type::shared_from_this()); - } else if (old_state == session::state::OPEN || - old_state == session::state::CLOSING) { - get_handler()->on_close(type::shared_from_this()); - } else { - // if we were already closed something is wrong - } - log_close_result(); - } - // finally remove this connection from the endpoint's list. This will - // remove the last shared pointer to the connection held by WS++. - m_endpoint.remove_connection(type::shared_from_this()); - } - - // this is called when an async asio call encounters an error - void log_error(std::string msg,const boost::system::error_code& e) { - m_endpoint.elog().at(log::elevel::ERROR) - << msg << "(" << e << ")" << log::endl; - } - - void log_close_result() { - m_endpoint.alog().at(log::alevel::DISCONNECT) - //<< "Disconnect " << (m_was_clean ? "Clean" : "Unclean") - << "Disconnect " - << " close local:[" << m_local_close_code - << (m_local_close_reason == "" ? "" : ","+m_local_close_reason) - << "] remote:[" << m_remote_close_code - << (m_remote_close_reason == "" ? "" : ","+m_remote_close_reason) << "]" - << log::endl; - } - - void fail_on_expire(const boost::system::error_code& error) { - if (error) { - if (error != boost::asio::error::operation_aborted) { - m_endpoint.elog().at(log::elevel::DEVEL) - << "fail_on_expire timer ended in unknown error" << log::endl; - terminate(false); - } - return; - } - m_endpoint.elog().at(log::elevel::DEVEL) - << "fail_on_expire timer expired" << log::endl; - terminate(true); - } - - boost::asio::streambuf& buffer() { - return m_buf; - } - - handler_ptr get_handler() { - return m_handler; - } + get_handler()->on_fail(type::shared_from_this()); + } else if (old_state == session::state::OPEN || + old_state == session::state::CLOSING) { + get_handler()->on_close(type::shared_from_this()); + } else { + // if we were already closed something is wrong + } + log_close_result(); + } + // finally remove this connection from the endpoint's list. This will + // remove the last shared pointer to the connection held by WS++. + m_endpoint.remove_connection(type::shared_from_this()); + } + + // this is called when an async asio call encounters an error + void log_error(std::string msg,const boost::system::error_code& e) { + m_endpoint.elog().at(log::elevel::ERROR) + << msg << "(" << e << ")" << log::endl; + } + + void log_close_result() { + m_endpoint.alog().at(log::alevel::DISCONNECT) + //<< "Disconnect " << (m_was_clean ? "Clean" : "Unclean") + << "Disconnect " + << " close local:[" << m_local_close_code + << (m_local_close_reason == "" ? "" : ","+m_local_close_reason) + << "] remote:[" << m_remote_close_code + << (m_remote_close_reason == "" ? "" : ","+m_remote_close_reason) << "]" + << log::endl; + } + + void fail_on_expire(const boost::system::error_code& error) { + if (error) { + if (error != boost::asio::error::operation_aborted) { + m_endpoint.elog().at(log::elevel::DEVEL) + << "fail_on_expire timer ended in unknown error" << log::endl; + terminate(false); + } + return; + } + m_endpoint.elog().at(log::elevel::DEVEL) + << "fail_on_expire timer expired" << log::endl; + terminate(true); + } + + boost::asio::streambuf& buffer() { + return m_buf; + } + + handler_ptr get_handler() { + return m_handler; + } protected: - endpoint_type& m_endpoint; - handler_ptr m_handler; - - // Network resources - boost::asio::streambuf m_buf; - boost::asio::deadline_timer m_timer; - - // WebSocket connection state - session::state::value m_state; - - // stuff that actually does the work - processor::ptr m_processor; - - // Write queue - std::queue m_write_queue; - uint64_t m_write_buffer; - write_state m_write_state; - - // Close state - close::status::value m_local_close_code; - std::string m_local_close_reason; - close::status::value m_remote_close_code; - std::string m_remote_close_reason; - bool m_closed_by_me; - bool m_failed_by_me; - bool m_dropped_by_me; - - // Read queue - read_state m_read_state; - message::control_ptr m_control_message; + endpoint_type& m_endpoint; + handler_ptr m_handler; + + // Network resources + boost::asio::streambuf m_buf; + boost::asio::deadline_timer m_timer; + + // WebSocket connection state + session::state::value m_state; + + // stuff that actually does the work + processor::ptr m_processor; + + // Write queue + std::queue m_write_queue; + uint64_t m_write_buffer; + write_state m_write_state; + + // Close state + close::status::value m_local_close_code; + std::string m_local_close_reason; + close::status::value m_remote_close_code; + std::string m_remote_close_reason; + bool m_closed_by_me; + bool m_failed_by_me; + bool m_dropped_by_me; + + // Read queue + read_state m_read_state; + message::control_ptr m_control_message; }; // connection related types that it and its policy classes need. template < - typename endpoint, - template class role, - template class socket> + typename endpoint, + template class role, + template class socket> struct connection_traits< connection > { - // type of the connection itself - typedef connection type; - - // types of the connection policies - typedef endpoint endpoint_type; - typedef role< type > role_type; - typedef socket< type > socket_type; + // type of the connection itself + typedef connection type; + + // types of the connection policies + typedef endpoint endpoint_type; + typedef role< type > role_type; + typedef socket< type > socket_type; }; - + } // namespace websocketpp #endif // WEBSOCKETPP_CONNECTION_HPP diff --git a/src/http/constants.hpp b/src/http/constants.hpp index bbdd76e79..c1a7ffa59 100644 --- a/src/http/constants.hpp +++ b/src/http/constants.hpp @@ -30,183 +30,183 @@ namespace websocketpp { namespace http { - namespace status_code { - enum value { - CONTINUE = 100, - SWITCHING_PROTOCOLS = 101, - - OK = 200, - CREATED = 201, - ACCEPTED = 202, - NON_AUTHORITATIVE_INFORMATION = 203, - NO_CONTENT = 204, - RESET_CONTENT = 205, - PARTIAL_CONTENT = 206, - - MULTIPLE_CHOICES = 300, - MOVED_PERMANENTLY = 301, - FOUND = 302, - SEE_OTHER = 303, - NOT_MODIFIED = 304, - USE_PROXY = 305, - TEMPORARY_REDIRECT = 307, - - BAD_REQUEST = 400, - UNAUTHORIZED = 401, - PAYMENT_REQUIRED = 402, - FORBIDDEN = 403, - NOT_FOUND = 404, - METHOD_NOT_ALLOWED = 405, - NOT_ACCEPTABLE = 406, - PROXY_AUTHENTICATION_REQUIRED = 407, - REQUEST_TIMEOUT = 408, - CONFLICT = 409, - GONE = 410, - LENGTH_REQUIRED = 411, - PRECONDITION_FAILED = 412, - REQUEST_ENTITY_TOO_LARGE = 413, - REQUEST_URI_TOO_LONG = 414, - UNSUPPORTED_MEDIA_TYPE = 415, - REQUEST_RANGE_NOT_SATISFIABLE = 416, - EXPECTATION_FAILED = 417, - IM_A_TEAPOT = 418, - UPGRADE_REQUIRED = 426, - PRECONDITION_REQUIRED = 428, - TOO_MANY_REQUESTS = 429, - REQUEST_HEADER_FIELDS_TOO_LARGE = 431, - - INTERNAL_SERVER_ERROR = 500, - NOT_IMPLIMENTED = 501, - BAD_GATEWAY = 502, - SERVICE_UNAVAILABLE = 503, - GATEWAY_TIMEOUT = 504, - HTTP_VERSION_NOT_SUPPORTED = 505, - NOT_EXTENDED = 510, - NETWORK_AUTHENTICATION_REQUIRED = 511 - }; - - // TODO: should this be inline? - inline std::string get_string(value c) { - switch (c) { - case CONTINUE: - return "Continue"; - case SWITCHING_PROTOCOLS: - return "Switching Protocols"; - case OK: - return "OK"; - case CREATED: - return "Created"; - case ACCEPTED: - return "Accepted"; - case NON_AUTHORITATIVE_INFORMATION: - return "Non Authoritative Information"; - case NO_CONTENT: - return "No Content"; - case RESET_CONTENT: - return "Reset Content"; - case PARTIAL_CONTENT: - return "Partial Content"; - case MULTIPLE_CHOICES: - return "Multiple Choices"; - case MOVED_PERMANENTLY: - return "Moved Permanently"; - case FOUND: - return "Found"; - case SEE_OTHER: - return "See Other"; - case NOT_MODIFIED: - return "Not Modified"; - case USE_PROXY: - return "Use Proxy"; - case TEMPORARY_REDIRECT: - return "Temporary Redirect"; - case BAD_REQUEST: - return "Bad Request"; - case UNAUTHORIZED: - return "Unauthorized"; - case FORBIDDEN: - return "Forbidden"; - case NOT_FOUND: - return "Not Found"; - case METHOD_NOT_ALLOWED: - return "Method Not Allowed"; - case NOT_ACCEPTABLE: - return "Not Acceptable"; - case PROXY_AUTHENTICATION_REQUIRED: - return "Proxy Authentication Required"; - case REQUEST_TIMEOUT: - return "Request Timeout"; - case CONFLICT: - return "Conflict"; - case GONE: - return "Gone"; - case LENGTH_REQUIRED: - return "Length Required"; - case PRECONDITION_FAILED: - return "Precondition Failed"; - case REQUEST_ENTITY_TOO_LARGE: - return "Request Entity Too Large"; - case REQUEST_URI_TOO_LONG: - return "Request-URI Too Long"; - case UNSUPPORTED_MEDIA_TYPE: - return "Unsupported Media Type"; - case REQUEST_RANGE_NOT_SATISFIABLE: - return "Requested Range Not Satisfiable"; - case EXPECTATION_FAILED: - return "Expectation Failed"; - case IM_A_TEAPOT: - return "I'm a teapot"; - case UPGRADE_REQUIRED: - return "Upgrade Required"; - case PRECONDITION_REQUIRED: - return "Precondition Required"; - case TOO_MANY_REQUESTS: - return "Too Many Requests"; - case REQUEST_HEADER_FIELDS_TOO_LARGE: - return "Request Header Fields Too Large"; - case INTERNAL_SERVER_ERROR: - return "Internal Server Error"; - case NOT_IMPLIMENTED: - return "Not Implimented"; - case BAD_GATEWAY: - return "Bad Gateway"; - case SERVICE_UNAVAILABLE: - return "Service Unavailable"; - case GATEWAY_TIMEOUT: - return "Gateway Timeout"; - case HTTP_VERSION_NOT_SUPPORTED: - return "HTTP Version Not Supported"; - case NOT_EXTENDED: - return "Not Extended"; - case NETWORK_AUTHENTICATION_REQUIRED: - return "Network Authentication Required"; - default: - return "Unknown"; - } - } - } - - class exception : public std::exception { - public: - exception(const std::string& log_msg, - status_code::value error_code, - const std::string& error_msg = "", - const std::string& body = "") - : m_msg(log_msg), - m_error_code(error_code), - m_error_msg(error_msg), - m_body(body) {} - ~exception() throw() {} - - virtual const char* what() const throw() { - return m_msg.c_str(); - } - - std::string m_msg; - status_code::value m_error_code; - std::string m_error_msg; - std::string m_body; - }; + namespace status_code { + enum value { + CONTINUE = 100, + SWITCHING_PROTOCOLS = 101, + + OK = 200, + CREATED = 201, + ACCEPTED = 202, + NON_AUTHORITATIVE_INFORMATION = 203, + NO_CONTENT = 204, + RESET_CONTENT = 205, + PARTIAL_CONTENT = 206, + + MULTIPLE_CHOICES = 300, + MOVED_PERMANENTLY = 301, + FOUND = 302, + SEE_OTHER = 303, + NOT_MODIFIED = 304, + USE_PROXY = 305, + TEMPORARY_REDIRECT = 307, + + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + PAYMENT_REQUIRED = 402, + FORBIDDEN = 403, + NOT_FOUND = 404, + METHOD_NOT_ALLOWED = 405, + NOT_ACCEPTABLE = 406, + PROXY_AUTHENTICATION_REQUIRED = 407, + REQUEST_TIMEOUT = 408, + CONFLICT = 409, + GONE = 410, + LENGTH_REQUIRED = 411, + PRECONDITION_FAILED = 412, + REQUEST_ENTITY_TOO_LARGE = 413, + REQUEST_URI_TOO_LONG = 414, + UNSUPPORTED_MEDIA_TYPE = 415, + REQUEST_RANGE_NOT_SATISFIABLE = 416, + EXPECTATION_FAILED = 417, + IM_A_TEAPOT = 418, + UPGRADE_REQUIRED = 426, + PRECONDITION_REQUIRED = 428, + TOO_MANY_REQUESTS = 429, + REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + + INTERNAL_SERVER_ERROR = 500, + NOT_IMPLIMENTED = 501, + BAD_GATEWAY = 502, + SERVICE_UNAVAILABLE = 503, + GATEWAY_TIMEOUT = 504, + HTTP_VERSION_NOT_SUPPORTED = 505, + NOT_EXTENDED = 510, + NETWORK_AUTHENTICATION_REQUIRED = 511 + }; + + // TODO: should this be inline? + inline std::string get_string(value c) { + switch (c) { + case CONTINUE: + return "Continue"; + case SWITCHING_PROTOCOLS: + return "Switching Protocols"; + case OK: + return "OK"; + case CREATED: + return "Created"; + case ACCEPTED: + return "Accepted"; + case NON_AUTHORITATIVE_INFORMATION: + return "Non Authoritative Information"; + case NO_CONTENT: + return "No Content"; + case RESET_CONTENT: + return "Reset Content"; + case PARTIAL_CONTENT: + return "Partial Content"; + case MULTIPLE_CHOICES: + return "Multiple Choices"; + case MOVED_PERMANENTLY: + return "Moved Permanently"; + case FOUND: + return "Found"; + case SEE_OTHER: + return "See Other"; + case NOT_MODIFIED: + return "Not Modified"; + case USE_PROXY: + return "Use Proxy"; + case TEMPORARY_REDIRECT: + return "Temporary Redirect"; + case BAD_REQUEST: + return "Bad Request"; + case UNAUTHORIZED: + return "Unauthorized"; + case FORBIDDEN: + return "Forbidden"; + case NOT_FOUND: + return "Not Found"; + case METHOD_NOT_ALLOWED: + return "Method Not Allowed"; + case NOT_ACCEPTABLE: + return "Not Acceptable"; + case PROXY_AUTHENTICATION_REQUIRED: + return "Proxy Authentication Required"; + case REQUEST_TIMEOUT: + return "Request Timeout"; + case CONFLICT: + return "Conflict"; + case GONE: + return "Gone"; + case LENGTH_REQUIRED: + return "Length Required"; + case PRECONDITION_FAILED: + return "Precondition Failed"; + case REQUEST_ENTITY_TOO_LARGE: + return "Request Entity Too Large"; + case REQUEST_URI_TOO_LONG: + return "Request-URI Too Long"; + case UNSUPPORTED_MEDIA_TYPE: + return "Unsupported Media Type"; + case REQUEST_RANGE_NOT_SATISFIABLE: + return "Requested Range Not Satisfiable"; + case EXPECTATION_FAILED: + return "Expectation Failed"; + case IM_A_TEAPOT: + return "I'm a teapot"; + case UPGRADE_REQUIRED: + return "Upgrade Required"; + case PRECONDITION_REQUIRED: + return "Precondition Required"; + case TOO_MANY_REQUESTS: + return "Too Many Requests"; + case REQUEST_HEADER_FIELDS_TOO_LARGE: + return "Request Header Fields Too Large"; + case INTERNAL_SERVER_ERROR: + return "Internal Server Error"; + case NOT_IMPLIMENTED: + return "Not Implimented"; + case BAD_GATEWAY: + return "Bad Gateway"; + case SERVICE_UNAVAILABLE: + return "Service Unavailable"; + case GATEWAY_TIMEOUT: + return "Gateway Timeout"; + case HTTP_VERSION_NOT_SUPPORTED: + return "HTTP Version Not Supported"; + case NOT_EXTENDED: + return "Not Extended"; + case NETWORK_AUTHENTICATION_REQUIRED: + return "Network Authentication Required"; + default: + return "Unknown"; + } + } + } + + class exception : public std::exception { + public: + exception(const std::string& log_msg, + status_code::value error_code, + const std::string& error_msg = "", + const std::string& body = "") + : m_msg(log_msg), + m_error_code(error_code), + m_error_msg(error_msg), + m_body(body) {} + ~exception() throw() {} + + virtual const char* what() const throw() { + return m_msg.c_str(); + } + + std::string m_msg; + status_code::value m_error_code; + std::string m_error_msg; + std::string m_body; + }; } } diff --git a/src/http/parser.hpp b/src/http/parser.hpp index 6ab143e00..b71b9381f 100644 --- a/src/http/parser.hpp +++ b/src/http/parser.hpp @@ -39,243 +39,243 @@ namespace websocketpp { namespace http { namespace parser { - namespace state { - enum value { - METHOD, - RESOURCE, - VERSION, - HEADERS - }; - } + namespace state { + enum value { + METHOD, + RESOURCE, + VERSION, + HEADERS + }; + } typedef std::map header_list; class parser { public: - // consumes bytes from the stream and returns true if enough bytes have - // been read - bool consume (std::istream& s) { - throw "No Implimented"; - } - - void set_version(const std::string& version) { - // TODO: validation? - m_version = version; - } - - const std::string& version() const { - return m_version; - } - - std::string header(const std::string& key) const { - header_list::const_iterator h = m_headers.find(key); - - if (h == m_headers.end()) { - return ""; - } else { - return h->second; - } - } - - // multiple calls to add header will result in values aggregating. - // use replace_header if you do not want this behavior. - void add_header(const std::string &key,const std::string &val) { - // TODO: prevent use of reserved headers? - if (this->header(key) == "") { - m_headers[key] = val; - } else { - m_headers[key] += ", " + val; - } - } - - void replace_header(const std::string &key,const std::string &val) { - m_headers[key] = val; - } - - void remove_header(const std::string &key) { - m_headers.erase(key); - } + // consumes bytes from the stream and returns true if enough bytes have + // been read + bool consume (std::istream& s) { + throw "No Implimented"; + } + + void set_version(const std::string& version) { + // TODO: validation? + m_version = version; + } + + const std::string& version() const { + return m_version; + } + + std::string header(const std::string& key) const { + header_list::const_iterator h = m_headers.find(key); + + if (h == m_headers.end()) { + return ""; + } else { + return h->second; + } + } + + // multiple calls to add header will result in values aggregating. + // use replace_header if you do not want this behavior. + void add_header(const std::string &key,const std::string &val) { + // TODO: prevent use of reserved headers? + if (this->header(key) == "") { + m_headers[key] = val; + } else { + m_headers[key] += ", " + val; + } + } + + void replace_header(const std::string &key,const std::string &val) { + m_headers[key] = val; + } + + void remove_header(const std::string &key) { + m_headers.erase(key); + } protected: - bool parse_headers(std::istream& s) { - std::string header; - std::string::size_type end; - - // get headers - while (std::getline(s, header) && header != "\r") { - if (header[header.size()-1] != '\r') { - continue; // ignore malformed header lines? - } else { - header.erase(header.end()-1); - } - - end = header.find(": ",0); - - if (end != std::string::npos) { - add_header(header.substr(0,end),header.substr(end+2)); - } - } - - return true; - } - - std::string raw_headers() { - std::stringstream raw; - - header_list::iterator it; - for (it = m_headers.begin(); it != m_headers.end(); it++) { - raw << it->first << ": " << it->second << "\r\n"; - } - - return raw.str(); - } - + bool parse_headers(std::istream& s) { + std::string header; + std::string::size_type end; + + // get headers + while (std::getline(s, header) && header != "\r") { + if (header[header.size()-1] != '\r') { + continue; // ignore malformed header lines? + } else { + header.erase(header.end()-1); + } + + end = header.find(": ",0); + + if (end != std::string::npos) { + add_header(header.substr(0,end),header.substr(end+2)); + } + } + + return true; + } + + std::string raw_headers() { + std::stringstream raw; + + header_list::iterator it; + for (it = m_headers.begin(); it != m_headers.end(); it++) { + raw << it->first << ": " << it->second << "\r\n"; + } + + return raw.str(); + } + private: - std::string m_version; - header_list m_headers; + std::string m_version; + header_list m_headers; }; class request : public parser { -public: - // parse a complete header (ie \r\n\r\n MUST be in the input stream) - bool parse_complete(std::istream& s) { - std::string request; - - // get status line - std::getline(s, request); - - if (request[request.size()-1] == '\r') { - request.erase(request.end()-1); - - std::stringstream ss(request); - std::string val; - - ss >> val; - set_method(val); - - ss >> val; - set_uri(val); - - ss >> val; - set_version(val); - } else { - return false; - } - - return parse_headers(s); - } - - // TODO: validation. Make sure all required fields have been set? - std::string raw() { - std::stringstream raw; - - raw << m_method << " " << m_uri << " " << version() << "\r\n"; - raw << raw_headers() << "\r\n"; - - return raw.str(); - } - - void set_method(const std::string& method) { - // TODO: validation? - m_method = method; - } - - const std::string& method() const { - return m_method; - } - - void set_uri(const std::string& uri) { - // TODO: validation? - m_uri = uri; - } - - const std::string& uri() const { - return m_uri; - } - +public: + // parse a complete header (ie \r\n\r\n MUST be in the input stream) + bool parse_complete(std::istream& s) { + std::string request; + + // get status line + std::getline(s, request); + + if (request[request.size()-1] == '\r') { + request.erase(request.end()-1); + + std::stringstream ss(request); + std::string val; + + ss >> val; + set_method(val); + + ss >> val; + set_uri(val); + + ss >> val; + set_version(val); + } else { + return false; + } + + return parse_headers(s); + } + + // TODO: validation. Make sure all required fields have been set? + std::string raw() { + std::stringstream raw; + + raw << m_method << " " << m_uri << " " << version() << "\r\n"; + raw << raw_headers() << "\r\n"; + + return raw.str(); + } + + void set_method(const std::string& method) { + // TODO: validation? + m_method = method; + } + + const std::string& method() const { + return m_method; + } + + void set_uri(const std::string& uri) { + // TODO: validation? + m_uri = uri; + } + + const std::string& uri() const { + return m_uri; + } + private: - std::string m_method; - std::string m_uri; + std::string m_method; + std::string m_uri; }; class response : public parser { public: - // parse a complete header (ie \r\n\r\n MUST be in the input stream) - bool parse_complete(std::istream& s) { - std::string response; - - // get status line - std::getline(s, response); - - if (response[response.size()-1] == '\r') { - response.erase(response.end()-1); - - std::stringstream ss(response); - std::string str_val; - int int_val; - char char_val[256]; - - ss >> str_val; - set_version(str_val); - - ss >> int_val; - ss.getline(char_val,256); - set_status(status_code::value(int_val),std::string(char_val)); - } else { - return false; - } - - return parse_headers(s); - } - - // TODO: validation. Make sure all required fields have been set? - std::string raw() { - std::stringstream raw; - - raw << version() << " " << m_status_code << " " << m_status_msg << "\r\n"; - raw << raw_headers() << "\r\n"; - - raw << m_body; - - return raw.str(); - } - - void set_status(status_code::value code) { - // TODO: validation? - m_status_code = code; - m_status_msg = get_string(code); - } - - void set_status(status_code::value code, const std::string& msg) { - // TODO: validation? - m_status_code = code; - m_status_msg = msg; - } - - void set_body(const std::string& value) { - if (value.size() == 0) { - remove_header("Content-Length"); - m_body = ""; - return; - } - - std::stringstream foo; - foo << value.size(); - replace_header("Content-Length", foo.str()); - m_body = value; - } - - status_code::value get_status_code() const { - return m_status_code; - } - - const std::string& get_status_msg() const { - return m_status_msg; - } + // parse a complete header (ie \r\n\r\n MUST be in the input stream) + bool parse_complete(std::istream& s) { + std::string response; + + // get status line + std::getline(s, response); + + if (response[response.size()-1] == '\r') { + response.erase(response.end()-1); + + std::stringstream ss(response); + std::string str_val; + int int_val; + char char_val[256]; + + ss >> str_val; + set_version(str_val); + + ss >> int_val; + ss.getline(char_val,256); + set_status(status_code::value(int_val),std::string(char_val)); + } else { + return false; + } + + return parse_headers(s); + } + + // TODO: validation. Make sure all required fields have been set? + std::string raw() { + std::stringstream raw; + + raw << version() << " " << m_status_code << " " << m_status_msg << "\r\n"; + raw << raw_headers() << "\r\n"; + + raw << m_body; + + return raw.str(); + } + + void set_status(status_code::value code) { + // TODO: validation? + m_status_code = code; + m_status_msg = get_string(code); + } + + void set_status(status_code::value code, const std::string& msg) { + // TODO: validation? + m_status_code = code; + m_status_msg = msg; + } + + void set_body(const std::string& value) { + if (value.size() == 0) { + remove_header("Content-Length"); + m_body = ""; + return; + } + + std::stringstream foo; + foo << value.size(); + replace_header("Content-Length", foo.str()); + m_body = value; + } + + status_code::value get_status_code() const { + return m_status_code; + } + + const std::string& get_status_msg() const { + return m_status_msg; + } private: - status_code::value m_status_code; - std::string m_status_msg; - std::string m_body; + status_code::value m_status_code; + std::string m_status_msg; + std::string m_body; }; } diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index 4b5cc7f89..49491c3e8 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -37,127 +37,125 @@ namespace websocketpp { namespace log { namespace alevel { - typedef uint16_t value; - - static const value OFF = 0x0; - - // A single line on connect with connecting ip, websocket version, - // request resource, user agent, and the response code. - static const value CONNECT = 0x1; - // A single line on disconnect with wasClean status and local and remote - // close codes and reasons. - static const value DISCONNECT = 0x2; - // A single line on incoming and outgoing control messages. - static const value CONTROL = 0x4; - // A single line on incoming and outgoing frames with full frame headers - static const value FRAME_HEADER = 0x10; - // Adds payloads to frame logs. Note these can be long! - static const value FRAME_PAYLOAD = 0x20; - // A single line on incoming and outgoing messages with metadata about type, - // length, etc - static const value MESSAGE_HEADER = 0x40; - // Adds payloads to message logs. Note these can be long! - static const value MESSAGE_PAYLOAD = 0x80; - - - // DEBUG values - static const value DEBUG_HANDSHAKE = 0x8000; - static const value DEBUG_CLOSE = 0x4000; - static const value DEVEL = 0x2000; - - static const value ALL = 0xFFFF; + typedef uint16_t value; + + static const value OFF = 0x0; + + // A single line on connect with connecting ip, websocket version, + // request resource, user agent, and the response code. + static const value CONNECT = 0x1; + // A single line on disconnect with wasClean status and local and remote + // close codes and reasons. + static const value DISCONNECT = 0x2; + // A single line on incoming and outgoing control messages. + static const value CONTROL = 0x4; + // A single line on incoming and outgoing frames with full frame headers + static const value FRAME_HEADER = 0x10; + // Adds payloads to frame logs. Note these can be long! + static const value FRAME_PAYLOAD = 0x20; + // A single line on incoming and outgoing messages with metadata about type, + // length, etc + static const value MESSAGE_HEADER = 0x40; + // Adds payloads to message logs. Note these can be long! + static const value MESSAGE_PAYLOAD = 0x80; + + + // DEBUG values + static const value DEBUG_HANDSHAKE = 0x8000; + static const value DEBUG_CLOSE = 0x4000; + static const value DEVEL = 0x2000; + + static const value ALL = 0xFFFF; } namespace elevel { - typedef uint16_t value; - - static const value OFF = 0x0; - - static const value DEVEL = 0x1; // debugging - static const value LIBRARY = 0x2; // library usage exceptions - static const value INFO = 0x4; - static const value WARN = 0x8; - static const value ERROR = 0x10; - static const value FATAL = 0x20; - - static const value ALL = 0xFFFF; + typedef uint16_t value; + + static const value OFF = 0x0; + + static const value DEVEL = 0x1; // debugging + static const value LIBRARY = 0x2; // library usage exceptions + static const value INFO = 0x4; + static const value WARN = 0x8; + static const value ERROR = 0x10; + static const value FATAL = 0x20; + + static const value ALL = 0xFFFF; } - + template class logger { public: - template - logger& operator<<(T a) { - if (test_level(m_write_level)) { - m_oss << a; - } - return *this; - } - - logger& operator<<(logger& (*f)(logger&)) { - return f(*this); - } - - bool test_level(level_type l) { - return (m_level & l) != 0; - } - - void set_level(level_type l) { - m_level |= l; - } - - void set_levels(level_type l1, level_type l2) { - level_type i = l1; - - while (i <= l2) { - set_level(i); - i *= 2; - } - } - - void unset_level(level_type l) { - m_level &= ~l; - } - - void set_prefix(const std::string& prefix) { - if (prefix == "") { - m_prefix = prefix; - } else { - m_prefix = prefix + " "; - } - } - - logger& print() { - if (test_level(m_write_level)) { - std::cout << m_prefix << - boost::posix_time::to_iso_extended_string( - boost::posix_time::second_clock::local_time() - ) << " [" << m_write_level << "] " << m_oss.str() << std::endl; - m_oss.str(""); - } - - return *this; - } - - logger& at(level_type l) { - m_write_level = l; - return *this; - } + template + logger& operator<<(T a) { + if (test_level(m_write_level)) { + m_oss << a; + } + return *this; + } + + logger& operator<<(logger& (*f)(logger&)) { + return f(*this); + } + + bool test_level(level_type l) { + return (m_level & l) != 0; + } + + void set_level(level_type l) { + m_level |= l; + } + + void set_levels(level_type l1, level_type l2) { + level_type i = l1; + + while (i <= l2) { + set_level(i); + i *= 2; + } + } + + void unset_level(level_type l) { + m_level &= ~l; + } + + void set_prefix(const std::string& prefix) { + if (prefix == "") { + m_prefix = prefix; + } else { + m_prefix = prefix + " "; + } + } + + logger& print() { + if (test_level(m_write_level)) { + std::cout << m_prefix << + boost::posix_time::to_iso_extended_string( + boost::posix_time::second_clock::local_time() + ) << " [" << m_write_level << "] " << m_oss.str() << std::endl; + m_oss.str(""); + } + + return *this; + } + + logger& at(level_type l) { + m_write_level = l; + return *this; + } private: - std::ostringstream m_oss; - level_type m_write_level; - level_type m_level; - std::string m_prefix; + std::ostringstream m_oss; + level_type m_write_level; + level_type m_level; + std::string m_prefix; }; template logger& endl(logger& out) { - return out.print(); + return out.print(); } - - } } diff --git a/src/messages/control.hpp b/src/messages/control.hpp index bd49f1633..a3cc9d529 100644 --- a/src/messages/control.hpp +++ b/src/messages/control.hpp @@ -44,19 +44,19 @@ class control { m_payload.reserve(PAYLOAD_SIZE_INIT); } - frame::opcode::value get_opcode() const { + frame::opcode::value get_opcode() const { return m_opcode; }; - - const std::string& get_payload() const { - return m_payload; - } - + + const std::string& get_payload() const { + return m_payload; + } + uint64_t process_payload(std::istream& input,uint64_t size) { char c; const uint64_t new_size = m_payload.size() + size; uint64_t i; - + if (new_size > PAYLOAD_SIZE_MAX) { throw processor::exception("Message payload was too large.",processor::error::MESSAGE_TOO_BIG); } @@ -73,9 +73,9 @@ class control { if (input.good()) { // process c if (m_masking_index >= 0) { - c = c ^ m_masking_key[(m_masking_index++)%4]; - } - + c = c ^ m_masking_key[(m_masking_index++)%4]; + } + // add c to payload m_payload.push_back(c); } else if (input.eof()) { @@ -90,91 +90,91 @@ class control { return i; } - void complete() { - if (m_opcode == frame::opcode::CLOSE) { - if (m_payload.size() == 1) { - throw processor::exception("Single byte close code",processor::error::PROTOCOL_VIOLATION); - } else if (m_payload.size() >= 2) { - close::status::value code = close::status::value(get_raw_close_code()); - - if (close::status::invalid(code)) { - throw processor::exception("Close code is not allowed on the wire.",processor::error::PROTOCOL_VIOLATION); - } else if (close::status::reserved(code)) { - throw processor::exception("Close code is reserved.",processor::error::PROTOCOL_VIOLATION); - } - - } - if (m_payload.size() > 2) { - if (!m_validator.decode(m_payload.begin()+2,m_payload.end())) { - throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION); - } - if (!m_validator.complete()) { - throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION); - } - } - } - } - + void complete() { + if (m_opcode == frame::opcode::CLOSE) { + if (m_payload.size() == 1) { + throw processor::exception("Single byte close code",processor::error::PROTOCOL_VIOLATION); + } else if (m_payload.size() >= 2) { + close::status::value code = close::status::value(get_raw_close_code()); + + if (close::status::invalid(code)) { + throw processor::exception("Close code is not allowed on the wire.",processor::error::PROTOCOL_VIOLATION); + } else if (close::status::reserved(code)) { + throw processor::exception("Close code is reserved.",processor::error::PROTOCOL_VIOLATION); + } + + } + if (m_payload.size() > 2) { + if (!m_validator.decode(m_payload.begin()+2,m_payload.end())) { + throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION); + } + if (!m_validator.complete()) { + throw processor::exception("Invalid UTF8",processor::error::PAYLOAD_VIOLATION); + } + } + } + } + void reset(frame::opcode::value opcode, uint32_t masking_key) { m_opcode = opcode; set_masking_key(masking_key); m_payload.resize(0); - m_validator.reset(); + m_validator.reset(); + } + + close::status::value get_close_code() const { + if (m_payload.size() == 0) { + return close::status::NO_STATUS; + } else { + return close::status::value(get_raw_close_code()); + } + } + + std::string get_close_reason() const { + if (m_payload.size() > 2) { + return m_payload.substr(2); + } else { + return std::string(); + } + } + + void set_masking_key(int32_t key) { + *reinterpret_cast(m_masking_key) = key; + m_masking_index = (key == 0 ? -1 : 0); } - - close::status::value get_close_code() const { - if (m_payload.size() == 0) { - return close::status::NO_STATUS; - } else { - return close::status::value(get_raw_close_code()); - } - } - - std::string get_close_reason() const { - if (m_payload.size() > 2) { - return m_payload.substr(2); - } else { - return std::string(); - } - } - - void set_masking_key(int32_t key) { - *reinterpret_cast(m_masking_key) = key; - m_masking_index = (key == 0 ? -1 : 0); - } private: - uint16_t get_raw_close_code() const { - if (m_payload.size() <= 1) { - throw processor::exception("get_raw_close_code called with invalid size",processor::error::FATAL_ERROR); - } - - char val[2]; - - val[0] = m_payload[0]; - val[1] = m_payload[1]; - - return ntohs(*(reinterpret_cast(&val[0]))); - } - + uint16_t get_raw_close_code() const { + if (m_payload.size() <= 1) { + throw processor::exception("get_raw_close_code called with invalid size",processor::error::FATAL_ERROR); + } + + char val[2]; + + val[0] = m_payload[0]; + val[1] = m_payload[1]; + + return ntohs(*(reinterpret_cast(&val[0]))); + } + static const uint64_t PAYLOAD_SIZE_INIT = 128; // 128B static const uint64_t PAYLOAD_SIZE_MAX = 128; // 128B - // Message state - frame::opcode::value m_opcode; - - // UTF8 validation state - utf8_validator::validator m_validator; - - // Masking state - unsigned char m_masking_key[4]; + // Message state + frame::opcode::value m_opcode; + + // UTF8 validation state + utf8_validator::validator m_validator; + + // Masking state + unsigned char m_masking_key[4]; int m_masking_index; - - // Message payload - std::string m_payload; + + // Message payload + std::string m_payload; }; typedef boost::shared_ptr control_ptr; - + } // namespace message } // namespace websocketpp diff --git a/src/messages/data.cpp b/src/messages/data.cpp index f6fb9cdf6..252dcf804 100644 --- a/src/messages/data.cpp +++ b/src/messages/data.cpp @@ -39,14 +39,14 @@ data::data(data::pool_ptr p, size_t s) : m_prepared(false),m_index(s),m_ref_coun websocketpp::frame::opcode::value data::get_opcode() const { return m_opcode; } - + const std::string& data::get_payload() const { return m_payload; } const std::string& data::get_header() const { return m_header; } - + uint64_t data::process_payload(std::istream& input,uint64_t size) { unsigned char c; const uint64_t new_size = m_payload.size() + size; @@ -84,7 +84,7 @@ uint64_t data::process_payload(std::istream& input,uint64_t size) { // successfully read all bytes return i; } - + void data::process_character(unsigned char c) { if (m_masking_index >= 0) { c = c ^ m_masking_key[m_masking_index]; @@ -108,7 +108,7 @@ void data::reset(frame::opcode::value opcode) { m_validator.reset(); m_prepared = false; } - + void data::complete() { if (m_opcode == frame::opcode::TEXT) { if (!m_validator.complete()) { diff --git a/src/messages/data.hpp b/src/messages/data.hpp index b131e066d..4b7426199 100644 --- a/src/messages/data.hpp +++ b/src/messages/data.hpp @@ -151,11 +151,11 @@ class data { typedef pool::ptr pool_ptr; data(pool_ptr p, size_t s); - + void reset(frame::opcode::value opcode); frame::opcode::value get_opcode() const; - const std::string& get_payload() const; + const std::string& get_payload() const; const std::string& get_header() const; // ##reading## @@ -167,8 +167,8 @@ class data { // throws a processor::exception if the message is too big, there is a fatal // istream read error, or invalid UTF8 data is read for a text message uint64_t process_payload(std::istream& input,uint64_t size); - void process_character(unsigned char c); - void complete(); + void process_character(unsigned char c); + void complete(); void validate_payload(); // ##writing## @@ -183,7 +183,7 @@ class data { void set_prepared(bool b); bool get_prepared() const; void mask(); - + // pool management interface void set_live(); size_t get_index() const; @@ -216,19 +216,19 @@ class data { } } - // Message state - frame::opcode::value m_opcode; - - // UTF8 validation state - utf8_validator::validator m_validator; - - // Masking state - unsigned char m_masking_key[4]; + // Message state + frame::opcode::value m_opcode; + + // UTF8 validation state + utf8_validator::validator m_validator; + + // Masking state + unsigned char m_masking_key[4]; // m_masking_index can take on index_value m_masking_index; std::string m_header; - std::string m_payload; + std::string m_payload; bool m_prepared; @@ -240,7 +240,7 @@ class data { }; typedef boost::intrusive_ptr data_ptr; - + } // namespace message } // namespace websocketpp diff --git a/src/network_utilities.cpp b/src/network_utilities.cpp index 1994ab931..792551d5e 100644 --- a/src/network_utilities.cpp +++ b/src/network_utilities.cpp @@ -28,57 +28,57 @@ #include "network_utilities.hpp" uint64_t htonll(uint64_t src) { - static int typ = TYP_INIT; - unsigned char c; - union { - uint64_t ull; - unsigned char c[8]; - } x; - if (typ == TYP_INIT) { - x.ull = 0x01; - typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE; - } - if (typ == TYP_BIGE) - return src; - x.ull = src; - c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; - c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; - c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; - c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; - return x.ull; + static int typ = TYP_INIT; + unsigned char c; + union { + uint64_t ull; + unsigned char c[8]; + } x; + if (typ == TYP_INIT) { + x.ull = 0x01; + typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE; + } + if (typ == TYP_BIGE) + return src; + x.ull = src; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + return x.ull; } uint64_t ntohll(uint64_t src) { - return htonll(src); + return htonll(src); } std::string lookup_ws_close_status_string(uint16_t code) { - switch (code) { - case 1000: - return "Normal closure"; - case 1001: - return "Going away"; - case 1002: - return "Protocol error"; - case 1003: - return "Unacceptable data"; - case 1004: - return "Reserved"; - case 1005: - return "No status received"; - case 1006: - return "Abnormal closure"; - case 1007: - return "Invalid message data"; - case 1008: - return "Policy Violation"; - case 1009: - return "Message too large"; - case 1010: - return "Missing required extensions"; - default: - return "Unknown"; - } + switch (code) { + case 1000: + return "Normal closure"; + case 1001: + return "Going away"; + case 1002: + return "Protocol error"; + case 1003: + return "Unacceptable data"; + case 1004: + return "Reserved"; + case 1005: + return "No status received"; + case 1006: + return "Abnormal closure"; + case 1007: + return "Invalid message data"; + case 1008: + return "Policy Violation"; + case 1009: + return "Message too large"; + case 1010: + return "Missing required extensions"; + default: + return "Unknown"; + } } std::string to_hex(const std::string& input) { diff --git a/src/processors/hybi.hpp b/src/processors/hybi.hpp index 920dbb1fc..fb938af11 100644 --- a/src/processors/hybi.hpp +++ b/src/processors/hybi.hpp @@ -41,11 +41,11 @@ namespace websocketpp { namespace processor { namespace hybi_state { - enum value { - READ_HEADER = 0, - READ_PAYLOAD = 1, - READY = 2 - }; + enum value { + READ_HEADER = 0, + READ_PAYLOAD = 1, + READY = 2 + }; } /* @@ -104,163 +104,163 @@ std::list< std::pair< std::string,std::string > > template class hybi : public processor_base { public: - hybi(connection_type &connection) + hybi(connection_type &connection) : m_connection(connection), m_write_frame(connection) { - reset(); - } - - void validate_handshake(const http::parser::request& request) const { - std::stringstream err; - std::string h; - - if (request.method() != "GET") { - err << "Websocket handshake has invalid method: " - << request.method(); - - throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); - } - - // TODO: allow versions greater than 1.1 - if (request.version() != "HTTP/1.1") { - err << "Websocket handshake has invalid HTTP version: " - << request.method(); - - throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); - } - - // verify the presence of required headers - if (request.header("Host") == "") { - throw(http::exception("Required Host header is missing",http::status_code::BAD_REQUEST)); - } - - h = request.header("Upgrade"); - if (h == "") { - throw(http::exception("Required Upgrade header is missing",http::status_code::BAD_REQUEST)); - } else if (!boost::ifind_first(h,"websocket")) { - err << "Upgrade header \"" << h << "\", does not contain required token \"websocket\""; - throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); - } - - h = request.header("Connection"); - if (h == "") { - throw(http::exception("Required Connection header is missing",http::status_code::BAD_REQUEST)); - } else if (!boost::ifind_first(h,"upgrade")) { - err << "Connection header, \"" << h - << "\", does not contain required token \"upgrade\""; - throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); - } - - if (request.header("Sec-WebSocket-Key") == "") { - throw(http::exception("Required Sec-WebSocket-Key header is missing",http::status_code::BAD_REQUEST)); - } - - h = request.header("Sec-WebSocket-Version"); - if (h == "") { - throw(http::exception("Required Sec-WebSocket-Version header is missing",http::status_code::BAD_REQUEST)); - } else { - int version = atoi(h.c_str()); - - if (version != 7 && version != 8 && version != 13) { - err << "This processor doesn't support WebSocket protocol version " - << version; - throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); - } - } - } - - std::string get_origin(const http::parser::request& request) const { - std::string h = request.header("Sec-WebSocket-Version"); - int version = atoi(h.c_str()); - - if (version == 13) { - return request.header("Origin"); - } else if (version == 7 || version == 8) { - return request.header("Sec-WebSocket-Origin"); - } else { - throw(http::exception("Could not determine origin header. Check Sec-WebSocket-Version header",http::status_code::BAD_REQUEST)); - } - } - - uri_ptr get_uri(const http::parser::request& request) const { - std::string h = request.header("Host"); - - size_t last_colon = h.rfind(":"); + reset(); + } + + void validate_handshake(const http::parser::request& request) const { + std::stringstream err; + std::string h; + + if (request.method() != "GET") { + err << "Websocket handshake has invalid method: " + << request.method(); + + throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); + } + + // TODO: allow versions greater than 1.1 + if (request.version() != "HTTP/1.1") { + err << "Websocket handshake has invalid HTTP version: " + << request.method(); + + throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); + } + + // verify the presence of required headers + if (request.header("Host") == "") { + throw(http::exception("Required Host header is missing",http::status_code::BAD_REQUEST)); + } + + h = request.header("Upgrade"); + if (h == "") { + throw(http::exception("Required Upgrade header is missing",http::status_code::BAD_REQUEST)); + } else if (!boost::ifind_first(h,"websocket")) { + err << "Upgrade header \"" << h << "\", does not contain required token \"websocket\""; + throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); + } + + h = request.header("Connection"); + if (h == "") { + throw(http::exception("Required Connection header is missing",http::status_code::BAD_REQUEST)); + } else if (!boost::ifind_first(h,"upgrade")) { + err << "Connection header, \"" << h + << "\", does not contain required token \"upgrade\""; + throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); + } + + if (request.header("Sec-WebSocket-Key") == "") { + throw(http::exception("Required Sec-WebSocket-Key header is missing",http::status_code::BAD_REQUEST)); + } + + h = request.header("Sec-WebSocket-Version"); + if (h == "") { + throw(http::exception("Required Sec-WebSocket-Version header is missing",http::status_code::BAD_REQUEST)); + } else { + int version = atoi(h.c_str()); + + if (version != 7 && version != 8 && version != 13) { + err << "This processor doesn't support WebSocket protocol version " + << version; + throw(http::exception(err.str(),http::status_code::BAD_REQUEST)); + } + } + } + + std::string get_origin(const http::parser::request& request) const { + std::string h = request.header("Sec-WebSocket-Version"); + int version = atoi(h.c_str()); + + if (version == 13) { + return request.header("Origin"); + } else if (version == 7 || version == 8) { + return request.header("Sec-WebSocket-Origin"); + } else { + throw(http::exception("Could not determine origin header. Check Sec-WebSocket-Version header",http::status_code::BAD_REQUEST)); + } + } + + uri_ptr get_uri(const http::parser::request& request) const { + std::string h = request.header("Host"); + + size_t last_colon = h.rfind(":"); size_t last_sbrace = h.rfind("]"); // no : = hostname with no port // last : before ] = ipv6 literal with no port // : with no ] = hostname with port // : after ] = ipv6 literal with port - if (last_colon == std::string::npos || + if (last_colon == std::string::npos || (last_sbrace != std::string::npos && last_sbrace > last_colon)) { - return uri_ptr(new uri(m_connection.is_secure(),h,request.uri())); - } else { - return uri_ptr(new uri(m_connection.is_secure(), - h.substr(0,last_colon), - h.substr(last_colon+1), - request.uri())); - } - - // TODO: check if get_uri is a full uri - } - - void handshake_response(const http::parser::request& request, - http::parser::response& response) - { - std::string server_key = request.header("Sec-WebSocket-Key"); - server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - SHA1 sha; - uint32_t message_digest[5]; - - sha.Reset(); - sha << server_key.c_str(); - - if (sha.Result(message_digest)){ - // convert sha1 hash bytes to network byte order because this sha1 - // library works on ints rather than bytes - for (int i = 0; i < 5; i++) { - message_digest[i] = htonl(message_digest[i]); - } - - server_key = base64_encode( - reinterpret_cast - (message_digest),20 - ); - - // set handshake accept headers - response.replace_header("Sec-WebSocket-Accept",server_key); - response.add_header("Upgrade","websocket"); - response.add_header("Connection","Upgrade"); - } else { - //m_endpoint->elog().at(log::elevel::ERROR) - //<< "Error computing handshake sha1 hash" << log::endl; - // TODO: make sure this error path works - response.set_status(http::status_code::INTERNAL_SERVER_ERROR); - } - } - - void consume(std::istream& s) { - while (s.good() && m_state != hybi_state::READY) { - try { - switch (m_state) { - case hybi_state::READ_HEADER: - process_header(s); - break; - case hybi_state::READ_PAYLOAD: - process_payload(s); - break; - case hybi_state::READY: - // shouldn't be here.. - break; - default: - break; - } - } catch (const processor::exception& e) { - if (e.code() != processor::error::OUT_OF_MESSAGES) { + return uri_ptr(new uri(m_connection.is_secure(),h,request.uri())); + } else { + return uri_ptr(new uri(m_connection.is_secure(), + h.substr(0,last_colon), + h.substr(last_colon+1), + request.uri())); + } + + // TODO: check if get_uri is a full uri + } + + void handshake_response(const http::parser::request& request, + http::parser::response& response) + { + std::string server_key = request.header("Sec-WebSocket-Key"); + server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + SHA1 sha; + uint32_t message_digest[5]; + + sha.Reset(); + sha << server_key.c_str(); + + if (sha.Result(message_digest)){ + // convert sha1 hash bytes to network byte order because this sha1 + // library works on ints rather than bytes + for (int i = 0; i < 5; i++) { + message_digest[i] = htonl(message_digest[i]); + } + + server_key = base64_encode( + reinterpret_cast + (message_digest),20 + ); + + // set handshake accept headers + response.replace_header("Sec-WebSocket-Accept",server_key); + response.add_header("Upgrade","websocket"); + response.add_header("Connection","Upgrade"); + } else { + //m_endpoint->elog().at(log::elevel::ERROR) + //<< "Error computing handshake sha1 hash" << log::endl; + // TODO: make sure this error path works + response.set_status(http::status_code::INTERNAL_SERVER_ERROR); + } + } + + void consume(std::istream& s) { + while (s.good() && m_state != hybi_state::READY) { + try { + switch (m_state) { + case hybi_state::READ_HEADER: + process_header(s); + break; + case hybi_state::READ_PAYLOAD: + process_payload(s); + break; + case hybi_state::READY: + // shouldn't be here.. + break; + default: + break; + } + } catch (const processor::exception& e) { + if (e.code() != processor::error::OUT_OF_MESSAGES) { // The out of messages exception acts as an inturrupt rather // than an error. In that case we don't want to reset // processor state. In all other cases we are aborting @@ -270,244 +270,244 @@ class hybi : public processor_base { m_header.reset(); } } - - throw e; - } - } - } - - void process_header(std::istream& s) { - m_header.consume(s); - - if (m_header.ready()) { - // Get a free message from the read queue for the type of the - // current message - if (m_header.is_control()) { - process_control_header(); - } else { - process_data_header(); - } - } - } - - void process_control_header() { - m_control_message = m_connection.get_control_message(); - - if (!m_control_message) { - throw processor::exception("Out of control messages", + + throw e; + } + } + } + + void process_header(std::istream& s) { + m_header.consume(s); + + if (m_header.ready()) { + // Get a free message from the read queue for the type of the + // current message + if (m_header.is_control()) { + process_control_header(); + } else { + process_data_header(); + } + } + } + + void process_control_header() { + m_control_message = m_connection.get_control_message(); + + if (!m_control_message) { + throw processor::exception("Out of control messages", processor::error::OUT_OF_MESSAGES); - } - - m_control_message->reset(m_header.get_opcode(),m_header.get_masking_key()); - - m_payload_left = m_header.get_payload_size(); - - if (m_payload_left == 0) { - process_frame(); - } else { - m_state = hybi_state::READ_PAYLOAD; - } - } - - void process_data_header() { - if (!m_data_message) { - // This is a new message. No continuation frames allowed. - if (m_header.get_opcode() == frame::opcode::CONTINUATION) { - throw processor::exception("Received continuation frame without an outstanding message.",processor::error::PROTOCOL_VIOLATION); - } - - m_data_message = m_connection.get_data_message(); - - if (!m_data_message) { - throw processor::exception("Out of data messages", + } + + m_control_message->reset(m_header.get_opcode(),m_header.get_masking_key()); + + m_payload_left = m_header.get_payload_size(); + + if (m_payload_left == 0) { + process_frame(); + } else { + m_state = hybi_state::READ_PAYLOAD; + } + } + + void process_data_header() { + if (!m_data_message) { + // This is a new message. No continuation frames allowed. + if (m_header.get_opcode() == frame::opcode::CONTINUATION) { + throw processor::exception("Received continuation frame without an outstanding message.",processor::error::PROTOCOL_VIOLATION); + } + + m_data_message = m_connection.get_data_message(); + + if (!m_data_message) { + throw processor::exception("Out of data messages", processor::error::OUT_OF_MESSAGES); - } - - m_data_message->reset(m_header.get_opcode()); - } else { - // A message has already been started. Continuation frames only! - if (m_header.get_opcode() != frame::opcode::CONTINUATION) { - throw processor::exception("Received new message before the completion of the existing one.",processor::error::PROTOCOL_VIOLATION); - } - } - - m_payload_left = m_header.get_payload_size(); - - if (m_payload_left == 0) { - process_frame(); - } else { - // each frame has a new masking key - m_data_message->set_masking_key(m_header.get_masking_key()); - m_state = hybi_state::READ_PAYLOAD; - } - } - - void process_payload(std::istream& input) { - uint64_t written; - if (m_header.is_control()) { - written = m_control_message->process_payload(input,m_payload_left); - } else { - //m_connection.alog().at(log::alevel::DEVEL) << "process_payload. Size: " << m_payload_left << log::endl; - written = m_data_message->process_payload(input,m_payload_left); - } - m_payload_left -= written; - - if (m_payload_left == 0) { - process_frame(); - } - - } - - void process_frame() { - if (m_header.get_fin()) { - if (m_header.is_control()) { - m_control_message->complete(); - } else { - m_data_message->complete(); - } - m_state = hybi_state::READY; - } else { - reset(); - } - } - - bool ready() const { - return m_state == hybi_state::READY; - } - - bool is_control() const { - return m_header.is_control(); - } - - // note this can only be called once - message::data_ptr get_data_message() { - message::data_ptr p = m_data_message; - m_data_message.reset(); - return p; - } - - // note this can only be called once - message::control_ptr get_control_message() { - message::control_ptr p = m_control_message; - m_control_message.reset(); - return p; - } - - void reset() { - m_state = m_state = hybi_state::READ_HEADER; - m_header.reset(); - } - - uint64_t get_bytes_needed() const { - switch (m_state) { - case hybi_state::READ_HEADER: - return m_header.get_bytes_needed(); - case hybi_state::READ_PAYLOAD: - return m_payload_left; - case hybi_state::READY: - return 0; - default: - throw "shouldn't be here"; - } - } + } + + m_data_message->reset(m_header.get_opcode()); + } else { + // A message has already been started. Continuation frames only! + if (m_header.get_opcode() != frame::opcode::CONTINUATION) { + throw processor::exception("Received new message before the completion of the existing one.",processor::error::PROTOCOL_VIOLATION); + } + } + + m_payload_left = m_header.get_payload_size(); + + if (m_payload_left == 0) { + process_frame(); + } else { + // each frame has a new masking key + m_data_message->set_masking_key(m_header.get_masking_key()); + m_state = hybi_state::READ_PAYLOAD; + } + } + + void process_payload(std::istream& input) { + uint64_t written; + if (m_header.is_control()) { + written = m_control_message->process_payload(input,m_payload_left); + } else { + //m_connection.alog().at(log::alevel::DEVEL) << "process_payload. Size: " << m_payload_left << log::endl; + written = m_data_message->process_payload(input,m_payload_left); + } + m_payload_left -= written; + + if (m_payload_left == 0) { + process_frame(); + } + + } + + void process_frame() { + if (m_header.get_fin()) { + if (m_header.is_control()) { + m_control_message->complete(); + } else { + m_data_message->complete(); + } + m_state = hybi_state::READY; + } else { + reset(); + } + } + + bool ready() const { + return m_state == hybi_state::READY; + } + + bool is_control() const { + return m_header.is_control(); + } + + // note this can only be called once + message::data_ptr get_data_message() { + message::data_ptr p = m_data_message; + m_data_message.reset(); + return p; + } + + // note this can only be called once + message::control_ptr get_control_message() { + message::control_ptr p = m_control_message; + m_control_message.reset(); + return p; + } + + void reset() { + m_state = m_state = hybi_state::READ_HEADER; + m_header.reset(); + } + + uint64_t get_bytes_needed() const { + switch (m_state) { + case hybi_state::READ_HEADER: + return m_header.get_bytes_needed(); + case hybi_state::READ_PAYLOAD: + return m_payload_left; + case hybi_state::READY: + return 0; + default: + throw "shouldn't be here"; + } + } + + // TODO: replace all this to remove all lingering dependencies on + // websocket_frame + binary_string_ptr prepare_frame(frame::opcode::value opcode, + bool mask, + const utf8_string& payload) { + /*if (opcode != frame::opcode::TEXT) { + // TODO: hybi_legacy doesn't allow non-text frames. + throw; + }*/ + + // TODO: utf8 validation on payload. + + + + binary_string_ptr response(new binary_string(0)); + + + m_write_frame.reset(); + m_write_frame.set_opcode(opcode); + m_write_frame.set_masked(mask); + + m_write_frame.set_fin(true); + m_write_frame.set_payload(payload); + + + m_write_frame.process_payload(); + + // TODO + response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); + + // copy header + std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); + + // copy payload + std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); + + + return response; + } + + binary_string_ptr prepare_frame(frame::opcode::value opcode, + bool mask, + const binary_string& payload) { + /*if (opcode != frame::opcode::TEXT) { + // TODO: hybi_legacy doesn't allow non-text frames. + throw; + }*/ + + // TODO: utf8 validation on payload. + + binary_string_ptr response(new binary_string(0)); + + m_write_frame.reset(); + m_write_frame.set_opcode(opcode); + m_write_frame.set_masked(mask); + m_write_frame.set_fin(true); + m_write_frame.set_payload(payload); + + m_write_frame.process_payload(); + + // TODO + response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); + + // copy header + std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); + + // copy payload + std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); + + return response; + } + + /*binary_string_ptr prepare_close_frame(close::status::value code, + bool mask, + const std::string& reason) { + binary_string_ptr response(new binary_string(0)); + + m_write_frame.reset(); + m_write_frame.set_opcode(frame::opcode::CLOSE); + m_write_frame.set_masked(mask); + m_write_frame.set_fin(true); + m_write_frame.set_status(code,reason); + + m_write_frame.process_payload(); + + // TODO + response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); + + // copy header + std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); + + // copy payload + std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); + + return response; + }*/ - // TODO: replace all this to remove all lingering dependencies on - // websocket_frame - binary_string_ptr prepare_frame(frame::opcode::value opcode, - bool mask, - const utf8_string& payload) { - /*if (opcode != frame::opcode::TEXT) { - // TODO: hybi_legacy doesn't allow non-text frames. - throw; - }*/ - - // TODO: utf8 validation on payload. - - - - binary_string_ptr response(new binary_string(0)); - - - m_write_frame.reset(); - m_write_frame.set_opcode(opcode); - m_write_frame.set_masked(mask); - - m_write_frame.set_fin(true); - m_write_frame.set_payload(payload); - - - m_write_frame.process_payload(); - - // TODO - response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); - - // copy header - std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); - - // copy payload - std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); - - - return response; - } - - binary_string_ptr prepare_frame(frame::opcode::value opcode, - bool mask, - const binary_string& payload) { - /*if (opcode != frame::opcode::TEXT) { - // TODO: hybi_legacy doesn't allow non-text frames. - throw; - }*/ - - // TODO: utf8 validation on payload. - - binary_string_ptr response(new binary_string(0)); - - m_write_frame.reset(); - m_write_frame.set_opcode(opcode); - m_write_frame.set_masked(mask); - m_write_frame.set_fin(true); - m_write_frame.set_payload(payload); - - m_write_frame.process_payload(); - - // TODO - response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); - - // copy header - std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); - - // copy payload - std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); - - return response; - } - - /*binary_string_ptr prepare_close_frame(close::status::value code, - bool mask, - const std::string& reason) { - binary_string_ptr response(new binary_string(0)); - - m_write_frame.reset(); - m_write_frame.set_opcode(frame::opcode::CLOSE); - m_write_frame.set_masked(mask); - m_write_frame.set_fin(true); - m_write_frame.set_status(code,reason); - - m_write_frame.process_payload(); - - // TODO - response->resize(m_write_frame.get_header_len()+m_write_frame.get_payload().size()); - - // copy header - std::copy(m_write_frame.get_header(),m_write_frame.get_header()+m_write_frame.get_header_len(),response->begin()); - - // copy payload - std::copy(m_write_frame.get_payload().begin(),m_write_frame.get_payload().end(),response->begin()+m_write_frame.get_header_len()); - - return response; - }*/ - // new prepare frame stuff void prepare_frame(message::data_ptr msg) { assert(msg); @@ -558,18 +558,18 @@ class hybi : public processor_base { prepare_frame(msg); } private: - connection_type& m_connection; - int m_state; - - message::data_ptr m_data_message; - message::control_ptr m_control_message; - hybi_header m_header; - hybi_header m_write_header; - uint64_t m_payload_left; - + connection_type& m_connection; + int m_state; + + message::data_ptr m_data_message; + message::control_ptr m_control_message; + hybi_header m_header; + hybi_header m_write_header; + uint64_t m_payload_left; + - frame::parser m_write_frame; // TODO: refactor this out -}; + frame::parser m_write_frame; // TODO: refactor this out +}; } // namespace processor } // namespace websocketpp diff --git a/src/processors/hybi_header.cpp b/src/processors/hybi_header.cpp index fab21860a..ae587f7d0 100644 --- a/src/processors/hybi_header.cpp +++ b/src/processors/hybi_header.cpp @@ -32,83 +32,83 @@ using websocketpp::processor::hybi_header; hybi_header::hybi_header() { - reset(); + reset(); } void hybi_header::reset() { memset(m_header, 0x00, MAX_HEADER_LENGTH); - m_state = STATE_BASIC_HEADER; + m_state = STATE_BASIC_HEADER; m_bytes_needed = BASIC_HEADER_LENGTH; } // Writing interface (parse a byte stream) void hybi_header::consume(std::istream& input) { - switch (m_state) { - case STATE_BASIC_HEADER: - input.read(&m_header[BASIC_HEADER_LENGTH-m_bytes_needed], + switch (m_state) { + case STATE_BASIC_HEADER: + input.read(&m_header[BASIC_HEADER_LENGTH-m_bytes_needed], m_bytes_needed); - - m_bytes_needed -= input.gcount(); - - if (m_bytes_needed == 0) { - process_basic_header(); - - validate_basic_header(); - - if (m_bytes_needed > 0) { - m_state = STATE_EXTENDED_HEADER; - } else { - process_extended_header(); - m_state = STATE_READY; - } - } - break; - case STATE_EXTENDED_HEADER: - input.read(&m_header[get_header_len()-m_bytes_needed], + + m_bytes_needed -= input.gcount(); + + if (m_bytes_needed == 0) { + process_basic_header(); + + validate_basic_header(); + + if (m_bytes_needed > 0) { + m_state = STATE_EXTENDED_HEADER; + } else { + process_extended_header(); + m_state = STATE_READY; + } + } + break; + case STATE_EXTENDED_HEADER: + input.read(&m_header[get_header_len()-m_bytes_needed], m_bytes_needed); - - m_bytes_needed -= input.gcount(); - - if (m_bytes_needed == 0) { - process_extended_header(); - m_state = STATE_READY; - } - break; - default: - break; - } + + m_bytes_needed -= input.gcount(); + + if (m_bytes_needed == 0) { + process_extended_header(); + m_state = STATE_READY; + } + break; + default: + break; + } } uint64_t hybi_header::get_bytes_needed() const { - return m_bytes_needed; + return m_bytes_needed; } bool hybi_header::ready() const { - return m_state == STATE_READY; + return m_state == STATE_READY; } // Writing interface (set fields directly) void hybi_header::set_fin(bool fin) { - set_header_bit(BPB0_FIN,0,fin); + set_header_bit(BPB0_FIN,0,fin); } void hybi_header::set_rsv1(bool b) { - set_header_bit(BPB0_RSV1,0,b); + set_header_bit(BPB0_RSV1,0,b); } void hybi_header::set_rsv2(bool b) { - set_header_bit(BPB0_RSV2,0,b); + set_header_bit(BPB0_RSV2,0,b); } void hybi_header::set_rsv3(bool b) { - set_header_bit(BPB0_RSV3,0,b); + set_header_bit(BPB0_RSV3,0,b); } void hybi_header::set_opcode(frame::opcode::value op) { - m_header[0] &= (0xFF ^ BPB0_OPCODE); // clear op bits - m_header[0] |= op; // set op bits + m_header[0] &= (0xFF ^ BPB0_OPCODE); // clear op bits + m_header[0] |= op; // set op bits } void hybi_header::set_masked(bool masked,int32_t key) { - if (masked) { - m_header[1] |= BPB1_MASK; - set_masking_key(key); - } else { - m_header[1] &= (0xFF ^ BPB1_MASK); - clear_masking_key(); - } + if (masked) { + m_header[1] |= BPB1_MASK; + set_masking_key(key); + } else { + m_header[1] &= (0xFF ^ BPB1_MASK); + clear_masking_key(); + } } void hybi_header::set_payload_size(uint64_t size) { if (size <= frame::limits::PAYLOAD_SIZE_BASIC) { @@ -153,137 +153,137 @@ std::string hybi_header::get_header_bytes() const { // Reading interface (get fields directly) bool hybi_header::get_fin() const { - return ((m_header[0] & BPB0_FIN) == BPB0_FIN); + return ((m_header[0] & BPB0_FIN) == BPB0_FIN); } bool hybi_header::get_rsv1() const { - return ((m_header[0] & BPB0_RSV1) == BPB0_RSV1); + return ((m_header[0] & BPB0_RSV1) == BPB0_RSV1); } bool hybi_header::get_rsv2() const { - return ((m_header[0] & BPB0_RSV2) == BPB0_RSV2); + return ((m_header[0] & BPB0_RSV2) == BPB0_RSV2); } bool hybi_header::get_rsv3() const { - return ((m_header[0] & BPB0_RSV3) == BPB0_RSV3); + return ((m_header[0] & BPB0_RSV3) == BPB0_RSV3); } websocketpp::frame::opcode::value hybi_header::get_opcode() const { - return frame::opcode::value(m_header[0] & BPB0_OPCODE); + return frame::opcode::value(m_header[0] & BPB0_OPCODE); } bool hybi_header::get_masked() const { - return ((m_header[1] & BPB1_MASK) == BPB1_MASK); + return ((m_header[1] & BPB1_MASK) == BPB1_MASK); } int32_t hybi_header::get_masking_key() const { - if (!get_masked()) { - return 0; - } - return *reinterpret_cast(&m_header[get_header_len()-4]); + if (!get_masked()) { + return 0; + } + return *reinterpret_cast(&m_header[get_header_len()-4]); } uint64_t hybi_header::get_payload_size() const { - return m_payload_size; + return m_payload_size; } bool hybi_header::is_control() const { - return (frame::opcode::is_control(get_opcode())); + return (frame::opcode::is_control(get_opcode())); } // private unsigned int hybi_header::get_header_len() const { - unsigned int temp = 2; - - if (get_masked()) { - temp += 4; - } - - if (get_basic_size() == 126) { - temp += 2; - } else if (get_basic_size() == 127) { - temp += 8; - } - - return temp; + unsigned int temp = 2; + + if (get_masked()) { + temp += 4; + } + + if (get_basic_size() == 126) { + temp += 2; + } else if (get_basic_size() == 127) { + temp += 8; + } + + return temp; } uint8_t hybi_header::get_basic_size() const { - return m_header[1] & BPB1_PAYLOAD; + return m_header[1] & BPB1_PAYLOAD; } void hybi_header::validate_basic_header() const { // check for control frame size - if (is_control() && get_basic_size() > frame::limits::PAYLOAD_SIZE_BASIC) { - throw processor::exception("Control Frame is too large",processor::error::PROTOCOL_VIOLATION); - } - - // check for reserved bits - if (get_rsv1() || get_rsv2() || get_rsv3()) { - throw processor::exception("Reserved bit used",processor::error::PROTOCOL_VIOLATION); - } - - // check for reserved opcodes - if (frame::opcode::reserved(get_opcode())) { - throw processor::exception("Reserved opcode used",processor::error::PROTOCOL_VIOLATION); - } + if (is_control() && get_basic_size() > frame::limits::PAYLOAD_SIZE_BASIC) { + throw processor::exception("Control Frame is too large",processor::error::PROTOCOL_VIOLATION); + } + + // check for reserved bits + if (get_rsv1() || get_rsv2() || get_rsv3()) { + throw processor::exception("Reserved bit used",processor::error::PROTOCOL_VIOLATION); + } + + // check for reserved opcodes + if (frame::opcode::reserved(get_opcode())) { + throw processor::exception("Reserved opcode used",processor::error::PROTOCOL_VIOLATION); + } // check for invalid opcodes - if (frame::opcode::invalid(get_opcode())) { - throw processor::exception("Invalid opcode used",processor::error::PROTOCOL_VIOLATION); - } - - // check for fragmented control message - if (is_control() && !get_fin()) { - throw processor::exception("Fragmented control message",processor::error::PROTOCOL_VIOLATION); - } + if (frame::opcode::invalid(get_opcode())) { + throw processor::exception("Invalid opcode used",processor::error::PROTOCOL_VIOLATION); + } + + // check for fragmented control message + if (is_control() && !get_fin()) { + throw processor::exception("Fragmented control message",processor::error::PROTOCOL_VIOLATION); + } } void hybi_header::process_basic_header() { - m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH; + m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH; } void hybi_header::process_extended_header() { - uint8_t s = get_basic_size(); - - if (s <= frame::limits::PAYLOAD_SIZE_BASIC) { - m_payload_size = s; - } else if (s == BASIC_PAYLOAD_16BIT_CODE) { - // reinterpret the second two bytes as a 16 bit integer in network - // byte order. Convert to host byte order and store locally. - m_payload_size = ntohs(*( + uint8_t s = get_basic_size(); + + if (s <= frame::limits::PAYLOAD_SIZE_BASIC) { + m_payload_size = s; + } else if (s == BASIC_PAYLOAD_16BIT_CODE) { + // reinterpret the second two bytes as a 16 bit integer in network + // byte order. Convert to host byte order and store locally. + m_payload_size = ntohs(*( reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) )); - - if (m_payload_size < s) { - std::stringstream err; - err << "payload length not minimally encoded. Using 16 bit form for payload size: " << m_payload_size; - throw processor::exception(err.str(),processor::error::PROTOCOL_VIOLATION); - } - - } else if (s == BASIC_PAYLOAD_64BIT_CODE) { - // reinterpret the second eight bytes as a 64 bit integer in - // network byte order. Convert to host byte order and store. - m_payload_size = ntohll(*( + + if (m_payload_size < s) { + std::stringstream err; + err << "payload length not minimally encoded. Using 16 bit form for payload size: " << m_payload_size; + throw processor::exception(err.str(),processor::error::PROTOCOL_VIOLATION); + } + + } else if (s == BASIC_PAYLOAD_64BIT_CODE) { + // reinterpret the second eight bytes as a 64 bit integer in + // network byte order. Convert to host byte order and store. + m_payload_size = ntohll(*( reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) )); - - if (m_payload_size <= frame::limits::PAYLOAD_SIZE_EXTENDED) { - throw processor::exception("payload length not minimally encoded", - processor::error::PROTOCOL_VIOLATION); - } - - } else { - // TODO: shouldn't be here how to handle? - throw processor::exception("invalid get_basic_size in process_extended_header"); - } + + if (m_payload_size <= frame::limits::PAYLOAD_SIZE_EXTENDED) { + throw processor::exception("payload length not minimally encoded", + processor::error::PROTOCOL_VIOLATION); + } + + } else { + // TODO: shouldn't be here how to handle? + throw processor::exception("invalid get_basic_size in process_extended_header"); + } } void hybi_header::set_header_bit(uint8_t bit,int byte,bool value) { - if (value) { - m_header[byte] |= bit; - } else { - m_header[byte] &= (0xFF ^ bit); - } + if (value) { + m_header[byte] |= bit; + } else { + m_header[byte] &= (0xFF ^ bit); + } } void hybi_header::set_masking_key(int32_t key) { - *(reinterpret_cast(&m_header[get_header_len()-4])) = key; + *(reinterpret_cast(&m_header[get_header_len()-4])) = key; } void hybi_header::clear_masking_key() { - // this is a no-op as clearing the mask bit also changes the get_header_len - // method to not include these byte ranges. Whenever the masking bit is re- - // set a new key is generated anyways. + // this is a no-op as clearing the mask bit also changes the get_header_len + // method to not include these byte ranges. Whenever the masking bit is re- + // set a new key is generated anyways. } \ No newline at end of file diff --git a/src/processors/hybi_header.hpp b/src/processors/hybi_header.hpp index 6343a05c6..0437ef469 100644 --- a/src/processors/hybi_header.hpp +++ b/src/processors/hybi_header.hpp @@ -57,16 +57,16 @@ namespace processor { class hybi_header { public: /// Construct a header processor and initialize for writing - hybi_header(); + hybi_header(); /// Reset a header processor for writing - void reset(); - - // Writing interface (parse a byte stream) + void reset(); + + // Writing interface (parse a byte stream) // valid only if ready() returns false // Consume will throw a processor::exception in the case that the bytes it // read do not form a valid WebSocket frame header. void consume(std::istream& input); - uint64_t get_bytes_needed() const; + uint64_t get_bytes_needed() const; bool ready() const; // Writing interface (set fields directly) @@ -110,37 +110,37 @@ class hybi_header { // helper functions for writing void process_basic_header(); - void process_extended_header(); + void process_extended_header(); void set_header_bit(uint8_t bit,int byte,bool value); void set_masking_key(int32_t key); - void clear_masking_key(); + void clear_masking_key(); + + // basic payload byte flags + static const uint8_t BPB0_OPCODE = 0x0F; + static const uint8_t BPB0_RSV3 = 0x10; + static const uint8_t BPB0_RSV2 = 0x20; + static const uint8_t BPB0_RSV1 = 0x40; + static const uint8_t BPB0_FIN = 0x80; + static const uint8_t BPB1_PAYLOAD = 0x7F; + static const uint8_t BPB1_MASK = 0x80; + + static const uint8_t BASIC_PAYLOAD_16BIT_CODE = 0x7E; // 126 + static const uint8_t BASIC_PAYLOAD_64BIT_CODE = 0x7F; // 127 - // basic payload byte flags - static const uint8_t BPB0_OPCODE = 0x0F; - static const uint8_t BPB0_RSV3 = 0x10; - static const uint8_t BPB0_RSV2 = 0x20; - static const uint8_t BPB0_RSV1 = 0x40; - static const uint8_t BPB0_FIN = 0x80; - static const uint8_t BPB1_PAYLOAD = 0x7F; - static const uint8_t BPB1_MASK = 0x80; - - static const uint8_t BASIC_PAYLOAD_16BIT_CODE = 0x7E; // 126 - static const uint8_t BASIC_PAYLOAD_64BIT_CODE = 0x7F; // 127 - - static const unsigned int BASIC_HEADER_LENGTH = 2; - static const unsigned int MAX_HEADER_LENGTH = 14; - - static const uint8_t STATE_BASIC_HEADER = 1; - static const uint8_t STATE_EXTENDED_HEADER = 2; - static const uint8_t STATE_READY = 3; + static const unsigned int BASIC_HEADER_LENGTH = 2; + static const unsigned int MAX_HEADER_LENGTH = 14; + + static const uint8_t STATE_BASIC_HEADER = 1; + static const uint8_t STATE_EXTENDED_HEADER = 2; + static const uint8_t STATE_READY = 3; static const uint8_t STATE_WRITE = 4; - - uint8_t m_state; - uint64_t m_bytes_needed; - uint64_t m_payload_size; - char m_header[MAX_HEADER_LENGTH]; + + uint8_t m_state; + uint64_t m_bytes_needed; + uint64_t m_payload_size; + char m_header[MAX_HEADER_LENGTH]; }; - + } // namespace processor } // namespace websocketpp diff --git a/src/processors/hybi_legacy.hpp b/src/processors/hybi_legacy.hpp index acdb00b89..44632217d 100644 --- a/src/processors/hybi_legacy.hpp +++ b/src/processors/hybi_legacy.hpp @@ -37,230 +37,230 @@ namespace websocketpp { namespace processor { namespace hybi_legacy_state { - enum value { - INIT = 0, - READ = 1, - DONE = 2 - }; + enum value { + INIT = 0, + READ = 1, + DONE = 2 + }; } template class hybi_legacy : public processor_base { public: - hybi_legacy(connection_type &connection) - : m_connection(connection), - m_state(hybi_legacy_state::INIT) - { - reset(); - } - - void validate_handshake(const http::parser::request& headers) const { - - } - - void handshake_response(const http::parser::request& request,http::parser::response& response) { - char key_final[16]; - - // key1 - *reinterpret_cast(&key_final[0]) = - decode_client_key(request.header("Sec-WebSocket-Key1")); - - // key2 - *reinterpret_cast(&key_final[4]) = - decode_client_key(request.header("Sec-WebSocket-Key2")); - - // key3 - memcpy(&key_final[8],request.header("Sec-WebSocket-Key3").c_str(),8); - - // md5 + hybi_legacy(connection_type &connection) + : m_connection(connection), + m_state(hybi_legacy_state::INIT) + { + reset(); + } + + void validate_handshake(const http::parser::request& headers) const { + + } + + void handshake_response(const http::parser::request& request,http::parser::response& response) { + char key_final[16]; + + // key1 + *reinterpret_cast(&key_final[0]) = + decode_client_key(request.header("Sec-WebSocket-Key1")); + + // key2 + *reinterpret_cast(&key_final[4]) = + decode_client_key(request.header("Sec-WebSocket-Key2")); + + // key3 + memcpy(&key_final[8],request.header("Sec-WebSocket-Key3").c_str(),8); + + // md5 m_key3 = key_final; - m_key3 = md5_hash_string(m_key3); - - response.add_header("Upgrade","websocket"); - response.add_header("Connection","Upgrade"); - - // TODO: require headers that need application specific information? - - // Echo back client's origin unless our local application set a - // more restrictive one. - if (response.header("Sec-WebSocket-Origin") == "") { - response.add_header("Sec-WebSocket-Origin",request.header("Origin")); - } - - // Echo back the client's request host unless our local application - // set a different one. - if (response.header("Sec-WebSocket-Location") == "") { - // TODO: extract from host header rather than hard code - uri_ptr uri = get_uri(request); - response.add_header("Sec-WebSocket-Location",uri->str()); - } - } - - std::string get_origin(const http::parser::request& request) const { - return request.header("Origin"); - } - - uri_ptr get_uri(const http::parser::request& request) const { - std::string h = request.header("Host"); - - size_t last_colon = h.rfind(":"); + m_key3 = md5_hash_string(m_key3); + + response.add_header("Upgrade","websocket"); + response.add_header("Connection","Upgrade"); + + // TODO: require headers that need application specific information? + + // Echo back client's origin unless our local application set a + // more restrictive one. + if (response.header("Sec-WebSocket-Origin") == "") { + response.add_header("Sec-WebSocket-Origin",request.header("Origin")); + } + + // Echo back the client's request host unless our local application + // set a different one. + if (response.header("Sec-WebSocket-Location") == "") { + // TODO: extract from host header rather than hard code + uri_ptr uri = get_uri(request); + response.add_header("Sec-WebSocket-Location",uri->str()); + } + } + + std::string get_origin(const http::parser::request& request) const { + return request.header("Origin"); + } + + uri_ptr get_uri(const http::parser::request& request) const { + std::string h = request.header("Host"); + + size_t last_colon = h.rfind(":"); size_t last_sbrace = h.rfind("]"); // no : = hostname with no port // last : before ] = ipv6 literal with no port // : with no ] = hostname with port // : after ] = ipv6 literal with port - if (last_colon == std::string::npos || + if (last_colon == std::string::npos || (last_sbrace != std::string::npos && last_sbrace > last_colon)) { - return uri_ptr(new uri(m_connection.is_secure(),h,request.uri())); - } else { - return uri_ptr(new uri(m_connection.is_secure(), - h.substr(0,last_colon), - h.substr(last_colon+1), - request.uri())); - } - - // TODO: check if get_uri is a full uri - } - - void consume(std::istream& s) { - //unsigned char c; - while (s.good() && m_state != hybi_legacy_state::DONE) { - //c = s.get(); - //if (s.good()) { - process(s); - //} - } - } - - bool ready() const { - return m_state == hybi_legacy_state::DONE; - } - - // legacy hybi has no control messages. - bool is_control() const { - return false; - } - - message::data_ptr get_data_message() { - message::data_ptr p = m_data_message; - m_data_message.reset(); - return p; - } - - message::control_ptr get_control_message() { - throw "Hybi legacy has no control messages."; - } - - void process(std::istream& input) { - if (m_state == hybi_legacy_state::INIT) { - // we are looking for a 0x00 - if (input.peek() == 0x00) { - // start a message - input.ignore(); - - m_state = hybi_legacy_state::READ; - - m_data_message = m_connection.get_data_message(); - - if (!m_data_message) { - throw processor::exception("Out of data messages",processor::error::OUT_OF_MESSAGES); - } - - m_data_message->reset(frame::opcode::TEXT); - } else { - input.ignore(); - // TODO: ignore or error - //std::stringstream foo; - - //foo << "invalid character read: |" << input.peek() << "|"; - - std::cout << "invalid character read: |" << input.peek() << "|" << std::endl; - - //throw processor::exception(foo.str(),processor::error::PROTOCOL_VIOLATION); - } - } else if (m_state == hybi_legacy_state::READ) { - if (input.peek() == 0xFF) { - // end - input.ignore(); - - m_state = hybi_legacy_state::DONE; - } else { - if (m_data_message) { - m_data_message->process_payload(input,1); - } - } - } - } - - void reset() { - m_state = hybi_legacy_state::INIT; - m_data_message.reset(); - } - - uint64_t get_bytes_needed() const { - return 1; - } - - std::string get_key3() const { - return m_key3; - } - - // TODO: to factor away - binary_string_ptr prepare_frame(frame::opcode::value opcode, - bool mask, - const binary_string& payload) { - if (opcode != frame::opcode::TEXT) { - // TODO: hybi_legacy doesn't allow non-text frames. - throw; - } - - // TODO: mask = ignore? - - // TODO: utf8 validation on payload. - - binary_string_ptr response(new binary_string(payload.size()+2)); - - (*response)[0] = 0x00; - std::copy(payload.begin(),payload.end(),response->begin()+1); - (*response)[response->size()-1] = 0xFF; - - return response; - } - - binary_string_ptr prepare_frame(frame::opcode::value opcode, - bool mask, - const utf8_string& payload) { - if (opcode != frame::opcode::TEXT) { - // TODO: hybi_legacy doesn't allow non-text frames. - throw; - } - - // TODO: mask = ignore? - - // TODO: utf8 validation on payload. - - binary_string_ptr response(new binary_string(payload.size()+2)); - - (*response)[0] = 0x00; - std::copy(payload.begin(),payload.end(),response->begin()+1); - (*response)[response->size()-1] = 0xFF; - - return response; - } - - binary_string_ptr prepare_close_frame(close::status::value code, - bool mask, - const std::string& reason) { - binary_string_ptr response(new binary_string(2)); - - (*response)[0] = 0xFF; - (*response)[1] = 0x00; - - return response; - } - + return uri_ptr(new uri(m_connection.is_secure(),h,request.uri())); + } else { + return uri_ptr(new uri(m_connection.is_secure(), + h.substr(0,last_colon), + h.substr(last_colon+1), + request.uri())); + } + + // TODO: check if get_uri is a full uri + } + + void consume(std::istream& s) { + //unsigned char c; + while (s.good() && m_state != hybi_legacy_state::DONE) { + //c = s.get(); + //if (s.good()) { + process(s); + //} + } + } + + bool ready() const { + return m_state == hybi_legacy_state::DONE; + } + + // legacy hybi has no control messages. + bool is_control() const { + return false; + } + + message::data_ptr get_data_message() { + message::data_ptr p = m_data_message; + m_data_message.reset(); + return p; + } + + message::control_ptr get_control_message() { + throw "Hybi legacy has no control messages."; + } + + void process(std::istream& input) { + if (m_state == hybi_legacy_state::INIT) { + // we are looking for a 0x00 + if (input.peek() == 0x00) { + // start a message + input.ignore(); + + m_state = hybi_legacy_state::READ; + + m_data_message = m_connection.get_data_message(); + + if (!m_data_message) { + throw processor::exception("Out of data messages",processor::error::OUT_OF_MESSAGES); + } + + m_data_message->reset(frame::opcode::TEXT); + } else { + input.ignore(); + // TODO: ignore or error + //std::stringstream foo; + + //foo << "invalid character read: |" << input.peek() << "|"; + + std::cout << "invalid character read: |" << input.peek() << "|" << std::endl; + + //throw processor::exception(foo.str(),processor::error::PROTOCOL_VIOLATION); + } + } else if (m_state == hybi_legacy_state::READ) { + if (input.peek() == 0xFF) { + // end + input.ignore(); + + m_state = hybi_legacy_state::DONE; + } else { + if (m_data_message) { + m_data_message->process_payload(input,1); + } + } + } + } + + void reset() { + m_state = hybi_legacy_state::INIT; + m_data_message.reset(); + } + + uint64_t get_bytes_needed() const { + return 1; + } + + std::string get_key3() const { + return m_key3; + } + + // TODO: to factor away + binary_string_ptr prepare_frame(frame::opcode::value opcode, + bool mask, + const binary_string& payload) { + if (opcode != frame::opcode::TEXT) { + // TODO: hybi_legacy doesn't allow non-text frames. + throw; + } + + // TODO: mask = ignore? + + // TODO: utf8 validation on payload. + + binary_string_ptr response(new binary_string(payload.size()+2)); + + (*response)[0] = 0x00; + std::copy(payload.begin(),payload.end(),response->begin()+1); + (*response)[response->size()-1] = 0xFF; + + return response; + } + + binary_string_ptr prepare_frame(frame::opcode::value opcode, + bool mask, + const utf8_string& payload) { + if (opcode != frame::opcode::TEXT) { + // TODO: hybi_legacy doesn't allow non-text frames. + throw; + } + + // TODO: mask = ignore? + + // TODO: utf8 validation on payload. + + binary_string_ptr response(new binary_string(payload.size()+2)); + + (*response)[0] = 0x00; + std::copy(payload.begin(),payload.end(),response->begin()+1); + (*response)[response->size()-1] = 0xFF; + + return response; + } + + binary_string_ptr prepare_close_frame(close::status::value code, + bool mask, + const std::string& reason) { + binary_string_ptr response(new binary_string(2)); + + (*response)[0] = 0xFF; + (*response)[1] = 0x00; + + return response; + } + void prepare_frame(message::data_ptr msg) { assert(msg); if (msg->get_prepared()) { @@ -294,36 +294,36 @@ class hybi_legacy : public processor_base { } private: - uint32_t decode_client_key(const std::string& key) { - int spaces = 0; - std::string digits = ""; - uint32_t num; - - // key2 - for (size_t i = 0; i < key.size(); i++) { - if (key[i] == ' ') { - spaces++; - } else if (key[i] >= '0' && key[i] <= '9') { - digits += key[i]; - } - } - - num = atoi(digits.c_str()); - if (spaces > 0 && num > 0) { - return htonl(num/spaces); - } else { - return 0; - } - } - - connection_type& m_connection; - hybi_legacy_state::value m_state; - - message::data_ptr m_data_message; - - std::string m_key3; + uint32_t decode_client_key(const std::string& key) { + int spaces = 0; + std::string digits = ""; + uint32_t num; + + // key2 + for (size_t i = 0; i < key.size(); i++) { + if (key[i] == ' ') { + spaces++; + } else if (key[i] >= '0' && key[i] <= '9') { + digits += key[i]; + } + } + + num = atoi(digits.c_str()); + if (spaces > 0 && num > 0) { + return htonl(num/spaces); + } else { + return 0; + } + } + + connection_type& m_connection; + hybi_legacy_state::value m_state; + + message::data_ptr m_data_message; + + std::string m_key3; }; - + } // processor } // websocketpp #endif // WEBSOCKET_PROCESSOR_HYBI_LEGACY_HPP diff --git a/src/processors/processor.hpp b/src/processors/processor.hpp index b61695318..9919f96d8 100644 --- a/src/processors/processor.hpp +++ b/src/processors/processor.hpp @@ -33,41 +33,41 @@ namespace websocketpp { namespace processor { - + namespace error { - enum value { - FATAL_ERROR = 0, // force session end - SOFT_ERROR = 1, // should log and ignore - PROTOCOL_VIOLATION = 2, // must end session - PAYLOAD_VIOLATION = 3, // should end session - INTERNAL_ENDPOINT_ERROR = 4,// cleanly end session - MESSAGE_TOO_BIG = 5, // ??? - OUT_OF_MESSAGES = 6 // read queue is empty, wait - }; + enum value { + FATAL_ERROR = 0, // force session end + SOFT_ERROR = 1, // should log and ignore + PROTOCOL_VIOLATION = 2, // must end session + PAYLOAD_VIOLATION = 3, // should end session + INTERNAL_ENDPOINT_ERROR = 4,// cleanly end session + MESSAGE_TOO_BIG = 5, // ??? + OUT_OF_MESSAGES = 6 // read queue is empty, wait + }; } class exception : public std::exception { -public: - exception(const std::string& msg, - error::value code = error::FATAL_ERROR) - : m_msg(msg),m_code(code) {} - ~exception() throw() {} - - virtual const char* what() const throw() { - return m_msg.c_str(); - } - - error::value code() const throw() { - return m_code; - } - - std::string m_msg; - error::value m_code; +public: + exception(const std::string& msg, + error::value code = error::FATAL_ERROR) + : m_msg(msg),m_code(code) {} + ~exception() throw() {} + + virtual const char* what() const throw() { + return m_msg.c_str(); + } + + error::value code() const throw() { + return m_code; + } + + std::string m_msg; + error::value m_code; }; } // namespace processor } // namespace websocketpp - + #include "../http/parser.hpp" #include "../uri.hpp" #include "../websocket_frame.hpp" // TODO: clean up @@ -81,62 +81,62 @@ class exception : public std::exception { namespace websocketpp { namespace processor { - + class processor_base { public: - // validate client handshake - // validate server handshake - - // Given a list of HTTP headers determine if the values are sufficient - // to start a websocket session. If so begin constructing a response, if not throw a handshake - // exception. - // validate handshake request - virtual void validate_handshake(const http::parser::request& headers) const = 0; - - virtual void handshake_response(const http::parser::request& request,http::parser::response& response) = 0; - - // Extracts client origin from a handshake request - virtual std::string get_origin(const http::parser::request& request) const = 0; - // Extracts client uri from a handshake request - virtual uri_ptr get_uri(const http::parser::request& request) const = 0; - - // consume bytes, throw on exception - virtual void consume(std::istream& s) = 0; - - // is there a message ready to be dispatched? - virtual bool ready() const = 0; - virtual bool is_control() const = 0; - virtual message::data_ptr get_data_message() = 0; - virtual message::control_ptr get_control_message() = 0; - virtual void reset() = 0; - - virtual uint64_t get_bytes_needed() const = 0; - - // Get information about the message that is ready - //virtual frame::opcode::value get_opcode() const = 0; - - //virtual utf8_string_ptr get_utf8_payload() const = 0; - //virtual binary_string_ptr get_binary_payload() const = 0; - //virtual close::status::value get_close_code() const = 0; - //virtual utf8_string get_close_reason() const = 0; - - // TODO: prepare a frame - //virtual binary_string_ptr prepare_frame(frame::opcode::value opcode, - // bool mask, - // const utf8_string& payload) = 0; - //virtual binary_string_ptr prepare_frame(frame::opcode::value opcode, - // bool mask, - // const binary_string& payload) = 0; - // - //virtual binary_string_ptr prepare_close_frame(close::status::value code, - // bool mask, - // const std::string& reason) = 0; - - virtual void prepare_frame(message::data_ptr msg) = 0; + // validate client handshake + // validate server handshake + + // Given a list of HTTP headers determine if the values are sufficient + // to start a websocket session. If so begin constructing a response, if not throw a handshake + // exception. + // validate handshake request + virtual void validate_handshake(const http::parser::request& headers) const = 0; + + virtual void handshake_response(const http::parser::request& request,http::parser::response& response) = 0; + + // Extracts client origin from a handshake request + virtual std::string get_origin(const http::parser::request& request) const = 0; + // Extracts client uri from a handshake request + virtual uri_ptr get_uri(const http::parser::request& request) const = 0; + + // consume bytes, throw on exception + virtual void consume(std::istream& s) = 0; + + // is there a message ready to be dispatched? + virtual bool ready() const = 0; + virtual bool is_control() const = 0; + virtual message::data_ptr get_data_message() = 0; + virtual message::control_ptr get_control_message() = 0; + virtual void reset() = 0; + + virtual uint64_t get_bytes_needed() const = 0; + + // Get information about the message that is ready + //virtual frame::opcode::value get_opcode() const = 0; + + //virtual utf8_string_ptr get_utf8_payload() const = 0; + //virtual binary_string_ptr get_binary_payload() const = 0; + //virtual close::status::value get_close_code() const = 0; + //virtual utf8_string get_close_reason() const = 0; + + // TODO: prepare a frame + //virtual binary_string_ptr prepare_frame(frame::opcode::value opcode, + // bool mask, + // const utf8_string& payload) = 0; + //virtual binary_string_ptr prepare_frame(frame::opcode::value opcode, + // bool mask, + // const binary_string& payload) = 0; + // + //virtual binary_string_ptr prepare_close_frame(close::status::value code, + // bool mask, + // const std::string& reason) = 0; + + virtual void prepare_frame(message::data_ptr msg) = 0; virtual void prepare_close_frame(message::data_ptr msg, close::status::value code, const std::string& reason) = 0; - + }; typedef boost::shared_ptr ptr; diff --git a/src/rng/blank_rng.hpp b/src/rng/blank_rng.hpp index 5bc731bf9..c4a53a99e 100644 --- a/src/rng/blank_rng.hpp +++ b/src/rng/blank_rng.hpp @@ -33,14 +33,14 @@ #include namespace websocketpp { - + class blank_rng { public: - int32_t gen() { - throw "Random Number generation not supported"; - } + int32_t gen() { + throw "Random Number generation not supported"; + } }; - + } #endif // BLANK_RNG_HPP diff --git a/src/rng/boost_rng.cpp b/src/rng/boost_rng.cpp index a20212dca..8cef6fe9d 100644 --- a/src/rng/boost_rng.cpp +++ b/src/rng/boost_rng.cpp @@ -32,8 +32,8 @@ using websocketpp::boost_rng; boost_rng::boost_rng() : m_gen(m_rng, - boost::random::uniform_int_distribution<>(INT32_MIN,INT32_MAX)); {} + boost::random::uniform_int_distribution<>(INT32_MIN,INT32_MAX)); {} int32_t boost_rng::gen() { - return m_gen(); + return m_gen(); } \ No newline at end of file diff --git a/src/rng/boost_rng.hpp b/src/rng/boost_rng.hpp index 730fea05a..251316391 100644 --- a/src/rng/boost_rng.hpp +++ b/src/rng/boost_rng.hpp @@ -35,18 +35,18 @@ #include namespace websocketpp { - class boost_rng { - public: - boost_rng(); - int32_t gen(); - private: - boost::random::random_device m_rng; - boost::random::variate_generator - < - boost::random::random_device&, - boost::random::uniform_int_distribution<> - > m_gen; - }; + class boost_rng { + public: + boost_rng(); + int32_t gen(); + private: + boost::random::random_device m_rng; + boost::random::variate_generator + < + boost::random::random_device&, + boost::random::uniform_int_distribution<> + > m_gen; + }; } #endif // BOOST_RNG_HPP diff --git a/src/roles/client.hpp b/src/roles/client.hpp index e3f4af281..d320c6435 100644 --- a/src/roles/client.hpp +++ b/src/roles/client.hpp @@ -48,105 +48,105 @@ using boost::asio::ip::tcp; namespace websocketpp { namespace role { - + template class client { public: - // Connection specific details - template - class connection { - public: - typedef connection type; - typedef endpoint endpoint_type; + // Connection specific details + template + class connection { + public: + typedef connection type; + typedef endpoint endpoint_type; // client connections are friends with their respective client endpoint friend class client; // Valid always int get_version() const { - return m_version; - } - - std::string get_origin() const { - return m_origin; - } - - // not sure when valid - std::string get_request_header(const std::string& key) const { - return m_request.header(key); - } - std::string get_response_header(const std::string& key) const { - return m_response.header(key); - } - + return m_version; + } + + std::string get_origin() const { + return m_origin; + } + + // not sure when valid + std::string get_request_header(const std::string& key) const { + return m_request.header(key); + } + std::string get_response_header(const std::string& key) const { + return m_response.header(key); + } + // Valid before connect is called void add_request_header(const std::string& key, const std::string& value) { - m_request.add_header(key,value); - } - void replace_request_header(const std::string& key, const std::string& value) { - m_request.replace_header(key,value); - } - void remove_request_header(const std::string& key) { - m_request.remove_header(key); - } - + m_request.add_header(key,value); + } + void replace_request_header(const std::string& key, const std::string& value) { + m_request.replace_header(key,value); + } + void remove_request_header(const std::string& key) { + m_request.remove_header(key); + } + // Information about the requested URI - // valid only after URIs are loaded - // TODO: check m_uri for NULLness - bool get_secure() const { - return m_uri->get_secure(); - } - std::string get_host() const { - return m_uri->get_host(); - } - std::string get_resource() const { - return m_uri->get_resource(); - } - uint16_t get_port() const { - return m_uri->get_port(); - } + // valid only after URIs are loaded + // TODO: check m_uri for NULLness + bool get_secure() const { + return m_uri->get_secure(); + } + std::string get_host() const { + return m_uri->get_host(); + } + std::string get_resource() const { + return m_uri->get_resource(); + } + uint16_t get_port() const { + return m_uri->get_port(); + } std::string get_uri() const { - return m_uri->str(); - } - - int32_t rand() { + return m_uri->str(); + } + + int32_t rand() { return m_endpoint.rand(); } bool is_server() const { return false; } - - // should this exist? - boost::asio::io_service& get_io_service() { - return m_endpoint.get_io_service(); - } - protected: + + // should this exist? + boost::asio::io_service& get_io_service() { + return m_endpoint.get_io_service(); + } + protected: connection(endpoint& e) : m_endpoint(e), m_connection(static_cast< connection_type& >(*this)), // TODO: version shouldn't be hardcoded m_version(13) {} - + void set_uri(uri_ptr u) { m_uri = u; } - void async_init() { - m_connection.m_processor = processor::ptr(new processor::hybi(m_connection)); - - write_request(); - } - + void async_init() { + m_connection.m_processor = processor::ptr(new processor::hybi(m_connection)); + + write_request(); + } + - void write_request(); - void handle_write_request(const boost::system::error_code& error); - void read_response(); - void handle_read_response(const boost::system::error_code& error, - std::size_t bytes_transferred); - - void log_open_result(); + void write_request(); + void handle_write_request(const boost::system::error_code& error); + void read_response(); + void handle_read_response(const boost::system::error_code& error, + std::size_t bytes_transferred); + + void log_open_result(); // retry once bool retry() { @@ -157,92 +157,92 @@ class client { return true; } } - private: - endpoint& m_endpoint; + private: + endpoint& m_endpoint; connection_type& m_connection; - int m_version; - uri_ptr m_uri; - std::string m_origin; - std::vector m_requested_subprotocols; - std::vector m_requested_extensions; - std::string m_subprotocol; - std::vector m_extensions; - + int m_version; + uri_ptr m_uri; + std::string m_origin; + std::vector m_requested_subprotocols; + std::vector m_requested_extensions; + std::string m_subprotocol; + std::vector m_extensions; + std::string m_handshake_key; - http::parser::request m_request; - http::parser::response m_response; + http::parser::request m_request; + http::parser::response m_response; int m_retry; - }; - - // types - typedef client type; - typedef endpoint endpoint_type; - - typedef typename endpoint_traits::connection_ptr connection_ptr; - typedef typename endpoint_traits::handler_ptr handler_ptr; - + }; + + // types + typedef client type; + typedef endpoint endpoint_type; + + typedef typename endpoint_traits::connection_ptr connection_ptr; + typedef typename endpoint_traits::handler_ptr handler_ptr; + // handler interface callback class - class handler_interface { - public: - // Required - virtual void on_open(connection_ptr connection) {}; - virtual void on_close(connection_ptr connection) {}; - virtual void on_fail(connection_ptr connection) {} - - virtual void on_message(connection_ptr connection,message::data_ptr) {}; - - // Optional - virtual bool on_ping(connection_ptr connection,std::string) {return true;} - virtual void on_pong(connection_ptr connection,std::string) {} - - }; - - client (boost::asio::io_service& m) - : m_state(UNINITIALIZED), - m_endpoint(static_cast< endpoint_type& >(*this)), - m_io_service(m), - m_resolver(m), + class handler_interface { + public: + // Required + virtual void on_open(connection_ptr connection) {}; + virtual void on_close(connection_ptr connection) {}; + virtual void on_fail(connection_ptr connection) {} + + virtual void on_message(connection_ptr connection,message::data_ptr) {}; + + // Optional + virtual bool on_ping(connection_ptr connection,std::string) {return true;} + virtual void on_pong(connection_ptr connection,std::string) {} + + }; + + client (boost::asio::io_service& m) + : m_state(UNINITIALIZED), + m_endpoint(static_cast< endpoint_type& >(*this)), + m_io_service(m), + m_resolver(m), m_gen(m_rng,boost::random::uniform_int_distribution<>(INT32_MIN, INT32_MAX)) {} - - connection_ptr connect(const std::string& u); - - // TODO: add a `perpetual` option - void run() { - m_io_service.run(); - } - - void reset() { - m_io_service.reset(); - } - + + connection_ptr connect(const std::string& u); + + // TODO: add a `perpetual` option + void run() { + m_io_service.run(); + } + + void reset() { + m_io_service.reset(); + } + protected: - bool is_server() { - return false; - } + bool is_server() { + return false; + } int32_t rand() { return m_gen(); } private: - enum state { - UNINITIALIZED = 0, - INITIALIZED = 1, - CONNECTING = 2, - CONNECTED = 3 - }; - - void handle_connect(connection_ptr con, + enum state { + UNINITIALIZED = 0, + INITIALIZED = 1, + CONNECTING = 2, + CONNECTED = 3 + }; + + void handle_connect(connection_ptr con, const boost::system::error_code& error); - - state m_state; - endpoint_type& m_endpoint; - boost::asio::io_service& m_io_service; - tcp::resolver m_resolver; + + state m_state; + endpoint_type& m_endpoint; + boost::asio::io_service& m_io_service; + tcp::resolver m_resolver; boost::random::random_device m_rng; - boost::random::variate_generator< + boost::random::variate_generator< boost::random::random_device&, boost::random::uniform_int_distribution<> > m_gen; @@ -296,17 +296,17 @@ void client::handle_connect(connection_ptr con, con->start(); } else { if (error == boost::system::errc::connection_refused) { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (connection refused)" << log::endl; - } else if (error == boost::system::errc::operation_canceled) { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (operation canceled)" << log::endl; - } else if (error == boost::system::errc::connection_reset) { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (connection reset)" << log::endl; + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (connection refused)" << log::endl; + } else if (error == boost::system::errc::operation_canceled) { + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (operation canceled)" << log::endl; + } else if (error == boost::system::errc::connection_reset) { + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (connection reset)" << log::endl; if (con->retry()) { m_endpoint.elog().at(log::elevel::ERROR) @@ -314,20 +314,20 @@ void client::handle_connect(connection_ptr con, connect(con->get_uri()); m_endpoint.remove_connection(con); } - } else if (error == boost::system::errc::timed_out) { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (operation timed out)" << log::endl; - } else if (error == boost::system::errc::broken_pipe) { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (broken pipe)" << log::endl; - } else { - m_endpoint.elog().at(log::elevel::ERROR) - << "An error occurred while establishing a connection: " - << error << " (unknown)" << log::endl; - throw "client error"; - } + } else if (error == boost::system::errc::timed_out) { + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (operation timed out)" << log::endl; + } else if (error == boost::system::errc::broken_pipe) { + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (broken pipe)" << log::endl; + } else { + m_endpoint.elog().at(log::elevel::ERROR) + << "An error occurred while establishing a connection: " + << error << " (unknown)" << log::endl; + throw "client error"; + } } } @@ -349,15 +349,15 @@ void client::connection::write_request() { m_request.replace_header("Host",m_uri->get_host_port()); if (m_origin != "") { - m_request.replace_header("Origin",m_origin); - } + m_request.replace_header("Origin",m_origin); + } // Generate client key int32_t raw_key[4]; for (int i = 0; i < 4; i++) { - raw_key[i] = this->rand(); - } + raw_key[i] = this->rand(); + } m_handshake_key = base64_encode(reinterpret_cast(raw_key), 16); @@ -386,8 +386,8 @@ void client::connection::handle_write_request( { if (error) { - - m_endpoint.elog().at(log::elevel::ERROR) << "Error writing WebSocket request. code: " << error << log::endl; + + m_endpoint.elog().at(log::elevel::ERROR) << "Error writing WebSocket request. code: " << error << log::endl; m_connection.terminate(false); return; @@ -462,33 +462,33 @@ void client::connection::handle_read_response ( m_response.get_status_msg()); } else { std::string server_key = m_handshake_key; - server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - SHA1 sha; - uint32_t message_digest[5]; - - sha.Reset(); - sha << server_key.c_str(); + SHA1 sha; + uint32_t message_digest[5]; + + sha.Reset(); + sha << server_key.c_str(); if (!sha.Result(message_digest)) { - m_endpoint.elog().at(log::elevel::ERROR) << "Error computing handshake sha1 hash." << log::endl; - // TODO: close behavior - return; - } + m_endpoint.elog().at(log::elevel::ERROR) << "Error computing handshake sha1 hash." << log::endl; + // TODO: close behavior + return; + } // convert sha1 hash bytes to network byte order because this sha1 - // library works on ints rather than bytes - for (int i = 0; i < 5; i++) { - message_digest[i] = htonl(message_digest[i]); - } + // library works on ints rather than bytes + for (int i = 0; i < 5; i++) { + message_digest[i] = htonl(message_digest[i]); + } server_key = base64_encode( reinterpret_cast(message_digest),20); if (server_key != h) { - m_endpoint.elog().at(log::elevel::ERROR) << "Server returned incorrect handshake key." << log::endl; - // TODO: close behavior - return; - } + m_endpoint.elog().at(log::elevel::ERROR) << "Server returned incorrect handshake key." << log::endl; + // TODO: close behavior + return; + } } log_open_result(); @@ -513,17 +513,17 @@ void client::connection::handle_read_response ( template template void client::connection::log_open_result() { - /*std::stringstream version; - version << "v" << m_version << " "; - - m_endpoint.alog().at(log::alevel::CONNECT) << (m_version == -1 ? "HTTP" : "WebSocket") << " Connection " - << m_connection.get_raw_socket().remote_endpoint() << " " - << (m_version == -1 ? "" : version.str()) - << (get_request_header("User-Agent") == "" ? "NULL" : get_request_header("User-Agent")) - << " " << m_uri->get_resource() << " " << m_response.get_status_code() - << log::endl;*/ + /*std::stringstream version; + version << "v" << m_version << " "; + + m_endpoint.alog().at(log::alevel::CONNECT) << (m_version == -1 ? "HTTP" : "WebSocket") << " Connection " + << m_connection.get_raw_socket().remote_endpoint() << " " + << (m_version == -1 ? "" : version.str()) + << (get_request_header("User-Agent") == "" ? "NULL" : get_request_header("User-Agent")) + << " " << m_uri->get_resource() << " " << m_response.get_status_code() + << log::endl;*/ } - + } // namespace role } // namespace websocketpp diff --git a/src/roles/server.hpp b/src/roles/server.hpp index 866424dfc..0c0f431ad 100644 --- a/src/roles/server.hpp +++ b/src/roles/server.hpp @@ -51,158 +51,158 @@ namespace role { template class server { public: - // Connection specific details - template - class connection { - public: - typedef connection type; - typedef endpoint endpoint_type; - - // Valid always + // Connection specific details + template + class connection { + public: + typedef connection type; + typedef endpoint endpoint_type; + + // Valid always int get_version() const { - return m_version; - } - std::string get_request_header(const std::string& key) const { - return m_request.header(key); - } - std::string get_origin() const { - return m_origin; - } - - // Information about the requested URI - // valid only after URIs are loaded - // TODO: check m_uri for NULLness - bool get_secure() const { - return m_uri->get_secure(); - } - std::string get_host() const { - return m_uri->get_host(); - } - std::string get_resource() const { - return m_uri->get_resource(); - } - uint16_t get_port() const { - return m_uri->get_port(); - } - - // Valid for CONNECTING state - void add_response_header(const std::string& key, const std::string& value) { - m_response.add_header(key,value); - } - void replace_response_header(const std::string& key, const std::string& value) { - m_response.replace_header(key,value); - } - void remove_response_header(const std::string& key) { - m_response.remove_header(key); - } - - const std::vector& get_subprotocols() const { - return m_requested_subprotocols; - } - const std::vector& get_extensions() const { - return m_requested_extensions; - } - void select_subprotocol(const std::string& value); - void select_extension(const std::string& value); - - // Valid if get_version() returns -1 (ie this is an http connection) - void set_body(const std::string& value); - - int32_t rand() { + return m_version; + } + std::string get_request_header(const std::string& key) const { + return m_request.header(key); + } + std::string get_origin() const { + return m_origin; + } + + // Information about the requested URI + // valid only after URIs are loaded + // TODO: check m_uri for NULLness + bool get_secure() const { + return m_uri->get_secure(); + } + std::string get_host() const { + return m_uri->get_host(); + } + std::string get_resource() const { + return m_uri->get_resource(); + } + uint16_t get_port() const { + return m_uri->get_port(); + } + + // Valid for CONNECTING state + void add_response_header(const std::string& key, const std::string& value) { + m_response.add_header(key,value); + } + void replace_response_header(const std::string& key, const std::string& value) { + m_response.replace_header(key,value); + } + void remove_response_header(const std::string& key) { + m_response.remove_header(key); + } + + const std::vector& get_subprotocols() const { + return m_requested_subprotocols; + } + const std::vector& get_extensions() const { + return m_requested_extensions; + } + void select_subprotocol(const std::string& value); + void select_extension(const std::string& value); + + // Valid if get_version() returns -1 (ie this is an http connection) + void set_body(const std::string& value); + + int32_t rand() { return 0; } - + bool is_server() const { return true; } - // should this exist? - boost::asio::io_service& get_io_service() { - return m_endpoint.get_io_service(); - } - protected: - connection(endpoint& e) + // should this exist? + boost::asio::io_service& get_io_service() { + return m_endpoint.get_io_service(); + } + protected: + connection(endpoint& e) : m_endpoint(e), m_connection(static_cast< connection_type& >(*this)), m_version(-1), m_uri() {} - - // initializes the websocket connection - void async_init(); - void handle_read_request(const boost::system::error_code& error, - std::size_t bytes_transferred); - void write_response(); - void handle_write_response(const boost::system::error_code& error); - - void log_open_result(); - private: - endpoint& m_endpoint; - connection_type& m_connection; - - int m_version; - uri_ptr m_uri; - std::string m_origin; - std::vector m_requested_subprotocols; - std::vector m_requested_extensions; - std::string m_subprotocol; - std::vector m_extensions; - - http::parser::request m_request; - http::parser::response m_response; - blank_rng m_rng; - }; - - // types - typedef server type; - typedef endpoint endpoint_type; - - typedef typename endpoint_traits::connection_ptr connection_ptr; - typedef typename endpoint_traits::handler_ptr handler_ptr; - - // handler interface callback base class + + // initializes the websocket connection + void async_init(); + void handle_read_request(const boost::system::error_code& error, + std::size_t bytes_transferred); + void write_response(); + void handle_write_response(const boost::system::error_code& error); + + void log_open_result(); + private: + endpoint& m_endpoint; + connection_type& m_connection; + + int m_version; + uri_ptr m_uri; + std::string m_origin; + std::vector m_requested_subprotocols; + std::vector m_requested_extensions; + std::string m_subprotocol; + std::vector m_extensions; + + http::parser::request m_request; + http::parser::response m_response; + blank_rng m_rng; + }; + + // types + typedef server type; + typedef endpoint endpoint_type; + + typedef typename endpoint_traits::connection_ptr connection_ptr; + typedef typename endpoint_traits::handler_ptr handler_ptr; + + // handler interface callback base class class handler_interface { - public: - virtual void validate(connection_ptr connection) {} - virtual void on_open(connection_ptr connection) {} - virtual void on_close(connection_ptr connection) {} - virtual void on_fail(connection_ptr connection) {} - - virtual void on_message(connection_ptr connection,message::data_ptr) {}; - - virtual bool on_ping(connection_ptr connection,std::string) {return true;} - virtual void on_pong(connection_ptr connection,std::string) {} - virtual void http(connection_ptr connection) {} - }; - - server(boost::asio::io_service& m) - : m_ws_endpoint(static_cast< endpoint_type& >(*this)), - m_io_service(m), + public: + virtual void validate(connection_ptr connection) {} + virtual void on_open(connection_ptr connection) {} + virtual void on_close(connection_ptr connection) {} + virtual void on_fail(connection_ptr connection) {} + + virtual void on_message(connection_ptr connection,message::data_ptr) {}; + + virtual bool on_ping(connection_ptr connection,std::string) {return true;} + virtual void on_pong(connection_ptr connection,std::string) {} + virtual void http(connection_ptr connection) {} + }; + + server(boost::asio::io_service& m) + : m_ws_endpoint(static_cast< endpoint_type& >(*this)), + m_io_service(m), // the only way to set an endpoint address family appears to be using // this constructor, which also requires a port. This port number can be // ignored, as it is always overwriten later by the listen() member func - m_endpoint(boost::asio::ip::tcp::v6(),9000), - m_acceptor(m), + m_endpoint(boost::asio::ip::tcp::v6(),9000), + m_acceptor(m), m_timer(m,boost::posix_time::seconds(0)) {} - + void listen(uint16_t port); protected: - bool is_server() { - return true; - } + bool is_server() { + return true; + } private: - // start_accept creates a new connection and begins an async_accept on it - void start_accept(); - - // handle_accept will begin the connection's read/write loop and then reset - // the server to accept a new connection. Errors returned by async_accept - // are logged and ingored. - void handle_accept(connection_ptr con, + // start_accept creates a new connection and begins an async_accept on it + void start_accept(); + + // handle_accept will begin the connection's read/write loop and then reset + // the server to accept a new connection. Errors returned by async_accept + // are logged and ingored. + void handle_accept(connection_ptr con, const boost::system::error_code& error); - - endpoint_type& m_ws_endpoint; - boost::asio::io_service& m_io_service; - boost::asio::ip::tcp::endpoint m_endpoint; - boost::asio::ip::tcp::acceptor m_acceptor; + + endpoint_type& m_ws_endpoint; + boost::asio::io_service& m_io_service; + boost::asio::ip::tcp::endpoint m_endpoint; + boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::deadline_timer m_timer; }; @@ -246,18 +246,18 @@ void server::handle_accept(connection_ptr con, const boost::system::error_code& error) { if (error) { - if (error == boost::system::errc::too_many_files_open) { - m_ws_endpoint.elog().at(log::elevel::ERROR) - << "async_accept returned error: " << error - << " (too many files open)" << log::endl; + if (error == boost::system::errc::too_many_files_open) { + m_ws_endpoint.elog().at(log::elevel::ERROR) + << "async_accept returned error: " << error + << " (too many files open)" << log::endl; m_timer.expires_from_now(boost::posix_time::milliseconds(1000)); m_timer.async_wait(boost::bind(&type::start_accept,this)); return; - } else { - m_ws_endpoint.elog().at(log::elevel::ERROR) - << "async_accept returned error: " << error - << " (unknown)" << log::endl; - } + } else { + m_ws_endpoint.elog().at(log::elevel::ERROR) + << "async_accept returned error: " << error + << " (unknown)" << log::endl; + } } else { con->start(); } @@ -533,19 +533,19 @@ void server::connection::log_open_result() { std::stringstream version; version << "v" << m_version << " "; - std::string remote; - boost::system::error_code ec; - boost::asio::ip::tcp::endpoint ep = m_connection.get_raw_socket().remote_endpoint(ec); - if (ec) { - // An error occurred. - //remote = "Unknown"; - //ignore? - m_endpoint.elog().at(log::elevel::WARN) << "Error getting remote endpoint. code: " << ec << log::endl; - } else { - - } - - + std::string remote; + boost::system::error_code ec; + boost::asio::ip::tcp::endpoint ep = m_connection.get_raw_socket().remote_endpoint(ec); + if (ec) { + // An error occurred. + //remote = "Unknown"; + //ignore? + m_endpoint.elog().at(log::elevel::WARN) << "Error getting remote endpoint. code: " << ec << log::endl; + } else { + + } + + m_endpoint.alog().at(log::alevel::CONNECT) << (m_version == -1 ? "HTTP" : "WebSocket") << " Connection " << ep << " " << (m_version == -1 ? "" : version.str()) @@ -554,7 +554,7 @@ void server::connection::log_open_result() { << log::endl; } -} // namespace role +} // namespace role } // namespace websocketpp #endif // WEBSOCKETPP_ROLE_SERVER_HPP diff --git a/src/sockets/plain.hpp b/src/sockets/plain.hpp index e6dbcf82c..875a681ed 100644 --- a/src/sockets/plain.hpp +++ b/src/sockets/plain.hpp @@ -41,67 +41,67 @@ namespace socket { template class plain { public: - boost::asio::io_service& get_io_service() { - return m_io_service; - } - - bool is_secure() { - return false; - } - - // plain sockets do not add anything to the handler interface - class handler_interface {}; - - // Connection specific details - template - class connection { - public: - // should these two be public or protected. If protected, how? - boost::asio::ip::tcp::socket& get_raw_socket() { - return m_socket; - } - - boost::asio::ip::tcp::socket& get_socket() { - return m_socket; - } - - bool is_secure() { - return false; - } - protected: - connection(plain& e) : m_socket(e.get_io_service()) {} - - void init() { - - } - - void async_init(socket_init_callback callback) { - // TODO: should this use post()? - //m_socket.set_option(boost::asio::ip::tcp::no_delay(true)); - - callback(boost::system::error_code()); - } - - bool shutdown() { - boost::system::error_code ignored_ec; - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both,ignored_ec); - - if (ignored_ec) { - return false; - } else { - return true; - } - } - private: - boost::asio::ip::tcp::socket m_socket; - }; + boost::asio::io_service& get_io_service() { + return m_io_service; + } + + bool is_secure() { + return false; + } + + // plain sockets do not add anything to the handler interface + class handler_interface {}; + + // Connection specific details + template + class connection { + public: + // should these two be public or protected. If protected, how? + boost::asio::ip::tcp::socket& get_raw_socket() { + return m_socket; + } + + boost::asio::ip::tcp::socket& get_socket() { + return m_socket; + } + + bool is_secure() { + return false; + } + protected: + connection(plain& e) : m_socket(e.get_io_service()) {} + + void init() { + + } + + void async_init(socket_init_callback callback) { + // TODO: should this use post()? + //m_socket.set_option(boost::asio::ip::tcp::no_delay(true)); + + callback(boost::system::error_code()); + } + + bool shutdown() { + boost::system::error_code ignored_ec; + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both,ignored_ec); + + if (ignored_ec) { + return false; + } else { + return true; + } + } + private: + boost::asio::ip::tcp::socket m_socket; + }; protected: - plain (boost::asio::io_service& m) : m_io_service(m) {} + plain (boost::asio::io_service& m) : m_io_service(m) {} private: - boost::asio::io_service& m_io_service; + boost::asio::io_service& m_io_service; }; - + } // namespace socket } // namespace websocketpp diff --git a/src/sockets/ssl.hpp b/src/sockets/ssl.hpp index 78ee78aa6..16c4fb342 100644 --- a/src/sockets/ssl.hpp +++ b/src/sockets/ssl.hpp @@ -42,115 +42,115 @@ namespace socket { template class ssl { public: - typedef ssl type; - typedef boost::asio::ssl::stream ssl_socket; - typedef boost::shared_ptr ssl_socket_ptr; - - // should be private friended - boost::asio::io_service& get_io_service() { - return m_io_service; - } - - // should be private friended? - ssl_socket::handshake_type get_handshake_type() { - if (static_cast< endpoint_type* >(this)->is_server()) { - return boost::asio::ssl::stream_base::server; - } else { - return boost::asio::ssl::stream_base::client; - } - } - - bool is_secure() { - return true; - } - - // TLS policy adds the on_tls_init method to the handler to allow the user - // to set up their asio TLS context. - class handler_interface { - public: - virtual boost::shared_ptr on_tls_init() = 0; - }; - - // Connection specific details - template - class connection { - public: - // should these two be public or protected. If protected, how? - ssl_socket::lowest_layer_type& get_raw_socket() { - return m_socket_ptr->lowest_layer(); - } - - ssl_socket& get_socket() { - return *m_socket_ptr; - } - - bool is_secure() { - return true; - } - protected: - connection(ssl& e) - : m_endpoint(e), - m_connection(static_cast< connection_type& >(*this)) {} - - void init() { - m_context_ptr = m_connection.get_handler()->on_tls_init(); - + typedef ssl type; + typedef boost::asio::ssl::stream ssl_socket; + typedef boost::shared_ptr ssl_socket_ptr; + + // should be private friended + boost::asio::io_service& get_io_service() { + return m_io_service; + } + + // should be private friended? + ssl_socket::handshake_type get_handshake_type() { + if (static_cast< endpoint_type* >(this)->is_server()) { + return boost::asio::ssl::stream_base::server; + } else { + return boost::asio::ssl::stream_base::client; + } + } + + bool is_secure() { + return true; + } + + // TLS policy adds the on_tls_init method to the handler to allow the user + // to set up their asio TLS context. + class handler_interface { + public: + virtual boost::shared_ptr on_tls_init() = 0; + }; + + // Connection specific details + template + class connection { + public: + // should these two be public or protected. If protected, how? + ssl_socket::lowest_layer_type& get_raw_socket() { + return m_socket_ptr->lowest_layer(); + } + + ssl_socket& get_socket() { + return *m_socket_ptr; + } + + bool is_secure() { + return true; + } + protected: + connection(ssl& e) + : m_endpoint(e), + m_connection(static_cast< connection_type& >(*this)) {} + + void init() { + m_context_ptr = m_connection.get_handler()->on_tls_init(); + if (!m_context_ptr) { throw "handler was unable to init tls, connection error"; } m_socket_ptr = ssl_socket_ptr(new ssl_socket(m_endpoint.get_io_service(),*m_context_ptr)); - } - - void async_init(boost::function callback) - { - m_socket_ptr->async_handshake( - m_endpoint.get_handshake_type(), - boost::bind( - &connection::handle_init, - this, - callback, - boost::asio::placeholders::error - ) - ); - } - - void handle_init(socket_init_callback callback,const boost::system::error_code& error) { - /*if (error) { - std::cout << "SSL handshake error" << std::endl; - } else { - //static_cast< connection_type* >(this)->websocket_handshake(); - - }*/ - callback(error); - } - + } + + void async_init(boost::function callback) + { + m_socket_ptr->async_handshake( + m_endpoint.get_handshake_type(), + boost::bind( + &connection::handle_init, + this, + callback, + boost::asio::placeholders::error + ) + ); + } + + void handle_init(socket_init_callback callback,const boost::system::error_code& error) { + /*if (error) { + std::cout << "SSL handshake error" << std::endl; + } else { + //static_cast< connection_type* >(this)->websocket_handshake(); + + }*/ + callback(error); + } + // note, this function for some reason shouldn't/doesn't need to be // called for plain HTTP connections. not sure why. - bool shutdown() { - boost::system::error_code ignored_ec; - - m_socket_ptr->shutdown(ignored_ec); - - if (ignored_ec) { - return false; - } else { - return true; - } - } - private: - boost::shared_ptr m_context_ptr; - ssl_socket_ptr m_socket_ptr; - ssl& m_endpoint; - connection_type& m_connection; - }; + bool shutdown() { + boost::system::error_code ignored_ec; + + m_socket_ptr->shutdown(ignored_ec); + + if (ignored_ec) { + return false; + } else { + return true; + } + } + private: + boost::shared_ptr m_context_ptr; + ssl_socket_ptr m_socket_ptr; + ssl& m_endpoint; + connection_type& m_connection; + }; protected: - ssl (boost::asio::io_service& m) : m_io_service(m) {} + ssl (boost::asio::io_service& m) : m_io_service(m) {} private: - boost::asio::io_service& m_io_service; - ssl_socket::handshake_type m_handshake_type; + boost::asio::io_service& m_io_service; + ssl_socket::handshake_type m_handshake_type; }; - + } // namespace socket } // namespace websocketpp diff --git a/src/uri.cpp b/src/uri.cpp index 6064b9336..2235dc295 100644 --- a/src/uri.cpp +++ b/src/uri.cpp @@ -174,38 +174,38 @@ uri::uri(const std::string& uri) { boost::cmatch matches; - static const boost::regex expression("(ws|wss)://([^/:\\[]+|\\[[0-9a-fA-F:.]+\\])(:\\d{1,5})?(/[^#]*)?"); - - // TODO: should this split resource into path/query? - - if (boost::regex_match(uri.c_str(), matches, expression)) { - m_secure = (matches[1] == "wss"); - m_host = matches[2]; - + static const boost::regex expression("(ws|wss)://([^/:\\[]+|\\[[0-9a-fA-F:.]+\\])(:\\d{1,5})?(/[^#]*)?"); + + // TODO: should this split resource into path/query? + + if (boost::regex_match(uri.c_str(), matches, expression)) { + m_secure = (matches[1] == "wss"); + m_host = matches[2]; + // strip brackets from IPv6 literal URIs if (m_host[0] == '[') { m_host = m_host.substr(1,m_host.size()-2); } - std::string port(matches[3]); - - if (port != "") { - // strip off the : - // this could probably be done with a better regex. - port = port.substr(1); - } - - m_port = get_port_from_string(port); - - m_resource = matches[4]; - - if (m_resource == "") { - m_resource = "/"; - } - - return; - } - + std::string port(matches[3]); + + if (port != "") { + // strip off the : + // this could probably be done with a better regex. + port = port.substr(1); + } + + m_port = get_port_from_string(port); + + m_resource = matches[4]; + + if (m_resource == "") { + m_resource = "/"; + } + + return; + } + throw websocketpp::uri_exception("Error parsing WebSocket URI"); } @@ -243,8 +243,8 @@ uri::uri(bool secure, m_resource(resource == "" ? "/" : resource) { if (m_port > 65535) { - throw websocketpp::uri_exception("Port must be less than 65535"); - } + throw websocketpp::uri_exception("Port must be less than 65535"); + } } uri::uri(bool secure, @@ -256,65 +256,65 @@ uri::uri(bool secure, */ bool uri::get_secure() const { - return m_secure; + return m_secure; } std::string uri::get_host() const { - return m_host; + return m_host; } std::string uri::get_host_port() const { - if (m_port == (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT)) { - return m_host; - } else { - std::stringstream p; - p << m_host << ":" << m_port; - return p.str(); - } - + if (m_port == (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT)) { + return m_host; + } else { + std::stringstream p; + p << m_host << ":" << m_port; + return p.str(); + } + } uint16_t uri::get_port() const { - return m_port; + return m_port; } std::string uri::get_port_str() const { - std::stringstream p; - p << m_port; - return p.str(); + std::stringstream p; + p << m_port; + return p.str(); } std::string uri::get_resource() const { - return m_resource; + return m_resource; } std::string uri::str() const { - std::stringstream s; - - s << "ws" << (m_secure ? "s" : "") << "://" << m_host; - - if (m_port != (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT)) { - s << ":" << m_port; - } - - s << m_resource; - return s.str(); + std::stringstream s; + + s << "ws" << (m_secure ? "s" : "") << "://" << m_host; + + if (m_port != (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT)) { + s << ":" << m_port; + } + + s << m_resource; + return s.str(); } uint16_t uri::get_port_from_string(const std::string& port) const { - if (port == "") { - return (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT); - } - - unsigned int t_port = atoi(port.c_str()); - - if (t_port > 65535) { - throw websocketpp::uri_exception("Port must be less than 65535"); - } - - if (t_port == 0) { - throw websocketpp::uri_exception("Error parsing port string: "+port); - } - - return t_port; + if (port == "") { + return (m_secure ? URI_DEFAULT_SECURE_PORT : URI_DEFAULT_PORT); + } + + unsigned int t_port = atoi(port.c_str()); + + if (t_port > 65535) { + throw websocketpp::uri_exception("Port must be less than 65535"); + } + + if (t_port == 0) { + throw websocketpp::uri_exception("Error parsing port string: "+port); + } + + return t_port; } \ No newline at end of file diff --git a/src/uri.hpp b/src/uri.hpp index 3e0fc49bf..26bcc9831 100644 --- a/src/uri.hpp +++ b/src/uri.hpp @@ -37,7 +37,7 @@ namespace websocketpp { // WebSocket URI only (not http/etc) class uri_exception : public std::exception { -public: +public: uri_exception(const std::string& msg) : m_msg(msg) {} ~uri_exception() throw() {} @@ -51,21 +51,19 @@ class uri_exception : public std::exception { // TODO: figure out why this fixes horrible linking errors. static const uint16_t URI_DEFAULT_PORT = 80; static const uint16_t URI_DEFAULT_SECURE_PORT = 443; - + class uri { public: - - explicit uri(const std::string& uri); uri(bool secure, const std::string& host, uint16_t port, const std::string& resource); - uri(bool secure, const std::string& host, const std::string& resource); + uri(bool secure, const std::string& host, const std::string& resource); uri(bool secure, const std::string& host, const std::string& port, const std::string& resource); bool get_secure() const; std::string get_host() const; - std::string get_host_port() const; + std::string get_host_port() const; uint16_t get_port() const; - std::string get_port_str() const; + std::string get_port_str() const; std::string get_resource() const; std::string str() const; @@ -97,7 +95,7 @@ class uri { }; typedef boost::shared_ptr uri_ptr; - + } // namespace websocketpp #endif // WEBSOCKETPP_URI_HPP diff --git a/src/utf8_validator/utf8_validator.hpp b/src/utf8_validator/utf8_validator.hpp index a7c3bd6d4..37b95e3e0 100644 --- a/src/utf8_validator/utf8_validator.hpp +++ b/src/utf8_validator/utf8_validator.hpp @@ -39,52 +39,52 @@ decode(uint32_t* state, uint32_t* codep, uint8_t byte) { *state = utf8d[256 + *state*16 + type]; return *state; } - + class validator { public: - validator() : m_state(UTF8_ACCEPT),m_codepoint(0) {} - - bool consume (uint32_t byte) { - if (utf8_validator::decode(&m_state,&m_codepoint,byte) == UTF8_REJECT) { - return false; - } - return true; - } - - template - bool decode (iterator_type b, iterator_type e) { - for (iterator_type i = b; i != e; i++) { - if (utf8_validator::decode(&m_state,&m_codepoint,*i) == UTF8_REJECT) { - return false; - } - } - return true; - } - - bool complete() { - return m_state == UTF8_ACCEPT; - } - - void reset() { - m_state = UTF8_ACCEPT; - m_codepoint = 0; - } + validator() : m_state(UTF8_ACCEPT),m_codepoint(0) {} + + bool consume (uint32_t byte) { + if (utf8_validator::decode(&m_state,&m_codepoint,byte) == UTF8_REJECT) { + return false; + } + return true; + } + + template + bool decode (iterator_type b, iterator_type e) { + for (iterator_type i = b; i != e; i++) { + if (utf8_validator::decode(&m_state,&m_codepoint,*i) == UTF8_REJECT) { + return false; + } + } + return true; + } + + bool complete() { + return m_state == UTF8_ACCEPT; + } + + void reset() { + m_state = UTF8_ACCEPT; + m_codepoint = 0; + } private: - uint32_t m_state; - uint32_t m_codepoint; + uint32_t m_state; + uint32_t m_codepoint; }; // convenience function that creates a validator, validates a complete string // and returns the result. // TODO: should this be inline? inline bool validate(const std::string& s) { - validator v; - if (!v.decode(s.begin(),s.end())) { - return false; - } - return v.complete(); + validator v; + if (!v.decode(s.begin(),s.end())) { + return false; + } + return v.complete(); } - + } // namespace utf8_validator #endif // UTF8_VALIDATOR_HPP \ No newline at end of file diff --git a/src/websocket_frame.hpp b/src/websocket_frame.hpp index 07adb597d..86c3a6219 100644 --- a/src/websocket_frame.hpp +++ b/src/websocket_frame.hpp @@ -49,7 +49,7 @@ namespace websocketpp { namespace frame { - + /* policies to abstract out - random number generation @@ -61,575 +61,575 @@ rng class boost_random { public: - boost_random() - int32_t gen(); + boost_random() + int32_t gen(); private: boost::random::random_device m_rng; boost::random::variate_generator > m_gen; } */ - + template class parser { public: - // basic payload byte flags - static const uint8_t BPB0_OPCODE = 0x0F; - static const uint8_t BPB0_RSV3 = 0x10; - static const uint8_t BPB0_RSV2 = 0x20; - static const uint8_t BPB0_RSV1 = 0x40; - static const uint8_t BPB0_FIN = 0x80; - static const uint8_t BPB1_PAYLOAD = 0x7F; - static const uint8_t BPB1_MASK = 0x80; - - static const uint8_t BASIC_PAYLOAD_16BIT_CODE = 0x7E; // 126 - static const uint8_t BASIC_PAYLOAD_64BIT_CODE = 0x7F; // 127 - - static const unsigned int BASIC_HEADER_LENGTH = 2; - static const unsigned int MAX_HEADER_LENGTH = 14; - static const uint8_t extended_header_length = 12; - static const uint64_t max_payload_size = 100000000; // 100MB - - // create an empty frame for writing into - parser(rng_policy& rng) : m_rng(rng) { - reset(); - } - - bool ready() const { - return (m_state == STATE_READY); - } - uint64_t get_bytes_needed() const { - return m_bytes_needed; - } - void reset() { - m_state = STATE_BASIC_HEADER; - m_bytes_needed = BASIC_HEADER_LENGTH; - m_degraded = false; - m_payload.clear(); - memset(m_header,0,MAX_HEADER_LENGTH); - } - - // Method invariant: One of the following must always be true even in the case - // of exceptions. - // - m_bytes_needed > 0 - // - m-state = STATE_READY - void consume(std::istream &s) { - try { - switch (m_state) { - case STATE_BASIC_HEADER: - s.read(&m_header[BASIC_HEADER_LENGTH-m_bytes_needed],m_bytes_needed); - - m_bytes_needed -= s.gcount(); - - if (m_bytes_needed == 0) { - process_basic_header(); - - validate_basic_header(); - - if (m_bytes_needed > 0) { - m_state = STATE_EXTENDED_HEADER; - } else { - process_extended_header(); - - if (m_bytes_needed == 0) { - m_state = STATE_READY; - process_payload(); - - } else { - m_state = STATE_PAYLOAD; - } - } - } - break; - case STATE_EXTENDED_HEADER: - s.read(&m_header[get_header_len()-m_bytes_needed],m_bytes_needed); - - m_bytes_needed -= s.gcount(); - - if (m_bytes_needed == 0) { - process_extended_header(); - if (m_bytes_needed == 0) { - m_state = STATE_READY; - process_payload(); - } else { - m_state = STATE_PAYLOAD; - } - } - break; - case STATE_PAYLOAD: - s.read(reinterpret_cast(&m_payload[m_payload.size()-m_bytes_needed]), - m_bytes_needed); - - m_bytes_needed -= s.gcount(); - - if (m_bytes_needed == 0) { - m_state = STATE_READY; - process_payload(); - } - break; - case STATE_RECOVERY: - // Recovery state discards all bytes that are not the first byte - // of a close frame. - do { - s.read(reinterpret_cast(&m_header[0]),1); - - //std::cout << std::hex << int(static_cast(m_header[0])) << " "; - - if (int(static_cast(m_header[0])) == 0x88) { - //(BPB0_FIN && CONNECTION_CLOSE) - m_bytes_needed--; - m_state = STATE_BASIC_HEADER; - break; - } - } while (s.gcount() > 0); - - //std::cout << std::endl; - - break; - default: - break; - } - - /*if (s.gcount() == 0) { - throw frame_error("consume read zero bytes",FERR_FATAL_SESSION_ERROR); - }*/ - } catch (const processor::exception& e) { - // After this point all non-close frames must be considered garbage, - // including the current one. Reset it and put the reading frame into - // a recovery state. - if (m_degraded == true) { - throw processor::exception("An error occurred while trying to gracefully recover from a less serious frame error.",processor::error::FATAL_ERROR); - } else { - reset(); - m_state = STATE_RECOVERY; - m_degraded = true; - - throw e; - } - } - } - - // get pointers to underlying buffers - char* get_header() { - return m_header; - } - char* get_extended_header() { - return m_header+BASIC_HEADER_LENGTH; - } - unsigned int get_header_len() const { - unsigned int temp = 2; - - if (get_masked()) { - temp += 4; - } - - if (get_basic_size() == 126) { - temp += 2; - } else if (get_basic_size() == 127) { - temp += 8; - } - - return temp; - } - - char* get_masking_key() { - /*if (m_state != STATE_READY) { - std::cout << "throw" << std::endl; - throw processor::exception("attempted to get masking_key before reading full header"); - }*/ - return &m_header[get_header_len()-4]; - } - - // get and set header bits - bool get_fin() const { - return ((m_header[0] & BPB0_FIN) == BPB0_FIN); - } - void set_fin(bool fin) { - if (fin) { - m_header[0] |= BPB0_FIN; - } else { - m_header[0] &= (0xFF ^ BPB0_FIN); - } - } - - bool get_rsv1() const { - return ((m_header[0] & BPB0_RSV1) == BPB0_RSV1); - } - void set_rsv1(bool b) { - if (b) { - m_header[0] |= BPB0_RSV1; - } else { - m_header[0] &= (0xFF ^ BPB0_RSV1); - } - } - - bool get_rsv2() const { - return ((m_header[0] & BPB0_RSV2) == BPB0_RSV2); - } - void set_rsv2(bool b) { - if (b) { - m_header[0] |= BPB0_RSV2; - } else { - m_header[0] &= (0xFF ^ BPB0_RSV2); - } - } - - bool get_rsv3() const { - return ((m_header[0] & BPB0_RSV3) == BPB0_RSV3); - } - void set_rsv3(bool b) { - if (b) { - m_header[0] |= BPB0_RSV3; - } else { - m_header[0] &= (0xFF ^ BPB0_RSV3); - } - } - - opcode::value get_opcode() const { - return frame::opcode::value(m_header[0] & BPB0_OPCODE); - } - void set_opcode(opcode::value op) { - if (opcode::reserved(op)) { - throw processor::exception("reserved opcode",processor::error::PROTOCOL_VIOLATION); - } - - if (opcode::invalid(op)) { - throw processor::exception("invalid opcode",processor::error::PROTOCOL_VIOLATION); - } - - if (is_control() && get_basic_size() > limits::PAYLOAD_SIZE_BASIC) { - throw processor::exception("control frames can't have large payloads",processor::error::PROTOCOL_VIOLATION); - } - - m_header[0] &= (0xFF ^ BPB0_OPCODE); // clear op bits - m_header[0] |= op; // set op bits - } - - bool get_masked() const { - return ((m_header[1] & BPB1_MASK) == BPB1_MASK); - } - void set_masked(bool masked) { - if (masked) { - m_header[1] |= BPB1_MASK; - generate_masking_key(); - } else { - m_header[1] &= (0xFF ^ BPB1_MASK); - clear_masking_key(); - } - } - - uint8_t get_basic_size() const { - return m_header[1] & BPB1_PAYLOAD; - } - size_t get_payload_size() const { - if (m_state != STATE_READY && m_state != STATE_PAYLOAD) { - // TODO: how to handle errors like this? - throw "attempted to get payload size before reading full header"; - } - - return m_payload.size(); - } - - close::status::value get_close_status() const { - if (get_payload_size() == 0) { - return close::status::NO_STATUS; - } else if (get_payload_size() >= 2) { - char val[2]; - - val[0] = m_payload[0]; - val[1] = m_payload[1]; - - uint16_t code = ntohs(*(reinterpret_cast(&val[0]))); - - return close::status::value(code); - } else { - return close::status::PROTOCOL_ERROR; - } - } - std::string get_close_msg() const { - if (get_payload_size() > 2) { - uint32_t state = utf8_validator::UTF8_ACCEPT; - uint32_t codep = 0; - validate_utf8(&state,&codep,2); - if (state != utf8_validator::UTF8_ACCEPT) { - throw processor::exception("Invalid UTF-8 Data",processor::error::PAYLOAD_VIOLATION); - } - return std::string(m_payload.begin()+2,m_payload.end()); - } else { - return std::string(); - } - } - - std::vector &get_payload() { - return m_payload; - } - - void set_payload(const std::vector& source) { - set_payload_helper(source.size()); - - std::copy(source.begin(),source.end(),m_payload.begin()); - } - void set_payload(const std::string& source) { - set_payload_helper(source.size()); - - std::copy(source.begin(),source.end(),m_payload.begin()); - } - void set_payload_helper(size_t s) { - if (s > max_payload_size) { - throw processor::exception("requested payload is over implementation defined limit",processor::error::MESSAGE_TOO_BIG); - } - - // limits imposed by the websocket spec - if (is_control() && s > limits::PAYLOAD_SIZE_BASIC) { - throw processor::exception("control frames can't have large payloads",processor::error::PROTOCOL_VIOLATION); - } - - bool masked = get_masked(); - - if (s <= limits::PAYLOAD_SIZE_BASIC) { - m_header[1] = s; - } else if (s <= limits::PAYLOAD_SIZE_EXTENDED) { - m_header[1] = BASIC_PAYLOAD_16BIT_CODE; - - // this reinterprets the second pair of bytes in m_header as a - // 16 bit int and writes the payload size there as an integer - // in network byte order - *reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) = htons(s); - } else if (s <= limits::PAYLOAD_SIZE_JUMBO) { - m_header[1] = BASIC_PAYLOAD_64BIT_CODE; - *reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) = htonll(s); - } else { - throw processor::exception("payload size limit is 63 bits",processor::error::PROTOCOL_VIOLATION); - } - - if (masked) { - m_header[1] |= BPB1_MASK; - } - - m_payload.resize(s); - } - - void set_status(close::status::value status,const std::string message = "") { - // check for valid statuses - if (close::status::invalid(status)) { - std::stringstream err; - err << "Status code " << status << " is invalid"; - throw processor::exception(err.str()); - } - - if (close::status::reserved(status)) { - std::stringstream err; - err << "Status code " << status << " is reserved"; - throw processor::exception(err.str()); - } - - m_payload.resize(2+message.size()); - - char val[2]; - - *reinterpret_cast(&val[0]) = htons(status); - - bool masked = get_masked(); - - m_header[1] = message.size()+2; - - if (masked) { - m_header[1] |= BPB1_MASK; - } - - m_payload[0] = val[0]; - m_payload[1] = val[1]; - - std::copy(message.begin(),message.end(),m_payload.begin()+2); - } - - bool is_control() const { - return (opcode::is_control(get_opcode())); - } - - std::string print_frame() const { - std::stringstream f; - - unsigned int len = get_header_len(); - - f << "frame: "; - // print header - for (unsigned int i = 0; i < len; i++) { - f << std::hex << (unsigned short)m_header[i] << " "; - } - // print message - if (m_payload.size() > 50) { - f << "[payload of " << m_payload.size() << " bytes]"; - } else { - std::vector::const_iterator it; - for (it = m_payload.begin(); it != m_payload.end(); it++) { - f << *it; - } - } - return f.str(); - } - - // reads basic header, sets and returns m_header_bits_needed - void process_basic_header() { - m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH; - } - void process_extended_header() { - uint8_t s = get_basic_size(); - uint64_t payload_size; - int mask_index = BASIC_HEADER_LENGTH; - - if (s <= limits::PAYLOAD_SIZE_BASIC) { - payload_size = s; - } else if (s == BASIC_PAYLOAD_16BIT_CODE) { - // reinterpret the second two bytes as a 16 bit integer in network - // byte order. Convert to host byte order and store locally. - payload_size = ntohs(*( - reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) - )); - - if (payload_size < s) { - std::stringstream err; - err << "payload length not minimally encoded. Using 16 bit form for payload size: " << payload_size; - m_bytes_needed = payload_size; - throw processor::exception(err.str(),processor::error::PROTOCOL_VIOLATION); - } - - mask_index += 2; - } else if (s == BASIC_PAYLOAD_64BIT_CODE) { - // reinterpret the second eight bytes as a 64 bit integer in - // network byte order. Convert to host byte order and store. - payload_size = ntohll(*( - reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) - )); - - if (payload_size <= limits::PAYLOAD_SIZE_EXTENDED) { - m_bytes_needed = payload_size; - throw processor::exception("payload length not minimally encoded", - processor::error::PROTOCOL_VIOLATION); - } - - mask_index += 8; - } else { - // TODO: shouldn't be here how to handle? - throw processor::exception("invalid get_basic_size in process_extended_header"); - } - - if (get_masked() == 0) { - clear_masking_key(); - } else { - // TODO: this should be removed entirely once it is confirmed to not - // be used by anything. - // std::copy(m_header[mask_index],m_header[mask_index+4],m_masking_key); - /*m_masking_key[0] = m_header[mask_index+0]; - m_masking_key[1] = m_header[mask_index+1]; - m_masking_key[2] = m_header[mask_index+2]; - m_masking_key[3] = m_header[mask_index+3];*/ - } - - if (payload_size > max_payload_size) { - // TODO: frame/message size limits - // TODO: find a way to throw a server error without coupling frame - // with server - // throw websocketpp::server_error("got frame with payload greater than maximum frame buffer size."); - throw "Got frame with payload greater than maximum frame buffer size."; - } - m_payload.resize(payload_size); - m_bytes_needed = payload_size; - } - - void process_payload() { - if (get_masked()) { - char *masking_key = get_masking_key(); - - for (uint64_t i = 0; i < m_payload.size(); i++) { - m_payload[i] = (m_payload[i] ^ masking_key[i%4]); - } - } - } - - // experiment with more efficient masking code. - void process_payload2() { - // unmask payload one byte at a time - - //uint64_t key = (*((uint32_t*)m_masking_key;)) << 32; - //key += *((uint32_t*)m_masking_key); - - // might need to switch byte order - /*uint32_t key = *((uint32_t*)m_masking_key); - - // 4 - - uint64_t i = 0; - uint64_t s = (m_payload.size() / 4); - - std::cout << "s: " << s << std::endl; - - // chunks of 4 - for (i = 0; i < s; i+=4) { - ((uint32_t*)(&m_payload[0]))[i] = (((uint32_t*)(&m_payload[0]))[i] ^ key); - } - - // finish the last few - for (i = s; i < m_payload.size(); i++) { - m_payload[i] = (m_payload[i] ^ m_masking_key[i%4]); - }*/ - } - - void validate_utf8(uint32_t* state,uint32_t* codep,size_t offset = 0) const { - for (size_t i = offset; i < m_payload.size(); i++) { - using utf8_validator::decode; - - if (decode(state,codep,m_payload[i]) == utf8_validator::UTF8_REJECT) { - throw processor::exception("Invalid UTF-8 Data",processor::error::PAYLOAD_VIOLATION); - } - } - } - void validate_basic_header() const { - // check for control frame size - if (is_control() && get_basic_size() > limits::PAYLOAD_SIZE_BASIC) { - throw processor::exception("Control Frame is too large",processor::error::PROTOCOL_VIOLATION); - } - - // check for reserved bits - if (get_rsv1() || get_rsv2() || get_rsv3()) { - throw processor::exception("Reserved bit used",processor::error::PROTOCOL_VIOLATION); - } - - // check for reserved opcodes - if (opcode::reserved(get_opcode())) { - throw processor::exception("Reserved opcode used",processor::error::PROTOCOL_VIOLATION); - } - - // check for fragmented control message - if (is_control() && !get_fin()) { - throw processor::exception("Fragmented control message",processor::error::PROTOCOL_VIOLATION); - } - } - - void generate_masking_key() { - *(reinterpret_cast(&m_header[get_header_len()-4])) = m_rng.rand(); - } - void clear_masking_key() { - // this is a no-op as clearing the mask bit also changes the get_header_len - // method to not include these byte ranges. Whenever the masking bit is re- - // set a new key is generated anyways. - } - + // basic payload byte flags + static const uint8_t BPB0_OPCODE = 0x0F; + static const uint8_t BPB0_RSV3 = 0x10; + static const uint8_t BPB0_RSV2 = 0x20; + static const uint8_t BPB0_RSV1 = 0x40; + static const uint8_t BPB0_FIN = 0x80; + static const uint8_t BPB1_PAYLOAD = 0x7F; + static const uint8_t BPB1_MASK = 0x80; + + static const uint8_t BASIC_PAYLOAD_16BIT_CODE = 0x7E; // 126 + static const uint8_t BASIC_PAYLOAD_64BIT_CODE = 0x7F; // 127 + + static const unsigned int BASIC_HEADER_LENGTH = 2; + static const unsigned int MAX_HEADER_LENGTH = 14; + static const uint8_t extended_header_length = 12; + static const uint64_t max_payload_size = 100000000; // 100MB + + // create an empty frame for writing into + parser(rng_policy& rng) : m_rng(rng) { + reset(); + } + + bool ready() const { + return (m_state == STATE_READY); + } + uint64_t get_bytes_needed() const { + return m_bytes_needed; + } + void reset() { + m_state = STATE_BASIC_HEADER; + m_bytes_needed = BASIC_HEADER_LENGTH; + m_degraded = false; + m_payload.clear(); + memset(m_header,0,MAX_HEADER_LENGTH); + } + + // Method invariant: One of the following must always be true even in the case + // of exceptions. + // - m_bytes_needed > 0 + // - m-state = STATE_READY + void consume(std::istream &s) { + try { + switch (m_state) { + case STATE_BASIC_HEADER: + s.read(&m_header[BASIC_HEADER_LENGTH-m_bytes_needed],m_bytes_needed); + + m_bytes_needed -= s.gcount(); + + if (m_bytes_needed == 0) { + process_basic_header(); + + validate_basic_header(); + + if (m_bytes_needed > 0) { + m_state = STATE_EXTENDED_HEADER; + } else { + process_extended_header(); + + if (m_bytes_needed == 0) { + m_state = STATE_READY; + process_payload(); + + } else { + m_state = STATE_PAYLOAD; + } + } + } + break; + case STATE_EXTENDED_HEADER: + s.read(&m_header[get_header_len()-m_bytes_needed],m_bytes_needed); + + m_bytes_needed -= s.gcount(); + + if (m_bytes_needed == 0) { + process_extended_header(); + if (m_bytes_needed == 0) { + m_state = STATE_READY; + process_payload(); + } else { + m_state = STATE_PAYLOAD; + } + } + break; + case STATE_PAYLOAD: + s.read(reinterpret_cast(&m_payload[m_payload.size()-m_bytes_needed]), + m_bytes_needed); + + m_bytes_needed -= s.gcount(); + + if (m_bytes_needed == 0) { + m_state = STATE_READY; + process_payload(); + } + break; + case STATE_RECOVERY: + // Recovery state discards all bytes that are not the first byte + // of a close frame. + do { + s.read(reinterpret_cast(&m_header[0]),1); + + //std::cout << std::hex << int(static_cast(m_header[0])) << " "; + + if (int(static_cast(m_header[0])) == 0x88) { + //(BPB0_FIN && CONNECTION_CLOSE) + m_bytes_needed--; + m_state = STATE_BASIC_HEADER; + break; + } + } while (s.gcount() > 0); + + //std::cout << std::endl; + + break; + default: + break; + } + + /*if (s.gcount() == 0) { + throw frame_error("consume read zero bytes",FERR_FATAL_SESSION_ERROR); + }*/ + } catch (const processor::exception& e) { + // After this point all non-close frames must be considered garbage, + // including the current one. Reset it and put the reading frame into + // a recovery state. + if (m_degraded == true) { + throw processor::exception("An error occurred while trying to gracefully recover from a less serious frame error.",processor::error::FATAL_ERROR); + } else { + reset(); + m_state = STATE_RECOVERY; + m_degraded = true; + + throw e; + } + } + } + + // get pointers to underlying buffers + char* get_header() { + return m_header; + } + char* get_extended_header() { + return m_header+BASIC_HEADER_LENGTH; + } + unsigned int get_header_len() const { + unsigned int temp = 2; + + if (get_masked()) { + temp += 4; + } + + if (get_basic_size() == 126) { + temp += 2; + } else if (get_basic_size() == 127) { + temp += 8; + } + + return temp; + } + + char* get_masking_key() { + /*if (m_state != STATE_READY) { + std::cout << "throw" << std::endl; + throw processor::exception("attempted to get masking_key before reading full header"); + }*/ + return &m_header[get_header_len()-4]; + } + + // get and set header bits + bool get_fin() const { + return ((m_header[0] & BPB0_FIN) == BPB0_FIN); + } + void set_fin(bool fin) { + if (fin) { + m_header[0] |= BPB0_FIN; + } else { + m_header[0] &= (0xFF ^ BPB0_FIN); + } + } + + bool get_rsv1() const { + return ((m_header[0] & BPB0_RSV1) == BPB0_RSV1); + } + void set_rsv1(bool b) { + if (b) { + m_header[0] |= BPB0_RSV1; + } else { + m_header[0] &= (0xFF ^ BPB0_RSV1); + } + } + + bool get_rsv2() const { + return ((m_header[0] & BPB0_RSV2) == BPB0_RSV2); + } + void set_rsv2(bool b) { + if (b) { + m_header[0] |= BPB0_RSV2; + } else { + m_header[0] &= (0xFF ^ BPB0_RSV2); + } + } + + bool get_rsv3() const { + return ((m_header[0] & BPB0_RSV3) == BPB0_RSV3); + } + void set_rsv3(bool b) { + if (b) { + m_header[0] |= BPB0_RSV3; + } else { + m_header[0] &= (0xFF ^ BPB0_RSV3); + } + } + + opcode::value get_opcode() const { + return frame::opcode::value(m_header[0] & BPB0_OPCODE); + } + void set_opcode(opcode::value op) { + if (opcode::reserved(op)) { + throw processor::exception("reserved opcode",processor::error::PROTOCOL_VIOLATION); + } + + if (opcode::invalid(op)) { + throw processor::exception("invalid opcode",processor::error::PROTOCOL_VIOLATION); + } + + if (is_control() && get_basic_size() > limits::PAYLOAD_SIZE_BASIC) { + throw processor::exception("control frames can't have large payloads",processor::error::PROTOCOL_VIOLATION); + } + + m_header[0] &= (0xFF ^ BPB0_OPCODE); // clear op bits + m_header[0] |= op; // set op bits + } + + bool get_masked() const { + return ((m_header[1] & BPB1_MASK) == BPB1_MASK); + } + void set_masked(bool masked) { + if (masked) { + m_header[1] |= BPB1_MASK; + generate_masking_key(); + } else { + m_header[1] &= (0xFF ^ BPB1_MASK); + clear_masking_key(); + } + } + + uint8_t get_basic_size() const { + return m_header[1] & BPB1_PAYLOAD; + } + size_t get_payload_size() const { + if (m_state != STATE_READY && m_state != STATE_PAYLOAD) { + // TODO: how to handle errors like this? + throw "attempted to get payload size before reading full header"; + } + + return m_payload.size(); + } + + close::status::value get_close_status() const { + if (get_payload_size() == 0) { + return close::status::NO_STATUS; + } else if (get_payload_size() >= 2) { + char val[2]; + + val[0] = m_payload[0]; + val[1] = m_payload[1]; + + uint16_t code = ntohs(*(reinterpret_cast(&val[0]))); + + return close::status::value(code); + } else { + return close::status::PROTOCOL_ERROR; + } + } + std::string get_close_msg() const { + if (get_payload_size() > 2) { + uint32_t state = utf8_validator::UTF8_ACCEPT; + uint32_t codep = 0; + validate_utf8(&state,&codep,2); + if (state != utf8_validator::UTF8_ACCEPT) { + throw processor::exception("Invalid UTF-8 Data",processor::error::PAYLOAD_VIOLATION); + } + return std::string(m_payload.begin()+2,m_payload.end()); + } else { + return std::string(); + } + } + + std::vector &get_payload() { + return m_payload; + } + + void set_payload(const std::vector& source) { + set_payload_helper(source.size()); + + std::copy(source.begin(),source.end(),m_payload.begin()); + } + void set_payload(const std::string& source) { + set_payload_helper(source.size()); + + std::copy(source.begin(),source.end(),m_payload.begin()); + } + void set_payload_helper(size_t s) { + if (s > max_payload_size) { + throw processor::exception("requested payload is over implementation defined limit",processor::error::MESSAGE_TOO_BIG); + } + + // limits imposed by the websocket spec + if (is_control() && s > limits::PAYLOAD_SIZE_BASIC) { + throw processor::exception("control frames can't have large payloads",processor::error::PROTOCOL_VIOLATION); + } + + bool masked = get_masked(); + + if (s <= limits::PAYLOAD_SIZE_BASIC) { + m_header[1] = s; + } else if (s <= limits::PAYLOAD_SIZE_EXTENDED) { + m_header[1] = BASIC_PAYLOAD_16BIT_CODE; + + // this reinterprets the second pair of bytes in m_header as a + // 16 bit int and writes the payload size there as an integer + // in network byte order + *reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) = htons(s); + } else if (s <= limits::PAYLOAD_SIZE_JUMBO) { + m_header[1] = BASIC_PAYLOAD_64BIT_CODE; + *reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) = htonll(s); + } else { + throw processor::exception("payload size limit is 63 bits",processor::error::PROTOCOL_VIOLATION); + } + + if (masked) { + m_header[1] |= BPB1_MASK; + } + + m_payload.resize(s); + } + + void set_status(close::status::value status,const std::string message = "") { + // check for valid statuses + if (close::status::invalid(status)) { + std::stringstream err; + err << "Status code " << status << " is invalid"; + throw processor::exception(err.str()); + } + + if (close::status::reserved(status)) { + std::stringstream err; + err << "Status code " << status << " is reserved"; + throw processor::exception(err.str()); + } + + m_payload.resize(2+message.size()); + + char val[2]; + + *reinterpret_cast(&val[0]) = htons(status); + + bool masked = get_masked(); + + m_header[1] = message.size()+2; + + if (masked) { + m_header[1] |= BPB1_MASK; + } + + m_payload[0] = val[0]; + m_payload[1] = val[1]; + + std::copy(message.begin(),message.end(),m_payload.begin()+2); + } + + bool is_control() const { + return (opcode::is_control(get_opcode())); + } + + std::string print_frame() const { + std::stringstream f; + + unsigned int len = get_header_len(); + + f << "frame: "; + // print header + for (unsigned int i = 0; i < len; i++) { + f << std::hex << (unsigned short)m_header[i] << " "; + } + // print message + if (m_payload.size() > 50) { + f << "[payload of " << m_payload.size() << " bytes]"; + } else { + std::vector::const_iterator it; + for (it = m_payload.begin(); it != m_payload.end(); it++) { + f << *it; + } + } + return f.str(); + } + + // reads basic header, sets and returns m_header_bits_needed + void process_basic_header() { + m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH; + } + void process_extended_header() { + uint8_t s = get_basic_size(); + uint64_t payload_size; + int mask_index = BASIC_HEADER_LENGTH; + + if (s <= limits::PAYLOAD_SIZE_BASIC) { + payload_size = s; + } else if (s == BASIC_PAYLOAD_16BIT_CODE) { + // reinterpret the second two bytes as a 16 bit integer in network + // byte order. Convert to host byte order and store locally. + payload_size = ntohs(*( + reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) + )); + + if (payload_size < s) { + std::stringstream err; + err << "payload length not minimally encoded. Using 16 bit form for payload size: " << payload_size; + m_bytes_needed = payload_size; + throw processor::exception(err.str(),processor::error::PROTOCOL_VIOLATION); + } + + mask_index += 2; + } else if (s == BASIC_PAYLOAD_64BIT_CODE) { + // reinterpret the second eight bytes as a 64 bit integer in + // network byte order. Convert to host byte order and store. + payload_size = ntohll(*( + reinterpret_cast(&m_header[BASIC_HEADER_LENGTH]) + )); + + if (payload_size <= limits::PAYLOAD_SIZE_EXTENDED) { + m_bytes_needed = payload_size; + throw processor::exception("payload length not minimally encoded", + processor::error::PROTOCOL_VIOLATION); + } + + mask_index += 8; + } else { + // TODO: shouldn't be here how to handle? + throw processor::exception("invalid get_basic_size in process_extended_header"); + } + + if (get_masked() == 0) { + clear_masking_key(); + } else { + // TODO: this should be removed entirely once it is confirmed to not + // be used by anything. + // std::copy(m_header[mask_index],m_header[mask_index+4],m_masking_key); + /*m_masking_key[0] = m_header[mask_index+0]; + m_masking_key[1] = m_header[mask_index+1]; + m_masking_key[2] = m_header[mask_index+2]; + m_masking_key[3] = m_header[mask_index+3];*/ + } + + if (payload_size > max_payload_size) { + // TODO: frame/message size limits + // TODO: find a way to throw a server error without coupling frame + // with server + // throw websocketpp::server_error("got frame with payload greater than maximum frame buffer size."); + throw "Got frame with payload greater than maximum frame buffer size."; + } + m_payload.resize(payload_size); + m_bytes_needed = payload_size; + } + + void process_payload() { + if (get_masked()) { + char *masking_key = get_masking_key(); + + for (uint64_t i = 0; i < m_payload.size(); i++) { + m_payload[i] = (m_payload[i] ^ masking_key[i%4]); + } + } + } + + // experiment with more efficient masking code. + void process_payload2() { + // unmask payload one byte at a time + + //uint64_t key = (*((uint32_t*)m_masking_key;)) << 32; + //key += *((uint32_t*)m_masking_key); + + // might need to switch byte order + /*uint32_t key = *((uint32_t*)m_masking_key); + + // 4 + + uint64_t i = 0; + uint64_t s = (m_payload.size() / 4); + + std::cout << "s: " << s << std::endl; + + // chunks of 4 + for (i = 0; i < s; i+=4) { + ((uint32_t*)(&m_payload[0]))[i] = (((uint32_t*)(&m_payload[0]))[i] ^ key); + } + + // finish the last few + for (i = s; i < m_payload.size(); i++) { + m_payload[i] = (m_payload[i] ^ m_masking_key[i%4]); + }*/ + } + + void validate_utf8(uint32_t* state,uint32_t* codep,size_t offset = 0) const { + for (size_t i = offset; i < m_payload.size(); i++) { + using utf8_validator::decode; + + if (decode(state,codep,m_payload[i]) == utf8_validator::UTF8_REJECT) { + throw processor::exception("Invalid UTF-8 Data",processor::error::PAYLOAD_VIOLATION); + } + } + } + void validate_basic_header() const { + // check for control frame size + if (is_control() && get_basic_size() > limits::PAYLOAD_SIZE_BASIC) { + throw processor::exception("Control Frame is too large",processor::error::PROTOCOL_VIOLATION); + } + + // check for reserved bits + if (get_rsv1() || get_rsv2() || get_rsv3()) { + throw processor::exception("Reserved bit used",processor::error::PROTOCOL_VIOLATION); + } + + // check for reserved opcodes + if (opcode::reserved(get_opcode())) { + throw processor::exception("Reserved opcode used",processor::error::PROTOCOL_VIOLATION); + } + + // check for fragmented control message + if (is_control() && !get_fin()) { + throw processor::exception("Fragmented control message",processor::error::PROTOCOL_VIOLATION); + } + } + + void generate_masking_key() { + *(reinterpret_cast(&m_header[get_header_len()-4])) = m_rng.rand(); + } + void clear_masking_key() { + // this is a no-op as clearing the mask bit also changes the get_header_len + // method to not include these byte ranges. Whenever the masking bit is re- + // set a new key is generated anyways. + } + private: - static const uint8_t STATE_BASIC_HEADER = 1; - static const uint8_t STATE_EXTENDED_HEADER = 2; - static const uint8_t STATE_PAYLOAD = 3; - static const uint8_t STATE_READY = 4; - static const uint8_t STATE_RECOVERY = 5; - - uint8_t m_state; - uint64_t m_bytes_needed; - bool m_degraded; - - char m_header[MAX_HEADER_LENGTH]; - std::vector m_payload; - - rng_policy& m_rng; + static const uint8_t STATE_BASIC_HEADER = 1; + static const uint8_t STATE_EXTENDED_HEADER = 2; + static const uint8_t STATE_PAYLOAD = 3; + static const uint8_t STATE_READY = 4; + static const uint8_t STATE_RECOVERY = 5; + + uint8_t m_state; + uint64_t m_bytes_needed; + bool m_degraded; + + char m_header[MAX_HEADER_LENGTH]; + std::vector m_payload; + + rng_policy& m_rng; }; } diff --git a/src/websocketpp.hpp b/src/websocketpp.hpp index bb8234cc9..d5cb21c5b 100644 --- a/src/websocketpp.hpp +++ b/src/websocketpp.hpp @@ -28,14 +28,8 @@ #ifndef WEBSOCKETPP_HPP #define WEBSOCKETPP_HPP -#include - +#include "common.hpp" #include "endpoint.hpp" #include "sockets/plain.hpp" -//#include "websocket_constants.hpp" - -//#include "websocket_server.hpp" -//#include "websocket_client.hpp" - #endif // WEBSOCKETPP_HPP diff --git a/test/basic/logging.cpp b/test/basic/logging.cpp index b389a3e5f..ed4f93e05 100644 --- a/test/basic/logging.cpp +++ b/test/basic/logging.cpp @@ -28,13 +28,13 @@ #include "../../src/logger/logger.hpp" int main () { - websocketpp::log::logger log; - - log.set_levels(websocketpp::log::elevel::DEVEL,websocketpp::log::elevel::ERROR); - log.at(websocketpp::log::elevel::DEVEL) << "devel: " << 5 << websocketpp::log::endl; - log.at(websocketpp::log::elevel::INFO) << "info: " << 5 << websocketpp::log::endl; - log.at(websocketpp::log::elevel::WARN) << "warn: " << 5 << websocketpp::log::endl; - log.at(websocketpp::log::elevel::ERROR) << "error: " << 5 << websocketpp::log::endl; - log.at(websocketpp::log::elevel::FATAL) << "fatal: " << 5 << websocketpp::log::endl; + websocketpp::log::logger log; + + log.set_levels(websocketpp::log::elevel::DEVEL,websocketpp::log::elevel::ERROR); + log.at(websocketpp::log::elevel::DEVEL) << "devel: " << 5 << websocketpp::log::endl; + log.at(websocketpp::log::elevel::INFO) << "info: " << 5 << websocketpp::log::endl; + log.at(websocketpp::log::elevel::WARN) << "warn: " << 5 << websocketpp::log::endl; + log.at(websocketpp::log::elevel::ERROR) << "error: " << 5 << websocketpp::log::endl; + log.at(websocketpp::log::elevel::FATAL) << "fatal: " << 5 << websocketpp::log::endl; } \ No newline at end of file diff --git a/test/basic/parsing.cpp b/test/basic/parsing.cpp index 11f61ed3b..932e76e95 100644 --- a/test/basic/parsing.cpp +++ b/test/basic/parsing.cpp @@ -34,279 +34,279 @@ // Test a regular valid ws URI BOOST_AUTO_TEST_CASE( uri_valid ) { - bool exception = false; - try { - websocketpp::uri uri("ws://localhost:9000/chat"); - - BOOST_CHECK( uri.get_secure() == false ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/chat" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("ws://localhost:9000/chat"); + + BOOST_CHECK( uri.get_secure() == false ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/chat" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Test a regular valid ws URI BOOST_AUTO_TEST_CASE( uri_valid_no_port_unsecure ) { - bool exception = false; - try { - websocketpp::uri uri("ws://localhost/chat"); - - BOOST_CHECK( uri.get_secure() == false ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 80 ); - BOOST_CHECK( uri.get_resource() == "/chat" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("ws://localhost/chat"); + + BOOST_CHECK( uri.get_secure() == false ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 80 ); + BOOST_CHECK( uri.get_resource() == "/chat" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Valid URI with no port (secure) BOOST_AUTO_TEST_CASE( uri_valid_no_port_secure ) { - bool exception = false; - try { - websocketpp::uri uri("wss://localhost/chat"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 443 ); - BOOST_CHECK( uri.get_resource() == "/chat" ); - } catch (websocketpp::uri_exception& e) { - exception = true; + bool exception = false; + try { + websocketpp::uri uri("wss://localhost/chat"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 443 ); + BOOST_CHECK( uri.get_resource() == "/chat" ); + } catch (websocketpp::uri_exception& e) { + exception = true; std::cout << e.what() << std::endl; - } + } - BOOST_CHECK( exception == false); + BOOST_CHECK( exception == false); } // Valid URI with no resource BOOST_AUTO_TEST_CASE( uri_valid_no_resource ) { - bool exception = false; - try { - websocketpp::uri uri("wss://localhost:9000"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://localhost:9000"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Valid URI IPv6 Literal BOOST_AUTO_TEST_CASE( uri_valid_ipv6_literal ) { - bool exception = false; - try { - websocketpp::uri uri("wss://[::1]:9000/chat"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "::1"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/chat" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://[::1]:9000/chat"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "::1"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/chat" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Valid URI with more complicated host BOOST_AUTO_TEST_CASE( uri_valid_2 ) { - bool exception = false; - try { - websocketpp::uri uri("wss://thor-websocket.zaphoyd.net:88/"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "thor-websocket.zaphoyd.net"); - BOOST_CHECK( uri.get_port() == 88 ); - BOOST_CHECK( uri.get_resource() == "/" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://thor-websocket.zaphoyd.net:88/"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "thor-websocket.zaphoyd.net"); + BOOST_CHECK( uri.get_port() == 88 ); + BOOST_CHECK( uri.get_resource() == "/" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Invalid URI (port too long) BOOST_AUTO_TEST_CASE( uri_invalid_long_port ) { - bool exception = false; - try { - websocketpp::uri uri("wss://localhost:900000/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == true); + bool exception = false; + try { + websocketpp::uri uri("wss://localhost:900000/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == true); } // Invalid URI (http method) BOOST_AUTO_TEST_CASE( uri_invalid_http ) { - bool exception = false; - try { - websocketpp::uri uri("http://localhost:9000/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == true); + bool exception = false; + try { + websocketpp::uri uri("http://localhost:9000/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == true); } // Valid URI IPv4 literal BOOST_AUTO_TEST_CASE( uri_valid_ipv4_literal ) { - bool exception = false; - try { - websocketpp::uri uri("wss://127.0.0.1:9000/chat"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "127.0.0.1"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/chat" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://127.0.0.1:9000/chat"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "127.0.0.1"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/chat" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Valid URI complicated resource path BOOST_AUTO_TEST_CASE( uri_valid_3 ) { - bool exception = false; - try { - websocketpp::uri uri("wss://localhost:9000/chat/foo/bar"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/chat/foo/bar" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://localhost:9000/chat/foo/bar"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/chat/foo/bar" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Invalid URI broken method separator BOOST_AUTO_TEST_CASE( uri_invalid_method_separator ) { - bool exception = false; - try { - websocketpp::uri uri("wss:/localhost:9000/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == true); + bool exception = false; + try { + websocketpp::uri uri("wss:/localhost:9000/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == true); } // Invalid URI port > 65535 BOOST_AUTO_TEST_CASE( uri_invalid_gt_16_bit_port ) { - bool exception = false; - try { - websocketpp::uri uri("wss:/localhost:70000/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == true); + bool exception = false; + try { + websocketpp::uri uri("wss:/localhost:70000/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == true); } // Invalid URI includes uri fragment BOOST_AUTO_TEST_CASE( uri_invalid_fragment ) { - bool exception = false; - try { - websocketpp::uri uri("wss:/localhost:70000/chat#foo"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == true); + bool exception = false; + try { + websocketpp::uri uri("wss:/localhost:70000/chat#foo"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == true); } // Invalid URI with no brackets around IPv6 literal BOOST_AUTO_TEST_CASE( uri_invalid_bad_v6_literal_1 ) { - bool exception = false; - try { - websocketpp::uri uri("wss://::1/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } + bool exception = false; + try { + websocketpp::uri uri("wss://::1/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } - BOOST_CHECK( exception == true); + BOOST_CHECK( exception == true); } // Invalid URI with port and no brackets around IPv6 literal BOOST_AUTO_TEST_CASE( uri_invalid_bad_v6_literal_2 ) { - bool exception = false; - try { - websocketpp::uri uri("wss://::1:2009/chat"); - } catch (websocketpp::uri_exception& e) { - exception = true; - } + bool exception = false; + try { + websocketpp::uri uri("wss://::1:2009/chat"); + } catch (websocketpp::uri_exception& e) { + exception = true; + } - BOOST_CHECK( exception == true); + BOOST_CHECK( exception == true); } // Valid URI complicated resource path with query BOOST_AUTO_TEST_CASE( uri_valid_4 ) { - bool exception = false; - try { - websocketpp::uri uri("wss://localhost:9000/chat/foo/bar?foo=bar"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "localhost"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/chat/foo/bar?foo=bar" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } - - BOOST_CHECK( exception == false); + bool exception = false; + try { + websocketpp::uri uri("wss://localhost:9000/chat/foo/bar?foo=bar"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "localhost"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/chat/foo/bar?foo=bar" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } + + BOOST_CHECK( exception == false); } // Valid URI with a mapped v4 ipv6 literal BOOST_AUTO_TEST_CASE( uri_valid_v4_mapped ) { - bool exception = false; - try { - websocketpp::uri uri("wss://[0000:0000:0000:0000:0000:0000:192.168.1.1]:9000/"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "0000:0000:0000:0000:0000:0000:192.168.1.1"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } + bool exception = false; + try { + websocketpp::uri uri("wss://[0000:0000:0000:0000:0000:0000:192.168.1.1]:9000/"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "0000:0000:0000:0000:0000:0000:192.168.1.1"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } - BOOST_CHECK( exception == false); + BOOST_CHECK( exception == false); } // Valid URI with a v6 address with mixed case BOOST_AUTO_TEST_CASE( uri_valid_v6_mixed_case ) { - bool exception = false; - try { - websocketpp::uri uri("wss://[::10aB]:9000/"); - - BOOST_CHECK( uri.get_secure() == true ); - BOOST_CHECK( uri.get_host() == "::10aB"); - BOOST_CHECK( uri.get_port() == 9000 ); - BOOST_CHECK( uri.get_resource() == "/" ); - } catch (websocketpp::uri_exception& e) { - exception = true; - } + bool exception = false; + try { + websocketpp::uri uri("wss://[::10aB]:9000/"); + + BOOST_CHECK( uri.get_secure() == true ); + BOOST_CHECK( uri.get_host() == "::10aB"); + BOOST_CHECK( uri.get_port() == 9000 ); + BOOST_CHECK( uri.get_resource() == "/" ); + } catch (websocketpp::uri_exception& e) { + exception = true; + } - BOOST_CHECK( exception == false); + BOOST_CHECK( exception == false); } // TODO: tests for the other two constructors diff --git a/test/basic/uri_perf.cpp b/test/basic/uri_perf.cpp index f87ecbfdb..0c621f5b8 100644 --- a/test/basic/uri_perf.cpp +++ b/test/basic/uri_perf.cpp @@ -32,20 +32,20 @@ #include "../../src/uri.hpp" int main() { - boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time(); - - long m = 100000; - long n = 3; - - for (long i = 0; i < m; i++) { - websocketpp::uri uri1("wss://thor-websocket.zaphoyd.net:9002/foo/bar/baz?a=b&c=d"); - websocketpp::uri uri2("ws://[::1]"); - websocketpp::uri uri3("ws://localhost:9000/chat"); - } - boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time(); - boost::posix_time::time_period period(start,end); - int ms = period.length().total_milliseconds(); - - std::cout << "Created " << m*n << " URIs in " << ms << "ms" << " (" << (m*n)/(ms/1000.0) << "/s)" << std::endl; + boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time(); + + long m = 100000; + long n = 3; + + for (long i = 0; i < m; i++) { + websocketpp::uri uri1("wss://thor-websocket.zaphoyd.net:9002/foo/bar/baz?a=b&c=d"); + websocketpp::uri uri2("ws://[::1]"); + websocketpp::uri uri3("ws://localhost:9000/chat"); + } + boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::time_period period(start,end); + int ms = period.length().total_milliseconds(); + + std::cout << "Created " << m*n << " URIs in " << ms << "ms" << " (" << (m*n)/(ms/1000.0) << "/s)" << std::endl; } diff --git a/websocketpp.bbprojectd/Scratchpad.txt b/websocketpp.bbprojectd/Scratchpad.txt new file mode 100644 index 000000000..e69de29bb diff --git a/websocketpp.bbprojectd/Unix Worksheet.worksheet b/websocketpp.bbprojectd/Unix Worksheet.worksheet new file mode 100644 index 000000000..e69de29bb diff --git a/websocketpp.bbprojectd/project.bbprojectdata b/websocketpp.bbprojectd/project.bbprojectdata new file mode 100644 index 000000000..ad0930f47 --- /dev/null +++ b/websocketpp.bbprojectd/project.bbprojectdata @@ -0,0 +1,342 @@ + + + + + HierarchyData + + 2F5C9ECD-49E4-4D1E-B7A7-97AD42355663 + 994091B7-AF96-4C6A-8673-F8CD179B9BB7 + 5B286FCE-C133-4923-A55E-C2445F22D56D + 70ACB16A-066F-48E1-8647-4A8E1796E2FE + 16709CCC-14BD-4083-870C-85AB16E1116C + 4B120009-0C8E-4DF6-A7E9-1476264C9495 + DF70D6BC-9D94-41B4-B625-A17AB95EE958 + 03203612-E240-4F97-90B4-33B4B352841F + 72436B78-928A-42B1-B7B4-A551F5DF176B + + ProjectItems + + 03203612-E240-4F97-90B4-33B4B352841F + + ItemData + + AliasData + + AAAAAAF0AAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwEdGVzdAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEpsq9yMEAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxEAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADhCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAdGVzdAAOAAoABAB0AGUAcwB0AA8AEAAHAEIA + ZQBsAGcAYQBlAHIAEgArVXNlcnMvemFwaG95ZC9Eb2N1 + bWVudHMvWlMvd2Vic29ja2V0cHAvdGVzdAAAEwABLwAA + FQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/test/ + RelativePath + ./test + TypeID + _CFileLocator + Version + 1 + + ItemName + test + ItemType + FolderReference + UserOverrideItemName + + + 16709CCC-14BD-4083-870C-85AB16E1116C + + ItemData + + AliasData + + AAAAAAGEAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwITWFrZWZpbGUAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIC3YssXdbIAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMsXyhIAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADxCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoATWFrZWZpbGUADgASAAgATQBhAGsAZQBmAGkA + bABlAA8AEAAHAEIAZQBsAGcAYQBlAHIAEgAvVXNlcnMv + emFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAv + TWFrZWZpbGUAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/Makefile + RelativePath + ./Makefile + TypeID + _CFileLocator + Version + 1 + + ItemName + Makefile + ItemType + FileReference + UserOverrideItemName + + + 2F5C9ECD-49E4-4D1E-B7A7-97AD42355663 + + ItemData + + AliasData + + AAAAAAGkAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwQZGVwZW5kZW5jaWVzLnR4 + dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHmmzcr8+n8AAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMr9Tt8AAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACAERCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAZGVwZW5kZW5jaWVzLnR4dAAOACIAEABkAGUA + cABlAG4AZABlAG4AYwBpAGUAcwAuAHQAeAB0AA8AEAAH + AEIAZQBsAGcAYQBlAHIAEgA3VXNlcnMvemFwaG95ZC9E + b2N1bWVudHMvWlMvd2Vic29ja2V0cHAvZGVwZW5kZW5j + aWVzLnR4dAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/dependencies.txt + RelativePath + ./dependencies.txt + TypeID + _CFileLocator + Version + 1 + + ItemName + dependencies.txt + ItemType + FileReference + UserOverrideItemName + + + 4B120009-0C8E-4DF6-A7E9-1476264C9495 + + ItemData + + AliasData + + AAAAAAGMAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwKcmVhZG1lLnR4dAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGkEDsrQL68AAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMrQdf8AAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACAD5CZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAcmVhZG1lLnR4dAAOABYACgByAGUAYQBkAG0A + ZQAuAHQAeAB0AA8AEAAHAEIAZQBsAGcAYQBlAHIAEgAx + VXNlcnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29j + a2V0cHAvcmVhZG1lLnR4dAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/readme.txt + RelativePath + ./readme.txt + TypeID + _CFileLocator + Version + 1 + + ItemName + readme.txt + ItemType + FileReference + UserOverrideItemName + + + 5B286FCE-C133-4923-A55E-C2445F22D56D + + ItemData + + AliasData + + AAAAAAGEAAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwIZXhhbXBsZXMAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEasq9yMAAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxAAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADxCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAZXhhbXBsZXMADgASAAgAZQB4AGEAbQBwAGwA + ZQBzAA8AEAAHAEIAZQBsAGcAYQBlAHIAEgAvVXNlcnMv + emFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAv + ZXhhbXBsZXMAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/ + RelativePath + ./examples + TypeID + _CFileLocator + Version + 1 + + ItemName + examples + ItemType + FolderReference + UserOverrideItemName + + + 70ACB16A-066F-48E1-8647-4A8E1796E2FE + + ItemData + + AliasData + + AAAAAAGQAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwLbGljZW5zZS50eHQAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEhcq9yMEAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxEAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACAD9CZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAbGljZW5zZS50eHQAAA4AGAALAGwAaQBjAGUA + bgBzAGUALgB0AHgAdAAPABAABwBCAGUAbABnAGEAZQBy + ABIAMlVzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dl + YnNvY2tldHBwL2xpY2Vuc2UudHh0ABMAAS8AABUAAgAO + //8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/license.txt + RelativePath + ./license.txt + TypeID + _CFileLocator + Version + 1 + + ItemName + license.txt + ItemType + FileReference + UserOverrideItemName + + + 72436B78-928A-42B1-B7B4-A551F5DF176B + + ItemData + + AliasData + + AAAAAAGEAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwIdG9kby50eHQAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEqsq9yMEAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxEAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADxCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAdG9kby50eHQADgASAAgAdABvAGQAbwAuAHQA + eAB0AA8AEAAHAEIAZQBsAGcAYQBlAHIAEgAvVXNlcnMv + emFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAv + dG9kby50eHQAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/todo.txt + RelativePath + ./todo.txt + TypeID + _CFileLocator + Version + 1 + + ItemName + todo.txt + ItemType + FileReference + UserOverrideItemName + + + 994091B7-AF96-4C6A-8673-F8CD179B9BB7 + + ItemData + + AliasData + + AAAAAAFwAAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwDZG9jAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHkIeMr6YxEAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMr6t3EAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADdCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAZG9jAAAOAAgAAwBkAG8AYwAPABAABwBCAGUA + bABnAGEAZQByABIAKlVzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2RvYwATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/doc/ + RelativePath + ./doc + TypeID + _CFileLocator + Version + 1 + + ItemName + doc + ItemType + FolderReference + UserOverrideItemName + + + DF70D6BC-9D94-41B4-B625-A17AB95EE958 + + ItemData + + AliasData + + AAAAAAFwAAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwDc3JjAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEh8q9yMEAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxEAAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACADdCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAc3JjAAAOAAgAAwBzAHIAYwAPABAABwBCAGUA + bABnAGEAZQByABIAKlVzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL3NyYwATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/src/ + RelativePath + ./src + TypeID + _CFileLocator + Version + 1 + + ItemName + src + ItemType + FolderReference + UserOverrideItemName + + + + com.barebones.DocumentFormatVersion + 5 + com.barebones.DocumentType + Project + + diff --git a/websocketpp.bbprojectd/zaphoyd.bbprojectsettings b/websocketpp.bbprojectd/zaphoyd.bbprojectsettings new file mode 100644 index 000000000..5c7bb1672 --- /dev/null +++ b/websocketpp.bbprojectd/zaphoyd.bbprojectsettings @@ -0,0 +1,1301 @@ + + + + + EmbeddedEditorHidden:zaphoyd + + ExpandedEditorWidth:zaphoyd:displays([(0, 0), (2560, 1440)]:[(2560, -37), (1920, 1200)]) + 876 + ExpandedItems:zaphoyd + + 994091B7-AF96-4C6A-8673-F8CD179B9BB7 + 5B286FCE-C133-4923-A55E-C2445F22D56D + + AliasData + + AAAAAAGsAAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRGoNc3RyZXNzX2NsaWVudAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHw2 + k8sHz48AAAAAAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAACGV4 + YW1wbGVzABAACAAAyg8HGgAAABEACAAAywgj7wAAAAEAGABgRGoA + YEQsAAZc8AAEhCwAA58OAACRkAACAEtCZWxnYWVyOlVzZXJzOgB6 + YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2NrZXRwcDoAZXhh + bXBsZXM6AHN0cmVzc19jbGllbnQAAA4AHAANAHMAdAByAGUAcwBz + AF8AYwBsAGkAZQBuAHQADwAQAAcAQgBlAGwAZwBhAGUAcgASAD1V + c2Vycy96YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9zdHJlc3NfY2xpZW50AAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/stress_client/ + TypeID + _CFileLocator + Version + 1 + + DF70D6BC-9D94-41B4-B625-A17AB95EE958 + 03203612-E240-4F97-90B4-33B4B352841F + + AliasData + + AAAAAAGAAAIAAQdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRKYFYmFzaWMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBE + p8q9yMEAAAAAAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAABHRl + c3QAEAAIAADKDwcaAAAAEQAIAADKvg8RAAAAAQAYAGBEpgBgRCwA + BlzwAASELAADnw4AAJGQAAIAP0JlbGdhZXI6VXNlcnM6AHphcGhv + eWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBwOgB0ZXN0OgBi + YXNpYwAADgAMAAUAYgBhAHMAaQBjAA8AEAAHAEIAZQBsAGcAYQBl + AHIAEgAxVXNlcnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29j + a2V0cHAvdGVzdC9iYXNpYwAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/test/basic/ + TypeID + _CFileLocator + Version + 1 + + + FileFilterID:zaphoyd + msng + OpenDocuments:zaphoyd + + + AliasData + + AAAAAAHiAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAAB8NpMRc3RyZXNzX2NsaWVudC5jcHAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImt + bsswcGxURVhUAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAADXN0 + cmVzc19jbGllbnQAABAACAAAyg8HGgAAABEACAAAyzDEzAAAAAEA + HAB8NpMAYERqAGBELAAGXPAABIQsAAOfDgAAkZAAAgBeQmVsZ2Fl + cjpVc2VyczoAemFwaG95ZDoARG9jdW1lbnRzOgBaUzoAd2Vic29j + a2V0cHA6AGV4YW1wbGVzOgBzdHJlc3NfY2xpZW50OgBzdHJlc3Nf + Y2xpZW50LmNwcAAOACQAEQBzAHQAcgBlAHMAcwBfAGMAbABpAGUA + bgB0AC4AYwBwAHAADwAQAAcAQgBlAGwAZwBhAGUAcgASAE9Vc2Vy + cy96YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9leGFt + cGxlcy9zdHJlc3NfY2xpZW50L3N0cmVzc19jbGllbnQuY3BwAAAT + AAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/stress_client/stress_client.cpp + RelativePath + ./examples/stress_client/stress_client.cpp + TypeID + _CFileLocator + Version + 1 + + + AliasData + + AAAAAAGkAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRCwQZGVwZW5kZW5jaWVzLnR4dAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHmm + zcr8+n8AAAAAAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAAC3dl + YnNvY2tldHBwAAAQAAgAAMoPBxoAAAARAAgAAMr9Tt8AAAABABQA + YEQsAAZc8AAEhCwAA58OAACRkAACAERCZWxnYWVyOlVzZXJzOgB6 + YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2NrZXRwcDoAZGVw + ZW5kZW5jaWVzLnR4dAAOACIAEABkAGUAcABlAG4AZABlAG4AYwBp + AGUAcwAuAHQAeAB0AA8AEAAHAEIAZQBsAGcAYQBlAHIAEgA3VXNl + cnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAvZGVw + ZW5kZW5jaWVzLnR4dAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/dependencies.txt + RelativePath + ./dependencies.txt + TypeID + _CFileLocator + Version + 1 + + + AliasData + + AAAAAAGuAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRKcMdXJpX3BlcmYuY3BwAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIqm + rcszKBxURVhUAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAABWJh + c2ljAAAQAAgAAMoPBxoAAAARAAgAAMszfHwAAAABABwAYESnAGBE + pgBgRCwABlzwAASELAADnw4AAJGQAAIATUJlbGdhZXI6VXNlcnM6 + AHphcGhveWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBwOgB0 + ZXN0OgBiYXNpYzoAdXJpX3BlcmYuY3BwAAAOABoADAB1AHIAaQBf + AHAAZQByAGYALgBjAHAAcAAPABAABwBCAGUAbABnAGEAZQByABIA + PlVzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dlYnNvY2tldHBw + L3Rlc3QvYmFzaWMvdXJpX3BlcmYuY3BwABMAAS8AABUAAgAO//8A + AA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/test/basic/uri_perf.cpp + RelativePath + ./test/basic/uri_perf.cpp + TypeID + _CFileLocator + Version + 1 + + + AliasData + + AAAAAAGaAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRIcMZW5kcG9pbnQuaHBwAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImt + ccswcGwAAAAAAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAAA3Ny + YwAAEAAIAADKDwcaAAAAEQAIAADLMMTMAAAAAQAYAGBEhwBgRCwA + BlzwAASELAADnw4AAJGQAAIARUJlbGdhZXI6VXNlcnM6AHphcGhv + eWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBwOgBzcmM6AGVu + ZHBvaW50LmhwcAAADgAaAAwAZQBuAGQAcABvAGkAbgB0AC4AaABw + AHAADwAQAAcAQgBlAGwAZwBhAGUAcgASADdVc2Vycy96YXBob3lk + L0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9zcmMvZW5kcG9pbnQu + aHBwAAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/src/endpoint.hpp + RelativePath + ./src/endpoint.hpp + TypeID + _CFileLocator + Version + 1 + + + AliasData + + AAAAAAGiAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAAAAAAAADK + DsDKSCsAAABgRIcOY29ubmVjdGlvbi5ocHAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAImt + cMswcGxURVhUAAAAAP////8AAAkgAAAAAAAAAAAAAAAAAAAAA3Ny + YwAAEAAIAADKDwcaAAAAEQAIAADLMMTMAAAAAQAYAGBEhwBgRCwA + BlzwAASELAADnw4AAJGQAAIAR0JlbGdhZXI6VXNlcnM6AHphcGhv + eWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBwOgBzcmM6AGNv + bm5lY3Rpb24uaHBwAAAOAB4ADgBjAG8AbgBuAGUAYwB0AGkAbwBu + AC4AaABwAHAADwAQAAcAQgBlAGwAZwBhAGUAcgASADlVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9zcmMvY29u + bmVjdGlvbi5ocHAAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/src/connection.hpp + RelativePath + ./src/connection.hpp + TypeID + _CFileLocator + Version + 1 + + + OpenDocumentsExpanded + + OpenDocumentsVisible + + ProjectViewVisible + + RecentItems:zaphoyd + + + Date + 2012-01-12T15:51:29Z + Location + + AliasData + + AAAAAAHiAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8NpMRc3RyZXNzX2NsaWVudC5j + cHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAImtbsswcGxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAADXN0cmVzc19jbGll + bnQAABAACAAAyg8HGgAAABEACAAAyzDEzAAAAAEAHAB8 + NpMAYERqAGBELAAGXPAABIQsAAOfDgAAkZAAAgBeQmVs + Z2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1lbnRzOgBa + UzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBzdHJlc3Nf + Y2xpZW50OgBzdHJlc3NfY2xpZW50LmNwcAAOACQAEQBz + AHQAcgBlAHMAcwBfAGMAbABpAGUAbgB0AC4AYwBwAHAA + DwAQAAcAQgBlAGwAZwBhAGUAcgASAE9Vc2Vycy96YXBo + b3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9leGFt + cGxlcy9zdHJlc3NfY2xpZW50L3N0cmVzc19jbGllbnQu + Y3BwAAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/stress_client/stress_client.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:51:11Z + Location + + AliasData + + AAAAAAIEAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB73nAWZnV6emluZ19zZXJ2ZXJf + dGxzLmNwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHvec8sGR4NURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAEmZ1enppbmdfc2Vy + dmVyX3RscwAQAAgAAMoPBxoAAAARAAgAAMsGm+MAAAAB + ABwAe95wAGBEagBgRCwABlzwAASELAADnw4AAJGQAAIA + aEJlbGdhZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50 + czoAWlM6AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZnV6 + emluZ19zZXJ2ZXJfdGxzOgBmdXp6aW5nX3NlcnZlcl90 + bHMuY3BwAA4ALgAWAGYAdQB6AHoAaQBuAGcAXwBzAGUA + cgB2AGUAcgBfAHQAbABzAC4AYwBwAHAADwAQAAcAQgBl + AGwAZwBhAGUAcgASAFlVc2Vycy96YXBob3lkL0RvY3Vt + ZW50cy9aUy93ZWJzb2NrZXRwcC9leGFtcGxlcy9mdXp6 + aW5nX3NlcnZlcl90bHMvZnV6emluZ19zZXJ2ZXJfdGxz + LmNwcAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/fuzzing_server_tls/fuzzing_server_tls.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:51:08Z + Location + + AliasData + + AAAAAAHsAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB73nAQZWNob19jbGllbnQuaHRt + bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHvecssGR4NURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAEmZ1enppbmdfc2Vy + dmVyX3RscwAQAAgAAMoPBxoAAAARAAgAAMsGm+MAAAAB + ABwAe95wAGBEagBgRCwABlzwAASELAADnw4AAJGQAAIA + YkJlbGdhZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50 + czoAWlM6AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZnV6 + emluZ19zZXJ2ZXJfdGxzOgBlY2hvX2NsaWVudC5odG1s + AA4AIgAQAGUAYwBoAG8AXwBjAGwAaQBlAG4AdAAuAGgA + dABtAGwADwAQAAcAQgBlAGwAZwBhAGUAcgASAFNVc2Vy + cy96YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRw + cC9leGFtcGxlcy9mdXp6aW5nX3NlcnZlcl90bHMvZWNo + b19jbGllbnQuaHRtbAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/fuzzing_server_tls/echo_client.html + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:50:58Z + Location + + AliasData + + AAAAAAHoAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB73m0SZnV6emluZ19jbGllbnQu + Y3BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAH02q8sNBB1URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAADmZ1enppbmdfY2xp + ZW50ABAACAAAyg8HGgAAABEACAAAyw1YfQAAAAEAHAB7 + 3m0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAAAgBgQmVs + Z2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1lbnRzOgBa + UzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBmdXp6aW5n + X2NsaWVudDoAZnV6emluZ19jbGllbnQuY3BwAA4AJgAS + AGYAdQB6AHoAaQBuAGcAXwBjAGwAaQBlAG4AdAAuAGMA + cABwAA8AEAAHAEIAZQBsAGcAYQBlAHIAEgBRVXNlcnMv + emFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAv + ZXhhbXBsZXMvZnV6emluZ19jbGllbnQvZnV6emluZ19j + bGllbnQuY3BwAAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/fuzzing_client/fuzzing_client.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:50:54Z + Location + + AliasData + + AAAAAAGkAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRCwQZGVwZW5kZW5jaWVzLnR4 + dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHmmzcr8+n8AAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC3dlYnNvY2tldHBw + AAAQAAgAAMoPBxoAAAARAAgAAMr9Tt8AAAABABQAYEQs + AAZc8AAEhCwAA58OAACRkAACAERCZWxnYWVyOlVzZXJz + OgB6YXBob3lkOgBEb2N1bWVudHM6AFpTOgB3ZWJzb2Nr + ZXRwcDoAZGVwZW5kZW5jaWVzLnR4dAAOACIAEABkAGUA + cABlAG4AZABlAG4AYwBpAGUAcwAuAHQAeAB0AA8AEAAH + AEIAZQBsAGcAYQBlAHIAEgA3VXNlcnMvemFwaG95ZC9E + b2N1bWVudHMvWlMvd2Vic29ja2V0cHAvZGVwZW5kZW5j + aWVzLnR4dAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/dependencies.txt + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:50:00Z + Location + + AliasData + + AAAAAAHEAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB5ptAIZWNoby5ocHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHmm08r8+n9URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAD2VjaG9fc2VydmVy + X3RscwAAEAAIAADKDwcaAAAAEQAIAADK/U7fAAAAAQAc + AHmm0ABgRGoAYEQsAAZc8AAEhCwAA58OAACRkAACAFdC + ZWxnYWVyOlVzZXJzOgB6YXBob3lkOgBEb2N1bWVudHM6 + AFpTOgB3ZWJzb2NrZXRwcDoAZXhhbXBsZXM6AGVjaG9f + c2VydmVyX3RsczoAZWNoby5ocHAAAA4AEgAIAGUAYwBo + AG8ALgBoAHAAcAAPABAABwBCAGUAbABnAGEAZQByABIA + SFVzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dlYnNv + Y2tldHBwL2V4YW1wbGVzL2VjaG9fc2VydmVyX3Rscy9l + Y2hvLmhwcAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server_tls/echo.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:49:54Z + Location + + AliasData + + AAAAAAHEAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB5ptAIZWNoby5jcHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHmm0sr8+n8AAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAD2VjaG9fc2VydmVy + X3RscwAAEAAIAADKDwcaAAAAEQAIAADK/U7fAAAAAQAc + AHmm0ABgRGoAYEQsAAZc8AAEhCwAA58OAACRkAACAFdC + ZWxnYWVyOlVzZXJzOgB6YXBob3lkOgBEb2N1bWVudHM6 + AFpTOgB3ZWJzb2NrZXRwcDoAZXhhbXBsZXM6AGVjaG9f + c2VydmVyX3RsczoAZWNoby5jcHAAAA4AEgAIAGUAYwBo + AG8ALgBjAHAAcAAPABAABwBCAGUAbABnAGEAZQByABIA + SFVzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dlYnNv + Y2tldHBwL2V4YW1wbGVzL2VjaG9fc2VydmVyX3Rscy9l + Y2hvLmNwcAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server_tls/echo.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:49:48Z + Location + + AliasData + + AAAAAAHwAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB5ptATZWNob19zZXJ2ZXJfdGxz + LmNwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIq3/csCiMZURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAD2VjaG9fc2VydmVy + X3RscwAAEAAIAADKDwcaAAAAEQAIAADLAt0mAAAAAQAc + AHmm0ABgRGoAYEQsAAZc8AAEhCwAA58OAACRkAACAGJC + ZWxnYWVyOlVzZXJzOgB6YXBob3lkOgBEb2N1bWVudHM6 + AFpTOgB3ZWJzb2NrZXRwcDoAZXhhbXBsZXM6AGVjaG9f + c2VydmVyX3RsczoAZWNob19zZXJ2ZXJfdGxzLmNwcAAO + ACgAEwBlAGMAaABvAF8AcwBlAHIAdgBlAHIAXwB0AGwA + cwAuAGMAcABwAA8AEAAHAEIAZQBsAGcAYQBlAHIAEgBT + VXNlcnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vic29j + a2V0cHAvZXhhbXBsZXMvZWNob19zZXJ2ZXJfdGxzL2Vj + aG9fc2VydmVyX3Rscy5jcHAAABMAAS8AABUAAgAO//8A + AA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server_tls/echo_server_tls.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:49:33Z + Location + + AliasData + + AAAAAAHkAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB5ptAQZWNob19jbGllbnQuaHRt + bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHmm1Mr8+n9URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAD2VjaG9fc2VydmVy + X3RscwAAEAAIAADKDwcaAAAAEQAIAADK/U7fAAAAAQAc + AHmm0ABgRGoAYEQsAAZc8AAEhCwAA58OAACRkAACAF9C + ZWxnYWVyOlVzZXJzOgB6YXBob3lkOgBEb2N1bWVudHM6 + AFpTOgB3ZWJzb2NrZXRwcDoAZXhhbXBsZXM6AGVjaG9f + c2VydmVyX3RsczoAZWNob19jbGllbnQuaHRtbAAADgAi + ABAAZQBjAGgAbwBfAGMAbABpAGUAbgB0AC4AaAB0AG0A + bAAPABAABwBCAGUAbABnAGEAZQByABIAUFVzZXJzL3ph + cGhveWQvRG9jdW1lbnRzL1pTL3dlYnNvY2tldHBwL2V4 + YW1wbGVzL2VjaG9fc2VydmVyX3Rscy9lY2hvX2NsaWVu + dC5odG1sABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server_tls/echo_client.html + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:49:02Z + Location + + AliasData + + AAAAAAG4AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRH4IZWNoby5ocHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAG9t4crdfj5URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMrd0p4AAAABABwAYER+ + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAU0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19zZXJ2 + ZXI6AGVjaG8uaHBwAAAOABIACABlAGMAaABvAC4AaABw + AHAADwAQAAcAQgBlAGwAZwBhAGUAcgASAERVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9lY2hvX3NlcnZlci9lY2hvLmhwcAATAAEv + AAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server/echo.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:59Z + Location + + AliasData + + AAAAAAG4AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRH4IZWNoby5jcHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAG0jCcrdfj4AAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMrd0p4AAAABABwAYER+ + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAU0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19zZXJ2 + ZXI6AGVjaG8uY3BwAAAOABIACABlAGMAaABvAC4AYwBw + AHAADwAQAAcAQgBlAGwAZwBhAGUAcgASAERVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9lY2hvX3NlcnZlci9lY2hvLmNwcAATAAEv + AAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server/echo.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:57Z + Location + + AliasData + + AAAAAAHUAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRH4PZWNob19zZXJ2ZXIuY3Bw + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIqxOcsDpeRURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMsD+kQAAAABABwAYER+ + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAWkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19zZXJ2 + ZXI6AGVjaG9fc2VydmVyLmNwcAAOACAADwBlAGMAaABv + AF8AcwBlAHIAdgBlAHIALgBjAHAAcAAPABAABwBCAGUA + bABnAGEAZQByABIAS1VzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2VjaG9f + c2VydmVyL2VjaG9fc2VydmVyLmNwcAAAEwABLwAAFQAC + AA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server/echo_server.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:55Z + Location + + AliasData + + AAAAAAHYAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRH4QZWNob19jbGllbnQuaHRt + bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEgsq9yMBURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxAAAAABABwAYER+ + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAW0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19zZXJ2 + ZXI6AGVjaG9fY2xpZW50Lmh0bWwAAA4AIgAQAGUAYwBo + AG8AXwBjAGwAaQBlAG4AdAAuAGgAdABtAGwADwAQAAcA + QgBlAGwAZwBhAGUAcgASAExVc2Vycy96YXBob3lkL0Rv + Y3VtZW50cy9aUy93ZWJzb2NrZXRwcC9leGFtcGxlcy9l + Y2hvX3NlcnZlci9lY2hvX2NsaWVudC5odG1sABMAAS8A + ABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_server/echo_client.html + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:35Z + Location + + AliasData + + AAAAAAHUAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHkPZWNob19jbGllbnQuY3Bw + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIrQGMswcGxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMswxMwAAAABABwAYER5 + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAWkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19jbGll + bnQ6AGVjaG9fY2xpZW50LmNwcAAOACAADwBlAGMAaABv + AF8AYwBsAGkAZQBuAHQALgBjAHAAcAAPABAABwBCAGUA + bABnAGEAZQByABIAS1VzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2VjaG9f + Y2xpZW50L2VjaG9fY2xpZW50LmNwcAAAEwABLwAAFQAC + AA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_client/echo_client.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:33Z + Location + + AliasData + + AAAAAAH0AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHkXZWNob19jbGllbnRfaGFu + ZGxlci5ocHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAG0jB8rdfj5URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMrd0p4AAAABABwAYER5 + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAYkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19jbGll + bnQ6AGVjaG9fY2xpZW50X2hhbmRsZXIuaHBwAA4AMAAX + AGUAYwBoAG8AXwBjAGwAaQBlAG4AdABfAGgAYQBuAGQA + bABlAHIALgBoAHAAcAAPABAABwBCAGUAbABnAGEAZQBy + ABIAU1VzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dl + YnNvY2tldHBwL2V4YW1wbGVzL2VjaG9fY2xpZW50L2Vj + aG9fY2xpZW50X2hhbmRsZXIuaHBwAAATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_client/echo_client_handler.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:28Z + Location + + AliasData + + AAAAAAH0AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHkXZWNob19jbGllbnRfaGFu + ZGxlci5jcHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGkECcrQL69URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2VjaG9fY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMrQdf8AAAABABwAYER5 + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAYkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAZWNob19jbGll + bnQ6AGVjaG9fY2xpZW50X2hhbmRsZXIuY3BwAA4AMAAX + AGUAYwBoAG8AXwBjAGwAaQBlAG4AdABfAGgAYQBuAGQA + bABlAHIALgBjAHAAcAAPABAABwBCAGUAbABnAGEAZQBy + ABIAU1VzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dl + YnNvY2tldHBwL2V4YW1wbGVzL2VjaG9fY2xpZW50L2Vj + aG9fY2xpZW50X2hhbmRsZXIuY3BwAAATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/echo_client/echo_client_handler.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:05Z + Location + + AliasData + + AAAAAAG4AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHIIY2hhdC5ocHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAG9vHcrQL69URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMrQdf8AAAABABwAYERy + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAU0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9zZXJ2 + ZXI6AGNoYXQuaHBwAAAOABIACABjAGgAYQB0AC4AaABw + AHAADwAQAAcAQgBlAGwAZwBhAGUAcgASAERVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9jaGF0X3NlcnZlci9jaGF0LmhwcAATAAEv + AAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_server/chat.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:48:02Z + Location + + AliasData + + AAAAAAG4AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHIIY2hhdC5jcHAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHIAEcrpNOZURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMrpiUYAAAABABwAYERy + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAU0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9zZXJ2 + ZXI6AGNoYXQuY3BwAAAOABIACABjAGgAYQB0AC4AYwBw + AHAADwAQAAcAQgBlAGwAZwBhAGUAcgASAERVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9jaGF0X3NlcnZlci9jaGF0LmNwcAATAAEv + AAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_server/chat.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:50Z + Location + + AliasData + + AAAAAAHUAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRHIPY2hhdF9zZXJ2ZXIuY3Bw + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHIAEsrpNOZURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfc2VydmVy + AAAQAAgAAMoPBxoAAAARAAgAAMrpiUYAAAABABwAYERy + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAWkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9zZXJ2 + ZXI6AGNoYXRfc2VydmVyLmNwcAAOACAADwBjAGgAYQB0 + AF8AcwBlAHIAdgBlAHIALgBjAHAAcAAPABAABwBCAGUA + bABnAGEAZQByABIAS1VzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2NoYXRf + c2VydmVyL2NoYXRfc2VydmVyLmNwcAAAEwABLwAAFQAC + AA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_server/chat_server.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:46Z + Location + + AliasData + + AAAAAAG4AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRGsITWFrZWZpbGUAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEbMq9yMAAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxAAAAABABwAYERr + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAU0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9jbGll + bnQ6AE1ha2VmaWxlAAAOABIACABNAGEAawBlAGYAaQBs + AGUADwAQAAcAQgBlAGwAZwBhAGUAcgASAERVc2Vycy96 + YXBob3lkL0RvY3VtZW50cy9aUy93ZWJzb2NrZXRwcC9l + eGFtcGxlcy9jaGF0X2NsaWVudC9NYWtlZmlsZQATAAEv + AAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_client/Makefile + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:35Z + Location + + AliasData + + AAAAAAHYAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRGsQY2hhdF9jbGllbnQuaHRt + bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEbsq9yMBURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxAAAAABABwAYERr + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAW0JlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9jbGll + bnQ6AGNoYXRfY2xpZW50Lmh0bWwAAA4AIgAQAGMAaABh + AHQAXwBjAGwAaQBlAG4AdAAuAGgAdABtAGwADwAQAAcA + QgBlAGwAZwBhAGUAcgASAExVc2Vycy96YXBob3lkL0Rv + Y3VtZW50cy9aUy93ZWJzb2NrZXRwcC9leGFtcGxlcy9j + aGF0X2NsaWVudC9jaGF0X2NsaWVudC5odG1sABMAAS8A + ABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_client/chat_client.html + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:20Z + Location + + AliasData + + AAAAAAH0AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRGsXY2hhdF9jbGllbnRfaGFu + ZGxlci5ocHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGkEA8rQL69URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMrQdf8AAAABABwAYERr + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAYkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9jbGll + bnQ6AGNoYXRfY2xpZW50X2hhbmRsZXIuaHBwAA4AMAAX + AGMAaABhAHQAXwBjAGwAaQBlAG4AdABfAGgAYQBuAGQA + bABlAHIALgBoAHAAcAAPABAABwBCAGUAbABnAGEAZQBy + ABIAU1VzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dl + YnNvY2tldHBwL2V4YW1wbGVzL2NoYXRfY2xpZW50L2No + YXRfY2xpZW50X2hhbmRsZXIuaHBwAAATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_client/chat_client_handler.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:19Z + Location + + AliasData + + AAAAAAHUAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRGsPY2hhdF9jbGllbnQuY3Bw + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGBEbcq9yMBURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMq+DxAAAAABABwAYERr + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAWkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9jbGll + bnQ6AGNoYXRfY2xpZW50LmNwcAAOACAADwBjAGgAYQB0 + AF8AYwBsAGkAZQBuAHQALgBjAHAAcAAPABAABwBCAGUA + bABnAGEAZQByABIAS1VzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2NoYXRf + Y2xpZW50L2NoYXRfY2xpZW50LmNwcAAAEwABLwAAFQAC + AA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_client/chat_client.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:10Z + Location + + AliasData + + AAAAAAH0AAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRGsXY2hhdF9jbGllbnRfaGFu + ZGxlci5jcHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAGkEAsrQL69URVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAC2NoYXRfY2xpZW50 + AAAQAAgAAMoPBxoAAAARAAgAAMrQdf8AAAABABwAYERr + AGBEagBgRCwABlzwAASELAADnw4AAJGQAAIAYkJlbGdh + ZXI6VXNlcnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6 + AHdlYnNvY2tldHBwOgBleGFtcGxlczoAY2hhdF9jbGll + bnQ6AGNoYXRfY2xpZW50X2hhbmRsZXIuY3BwAA4AMAAX + AGMAaABhAHQAXwBjAGwAaQBlAG4AdABfAGgAYQBuAGQA + bABlAHIALgBjAHAAcAAPABAABwBCAGUAbABnAGEAZQBy + ABIAU1VzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dl + YnNvY2tldHBwL2V4YW1wbGVzL2NoYXRfY2xpZW50L2No + YXRfY2xpZW50X2hhbmRsZXIuY3BwAAATAAEvAAAVAAIA + Dv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/chat_client/chat_client_handler.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:47:04Z + Location + + AliasData + + AAAAAAHSAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0ITWFrZWZpbGUAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIC3Y8sXdbIAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyxfKEgAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBcQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoATWFrZWZpbGUADgAS + AAgATQBhAGsAZQBmAGkAbABlAA8AEAAHAEIAZQBsAGcA + YQBlAHIAEgBNVXNlcnMvemFwaG95ZC9Eb2N1bWVudHMv + WlMvd2Vic29ja2V0cHAvZXhhbXBsZXMvYnJvYWRjYXN0 + X3NlcnZlcl90bHMvTWFrZWZpbGUAABMAAS8AABUAAgAO + //8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/Makefile + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:46:59Z + Location + + AliasData + + AAAAAAHKAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0GbWQ1LmpzAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIiW6csscHUAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyyzE1QAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBaQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAbWQ1LmpzAA4ADgAG + AG0AZAA1AC4AagBzAA8AEAAHAEIAZQBsAGcAYQBlAHIA + EgBLVXNlcnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vi + c29ja2V0cHAvZXhhbXBsZXMvYnJvYWRjYXN0X3NlcnZl + cl90bHMvbWQ1LmpzAAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/md5.js + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:46:49Z + Location + + AliasData + + AAAAAAHWAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0Jd3NjbWQuaHBwAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIC3acsXdbIAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyxfKEgAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBdQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAd3NjbWQuaHBwAAAO + ABQACQB3AHMAYwBtAGQALgBoAHAAcAAPABAABwBCAGUA + bABnAGEAZQByABIATlVzZXJzL3phcGhveWQvRG9jdW1l + bnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2Jyb2Fk + Y2FzdF9zZXJ2ZXJfdGxzL3dzY21kLmhwcAATAAEvAAAV + AAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/wscmd.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:46:41Z + Location + + AliasData + + AAAAAAISAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0YYnJvYWRjYXN0X3NlcnZl + cl90bHMuY3BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIqYgcszIORURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyzN1RAAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBsQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAYnJvYWRjYXN0X3Nl + cnZlcl90bHMuY3BwAA4AMgAYAGIAcgBvAGEAZABjAGEA + cwB0AF8AcwBlAHIAdgBlAHIAXwB0AGwAcwAuAGMAcABw + AA8AEAAHAEIAZQBsAGcAYQBlAHIAEgBdVXNlcnMvemFw + aG95ZC9Eb2N1bWVudHMvWlMvd2Vic29ja2V0cHAvZXhh + bXBsZXMvYnJvYWRjYXN0X3NlcnZlcl90bHMvYnJvYWRj + YXN0X3NlcnZlcl90bHMuY3BwAAATAAEvAAAVAAIADv// + AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/broadcast_server_tls.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:46:33Z + Location + + AliasData + + AAAAAAIiAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0cYnJvYWRjYXN0X3NlcnZl + cl9oYW5kbGVyLmhwcAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIC3Z8sXdbIAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyxfKEgAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBwQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAYnJvYWRjYXN0X3Nl + cnZlcl9oYW5kbGVyLmhwcAAOADoAHABiAHIAbwBhAGQA + YwBhAHMAdABfAHMAZQByAHYAZQByAF8AaABhAG4AZABs + AGUAcgAuAGgAcABwAA8AEAAHAEIAZQBsAGcAYQBlAHIA + EgBhVXNlcnMvemFwaG95ZC9Eb2N1bWVudHMvWlMvd2Vi + c29ja2V0cHAvZXhhbXBsZXMvYnJvYWRjYXN0X3NlcnZl + cl90bHMvYnJvYWRjYXN0X3NlcnZlcl9oYW5kbGVyLmhw + cAAAEwABLwAAFQACAA7//wAA + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/broadcast_server_handler.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:46:20Z + Location + + AliasData + + AAAAAAIGAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0VYnJvYWRjYXN0X2hhbmRs + ZXIuaHBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAImta8swcGxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyzDEzAAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBpQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAYnJvYWRjYXN0X2hh + bmRsZXIuaHBwAAAOACwAFQBiAHIAbwBhAGQAYwBhAHMA + dABfAGgAYQBuAGQAbABlAHIALgBoAHAAcAAPABAABwBC + AGUAbABnAGEAZQByABIAWlVzZXJzL3phcGhveWQvRG9j + dW1lbnRzL1pTL3dlYnNvY2tldHBwL2V4YW1wbGVzL2Jy + b2FkY2FzdF9zZXJ2ZXJfdGxzL2Jyb2FkY2FzdF9oYW5k + bGVyLmhwcAATAAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/broadcast_handler.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:45:52Z + Location + + AliasData + + AAAAAAICAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0UYnJvYWRjYXN0X2FkbWlu + Lmh0bWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIiW48sscHRURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyyzE1AAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBoQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAYnJvYWRjYXN0X2Fk + bWluLmh0bWwADgAqABQAYgByAG8AYQBkAGMAYQBzAHQA + XwBhAGQAbQBpAG4ALgBoAHQAbQBsAA8AEAAHAEIAZQBs + AGcAYQBlAHIAEgBZVXNlcnMvemFwaG95ZC9Eb2N1bWVu + dHMvWlMvd2Vic29ja2V0cHAvZXhhbXBsZXMvYnJvYWRj + YXN0X3NlcnZlcl90bHMvYnJvYWRjYXN0X2FkbWluLmh0 + bWwAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/broadcast_admin.html + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:45:42Z + Location + + AliasData + + AAAAAAIeAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAAB8No0bYnJvYWRjYXN0X2FkbWlu + X2hhbmRsZXIuaHBwAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAImtasswcGxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAFGJyb2FkY2FzdF9z + ZXJ2ZXJfdGxzABAACAAAyg8HGgAAABEACAAAyzDEzAAA + AAEAHAB8No0AYERqAGBELAAGXPAABIQsAAOfDgAAkZAA + AgBvQmVsZ2FlcjpVc2VyczoAemFwaG95ZDoARG9jdW1l + bnRzOgBaUzoAd2Vic29ja2V0cHA6AGV4YW1wbGVzOgBi + cm9hZGNhc3Rfc2VydmVyX3RsczoAYnJvYWRjYXN0X2Fk + bWluX2hhbmRsZXIuaHBwAAAOADgAGwBiAHIAbwBhAGQA + YwBhAHMAdABfAGEAZABtAGkAbgBfAGgAYQBuAGQAbABl + AHIALgBoAHAAcAAPABAABwBCAGUAbABnAGEAZQByABIA + YFVzZXJzL3phcGhveWQvRG9jdW1lbnRzL1pTL3dlYnNv + Y2tldHBwL2V4YW1wbGVzL2Jyb2FkY2FzdF9zZXJ2ZXJf + dGxzL2Jyb2FkY2FzdF9hZG1pbl9oYW5kbGVyLmhwcAAT + AAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/examples/broadcast_server_tls/broadcast_admin_handler.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:45:33Z + Location + + AliasData + + AAAAAAGuAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRKcMdXJpX3BlcmYuY3BwAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIqmrcszKBxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAABWJhc2ljAAAQAAgA + AMoPBxoAAAARAAgAAMszfHwAAAABABwAYESnAGBEpgBg + RCwABlzwAASELAADnw4AAJGQAAIATUJlbGdhZXI6VXNl + cnM6AHphcGhveWQ6AERvY3VtZW50czoAWlM6AHdlYnNv + Y2tldHBwOgB0ZXN0OgBiYXNpYzoAdXJpX3BlcmYuY3Bw + AAAOABoADAB1AHIAaQBfAHAAZQByAGYALgBjAHAAcAAP + ABAABwBCAGUAbABnAGEAZQByABIAPlVzZXJzL3phcGhv + eWQvRG9jdW1lbnRzL1pTL3dlYnNvY2tldHBwL3Rlc3Qv + YmFzaWMvdXJpX3BlcmYuY3BwABMAAS8AABUAAgAO//8A + AA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/test/basic/uri_perf.cpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:45:24Z + Location + + AliasData + + AAAAAAGaAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRIcMZW5kcG9pbnQuaHBwAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAImtccswcGwAAAAAAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAA3NyYwAAEAAIAADK + DwcaAAAAEQAIAADLMMTMAAAAAQAYAGBEhwBgRCwABlzw + AASELAADnw4AAJGQAAIARUJlbGdhZXI6VXNlcnM6AHph + cGhveWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBw + OgBzcmM6AGVuZHBvaW50LmhwcAAADgAaAAwAZQBuAGQA + cABvAGkAbgB0AC4AaABwAHAADwAQAAcAQgBlAGwAZwBh + AGUAcgASADdVc2Vycy96YXBob3lkL0RvY3VtZW50cy9a + Uy93ZWJzb2NrZXRwcC9zcmMvZW5kcG9pbnQuaHBwAAAT + AAEvAAAVAAIADv//AAA= + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/src/endpoint.hpp + TypeID + _CFileLocator + Version + 1 + + + + Date + 2012-01-12T15:41:09Z + Location + + AliasData + + AAAAAAGiAAIAAAdCZWxnYWVyAAAAAAAAAAAAAAAAAAAA + AAAAAADKDsDKSCsAAABgRIcOY29ubmVjdGlvbi5ocHAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAImtcMswcGxURVhUAAAAAP// + //8AAAkgAAAAAAAAAAAAAAAAAAAAA3NyYwAAEAAIAADK + DwcaAAAAEQAIAADLMMTMAAAAAQAYAGBEhwBgRCwABlzw + AASELAADnw4AAJGQAAIAR0JlbGdhZXI6VXNlcnM6AHph + cGhveWQ6AERvY3VtZW50czoAWlM6AHdlYnNvY2tldHBw + OgBzcmM6AGNvbm5lY3Rpb24uaHBwAAAOAB4ADgBjAG8A + bgBuAGUAYwB0AGkAbwBuAC4AaABwAHAADwAQAAcAQgBl + AGwAZwBhAGUAcgASADlVc2Vycy96YXBob3lkL0RvY3Vt + ZW50cy9aUy93ZWJzb2NrZXRwcC9zcmMvY29ubmVjdGlv + bi5ocHAAABMAAS8AABUAAgAO//8AAA== + + FileURL + file://localhost/Users/zaphoyd/Documents/ZS/websocketpp/src/connection.hpp + TypeID + _CFileLocator + Version + 1 + + + + RecentItemsExpanded + + RecentItemsVisible + + ScratchpadItemsExpanded + + ScratchpadItemsVisible + + ShowInvisibles:zaphoyd + + ShowSCMData:zaphoyd + + TextFilesOnly:zaphoyd + + ToolbarVisible:zaphoyd + + ViewSplitterPosition:zaphoyd + 0.18435753881931305 + WindowFrame:zaphoyd:displays([(0, 0), (2560, 1440)]:[(2560, -37), (1920, 1200)]) + rect(66,43,1360,1117) + +