Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
/**
 * @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);
}