Browse Source

Implement viabranch-based call-list.

git.mgm/mediaproxy-ng/2.0
Andreas Granig 14 years ago
parent
commit
7b51c0bc30
2 changed files with 105 additions and 46 deletions
  1. +102
    -46
      daemon/call.c
  2. +3
    -0
      daemon/call.h

+ 102
- 46
daemon/call.c View File

@ -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)");


+ 3
- 0
daemon/call.h View File

@ -78,6 +78,7 @@ struct call {
GQueue *callstreams;
char *callid;
char *viabranch;
#ifndef NO_REDIS
char redis_uuid[37];
#endif
@ -86,6 +87,8 @@ struct call {
char *called_agent;
GHashTable *infohash;
time_t lookup_done;
struct call *next;
struct call *prev;
};
struct callmaster {


Loading…
Cancel
Save