|
|
|
|
@ -16,9 +16,6 @@
|
|
|
|
|
#include "call.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *cookie_in_use = "MAGIC";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void control_udp_closed(int fd, void *p, uintptr_t x) {
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
@ -95,41 +92,13 @@ next:
|
|
|
|
|
|
|
|
|
|
pcre_get_substring_list(buf, ovec, ret, &out);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&u->lock);
|
|
|
|
|
if (poller_now - u->oven_time >= 30) {
|
|
|
|
|
g_hash_table_remove_all(u->stale_cookies);
|
|
|
|
|
#if GLIB_CHECK_VERSION(2,14,0)
|
|
|
|
|
g_string_chunk_clear(u->stale_chunks);
|
|
|
|
|
swap_ptrs(&u->stale_chunks, &u->fresh_chunks);
|
|
|
|
|
#else
|
|
|
|
|
g_string_chunk_free(u->stale_chunks);
|
|
|
|
|
u->stale_chunks = u->fresh_chunks;
|
|
|
|
|
u->fresh_chunks = g_string_chunk_new(4 * 1024);
|
|
|
|
|
#endif
|
|
|
|
|
swap_ptrs(&u->stale_cookies, &u->fresh_cookies);
|
|
|
|
|
u->oven_time = poller_now; /* baked new cookies! */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
|
/* XXX better hashing */
|
|
|
|
|
reply = g_hash_table_lookup(u->fresh_cookies, out[RE_UDP_COOKIE]);
|
|
|
|
|
if (!reply)
|
|
|
|
|
reply = g_hash_table_lookup(u->stale_cookies, out[RE_UDP_COOKIE]);
|
|
|
|
|
reply = cookie_cache_lookup(&u->cookie_cache, out[RE_UDP_COOKIE]);
|
|
|
|
|
if (reply) {
|
|
|
|
|
if (reply == cookie_in_use) {
|
|
|
|
|
/* another thread is working on this right now */
|
|
|
|
|
cond_wait(&u->cond, &u->lock);
|
|
|
|
|
goto restart;
|
|
|
|
|
}
|
|
|
|
|
mutex_unlock(&u->lock);
|
|
|
|
|
mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin.sin6_port));
|
|
|
|
|
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_hash_table_replace(u->fresh_cookies, (void *) out[RE_UDP_COOKIE], (void *) cookie_in_use);
|
|
|
|
|
mutex_unlock(&u->lock);
|
|
|
|
|
|
|
|
|
|
if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U')
|
|
|
|
|
reply = call_update_udp(out, u->callmaster);
|
|
|
|
|
else if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L')
|
|
|
|
|
@ -171,22 +140,13 @@ restart:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reply) {
|
|
|
|
|
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len);
|
|
|
|
|
mutex_lock(&u->lock);
|
|
|
|
|
g_hash_table_replace(u->fresh_cookies, g_string_chunk_insert(u->fresh_chunks, out[RE_UDP_COOKIE]),
|
|
|
|
|
g_string_chunk_insert(u->fresh_chunks, reply));
|
|
|
|
|
g_hash_table_remove(u->stale_cookies, out[RE_UDP_COOKIE]);
|
|
|
|
|
cond_broadcast(&u->cond);
|
|
|
|
|
mutex_unlock(&u->lock);
|
|
|
|
|
len = strlen(reply);
|
|
|
|
|
sendto(fd, reply, len, 0, (struct sockaddr *) &sin, sin_len);
|
|
|
|
|
cookie_cache_insert(&u->cookie_cache, out[RE_UDP_COOKIE], reply, len);
|
|
|
|
|
free(reply);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
mutex_lock(&u->lock);
|
|
|
|
|
g_hash_table_remove(u->fresh_cookies, out[RE_UDP_COOKIE]);
|
|
|
|
|
g_hash_table_remove(u->stale_cookies, out[RE_UDP_COOKIE]);
|
|
|
|
|
cond_broadcast(&u->cond);
|
|
|
|
|
mutex_unlock(&u->lock);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cookie_cache_remove(&u->cookie_cache, out[RE_UDP_COOKIE]);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
pcre_free(out);
|
|
|
|
|
@ -225,13 +185,6 @@ struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int1
|
|
|
|
|
c->fd = fd;
|
|
|
|
|
c->poller = p;
|
|
|
|
|
c->callmaster = m;
|
|
|
|
|
c->fresh_cookies = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
|
c->stale_cookies = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
|
c->fresh_chunks = g_string_chunk_new(4 * 1024);
|
|
|
|
|
c->stale_chunks = g_string_chunk_new(4 * 1024);
|
|
|
|
|
c->oven_time = poller_now;
|
|
|
|
|
mutex_init(&c->lock);
|
|
|
|
|
cond_init(&c->cond);
|
|
|
|
|
c->parse_re = pcre_compile(
|
|
|
|
|
/* cookie cmd flags callid viabranch:5 */
|
|
|
|
|
"^(\\S+)\\s+(?:([ul])(\\S*)\\s+([^;]+)(?:;(\\S+))?\\s+" \
|
|
|
|
|
@ -251,6 +204,8 @@ struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int1
|
|
|
|
|
if (!c->parse_re || !c->fallback_re)
|
|
|
|
|
goto fail2;
|
|
|
|
|
|
|
|
|
|
cookie_cache_init(&c->cookie_cache);
|
|
|
|
|
|
|
|
|
|
ZERO(i);
|
|
|
|
|
i.fd = fd;
|
|
|
|
|
i.closed = control_udp_closed;
|
|
|
|
|
|