summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2018-01-17 13:31:14 -0500
committerMathias Stearn <mathias@10gen.com>2018-01-19 21:43:07 -0500
commit6d92ce0e7ec4e9a0cf31e9f9940a63b03968bb88 (patch)
treeee06bd3cd1d5f34b114c81bffb715e432fbe6880 /src/mongo/util
parent410d6cf705eafd46499e8b338be5103becd377ff (diff)
downloadmongo-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.cpp7
-rw-r--r--src/mongo/util/net/sock.cpp16
-rw-r--r--src/mongo/util/net/sock_test.cpp12
-rw-r--r--src/mongo/util/net/socket_exception.cpp50
-rw-r--r--src/mongo/util/net/socket_exception.h52
-rw-r--r--src/mongo/util/net/ssl_manager.cpp13
-rw-r--r--src/mongo/util/net/ssl_manager.h8
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(