|
|
|
@ -440,40 +440,45 @@ static void call_timer_iterator(void *key, void *val, void *ptr) { |
|
|
|
struct callmaster *cm; |
|
|
|
unsigned int check; |
|
|
|
|
|
|
|
if (!c->callstreams->head) |
|
|
|
goto drop; |
|
|
|
while(c) { |
|
|
|
|
|
|
|
cm = c->callmaster; |
|
|
|
po = cm->poller; |
|
|
|
if (!c->callstreams->head) |
|
|
|
goto drop; |
|
|
|
|
|
|
|
for (it = c->callstreams->head; it; it = it->next) { |
|
|
|
cs = it->data; |
|
|
|
cm = c->callmaster; |
|
|
|
po = cm->poller; |
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) { |
|
|
|
p = &cs->peers[i]; |
|
|
|
for (it = c->callstreams->head; it; it = it->next) { |
|
|
|
cs = it->data; |
|
|
|
|
|
|
|
hlp->ports[p->rtps[0].localport] = &p->rtps[0]; |
|
|
|
hlp->ports[p->rtps[1].localport] = &p->rtps[1]; |
|
|
|
for (i = 0; i < 2; i++) { |
|
|
|
p = &cs->peers[i]; |
|
|
|
|
|
|
|
check = cm->timeout; |
|
|
|
if (!p->rtps[0].peer.port) |
|
|
|
check = cm->silent_timeout; |
|
|
|
else if (IN6_IS_ADDR_UNSPECIFIED(&p->rtps[0].peer.ip46)) |
|
|
|
check = cm->silent_timeout; |
|
|
|
hlp->ports[p->rtps[0].localport] = &p->rtps[0]; |
|
|
|
hlp->ports[p->rtps[1].localport] = &p->rtps[1]; |
|
|
|
|
|
|
|
if (po->now - p->rtps[0].last < check) |
|
|
|
goto good; |
|
|
|
check = cm->timeout; |
|
|
|
if (!p->rtps[0].peer.port) |
|
|
|
check = cm->silent_timeout; |
|
|
|
else if (IN6_IS_ADDR_UNSPECIFIED(&p->rtps[0].peer.ip46)) |
|
|
|
check = cm->silent_timeout; |
|
|
|
|
|
|
|
if (po->now - p->rtps[0].last < check) |
|
|
|
goto good; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
mylog(LOG_INFO, "[%s] Closing call due to timeout", c->callid); |
|
|
|
mylog(LOG_INFO, "[%s - %s] Closing call branch due to timeout", |
|
|
|
c->callid, c->viabranch ? c->viabranch : "<none>"); |
|
|
|
|
|
|
|
drop: |
|
|
|
hlp->del = g_list_prepend(hlp->del, c); |
|
|
|
return; |
|
|
|
drop: |
|
|
|
hlp->del = g_list_prepend(hlp->del, c); |
|
|
|
c = c->next; |
|
|
|
continue; |
|
|
|
|
|
|
|
good: |
|
|
|
; |
|
|
|
good: |
|
|
|
c = c->next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -528,6 +533,7 @@ next: |
|
|
|
for (i = hlp.del; i; i = n) { |
|
|
|
n = i->next; |
|
|
|
c = i->data; |
|
|
|
c->prev->next = c->next; |
|
|
|
call_destroy(c); |
|
|
|
g_list_free_1(i); |
|
|
|
} |
|
|
|
@ -899,12 +905,6 @@ static int call_streams(struct call *c, GQueue *s, const char *tag, int opmode) |
|
|
|
|
|
|
|
p = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* look for an existing call stream with identical parameters */ |
|
|
|
for (l = c->callstreams->head; l; l = l->next) { |
|
|
|
cs_o = l->data; |
|
|
|
@ -1106,6 +1106,7 @@ static void call_destroy(struct call *c) { |
|
|
|
|
|
|
|
g_hash_table_remove(m->callhash, c->callid); |
|
|
|
#ifndef NO_REDIS |
|
|
|
/* TODO: take into account the viabranch */ |
|
|
|
redis_delete(c); |
|
|
|
#endif |
|
|
|
|
|
|
|
@ -1191,23 +1192,48 @@ out: |
|
|
|
return g_string_free(o, FALSE); |
|
|
|
} |
|
|
|
|
|
|
|
static struct call *call_create(const char *callid, const char *viabranch, struct callmaster *m) { |
|
|
|
struct call *c; |
|
|
|
|
|
|
|
mylog(LOG_NOTICE, "[%s] Creating new call for viabranch %s", |
|
|
|
callid, (viabranch ? viabranch : "<none>")); /* XXX will spam syslog on recovery from DB */ |
|
|
|
c = g_slice_alloc0(sizeof(*c)); |
|
|
|
c->callmaster = m; |
|
|
|
c->callid = strdup(callid); |
|
|
|
if(viabranch) |
|
|
|
c->viabranch = strdup(viabranch); |
|
|
|
c->callstreams = g_queue_new(); |
|
|
|
c->created = m->poller->now; |
|
|
|
c->infohash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); |
|
|
|
return c; |
|
|
|
} |
|
|
|
|
|
|
|
static struct call *call_get_or_create(const char *callid, struct callmaster *m) { |
|
|
|
struct call *c; |
|
|
|
static struct call *call_get_or_create(const char *callid, const char *viabranch, struct callmaster *m) { |
|
|
|
struct call *c, *last; |
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, callid); |
|
|
|
if (!c) { |
|
|
|
mylog(LOG_NOTICE, "[%s] Creating new call", callid); /* XXX will spam syslog on recovery from DB */ |
|
|
|
c = g_slice_alloc0(sizeof(*c)); |
|
|
|
c->callmaster = m; |
|
|
|
c->callid = strdup(callid); |
|
|
|
c->callstreams = g_queue_new(); |
|
|
|
c->created = m->poller->now; |
|
|
|
c->infohash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); |
|
|
|
/* completely new call-id, create call */ |
|
|
|
c = call_create(callid, viabranch, m); |
|
|
|
g_hash_table_insert(m->callhash, c->callid, c); |
|
|
|
return c; |
|
|
|
} |
|
|
|
|
|
|
|
/* we have a call already, search list for viabranch */ |
|
|
|
while(c) { |
|
|
|
if(g_strcmp0(viabranch, c->viabranch) == 0) { |
|
|
|
/* we got such viabranch (even if NULL) already */ |
|
|
|
return c; |
|
|
|
} |
|
|
|
if(!c->next) |
|
|
|
last = c; |
|
|
|
c = c->next; |
|
|
|
} |
|
|
|
|
|
|
|
/* no such viabranch for this callid, create new call */ |
|
|
|
c = call_create(callid, viabranch, m); |
|
|
|
last->next = c; |
|
|
|
c->prev = last; |
|
|
|
return c; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1264,7 +1290,7 @@ char *call_update_udp(const char **out, struct callmaster *m) { |
|
|
|
int num; |
|
|
|
char *ret; |
|
|
|
|
|
|
|
c = call_get_or_create(out[RE_UDP_UL_CALLID], m); |
|
|
|
c = call_get_or_create(out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH], m); |
|
|
|
strdupfree(&c->calling_agent, "UNKNOWN(udp)"); |
|
|
|
|
|
|
|
if (addr_parse_udp(&st, out)) |
|
|
|
@ -1276,11 +1302,12 @@ char *call_update_udp(const char **out, struct callmaster *m) { |
|
|
|
g_queue_clear(&q); |
|
|
|
|
|
|
|
#ifndef NO_REDIS |
|
|
|
/* TODO: need to change structure in regards to viabranch as well */ |
|
|
|
redis_update(c); |
|
|
|
#endif |
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 0 : 1, out[RE_UDP_COOKIE], 1); |
|
|
|
mylog(LOG_INFO, "[%s] Returning to SIP proxy: %s", c->callid, ret); |
|
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, c->viabranch ? c->viabranch : "<none>", ret); |
|
|
|
return ret; |
|
|
|
|
|
|
|
fail: |
|
|
|
@ -1314,11 +1341,12 @@ char *call_lookup_udp(const char **out, struct callmaster *m) { |
|
|
|
g_queue_clear(&q); |
|
|
|
|
|
|
|
#ifndef NO_REDIS |
|
|
|
/* TODO: need to change structure in regards to viabranch as well */ |
|
|
|
redis_update(c); |
|
|
|
#endif |
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 1 : 0, out[RE_UDP_COOKIE], 1); |
|
|
|
mylog(LOG_INFO, "[%s] Returning to SIP proxy: %s", c->callid, ret); |
|
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, c->viabranch ? c->viabranch : "<none>", ret); |
|
|
|
return ret; |
|
|
|
|
|
|
|
fail: |
|
|
|
@ -1333,7 +1361,7 @@ char *call_request(const char **out, struct callmaster *m) { |
|
|
|
int num; |
|
|
|
char *ret; |
|
|
|
|
|
|
|
c = call_get_or_create(out[RE_TCP_RL_CALLID], m); |
|
|
|
c = call_get_or_create(out[RE_TCP_RL_CALLID], NULL, m); |
|
|
|
|
|
|
|
strdupfree(&c->calling_agent, out[RE_TCP_RL_AGENT] ? : "UNKNOWN"); |
|
|
|
info_parse(out[RE_TCP_RL_INFO], &c->infohash); |
|
|
|
@ -1378,14 +1406,39 @@ char *call_lookup(const char **out, struct callmaster *m) { |
|
|
|
} |
|
|
|
|
|
|
|
char *call_delete_udp(const char **out, struct callmaster *m) { |
|
|
|
struct call *c; |
|
|
|
struct call *c, *next; |
|
|
|
char *ret; |
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_D_CALLID]); |
|
|
|
if (!c) |
|
|
|
goto err; |
|
|
|
|
|
|
|
call_destroy(c); |
|
|
|
if(out[RE_UDP_D_VIABRANCH]) { |
|
|
|
/* only delete selective branch */ |
|
|
|
while(c) { |
|
|
|
next = c->next; |
|
|
|
if(g_strcmp0(out[RE_UDP_D_VIABRANCH], c->viabranch) == 0) { |
|
|
|
mylog(LOG_INFO, "[%s - %s] Deleting selective call branch", |
|
|
|
c->callid, c->viabranch ? c->viabranch : "<none>"); |
|
|
|
if(c->prev) |
|
|
|
c->prev->next = c->next; |
|
|
|
call_destroy(c); |
|
|
|
break; |
|
|
|
} |
|
|
|
c = next; |
|
|
|
} |
|
|
|
} else { |
|
|
|
mylog(LOG_INFO, "[%s] Deleting all call branches", c->callid); |
|
|
|
/* delete whole list */ |
|
|
|
while(c) { |
|
|
|
mylog(LOG_INFO, "[%s - %s] Deleted call branch", |
|
|
|
c->callid, c->viabranch ? c->viabranch : "<none>"); |
|
|
|
next = c->next; |
|
|
|
call_destroy(c); |
|
|
|
c = next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
asprintf(&ret, "%s 0\n", out[RE_UDP_COOKIE]); |
|
|
|
goto out; |
|
|
|
@ -1405,6 +1458,7 @@ void call_delete(const char **out, struct callmaster *m) { |
|
|
|
if (!c) |
|
|
|
return; |
|
|
|
|
|
|
|
/* delete whole list, as we don't have branches in tcp controller */ |
|
|
|
call_destroy(c); |
|
|
|
} |
|
|
|
|
|
|
|
@ -1423,6 +1477,8 @@ static void call_status_iterator(void *key, void *val, void *ptr) { |
|
|
|
|
|
|
|
m = c->callmaster; |
|
|
|
|
|
|
|
/* TODO: only called for tcp controller, so no linked list of calls? */ |
|
|
|
|
|
|
|
streambuf_printf(s->outbuf, "session %s %s %s %s %s %i\n", |
|
|
|
c->callid, |
|
|
|
(char *) g_hash_table_lookup(c->infohash, "from"), |
|
|
|
@ -1484,7 +1540,7 @@ void call_restore(struct callmaster *m, char *uuid, redisReply **hash, GList *st |
|
|
|
int i, kernel; |
|
|
|
struct peer *p; |
|
|
|
|
|
|
|
c = call_get_or_create(hash[0]->str, m); |
|
|
|
c = call_get_or_create(hash[0]->str, NULL, m); /* TODO: restore viabranch as well */ |
|
|
|
strcpy(c->redis_uuid, uuid); |
|
|
|
c->created = strtoll(hash[1]->str, NULL, 10); |
|
|
|
strdupfree(&c->calling_agent, "UNKNOWN(recovered)"); |
|
|
|
|