websocketpp  0.4.0
C++/Boost Asio based websocket client/server library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
processor.hpp
1 /*
2  * Copyright (c) 2014, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the WebSocket++ Project nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef WEBSOCKETPP_PROCESSOR_HPP
29 #define WEBSOCKETPP_PROCESSOR_HPP
30 
31 #include <websocketpp/processors/base.hpp>
32 #include <websocketpp/common/system_error.hpp>
33 
34 #include <websocketpp/close.hpp>
35 #include <websocketpp/utilities.hpp>
36 #include <websocketpp/uri.hpp>
37 
38 #include <map>
39 #include <string>
40 
41 namespace websocketpp {
43 
57 namespace processor {
58 
60 
65 template <typename request_type>
66 bool is_websocket_handshake(request_type& r) {
68 
69  std::string const & upgrade_header = r.get_header("Upgrade");
70 
71  if (ci_find_substr(upgrade_header, constants::upgrade_token,
72  sizeof(constants::upgrade_token)-1) == upgrade_header.end())
73  {
74  return false;
75  }
76 
77  std::string const & con_header = r.get_header("Connection");
78 
79  if (ci_find_substr(con_header, constants::connection_token,
80  sizeof(constants::connection_token)-1) == con_header.end())
81  {
82  return false;
83  }
84 
85  return true;
86 }
87 
89 
104 template <typename request_type>
105 int get_websocket_version(request_type& r) {
106  if (r.get_header("Sec-WebSocket-Version") == "") {
107  return 0;
108  }
109 
110  int version;
111  std::istringstream ss(r.get_header("Sec-WebSocket-Version"));
112 
113  if ((ss >> version).fail()) {
114  return -1;
115  }
116 
117  return version;
118 }
119 
121 
129 template <typename request_type>
130 uri_ptr get_uri_from_host(request_type & request, std::string scheme) {
131  std::string h = request.get_header("Host");
132 
133  size_t last_colon = h.rfind(":");
134  size_t last_sbrace = h.rfind("]");
135 
136  // no : = hostname with no port
137  // last : before ] = ipv6 literal with no port
138  // : with no ] = hostname with port
139  // : after ] = ipv6 literal with port
140  if (last_colon == std::string::npos ||
141  (last_sbrace != std::string::npos && last_sbrace > last_colon))
142  {
143  return lib::make_shared<uri>(scheme, h, request.get_uri());
144  } else {
145  return lib::make_shared<uri>(scheme,
146  h.substr(0,last_colon),
147  h.substr(last_colon+1),
148  request.get_uri());
149  }
150 }
151 
153 template <typename config>
154 class processor {
155 public:
156  typedef processor<config> type;
157  typedef typename config::request_type request_type;
158  typedef typename config::response_type response_type;
159  typedef typename config::message_type::ptr message_ptr;
160  typedef std::pair<lib::error_code,std::string> err_str_pair;
161 
162  explicit processor(bool secure, bool p_is_server)
163  : m_secure(secure)
164  , m_server(p_is_server)
165  , m_max_message_size(config::max_message_size)
166  {}
167 
168  virtual ~processor() {}
169 
171  virtual int get_version() const = 0;
172 
174 
182  size_t get_max_message_size() const {
183  return m_max_message_size;
184  }
185 
187 
197  void set_max_message_size(size_t new_value) {
198  m_max_message_size = new_value;
199  }
200 
202 
206  virtual bool has_permessage_compress() const {
207  return false;
208  }
209 
211 
218  virtual err_str_pair negotiate_extensions(request_type const &) {
219  return err_str_pair();
220  }
221 
223 
231  virtual lib::error_code validate_handshake(request_type const & request) const = 0;
232 
234 
243  virtual lib::error_code process_handshake(request_type const & req,
244  std::string const & subprotocol, response_type& res) const = 0;
245 
247 
252  virtual lib::error_code client_handshake_request(request_type & req,
253  uri_ptr uri, std::vector<std::string> const & subprotocols) const = 0;
254 
256 
261  virtual lib::error_code validate_server_handshake_response(request_type
262  const & req, response_type & res) const = 0;
263 
265  virtual std::string get_raw(response_type const & request) const = 0;
266 
268  virtual std::string const & get_origin(request_type const & request) const = 0;
269 
271 
279  virtual lib::error_code extract_subprotocols(const request_type & req,
280  std::vector<std::string> & subprotocol_list) = 0;
281 
283  virtual uri_ptr get_uri(request_type const & request) const = 0;
284 
286 
295  virtual size_t consume(uint8_t *buf, size_t len, lib::error_code & ec) = 0;
296 
298 
306  virtual bool ready() const = 0;
307 
309 
320  virtual message_ptr get_message() = 0;
321 
323  virtual bool get_error() const = 0;
324 
328  virtual size_t get_bytes_needed() const {
329  return 1;
330  }
331 
333 
337  virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out) = 0;
338 
340 
348  virtual lib::error_code prepare_ping(std::string const & in, message_ptr out) const
349  = 0;
350 
352 
360  virtual lib::error_code prepare_pong(std::string const & in, message_ptr out) const
361  = 0;
362 
364 
375  virtual lib::error_code prepare_close(close::status::value code,
376  std::string const & reason, message_ptr out) const = 0;
377 protected:
378  bool const m_secure;
379  bool const m_server;
380  size_t m_max_message_size;
381 };
382 
383 } // namespace processor
384 } // namespace websocketpp
385 
386 #endif //WEBSOCKETPP_PROCESSOR_HPP
uint16_t value
The type of a close code value.
Definition: close.hpp:49
size_t get_max_message_size() const
Get maximum message size.
Definition: processor.hpp:182
uri_ptr get_uri_from_host(request_type &request, std::string scheme)
Extract a URI ptr from the host header of the request.
Definition: processor.hpp:130
bool is_websocket_handshake(request_type &r)
Determine whether or not a generic HTTP request is a WebSocket handshake.
Definition: processor.hpp:66
void set_max_message_size(size_t new_value)
Set maximum message size.
Definition: processor.hpp:197
WebSocket protocol processor abstract base class.
Definition: processor.hpp:154
int get_websocket_version(request_type &r)
Extract the version from a WebSocket handshake request.
Definition: processor.hpp:105
virtual lib::error_code validate_handshake(request_type const &request) const =0
validate a WebSocket handshake request for this version
virtual std::string const & get_origin(request_type const &request) const =0
Return the value of the header containing the CORS origin.
virtual bool has_permessage_compress() const
Returns whether or not the permessage_compress extension is implemented.
Definition: processor.hpp:206
virtual lib::error_code prepare_pong(std::string const &in, message_ptr out) const =0
Prepare a pong frame.
virtual std::string get_raw(response_type const &request) const =0
Given a completed response, get the raw bytes to put on the wire.
virtual lib::error_code prepare_ping(std::string const &in, message_ptr out) const =0
Prepare a ping frame.
virtual bool get_error() const =0
Tests whether the processor is in a fatal error state.
virtual size_t consume(uint8_t *buf, size_t len, lib::error_code &ec)=0
process new websocket connection bytes
virtual int get_version() const =0
Get the protocol version of this processor.
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)=0
Prepare a data message for writing.
virtual message_ptr get_message()=0
Retrieves the most recently processed message.
virtual uri_ptr get_uri(request_type const &request) const =0
Extracts client uri from a handshake request.
virtual lib::error_code client_handshake_request(request_type &req, uri_ptr uri, std::vector< std::string > const &subprotocols) const =0
Fill in an HTTP request for an outgoing connection handshake.
Namespace for the WebSocket++ project.
Definition: base64.hpp:41
virtual err_str_pair negotiate_extensions(request_type const &)
Initializes extensions based on the Sec-WebSocket-Extensions header.
Definition: processor.hpp:218
virtual bool ready() const =0
Checks if there is a message ready.
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
Definition: uri.hpp:350
virtual lib::error_code prepare_close(close::status::value code, std::string const &reason, message_ptr out) const =0
Prepare a close frame.
virtual size_t get_bytes_needed() const
Definition: processor.hpp:328
virtual lib::error_code validate_server_handshake_response(request_type const &req, response_type &res) const =0
Validate the server's response to an outgoing handshake request.
virtual lib::error_code process_handshake(request_type const &req, std::string const &subprotocol, response_type &res) const =0
Calculate the appropriate response for this websocket request.
virtual lib::error_code extract_subprotocols(const request_type &req, std::vector< std::string > &subprotocol_list)=0
Extracts requested subprotocols from a handshake request.
T::const_iterator ci_find_substr(T const &haystack, T const &needle, std::locale const &loc=std::locale())
Find substring (case insensitive)
Definition: utilities.hpp:103