Merge
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / websocketpp-0.7.0 / websocketpp / close.hpp
1
2 /*
3  * Copyright (c) 2014, Peter Thorson. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the WebSocket++ Project nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28
29 #ifndef WEBSOCKETPP_CLOSE_HPP
30 #define WEBSOCKETPP_CLOSE_HPP
31
32 /** \file
33  * A package of types and methods for manipulating WebSocket close codes.
34  */
35
36 #include <websocketpp/error.hpp>
37 #include <websocketpp/common/network.hpp>
38 #include <websocketpp/common/stdint.hpp>
39 #include <websocketpp/utf8_validator.hpp>
40
41 #include <string>
42
43 namespace websocketpp {
44 /// A package of types and methods for manipulating WebSocket close codes.
45 namespace close {
46 /// A package of types and methods for manipulating WebSocket close status'
47 namespace status {
48     /// The type of a close code value.
49     typedef uint16_t value;
50
51     /// A blank value for internal use.
52     static value const blank = 0;
53
54     /// Close the connection without a WebSocket close handshake.
55     /**
56      * This special value requests that the WebSocket connection be closed
57      * without performing the WebSocket closing handshake. This does not comply
58      * with RFC6455, but should be safe to do if necessary. This could be useful
59      * for clients that need to disconnect quickly and cannot afford the
60      * complete handshake.
61      */
62     static value const omit_handshake = 1;
63
64     /// Close the connection with a forced TCP drop.
65     /**
66      * This special value requests that the WebSocket connection be closed by
67      * forcibly dropping the TCP connection. This will leave the other side of
68      * the connection with a broken connection and some expensive timeouts. this
69      * should not be done except in extreme cases or in cases of malicious
70      * remote endpoints.
71      */
72     static value const force_tcp_drop = 2;
73
74     /// Normal closure, meaning that the purpose for which the connection was
75     /// established has been fulfilled.
76     static value const normal = 1000;
77
78     /// The endpoint was "going away", such as a server going down or a browser
79     /// navigating away from a page.
80     static value const going_away = 1001;
81
82     /// A protocol error occurred.
83     static value const protocol_error = 1002;
84
85     /// The connection was terminated because an endpoint received a type of
86     /// data it cannot accept.
87     /**
88      * (e.g., an endpoint that understands only text data MAY send this if it
89      * receives a binary message).
90      */
91     static value const unsupported_data = 1003;
92
93     /// A dummy value to indicate that no status code was received.
94     /**
95      * This value is illegal on the wire.
96      */
97     static value const no_status = 1005;
98
99     /// A dummy value to indicate that the connection was closed abnormally.
100     /**
101      * In such a case there was no close frame to extract a value from. This
102      * value is illegal on the wire.
103      */
104     static value const abnormal_close = 1006;
105
106     /// An endpoint received message data inconsistent with its type.
107     /**
108      * For example: Invalid UTF8 bytes in a text message.
109      */
110     static value const invalid_payload = 1007;
111
112     /// An endpoint received a message that violated its policy.
113     /**
114      * This is a generic status code that can be returned when there is no other
115      * more suitable status code (e.g., 1003 or 1009) or if there is a need to
116      * hide specific details about the policy.
117      */
118     static value const policy_violation = 1008;
119
120     /// An endpoint received a message too large to process.
121     static value const message_too_big = 1009;
122
123     /// A client expected the server to accept a required extension request
124     /**
125      * The list of extensions that are needed SHOULD appear in the /reason/ part
126      * of the Close frame. Note that this status code is not used by the server,
127      * because it can fail the WebSocket handshake instead.
128      */
129     static value const extension_required = 1010;
130
131     /// An endpoint encountered an unexpected condition that prevented it from
132     /// fulfilling the request.
133     static value const internal_endpoint_error = 1011;
134
135     /// Indicates that the service is restarted. A client may reconnect and if
136     /// if it chooses to do so, should reconnect using a randomized delay of
137     /// 5-30s
138     static value const service_restart = 1012;
139
140     /// Indicates that the service is experiencing overload. A client should
141     /// only connect to a different IP (when there are multiple for the target)
142     /// or reconnect to the same IP upon user action.
143     static value const try_again_later = 1013;
144
145     /// An endpoint failed to perform a TLS handshake
146     /**
147      * Designated for use in applications expecting a status code to indicate
148      * that the connection was closed due to a failure to perform a TLS
149      * handshake (e.g., the server certificate can't be verified). This value is
150      * illegal on the wire.
151      */
152     static value const tls_handshake = 1015;
153     
154     /// A generic subprotocol error
155     /**
156      * Indicates that a subprotocol error occurred. Typically this involves
157      * receiving a message that is not formatted as a valid message for the
158      * subprotocol in use.
159      */
160     static value const subprotocol_error = 3000;
161     
162     /// A invalid subprotocol data
163     /**
164      * Indicates that data was received that violated the specification of the
165      * subprotocol in use.
166      */
167     static value const invalid_subprotocol_data = 3001;
168
169     /// First value in range reserved for future protocol use
170     static value const rsv_start = 1016;
171     /// Last value in range reserved for future protocol use
172     static value const rsv_end = 2999;
173
174     /// Test whether a close code is in a reserved range
175     /**
176      * @param [in] code The code to test
177      * @return Whether or not code is reserved
178      */
179     inline bool reserved(value code) {
180         return ((code >= rsv_start && code <= rsv_end) ||
181                 code == 1004 || code == 1014);
182     }
183
184     /// First value in range that is always invalid on the wire
185     static value const invalid_low = 999;
186     /// Last value in range that is always invalid on the wire
187     static value const invalid_high = 5000;
188
189     /// Test whether a close code is invalid on the wire
190     /**
191      * @param [in] code The code to test
192      * @return Whether or not code is invalid on the wire
193      */
194     inline bool invalid(value code) {
195         return (code <= invalid_low || code >= invalid_high ||
196                 code == no_status || code == abnormal_close ||
197                 code == tls_handshake);
198     }
199
200     /// Determine if the code represents an unrecoverable error
201     /**
202      * There is a class of errors for which once they are discovered normal
203      * WebSocket functionality can no longer occur. This function determines
204      * if a given code is one of these values. This information is used to
205      * determine if the system has the capability of waiting for a close
206      * acknowledgement or if it should drop the TCP connection immediately
207      * after sending its close frame.
208      *
209      * @param [in] code The value to test.
210      * @return True if the code represents an unrecoverable error
211      */
212     inline bool terminal(value code) {
213         return (code == protocol_error || code == invalid_payload ||
214                 code == policy_violation || code == message_too_big ||
215                  code == internal_endpoint_error);
216     }
217     
218     /// Return a human readable interpretation of a WebSocket close code
219     /**
220      * See https://tools.ietf.org/html/rfc6455#section-7.4 for more details.
221      *
222      * @since 0.3.0
223      *
224      * @param [in] code The code to look up.
225      * @return A human readable interpretation of the code.
226      */
227     inline std::string get_string(value code) {
228         switch (code) {
229             case normal:
230                 return "Normal close";
231             case going_away:
232                 return "Going away";
233             case protocol_error:
234                 return "Protocol error";
235             case unsupported_data:
236                 return "Unsupported data";
237             case no_status:
238                 return "No status set";
239             case abnormal_close:
240                 return "Abnormal close";
241             case invalid_payload:
242                 return "Invalid payload";
243             case policy_violation:
244                 return "Policy violoation";
245             case message_too_big:
246                 return "Message too big";
247             case extension_required:
248                 return "Extension required";
249             case internal_endpoint_error:
250                 return "Internal endpoint error";
251             case tls_handshake:
252                 return "TLS handshake failure";
253             case subprotocol_error:
254                 return "Generic subprotocol error";
255             case invalid_subprotocol_data:
256                 return "Invalid subprotocol data";
257             default:
258                 return "Unknown";
259         }
260     }
261 } // namespace status
262
263 /// Type used to convert close statuses between integer and wire representations
264 union code_converter {
265     uint16_t i;
266     char c[2];
267 };
268
269 /// Extract a close code value from a close payload
270 /**
271  * If there is no close value (ie string is empty) status::no_status is
272  * returned. If a code couldn't be extracted (usually do to a short or
273  * otherwise mangled payload) status::protocol_error is returned and the ec
274  * value is flagged as an error. Note that this case is different than the case
275  * where protocol error is received over the wire.
276  *
277  * If the value is in an invalid or reserved range ec is set accordingly.
278  *
279  * @param [in] payload Close frame payload value received over the wire.
280  * @param [out] ec Set to indicate what error occurred, if any.
281  * @return The extracted value
282  */
283 inline status::value extract_code(std::string const & payload, lib::error_code
284     & ec)
285 {
286     ec = lib::error_code();
287
288     if (payload.size() == 0) {
289         return status::no_status;
290     } else if (payload.size() == 1) {
291         ec = make_error_code(error::bad_close_code);
292         return status::protocol_error;
293     }
294
295     code_converter val;
296
297     val.c[0] = payload[0];
298     val.c[1] = payload[1];
299
300     status::value code(ntohs(val.i));
301
302     if (status::invalid(code)) {
303         ec = make_error_code(error::invalid_close_code);
304     }
305
306     if (status::reserved(code)) {
307         ec = make_error_code(error::reserved_close_code);
308     }
309
310     return code;
311 }
312
313 /// Extract the reason string from a close payload
314 /**
315  * The string should be a valid UTF8 message. error::invalid_utf8 will be set if
316  * the function extracts a reason that is not valid UTF8.
317  *
318  * @param [in] payload The payload string to extract a reason from.
319  * @param [out] ec Set to indicate what error occurred, if any.
320  * @return The reason string.
321  */
322 inline std::string extract_reason(std::string const & payload, lib::error_code
323     & ec)
324 {
325     std::string reason;
326     ec = lib::error_code();
327
328     if (payload.size() > 2) {
329         reason.append(payload.begin()+2,payload.end());
330     }
331
332     if (!websocketpp::utf8_validator::validate(reason)) {
333         ec = make_error_code(error::invalid_utf8);
334     }
335
336     return reason;
337 }
338
339 } // namespace close
340 } // namespace websocketpp
341
342 #endif // WEBSOCKETPP_CLOSE_HPP