bool MessagingPort::connect(SockAddr& _far) { farEnd = _far; sock = socket(AF_INET, SOCK_STREAM, 0); if ( sock == INVALID_SOCKET ) { log() << "ERROR: connect(): invalid socket? " << OUTPUT_ERRNO << endl; return false; } #if 0 long fl = fcntl(sock, F_GETFL, 0); assert( fl >= 0 ); fl |= O_NONBLOCK; fcntl(sock, F_SETFL, fl); int res = ::connect(sock, (sockaddr *) &farEnd.sa, farEnd.addressSize); if ( res ) { if ( errno == EINPROGRESS ) closesocket(sock); sock = -1; return false; } #endif ConnectBG bg; bg.sock = sock; bg.farEnd = farEnd; bg.go(); // int res = ::connect(sock, (sockaddr *) &farEnd.sa, farEnd.addressSize); if ( bg.wait(5000) ) { if ( bg.res ) { closesocket(sock); sock = -1; return false; } } else { // time out the connect closesocket(sock); sock = -1; bg.wait(); // so bg stays in scope until bg thread terminates return false; } disableNagle(sock); #ifdef SO_NOSIGPIPE // osx const int one = 1; setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif return true; }
bool Socket::connect(SockAddr& remote) { _remote = remote; _fd = socket(remote.getType(), SOCK_STREAM, 0); if ( _fd == INVALID_SOCKET ) { LOG(_logLevel) << "ERROR: connect invalid socket " << errnoWithDescription() << endl; return false; } if ( _timeout > 0 ) { setTimeout( _timeout ); } static const unsigned int connectTimeoutMillis = 5000; ConnectBG bg(_fd, remote); bg.go(); if ( bg.wait(connectTimeoutMillis) ) { if ( bg.inError() ) { warning() << "Failed to connect to " << _remote.getAddr() << ":" << _remote.getPort() << ", reason: " << bg.getErrnoWithDescription() << endl; close(); return false; } } else { // time out the connect close(); bg.wait(); // so bg stays in scope until bg thread terminates warning() << "Failed to connect to " << _remote.getAddr() << ":" << _remote.getPort() << " after " << connectTimeoutMillis << " milliseconds, giving up." << endl; return false; } if (remote.getType() != AF_UNIX) disableNagle(_fd); #ifdef SO_NOSIGPIPE // ignore SIGPIPE signals on osx, to avoid process exit const int one = 1; setsockopt( _fd , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif _local = getLocalAddrForBoundSocketFd(_fd); _fdCreationMicroSec = curTimeMicros64(); _awaitingHandshake = false; return true; }
void Listener::listen() { SockAddr from; while ( 1 ) { int s = accept(sock, (sockaddr *) &from.sa, &from.addressSize); if ( s < 0 ) { if ( errno == ECONNABORTED || errno == EBADF ) { log() << "Listener on port " << port << " aborted" << endl; return; } log() << "Listener: accept() returns " << s << " errno:" << errno << ", strerror: " << strerror( errno ) << endl; continue; } disableNagle(s); log() << "connection accepted from " << from.toString() << endl; accepted( new MessagingPort(s, from) ); } }
void Listener::listen() { static long connNumber = 0; SockAddr from; while ( ! inShutdown() ) { int s = accept(sock, (sockaddr *) &from.sa, &from.addressSize); if ( s < 0 ) { if ( errno == ECONNABORTED || errno == EBADF ) { log() << "Listener on port " << port << " aborted" << endl; return; } log() << "Listener: accept() returns " << s << " " << OUTPUT_ERRNO << endl; continue; } disableNagle(s); if ( ! cmdLine.quiet ) log() << "connection accepted from " << from.toString() << " #" << ++connNumber << endl; accepted( new MessagingPort(s, from) ); } }
void MiniWebServer::run() { SockAddr from; while ( 1 ) { int s = accept(sock, from.getSockAddr(), &from.addressSize); if ( s < 0 ) { if ( errno == ECONNABORTED ) { log() << "Listener on port " << port << " aborted." << endl; return; } log() << "MiniWebServer: accept() returns " << s << " errno:" << errno << endl; sleepmillis(200); continue; } disableNagle(s); RARELY log() << "MiniWebServer: connection accepted from " << from.toString() << endl; accepted( s, from ); closesocket(s); } }
bool Socket::connect(SockAddr& remote) { _remote = remote; _fd = socket(remote.getType(), SOCK_STREAM, 0); if ( _fd == INVALID_SOCKET ) { LOG(_logLevel) << "ERROR: connect invalid socket " << errnoWithDescription() << endl; return false; } if ( _timeout > 0 ) { setTimeout( _timeout ); } ConnectBG bg(_fd, remote); bg.go(); if ( bg.wait(5000) ) { if ( bg.inError() ) { close(); return false; } } else { // time out the connect close(); bg.wait(); // so bg stays in scope until bg thread terminates return false; } if (remote.getType() != AF_UNIX) disableNagle(_fd); #ifdef SO_NOSIGPIPE // ignore SIGPIPE signals on osx, to avoid process exit const int one = 1; setsockopt( _fd , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif _local = getLocalAddrForBoundSocketFd(_fd); _fdCreationMicroSec = curTimeMicros64(); return true; }
bool Socket::connect(SockAddr& remote) { _remote = remote; _fd = socket(remote.getType(), SOCK_STREAM, 0); if ( _fd == INVALID_SOCKET ) { log(_logLevel) << "ERROR: connect invalid socket " << errnoWithDescription() << endl; return false; } if ( _timeout > 0 ) { setSockTimeouts( _fd, _timeout ); } ConnectBG bg(_fd, remote); bg.go(); if ( bg.wait(5000) ) { if ( bg.inError() ) { close(); return false; } } else { // time out the connect close(); bg.wait(); // so bg stays in scope until bg thread terminates return false; } if (remote.getType() != AF_UNIX) disableNagle(_fd); #ifdef SO_NOSIGPIPE // osx const int one = 1; setsockopt( _fd , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif return true; }
void Listener::initAndListen() { vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port); vector<int> socks; SOCKET maxfd = 0; // needed for select() for (vector<SockAddr>::iterator it=mine.begin(), end=mine.end(); it != end; ++it){ SockAddr& me = *it; SOCKET sock = ::socket(me.getType(), SOCK_STREAM, 0); if ( sock == INVALID_SOCKET ) { log() << "ERROR: listen(): invalid socket? " << errnoWithDescription() << endl; } if (me.getType() == AF_UNIX){ #if !defined(_WIN32) if (unlink(me.getAddr().c_str()) == -1){ int x = errno; if (x != ENOENT){ log() << "couldn't unlink socket file " << me << errnoWithDescription(x) << " skipping" << endl; continue; } } #endif } else if (me.getType() == AF_INET6) { // IPv6 can also accept IPv4 connections as mapped addresses (::ffff:127.0.0.1) // That causes a conflict if we don't do set it to IPV6_ONLY const int one = 1; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &one, sizeof(one)); } prebindOptions( sock ); if ( ::bind(sock, me.raw(), me.addressSize) != 0 ) { int x = errno; log() << "listen(): bind() failed " << errnoWithDescription(x) << " for socket: " << me.toString() << endl; if ( x == EADDRINUSE ) log() << " addr already in use" << endl; closesocket(sock); return; } if ( ::listen(sock, 128) != 0 ) { log() << "listen(): listen() failed " << errnoWithDescription() << endl; closesocket(sock); return; } ListeningSockets::get()->add( sock ); socks.push_back(sock); if (sock > maxfd) maxfd = sock; } static long connNumber = 0; struct timeval maxSelectTime; while ( ! inShutdown() ) { fd_set fds[1]; FD_ZERO(fds); for (vector<int>::iterator it=socks.begin(), end=socks.end(); it != end; ++it){ FD_SET(*it, fds); } maxSelectTime.tv_sec = 0; maxSelectTime.tv_usec = 10000; const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime); if (ret == 0){ _elapsedTime += maxSelectTime.tv_usec / 1000; continue; } _elapsedTime += ret; // assume 1ms to grab connection. very rough if (ret < 0){ int x = errno; #ifdef EINTR if ( x == EINTR ){ log() << "select() signal caught, continuing" << endl; continue; } #endif if ( ! inShutdown() ) log() << "select() failure: ret=" << ret << " " << errnoWithDescription(x) << endl; return; } for (vector<int>::iterator it=socks.begin(), end=socks.end(); it != end; ++it){ if (! (FD_ISSET(*it, fds))) continue; SockAddr from; int s = accept(*it, from.raw(), &from.addressSize); if ( s < 0 ) { int x = errno; // so no global issues if ( x == ECONNABORTED || x == EBADF ) { log() << "Listener on port " << _port << " aborted" << endl; return; } if ( x == 0 && inShutdown() ){ return; // socket closed } log() << "Listener: accept() returns " << s << " " << errnoWithDescription(x) << endl; continue; } if (from.getType() != AF_UNIX) disableNagle(s); if ( _logConnect && ! cmdLine.quiet ) log() << "connection accepted from " << from.toString() << " #" << ++connNumber << endl; accepted(s, from); } } }
void Listener::initAndListen() { checkTicketNumbers(); vector<SOCKET> socks; set<int> sslSocks; { // normal sockets vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port, (!cmdLine.noUnixSocket && useUnixSockets())); if ( ! _setupSockets( mine , socks ) ) return; } #ifdef MONGO_SSL if ( _ssl && _sslPort > 0 ) { unsigned prev = socks.size(); vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _sslPort, false ); if ( ! _setupSockets( mine , socks ) ) return; for ( unsigned i=prev; i<socks.size(); i++ ) { sslSocks.insert( socks[i] ); } } #endif SOCKET maxfd = 0; // needed for select() for ( unsigned i=0; i<socks.size(); i++ ) { if ( socks[i] > maxfd ) maxfd = socks[i]; } #ifdef MONGO_SSL if ( _ssl == 0 ) { _logListen( _port , false ); } else if ( _sslPort == 0 ) { _logListen( _port , true ); } else { // both _logListen( _port , false ); _logListen( _sslPort , true ); } #else _logListen( _port , false ); #endif static long connNumber = 0; struct timeval maxSelectTime; while ( ! inShutdown() ) { fd_set fds[1]; FD_ZERO(fds); for (vector<SOCKET>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { FD_SET(*it, fds); } maxSelectTime.tv_sec = 0; maxSelectTime.tv_usec = 10000; const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime); if (ret == 0) { #if defined(__linux__) _elapsedTime += ( 10000 - maxSelectTime.tv_usec ) / 1000; #else _elapsedTime += 10; #endif continue; } if (ret < 0) { int x = errno; #ifdef EINTR if ( x == EINTR ) { log() << "select() signal caught, continuing" << endl; continue; } #endif if ( ! inShutdown() ) log() << "select() failure: ret=" << ret << " " << errnoWithDescription(x) << endl; return; } #if defined(__linux__) _elapsedTime += max(ret, (int)(( 10000 - maxSelectTime.tv_usec ) / 1000)); #else _elapsedTime += ret; // assume 1ms to grab connection. very rough #endif for (vector<SOCKET>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { if (! (FD_ISSET(*it, fds))) continue; SockAddr from; int s = accept(*it, from.raw(), &from.addressSize); if ( s < 0 ) { int x = errno; // so no global issues if ( x == ECONNABORTED || x == EBADF ) { log() << "Listener on port " << _port << " aborted" << endl; return; } if ( x == 0 && inShutdown() ) { return; // socket closed } if( !inShutdown() ) { log() << "Listener: accept() returns " << s << " " << errnoWithDescription(x) << endl; if (x == EMFILE || x == ENFILE) { // Connection still in listen queue but we can't accept it yet error() << "Out of file descriptors. Waiting one second before trying to accept more connections." << warnings; sleepsecs(1); } } continue; } if (from.getType() != AF_UNIX) disableNagle(s); #ifdef SO_NOSIGPIPE // ignore SIGPIPE signals on osx, to avoid process exit const int one = 1; setsockopt( s , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif if ( _logConnect && ! cmdLine.quiet ){ int conns = connTicketHolder.used()+1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "connection accepted from " << from.toString() << " #" << ++connNumber << " (" << conns << word << " now open)" << endl; } boost::shared_ptr<Socket> pnewSock( new Socket(s, from) ); #ifdef MONGO_SSL if ( _ssl && ( _sslPort == 0 || sslSocks.count(*it) ) ) { pnewSock->secureAccepted( _ssl ); } #endif accepted( pnewSock ); } } }
bool Socket::connect(SockAddr& remote) { _remote = remote; _fd = ::socket(remote.getType(), SOCK_STREAM, 0); if (_fd == INVALID_SOCKET) { networkWarnWithDescription(*this, "socket"); return false; } if (!setBlock(_fd, false)) { networkWarnWithDescription(*this, "set socket to non-blocking mode"); return false; } const Milliseconds connectTimeoutMillis(static_cast<int64_t>( _timeout > 0 ? std::min(kMaxConnectTimeoutMS, (_timeout * 1000)) : kMaxConnectTimeoutMS)); const Date_t expiration = Date_t::now() + connectTimeoutMillis; bool connectSucceeded = ::connect(_fd, _remote.raw(), _remote.addressSize) == 0; if (!connectSucceeded) { #ifdef _WIN32 if (WSAGetLastError() != WSAEWOULDBLOCK) { networkWarnWithDescription(*this, "connect"); return false; } #else if (errno != EINTR && errno != EINPROGRESS) { networkWarnWithDescription(*this, "connect"); return false; } #endif pollfd pfd; pfd.fd = _fd; pfd.events = POLLOUT; while (true) { const auto timeout = std::max(Milliseconds(0), expiration - Date_t::now()); int pollReturn = socketPoll(&pfd, 1, timeout.count()); #ifdef _WIN32 if (pollReturn == SOCKET_ERROR) { networkWarnWithDescription(*this, "poll"); return false; } #else if (pollReturn == -1) { if (errno != EINTR) { networkWarnWithDescription(*this, "poll"); return false; } // EINTR in poll, try again continue; } #endif // No activity for the full duration of the timeout. if (pollReturn == 0) { warning() << "Failed to connect to " << _remote.getAddr() << ":" << _remote.getPort() << " after " << connectTimeoutMillis << " milliseconds, giving up."; return false; } // We had a result, see if there's an error on the socket. int optVal; socklen_t optLen = sizeof(optVal); if (::getsockopt( _fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&optVal), &optLen) == -1) { networkWarnWithDescription(*this, "getsockopt"); return false; } if (optVal != 0) { networkWarnWithDescription(*this, "checking socket for error after poll", optVal); return false; } // We had activity and we don't have errors on the socket, we're connected. break; } } if (!setBlock(_fd, true)) { networkWarnWithDescription(*this, "could not set socket to blocking mode"); return false; } if (_timeout > 0) { setTimeout(_timeout); } if (remote.getType() != AF_UNIX) disableNagle(_fd); #ifdef SO_NOSIGPIPE // ignore SIGPIPE signals on osx, to avoid process exit const int one = 1; setsockopt(_fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif _local = getLocalAddrForBoundSocketFd(_fd); _fdCreationMicroSec = curTimeMicros64(); _awaitingHandshake = false; return true; }
void Listener::initAndListen() { if (!_setupSocketsSuccessful) { return; } #ifdef MONGO_SSL _logListen(_port, _ssl); #else _logListen(_port, false); #endif OwnedPointerVector<EventHolder> eventHolders; boost::scoped_array<WSAEVENT> events(new WSAEVENT[_socks.size()]); // Populate events array with an event for each socket we are watching for (size_t count = 0; count < _socks.size(); ++count) { EventHolder* ev(new EventHolder); eventHolders.mutableVector().push_back(ev); events[count] = ev->get(); } while ( ! inShutdown() ) { // Turn on listening for accept-ready sockets for (size_t count = 0; count < _socks.size(); ++count) { int status = WSAEventSelect(_socks[count], events[count], FD_ACCEPT | FD_CLOSE); if (status == SOCKET_ERROR) { const int mongo_errno = WSAGetLastError(); // During shutdown, we may fail to listen on the socket if it has already // been closed if (inShutdown()) { return; } error() << "Windows WSAEventSelect returned " << errnoWithDescription(mongo_errno) << endl; fassertFailed(16727); } } // Wait till one of them goes active, or we time out DWORD result = WSAWaitForMultipleEvents(_socks.size(), events.get(), FALSE, // don't wait for all the events 10, // timeout, in ms FALSE); // do not allow I/O interruptions if (result == WSA_WAIT_FAILED) { const int mongo_errno = WSAGetLastError(); error() << "Windows WSAWaitForMultipleEvents returned " << errnoWithDescription(mongo_errno) << endl; fassertFailed(16723); } if (result == WSA_WAIT_TIMEOUT) { _elapsedTime += 10; continue; } _elapsedTime += 1; // assume 1ms to grab connection. very rough // Determine which socket is ready DWORD eventIndex = result - WSA_WAIT_EVENT_0; WSANETWORKEVENTS networkEvents; // Extract event details, and clear event for next pass int status = WSAEnumNetworkEvents(_socks[eventIndex], events[eventIndex], &networkEvents); if (status == SOCKET_ERROR) { const int mongo_errno = WSAGetLastError(); error() << "Windows WSAEnumNetworkEvents returned " << errnoWithDescription(mongo_errno) << endl; continue; } if (networkEvents.lNetworkEvents & FD_CLOSE) { log() << "listen socket closed" << endl; break; } if (!(networkEvents.lNetworkEvents & FD_ACCEPT)) { error() << "Unexpected network event: " << networkEvents.lNetworkEvents << endl; continue; } int iec = networkEvents.iErrorCode[FD_ACCEPT_BIT]; if (iec != 0) { error() << "Windows socket accept did not work:" << errnoWithDescription(iec) << endl; continue; } status = WSAEventSelect(_socks[eventIndex], NULL, 0); if (status == SOCKET_ERROR) { const int mongo_errno = WSAGetLastError(); error() << "Windows WSAEventSelect returned " << errnoWithDescription(mongo_errno) << endl; continue; } disableNonblockingMode(_socks[eventIndex]); SockAddr from; int s = accept(_socks[eventIndex], from.raw(), &from.addressSize); if ( s < 0 ) { int x = errno; // so no global issues if (x == EBADF) { log() << "Port " << _port << " is no longer valid" << endl; continue; } else if (x == ECONNABORTED) { log() << "Listener on port " << _port << " aborted" << endl; continue; } if ( x == 0 && inShutdown() ) { return; // socket closed } if( !inShutdown() ) { log() << "Listener: accept() returns " << s << " " << errnoWithDescription(x) << endl; if (x == EMFILE || x == ENFILE) { // Connection still in listen queue but we can't accept it yet error() << "Out of file descriptors. Waiting one second before" " trying to accept more connections." << warnings; sleepsecs(1); } } continue; } if (from.getType() != AF_UNIX) disableNagle(s); long long myConnectionNumber = globalConnectionNumber.addAndFetch(1); if (_logConnect && !serverGlobalParams.quiet) { int conns = globalTicketHolder.used()+1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "connection accepted from " << from.toString() << " #" << myConnectionNumber << " (" << conns << word << " now open)" << endl; } boost::shared_ptr<Socket> pnewSock( new Socket(s, from) ); #ifdef MONGO_SSL if (_ssl) { pnewSock->secureAccepted(_ssl); } #endif accepted( pnewSock , myConnectionNumber ); } }
void Listener::initAndListen() { if (!_setupSocketsSuccessful) { return; } SOCKET maxfd = 0; // needed for select() for (unsigned i = 0; i < _socks.size(); i++) { if (_socks[i] > maxfd) maxfd = _socks[i]; } if ( maxfd >= FD_SETSIZE ) { error() << "socket " << maxfd << " is higher than " << FD_SETSIZE-1 << "; not supported" << warnings; return; } #ifdef MONGO_SSL _logListen(_port, _ssl); #else _logListen(_port, false); #endif struct timeval maxSelectTime; while ( ! inShutdown() ) { fd_set fds[1]; FD_ZERO(fds); for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) { FD_SET(*it, fds); } maxSelectTime.tv_sec = 0; maxSelectTime.tv_usec = 10000; const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime); if (ret == 0) { #if defined(__linux__) _elapsedTime += ( 10000 - maxSelectTime.tv_usec ) / 1000; #else _elapsedTime += 10; #endif continue; } if (ret < 0) { int x = errno; #ifdef EINTR if ( x == EINTR ) { log() << "select() signal caught, continuing" << endl; continue; } #endif if ( ! inShutdown() ) log() << "select() failure: ret=" << ret << " " << errnoWithDescription(x) << endl; return; } #if defined(__linux__) _elapsedTime += max(ret, (int)(( 10000 - maxSelectTime.tv_usec ) / 1000)); #else _elapsedTime += ret; // assume 1ms to grab connection. very rough #endif for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) { if (! (FD_ISSET(*it, fds))) continue; SockAddr from; int s = accept(*it, from.raw(), &from.addressSize); if ( s < 0 ) { int x = errno; // so no global issues if (x == EBADF) { log() << "Port " << _port << " is no longer valid" << endl; return; } else if (x == ECONNABORTED) { log() << "Connection on port " << _port << " aborted" << endl; continue; } if ( x == 0 && inShutdown() ) { return; // socket closed } if( !inShutdown() ) { log() << "Listener: accept() returns " << s << " " << errnoWithDescription(x) << endl; if (x == EMFILE || x == ENFILE) { // Connection still in listen queue but we can't accept it yet error() << "Out of file descriptors. Waiting one second before trying to accept more connections." << warnings; sleepsecs(1); } } continue; } if (from.getType() != AF_UNIX) disableNagle(s); #ifdef SO_NOSIGPIPE // ignore SIGPIPE signals on osx, to avoid process exit const int one = 1; setsockopt( s , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); #endif long long myConnectionNumber = globalConnectionNumber.addAndFetch(1); if (_logConnect && !serverGlobalParams.quiet) { int conns = globalTicketHolder.used()+1; const char* word = (conns == 1 ? " connection" : " connections"); log() << "connection accepted from " << from.toString() << " #" << myConnectionNumber << " (" << conns << word << " now open)" << endl; } boost::shared_ptr<Socket> pnewSock( new Socket(s, from) ); #ifdef MONGO_SSL if (_ssl) { pnewSock->secureAccepted(_ssl); } #endif accepted( pnewSock , myConnectionNumber ); } } }