From aec59a1eb99edab240519b8c83b3b704a2db21eb Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Sun, 31 Mar 2013 12:37:43 -0500 Subject: [PATCH] adds client handshake request generation and server response validation --- websocketpp/processors/hybi00.hpp | 10 +++++- websocketpp/processors/hybi13.hpp | 51 ++++++++++++++++++++++------ websocketpp/processors/processor.hpp | 15 ++++++-- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/websocketpp/processors/hybi00.hpp b/websocketpp/processors/hybi00.hpp index cfd0c335e5..28d5e7fbf1 100644 --- a/websocketpp/processors/hybi00.hpp +++ b/websocketpp/processors/hybi00.hpp @@ -137,7 +137,15 @@ public: } // outgoing client connection processing is not supported for this version - lib::error_code handshake_request(request_type& req, uri_ptr uri) const { + lib::error_code client_handshake_request(request_type& req, uri_ptr uri) + const + { + return error::make_error_code(error::no_protocol_support); + } + + lib::error_code validate_server_handshake_response(const request_type& req, + response_type& res) const + { return error::make_error_code(error::no_protocol_support); } diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index fabfa13e89..f8486948ec 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -40,6 +40,8 @@ #include #include +#include + #include #include @@ -166,14 +168,6 @@ public: { std::string server_key = request.get_header("Sec-WebSocket-Key"); - // library works on ints rather than bytes - message_digest[i] = htonl(message_digest[i]); - } - server_key = base64_encode( - reinterpret_cast(message_digest), - ); - - response.replace_header("Sec-WebSocket-Accept",server_key); lib::error_code ec = process_handshake_key(server_key); if (ec) { @@ -187,7 +181,9 @@ public: return lib::error_code(); } - lib::error_code handshake_request(request_type& req, uri_ptr uri) const { + lib::error_code client_handshake_request(request_type& req, uri_ptr + uri) const + { req.set_method("GET"); req.set_uri(uri->get_resource()); req.set_version("HTTP/1.1"); @@ -211,6 +207,41 @@ public: return lib::error_code(); } + lib::error_code validate_server_handshake_response(const request_type& req, + response_type& res) const + { + // A valid response has an HTTP 101 switching protocols code + if (res.get_status_code() != http::status_code::switching_protocols) { + return error::make_error_code(error::invalid_http_status); + } + + // And the upgrade token in an upgrade header + const std::string& upgrade_header = res.get_header("Upgrade"); + if (utility::ci_find_substr(upgrade_header, constants::upgrade_token, + sizeof(constants::upgrade_token)-1) == upgrade_header.end()) + { + return error::make_error_code(error::missing_required_header); + } + + // And the websocket token in the connection header + const std::string& con_header = res.get_header("Connection"); + if (utility::ci_find_substr(con_header, constants::connection_token, + sizeof(constants::connection_token)-1) == con_header.end()) + { + return error::make_error_code(error::missing_required_header); + } + + // And has a valid Sec-WebSocket-Accept value + std::string key = req.get_header("Sec-WebSocket-Key"); + lib::error_code ec = process_handshake_key(key); + + if (ec || key != res.get_header("Sec-WebSocket-Accept")) { + return error::make_error_code(error::missing_required_header); + } + + return lib::error_code(); + } + std::string get_raw(const response_type& res) const { return res.raw(); } @@ -847,7 +878,7 @@ protected: * * @return Status code, zero on success, non-zero on error */ - lib::error_code prepare_control(frame::opcode::value op, + lib::error_code prepare_control(frame::opcode::value op, const std::string & payload, message_ptr out) const { if (!out) { diff --git a/websocketpp/processors/processor.hpp b/websocketpp/processors/processor.hpp index 1e4b9b1f36..fa8837d677 100644 --- a/websocketpp/processors/processor.hpp +++ b/websocketpp/processors/processor.hpp @@ -199,8 +199,19 @@ public: * * @return An error code, 0 on success, non-zero for other errors */ - virtual lib::error_code handshake_request(request_type& req, uri_ptr uri) - const = 0; + virtual lib::error_code client_handshake_request(request_type& req, + uri_ptr uri) const = 0; + + /// Validate the server's response to an outgoing handshake request + /** + * @param req The original request sent + * + * @param res The reponse to generate + * + * @return An error code, 0 on success, non-zero for other errors + */ + virtual lib::error_code validate_server_handshake_response(const + request_type & req, response_type & res) const = 0; /// Given a completed response, get the raw bytes to put on the wire virtual std::string get_raw(const response_type& request) const = 0;