2009-04-30 08:25:52 -04:00
|
|
|
#ifndef __MISC_H__
|
|
|
|
#define __MISC_H__
|
|
|
|
|
2017-01-06 03:44:18 -05:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2009-04-30 08:51:36 -04:00
|
|
|
#include <stdint.h>
|
2021-02-26 13:23:00 -05:00
|
|
|
#include <stddef.h>
|
2017-11-15 17:13:20 -05:00
|
|
|
#include <stdbool.h>
|
2010-09-18 11:15:41 -04:00
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
|
|
|
|
/* ------------------------ Network utility functions ----------------------- */
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
union net_sockaddr
|
|
|
|
{
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
struct sockaddr sa;
|
|
|
|
struct sockaddr_storage ss;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Checks if the address is in a network that is configured as trusted
|
|
|
|
bool
|
|
|
|
net_peer_address_is_trusted(const char *addr);
|
|
|
|
|
|
|
|
int
|
|
|
|
net_address_get(char *addr, size_t addr_len, union net_sockaddr *naddr);
|
|
|
|
|
|
|
|
int
|
|
|
|
net_port_get(short unsigned *port, union net_sockaddr *naddr);
|
|
|
|
|
2022-07-14 15:12:31 -04:00
|
|
|
int
|
|
|
|
net_if_get(char *ifname, size_t ifname_len, const char *addr);
|
|
|
|
|
2021-02-27 18:06:01 -05:00
|
|
|
// Returns the socket fd from socket(), -1 on error
|
2021-02-26 13:23:00 -05:00
|
|
|
int
|
2021-02-26 16:42:09 -05:00
|
|
|
net_connect(const char *addr, unsigned short port, int type, const char *log_service_name);
|
2021-02-26 13:23:00 -05:00
|
|
|
|
2021-02-27 18:06:01 -05:00
|
|
|
// Returns the socket fd from socket(), -1 on error
|
2021-02-26 13:23:00 -05:00
|
|
|
int
|
|
|
|
net_bind(short unsigned *port, int type, const char *log_service_name);
|
|
|
|
|
2023-01-21 18:33:54 -05:00
|
|
|
int
|
|
|
|
net_bind_with_reuseport(short unsigned *port, int type, const char *log_service_name);
|
|
|
|
|
2022-12-21 13:11:03 -05:00
|
|
|
// To avoid polluting namespace too much we don't include event2/http.h here
|
|
|
|
struct evhttp;
|
|
|
|
|
2021-02-27 18:06:01 -05:00
|
|
|
int
|
2022-12-22 09:02:17 -05:00
|
|
|
net_evhttp_bind(struct evhttp *evhttp, unsigned short port, const char *log_service_name);
|
2021-02-27 18:06:01 -05:00
|
|
|
|
2021-05-19 16:53:25 -04:00
|
|
|
// Just checks if the protocol is http or https
|
|
|
|
bool
|
|
|
|
net_is_http_or_https(const char *url);
|
2021-02-26 13:23:00 -05:00
|
|
|
|
|
|
|
/* ----------------------- Conversion/hashing/sanitizers -------------------- */
|
|
|
|
|
|
|
|
// Samples to bytes, bytes to samples
|
2019-02-08 12:58:46 -05:00
|
|
|
#define STOB(s, bits, c) ((s) * (c) * (bits) / 8)
|
|
|
|
#define BTOS(b, bits, c) ((b) / ((c) * (bits) / 8))
|
2016-12-26 13:29:47 -05:00
|
|
|
|
2018-09-04 14:07:05 -04:00
|
|
|
#define ARRAY_SIZE(x) ((unsigned int)(sizeof(x) / sizeof((x)[0])))
|
2016-12-26 13:29:47 -05:00
|
|
|
|
2019-02-10 17:18:26 -05:00
|
|
|
#ifndef MIN
|
2019-04-02 16:47:11 -04:00
|
|
|
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
2019-02-10 17:18:26 -05:00
|
|
|
#endif
|
|
|
|
|
2019-02-16 13:34:36 -05:00
|
|
|
#ifndef MAX
|
2019-04-02 16:47:11 -04:00
|
|
|
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
2019-02-16 13:34:36 -05:00
|
|
|
#endif
|
|
|
|
|
2020-11-05 17:28:57 -05:00
|
|
|
// If you have something like "#define MYNUMBER 3" then NTOSTR(MYNUMBER) will be
|
|
|
|
// the string value, so "3".
|
|
|
|
#define NTOSTR_HELPER(x) #x
|
|
|
|
#define NTOSTR(x) NTOSTR_HELPER(x)
|
|
|
|
|
2009-04-30 08:25:52 -04:00
|
|
|
int
|
2010-02-02 15:02:24 -05:00
|
|
|
safe_atoi32(const char *str, int32_t *val);
|
2009-04-30 08:25:52 -04:00
|
|
|
|
2010-02-08 08:58:14 -05:00
|
|
|
int
|
|
|
|
safe_atou32(const char *str, uint32_t *val);
|
|
|
|
|
2010-05-05 13:03:53 -04:00
|
|
|
int
|
|
|
|
safe_hextou32(const char *str, uint32_t *val);
|
|
|
|
|
2009-04-30 08:25:52 -04:00
|
|
|
int
|
2010-02-02 15:02:24 -05:00
|
|
|
safe_atoi64(const char *str, int64_t *val);
|
2010-01-10 06:09:29 -05:00
|
|
|
|
2010-02-08 08:58:14 -05:00
|
|
|
int
|
|
|
|
safe_atou64(const char *str, uint64_t *val);
|
|
|
|
|
2010-04-04 12:07:32 -04:00
|
|
|
int
|
|
|
|
safe_hextou64(const char *str, uint64_t *val);
|
|
|
|
|
2017-01-01 04:23:34 -05:00
|
|
|
char *
|
|
|
|
safe_strdup(const char *str);
|
2010-09-18 11:15:41 -04:00
|
|
|
|
2017-05-05 14:00:51 -04:00
|
|
|
char *
|
2019-01-26 04:08:11 -05:00
|
|
|
safe_asprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
2017-05-05 14:00:51 -04:00
|
|
|
|
2018-10-06 17:27:54 -04:00
|
|
|
int
|
2019-01-26 04:08:11 -05:00
|
|
|
safe_snprintf_cat(char *dst, size_t n, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
2018-10-06 17:27:54 -04:00
|
|
|
|
2020-02-11 08:12:04 -05:00
|
|
|
int
|
|
|
|
safe_snreplace(char *s, size_t sz, const char *pattern, const char *replacement);
|
2018-10-06 17:27:54 -04:00
|
|
|
|
2010-06-21 11:50:09 -04:00
|
|
|
char *
|
2015-05-31 09:05:31 -04:00
|
|
|
unicode_fixup_string(char *str, const char *fromcode);
|
2010-06-21 11:50:09 -04:00
|
|
|
|
2018-10-06 17:27:54 -04:00
|
|
|
// Modifies str so it is trimmed. Returns pointer to str.
|
2014-08-15 16:56:39 -04:00
|
|
|
char *
|
2018-10-06 17:27:54 -04:00
|
|
|
trim(char *str);
|
|
|
|
|
|
|
|
// Copies the trimmed part of str to a newly allocated string (caller must free)
|
|
|
|
char *
|
|
|
|
atrim(const char *str);
|
2014-08-15 16:56:39 -04:00
|
|
|
|
2017-01-22 17:06:13 -05:00
|
|
|
void
|
|
|
|
swap_pointers(char **a, char **b);
|
|
|
|
|
2009-04-30 08:51:36 -04:00
|
|
|
uint32_t
|
2016-01-17 14:59:16 -05:00
|
|
|
djb_hash(const void *data, size_t len);
|
2009-04-30 08:51:36 -04:00
|
|
|
|
2019-05-12 17:28:38 -04:00
|
|
|
int64_t
|
|
|
|
two_str_hash(const char *a, const char *b);
|
|
|
|
|
2019-09-06 15:51:53 -04:00
|
|
|
uint8_t *
|
|
|
|
b64_decode(int *dstlen, const char *src);
|
2009-05-01 14:56:22 -04:00
|
|
|
|
2010-04-12 12:22:38 -04:00
|
|
|
char *
|
2019-09-06 15:51:53 -04:00
|
|
|
b64_encode(const uint8_t *src, int srclen);
|
2010-04-12 12:22:38 -04:00
|
|
|
|
2010-01-04 11:58:28 -05:00
|
|
|
uint64_t
|
|
|
|
murmur_hash64(const void *key, int len, uint32_t seed);
|
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
|
|
|
|
/* --------------------------- Key/value functions -------------------------- */
|
|
|
|
|
|
|
|
struct onekeyval {
|
|
|
|
char *name;
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
struct onekeyval *next;
|
|
|
|
struct onekeyval *sort;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct keyval {
|
|
|
|
struct onekeyval *head;
|
|
|
|
struct onekeyval *tail;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct keyval *
|
|
|
|
keyval_alloc(void);
|
2021-01-03 18:05:04 -05:00
|
|
|
|
2019-04-07 18:50:20 -04:00
|
|
|
int
|
2021-02-26 13:23:00 -05:00
|
|
|
keyval_add(struct keyval *kv, const char *name, const char *value);
|
2019-04-07 18:50:20 -04:00
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
int
|
|
|
|
keyval_add_size(struct keyval *kv, const char *name, const char *value, size_t size);
|
2019-02-08 12:58:46 -05:00
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
void
|
|
|
|
keyval_remove(struct keyval *kv, const char *name);
|
|
|
|
|
|
|
|
const char *
|
|
|
|
keyval_get(struct keyval *kv, const char *name);
|
|
|
|
|
|
|
|
void
|
|
|
|
keyval_clear(struct keyval *kv);
|
|
|
|
|
|
|
|
void
|
|
|
|
keyval_sort(struct keyval *kv);
|
|
|
|
|
|
|
|
|
|
|
|
/* ------------------------------- Ringbuffer ------------------------------- */
|
|
|
|
|
|
|
|
struct ringbuffer {
|
|
|
|
uint8_t *buffer;
|
|
|
|
size_t size;
|
|
|
|
size_t write_avail;
|
|
|
|
size_t read_avail;
|
|
|
|
size_t write_pos;
|
|
|
|
size_t read_pos;
|
|
|
|
};
|
2017-11-15 17:13:20 -05:00
|
|
|
|
2019-02-22 02:36:27 -05:00
|
|
|
int
|
|
|
|
ringbuffer_init(struct ringbuffer *buf, size_t size);
|
|
|
|
|
|
|
|
void
|
|
|
|
ringbuffer_free(struct ringbuffer *buf, bool content_only);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
ringbuffer_write(struct ringbuffer *buf, const void* src, size_t srclen);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
ringbuffer_read(uint8_t **dst, size_t dstlen, struct ringbuffer *buf);
|
|
|
|
|
2017-11-15 17:13:20 -05:00
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
/* ------------------------- Clock utility functions ------------------------ */
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
2017-01-14 00:56:43 -05:00
|
|
|
#ifndef HAVE_CLOCK_GETTIME
|
|
|
|
|
|
|
|
#ifndef CLOCK_REALTIME
|
|
|
|
# define CLOCK_REALTIME 0
|
|
|
|
#endif
|
|
|
|
#ifndef CLOCK_MONOTONIC
|
|
|
|
# define CLOCK_MONOTONIC 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef int clockid_t;
|
|
|
|
|
|
|
|
int
|
|
|
|
clock_gettime(clockid_t clock_id, struct timespec *tp);
|
|
|
|
|
|
|
|
int
|
|
|
|
clock_getres(clockid_t clock_id, struct timespec *res);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef HAVE_TIMER_SETTIME
|
|
|
|
|
|
|
|
struct itimerspec {
|
|
|
|
struct timespec it_interval;
|
|
|
|
struct timespec it_value;
|
|
|
|
};
|
|
|
|
typedef uint64_t timer_t;
|
|
|
|
|
|
|
|
int
|
|
|
|
timer_create(clockid_t clock_id, void *sevp, timer_t *timer_id);
|
|
|
|
|
|
|
|
int
|
|
|
|
timer_delete(timer_t timer_id);
|
|
|
|
|
|
|
|
int
|
|
|
|
timer_settime(timer_t timer_id, int flags, const struct itimerspec *tp,
|
|
|
|
struct itimerspec *old);
|
|
|
|
|
|
|
|
int
|
|
|
|
timer_getoverrun(timer_t timer_id);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
// Timer function for platforms without hi-res timers
|
2011-02-17 10:21:35 -05:00
|
|
|
int
|
|
|
|
clock_gettime_with_res(clockid_t clock_id, struct timespec *tp, struct timespec *res);
|
|
|
|
|
|
|
|
struct timespec
|
|
|
|
timespec_add(struct timespec time1, struct timespec time2);
|
|
|
|
|
|
|
|
int
|
|
|
|
timespec_cmp(struct timespec time1, struct timespec time2);
|
|
|
|
|
2017-01-15 17:19:57 -05:00
|
|
|
struct timespec
|
|
|
|
timespec_reltoabs(struct timespec relative);
|
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
|
|
|
|
/* ------------------------------- Media quality ---------------------------- */
|
|
|
|
|
|
|
|
// Remember to adjust quality_is_equal() if adding elements
|
|
|
|
struct media_quality {
|
|
|
|
int sample_rate;
|
|
|
|
int bits_per_sample;
|
|
|
|
int channels;
|
|
|
|
int bit_rate;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool
|
|
|
|
quality_is_equal(struct media_quality *a, struct media_quality *b);
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------- Misc utility functions ------------------------ */
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
|
|
|
char **
|
|
|
|
buildopts_get(void);
|
|
|
|
|
|
|
|
// initialize mutex with error checking (not default on all platforms)
|
2017-01-13 17:32:59 -05:00
|
|
|
int
|
2017-01-21 10:11:20 -05:00
|
|
|
mutex_init(pthread_mutex_t *mutex);
|
|
|
|
|
2021-07-05 15:40:31 -04:00
|
|
|
// wrapper for pthread_setname_np/pthread_set_name_np
|
|
|
|
void
|
|
|
|
thread_setname(pthread_t thread, const char *name);
|
|
|
|
|
2021-02-26 13:23:00 -05:00
|
|
|
void
|
|
|
|
uuid_make(char *str);
|
|
|
|
|
|
|
|
int
|
|
|
|
linear_regression(double *m, double *b, double *r, const double *x, const double *y, int n);
|
|
|
|
|
|
|
|
char **
|
|
|
|
m_readfile(const char *path, int num_lines);
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------- Assertion ------------------------------- */
|
|
|
|
|
2017-01-21 10:11:20 -05:00
|
|
|
/* Check that the function returns 0, logging a fatal error referencing
|
|
|
|
returned error (type errno) if it fails, and aborts the process.
|
|
|
|
Example: CHECK_ERR(L_MAIN, my_function()); */
|
|
|
|
#define CHECK_ERR(d, f) \
|
|
|
|
do { int chk_err; \
|
|
|
|
if ( (chk_err = (f)) != 0) \
|
|
|
|
log_fatal_err(d, #f, __LINE__, chk_err); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
/* Check that the function returns 0 or okval, logging a fatal
|
|
|
|
error referencing returned erro (type errno) if not, and aborts the process.
|
|
|
|
Example: int err; CHECK_ERR_EXCEPT(L_MAIN, my_wait(), err, ETIMEDOUT); */
|
|
|
|
#define CHECK_ERR_EXCEPT(d, f, var, okval) \
|
|
|
|
do { (var) = (f); \
|
|
|
|
if (! (((var) == (okval)) || ((var) == 0))) \
|
|
|
|
log_fatal_err(d, #f, __LINE__, (var)); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
/* Check that the function returns value >= 0, logging a fatal error
|
|
|
|
referencing errno if it not, and aborts the process.
|
|
|
|
Example: int ret; CHECK_ERRNO(L_MAIN, ret = my_function()); */
|
|
|
|
#define CHECK_ERRNO(d, f) \
|
|
|
|
do { \
|
|
|
|
if ( (f) < 0 ) \
|
|
|
|
log_fatal_errno(d, #f, __LINE__); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
/* Check that the function returns non-NULL, logging a fatal error if not,
|
|
|
|
and aborts the process.
|
|
|
|
Example: void *ptr; CHECK_NULL(L_MAIN, ptr = my_create()); */
|
|
|
|
#define CHECK_NULL(d, f) \
|
|
|
|
do { \
|
|
|
|
if ( (f) == NULL ) \
|
|
|
|
log_fatal_null(d, #f, __LINE__); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
/* Used by CHECK_*() macros */
|
2017-03-04 12:30:38 -05:00
|
|
|
void
|
|
|
|
log_fatal_err(int domain, const char *func, int line, int err) __attribute__((__noreturn__));
|
|
|
|
|
|
|
|
void
|
|
|
|
log_fatal_errno(int domain, const char *func, int line) __attribute__((__noreturn__));
|
|
|
|
|
|
|
|
void
|
|
|
|
log_fatal_null(int domain, const char *func, int line) __attribute__((__noreturn__));
|
2017-01-13 17:32:59 -05:00
|
|
|
|
2009-04-30 08:25:52 -04:00
|
|
|
#endif /* !__MISC_H__ */
|