WebSocket++  0.8.3-dev
C++ websocket client/server library
constants.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 HTTP_CONSTANTS_HPP
29 #define HTTP_CONSTANTS_HPP
30 
31 #include <exception>
32 #include <map>
33 #include <string>
34 #include <vector>
35 #include <utility>
36 
37 namespace websocketpp {
38 /// HTTP handling support
39 namespace http {
40 
41 /// The type of an HTTP attribute list
42 /**
43  * The attribute list is an unordered key/value map. Encoded attribute
44  * values are delimited by semicolons.
45  */
47 
48 /// The type of an HTTP parameter list
49 /**
50  * The parameter list is an ordered pairing of a parameter and its
51  * associated attribute list. Encoded parameter values are delimited by
52  * commas.
53  */
55 
56 /// Literal value of the HTTP header delimiter
57 static char const header_delimiter[] = "\r\n";
58 
59 /// Literal value of the HTTP header separator
60 static char const header_separator[] = ":";
61 
62 /// Literal value of an empty header
63 static std::string const empty_header;
64 
65 /// Maximum size in bytes before rejecting an HTTP header as too big.
66 size_t const max_header_size = 16000;
67 
68 /// Default Maximum size in bytes for HTTP message bodies.
69 size_t const max_body_size = 32000000;
70 
71 /// Number of bytes to use for temporary istream read buffers
72 size_t const istream_buffer = 512;
73 
74 /// invalid HTTP token characters
75 /**
76  * 0x00 - 0x32, 0x7f-0xff
77  * ( ) < > @ , ; : \ " / [ ] ? = { }
78  */
79 static char const header_token[] = {
80  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..0f
81  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10..1f
82  0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0, // 20..2f
83  1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 30..3f
84  0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 40..4f
85  1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1, // 50..5f
86  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 60..6f
87  1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0, // 70..7f
88  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80..8f
89  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90..9f
90  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a0..af
91  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b0..bf
92  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c0..cf
93  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d0..df
94  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e0..ef
95  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // f0..ff
96 };
97 
98 /// Is the character a token
99 inline bool is_token_char(unsigned char c) {
100  return (header_token[c] == 1);
101 }
102 
103 /// Is the character a non-token
104 inline bool is_not_token_char(unsigned char c) {
105  return !header_token[c];
106 }
107 
108 /// Is the character whitespace
109 /**
110  * whitespace is space (32) or horizontal tab (9)
111  */
112 inline bool is_whitespace_char(unsigned char c) {
113  return (c == 9 || c == 32);
114 }
115 
116 /// Is the character non-whitespace
117 inline bool is_not_whitespace_char(unsigned char c) {
118  return (c != 9 && c != 32);
119 }
120 
121 /// HTTP Status codes
122 namespace status_code {
123 /// Known values for HTTP Status codes
124 enum value {
125  uninitialized = 0,
126 
127  continue_code = 100,
128  switching_protocols = 101,
129 
130  ok = 200,
131  created = 201,
132  accepted = 202,
133  non_authoritative_information = 203,
134  no_content = 204,
135  reset_content = 205,
136  partial_content = 206,
137 
138  multiple_choices = 300,
139  moved_permanently = 301,
140  found = 302,
141  see_other = 303,
142  not_modified = 304,
143  use_proxy = 305,
144  temporary_redirect = 307,
145 
146  bad_request = 400,
147  unauthorized = 401,
148  payment_required = 402,
149  forbidden = 403,
150  not_found = 404,
151  method_not_allowed = 405,
152  not_acceptable = 406,
153  proxy_authentication_required = 407,
154  request_timeout = 408,
155  conflict = 409,
156  gone = 410,
157  length_required = 411,
158  precondition_failed = 412,
159  request_entity_too_large = 413,
160  request_uri_too_long = 414,
161  unsupported_media_type = 415,
162  request_range_not_satisfiable = 416,
163  expectation_failed = 417,
164  im_a_teapot = 418,
165  upgrade_required = 426,
166  precondition_required = 428,
167  too_many_requests = 429,
168  request_header_fields_too_large = 431,
169 
170  internal_server_error = 500,
171  not_implemented = 501,
172  bad_gateway = 502,
173  service_unavailable = 503,
174  gateway_timeout = 504,
175  http_version_not_supported = 505,
176  not_extended = 510,
177  network_authentication_required = 511
178 };
179 
180 /// Given a status code value, return the default status message
181 /**
182  *
183  * @param[in] code The HTTP status code to look up
184  * @return A string representing the default status message for this code
185  * @see websocketpp::http::status_code::value (list of valid codes)
186  */
188  switch (code) {
189  case uninitialized:
190  return "Uninitialized";
191  case continue_code:
192  return "Continue";
193  case switching_protocols:
194  return "Switching Protocols";
195  case ok:
196  return "OK";
197  case created:
198  return "Created";
199  case accepted:
200  return "Accepted";
201  case non_authoritative_information:
202  return "Non Authoritative Information";
203  case no_content:
204  return "No Content";
205  case reset_content:
206  return "Reset Content";
207  case partial_content:
208  return "Partial Content";
209  case multiple_choices:
210  return "Multiple Choices";
211  case moved_permanently:
212  return "Moved Permanently";
213  case found:
214  return "Found";
215  case see_other:
216  return "See Other";
217  case not_modified:
218  return "Not Modified";
219  case use_proxy:
220  return "Use Proxy";
221  case temporary_redirect:
222  return "Temporary Redirect";
223  case bad_request:
224  return "Bad Request";
225  case unauthorized:
226  return "Unauthorized";
227  case payment_required:
228  return "Payment Required";
229  case forbidden:
230  return "Forbidden";
231  case not_found:
232  return "Not Found";
233  case method_not_allowed:
234  return "Method Not Allowed";
235  case not_acceptable:
236  return "Not Acceptable";
237  case proxy_authentication_required:
238  return "Proxy Authentication Required";
239  case request_timeout:
240  return "Request Timeout";
241  case conflict:
242  return "Conflict";
243  case gone:
244  return "Gone";
245  case length_required:
246  return "Length Required";
247  case precondition_failed:
248  return "Precondition Failed";
249  case request_entity_too_large:
250  return "Request Entity Too Large";
251  case request_uri_too_long:
252  return "Request-URI Too Long";
253  case unsupported_media_type:
254  return "Unsupported Media Type";
255  case request_range_not_satisfiable:
256  return "Requested Range Not Satisfiable";
257  case expectation_failed:
258  return "Expectation Failed";
259  case im_a_teapot:
260  return "I'm a teapot";
261  case upgrade_required:
262  return "Upgrade Required";
263  case precondition_required:
264  return "Precondition Required";
265  case too_many_requests:
266  return "Too Many Requests";
267  case request_header_fields_too_large:
268  return "Request Header Fields Too Large";
269  case internal_server_error:
270  return "Internal Server Error";
271  case not_implemented:
272  return "Not Implemented";
273  case bad_gateway:
274  return "Bad Gateway";
275  case service_unavailable:
276  return "Service Unavailable";
277  case gateway_timeout:
278  return "Gateway Timeout";
279  case http_version_not_supported:
280  return "HTTP Version Not Supported";
281  case not_extended:
282  return "Not Extended";
283  case network_authentication_required:
284  return "Network Authentication Required";
285  default:
286  return "Unknown";
287  }
288 }
289 
290 } // namespace status_code
291 
292 /// An exception type specific to HTTP errors
293 /**
294  * Includes additional details, such as HTTP error code,
295  * HTTP error message, and a body to return with the HTTP
296  * error response.
297  */
298 class exception : public std::exception {
299 public:
300  exception(const std::string& log_msg,
301  status_code::value error_code,
302  const std::string& error_msg = std::string(),
303  const std::string& body = std::string())
304  : m_msg(log_msg)
305  , m_error_msg(error_msg)
306  , m_body(body)
307  , m_error_code(error_code) {}
308 
309  ~exception() throw() {}
310 
311  virtual const char* what() const throw() {
312  return m_msg.c_str();
313  }
314 
315  std::string m_msg;
316  std::string m_error_msg;
317  std::string m_body;
318  status_code::value m_error_code;
319 };
320 
321 
322 /// HTTP parser errors
323 namespace error {
324 enum value {
325  /// Catch-all error for http parser errors that don't fit in other
326  /// categories
327  general = 1,
328 
329  /// The header name specified contains illegal characters
331 
332  /// The body value is larger than the configured maximum size
334 };
335 
336 /// HTTP parser error category
337 class category : public lib::error_category {
338 public:
339  char const * name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
340  return "websocketpp.http";
341  }
342 
343  std::string message(int value) const {
344  switch(value) {
345  case error::general:
346  return "Generic http parser error";
347  case error::invalid_header_name:
348  return "The header name specified contains illegal characters";
349  case error::body_too_large:
350  return "The body value is larger than the configured maximum size";
351  default:
352  return "Unknown";
353  }
354  }
355 };
356 
357 /// Get a reference to a static copy of the asio transport error category
358 inline lib::error_category const & get_category() {
359  static category instance;
360  return instance;
361 }
362 
363 /// Create an error code with the given value and the asio transport category
365  return lib::error_code(static_cast<int>(e), get_category());
366 }
367 
368 } // namespace error
369 } // namespace http
370 } // namespace websocketpp
371 
372 _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_
373 template<> struct is_error_code_enum<websocketpp::transport::asio::error::value>
374 {
375  static bool const value = true;
376 };
377 _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_
378 
379 
380 
381 #endif // HTTP_CONSTANTS_HPP
websocketpp::http::max_body_size
size_t const max_body_size
Default Maximum size in bytes for HTTP message bodies.
Definition: constants.hpp:69
websocketpp::http::is_not_whitespace_char
bool is_not_whitespace_char(unsigned char c)
Is the character non-whitespace.
Definition: constants.hpp:117
websocketpp::http::status_code
HTTP Status codes.
Definition: constants.hpp:122
websocketpp::http::empty_header
static std::string const empty_header
Literal value of an empty header.
Definition: constants.hpp:63
websocketpp::http::header_delimiter
static char const header_delimiter[]
Literal value of the HTTP header delimiter.
Definition: constants.hpp:57
websocketpp::http::error::make_error_code
lib::error_code make_error_code(error::value e)
Create an error code with the given value and the asio transport category.
Definition: constants.hpp:364
websocketpp::http::error::invalid_header_name
@ invalid_header_name
The header name specified contains illegal characters.
Definition: constants.hpp:330
websocketpp::http::header_separator
static char const header_separator[]
Literal value of the HTTP header separator.
Definition: constants.hpp:60
websocketpp::http::error
HTTP parser errors.
Definition: constants.hpp:323
websocketpp::http::error::general
@ general
Definition: constants.hpp:327
websocketpp::http::parameter_list
std::vector< std::pair< std::string, attribute_list > > parameter_list
The type of an HTTP parameter list.
Definition: constants.hpp:54
websocketpp::versions_supported
static std::vector< int > const versions_supported(helper, helper+4)
Container that stores the list of protocol versions supported.
websocketpp::http::is_not_token_char
bool is_not_token_char(unsigned char c)
Is the character a non-token.
Definition: constants.hpp:104
websocketpp::http::istream_buffer
size_t const istream_buffer
Number of bytes to use for temporary istream read buffers.
Definition: constants.hpp:72
websocketpp::http
HTTP handling support.
Definition: constants.hpp:39
websocketpp::http::max_header_size
size_t const max_header_size
Maximum size in bytes before rejecting an HTTP header as too big.
Definition: constants.hpp:66
websocketpp::http::error::value
value
Definition: constants.hpp:324
websocketpp::http::error::body_too_large
@ body_too_large
The body value is larger than the configured maximum size.
Definition: constants.hpp:333
websocketpp::http::header_token
static char const header_token[]
invalid HTTP token characters
Definition: constants.hpp:79
websocketpp::http::attribute_list
std::map< std::string, std::string > attribute_list
The type of an HTTP attribute list.
Definition: constants.hpp:46
websocketpp::http::is_whitespace_char
bool is_whitespace_char(unsigned char c)
Is the character whitespace.
Definition: constants.hpp:112
websocketpp::http::error::get_category
lib::error_category const & get_category()
Get a reference to a static copy of the asio transport error category.
Definition: constants.hpp:358
websocketpp::http::status_code::get_string
std::string get_string(value code)
Given a status code value, return the default status message.
Definition: constants.hpp:187
websocketpp::http::status_code::value
value
Known values for HTTP Status codes.
Definition: constants.hpp:124
websocketpp::http::exception
An exception type specific to HTTP errors.
Definition: constants.hpp:298
websocketpp::http::is_token_char
bool is_token_char(unsigned char c)
Is the character a token.
Definition: constants.hpp:99