class AsyncSocketException : public std::runtime_error {
public:
- enum AsyncSocketExceptionType
- { UNKNOWN = 0
- , NOT_OPEN = 1
- , ALREADY_OPEN = 2
- , TIMED_OUT = 3
- , END_OF_FILE = 4
- , INTERRUPTED = 5
- , BAD_ARGS = 6
- , CORRUPTED_DATA = 7
- , INTERNAL_ERROR = 8
- , NOT_SUPPORTED = 9
- , INVALID_STATE = 10
- , SSL_ERROR = 12
- , COULD_NOT_BIND = 13
- , SASL_HANDSHAKE_TIMEOUT = 14
+ enum AsyncSocketExceptionType {
+ UNKNOWN = 0,
+ NOT_OPEN = 1,
+ ALREADY_OPEN = 2,
+ TIMED_OUT = 3,
+ END_OF_FILE = 4,
+ INTERRUPTED = 5,
+ BAD_ARGS = 6,
+ CORRUPTED_DATA = 7,
+ INTERNAL_ERROR = 8,
+ NOT_SUPPORTED = 9,
+ INVALID_STATE = 10,
+ SSL_ERROR = 12,
+ COULD_NOT_BIND = 13,
+ SASL_HANDSHAKE_TIMEOUT = 14,
+ NETWORK_ERROR = 15
};
AsyncSocketException(AsyncSocketExceptionType type,
}
return ret;
}
+
+AsyncSocketException::AsyncSocketExceptionType exTypefromSSLErrInfo(
+ int sslErr,
+ unsigned long errError,
+ int sslOperationReturnValue) {
+ if (sslErr == SSL_ERROR_ZERO_RETURN) {
+ return AsyncSocketException::END_OF_FILE;
+ } else if (sslErr == SSL_ERROR_SYSCALL) {
+ if (errError == 0 && sslOperationReturnValue == 0) {
+ return AsyncSocketException::END_OF_FILE;
+ } else {
+ return AsyncSocketException::NETWORK_ERROR;
+ }
+ } else {
+ // Assume an actual SSL error
+ return AsyncSocketException::SSL_ERROR;
+ }
+}
+
+AsyncSocketException::AsyncSocketExceptionType exTypefromSSLErr(SSLError err) {
+ switch (err) {
+ case SSLError::EOF_ERROR:
+ return AsyncSocketException::END_OF_FILE;
+ case SSLError::NETWORK_ERROR:
+ return AsyncSocketException::NETWORK_ERROR;
+ default:
+ // everything else is a SSL_ERROR
+ return AsyncSocketException::SSL_ERROR;
+ }
+}
}
namespace folly {
int sslOperationReturnValue,
int errno_copy)
: AsyncSocketException(
- AsyncSocketException::SSL_ERROR,
+ exTypefromSSLErrInfo(sslErr, errError, sslOperationReturnValue),
decodeOpenSSLError(sslErr, errError, sslOperationReturnValue),
sslErr == SSL_ERROR_SYSCALL ? errno_copy : 0) {
if (sslErr == SSL_ERROR_ZERO_RETURN) {
SSLException::SSLException(SSLError error)
: AsyncSocketException(
- AsyncSocketException::SSL_ERROR,
+ exTypefromSSLErr(error),
getSSLErrorString(error).str(),
0),
sslError(error) {}
explicit SSLException(SSLError error);
- SSLError getType() const {
+ SSLError getSSLError() const {
return sslError;
}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <gtest/gtest.h>
+#include <array>
+
#include <folly/io/async/AsyncSocketException.h>
+#include <folly/io/async/ssl/SSLErrors.h>
+#include <gtest/gtest.h>
+#include <openssl/ssl.h>
using namespace testing;
std::string(ex2.what()));
}
+TEST(AsyncSocketException, SSLExceptionType) {
+ {
+ SSLException eof(SSL_ERROR_ZERO_RETURN, 0, 0, 0);
+ EXPECT_EQ(eof.getType(), AsyncSocketException::END_OF_FILE);
+
+ SSLException netEof(SSL_ERROR_SYSCALL, 0, 0, 0);
+ EXPECT_EQ(netEof.getType(), AsyncSocketException::END_OF_FILE);
+
+ SSLException netOther(SSL_ERROR_SYSCALL, 0, 1, 0);
+ EXPECT_EQ(netOther.getType(), AsyncSocketException::NETWORK_ERROR);
+
+ std::array<int, 6> sslErrs{{SSL_ERROR_SSL,
+ SSL_ERROR_WANT_READ,
+ SSL_ERROR_WANT_WRITE,
+ SSL_ERROR_WANT_X509_LOOKUP,
+ SSL_ERROR_WANT_CONNECT,
+ SSL_ERROR_WANT_ACCEPT}};
+
+ for (auto& e : sslErrs) {
+ SSLException sslEx(e, 0, 0, 0);
+ EXPECT_EQ(sslEx.getType(), AsyncSocketException::SSL_ERROR);
+ }
+ }
+
+ {
+ SSLException eof(SSLError::EOF_ERROR);
+ EXPECT_EQ(eof.getType(), AsyncSocketException::END_OF_FILE);
+
+ SSLException net(SSLError::NETWORK_ERROR);
+ EXPECT_EQ(net.getType(), AsyncSocketException::NETWORK_ERROR);
+
+ std::array<SSLError, 4> errs{{SSLError::CLIENT_RENEGOTIATION,
+ SSLError::INVALID_RENEGOTIATION,
+ SSLError::EARLY_WRITE,
+ SSLError::SSL_ERROR}};
+
+ for (auto& e : errs) {
+ SSLException sslEx(e);
+ EXPECT_EQ(sslEx.getType(), AsyncSocketException::SSL_ERROR);
+ }
+ }
+}
+
} // namespace folly