You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rtpengine/daemon/aux.h

429 lines
12 KiB

#ifndef __AUX_H__
#define __AUX_H__
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <fcntl.h>
#include <glib.h>
#include <pcre.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "compat.h"
#if 0 && defined(__DEBUG)
#define __THREAD_DEBUG 1
#endif
#define OFFSET_OF(t,e) ((unsigned int) (unsigned long) &(((t *) 0)->e))
#define ZERO(x) memset(&(x), 0, sizeof(x))
#define IPF "%u.%u.%u.%u"
#define IPP(x) ((unsigned char *) (&(x)))[0], ((unsigned char *) (&(x)))[1], ((unsigned char *) (&(x)))[2], ((unsigned char *) (&(x)))[3]
#define IP6F "%x:%x:%x:%x:%x:%x:%x:%x"
#define IP6P(x) ntohs(((u_int16_t *) (x))[0]), \
ntohs(((u_int16_t *) (x))[1]), \
ntohs(((u_int16_t *) (x))[2]), \
ntohs(((u_int16_t *) (x))[3]), \
ntohs(((u_int16_t *) (x))[4]), \
ntohs(((u_int16_t *) (x))[5]), \
ntohs(((u_int16_t *) (x))[6]), \
ntohs(((u_int16_t *) (x))[7])
#define D6F "["IP6F"]:%u"
#define D6P(x) IP6P((x).sin6_addr.s6_addr), ntohs((x).sin6_port)
#define DF IPF ":%u"
#define DP(x) IPP((x).sin_addr.s_addr), ntohs((x).sin_port)
#define BIT_ARRAY_DECLARE(name, size) unsigned long name[((size) + sizeof(long) * 8 - 1) / (sizeof(long) * 8)]
#define UINT64F "%" G_GUINT64_FORMAT
typedef int (*parse_func)(char **, void **, void *);
GList *g_list_link(GList *, GList *);
int pcre_multi_match(pcre *, pcre_extra *, const char *, unsigned int, parse_func, void *, GQueue *);
INLINE void strmove(char **, char **);
INLINE void strdupfree(char **, const char *);
#if !GLIB_CHECK_VERSION(2,14,0)
#define G_QUEUE_INIT { NULL, NULL, 0 }
void g_string_vprintf(GString *string, const gchar *format, va_list args);
void g_queue_clear(GQueue *);
#endif
#if !GLIB_CHECK_VERSION(2,32,0)
INLINE int g_hash_table_contains(GHashTable *h, const void *k) {
return g_hash_table_lookup(h, k) ? 1 : 0;
}
#endif
INLINE void g_queue_move(GQueue *dst, GQueue *src) {
GList *l;
while ((l = g_queue_pop_head_link(src)))
g_queue_push_tail_link(dst, l);
}
INLINE void g_queue_truncate(GQueue *q, unsigned int len) {
while (q->length > len)
g_queue_pop_tail(q);
}
INLINE void strmove(char **d, char **s) {
if (*d)
free(*d);
*d = *s;
*s = strdup("");
}
INLINE void strdupfree(char **d, const char *s) {
if (*d)
free(*d);
*d = strdup(s);
}
INLINE void nonblock(int fd) {
fcntl(fd, F_SETFL, O_NONBLOCK);
}
INLINE void reuseaddr(int fd) {
int one = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
}
INLINE void ipv6only(int fd, int yn) {
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yn, sizeof(yn));
}
INLINE unsigned long bit_array_isset(unsigned long *name, unsigned int bit) {
return name[(bit) / (sizeof(long) * 8)] & (1UL << ((bit) % (sizeof(long) * 8)));
}
INLINE void bit_array_set(unsigned long *name, unsigned int bit) {
name[(bit) / (sizeof(long) * 8)] |= 1UL << ((bit) % (sizeof(long) * 8));
}
INLINE void bit_array_clear(unsigned long *name, unsigned int bit) {
name[(bit) / (sizeof(long) * 8)] &= ~(1UL << ((bit) % (sizeof(long) * 8)));
}
INLINE char chrtoupper(char x) {
return x & 0xdf;
}
INLINE void swap_ptrs(void *a, void *b) {
void *t, **aa, **bb;
aa = a;
bb = b;
t = *aa;
*aa = *bb;
*bb = t;
}
INLINE void in4_to_6(struct in6_addr *o, u_int32_t ip) {
o->s6_addr32[0] = 0;
o->s6_addr32[1] = 0;
o->s6_addr32[2] = htonl(0xffff);
o->s6_addr32[3] = ip;
}
INLINE u_int32_t in6_to_4(const struct in6_addr *a) {
return a->s6_addr32[3];
}
INLINE void smart_ntop(char *o, struct in6_addr *a, size_t len) {
const char *r;
if (IN6_IS_ADDR_V4MAPPED(a))
r = inet_ntop(AF_INET, &(a->s6_addr32[3]), o, len);
else
r = inet_ntop(AF_INET6, a, o, len);
if (!r)
*o = '\0';
}
INLINE char *smart_ntop_p(char *o, struct in6_addr *a, size_t len) {
int l;
if (IN6_IS_ADDR_V4MAPPED(a)) {
if (inet_ntop(AF_INET, &(a->s6_addr32[3]), o, len))
return o + strlen(o);
*o = '\0';
return NULL;
}
else {
*o = '[';
if (!inet_ntop(AF_INET6, a, o+1, len-2)) {
*o = '\0';
return NULL;
}
l = strlen(o);
o[l] = ']';
o[l+1] = '\0';
return o + (l + 1);
}
}
INLINE void smart_ntop_port(char *o, struct sockaddr_in6 *a, size_t len) {
char *e;
e = smart_ntop_p(o, &a->sin6_addr, len);
if (!e)
return;
if (len - (e - o) < 7)
return;
sprintf(e, ":%hu", ntohs(a->sin6_port));
}
INLINE int smart_pton(int af, char *src, void *dst) {
char *p;
int ret;
if (af == AF_INET6) {
if (src[0] == '[' && (p = strchr(src, ']'))) {
*p = '\0';
ret = inet_pton(af, src+1, dst);
*p = ']';
return ret;
}
}
return inet_pton(af, src, dst);
}
INLINE int pton_46(struct in6_addr *dst, const char *src, int *family) {
u_int32_t in4;
if (inet_pton(AF_INET6, src, dst) == 1) {
if (family)
*family = AF_INET6;
return 0;
}
in4 = inet_addr(src);
if (in4 == INADDR_NONE)
return -1;
in4_to_6(dst, in4);
if (family)
*family = AF_INET;
return 0;
}
INLINE int strmemcmp(const void *mem, int len, const char *str) {
int l = strlen(str);
if (l < len)
return -1;
if (l > len)
return 1;
return memcmp(mem, str, len);
}
/* XXX replace with better source of randomness */
INLINE void random_string(unsigned char *buf, int len) {
while (len--)
*buf++ = random() % 0x100;
}
typedef pthread_mutex_t mutex_t;
typedef pthread_rwlock_t rwlock_t;
typedef pthread_cond_t cond_t;
#define mutex_init(m) __debug_mutex_init(m, __FILE__, __LINE__)
#define mutex_destroy(m) __debug_mutex_destroy(m, __FILE__, __LINE__)
#define mutex_lock(m) __debug_mutex_lock(m, __FILE__, __LINE__)
#define mutex_trylock(m) __debug_mutex_trylock(m, __FILE__, __LINE__)
#define mutex_unlock(m) __debug_mutex_unlock(m, __FILE__, __LINE__)
#define MUTEX_STATIC_INIT PTHREAD_MUTEX_INITIALIZER
#define rwlock_init(l) __debug_rwlock_init(l, __FILE__, __LINE__)
#define rwlock_destroy(l) __debug_rwlock_destroy(l, __FILE__, __LINE__)
#define rwlock_lock_r(l) __debug_rwlock_lock_r(l, __FILE__, __LINE__)
#define rwlock_unlock_r(l) __debug_rwlock_unlock_r(l, __FILE__, __LINE__)
#define rwlock_lock_w(l) __debug_rwlock_lock_w(l, __FILE__, __LINE__)
#define rwlock_unlock_w(l) __debug_rwlock_unlock_w(l, __FILE__, __LINE__)
#define cond_init(c) __debug_cond_init(c, __FILE__, __LINE__)
#define cond_wait(c,m) __debug_cond_wait(c,m, __FILE__, __LINE__)
#define cond_signal(c) __debug_cond_signal(c, __FILE__, __LINE__)
#define cond_broadcast(c) __debug_cond_broadcast(c, __FILE__, __LINE__)
#define COND_STATIC_INIT PTHREAD_COND_INITIALIZER
#ifndef __THREAD_DEBUG
#define __debug_mutex_init(m, F, L) pthread_mutex_init(m, NULL)
#define __debug_mutex_destroy(m, F, L) pthread_mutex_destroy(m)
#define __debug_mutex_lock(m, F, L) pthread_mutex_lock(m)
#define __debug_mutex_trylock(m, F, L) pthread_mutex_trylock(m)
#define __debug_mutex_unlock(m, F, L) pthread_mutex_unlock(m)
#define __debug_rwlock_init(l, F, L) pthread_rwlock_init(l, NULL)
#define __debug_rwlock_destroy(l, F, L) pthread_rwlock_destroy(l)
#define __debug_rwlock_lock_r(l, F, L) pthread_rwlock_rdlock(l)
#define __debug_rwlock_unlock_r(l, F, L) pthread_rwlock_unlock(l)
#define __debug_rwlock_lock_w(l, F, L) pthread_rwlock_wrlock(l)
#define __debug_rwlock_unlock_w(l, F, L) pthread_rwlock_unlock(l)
#define __debug_cond_init(c, F, L) pthread_cond_init(c, NULL)
#define __debug_cond_wait(c, m, F, L) pthread_cond_wait(c,m)
#define __debug_cond_signal(c, F, L) pthread_cond_signal(c)
#define __debug_cond_broadcast(c, F, L) pthread_cond_broadcast(c)
#else
#include "log.h"
INLINE int __debug_mutex_init(mutex_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "mutex_init(%p) at %s:%u", m, file, line);
return pthread_mutex_init(m, NULL);
}
INLINE int __debug_mutex_destroy(mutex_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "mutex_destroy(%p) at %s:%u", m, file, line);
return pthread_mutex_destroy(m);
}
INLINE int __debug_mutex_lock(mutex_t *m, const char *file, unsigned int line) {
int ret;
mylog(LOG_DEBUG, "mutex_lock(%p) at %s:%u ...", m, file, line);
ret = pthread_mutex_lock(m);
mylog(LOG_DEBUG, "mutex_lock(%p) at %s:%u returning %i", m, file, line, ret);
return ret;
}
INLINE int __debug_mutex_trylock(mutex_t *m, const char *file, unsigned int line) {
int ret;
mylog(LOG_DEBUG, "mutex_trylock(%p) at %s:%u ...", m, file, line);
ret = pthread_mutex_trylock(m);
mylog(LOG_DEBUG, "mutex_trylock(%p) at %s:%u returning %i", m, file, line, ret);
return ret;
}
INLINE int __debug_mutex_unlock(mutex_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "mutex_unlock(%p) at %s:%u", m, file, line);
return pthread_mutex_unlock(m);
}
INLINE int __debug_rwlock_init(rwlock_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "rwlock_init(%p) at %s:%u", m, file, line);
return pthread_rwlock_init(m, NULL);
}
INLINE int __debug_rwlock_destroy(rwlock_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "rwlock_destroy(%p) at %s:%u", m, file, line);
return pthread_rwlock_destroy(m);
}
INLINE int __debug_rwlock_lock_r(rwlock_t *m, const char *file, unsigned int line) {
int ret;
mylog(LOG_DEBUG, "rwlock_lock_r(%p) at %s:%u ...", m, file, line);
ret = pthread_rwlock_rdlock(m);
mylog(LOG_DEBUG, "rwlock_lock_r(%p) at %s:%u returning %i", m, file, line, ret);
return ret;
}
INLINE int __debug_rwlock_lock_w(rwlock_t *m, const char *file, unsigned int line) {
int ret;
mylog(LOG_DEBUG, "rwlock_lock_w(%p) at %s:%u ...", m, file, line);
ret = pthread_rwlock_wrlock(m);
mylog(LOG_DEBUG, "rwlock_lock_w(%p) at %s:%u returning %i", m, file, line, ret);
return ret;
}
INLINE int __debug_rwlock_unlock_r(rwlock_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "rwlock_unlock_r(%p) at %s:%u", m, file, line);
return pthread_rwlock_unlock(m);
}
INLINE int __debug_rwlock_unlock_w(rwlock_t *m, const char *file, unsigned int line) {
mylog(LOG_DEBUG, "rwlock_unlock_w(%p) at %s:%u", m, file, line);
return pthread_rwlock_unlock(m);
}
#define __debug_cond_init(c, F, L) pthread_cond_init(c, NULL)
#define __debug_cond_wait(c, m, F, L) pthread_cond_wait(c,m)
#define __debug_cond_signal(c, F, L) pthread_cond_signal(c)
#define __debug_cond_broadcast(c, F, L) pthread_cond_broadcast(c)
#endif
void threads_join_all(int);
void thread_create_detach(void (*)(void *), void *);
INLINE int rlim(int res, rlim_t val) {
struct rlimit rlim;
ZERO(rlim);
rlim.rlim_cur = rlim.rlim_max = val;
return setrlimit(res, &rlim);
}
INLINE int is_addr_unspecified(const struct in6_addr *a) {
if (a->s6_addr32[0])
return 0;
if (a->s6_addr32[1])
return 0;
if (a->s6_addr32[3])
return 0;
if (a->s6_addr32[2] == 0 || a->s6_addr32[2] == htonl(0xffff))
return 1;
return 0;
}
INLINE int family_from_address(const struct in6_addr *a) {
if (IN6_IS_ADDR_V4MAPPED(a))
return AF_INET;
return AF_INET6;
}
/* checks if at least one of the flags is set */
INLINE int bf_isset(const unsigned int *u, unsigned int f) {
if ((*u & f))
return -1;
return 0;
}
INLINE void bf_set(unsigned int *u, unsigned int f) {
*u |= f;
}
INLINE void bf_clear(unsigned int *u, unsigned int f) {
*u &= ~f;
}
INLINE void bf_xset(unsigned int *u, unsigned int f, int cond) {
bf_clear(u, f);
bf_set(u, cond ? f : 0);
}
/* works only for single flags */
INLINE void bf_copy(unsigned int *u, unsigned int f, const unsigned int *s, unsigned int g) {
/* a good compiler will optimize out the calls to log2() */
*u &= ~f;
if (f >= g)
*u |= (*s & g) << (int) (log2(f) - log2(g));
else
*u |= (*s & g) >> (int) (log2(g) - log2(f));
}
/* works for multiple flags */
INLINE void bf_copy_same(unsigned int *u, const unsigned int *s, unsigned int g) {
bf_copy(u, g, s, g);
}
INLINE void g_queue_append(GQueue *dst, const GQueue *src) {
GList *l;
if (!src || !dst)
return;
for (l = src->head; l; l = l->next)
g_queue_push_tail(dst, l->data);
}
#endif