Skip to content

Commit

Permalink
SERVER-8864 Use BIO pairs for socket decoupled SSL network interface
Browse files Browse the repository at this point in the history
  • Loading branch information
agralius committed Sep 2, 2013
1 parent 804f5db commit 9ca2fb0
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 177 deletions.
3 changes: 2 additions & 1 deletion src/mongo/client/dbclient.cpp
Expand Up @@ -570,7 +570,8 @@ namespace mongo {
&user));

uassert(ErrorCodes::AuthenticationFailed,
"Username does not match the provided client certificate",
"Username \"" + user + "\" does not match the provided client certificate user \"" +
getSSLManager()->getClientSubjectName() + "\"",
user == getSSLManager()->getClientSubjectName());

std::string errmsg;
Expand Down
81 changes: 29 additions & 52 deletions src/mongo/util/net/sock.cpp
Expand Up @@ -423,10 +423,8 @@ namespace mongo {
Socket::~Socket() {
close();
#ifdef MONGO_SSL
if ( _ssl ) {
_sslManager->SSL_shutdown( _ssl );
_sslManager->SSL_free( _ssl );
_ssl = 0;
if (_sslConnection.get()) {
_sslManager->SSL_shutdown( _sslConnection.get() );
}
#endif
}
Expand All @@ -435,7 +433,6 @@ namespace mongo {
_bytesOut = 0;
_bytesIn = 0;
#ifdef MONGO_SSL
_ssl = 0;
_sslManager = 0;
#endif
}
Expand All @@ -456,11 +453,10 @@ namespace mongo {
#ifdef MONGO_SSL
void Socket::secure(SSLManagerInterface* mgr) {
fassert(16503, mgr);
fassert(16504, !_ssl);
fassert(16505, _fd >= 0);
_sslManager = mgr;
_ssl = _sslManager->connect(_fd);
mgr->validatePeerCertificate(_ssl);
_sslConnection.reset(_sslManager->connect(this));
mgr->validatePeerCertificate(_sslConnection.get());
}

void Socket::secureAccepted( SSLManagerInterface* ssl ) {
Expand All @@ -470,8 +466,8 @@ namespace mongo {
std::string Socket::doSSLHandshake() {
if (!_sslManager) return "";
fassert(16506, _fd);
_ssl = _sslManager->accept(_fd);
return _sslManager->validatePeerCertificate(_ssl);
_sslConnection.reset(_sslManager->accept(this));
return _sslManager->validatePeerCertificate(_sslConnection.get());
}
#endif

Expand Down Expand Up @@ -532,13 +528,18 @@ namespace mongo {
return true;
}

int Socket::_send( const char * data , int len ) {
// throws if SSL_write or send fails
int Socket::_send( const char * data , int len, const char * context ) {
#ifdef MONGO_SSL
if ( _ssl ) {
return _sslManager->SSL_write( _ssl , data , len );
if ( _sslConnection.get() ) {
return _sslManager->SSL_write( _sslConnection.get() , data , len );
}
#endif
return ::send( _fd , data , len , portSendFlags );
int ret = ::send( _fd , data , len , portSendFlags );
if (ret < 0) {
handleSendError(ret, context);
}
return ret;
}

// sends all data or throws an exception
Expand All @@ -553,12 +554,9 @@ namespace mongo {
#endif
}
else {
ret = _send(data, len);
ret = _send(data, len, context);
}

if (ret == -1)
_handleSendError(ret, context);

_bytesOut += ret;

fassert(16507, ret <= len);
Expand All @@ -584,7 +582,7 @@ namespace mongo {
void Socket::send( const vector< pair< char *, int > > &data, const char *context ) {

#ifdef MONGO_SSL
if ( _ssl ) {
if ( _sslConnection.get() ) {
_send( data , context );
return;
}
Expand Down Expand Up @@ -656,7 +654,6 @@ namespace mongo {
}

void Socket::recv( char * buf , int len ) {
int retries = 0;
while( len > 0 ) {
int ret = -1;
if (MONGO_FAIL_POINT(throwSockExcep)) {
Expand All @@ -669,10 +666,6 @@ namespace mongo {
else {
ret = unsafe_recv(buf, len);
}
if (ret <= 0) {
_handleRecvError(ret, len, &retries);
continue;
}

if ( len <= 4 && ret != len ) {
LOG(_logLevel) << "Socket recv() got " << ret <<
Expand All @@ -690,27 +683,22 @@ namespace mongo {
return x;
}


// throws if SSL_read fails or recv returns an error
int Socket::_recv( char *buf, int max ) {
#ifdef MONGO_SSL
if ( _ssl ){
return _sslManager->SSL_read( _ssl , buf , max );
if ( _sslConnection.get() ){
return _sslManager->SSL_read( _sslConnection.get() , buf , max );
}
#endif
return ::recv( _fd , buf , max , portRecvFlags );
int ret = ::recv( _fd , buf , max , portRecvFlags );
if (ret <= 0) {
handleRecvError(ret, max); // If no throw return and call _recv again
return 0;
}
return ret;
}

void Socket::_handleSendError(int ret, const char* context) {
#ifdef MONGO_SSL
if (_ssl) {
LOG(_logLevel) << "SSL Error ret: " << ret
<< " err: " << _sslManager->SSL_get_error(_ssl , ret)
<< " "
<< _sslManager->ERR_error_string(_sslManager->ERR_get_error(), NULL)
<< endl;
throw SocketException(SocketException::SEND_ERROR , remoteString());
}
#endif
void Socket::handleSendError(int ret, const char* context) {

#if defined(_WIN32)
const int mongo_errno = WSAGetLastError();
Expand All @@ -730,31 +718,20 @@ namespace mongo {
}
}

void Socket::_handleRecvError(int ret, int len, int* retries) {
void Socket::handleRecvError(int ret, int len) {
if (ret == 0) {
LOG(3) << "Socket recv() conn closed? " << remoteString() << endl;
throw SocketException(SocketException::CLOSED , remoteString());
}

// ret < 0
#ifdef MONGO_SSL
if (_ssl) {
LOG(_logLevel) << "SSL Error ret when receiving: " << ret
<< " err: " << _sslManager->SSL_get_error(_ssl , ret)
<< " "
<< _sslManager->ERR_error_string(_sslManager->ERR_get_error(), NULL)
<< endl;
throw SocketException(SocketException::RECV_ERROR, remoteString());
}
#endif

#if defined(_WIN32)
int e = WSAGetLastError();
#else
int e = errno;
# if defined(EINTR)
if (e == EINTR) {
LOG(_logLevel) << "EINTR retry " << ++*retries << endl;
LOG(_logLevel) << "EINTR returned from recv(), retrying";
return;
}
# endif
Expand Down
26 changes: 15 additions & 11 deletions src/mongo/util/net/sock.h
Expand Up @@ -33,10 +33,7 @@

#endif // not _WIN32

#ifdef MONGO_SSL
#include <openssl/ssl.h>
#endif

#include <boost/scoped_ptr.hpp>
#include <string>
#include <utility>
#include <vector>
Expand All @@ -49,7 +46,13 @@

namespace mongo {

#ifdef MONGO_SSL
class SSLManagerInterface;
class SSLConnection;
#endif

extern const int portSendFlags;
extern const int portRecvFlags;

const int SOCK_FAMILY_UNKNOWN_ERROR=13078;

Expand Down Expand Up @@ -221,7 +224,8 @@ namespace mongo {
void clearCounters() { _bytesIn = 0; _bytesOut = 0; }
long long getBytesIn() const { return _bytesIn; }
long long getBytesOut() const { return _bytesOut; }

int rawFD() const { return _fd; }

void setTimeout( double secs );
bool isStillConnected();

Expand All @@ -248,21 +252,21 @@ namespace mongo {
return _fdCreationMicroSec;
}

void handleRecvError(int ret, int len);
MONGO_COMPILER_NORETURN void handleSendError(int ret, const char* context);

private:
void _init();

/** sends dumbly, just each buffer at a time */
void _send( const std::vector< std::pair< char *, int > > &data, const char *context );

/** raw send, same semantics as ::send */
int _send( const char * data , int len );
/** raw send, same semantics as ::send with an additional context parameter */
int _send( const char * data , int len , const char * context );

/** raw recv, same semantics as ::recv */
int _recv( char * buf , int max );

void _handleRecvError(int ret, int len, int* retries);
MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context);

int _fd;
uint64_t _fdCreationMicroSec;
SockAddr _local;
Expand All @@ -274,7 +278,7 @@ namespace mongo {
time_t _lastValidityCheckAtSecs;

#ifdef MONGO_SSL
SSL* _ssl;
boost::scoped_ptr<SSLConnection> _sslConnection;
SSLManagerInterface* _sslManager;
#endif
logger::LogSeverity _logLevel; // passed to log() when logging errors
Expand Down

0 comments on commit 9ca2fb0

Please sign in to comment.