/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }