summaryrefslogtreecommitdiff
path: root/util/net/sock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'util/net/sock.cpp')
-rw-r--r--util/net/sock.cpp85
1 files changed, 77 insertions, 8 deletions
diff --git a/util/net/sock.cpp b/util/net/sock.cpp
index 69c42f2..ac565c3 100644
--- a/util/net/sock.cpp
+++ b/util/net/sock.cpp
@@ -342,6 +342,67 @@ namespace mongo {
// ------------ SSLManager -----------------
#ifdef MONGO_SSL
+ static unsigned long _ssl_id_callback();
+ static void _ssl_locking_callback(int mode, int type, const char *file, int line);
+
+ class SSLThreadInfo {
+ public:
+
+ SSLThreadInfo() {
+ _id = ++_next;
+ CRYPTO_set_id_callback(_ssl_id_callback);
+ CRYPTO_set_locking_callback(_ssl_locking_callback);
+ }
+
+ ~SSLThreadInfo() {
+ CRYPTO_set_id_callback(0);
+ }
+
+ unsigned long id() const { return _id; }
+
+ void lock_callback( int mode, int type, const char *file, int line ) {
+ if ( mode & CRYPTO_LOCK ) {
+ _mutex[type]->lock();
+ }
+ else {
+ _mutex[type]->unlock();
+ }
+ }
+
+ static void init() {
+ while ( (int)_mutex.size() < CRYPTO_num_locks() )
+ _mutex.push_back( new SimpleMutex("SSLThreadInfo") );
+ }
+
+ static SSLThreadInfo* get() {
+ SSLThreadInfo* me = _thread.get();
+ if ( ! me ) {
+ me = new SSLThreadInfo();
+ _thread.reset( me );
+ }
+ return me;
+ }
+
+ private:
+ unsigned _id;
+
+ static AtomicUInt _next;
+ static vector<SimpleMutex*> _mutex;
+ static boost::thread_specific_ptr<SSLThreadInfo> _thread;
+ };
+
+ static unsigned long _ssl_id_callback() {
+ return SSLThreadInfo::get()->id();
+ }
+ static void _ssl_locking_callback(int mode, int type, const char *file, int line) {
+ SSLThreadInfo::get()->lock_callback( mode , type , file , line );
+ }
+
+ AtomicUInt SSLThreadInfo::_next;
+ vector<SimpleMutex*> SSLThreadInfo::_mutex;
+ boost::thread_specific_ptr<SSLThreadInfo> SSLThreadInfo::_thread;
+
+
SSLManager::SSLManager( bool client ) {
_client = client;
SSL_library_init();
@@ -352,6 +413,8 @@ namespace mongo {
massert( 15864 , mongoutils::str::stream() << "can't create SSL Context: " << ERR_error_string(ERR_get_error(), NULL) , _context );
SSL_CTX_set_options( _context, SSL_OP_ALL);
+ SSLThreadInfo::init();
+ SSLThreadInfo::get();
}
void SSLManager::setupPubPriv( const string& privateKeyFile , const string& publicKeyFile ) {
@@ -387,6 +450,7 @@ namespace mongo {
}
SSL * SSLManager::secure( int fd ) {
+ SSLThreadInfo::get();
SSL * ssl = SSL_new( _context );
massert( 15861 , "can't create SSL" , ssl );
SSL_set_fd( ssl , fd );
@@ -415,13 +479,18 @@ namespace mongo {
_bytesOut = 0;
_bytesIn = 0;
#ifdef MONGO_SSL
+ _ssl = 0;
_sslAccepted = 0;
#endif
}
void Socket::close() {
#ifdef MONGO_SSL
- _ssl.reset();
+ if ( _ssl ) {
+ SSL_shutdown( _ssl );
+ SSL_free( _ssl );
+ _ssl = 0;
+ }
#endif
if ( _fd >= 0 ) {
closesocket( _fd );
@@ -433,8 +502,8 @@ namespace mongo {
void Socket::secure( SSLManager * ssl ) {
assert( ssl );
assert( _fd >= 0 );
- _ssl.reset( ssl->secure( _fd ) );
- SSL_connect( _ssl.get() );
+ _ssl = ssl->secure( _fd );
+ SSL_connect( _ssl );
}
void Socket::secureAccepted( SSLManager * ssl ) {
@@ -446,8 +515,8 @@ namespace mongo {
#ifdef MONGO_SSL
if ( _sslAccepted ) {
assert( _fd );
- _ssl.reset( _sslAccepted->secure( _fd ) );
- SSL_accept( _ssl.get() );
+ _ssl = _sslAccepted->secure( _fd );
+ SSL_accept( _ssl );
_sslAccepted = 0;
}
#endif
@@ -510,7 +579,7 @@ namespace mongo {
int Socket::_send( const char * data , int len ) {
#ifdef MONGO_SSL
if ( _ssl ) {
- return SSL_write( _ssl.get() , data , len );
+ return SSL_write( _ssl , data , len );
}
#endif
return ::send( _fd , data , len , portSendFlags );
@@ -524,7 +593,7 @@ namespace mongo {
#ifdef MONGO_SSL
if ( _ssl ) {
- log() << "SSL Error ret: " << ret << " err: " << SSL_get_error( _ssl.get() , ret )
+ log() << "SSL Error ret: " << ret << " err: " << SSL_get_error( _ssl , ret )
<< " " << ERR_error_string(ERR_get_error(), NULL)
<< endl;
}
@@ -679,7 +748,7 @@ namespace mongo {
int Socket::_recv( char *buf, int max ) {
#ifdef MONGO_SSL
if ( _ssl ){
- return SSL_read( _ssl.get() , buf , max );
+ return SSL_read( _ssl , buf , max );
}
#endif
return ::recv( _fd , buf , max , portRecvFlags );