예제 #1
0
void MockRemoteDBServer::checkIfUp(InstanceID id) const {
    scoped_spinlock sLock(_lock);

    if (!_isRunning || id < _instanceID) {
        throwSocketError(mongo::SocketErrorKind::CLOSED, _hostAndPort);
    }
}
예제 #2
0
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;
}
예제 #3
0
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;
		}
	}
}
예제 #4
0
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);
}