/** * Parse a inet socket address given as a string and convert it to sockaddr. * @param buf: input string. * @param addr: destination structure. * @param addrlen: maximum size of destination structure as input, real size * converted as output. * @return 0 in case of success, negative errno value in case of error. */ static int pomp_addr_parse_inet(const char *buf, struct sockaddr *addr, uint32_t *addrlen) { int res = -EINVAL; struct addrinfo hints; char *ip = NULL, *sep = NULL; struct addrinfo *ai = NULL; /* Setup hints for getaddrinfo */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = 0; hints.ai_flags = AI_NUMERICHOST; hints.ai_protocol = 0; /* Duplicate string as we need to modify it */ ip = strdup(buf); if (ip == NULL) goto out; /* Find port separator */ sep = strrchr(ip, ':'); if (sep == NULL) goto out; *sep = '\0'; /* Convert address and port * WIN32 returns positive value for errors */ res = getaddrinfo(ip, sep + 1, &hints, &ai); if (res != 0) { POMP_LOGE("getaddrinfo(%s:%s): err=%d(%s)", ip, sep + 1, res, gai_strerror(res)); res = -EINVAL; goto out; } if (*addrlen < (uint32_t)ai->ai_addrlen) { res = -EINVAL; goto out; } memcpy(addr, ai->ai_addr, ai->ai_addrlen); *addrlen = ai->ai_addrlen; res = 0; out: /* Free resources */ if (ai != NULL) freeaddrinfo(ai); free(ip); return res; }
/** * @see pomp_loop_do_wait_and_process. */ static int pomp_loop_poll_do_wait_and_process(struct pomp_loop *loop, int timeout) { int res = 0; uint32_t i = 0, nevents = 0; struct pomp_fd *pfd = NULL; struct pollfd *pollfds = NULL; uint32_t revents = 0; uint32_t pfdcount = 0; /* Remember number of fds now because it can change during callback * processing */ pfdcount = loop->pfdcount + 1; /* Make sure internal pollfd array is big enough */ if (loop->pollfdsize < pfdcount) { pollfds = realloc(loop->pollfds, pfdcount * sizeof(struct pollfd)); if (pollfds == NULL) return -ENOMEM; loop->pollfds = pollfds; loop->pollfdsize = pfdcount; } memset(loop->pollfds, 0, loop->pollfdsize * sizeof(struct pollfd)); /* Wakeup pipe */ loop->pollfds[0].fd = loop->wakeup.pipefds[0]; loop->pollfds[0].events = POLLIN; loop->pollfds[0].revents = 0; /* Registered fds */ for (pfd = loop->pfds, i = 1; pfd != NULL; pfd = pfd->next, i++) { if (i >= pfdcount) { POMP_LOGE("Internal fd list corruption"); break; } loop->pollfds[i].fd = pfd->fd; loop->pollfds[i].events = fd_events_to_poll(pfd->events); loop->pollfds[i].revents = 0; } /* Wait for poll events */ do { res = poll(loop->pollfds, pfdcount, timeout); } while (res < 0 && errno == EINTR); if (res < 0) { res = -errno; POMP_LOG_ERRNO("poll"); return res; } /* Process events */ nevents = (uint32_t)res; for (i = 0; i < pfdcount; i++) { revents = fd_events_from_poll(loop->pollfds[i].revents); if (revents == 0) continue; /* Check for wakeup event */ if (loop->pollfds[i].fd == loop->wakeup.pipefds[0]) { pomp_loop_poll_wakeup_cb(loop); continue; } /* The list might be modified during the callback call */ pfd = pomp_loop_find_pfd(loop, loop->pollfds[i].fd); if (pfd != NULL) (*pfd->cb)(pfd->fd, revents, pfd->userdata); } return timeout == -1 ? 0 : (nevents > 0 ? 0 : -ETIMEDOUT); }