void MockRemoteDBServer::checkIfUp(InstanceID id) const { scoped_spinlock sLock(_lock); if (!_isRunning || id < _instanceID) { throwSocketError(mongo::SocketErrorKind::CLOSED, _hostAndPort); } }
posixSocket::size_type posixSocket::receiveRaw(char* buffer, const size_type count) { const int ret = ::recv(m_desc, buffer, count, 0); if (ret < 0) { if (errno != EAGAIN) throwSocketError(errno); // No data available at this time return 0; } else if (ret == 0) { // Host shutdown throwSocketError(ENOTCONN); } return ret; }
void posixSocket::sendRaw(const char* buffer, const size_type count) { size_type size = count; while (size > 0) { const int ret = ::send(m_desc, buffer, size, 0); if (ret < 0) { if (errno != EAGAIN) throwSocketError(errno); platform::getHandler()->wait(); } else { buffer += ret; size -= ret; } } }
void posixSocket::connect(const vmime::string& address, const vmime::port_t port) { // Close current connection, if any if (m_desc != -1) { ::close(m_desc); m_desc = -1; } #if VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available // Resolve address, if needed struct ::addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; std::ostringstream portStr; portStr.imbue(std::locale::classic()); portStr << port; struct ::addrinfo* res0; if (::getaddrinfo(address.c_str(), portStr.str().c_str(), &hints, &res0) != 0) { // Error: cannot resolve address throw vmime::exceptions::connection_error("Cannot resolve address."); } // Connect to host int sock = -1; struct ::addrinfo* res = res0; for ( ; sock == -1 && res != NULL ; res = res->ai_next) { sock = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) continue; // try next if (m_timeoutHandler != NULL) { ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK); if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0) { switch (errno) { case 0: case EINPROGRESS: case EINTR: #if defined(EAGAIN) case EAGAIN: #endif // EAGAIN #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) case EWOULDBLOCK: #endif // EWOULDBLOCK // Connection in progress break; default: ::close(sock); sock = -1; continue; // try next } // Wait for socket to be connected. // We will check for time out every second. fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); fd_set fdsError; FD_ZERO(&fdsError); FD_SET(sock, &fdsError); struct timeval tm; tm.tv_sec = 1; tm.tv_usec = 0; m_timeoutHandler->resetTimeOut(); bool connected = false; do { const int ret = select(sock + 1, NULL, &fds, &fdsError, &tm); // Success if (ret > 0) { connected = true; break; } // Error else if (ret < -1) { if (errno != EINTR) { // Cancel connection break; } } // 1-second timeout else if (ret == 0) { if (m_timeoutHandler->isTimeOut()) { if (!m_timeoutHandler->handleTimeOut()) { // Cancel connection break; } else { // Reset timeout and keep waiting for connection m_timeoutHandler->resetTimeOut(); } } else { // Keep waiting for connection } } ::sched_yield(); } while (true); if (!connected) { ::close(sock); sock = -1; continue; // try next } break; } } else { if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0) { ::close(sock); sock = -1; continue; // try next } } } ::freeaddrinfo(res0); if (sock == -1) { try { throwSocketError(errno); } catch (exceptions::socket_exception& e) { throw vmime::exceptions::connection_error ("Error while connecting socket.", e); } } m_desc = sock; #else // !VMIME_HAVE_GETADDRINFO // Resolve address ::sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(static_cast <unsigned short>(port)); addr.sin_addr.s_addr = ::inet_addr(address.c_str()); if (addr.sin_addr.s_addr == static_cast <in_addr_t>(-1)) { ::hostent* hostInfo = ::gethostbyname(address.c_str()); if (hostInfo == NULL) { // Error: cannot resolve address throw vmime::exceptions::connection_error("Cannot resolve address."); } ::memcpy(reinterpret_cast <char*>(&addr.sin_addr), hostInfo->h_addr, hostInfo->h_length); } // Get a new socket m_desc = ::socket(AF_INET, SOCK_STREAM, 0); if (m_desc == -1) { try { throwSocketError(errno); } catch (exceptions::socket_exception& e) { throw vmime::exceptions::connection_error ("Error while creating socket.", e); } } // Start connection if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) { try { throwSocketError(errno); } catch (exceptions::socket_exception& e) { ::close(m_desc); m_desc = -1; // Error throw vmime::exceptions::connection_error ("Error while connecting socket.", e); } } #endif // VMIME_HAVE_GETADDRINFO ::fcntl(m_desc, F_SETFL, ::fcntl(m_desc, F_GETFL) | O_NONBLOCK); }