예제 #1
0
파일: net.c 프로젝트: Honglongwu/ccan
int net_connect_complete(struct pollfd pfds[2])
{
	unsigned int i;

	assert(pfds[0].fd != -1 || pfds[1].fd != -1);

	for (i = 0; i < 2; i++) {
		int err;
		socklen_t errlen = sizeof(err);

		if (pfds[i].fd == -1)
			continue;
		if (getsockopt(pfds[i].fd, SOL_SOCKET, SO_ERROR, &err,
			       &errlen) != 0) {
			net_connect_abort(pfds);
			return -1;
		}
		if (err == 0) {
			/* Don't hand them non-blocking fd! */
			if (!set_nonblock(pfds[i].fd, false)) {
				net_connect_abort(pfds);
				return -1;
			}
			/* Close other one. */
			if (pfds[!i].fd != -1)
				close(pfds[!i].fd);
			return pfds[i].fd;
		}
	}

	/* Still going... */
	errno = EINPROGRESS;
	return -1;
}
예제 #2
0
int net_connect_complete(struct pollfd pfds[2])
{
	unsigned int i;

	assert(pfds[0].fd != -1 || pfds[1].fd != -1);

	for (i = 0; i < 2; i++) {
		int err;
		socklen_t errlen = sizeof(err);

		if (pfds[i].fd == -1)
			continue;
		if (pfds[i].revents & POLLHUP) {
			/* Linux gives this if connecting to local
			 * non-listening port */
			close(pfds[i].fd);
			pfds[i].fd = -1;
			if (pfds[!i].fd == -1) {
				errno = ECONNREFUSED;
				return -1;
			}
			continue;
		}
		if (!(pfds[i].revents & POLLOUT))
			continue;

		if (getsockopt(pfds[i].fd, SOL_SOCKET, SO_ERROR, &err,
			       &errlen) != 0) {
			net_connect_abort(pfds);
			return -1;
		}
		if (err == 0) {
			/* Don't hand them non-blocking fd! */
			if (!set_nonblock(pfds[i].fd, false)) {
				net_connect_abort(pfds);
				return -1;
			}
			/* Close other one. */
			if (pfds[!i].fd != -1)
				close(pfds[!i].fd);
			return pfds[i].fd;
		}
	}

	/* Still going... */
	errno = EINPROGRESS;
	return -1;
}
예제 #3
0
int net_connect(const struct addrinfo *addrinfo)
{
	struct pollfd pfds[2];
	int sockfd;

	sockfd = net_connect_async(addrinfo, pfds);
	/* Immediate connect or error is easy. */
	if (sockfd >= 0 || errno != EINPROGRESS)
		return sockfd;

	while (poll(pfds, 2, -1) != -1) {
		sockfd = net_connect_complete(pfds);
		if (sockfd >= 0 || errno != EINPROGRESS)
			return sockfd;
	}

	net_connect_abort(pfds);
	return -1;
}