Add AsyncSocketExceptionType for early data rejection.
[folly.git] / folly / io / async / AsyncSocketException.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <stdexcept>
20
21 #include <folly/Format.h>
22 #include <folly/io/async/DelayedDestruction.h>
23
24 namespace folly {
25
26 class AsyncSocketException : public std::runtime_error {
27  public:
28   enum AsyncSocketExceptionType {
29     UNKNOWN = 0,
30     NOT_OPEN = 1,
31     ALREADY_OPEN = 2,
32     TIMED_OUT = 3,
33     END_OF_FILE = 4,
34     INTERRUPTED = 5,
35     BAD_ARGS = 6,
36     CORRUPTED_DATA = 7,
37     INTERNAL_ERROR = 8,
38     NOT_SUPPORTED = 9,
39     INVALID_STATE = 10,
40     SSL_ERROR = 12,
41     COULD_NOT_BIND = 13,
42     SASL_HANDSHAKE_TIMEOUT = 14,
43     NETWORK_ERROR = 15,
44     EARLY_DATA_REJECTED = 16,
45   };
46
47   AsyncSocketException(AsyncSocketExceptionType type,
48                        const std::string& message,
49                        int errno_copy = 0)
50       : std::runtime_error(
51             AsyncSocketException::getMessage(type, message, errno_copy)),
52         type_(type),
53         errno_(errno_copy) {}
54
55   /** Error code */
56   AsyncSocketExceptionType type_;
57
58   /** A copy of the errno. */
59   int errno_;
60
61   AsyncSocketExceptionType getType() const noexcept { return type_; }
62   int getErrno() const noexcept { return errno_; }
63
64  protected:
65   /** Just like strerror_r but returns a C++ string object. */
66   static std::string strerror_s(int errno_copy) {
67     return folly::sformat("errno = {} ({})", errno_copy, strerror(errno_copy));
68   }
69
70   /** get the string of exception type */
71   static folly::StringPiece getExceptionTypeString(
72       AsyncSocketExceptionType type) {
73     switch (type) {
74       case UNKNOWN:
75         return "Unknown async socket exception";
76       case NOT_OPEN:
77         return "Socket not open";
78       case ALREADY_OPEN:
79         return "Socket already open";
80       case TIMED_OUT:
81         return "Timed out";
82       case END_OF_FILE:
83         return "End of file";
84       case INTERRUPTED:
85         return "Interrupted";
86       case BAD_ARGS:
87         return "Invalid arguments";
88       case CORRUPTED_DATA:
89         return "Corrupted Data";
90       case INTERNAL_ERROR:
91         return "Internal error";
92       case NOT_SUPPORTED:
93         return "Not supported";
94       case INVALID_STATE:
95         return "Invalid state";
96       case SSL_ERROR:
97         return "SSL error";
98       case COULD_NOT_BIND:
99         return "Could not bind";
100       case SASL_HANDSHAKE_TIMEOUT:
101         return "SASL handshake timeout";
102       case NETWORK_ERROR:
103         return "Network error";
104       case EARLY_DATA_REJECTED:
105         return "Early data rejected";
106       default:
107         return "(Invalid exception type)";
108     }
109   }
110
111   /** Return a message based on the input. */
112   static std::string getMessage(AsyncSocketExceptionType type,
113                                 const std::string& message,
114                                 int errno_copy) {
115     if (errno_copy != 0) {
116       return folly::sformat(
117           "AsyncSocketException: {}, type = {}, errno = {} ({})",
118           message,
119           AsyncSocketException::getExceptionTypeString(type),
120           errno_copy,
121           strerror(errno_copy));
122     } else {
123       return folly::sformat("AsyncSocketException: {}, type = {}",
124                             message,
125                             AsyncSocketException::getExceptionTypeString(type));
126     }
127   }
128 };
129
130 } // namespace folly