Exemple #1
0
static void
acceptSingleConnection(ListenState *listenState, NetDescriptor *nd) {
	Socket *sock;
	Socket *acceptResult;
	struct sockaddr_storage addr;
	socklen_t addrLen;
	NetDescriptor *newNd;

	sock = NetDescriptor_getSocket(nd);
	addrLen = sizeof (addr);
	acceptResult = Socket_accept(sock, (struct sockaddr *) &addr, &addrLen);
	if (acceptResult == Socket_noSocket) {
		switch (errno) {
			case EWOULDBLOCK:
			case ECONNABORTED:
				// Nothing serious. Keep listening.
				return;
			case EMFILE:
			case ENFILE:
			case ENOBUFS:
			case ENOMEM:
#ifdef ENOSR
			case ENOSR:
#endif
				// Serious problems, but future connections may still
				// be possible.
				log_add(log_Warning, "accept() reported '%s'",
						strerror(errno));
				return;
			default:
				// Should not happen.
				log_add(log_Fatal, "Internal error: accept() reported "
						"'%s'", strerror(errno));
				explode();
		}
	}

	(void) Socket_setReuseAddr(acceptResult);
			// Ignore errors; it's not a big deal.
	if (Socket_setNonBlocking(acceptResult) == -1) {
		int savedErrno = errno;
		log_add(log_Error, "Could not make socket non-blocking: %s.",
				strerror(errno));
		Socket_close(acceptResult);
		errno = savedErrno;
		return;
	}
	(void) Socket_setInlineOOB(acceptResult);
			// Ignore errors; it's not a big deal as the other
			// party is not not supposed to send any OOB data.
	(void) Socket_setKeepAlive(sock);
			// Ignore errors; it's not a big deal.

#ifdef DEBUG
	{
		char hostname[NI_MAXHOST];
		int gniRes;

		gniRes = getnameinfo((struct sockaddr *) &addr, addrLen,
				hostname, sizeof hostname, NULL, 0, 0);
		if (gniRes != 0) {
			log_add(log_Error, "Error while performing hostname "
					"lookup for incoming connection: %s",
					(gniRes == EAI_SYSTEM) ? strerror(errno) :
					gai_strerror(gniRes));
		} else {
			log_add(log_Debug, "Accepted incoming connection from '%s'.",
					hostname);
		}
	}
#endif
	
	newNd = NetDescriptor_new(acceptResult, NULL);
	if (newNd == NULL) {
		int savedErrno = errno;
		log_add(log_Error, "NetDescriptor_new() failed: %s.",
				strerror(errno));
		Socket_close(acceptResult);
		errno = savedErrno;
		return;
	}

	doListenConnectCallback(listenState, nd, newNd,
			(struct sockaddr *) &addr, addrLen);
	// NB: newNd is now handed over to the callback function, and should
	//     no longer be referenced from here.
}
Exemple #2
0
// Try connecting to the next address.
static Socket *
tryConnectHostNext(ConnectState *connectState) {
	struct addrinfo *info;
	Socket *sock;
	int connectResult;

	assert(connectState->nd == NULL);

	info = connectState->infoPtr;

	sock = Socket_openNative(info->ai_family, info->ai_socktype,
			info->ai_protocol);
	if (sock == Socket_noSocket) {
		int savedErrno = errno;
		log_add(log_Error, "socket() failed: %s.\n", strerror(errno));
		errno = savedErrno;
		return Socket_noSocket;
	}
	
	if (Socket_setNonBlocking(sock) == -1) {
		int savedErrno = errno;
		log_add(log_Error, "Could not make socket non-blocking: %s.\n",
				strerror(errno));
		errno = savedErrno;
		return Socket_noSocket;
	}

	(void) Socket_setReuseAddr(sock);
			// Ignore errors; it's not a big deal.
	(void) Socket_setInlineOOB(sock);
			// Ignore errors; it's not a big deal as the other party is not
			// not supposed to send any OOB data.
	(void) Socket_setKeepAlive(sock);
			// Ignore errors; it's not a big deal.

	connectResult = Socket_connect(sock, info->ai_addr, info->ai_addrlen);
	if (connectResult == 0) {
		// Connection has already succeeded.
		// We just wait for the writability callback anyhow, so that
		// we can use one code path.
		return sock;
	}

	switch (errno) {
		case EINPROGRESS:
			// Connection in progress; wait for the write callback.
			return sock;
	}

	// Connection failed immediately. This is just for one of the addresses,
	// so this does not have to be final.
	// Note that as the socket is non-blocking, most failed connection
	// errors will usually not be reported immediately.
	{
		int savedErrno = errno;
		Socket_close(sock);
#ifdef DEBUG
		log_add(log_Debug, "connect() immediately failed for one address: "
				"%s.\n", strerror(errno));
				// TODO: add the address in the status message.
#endif
		errno = savedErrno;
	}
	return Socket_noSocket;
}