rfc6455.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_WEBSOCKET_RFC6455_HPP
  10. #define BOOST_BEAST_WEBSOCKET_RFC6455_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/static_string.hpp>
  13. #include <boost/beast/core/string.hpp>
  14. #include <boost/beast/http/empty_body.hpp>
  15. #include <boost/beast/http/message.hpp>
  16. #include <boost/beast/http/string_body.hpp>
  17. #include <array>
  18. #include <cstdint>
  19. namespace boost {
  20. namespace beast {
  21. namespace websocket {
  22. /// The type of object holding HTTP Upgrade requests
  23. using request_type = http::request<http::empty_body>;
  24. /// The type of object holding HTTP Upgrade responses
  25. using response_type = http::response<http::string_body>;
  26. /** Returns `true` if the specified HTTP request is a WebSocket Upgrade.
  27. This function returns `true` when the passed HTTP Request
  28. indicates a WebSocket Upgrade. It does not validate the
  29. contents of the fields: it just trivially accepts requests
  30. which could only possibly be a valid or invalid WebSocket
  31. Upgrade message.
  32. Callers who wish to manually read HTTP requests in their
  33. server implementation can use this function to determine if
  34. the request should be routed to an instance of
  35. @ref websocket::stream.
  36. @par Example
  37. @code
  38. void handle_connection(net::ip::tcp::socket& sock)
  39. {
  40. boost::beast::flat_buffer buffer;
  41. boost::beast::http::request<boost::beast::http::string_body> req;
  42. boost::beast::http::read(sock, buffer, req);
  43. if(boost::beast::websocket::is_upgrade(req))
  44. {
  45. boost::beast::websocket::stream<decltype(sock)> ws{std::move(sock)};
  46. ws.accept(req);
  47. }
  48. }
  49. @endcode
  50. @param req The HTTP Request object to check.
  51. @return `true` if the request is a WebSocket Upgrade.
  52. */
  53. template<class Allocator>
  54. bool
  55. is_upgrade(beast::http::header<true,
  56. http::basic_fields<Allocator>> const& req);
  57. /** Close status codes.
  58. These codes accompany close frames.
  59. @see <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455 7.4.1 Defined Status Codes</a>
  60. */
  61. enum close_code : std::uint16_t
  62. {
  63. /// Normal closure; the connection successfully completed whatever purpose for which it was created.
  64. normal = 1000,
  65. /// The endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.
  66. going_away = 1001,
  67. /// The endpoint is terminating the connection due to a protocol error.
  68. protocol_error = 1002,
  69. /// The connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).
  70. unknown_data = 1003,
  71. /// The endpoint is terminating the connection because a message was received that contained inconsistent data (e.g., non-UTF-8 data within a text message).
  72. bad_payload = 1007,
  73. /// The endpoint is terminating the connection because it received a message that violates its policy. This is a generic status code, used when codes 1003 and 1009 are not suitable.
  74. policy_error = 1008,
  75. /// The endpoint is terminating the connection because a data frame was received that is too large.
  76. too_big = 1009,
  77. /// The client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn't.
  78. needs_extension = 1010,
  79. /// The server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
  80. internal_error = 1011,
  81. /// The server is terminating the connection because it is restarting.
  82. service_restart = 1012,
  83. /// The server is terminating the connection due to a temporary condition, e.g. it is overloaded and is casting off some of its clients.
  84. try_again_later = 1013,
  85. //----
  86. //
  87. // The following are illegal on the wire
  88. //
  89. /** Used internally to mean "no error"
  90. This code is reserved and may not be sent.
  91. */
  92. none = 0,
  93. /** Reserved for future use by the WebSocket standard.
  94. This code is reserved and may not be sent.
  95. */
  96. reserved1 = 1004,
  97. /** No status code was provided even though one was expected.
  98. This code is reserved and may not be sent.
  99. */
  100. no_status = 1005,
  101. /** Connection was closed without receiving a close frame
  102. This code is reserved and may not be sent.
  103. */
  104. abnormal = 1006,
  105. /** Reserved for future use by the WebSocket standard.
  106. This code is reserved and may not be sent.
  107. */
  108. reserved2 = 1014,
  109. /** Reserved for future use by the WebSocket standard.
  110. This code is reserved and may not be sent.
  111. */
  112. reserved3 = 1015
  113. //
  114. //----
  115. //last = 5000 // satisfy warnings
  116. };
  117. /// The type representing the reason string in a close frame.
  118. using reason_string = static_string<123, char>;
  119. /// The type representing the payload of ping and pong messages.
  120. using ping_data = static_string<125, char>;
  121. /** Description of the close reason.
  122. This object stores the close code (if any) and the optional
  123. utf-8 encoded implementation defined reason string.
  124. */
  125. struct close_reason
  126. {
  127. /// The close code.
  128. std::uint16_t code = close_code::none;
  129. /// The optional utf8-encoded reason string.
  130. reason_string reason;
  131. /** Default constructor.
  132. The code will be none. Default constructed objects
  133. will explicitly convert to bool as `false`.
  134. */
  135. close_reason() = default;
  136. /// Construct from a code.
  137. close_reason(std::uint16_t code_)
  138. : code(code_)
  139. {
  140. }
  141. /// Construct from a reason string. code is @ref close_code::normal.
  142. close_reason(string_view s)
  143. : code(close_code::normal)
  144. , reason(s.data(), s.size())
  145. {
  146. }
  147. /// Construct from a reason string literal. code is @ref close_code::normal.
  148. close_reason(char const* s)
  149. : code(close_code::normal)
  150. , reason(s)
  151. {
  152. }
  153. /// Construct from a close code and reason string.
  154. close_reason(close_code code_, string_view s)
  155. : code(code_)
  156. , reason(s.data(), s.size())
  157. {
  158. }
  159. /// Returns `true` if a code was specified
  160. operator bool() const
  161. {
  162. return code != close_code::none;
  163. }
  164. };
  165. } // websocket
  166. } // beast
  167. } // boost
  168. #include <boost/beast/websocket/impl/rfc6455.hpp>
  169. #endif