From d806bea762ca6d51d8e162f8ed52466c6b2d30cf Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Sun, 30 Oct 2011 07:43:59 -0500 Subject: [PATCH] more work, compiles and passes tests now --- Makefile | 5 +- examples/echo_server/Makefile | 2 +- examples/echo_server/echo.cpp | 14 - examples/echo_server/echo.hpp | 21 +- examples/echo_server/echo_server.cpp | 19 +- src/policy/rng/blank_rng.cpp | 10 - src/policy/rng/blank_rng.hpp | 5 +- src/websocket_connection_handler.hpp | 13 +- src/websocket_constants.hpp | 18 ++ src/websocket_frame.hpp | 5 +- src/websocket_server.hpp | 93 +++--- src/websocket_session.hpp | 418 +++++++++++++++++++++++--- src/websocketpp.hpp | 2 +- websocketpp.xcodeproj/project.pbxproj | 12 +- 14 files changed, 485 insertions(+), 152 deletions(-) diff --git a/Makefile b/Makefile index 75ecb2e9f0..04c817cf2e 100644 --- a/Makefile +++ b/Makefile @@ -28,10 +28,9 @@ # It's authors were Jonathan Wallace and Bernhard Fluehmann. -objects = websocket_server_session.o websocket_client_session.o websocket_session.o websocket_server.o websocket_client.o websocket_frame.o \ - network_utilities.o sha1.o base64.o +objects = network_utilities.o sha1.o base64.o -libs = -lboost_system -lboost_date_time -lboost_regex -lboost_random +libs = -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options OS=$(shell uname) diff --git a/examples/echo_server/Makefile b/examples/echo_server/Makefile index ab1c38d55d..e79b687288 100644 --- a/examples/echo_server/Makefile +++ b/examples/echo_server/Makefile @@ -5,7 +5,7 @@ CXX ?= c++ SHARED ?= "1" ifeq ($(SHARED), 1) - LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lwebsocketpp + LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_program_options -lwebsocketpp else LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options ../../libwebsocketpp.a endif diff --git a/examples/echo_server/echo.cpp b/examples/echo_server/echo.cpp index 202e725cee..d1001affb6 100644 --- a/examples/echo_server/echo.cpp +++ b/examples/echo_server/echo.cpp @@ -25,17 +25,3 @@ * */ -#include "echo.hpp" - -using websocketecho::echo_server_handler; - -void echo_server_handler::validate(websocketpp::session_ptr client) {} - -void echo_server_handler::on_message(websocketpp::session_ptr client, const std::string &msg) { - client->send(msg); -} - -void echo_server_handler::on_message(websocketpp::session_ptr client, - const std::vector &data) { - client->send(data); -} diff --git a/examples/echo_server/echo.hpp b/examples/echo_server/echo.hpp index c2c989a6a8..b3105eea2b 100644 --- a/examples/echo_server/echo.hpp +++ b/examples/echo_server/echo.hpp @@ -34,17 +34,20 @@ #include #include -using websocketpp::session_ptr; - namespace websocketecho { -class echo_server_handler : public websocketpp::connection_handler { +template +class echo_server_handler : public websocketpp::connection_handler { public: + //typedef boost::shared_ptr > + //typedef typename websocketpp::connection_handler::ptr session_ptr; + typedef typename websocketpp::connection_handler::session_ptr session_ptr; + echo_server_handler() {} virtual ~echo_server_handler() {} // The echo server allows all domains is protocol free. - void validate(session_ptr client); + void validate(session_ptr client) {} // an echo server is stateless. // The handler has no need to keep track of connected clients. @@ -53,13 +56,15 @@ public: void on_close(session_ptr client) {} // both text and binary messages are echoed back to the sending client. - void on_message(session_ptr client,const std::string &msg); + void on_message(session_ptr client,const std::string &msg) { + client->send(msg); + } void on_message(session_ptr client, - const std::vector &data); + const std::vector &data) { + client->send(data); + } }; -typedef boost::shared_ptr echo_server_handler_ptr; - } #endif // ECHO_SERVER_HANDLER_HPP diff --git a/examples/echo_server/echo_server.cpp b/examples/echo_server/echo_server.cpp index 001c9002ca..7de7140db1 100644 --- a/examples/echo_server/echo_server.cpp +++ b/examples/echo_server/echo_server.cpp @@ -50,15 +50,22 @@ int main(int argc, char* argv[]) { temp << host << ":" << port; full_host = temp.str(); - websocketecho::echo_server_handler_ptr echo_handler(new websocketecho::echo_server_handler()); + try { boost::asio::io_service io_service; tcp::endpoint endpoint(tcp::v6(), port); - websocketpp::server_ptr server( - new websocketpp::server<>(io_service,endpoint,echo_handler) - ); + using websocketpp::server; + + typedef boost::shared_ptr< server<> > server_ptr; + //typedef server<>::ptr server_ptr; + + server_ptr s(new server<>(io_service,endpoint)); + + server<>::connection_handler_ptr handler = s->make_handler(); + + s->set_default_connection_handler(handler); //server->parse_command_line(argc, argv); @@ -68,10 +75,10 @@ int main(int argc, char* argv[]) { // bump up max message size to maximum since we may be using the echo // server to test performance and protocol extremes. - server->set_max_message_size(websocketpp::frame::PAYLOAD_64BIT_LIMIT); + s->set_max_message_size(websocketpp::frame::limits::PAYLOAD_SIZE_JUMBO); // start the server - server->start_accept(); + s->start_accept(); std::cout << "Starting echo server on " << full_host << std::endl; diff --git a/src/policy/rng/blank_rng.cpp b/src/policy/rng/blank_rng.cpp index dcfcb81971..476770b0b4 100644 --- a/src/policy/rng/blank_rng.cpp +++ b/src/policy/rng/blank_rng.cpp @@ -26,13 +26,3 @@ * This Makefile was derived from a similar one included in the libjson project * It's authors were Jonathan Wallace and Bernhard Fluehmann. */ - -#include "blank_rng.hpp" - -using websocketpp::blank_rng; - -blank_rng::blank_rng() {} - -int32_t blank_rng::gen() { - throw "Random Number generation not supported"; -} \ No newline at end of file diff --git a/src/policy/rng/blank_rng.hpp b/src/policy/rng/blank_rng.hpp index b58f39ca20..5bc731bf96 100644 --- a/src/policy/rng/blank_rng.hpp +++ b/src/policy/rng/blank_rng.hpp @@ -36,8 +36,9 @@ namespace websocketpp { class blank_rng { public: - blank_rng(); - int32_t gen(); + int32_t gen() { + throw "Random Number generation not supported"; + } }; } diff --git a/src/websocket_connection_handler.hpp b/src/websocket_connection_handler.hpp index f3d93e43bf..652f5347f1 100644 --- a/src/websocket_connection_handler.hpp +++ b/src/websocket_connection_handler.hpp @@ -33,17 +33,16 @@ #include #include -namespace websocketpp { - class connection_handler; - typedef boost::shared_ptr connection_handler_ptr; -} - -#include "websocket_session.hpp" - namespace websocketpp { +template class connection_handler { public: + typedef connection_handler connection_handler_type; + + typedef boost::shared_ptr ptr; + typedef boost::shared_ptr session_ptr; + // validate will be called after a websocket handshake has been received and // before it is accepted. It provides a handler the ability to refuse a // connection based on application specific logic (ex: restrict domains or diff --git a/src/websocket_constants.hpp b/src/websocket_constants.hpp index b2758f79e4..4eb69b72e3 100644 --- a/src/websocket_constants.hpp +++ b/src/websocket_constants.hpp @@ -32,6 +32,10 @@ #include +// for exceptions that should be somewhere else +#include +#include + // Defaults namespace websocketpp { const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB @@ -151,6 +155,20 @@ namespace websocketpp { static const uint64_t PAYLOAD_SIZE_JUMBO = 0x7FFFFFFFFFFFFFFF;//2^63 } } + + // TODO: these classes need a better place to live + class server_error : public std::exception { + public: + server_error(const std::string& msg) + : m_msg(msg) {} + ~server_error() throw() {} + + virtual const char* what() const throw() { + return m_msg.c_str(); + } + private: + std::string m_msg; + }; } #endif // WEBSOCKET_CONSTANTS_HPP diff --git a/src/websocket_frame.hpp b/src/websocket_frame.hpp index 7c9a72ca67..bc93f0919f 100644 --- a/src/websocket_frame.hpp +++ b/src/websocket_frame.hpp @@ -534,7 +534,10 @@ public: if (payload_size > max_payload_size) { // TODO: frame/message size limits - throw websocketpp::server_error("got frame with payload greater than maximum frame buffer size."); + // 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; diff --git a/src/websocket_server.hpp b/src/websocket_server.hpp index 835882ff3a..38dfe64f94 100644 --- a/src/websocket_server.hpp +++ b/src/websocket_server.hpp @@ -36,11 +36,6 @@ namespace po = boost::program_options; #include -namespace websocketpp { - //class server; - //typedef boost::shared_ptr server_ptr; -} - #include "websocketpp.hpp" #include "websocket_session.hpp" #include "websocket_connection_handler.hpp" @@ -53,34 +48,28 @@ using boost::asio::ip::tcp; namespace websocketpp { -class server_error : public std::exception { -public: - server_error(const std::string& msg) - : m_msg(msg) {} - ~server_error() throw() {} - - virtual const char* what() const throw() { - return m_msg.c_str(); - } -private: - std::string m_msg; -}; -template + +template class server : public boost::enable_shared_from_this< server > { public: - typedef boost::shared_ptr< server > ptr; typedef rng_policy rng_t; + typedef server server_type; + typedef session session_type; + typedef connection_handler connection_handler_type; + + typedef boost::shared_ptr ptr; + typedef boost::shared_ptr session_ptr; + typedef boost::shared_ptr connection_handler_ptr; + server(boost::asio::io_service& io_service, - const tcp::endpoint& endpoint, - connection_handler_ptr defc) + const tcp::endpoint& endpoint) : m_elog_level(LOG_ALL), m_alog_level(ALOG_ALL), m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE), m_io_service(io_service), m_acceptor(io_service, endpoint), - m_def_con_handler(defc), m_desc("websocketpp::server") { m_desc.add_options() @@ -90,13 +79,21 @@ public: ; } + void set_default_connection_handler(connection_handler_ptr c) { + m_def_con_handler = c; + } + // creates a new session object and connects the next websocket // connection to it. void start_accept() { + if (m_def_con_handler == connection_handler_ptr()) { + throw server_error("start_accept called before a connection handler was set"); + } + // TODO: sanity check whether the session buffer size bound could be reduced - session >::ptr new_session( - new session >( - shared_from_this(), + session_ptr new_session( + new session_type( + server_type::shared_from_this(), m_io_service, m_def_con_handler, m_max_message_size*2 @@ -106,26 +103,20 @@ public: m_acceptor.async_accept( new_session->socket(), boost::bind( - &server::handle_accept, - shared_from_this(), + &server_type::handle_accept, + server_type::shared_from_this(), new_session, boost::asio::placeholders::error ) ); } - // INTERFACE FOR LOCAL APPLICATIONS - - // Add or remove a host string (host:port) to the list of acceptable - // hosts to accept websocket connections from. Additions/deletions here - // only affect new connections. - void add_host(std::string host) { - m_hosts.insert(host); - } - void remove_host(std::string host) { - m_hosts.erase(host); + template