- while (num && poll(pfd, num, -1) != -1) {
- for (i = 0; i < num; i++) {
- int err;
- socklen_t errlen = sizeof(err);
- if (!pfd[i].revents)
- continue;
- if (getsockopt(pfd[i].fd, SOL_SOCKET, SO_ERROR, &err,
- &errlen) != 0)
- goto out;
- if (err == 0)
- goto got_one;
-
- /* Remove dead one. */
- errno = err;
- remove_fd(pfd, addr, slen, &num, i--);
- }
+ /* Still going... */
+ errno = EINPROGRESS;
+ return -1;
+}
+
+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;
+}
+
+struct addrinfo *net_server_lookup(const char *service,
+ int family,
+ int socktype)
+{
+ struct addrinfo *res, hints;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = 0;
+
+ if (getaddrinfo(NULL, service, &hints, &res) != 0)
+ return NULL;
+
+ return res;
+}
+
+static bool should_listen(const struct addrinfo *addrinfo)
+{
+#ifdef SOCK_SEQPACKET
+ if (addrinfo->ai_socktype == SOCK_SEQPACKET)
+ return true;
+#endif
+ return (addrinfo->ai_socktype == SOCK_STREAM);
+}
+
+static int make_listen_fd(const struct addrinfo *addrinfo)
+{
+ int saved_errno, fd, on = 1;
+
+ fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
+ addrinfo->ai_protocol);
+ if (fd < 0)
+ return -1;
+
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
+ goto fail;
+
+ if (should_listen(addrinfo) && listen(fd, 5) != 0)
+ goto fail;
+ return fd;
+
+fail:
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+}
+
+int net_bind(const struct addrinfo *addrinfo, int fds[2])
+{
+ const struct addrinfo *ipv6 = NULL;
+ const struct addrinfo *ipv4 = NULL;
+ unsigned int num;
+
+ if (addrinfo->ai_family == AF_INET)
+ ipv4 = addrinfo;
+ else if (addrinfo->ai_family == AF_INET6)
+ ipv6 = addrinfo;
+
+ if (addrinfo->ai_next) {
+ if (addrinfo->ai_next->ai_family == AF_INET)
+ ipv4 = addrinfo->ai_next;
+ else if (addrinfo->ai_next->ai_family == AF_INET6)
+ ipv6 = addrinfo->ai_next;