diff options
author | Mathias Stearn <mathias@10gen.com> | 2018-01-17 13:31:14 -0500 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2018-01-19 21:43:07 -0500 |
commit | 6d92ce0e7ec4e9a0cf31e9f9940a63b03968bb88 (patch) | |
tree | ee06bd3cd1d5f34b114c81bffb715e432fbe6880 /src/mongo/util | |
parent | 410d6cf705eafd46499e8b338be5103becd377ff (diff) | |
download | mongo-6d92ce0e7ec4e9a0cf31e9f9940a63b03968bb88.tar.gz |
SERVER-32674 Make SocketException not be a special type
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/net/message_port.cpp | 7 | ||||
-rw-r--r-- | src/mongo/util/net/sock.cpp | 16 | ||||
-rw-r--r-- | src/mongo/util/net/sock_test.cpp | 12 | ||||
-rw-r--r-- | src/mongo/util/net/socket_exception.cpp | 50 | ||||
-rw-r--r-- | src/mongo/util/net/socket_exception.h | 52 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 13 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.h | 8 |
7 files changed, 66 insertions, 92 deletions
diff --git a/src/mongo/util/net/message_port.cpp b/src/mongo/util/net/message_port.cpp index 17fb8a30497..504d61c8eeb 100644 --- a/src/mongo/util/net/message_port.cpp +++ b/src/mongo/util/net/message_port.cpp @@ -172,11 +172,8 @@ bool MessagingPort::recv(Message& m) { m.setData(std::move(buf)); return true; - } catch (const SocketException& e) { - logger::LogSeverity severity = _psock->getLogLevel(); - if (!e.shouldPrint()) - severity = severity.lessSevere(); - LOG(severity) << "SocketException: remote: " << remote() << " error: " << e; + } catch (const NetworkException& e) { + LOG(_psock->getLogLevel()) << "NetworkException: remote: " << remote() << " error: " << e; m.reset(); return false; } diff --git a/src/mongo/util/net/sock.cpp b/src/mongo/util/net/sock.cpp index 4b8665895ff..30e17d83e5f 100644 --- a/src/mongo/util/net/sock.cpp +++ b/src/mongo/util/net/sock.cpp @@ -403,9 +403,9 @@ SSLPeerInfo Socket::doSSLHandshake(const char* firstBytes, int len) { return SSLPeerInfo(); fassert(16506, _fd != INVALID_SOCKET); if (_sslConnection.get()) { - throw SocketException(SocketException::RECV_ERROR, - "Attempt to call SSL_accept on already secure Socket from " + - remoteString()); + throwSocketError(SocketErrorKind::RECV_ERROR, + "Attempt to call SSL_accept on already secure Socket from " + + remoteString()); } _sslConnection.reset(_sslManager->accept(this, firstBytes, len)); return _sslManager->parseAndValidatePeerCertificateDeprecated(_sslConnection.get(), ""); @@ -698,18 +698,18 @@ void Socket::handleSendError(int ret, const char* context) { if ((mongo_errno == EAGAIN || mongo_errno == EWOULDBLOCK) && _timeout != 0) { #endif LOG(_logLevel) << "Socket " << context << " send() timed out " << remoteString(); - throw SocketException(SocketException::SEND_TIMEOUT, remoteString()); + throwSocketError(SocketErrorKind::SEND_TIMEOUT, remoteString()); } else if (mongo_errno != EINTR) { LOG(_logLevel) << "Socket " << context << " send() " << errnoWithDescription(mongo_errno) << ' ' << remoteString(); - throw SocketException(SocketException::SEND_ERROR, remoteString()); + throwSocketError(SocketErrorKind::SEND_ERROR, remoteString()); } } void Socket::handleRecvError(int ret, int len) { if (ret == 0) { LOG(3) << "Socket recv() conn closed? " << remoteString(); - throw SocketException(SocketException::CLOSED, remoteString()); + throwSocketError(SocketErrorKind::CLOSED, remoteString()); } // ret < 0 @@ -732,11 +732,11 @@ void Socket::handleRecvError(int ret, int len) { #endif // this is a timeout LOG(_logLevel) << "Socket recv() timeout " << remoteString(); - throw SocketException(SocketException::RECV_TIMEOUT, remoteString()); + throwSocketError(SocketErrorKind::RECV_TIMEOUT, remoteString()); } LOG(_logLevel) << "Socket recv() " << errnoWithDescription(e) << " " << remoteString(); - throw SocketException(SocketException::RECV_ERROR, remoteString()); + throwSocketError(SocketErrorKind::RECV_ERROR, remoteString()); } void Socket::setTimeout(double secs) { diff --git a/src/mongo/util/net/sock_test.cpp b/src/mongo/util/net/sock_test.cpp index babd6bea6c5..ba82776935d 100644 --- a/src/mongo/util/net/sock_test.cpp +++ b/src/mongo/util/net/sock_test.cpp @@ -268,7 +268,7 @@ TEST_F(SocketFailPointTest, TestSend) { ASSERT_TRUE(tryRecv()); { const ScopedFailPointEnabler enabled(*_failPoint); - ASSERT_THROWS(trySend(), SocketException); + ASSERT_THROWS(trySend(), NetworkException); } // Channel should be working again ASSERT_TRUE(trySend()); @@ -280,7 +280,7 @@ TEST_F(SocketFailPointTest, TestSendVector) { ASSERT_TRUE(tryRecv()); { const ScopedFailPointEnabler enabled(*_failPoint); - ASSERT_THROWS(trySendVector(), SocketException); + ASSERT_THROWS(trySendVector(), NetworkException); } ASSERT_TRUE(trySendVector()); ASSERT_TRUE(tryRecv()); @@ -292,7 +292,7 @@ TEST_F(SocketFailPointTest, TestRecv) { { ASSERT_TRUE(trySend()); // data for recv const ScopedFailPointEnabler enabled(*_failPoint); - ASSERT_THROWS(tryRecv(), SocketException); + ASSERT_THROWS(tryRecv(), NetworkException); } ASSERT_TRUE(trySend()); // data for recv ASSERT_TRUE(tryRecv()); @@ -305,7 +305,7 @@ TEST_F(SocketFailPointTest, TestFailedSendsDontSend) { ASSERT_TRUE(trySend()); // queue 1 byte const ScopedFailPointEnabler enabled(*_failPoint); // Fail to queue another byte - ASSERT_THROWS(trySend(), SocketException); + ASSERT_THROWS(trySend(), NetworkException); } // Failed byte should not have been transmitted. ASSERT_EQUALS(size_t(1), countRecvable(2)); @@ -319,7 +319,7 @@ TEST_F(SocketFailPointTest, TestFailedVectorSendsDontSend) { ASSERT_TRUE(trySend()); // queue 1 byte const ScopedFailPointEnabler enabled(*_failPoint); // Fail to queue another byte - ASSERT_THROWS(trySendVector(), SocketException); + ASSERT_THROWS(trySendVector(), NetworkException); } // Failed byte should not have been transmitted. ASSERT_EQUALS(size_t(1), countRecvable(2)); @@ -332,7 +332,7 @@ TEST_F(SocketFailPointTest, TestFailedRecvsDontRecv) { ASSERT_TRUE(trySend()); const ScopedFailPointEnabler enabled(*_failPoint); // Fail to recv that byte - ASSERT_THROWS(tryRecv(), SocketException); + ASSERT_THROWS(tryRecv(), NetworkException); } // Failed byte should still be queued to recv. ASSERT_EQUALS(size_t(1), countRecvable(1)); diff --git a/src/mongo/util/net/socket_exception.cpp b/src/mongo/util/net/socket_exception.cpp index 1d96186874d..7b7d72e9c5f 100644 --- a/src/mongo/util/net/socket_exception.cpp +++ b/src/mongo/util/net/socket_exception.cpp @@ -36,21 +36,21 @@ namespace mongo { namespace { -std::string getStringType(SocketException::Type t) { - switch (t) { - case SocketException::Type::CLOSED: +std::string getStringType(SocketErrorKind kind) { + switch (kind) { + case SocketErrorKind::CLOSED: return "CLOSED"; - case SocketException::Type::RECV_ERROR: + case SocketErrorKind::RECV_ERROR: return "RECV_ERROR"; - case SocketException::Type::SEND_ERROR: + case SocketErrorKind::SEND_ERROR: return "SEND_ERROR"; - case SocketException::Type::RECV_TIMEOUT: + case SocketErrorKind::RECV_TIMEOUT: return "RECV_TIMEOUT"; - case SocketException::Type::SEND_TIMEOUT: + case SocketErrorKind::SEND_TIMEOUT: return "SEND_TIMEOUT"; - case SocketException::Type::FAILED_STATE: + case SocketErrorKind::FAILED_STATE: return "FAILED_STATE"; - case SocketException::Type::CONNECT_ERROR: + case SocketErrorKind::CONNECT_ERROR: return "CONNECT_ERROR"; default: return "UNKNOWN"; // should never happen @@ -59,32 +59,18 @@ std::string getStringType(SocketException::Type t) { } // namespace -SocketException::SocketException(Type t, - const std::string& server, - int code, - const std::string& extra) - : DBException(Status(ErrorCodes::Error(code), - std::string("socket exception [") + getStringType(t) + "] for " + server)), - _type(t), - _server(server), - _extra(extra) {} +Status makeSocketError(SocketErrorKind kind, const std::string& server, const std::string& extra) { + StringBuilder ss; + ss << "socket exception [" << getStringType(kind) << "]"; + if (!server.empty()) + ss << " server [" << server << "]"; -bool SocketException::shouldPrint() const { - return _type != CLOSED; -} - -std::string SocketException::toString() const { - std::stringstream ss; - ss << codeString() << " socket exception [" << getStringType(_type) << "] "; - - if (_server.size()) - ss << "server [" << _server << "] "; + if (!extra.empty()) + ss << ' ' << extra; - if (_extra.size()) - ss << _extra; - - return ss.str(); + return Status(ErrorCodes::SocketException, ss.str()); } + } // namespace mongo diff --git a/src/mongo/util/net/socket_exception.h b/src/mongo/util/net/socket_exception.h index e6e5ac25c2d..558975876ef 100644 --- a/src/mongo/util/net/socket_exception.h +++ b/src/mongo/util/net/socket_exception.h @@ -33,38 +33,30 @@ #include <string> namespace mongo { +enum class SocketErrorKind { + CLOSED, + RECV_ERROR, + SEND_ERROR, + RECV_TIMEOUT, + SEND_TIMEOUT, + FAILED_STATE, + CONNECT_ERROR +}; /** - * A special class of DBException thrown by Sockets. + * Returns a Status with ErrorCodes::SocketException with a correctly formed message. */ -class SocketException final : public DBException { -public: - const enum Type { - CLOSED, - RECV_ERROR, - SEND_ERROR, - RECV_TIMEOUT, - SEND_TIMEOUT, - FAILED_STATE, - CONNECT_ERROR - } _type; - - SocketException(Type t, - const std::string& server, - int code = ErrorCodes::SocketException, - const std::string& extra = ""); - - ~SocketException() throw() override {} - - bool shouldPrint() const; - - std::string toString() const override; - -private: - void defineOnlyInFinalSubclassToPreventSlicing() final {} - - std::string _server; - std::string _extra; -}; +Status makeSocketError(SocketErrorKind kind, + const std::string& server, + const std::string& extra = ""); + +// Using a macro to preserve file/line info from call site. +#define throwSocketError(...) \ + do { \ + uassertStatusOK(makeSocketError(__VA_ARGS__)); \ + MONGO_UNREACHABLE; \ + } while (false) + +using NetworkException = ExceptionForCat<ErrorCategory::NetworkError>; } // namespace mongo diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index c1c68e31926..5c5e3f7fc18 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -420,7 +420,7 @@ private: /** * Given an error code from an SSL-type IO function, logs an - * appropriate message and throws a SocketException. + * appropriate message and throws a NetworkException. */ MONGO_COMPILER_NORETURN void _handleSSLError(int code, int ret); @@ -587,7 +587,7 @@ SSLConnection::SSLConnection(SSL_CTX* context, Socket* sock, const char* initial int toBIO = BIO_write(networkBIO, initialBytes, len); if (toBIO != len) { LOG(3) << "Failed to write initial network data to the SSL BIO layer"; - throw SocketException(SocketException::RECV_ERROR, socket->remoteString()); + throwSocketError(SocketErrorKind::RECV_ERROR, socket->remoteString()); } } } @@ -1266,7 +1266,7 @@ void SSLManager::_flushNetworkBIO(SSLConnection* conn) { int toBIO = BIO_write(conn->networkBIO, buffer, numRead); if (toBIO != numRead) { LOG(3) << "Failed to write network data to the SSL BIO layer"; - throw SocketException(SocketException::RECV_ERROR, conn->socket->remoteString()); + throwSocketError(SocketErrorKind::RECV_ERROR, conn->socket->remoteString()); } } } @@ -1432,10 +1432,9 @@ StatusWith<boost::optional<SSLPeerInfo>> SSLManager::parseAndValidatePeerCertifi SSLPeerInfo SSLManager::parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn, const std::string& remoteHost) { auto swPeerSubjectName = parseAndValidatePeerCertificate(conn->ssl, remoteHost); - // We can't use uassertStatusOK here because we need to throw a SocketException. + // We can't use uassertStatusOK here because we need to throw a NetworkException. if (!swPeerSubjectName.isOK()) { - throw SocketException(SocketException::CONNECT_ERROR, - swPeerSubjectName.getStatus().reason()); + throwSocketError(SocketErrorKind::CONNECT_ERROR, swPeerSubjectName.getStatus().reason()); } return swPeerSubjectName.getValue().get_value_or(SSLPeerInfo()); } @@ -1607,7 +1606,7 @@ void SSLManager::_handleSSLError(int code, int ret) { error() << "unrecognized SSL error"; break; } - throw SocketException(SocketException::CONNECT_ERROR, ""); + throwSocketError(SocketErrorKind::CONNECT_ERROR, ""); } } // namespace mongo diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h index 002a0dd6be7..f1caf1f6d20 100644 --- a/src/mongo/util/net/ssl_manager.h +++ b/src/mongo/util/net/ssl_manager.h @@ -114,25 +114,25 @@ public: /** * Initiates a TLS connection. - * Throws SocketException on failure. + * Throws NetworkException on failure. * @return a pointer to an SSLConnection. Resources are freed in SSLConnection's destructor */ virtual SSLConnection* connect(Socket* socket) = 0; /** * Waits for the other side to initiate a TLS connection. - * Throws SocketException on failure. + * Throws NetworkException on failure. * @return a pointer to an SSLConnection. Resources are freed in SSLConnection's destructor */ virtual SSLConnection* accept(Socket* socket, const char* initialBytes, int len) = 0; /** * Fetches a peer certificate and validates it if it exists - * Throws SocketException on failure + * Throws NetworkException on failure * @return a std::string containing the certificate's subject name. * * This version of parseAndValidatePeerCertificate is deprecated because it throws a - * SocketException upon failure. New code should prefer the version that returns + * NetworkException upon failure. New code should prefer the version that returns * a StatusWith instead. */ virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated( |