Esempio n. 1
0
/*
 * See documentation in public header.
 */
int pomp_decoder_init(struct pomp_decoder *dec, const struct pomp_msg *msg)
{
	POMP_RETURN_ERR_IF_FAILED(dec != NULL, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(msg != NULL, -EINVAL);
	dec->msg = msg;
	dec->pos = POMP_PROT_HEADER_SIZE;
	return 0;
}
Esempio n. 2
0
/*
 * See documentation in public header.
 */
int pomp_addr_format(char *buf, uint32_t buflen, const struct sockaddr *addr,
		uint32_t addrlen)
{
	char ip[64] = "";
	char port[8] = "";
	const struct sockaddr_un *addr_un = NULL;

	POMP_RETURN_ERR_IF_FAILED(buf != NULL, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(buflen != 0, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(addr != NULL, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(addrlen >= sizeof(struct sockaddr), -EINVAL);

	/* WIN32 returns positive value for errors for getnameinfo */
	switch (addr->sa_family) {
	case AF_INET:
		if (getnameinfo(addr, addrlen, ip, sizeof(ip),
				port, sizeof(port),
				NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
			return -EINVAL;
		}
		snprintf(buf, buflen, "inet:%s:%s", ip, port);
		break;

	case AF_INET6:
		if (getnameinfo(addr, addrlen, ip, sizeof(ip),
				port, sizeof(port),
				NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
			return -EINVAL;
		}
		snprintf(buf, buflen, "inet6:%s:%s", ip, port);
		break;

	case AF_UNIX:
		POMP_RETURN_ERR_IF_FAILED(addrlen >= sizeof(struct sockaddr_un),
				-EINVAL);
		addr_un = (const struct sockaddr_un *)addr;
		if (addr_un->sun_path[0] == '\0')
			snprintf(buf, buflen, "unix:@%s", addr_un->sun_path+1);
		else
			snprintf(buf, buflen, "unix:%s", addr_un->sun_path);
		break;

	default:
		snprintf(buf, buflen, "addr:family:%d", addr->sa_family);
		break;
	}

	return 0;
}
/**
 * @see pomp_timer_destroy.
 */
static int pomp_timer_win32_destroy(struct pomp_timer *timer)
{
	struct pomp_fd *pfd = NULL;
	POMP_RETURN_ERR_IF_FAILED(timer != NULL, -EINVAL);

	/* Free resources */
	if (timer->htimer != NULL) {
		/* Wait for cancellation */
		DeleteTimerQueueTimer(NULL, timer->htimer,
				INVALID_HANDLE_VALUE);
	}
	if (timer->hevt != NULL) {
		pfd = pomp_loop_win32_find_pfd_by_hevt(
				timer->loop, timer->hevt);
		if (pfd == NULL) {
			POMP_LOGW("hevt %p not found in loop %p",
					timer->hevt, timer->loop);
		} else {
			pomp_loop_remove_pfd(timer->loop, pfd);
			free(pfd);
		}
		CloseHandle(timer->hevt);
	}
	free(timer);
	return 0;
}
Esempio n. 4
0
/*
 * See documentation in public header.
 */
int pomp_decoder_clear(struct pomp_decoder *dec)
{
	POMP_RETURN_ERR_IF_FAILED(dec != NULL, -EINVAL);
	dec->msg = NULL;
	dec->pos = 0;
	return 0;
}
Esempio n. 5
0
/*
 * See documentation in public header.
 */
int pomp_addr_parse(const char *buf, struct sockaddr *addr, uint32_t *addrlen)
{
	int res = -EINVAL;
	struct sockaddr_un *addr_un = NULL;

	POMP_RETURN_ERR_IF_FAILED(buf != NULL, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(addr != NULL, -EINVAL);
	POMP_RETURN_ERR_IF_FAILED(addrlen != NULL, -EINVAL);

	if (strncmp(buf, "inet:", 5) == 0) {
		/* Inet v4 address */
		res = pomp_addr_parse_inet(buf + 5, addr, addrlen);
		if (res < 0)
			goto out;
	} else if (strncmp(buf, "inet6:", 6) == 0) {
		/* Inet v6 address */
		res = pomp_addr_parse_inet(buf + 6, addr, addrlen);
		if (res < 0)
			goto out;
	} else if (strncmp(buf, "unix:", 5) == 0) {
		/* Unix address */
		if (*addrlen < sizeof(struct sockaddr_un))
			goto out;
		addr_un = (struct sockaddr_un *)addr;
		memset(addr_un, 0, sizeof(*addr_un));
		addr_un->sun_family = AF_UNIX;
		strncpy(addr_un->sun_path, buf + 5, sizeof(addr_un->sun_path));
		if (buf[5] == '@')
			addr_un->sun_path[0] = '\0';
		*addrlen = (uint32_t)sizeof(*addr_un);
	} else {
		goto out;
	}

	/* Success */
	res = 0;

out:
	return res;
}
/**
 * @see pomp_timer_set.
 */
static int pomp_timer_win32_set(struct pomp_timer *timer, uint32_t delay,
		uint32_t period)
{
	int res = 0;
	POMP_RETURN_ERR_IF_FAILED(timer != NULL, -EINVAL);

	/* Delete current one if needed */
	if (timer->htimer != NULL) {
		/* Wait for cancellation */
		DeleteTimerQueueTimer(NULL, timer->htimer,
				INVALID_HANDLE_VALUE);
		timer->htimer = NULL;
	}

	/* Create timer if needed */
	if (delay != 0 && !CreateTimerQueueTimer(&timer->htimer, NULL,
			&pomp_timer_win32_native_cb, timer, delay, period, 0)) {
		res = -ENOMEM;
		POMP_LOG_ERRNO("CreateTimerQueueTimer");
	}

	return res;
}
Esempio n. 7
0
/*
 * See documentation in public header.
 */
int pomp_decoder_destroy(struct pomp_decoder *dec)
{
	POMP_RETURN_ERR_IF_FAILED(dec != NULL, -EINVAL);
	free(dec);
	return 0;
}
Esempio n. 8
0
/*
 * See documentation in public header.
 */
int pomp_decoder_readv(struct pomp_decoder *dec, const char *fmt, va_list args)
{
	int res = 0;
	int flags = 0;
	char c = 0;
	uint32_t len = 0;
	union pomp_value v;
	char **strsav[MAX_DECODE_STR];
	size_t strsavcount = 0, i = 0;

	POMP_RETURN_ERR_IF_FAILED(dec != NULL, -EINVAL);

	/* Allow NULL format string, simply return immediately */
	if (fmt == NULL)
		return 0;

	memset(strsav, 0, sizeof(strsav));
	while (*fmt != '\0') {
		/* Only formatting spec expected here */
		c = *fmt++;
		if (c != '%') {
			POMP_LOGW("decoder : invalid format char (%c)", c);
			res = -EINVAL;
			goto error;
		}
		flags = 0;

again:
		c = *fmt++;
		switch (c) {
		case 'l':
			if (*fmt == 'l') {
				fmt++;
				flags |= FLAG_LL;
			} else {
				flags |= FLAG_L;
			}
			goto again;

		case 'h':
			if (*fmt == 'h') {
				fmt++;
				flags |= FLAG_HH;
			} else {
				flags |= FLAG_H;
			}
			goto again;

		case 'm':
			flags |= FLAG_M;
			goto again;

#ifdef _WIN32
		case 'I':
			if (*fmt == '6' && *(fmt + 1) == '4') {
				fmt += 2;
				flags |= FLAG_LL;
				goto again;
			}
			POMP_LOGW("decoder : invalid format specifier (%c)", c);
			res = -EINVAL;
			break;
#endif /* _WIN32 */

		/* Signed integer */
		case 'i': /* NO BREAK */
		case 'd':
			if (flags & FLAG_LL) {
				res = pomp_decoder_read_i64(dec, &v.i64);
				if (res < 0)
					goto error;
				*va_arg(args, signed long long int *) = v.i64;
			} else if (flags & FLAG_L) {
#if defined(__WORDSIZE) && (__WORDSIZE == 64)
				res = pomp_decoder_read_i64(dec, &v.i64);
				if (res < 0)
					goto error;
				*va_arg(args, signed long int *) = v.i64;
#else
				res = pomp_decoder_read_i32(dec, &v.i32);
				if (res < 0)
					goto error;
				*va_arg(args, signed long int *) = v.i32;
#endif
			} else if (flags & FLAG_HH) {
				res = pomp_decoder_read_i8(dec, &v.i8);
				if (res < 0)
					goto error;
				*va_arg(args, signed char *) = v.i8;
			} else if (flags & FLAG_H) {
				res = pomp_decoder_read_i16(dec, &v.i16);
				if (res < 0)
					goto error;
				*va_arg(args, signed short *) = v.i16;
			} else {
				res = pomp_decoder_read_i32(dec, &v.i32);
				if (res < 0)
					goto error;
				*va_arg(args, signed int *) = v.i32;
			}
			break;

		/* Unsigned integer */
		case 'u':
			if (flags & FLAG_LL) {
				res = pomp_decoder_read_u64(dec, &v.u64);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned long long int *) = v.u64;
			} else if (flags & FLAG_L) {
#if defined(__WORDSIZE) && (__WORDSIZE == 64)
				res = pomp_decoder_read_u64(dec, &v.u64);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned long int *) = v.u64;
#else
				res = pomp_decoder_read_u32(dec, &v.u32);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned long int *) = v.u32;
#endif
			} else if (flags & FLAG_HH) {
				res = pomp_decoder_read_u8(dec, &v.u8);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned char *) = v.u8;
			} else if (flags & FLAG_H) {
				res = pomp_decoder_read_u16(dec, &v.u16);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned short *) = v.u16;
			} else {
				res = pomp_decoder_read_u32(dec, &v.u32);
				if (res < 0)
					goto error;
				*va_arg(args, unsigned int *) = v.u32;
			}
			break;

		/* String */
		case 's':
			if (!(flags & FLAG_M)) {
				/* Only dynamically allocated string allowed */
				POMP_LOGW("decoder : use %%ms instead of %%s");
				res = -EINVAL;
				goto error;
			} else if (strsavcount == MAX_DECODE_STR) {
				/* Too may strings decoded */
				POMP_LOGW("decoder : too many strings");
				res = -E2BIG;
				goto error;
			} else {
				res = pomp_decoder_read_str(dec, &v.str);
				if (res < 0)
					goto error;
				/* Save address where we stored the allocated
				 * string so we can cleanup in case of error */
				strsav[strsavcount] = va_arg(args, char **);
				*strsav[strsavcount] = v.str;
				strsavcount++;
			}
			break;

		/* Buffer */
		case 'p':
			/* Size expected after pointer */
			if (*fmt++ != '%' || *fmt++ != 'u') {
				POMP_LOGW("decoder : expected %%u after %%p");
				res = -EINVAL;
				goto error;
			} else {
				/* codecheck_ignore[LONG_LINE] */
				res = pomp_decoder_read_cbuf(dec, &v.cbuf, &len);
				if (res < 0)
					goto error;
				*va_arg(args, const void **) = v.cbuf;
				*va_arg(args, unsigned int *) = len;
			}
			break;

		/* Floating point */
		case 'f': /* NO BREAK */
		case 'F': /* NO BREAK */
		case 'e': /* NO BREAK */
		case 'E': /* NO BREAK */
		case 'g': /* NO BREAK */
		case 'G':
			if (flags & (FLAG_LL | FLAG_H | FLAG_HH)) {
				POMP_LOGW("decoder : unsupported format width");
				res = -EINVAL;
				goto error;
			} else if (flags & FLAG_L) {
				res = pomp_decoder_read_f64(dec, &v.f64);
				if (res < 0)
					goto error;
				*va_arg(args, double *) = v.f64;
			} else {
				res = pomp_decoder_read_f32(dec, &v.f32);
				if (res < 0)
					goto error;
				*va_arg(args, float *) = v.f32;
			}
			break;

		/* File descriptor (hack) */
		case 'x':
			if (flags & (FLAG_LL | FLAG_L | FLAG_H | FLAG_HH)) {
				POMP_LOGW("decoder : unsupported format width");
				res = -EINVAL;
				goto error;
			} else {
				res = pomp_decoder_read_fd(dec, &v.fd);
				if (res < 0)
					goto error;
				*va_arg(args, int *) = v.fd;
			}
			break;

		default:
			POMP_LOGW("decoder : invalid format specifier (%c)", c);
			res = -EINVAL;
			goto error;
		}
	}

	/* Success, caller will now need to free allocated strings */
	return 0;

	/* We need to free allocated strings in case of error */
error:
	for (i = 0; i < strsavcount; i++) {
		free(*strsav[i]);
		*strsav[i] = NULL;
	}
	return res;
}