From dd4db981d537b2e4ba2e09ae614fc48785fd1a72 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 18 Oct 2011 17:23:41 -0500 Subject: [PATCH] more docs --- readme.txt | 120 ++++++++++++++++++++++++-- src/websocket_client.hpp | 25 ------ src/websocket_connection_handler.hpp | 63 +++++++++----- src/websocket_server.hpp | 25 ------ websocketpp.xcodeproj/project.pbxproj | 10 +++ 5 files changed, 162 insertions(+), 81 deletions(-) diff --git a/readme.txt b/readme.txt index 8fbeeb9d81..087106ffd2 100644 --- a/readme.txt +++ b/readme.txt @@ -110,10 +110,8 @@ Acknowledgements API spec notes -6.59 - -Server API +## Server API ## websocketpp.hpp create a websocketpp::server_ptr initialized to a new websocketpp::server object @@ -131,7 +129,9 @@ The only required option is that at least one host value must be set. Incoming w Once the server has been configured the way you want, call the start_accept() method. This will add the first async call to your io_service. If your io_service was already running, the server will start accepting connections immediately. If not you will need to call io_service.run() to start it. -Client API +Once the server has started it will accept new connections. A new session object will be created for each connection accepted. The session will perform the websocket handshake and if it is successful begin reading frames. The session will continue reading frames until an error occurs or a connection close frame is seen. The session will notify the handler that it was initilized with (see Handler API) as necessary. The Session API defines how a handler (or other part of the end application) can interact with the session (to get information about the session, send messages back to the client, etc) + +## Client API ## include websocketpp.hpp create a websocketpp::client_ptr initialized to a new websocketpp::client object @@ -147,14 +147,118 @@ Per the websocket spec, a client can only have one connection in the connecting - call websocketpp::client::new_session(). This will return a session_ptr -Handler API +## Handler API ## +The handler API defines the interface that a websocketpp session will use to communicate information about the session state and new messages to your application. + +A client or server must be initialized with a default handler that will be used for all sessions. The default handler may pass a session off to another handler as necessary. + +A handler must impliment the following methods: +- validate(session_ptr) +- on_fail(session_ptr) +- on_open(session_ptr) +- on_close(session_ptr) +- on_message(session_ptr,const std::vector &) +- on_message(session_ptr,const std::string &) + +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 negotiate subprotocols). To reject the connection throw a handshake_error. Validate is never called for client sessions. To refuse a client session (ex: if you do not like the set of extensions/subprotocols the server chose) you can close the connection immediately in the on_open member function. + +on_fail is called whenever a session is terminated or failed before it was successfully established. This happens if there is an error during the handshake process or if the server refused the connection. +on_fail will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out. + +on_open is called after the websocket session has been successfully established and is in the OPEN state. The session is now avaliable to send messages and will begin reading frames and calling the on_message/on_close/on_error callbacks. A client may reject the connection by closing the session at this point. + +on_close is called whenever an open session is closed for any reason. This can be due to either endpoint requesting a connection close or an error occuring. Information about why the session was closed can be extracted from the session itself. +on_close will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out. + +on_message (binary version) will be called when a binary message is recieved. Message data is passed as a vector of bytes (unsigned char). data will not be avaliable after this callback ends so the handler must either completely process the message or copy it somewhere else for processing later. + +TODO: Notes about thread safety + + +## Session API ## +The Session API allows a handler to look up information about a session as well as interact with that session (send messages, close the connection, etc) + +Session pointers are returned with every handler callback as well as every call to websocketpp::client::connect. + + +Handler Interface: +- set_handler(connection_handler_ptr) + +Handshake Interface: +For the client these methods are valid after the server's handshake has been received. This is guaranteed to be the case by the time `on_open` is called. +For the server these methods are valid after the client's handshake has been received. This is guaranteed to be the case by the time `validate` is called. + +- const std::string& get_subprotocol() const; +- const std::string& get_resource() const; +- const std::string& get_origin() const; +- std::string get_client_header(const std::string&) const; +- std::string get_server_header(const std::string&) const; +- const std::vector& get_extensions() const; +- unsigned int get_version() const; + +Frame Interface +- void send(const std::string &); +- void send(const std::vector &); +- void ping(const std::string &); +- void pong(const std::string &); + +These methods are valid only for open connections. They will throw an exception if called from any other state. + +WebSocket++ does not queue messages. As such only one send operation can be occuring at once. +TODO: failure behavior. OPTIONS: +- send will throw a `session_busy` exception if busy +- send will return true/false +- a callback could be defined letting the handler know that it is safe to write again. + +Session Interface +- void close(uint16_t status,const std::string &reason); +- bool is_server() const; -Session API - - +-------------------------------- +screwing around with a policy based refactoring +-------------------------------- +template +class endpoint : public WebSocketRole, Logger { +public: + endpoint(connection_handler_ptr); + + size_t get_connected_client_count() const; + + void set_endpoint(const tcp::endpoint& endpoint); // asio::bind + +private: + std::list m_connections; + connection_handler_ptr m_handler; + + boost::asio::io_service m_io_service; + tcp::acceptor m_acceptor; +} +class server_interface { +public: + void add_host(const std::string &host); + void remove_host(const std::string &host); + bool validate_host(const std::string &host) const; + + void set_max_message_size(uint64_t size); + bool validate_message_size(uint64_t size) const; + + void start() { + // start_accept() + // io_service.run() + } +private: + void start_accept(); + void handle_accept(session_ptr session, const boost::system::error_code&) + + std::set m_hosts; + uint64_t m_max_message_size; +} +class client_interface { + +} diff --git a/src/websocket_client.hpp b/src/websocket_client.hpp index 89bbe27395..0ef1437178 100644 --- a/src/websocket_client.hpp +++ b/src/websocket_client.hpp @@ -61,31 +61,6 @@ private: class client : public boost::enable_shared_from_this { public: - // System logging levels - /* static const uint16_t LOG_ALL = 0; - static const uint16_t LOG_DEBUG = 1; - static const uint16_t LOG_INFO = 2; - static const uint16_t LOG_WARN = 3; - static const uint16_t LOG_ERROR = 4; - static const uint16_t LOG_FATAL = 5; - static const uint16_t LOG_OFF = 6; - - // Access logging controls - // Individual bits - static const uint16_t ALOG_CONNECT = 0x1; - static const uint16_t ALOG_DISCONNECT = 0x2; - static const uint16_t ALOG_MISC_CONTROL = 0x4; - static const uint16_t ALOG_FRAME = 0x8; - static const uint16_t ALOG_MESSAGE = 0x10; - static const uint16_t ALOG_INFO = 0x20; - static const uint16_t ALOG_HANDSHAKE = 0x40; - // Useful groups - static const uint16_t ALOG_OFF = 0x0; - static const uint16_t ALOG_CONTROL = ALOG_CONNECT - & ALOG_DISCONNECT - & ALOG_MISC_CONTROL; - static const uint16_t ALOG_ALL = 0xFFFF; - */ static const uint16_t CLIENT_STATE_NULL = 0; static const uint16_t CLIENT_STATE_INITIALIZED = 1; static const uint16_t CLIENT_STATE_CONNECTING = 2; diff --git a/src/websocket_connection_handler.hpp b/src/websocket_connection_handler.hpp index 5a1778e274..9c48a46358 100644 --- a/src/websocket_connection_handler.hpp +++ b/src/websocket_connection_handler.hpp @@ -49,39 +49,56 @@ public: // connection based on application specific logic (ex: restrict domains or // negotiate subprotocols). To reject the connection throw a handshake_error // + // Validate is never called for client sessions. To refuse a client session + // (ex: if you do not like the set of extensions/subprotocols the server + // chose) you can close the connection immediately in the on_open method. + // // handshake_error parameters: // log_message - error message to send to server log // http_error_code - numeric HTTP error code to return to the client // http_error_msg - (optional) string HTTP error code to return to the // client (useful for returning non-standard error codes) - virtual void validate(session_ptr client) = 0; - + virtual void validate(session_ptr session) = 0; + // on_fail is called whenever a session is terminated or failed before it + // was successfully established. This happens if there is an error during + // the handshake process or if the server refused the connection. + // + // on_fail will be the last time a session calls its handler. If your + // application will need information from `session` after this function you + // should either save the session_ptr somewhere or copy the data out. + virtual void on_fail(session_ptr session) = 0; - // this will be called once the connected websocket is avaliable for - // writing messages. client may be a new websocket session or an existing - // session that was recently passed to this handler. - virtual void on_open(session_ptr client) = 0; - + // on_open is called after the websocket session has been successfully + // established and is in the OPEN state. The session is now avaliable to + // send messages and will begin reading frames and calling the on_message/ + // on_close/on_error callbacks. A client may reject the connection by + // closing the session at this point. + virtual void on_open(session_ptr session) = 0; - // this will be called when the connected websocket is no longer avaliable - // for writing messages. This occurs under the following conditions: - // - Disconnect message recieved from the remote endpoint - // - Someone (usually this object) calls the disconnect method of session - // - A disconnect acknowledgement is recieved (in case another object - // calls the disconnect method of session - // - The connection handler assigned to this client was set to another - // handler - virtual void on_close(session_ptr client,uint16_t status,const std::string &reason) = 0; + // on_close is called whenever an open session is closed for any reason. + // This can be due to either endpoint requesting a connection close or an + // error occuring. Information about why the session was closed can be + // extracted from the session itself. + // + // on_close will be the last time a session calls its handler. If your + // application will need information from `session` after this function you + // should either save the session_ptr somewhere or copy the data out. + virtual void on_close(session_ptr session) = 0; - // this will be called when a text message is recieved. Text will be - // encoded as UTF-8. - virtual void on_message(session_ptr client,const std::string &msg) = 0; + // on_message (binary version) will be called when a binary message is + // recieved. Message data is passed as a vector of bytes (unsigned char). + // data will not be avaliable after this callback ends so the handler must + // either completely process the message or copy it somewhere else for + // processing later. + virtual void on_message(session_ptr session, + const std::vector &data) = 0; + + // on_message (text version). Identical to on_message except the data + // parameter is a string interpreted as UTF-8. WebSocket++ guarantees that + // this string is valid UTF-8. + virtual void on_message(session_ptr session,const std::string &msg) = 0; - // this will be called when a binary message is recieved. Argument is a - // vector of the raw bytes in the message body. - virtual void on_message(session_ptr client, - const std::vector &data) = 0; }; diff --git a/src/websocket_server.hpp b/src/websocket_server.hpp index a1415b63ed..d294c13505 100644 --- a/src/websocket_server.hpp +++ b/src/websocket_server.hpp @@ -61,31 +61,6 @@ private: class server : public boost::enable_shared_from_this { public: - // System logging levels - /*static const uint16_t LOG_ALL = 0; - static const uint16_t LOG_DEBUG = 1; - static const uint16_t LOG_INFO = 2; - static const uint16_t LOG_WARN = 3; - static const uint16_t LOG_ERROR = 4; - static const uint16_t LOG_FATAL = 5; - static const uint16_t LOG_OFF = 6; - - // Access logging controls - // Individual bits - static const uint16_t ALOG_CONNECT = 0x1; - static const uint16_t ALOG_DISCONNECT = 0x2; - static const uint16_t ALOG_MISC_CONTROL = 0x4; - static const uint16_t ALOG_FRAME = 0x8; - static const uint16_t ALOG_MESSAGE = 0x10; - static const uint16_t ALOG_INFO = 0x20; - static const uint16_t ALOG_HANDSHAKE = 0x40; - // Useful groups - static const uint16_t ALOG_OFF = 0x0; - static const uint16_t ALOG_CONTROL = ALOG_CONNECT - & ALOG_DISCONNECT - & ALOG_MISC_CONTROL; - static const uint16_t ALOG_ALL = 0xFFFF; -*/ server(boost::asio::io_service& io_service, const tcp::endpoint& endpoint, connection_handler_ptr defc); diff --git a/websocketpp.xcodeproj/project.pbxproj b/websocketpp.xcodeproj/project.pbxproj index c44ea01195..70da3c369f 100644 --- a/websocketpp.xcodeproj/project.pbxproj +++ b/websocketpp.xcodeproj/project.pbxproj @@ -163,6 +163,7 @@ B6DF1CD11435ED910029A1B1 /* echo_server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = echo_server; sourceTree = BUILT_PRODUCTS_DIR; }; B6DF1CE11435F1860029A1B1 /* libboost_system.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_system.dylib; path = usr/local/lib/libboost_system.dylib; sourceTree = SDKROOT; }; B6DF1CE31435F8250029A1B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + B6FE8CE2144DE17F00B32547 /* readme.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = readme.txt; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -236,6 +237,7 @@ B682888C1437464A002BA48B /* libboost_random.dylib */, B682888A14374623002BA48B /* libboost_system.dylib */, B6DF1CE31435F8250029A1B1 /* Foundation.framework */, + B6FE8CE4144DE18900B32547 /* documentation */, B6DF1CC61435ED380029A1B1 /* examples */, B6DF1CC51435ECE40029A1B1 /* libraries */, B6DF1C7F1434ABB70029A1B1 /* src */, @@ -359,6 +361,14 @@ name = chat_server; sourceTree = ""; }; + B6FE8CE4144DE18900B32547 /* documentation */ = { + isa = PBXGroup; + children = ( + B6FE8CE2144DE17F00B32547 /* readme.txt */, + ); + name = documentation; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */