|
|
|
@ -34,12 +34,12 @@
|
|
|
|
|
#define DBG(x...) ((void)0)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define LOG_PREFIX_C "[%s] "
|
|
|
|
|
#define LOG_PREFIX_CI "[%s - %s] "
|
|
|
|
|
#define LOG_PARAMS_C(c) (c)->callid
|
|
|
|
|
#define LOG_PARAMS_CI(c) (c)->callid, log_info
|
|
|
|
|
#define LOG_PREFIX_C "[%.*s] "
|
|
|
|
|
#define LOG_PREFIX_CI "[%.*s - %.*s] "
|
|
|
|
|
#define LOG_PARAMS_C(c) STR_FMT(&(c)->callid)
|
|
|
|
|
#define LOG_PARAMS_CI(c) STR_FMT(&(c)->callid), STR_FMT(log_info)
|
|
|
|
|
|
|
|
|
|
static __thread const char *log_info;
|
|
|
|
|
static __thread const str *log_info;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -436,7 +436,7 @@ out:
|
|
|
|
|
static int info_parse_func(char **a, void **ret, void *p) {
|
|
|
|
|
struct call *c = p;
|
|
|
|
|
|
|
|
|
|
g_hash_table_replace(c->infohash, call_strdup(c, a[0]), call_strdup(c, a[1]));
|
|
|
|
|
g_hash_table_replace(c->infohash, call_strdup(c, a[0]), call_str_init_dup(c, a[1]));
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@ -573,9 +573,12 @@ void xmlrpc_kill_calls(void *p) {
|
|
|
|
|
sigset_t ss;
|
|
|
|
|
int i = 0;
|
|
|
|
|
int status;
|
|
|
|
|
str *tag;
|
|
|
|
|
|
|
|
|
|
while (xh->tags) {
|
|
|
|
|
mylog(LOG_INFO, "Forking child to close call with tag %s via XMLRPC", (char *) xh->tags->data);
|
|
|
|
|
tag = xh->tags->data;
|
|
|
|
|
|
|
|
|
|
mylog(LOG_INFO, "Forking child to close call with tag %.*s via XMLRPC", STR_FMT(tag));
|
|
|
|
|
pid = fork();
|
|
|
|
|
|
|
|
|
|
if (pid) {
|
|
|
|
@ -604,7 +607,7 @@ retry:
|
|
|
|
|
close(i);
|
|
|
|
|
|
|
|
|
|
openlog("mediaproxy-ng/child", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
|
|
|
mylog(LOG_INFO, "Initiating XMLRPC call for tag %s", (char *) xh->tags->data);
|
|
|
|
|
mylog(LOG_INFO, "Initiating XMLRPC call for tag %.*s", STR_FMT(tag));
|
|
|
|
|
|
|
|
|
|
alarm(5);
|
|
|
|
|
|
|
|
|
@ -617,7 +620,7 @@ retry:
|
|
|
|
|
|
|
|
|
|
r = NULL;
|
|
|
|
|
xmlrpc_client_call2f(&e, c, xh->url, "di", &r, "(ssss)",
|
|
|
|
|
"sbc", "postControlCmd", xh->tags->data, "teardown");
|
|
|
|
|
"sbc", "postControlCmd", tag->s, "teardown");
|
|
|
|
|
if (r)
|
|
|
|
|
xmlrpc_DECREF(r);
|
|
|
|
|
if (e.fault_occurred)
|
|
|
|
@ -668,9 +671,9 @@ void kill_calls_timer(GSList *list, struct callmaster *m) {
|
|
|
|
|
for (csl = ca->callstreams->head; csl; csl = csl->next) {
|
|
|
|
|
cs = csl->data;
|
|
|
|
|
mutex_lock(&cs->lock);
|
|
|
|
|
if (!cs->peers[1].tag || !*cs->peers[1].tag)
|
|
|
|
|
if (!cs->peers[1].tag.s || !cs->peers[1].tag.len)
|
|
|
|
|
goto next;
|
|
|
|
|
xh->tags = g_slist_prepend(xh->tags, g_string_chunk_insert(xh->c, cs->peers[1].tag));
|
|
|
|
|
xh->tags = g_slist_prepend(xh->tags, str_chunk_insert(xh->c, &cs->peers[1].tag));
|
|
|
|
|
next:
|
|
|
|
|
mutex_unlock(&cs->lock);
|
|
|
|
|
}
|
|
|
|
@ -774,7 +777,7 @@ struct callmaster *callmaster_new(struct poller *p) {
|
|
|
|
|
|
|
|
|
|
c = obj_alloc0("callmaster", sizeof(*c), NULL);
|
|
|
|
|
|
|
|
|
|
c->callhash = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
|
c->callhash = g_hash_table_new(str_hash, str_equal);
|
|
|
|
|
if (!c->callhash)
|
|
|
|
|
goto fail;
|
|
|
|
|
c->poller = p;
|
|
|
|
@ -987,7 +990,7 @@ fail:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* caller is responsible for appropriate locking */
|
|
|
|
|
static int setup_peer(struct peer *p, struct stream *s, const char *tag) {
|
|
|
|
|
static int setup_peer(struct peer *p, struct stream *s, const str *tag) {
|
|
|
|
|
struct streamrelay *a, *b;
|
|
|
|
|
struct callstream *cs;
|
|
|
|
|
struct call *ca;
|
|
|
|
@ -1027,7 +1030,7 @@ static int setup_peer(struct peer *p, struct stream *s, const char *tag) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p->mediatype = call_strdup(ca, s->mediatype);
|
|
|
|
|
p->tag = call_strdup(ca, tag);
|
|
|
|
|
call_str_cpy(ca, &p->tag, tag);
|
|
|
|
|
p->filled = 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@ -1061,7 +1064,7 @@ static void steal_peer(struct peer *dest, struct peer *src) {
|
|
|
|
|
dest->mediatype = src->mediatype;
|
|
|
|
|
dest->tag = src->tag;
|
|
|
|
|
src->mediatype = "";
|
|
|
|
|
src->tag = "";
|
|
|
|
|
src->tag = STR_NULL;
|
|
|
|
|
//dest->kernelized = src->kernelized;
|
|
|
|
|
//src->kernelized = 0;
|
|
|
|
|
dest->desired_family = src->desired_family;
|
|
|
|
@ -1122,7 +1125,7 @@ void callstream_init(struct callstream *s, int port1, int port2) {
|
|
|
|
|
|
|
|
|
|
p->idx = i;
|
|
|
|
|
p->up = s;
|
|
|
|
|
p->tag = "";
|
|
|
|
|
p->tag = STR_NULL;
|
|
|
|
|
p->mediatype = "";
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
@ -1175,7 +1178,7 @@ static void callstream_free(void *ptr) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* called with call->lock held */
|
|
|
|
|
static int call_streams(struct call *c, GQueue *s, const char *tag, int opmode) {
|
|
|
|
|
static int call_streams(struct call *c, GQueue *s, const str *tag, int opmode) {
|
|
|
|
|
GQueue *q;
|
|
|
|
|
GList *i, *l;
|
|
|
|
|
struct stream *t;
|
|
|
|
@ -1187,9 +1190,6 @@ static int call_streams(struct call *c, GQueue *s, const char *tag, int opmode)
|
|
|
|
|
|
|
|
|
|
q = g_queue_new(); /* new callstreams list */
|
|
|
|
|
|
|
|
|
|
if (!tag)
|
|
|
|
|
tag = "";
|
|
|
|
|
|
|
|
|
|
for (i = s->head; i; i = i->next) {
|
|
|
|
|
t = i->data;
|
|
|
|
|
|
|
|
|
@ -1201,15 +1201,15 @@ static int call_streams(struct call *c, GQueue *s, const char *tag, int opmode)
|
|
|
|
|
mutex_lock(&cs_o->lock);
|
|
|
|
|
for (x = 0; x < 2; x++) {
|
|
|
|
|
r = &cs_o->peers[x].rtps[0];
|
|
|
|
|
DBG("comparing new ["IP6F"]:%u/%s to old ["IP6F"]:%u/%s",
|
|
|
|
|
IP6P(&t->ip46), t->port, tag,
|
|
|
|
|
IP6P(&r->peer_advertised.ip46), r->peer_advertised.port, cs_o->peers[x].tag);
|
|
|
|
|
DBG("comparing new ["IP6F"]:%u/%.*s to old ["IP6F"]:%u/%.*s",
|
|
|
|
|
IP6P(&t->ip46), t->port, STR_FMT(tag),
|
|
|
|
|
IP6P(&r->peer_advertised.ip46), r->peer_advertised.port, STR_FMT(&cs_o->peers[x].tag));
|
|
|
|
|
|
|
|
|
|
if (!IN6_ARE_ADDR_EQUAL(&r->peer_advertised.ip46, &t->ip46))
|
|
|
|
|
continue;
|
|
|
|
|
if (r->peer_advertised.port != t->port)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(cs_o->peers[x].tag, tag))
|
|
|
|
|
if (str_cmp_str0(&cs_o->peers[x].tag, tag))
|
|
|
|
|
continue;
|
|
|
|
|
DBG("found existing call stream to steal");
|
|
|
|
|
goto found;
|
|
|
|
@ -1405,7 +1405,7 @@ static void call_destroy(struct call *c) {
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
rwlock_lock_w(&m->hashlock);
|
|
|
|
|
ret = g_hash_table_remove(m->callhash, c->callid);
|
|
|
|
|
ret = g_hash_table_remove(m->callhash, &c->callid);
|
|
|
|
|
rwlock_unlock_w(&m->hashlock);
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
@ -1418,7 +1418,7 @@ static void call_destroy(struct call *c) {
|
|
|
|
|
|
|
|
|
|
mutex_lock(&c->lock);
|
|
|
|
|
/* at this point, no more callstreams can be added */
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Final packet stats:", c->callid);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Final packet stats:", LOG_PARAMS_C(c));
|
|
|
|
|
while (c->callstreams->head) {
|
|
|
|
|
s = g_queue_pop_head(c->callstreams);
|
|
|
|
|
mutex_unlock(&c->lock);
|
|
|
|
@ -1431,7 +1431,7 @@ static void call_destroy(struct call *c) {
|
|
|
|
|
"side B: "
|
|
|
|
|
"RTP[%u] %lu p, %lu b, %lu e; "
|
|
|
|
|
"RTCP[%u] %lu p, %lu b, %lu e",
|
|
|
|
|
c->callid,
|
|
|
|
|
LOG_PARAMS_C(c),
|
|
|
|
|
s->peers[0].rtps[0].localport, s->peers[0].rtps[0].stats.packets,
|
|
|
|
|
s->peers[0].rtps[0].stats.bytes, s->peers[0].rtps[0].stats.errors,
|
|
|
|
|
s->peers[0].rtps[1].localport, s->peers[0].rtps[1].stats.packets,
|
|
|
|
@ -1514,23 +1514,6 @@ out:
|
|
|
|
|
return g_string_free_str(o);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean g_str_equal0(gconstpointer a, gconstpointer b) {
|
|
|
|
|
if (!a) {
|
|
|
|
|
if (!b)
|
|
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (!b)
|
|
|
|
|
return FALSE;
|
|
|
|
|
return g_str_equal(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint g_str_hash0(gconstpointer v) {
|
|
|
|
|
if (!v)
|
|
|
|
|
return 0;
|
|
|
|
|
return g_str_hash(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void call_free(void *p) {
|
|
|
|
|
struct call *c = p;
|
|
|
|
|
|
|
|
|
@ -1542,26 +1525,26 @@ static void call_free(void *p) {
|
|
|
|
|
g_string_chunk_free(c->chunk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct call *call_create(const char *callid, struct callmaster *m) {
|
|
|
|
|
static struct call *call_create(const str *callid, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
|
|
|
|
|
mylog(LOG_NOTICE, LOG_PREFIX_C "Creating new call",
|
|
|
|
|
callid); /* XXX will spam syslog on recovery from DB */
|
|
|
|
|
STR_FMT(callid)); /* XXX will spam syslog on recovery from DB */
|
|
|
|
|
c = obj_alloc0("call", sizeof(*c), call_free);
|
|
|
|
|
c->callmaster = m;
|
|
|
|
|
c->chunk = g_string_chunk_new(256);
|
|
|
|
|
mutex_init(&c->chunk_lock);
|
|
|
|
|
c->callid = call_strdup(c, callid);
|
|
|
|
|
call_str_cpy(c, &c->callid, callid);
|
|
|
|
|
c->callstreams = g_queue_new();
|
|
|
|
|
c->created = poller_now;
|
|
|
|
|
c->infohash = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
|
c->branches = g_hash_table_new(g_str_hash0, g_str_equal0);
|
|
|
|
|
c->branches = g_hash_table_new(str_hash, str_equal);
|
|
|
|
|
mutex_init(&c->lock);
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns call with lock held */
|
|
|
|
|
struct call *call_get_or_create(const char *callid, const char *viabranch, struct callmaster *m) {
|
|
|
|
|
struct call *call_get_or_create(const str *callid, const str *viabranch, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
@ -1578,7 +1561,7 @@ restart:
|
|
|
|
|
obj_put(c);
|
|
|
|
|
goto restart;
|
|
|
|
|
}
|
|
|
|
|
g_hash_table_insert(m->callhash, c->callid, obj_get(c));
|
|
|
|
|
g_hash_table_insert(m->callhash, &c->callid, obj_get(c));
|
|
|
|
|
mutex_lock(&c->lock);
|
|
|
|
|
rwlock_unlock_w(&m->hashlock);
|
|
|
|
|
}
|
|
|
|
@ -1588,14 +1571,15 @@ restart:
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (viabranch && *viabranch && !g_hash_table_lookup(c->branches, viabranch))
|
|
|
|
|
g_hash_table_insert(c->branches, call_strdup(c, viabranch),
|
|
|
|
|
if (viabranch && viabranch->s && viabranch->len
|
|
|
|
|
&& !g_hash_table_lookup(c->branches, viabranch))
|
|
|
|
|
g_hash_table_insert(c->branches, call_str_dup(c, viabranch),
|
|
|
|
|
(void *) 0x1);
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int addr_parse_udp(struct stream *st, const char **out) {
|
|
|
|
|
static int addr_parse_udp(struct stream *st, char **out) {
|
|
|
|
|
u_int32_t ip4;
|
|
|
|
|
const char *cp;
|
|
|
|
|
char c;
|
|
|
|
@ -1641,22 +1625,26 @@ fail:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_update_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_update_udp(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
GQueue q = G_QUEUE_INIT;
|
|
|
|
|
struct stream st;
|
|
|
|
|
int num;
|
|
|
|
|
str *ret;
|
|
|
|
|
str *ret, callid, viabranch, fromtag;
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_UDP_UL_CALLID]);
|
|
|
|
|
str_init(&viabranch, out[RE_UDP_UL_VIABRANCH]);
|
|
|
|
|
str_init(&fromtag, out[RE_UDP_UL_FROMTAG]);
|
|
|
|
|
|
|
|
|
|
c = call_get_or_create(out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH], m);
|
|
|
|
|
log_info = out[RE_UDP_UL_VIABRANCH];
|
|
|
|
|
c = call_get_or_create(&callid, &viabranch, m);
|
|
|
|
|
log_info = &viabranch;
|
|
|
|
|
c->calling_agent = "UNKNOWN(udp)";
|
|
|
|
|
|
|
|
|
|
if (addr_parse_udp(&st, out))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
g_queue_push_tail(&q, &st);
|
|
|
|
|
num = call_streams(c, &q, out[RE_UDP_UL_FROMTAG], 0);
|
|
|
|
|
num = call_streams(c, &q, &fromtag, 0);
|
|
|
|
|
g_queue_clear(&q);
|
|
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 0 : 1, out[RE_UDP_COOKIE], 1);
|
|
|
|
@ -1679,22 +1667,23 @@ fail:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_lookup_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_lookup_udp(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
GQueue q = G_QUEUE_INIT;
|
|
|
|
|
struct stream st;
|
|
|
|
|
int num;
|
|
|
|
|
str *ret;
|
|
|
|
|
const char *branch;
|
|
|
|
|
str *ret, callid, branch, totag;
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_UDP_UL_CALLID]);
|
|
|
|
|
str_init(&branch, out[RE_UDP_UL_VIABRANCH]);
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_UL_CALLID]);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, &callid);
|
|
|
|
|
if (c)
|
|
|
|
|
mutex_lock(&c->lock);
|
|
|
|
|
else {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_CI "Got UDP LOOKUP for unknown call-id or unknown via-branch",
|
|
|
|
|
out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH]);
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_CI "Got UDP LOOKUP for unknown call-id",
|
|
|
|
|
STR_FMT(&callid), STR_FMT(&branch));
|
|
|
|
|
ret = str_sprintf("%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->conf.ipv4));
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
@ -1702,19 +1691,19 @@ str *call_lookup_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
obj_hold(c);
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
|
|
|
|
|
branch = out[RE_UDP_UL_VIABRANCH];
|
|
|
|
|
if (branch && *branch && !g_hash_table_lookup(c->branches, branch))
|
|
|
|
|
g_hash_table_insert(c->branches, call_strdup(c, branch),
|
|
|
|
|
if (branch.s && branch.len && !g_hash_table_lookup(c->branches, &branch))
|
|
|
|
|
g_hash_table_insert(c->branches, call_str_dup(c, &branch),
|
|
|
|
|
(void *) 0x1);
|
|
|
|
|
|
|
|
|
|
log_info = branch;
|
|
|
|
|
log_info = &branch;
|
|
|
|
|
c->called_agent = "UNKNOWN(udp)";
|
|
|
|
|
|
|
|
|
|
if (addr_parse_udp(&st, out))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
g_queue_push_tail(&q, &st);
|
|
|
|
|
num = call_streams(c, &q, out[RE_UDP_UL_TOTAG], 1);
|
|
|
|
|
str_init(&totag, out[RE_UDP_UL_TOTAG]);
|
|
|
|
|
num = call_streams(c, &q, &totag, 1);
|
|
|
|
|
g_queue_clear(&q);
|
|
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 1 : 0, out[RE_UDP_COOKIE], 1);
|
|
|
|
@ -1737,13 +1726,14 @@ fail:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_request(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_request(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
GQueue s = G_QUEUE_INIT;
|
|
|
|
|
int num;
|
|
|
|
|
str *ret;
|
|
|
|
|
str *ret, callid;
|
|
|
|
|
|
|
|
|
|
c = call_get_or_create(out[RE_TCP_RL_CALLID], NULL, m);
|
|
|
|
|
str_init(&callid, out[RE_TCP_RL_CALLID]);
|
|
|
|
|
c = call_get_or_create(&callid, NULL, m);
|
|
|
|
|
|
|
|
|
|
c->calling_agent = (out[RE_TCP_RL_AGENT] && *out[RE_TCP_RL_AGENT])
|
|
|
|
|
? call_strdup(c, out[RE_TCP_RL_AGENT]) : "UNKNOWN";
|
|
|
|
@ -1762,17 +1752,18 @@ str *call_request(const char **out, struct callmaster *m) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_lookup(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_lookup(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
GQueue s = G_QUEUE_INIT;
|
|
|
|
|
int num;
|
|
|
|
|
str *ret;
|
|
|
|
|
str *ret, callid;
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_TCP_RL_CALLID]);
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_TCP_RL_CALLID]);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, &callid);
|
|
|
|
|
if (!c) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_C "Got LOOKUP for unknown call-id", out[RE_TCP_RL_CALLID]);
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_C "Got LOOKUP for unknown call-id", STR_FMT(&callid));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
obj_hold(c);
|
|
|
|
@ -1796,9 +1787,9 @@ str *call_lookup(const char **out, struct callmaster *m) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_delete_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_delete_udp(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
str *ret;
|
|
|
|
|
str *ret, callid, branch;
|
|
|
|
|
struct callstream *cs;
|
|
|
|
|
GList *l;
|
|
|
|
|
int i;
|
|
|
|
@ -1807,18 +1798,20 @@ str *call_delete_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
DBG("got delete for callid '%s' and viabranch '%s'",
|
|
|
|
|
out[RE_UDP_DQ_CALLID], out[RE_UDP_DQ_VIABRANCH]);
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
str_init(&branch, out[RE_UDP_DQ_VIABRANCH]);
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, &callid);
|
|
|
|
|
if (!c) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", STR_FMT(&callid));
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
obj_hold(c);
|
|
|
|
|
mutex_lock(&c->lock);
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
|
|
|
|
|
log_info = out[RE_UDP_DQ_VIABRANCH];
|
|
|
|
|
log_info = &branch;
|
|
|
|
|
|
|
|
|
|
if (out[RE_UDP_DQ_FROMTAG] && *out[RE_UDP_DQ_FROMTAG]) {
|
|
|
|
|
for (l = c->callstreams->head; l; l = l->next) {
|
|
|
|
@ -1827,17 +1820,13 @@ str *call_delete_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
|
p = &cs->peers[i];
|
|
|
|
|
if (!p->tag)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(p->tag, out[RE_UDP_DQ_FROMTAG]))
|
|
|
|
|
if (str_cmp(&p->tag, out[RE_UDP_DQ_FROMTAG]))
|
|
|
|
|
continue;
|
|
|
|
|
if (!out[RE_UDP_DQ_TOTAG] || !*out[RE_UDP_DQ_TOTAG])
|
|
|
|
|
goto tag_match;
|
|
|
|
|
|
|
|
|
|
px = &cs->peers[i ^ 1];
|
|
|
|
|
if (!px->tag)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(px->tag, out[RE_UDP_DQ_TOTAG]))
|
|
|
|
|
if (str_cmp(&px->tag, out[RE_UDP_DQ_TOTAG]))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
goto tag_match;
|
|
|
|
@ -1847,15 +1836,15 @@ str *call_delete_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Tags didn't match for delete message, ignoring", c->callid);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Tags didn't match for delete message, ignoring", LOG_PARAMS_C(c));
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
tag_match:
|
|
|
|
|
mutex_unlock(&cs->lock);
|
|
|
|
|
|
|
|
|
|
if (out[RE_UDP_DQ_VIABRANCH] && *out[RE_UDP_DQ_VIABRANCH]) {
|
|
|
|
|
if (!g_hash_table_remove(c->branches, out[RE_UDP_DQ_VIABRANCH])) {
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Branch to delete doesn't exist", c->callid, out[RE_UDP_DQ_VIABRANCH]);
|
|
|
|
|
if (branch.s && branch.len) {
|
|
|
|
|
if (!g_hash_table_remove(c->branches, &branch)) {
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Branch to delete doesn't exist", STR_FMT(&c->callid), STR_FMT(&branch));
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1867,7 +1856,7 @@ tag_match:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_unlock(&c->lock);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Deleting full call", c->callid);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Deleting full call", LOG_PARAMS_C(c));
|
|
|
|
|
call_destroy(c);
|
|
|
|
|
goto success;
|
|
|
|
|
|
|
|
|
@ -1890,9 +1879,9 @@ out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str *call_query_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
str *call_query_udp(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
str *ret;
|
|
|
|
|
str *ret, callid;
|
|
|
|
|
struct callstream *cs;
|
|
|
|
|
long long unsigned int pcs[4] = {0,0,0,0};
|
|
|
|
|
time_t newest = 0;
|
|
|
|
@ -1902,11 +1891,12 @@ str *call_query_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
|
|
|
|
|
DBG("got query for callid '%s'", out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, &callid);
|
|
|
|
|
if (!c) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to query not found", out[RE_UDP_DQ_CALLID]);
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to query not found", STR_FMT(&callid));
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
obj_hold(c);
|
|
|
|
@ -1929,16 +1919,12 @@ str *call_query_udp(const char **out, struct callmaster *m) {
|
|
|
|
|
if (!out[RE_UDP_DQ_FROMTAG] || !*out[RE_UDP_DQ_FROMTAG])
|
|
|
|
|
goto tag_match;
|
|
|
|
|
|
|
|
|
|
if (!p->tag)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(p->tag, out[RE_UDP_DQ_FROMTAG]))
|
|
|
|
|
if (str_cmp(&p->tag, out[RE_UDP_DQ_FROMTAG]))
|
|
|
|
|
continue;
|
|
|
|
|
if (!out[RE_UDP_DQ_TOTAG] || !*out[RE_UDP_DQ_TOTAG])
|
|
|
|
|
goto tag_match;
|
|
|
|
|
|
|
|
|
|
if (!px->tag)
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp(px->tag, out[RE_UDP_DQ_TOTAG]))
|
|
|
|
|
if (str_cmp(&px->tag, out[RE_UDP_DQ_TOTAG]))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
tag_match:
|
|
|
|
@ -1970,11 +1956,13 @@ out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void call_delete(const char **out, struct callmaster *m) {
|
|
|
|
|
void call_delete(char **out, struct callmaster *m) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
str callid;
|
|
|
|
|
|
|
|
|
|
str_init(&callid, out[RE_TCP_D_CALLID]);
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_TCP_D_CALLID]);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, &callid);
|
|
|
|
|
if (!c) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
return;
|
|
|
|
@ -1997,14 +1985,15 @@ static void call_status_iterator(struct call *c, struct control_stream *s) {
|
|
|
|
|
struct streamrelay *rx1, *rx2;
|
|
|
|
|
struct callmaster *m;
|
|
|
|
|
char addr1[64], addr2[64], addr3[64];
|
|
|
|
|
str *from, *to;
|
|
|
|
|
|
|
|
|
|
m = c->callmaster;
|
|
|
|
|
mutex_lock(&c->lock);
|
|
|
|
|
|
|
|
|
|
control_stream_printf(s, "session %s %s %s %s %s %i\n",
|
|
|
|
|
c->callid,
|
|
|
|
|
(char *) g_hash_table_lookup(c->infohash, "from"),
|
|
|
|
|
(char *) g_hash_table_lookup(c->infohash, "to"),
|
|
|
|
|
from = g_hash_table_lookup(c->infohash, "from");
|
|
|
|
|
to = g_hash_table_lookup(c->infohash, "to");
|
|
|
|
|
control_stream_printf(s, "session %.*s %.*s %.*s %s %s %i\n",
|
|
|
|
|
STR_FMT(&c->callid), STR_FMT(from), STR_FMT(to),
|
|
|
|
|
c->calling_agent, c->called_agent,
|
|
|
|
|
(int) (poller_now - c->created));
|
|
|
|
|
|
|
|
|
@ -2113,14 +2102,18 @@ struct callstream *callstream_new(struct call *ca, int num) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *call_offer(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) {
|
|
|
|
|
str sdp;
|
|
|
|
|
str sdp, fromtag;
|
|
|
|
|
char *errstr;
|
|
|
|
|
GQueue parsed = G_QUEUE_INIT;
|
|
|
|
|
GQueue streams = G_QUEUE_INIT;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
bencode_dictionary_get_str(input, "sdp", &sdp);
|
|
|
|
|
if (!sdp.s)
|
|
|
|
|
return "No SDP body in message";
|
|
|
|
|
bencode_dictionary_get_str(input, "from-tag", &fromtag);
|
|
|
|
|
if (!fromtag.s)
|
|
|
|
|
return "No from-tag in message";
|
|
|
|
|
|
|
|
|
|
if (sdp_parse(&sdp, &parsed))
|
|
|
|
|
return "Failed to parse SDP";
|
|
|
|
|