|
|
@ -33,7 +33,10 @@ |
|
|
#define DBG(x...) ((void)0) |
|
|
#define DBG(x...) ((void)0) |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#define VIA2STR(x) ( x ? x : "<none>") |
|
|
|
|
|
|
|
|
#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, (c)->log_info |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -78,7 +81,6 @@ static char *rtp_codecs[] = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void call_destroy(struct call *); |
|
|
static void call_destroy(struct call *); |
|
|
static void call_destroy_all_branches(struct call *); |
|
|
|
|
|
static void unkernelize(struct peer *); |
|
|
static void unkernelize(struct peer *); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -90,9 +92,9 @@ static void stream_closed(int fd, void *p) { |
|
|
|
|
|
|
|
|
c = r->up->up->call; |
|
|
c = r->up->up->call; |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, "[%s - %s] Read error on RTP socket", c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_C "Read error on RTP socket", LOG_PARAMS_C(c)); |
|
|
|
|
|
|
|
|
call_destroy_all_branches(c); |
|
|
|
|
|
|
|
|
call_destroy(c); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -104,7 +106,7 @@ static void kernelize(struct callstream *c) { |
|
|
struct streamrelay *r, *rp; |
|
|
struct streamrelay *r, *rp; |
|
|
struct kernel_stream ks; |
|
|
struct kernel_stream ks; |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, "[%s - %s] Kernelizing RTP streams", c->call->callid, VIA2STR(c->call->viabranch)); |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_C "Kernelizing RTP streams", LOG_PARAMS_C(c->call)); |
|
|
|
|
|
|
|
|
ZERO(ks); |
|
|
ZERO(ks); |
|
|
|
|
|
|
|
|
@ -179,8 +181,8 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_ |
|
|
smart_ntop_p(addr, &fsin->sin6_addr, sizeof(addr)); |
|
|
smart_ntop_p(addr, &fsin->sin6_addr, sizeof(addr)); |
|
|
|
|
|
|
|
|
if (p->fd == -1) { |
|
|
if (p->fd == -1) { |
|
|
mylog(LOG_WARNING, "[%s - %s] RTP packet to port %u discarded from %s:%u", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch), r->localport, addr, ntohs(fsin->sin6_port)); |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_C "RTP packet to port %u discarded from %s:%u", |
|
|
|
|
|
LOG_PARAMS_C(c), r->localport, addr, ntohs(fsin->sin6_port)); |
|
|
r->stats.errors++; |
|
|
r->stats.errors++; |
|
|
m->statsps.errors++; |
|
|
m->statsps.errors++; |
|
|
return 0; |
|
|
return 0; |
|
|
@ -200,8 +202,8 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_ |
|
|
pe->codec = "unknown"; |
|
|
pe->codec = "unknown"; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, "[%s - %s] Confirmed peer information for port %u - %s:%u", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch), r->localport, addr, ntohs(fsin->sin6_port)); |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_C "Confirmed peer information for port %u - %s:%u", |
|
|
|
|
|
LOG_PARAMS_C(c), r->localport, addr, ntohs(fsin->sin6_port)); |
|
|
|
|
|
|
|
|
pe->confirmed = 1; |
|
|
pe->confirmed = 1; |
|
|
} |
|
|
} |
|
|
@ -345,7 +347,7 @@ err: |
|
|
|
|
|
|
|
|
if (stream_packet(r, buf, ret, sinp)) { |
|
|
if (stream_packet(r, buf, ret, sinp)) { |
|
|
mylog(LOG_WARNING, "Write error on RTP socket"); |
|
|
mylog(LOG_WARNING, "Write error on RTP socket"); |
|
|
call_destroy_all_branches(r->up->up->call); |
|
|
|
|
|
|
|
|
call_destroy(r->up->up->call); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -442,45 +444,41 @@ static void call_timer_iterator(void *key, void *val, void *ptr) { |
|
|
struct callmaster *cm; |
|
|
struct callmaster *cm; |
|
|
unsigned int check; |
|
|
unsigned int check; |
|
|
|
|
|
|
|
|
while(c) { |
|
|
|
|
|
|
|
|
|
|
|
if (!c->callstreams->head) |
|
|
|
|
|
goto drop; |
|
|
|
|
|
|
|
|
if (!c->callstreams->head) |
|
|
|
|
|
goto drop; |
|
|
|
|
|
|
|
|
cm = c->callmaster; |
|
|
|
|
|
po = cm->poller; |
|
|
|
|
|
|
|
|
cm = c->callmaster; |
|
|
|
|
|
po = cm->poller; |
|
|
|
|
|
|
|
|
for (it = c->callstreams->head; it; it = it->next) { |
|
|
|
|
|
cs = it->data; |
|
|
|
|
|
|
|
|
for (it = c->callstreams->head; it; it = it->next) { |
|
|
|
|
|
cs = it->data; |
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) { |
|
|
|
|
|
p = &cs->peers[i]; |
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) { |
|
|
|
|
|
p = &cs->peers[i]; |
|
|
|
|
|
|
|
|
hlp->ports[p->rtps[0].localport] = &p->rtps[0]; |
|
|
|
|
|
hlp->ports[p->rtps[1].localport] = &p->rtps[1]; |
|
|
|
|
|
|
|
|
hlp->ports[p->rtps[0].localport] = &p->rtps[0]; |
|
|
|
|
|
hlp->ports[p->rtps[1].localport] = &p->rtps[1]; |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (po->now - p->rtps[0].last < check) |
|
|
|
|
|
goto good; |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, "[%s - %s] Closing call branch due to timeout", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Closing call branch due to timeout", |
|
|
|
|
|
LOG_PARAMS_C(c)); |
|
|
|
|
|
|
|
|
drop: |
|
|
|
|
|
hlp->del = g_list_prepend(hlp->del, c); |
|
|
|
|
|
c = c->next; |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
drop: |
|
|
|
|
|
hlp->del = g_list_prepend(hlp->del, c); |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
good: |
|
|
|
|
|
c = c->next; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
good: |
|
|
|
|
|
; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -535,11 +533,7 @@ next: |
|
|
for (i = hlp.del; i; i = n) { |
|
|
for (i = hlp.del; i; i = n) { |
|
|
n = i->next; |
|
|
n = i->next; |
|
|
c = i->data; |
|
|
c = i->data; |
|
|
if(!c->prev && !c->next) { |
|
|
|
|
|
call_destroy_all_branches(c); |
|
|
|
|
|
} else { |
|
|
|
|
|
call_destroy(c); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
call_destroy(c); |
|
|
g_list_free_1(i); |
|
|
g_list_free_1(i); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -706,8 +700,8 @@ next: |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
m->lastport = port; |
|
|
m->lastport = port; |
|
|
mylog(LOG_DEBUG, "[%s - %s] Opened ports %u/%u for RTP", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch), a->localport, b->localport); |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_CI "Opened ports %u/%u for RTP", |
|
|
|
|
|
LOG_PARAMS_CI(c), a->localport, b->localport); |
|
|
|
|
|
|
|
|
reserve: |
|
|
reserve: |
|
|
bit_array_set(ports_used, a->localport); |
|
|
bit_array_set(ports_used, a->localport); |
|
|
@ -716,7 +710,7 @@ reserve: |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
fail: |
|
|
fail: |
|
|
mylog(LOG_ERR, "[%s - %s] Failed to get RTP port pair", c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
|
|
|
mylog(LOG_ERR, LOG_PREFIX_CI "Failed to get RTP port pair", LOG_PARAMS_CI(c)); |
|
|
if (a->fd != -1) |
|
|
if (a->fd != -1) |
|
|
close(a->fd); |
|
|
close(a->fd); |
|
|
if (b->fd != -1) |
|
|
if (b->fd != -1) |
|
|
@ -783,8 +777,8 @@ static void steal_peer(struct peer *dest, struct peer *src) { |
|
|
c = src->up->call; |
|
|
c = src->up->call; |
|
|
po = c->callmaster->poller; |
|
|
po = c->callmaster->poller; |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, "[%s - %s] Re-using existing open RTP port %u", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch), r->localport); |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_CI "Re-using existing open RTP port %u", |
|
|
|
|
|
LOG_PARAMS_CI(c), r->localport); |
|
|
|
|
|
|
|
|
dest->confirmed = 0; |
|
|
dest->confirmed = 0; |
|
|
unkernelize(dest); |
|
|
unkernelize(dest); |
|
|
@ -803,8 +797,8 @@ static void steal_peer(struct peer *dest, struct peer *src) { |
|
|
srs = &src->rtps[i]; |
|
|
srs = &src->rtps[i]; |
|
|
|
|
|
|
|
|
if (sr->fd != -1) { |
|
|
if (sr->fd != -1) { |
|
|
mylog(LOG_DEBUG, "[%s - %s] Closing port %u in favor of re-use", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch), sr->localport); |
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_CI "Closing port %u in favor of re-use", |
|
|
|
|
|
LOG_PARAMS_CI(c), sr->localport); |
|
|
close(sr->fd); |
|
|
close(sr->fd); |
|
|
bit_array_clear(ports_used, sr->localport); |
|
|
bit_array_clear(ports_used, sr->localport); |
|
|
poller_del_item(po, sr->fd); |
|
|
poller_del_item(po, sr->fd); |
|
|
@ -980,8 +974,8 @@ found: |
|
|
goto got_cs; |
|
|
goto got_cs; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, "[%s - %s] Got LOOKUP, but no usable callstreams found", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_CI "Got LOOKUP, but no usable callstreams found", |
|
|
|
|
|
LOG_PARAMS_CI(c)); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
got_cs: |
|
|
got_cs: |
|
|
@ -1107,36 +1101,11 @@ static void kill_callstream(struct callstream *s) { |
|
|
g_slice_free1(sizeof(*s), s); |
|
|
g_slice_free1(sizeof(*s), s); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void call_destroy_all_branches(struct call *c) { |
|
|
|
|
|
struct callmaster *m = c->callmaster; |
|
|
|
|
|
struct call *next; |
|
|
|
|
|
|
|
|
|
|
|
g_hash_table_remove(m->callhash, c->callid); |
|
|
|
|
|
|
|
|
|
|
|
/* rewind to beginning of list */ |
|
|
|
|
|
for(; c->prev; c = c->prev); |
|
|
|
|
|
|
|
|
|
|
|
/* delete full list */ |
|
|
|
|
|
while(c) { |
|
|
|
|
|
mylog(LOG_INFO, "[%s - %s] Delete call branch", c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
next = c->next; |
|
|
|
|
|
c->next = NULL; |
|
|
|
|
|
call_destroy(c); |
|
|
|
|
|
c = next; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void call_destroy(struct call *c) { |
|
|
static void call_destroy(struct call *c) { |
|
|
|
|
|
struct callmaster *m = c->callmaster; |
|
|
struct callstream *s; |
|
|
struct callstream *s; |
|
|
|
|
|
|
|
|
if(c->next) |
|
|
|
|
|
c->next->prev = c->prev; |
|
|
|
|
|
|
|
|
|
|
|
if(c->prev) |
|
|
|
|
|
c->prev->next = c->next; |
|
|
|
|
|
else if(c->next) |
|
|
|
|
|
/* we delete first element in list, so update callid hash */ |
|
|
|
|
|
g_hash_table_replace(c->callmaster->callhash, strdup(c->callid), c->next); |
|
|
|
|
|
|
|
|
g_hash_table_remove(m->callhash, c->callid); |
|
|
|
|
|
|
|
|
#ifndef NO_REDIS |
|
|
#ifndef NO_REDIS |
|
|
/* TODO: take into account the viabranch list */ |
|
|
/* TODO: take into account the viabranch list */ |
|
|
@ -1144,9 +1113,8 @@ static void call_destroy(struct call *c) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
free(c->callid); |
|
|
free(c->callid); |
|
|
if(c->viabranch) |
|
|
|
|
|
free(c->viabranch); |
|
|
|
|
|
g_hash_table_destroy(c->infohash); |
|
|
g_hash_table_destroy(c->infohash); |
|
|
|
|
|
g_hash_table_destroy(c->branches); |
|
|
if (c->calling_agent) |
|
|
if (c->calling_agent) |
|
|
free(c->calling_agent); |
|
|
free(c->calling_agent); |
|
|
if (c->called_agent) |
|
|
if (c->called_agent) |
|
|
@ -1227,48 +1195,51 @@ out: |
|
|
return g_string_free(o, FALSE); |
|
|
return g_string_free(o, FALSE); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static struct call *call_create(const char *callid, const char *viabranch, struct callmaster *m) { |
|
|
|
|
|
|
|
|
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 struct call *call_create(const char *callid, struct callmaster *m) { |
|
|
struct call *c; |
|
|
struct call *c; |
|
|
|
|
|
|
|
|
mylog(LOG_NOTICE, "[%s - %s] Creating new call", |
|
|
|
|
|
callid, VIA2STR(viabranch)); /* XXX will spam syslog on recovery from DB */ |
|
|
|
|
|
|
|
|
mylog(LOG_NOTICE, LOG_PREFIX_C "Creating new call", |
|
|
|
|
|
callid); /* XXX will spam syslog on recovery from DB */ |
|
|
c = g_slice_alloc0(sizeof(*c)); |
|
|
c = g_slice_alloc0(sizeof(*c)); |
|
|
c->callmaster = m; |
|
|
c->callmaster = m; |
|
|
c->callid = strdup(callid); |
|
|
c->callid = strdup(callid); |
|
|
if(viabranch) |
|
|
|
|
|
c->viabranch = strdup(viabranch); |
|
|
|
|
|
c->callstreams = g_queue_new(); |
|
|
c->callstreams = g_queue_new(); |
|
|
c->created = m->poller->now; |
|
|
c->created = m->poller->now; |
|
|
c->infohash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); |
|
|
c->infohash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); |
|
|
|
|
|
c->branches = g_hash_table_new_full(g_str_hash0, g_str_equal0, free, NULL); |
|
|
return c; |
|
|
return c; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static struct call *call_get_or_create(const char *callid, const char *viabranch, struct callmaster *m) { |
|
|
static struct call *call_get_or_create(const char *callid, const char *viabranch, struct callmaster *m) { |
|
|
struct call *c, *last; |
|
|
|
|
|
|
|
|
struct call *c; |
|
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, callid); |
|
|
c = g_hash_table_lookup(m->callhash, callid); |
|
|
if (!c) { |
|
|
if (!c) { |
|
|
/* completely new call-id, create call */ |
|
|
/* completely new call-id, create call */ |
|
|
c = call_create(callid, viabranch, m); |
|
|
|
|
|
|
|
|
c = call_create(callid, m); |
|
|
g_hash_table_insert(m->callhash, c->callid, c); |
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!g_hash_table_lookup(c->branches, viabranch)) |
|
|
|
|
|
g_hash_table_insert(c->branches, strdup(viabranch), (void *) 0x1); |
|
|
|
|
|
|
|
|
/* no such viabranch for this callid, create new call */ |
|
|
|
|
|
c = call_create(callid, viabranch, m); |
|
|
|
|
|
last->next = c; |
|
|
|
|
|
c->prev = last; |
|
|
|
|
|
return c; |
|
|
return c; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1326,6 +1297,7 @@ char *call_update_udp(const char **out, struct callmaster *m) { |
|
|
char *ret; |
|
|
char *ret; |
|
|
|
|
|
|
|
|
c = call_get_or_create(out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH], m); |
|
|
c = call_get_or_create(out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH], m); |
|
|
|
|
|
c->log_info = out[RE_UDP_UL_VIABRANCH]; |
|
|
strdupfree(&c->calling_agent, "UNKNOWN(udp)"); |
|
|
strdupfree(&c->calling_agent, "UNKNOWN(udp)"); |
|
|
|
|
|
|
|
|
if (addr_parse_udp(&st, out)) |
|
|
if (addr_parse_udp(&st, out)) |
|
|
@ -1342,45 +1314,33 @@ char *call_update_udp(const char **out, struct callmaster *m) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 0 : 1, out[RE_UDP_COOKIE], 1); |
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 0 : 1, out[RE_UDP_COOKIE], 1); |
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, VIA2STR(c->viabranch), ret); |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); |
|
|
|
|
|
c->log_info = NULL; |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
fail: |
|
|
fail: |
|
|
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); |
|
|
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); |
|
|
asprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); |
|
|
asprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); |
|
|
|
|
|
c->log_info = NULL; |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
char *call_lookup_udp(const char **out, struct callmaster *m) { |
|
|
char *call_lookup_udp(const char **out, struct callmaster *m) { |
|
|
struct call *c, *tmp; |
|
|
|
|
|
|
|
|
struct call *c; |
|
|
GQueue q = G_QUEUE_INIT; |
|
|
GQueue q = G_QUEUE_INIT; |
|
|
struct stream st; |
|
|
struct stream st; |
|
|
int num; |
|
|
int num; |
|
|
char *ret; |
|
|
char *ret; |
|
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_UL_CALLID]); |
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_UL_CALLID]); |
|
|
tmp = NULL; |
|
|
|
|
|
if (!c) { |
|
|
|
|
|
mylog(LOG_WARNING, "[%s] Got UDP LOOKUP for unknown call-id", out[RE_UDP_UL_CALLID]); |
|
|
|
|
|
asprintf(&ret, "%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->ipv4)); |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
while(c) { |
|
|
|
|
|
if(g_strcmp0(out[RE_UDP_UL_VIABRANCH], c->viabranch) == 0) { |
|
|
|
|
|
/* found viabranch (even if NULL) */ |
|
|
|
|
|
tmp = c; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
c = c->next; |
|
|
|
|
|
} |
|
|
|
|
|
if (!tmp) { |
|
|
|
|
|
mylog(LOG_WARNING, "[%s] Got UDP LOOKUP for unknown viabranch '%s' in call-id", |
|
|
|
|
|
out[RE_UDP_UL_CALLID], VIA2STR(out[RE_UDP_UL_VIABRANCH])); |
|
|
|
|
|
|
|
|
if (!c || !g_hash_table_lookup(c->branches, out[RE_UDP_UL_VIABRANCH])) { |
|
|
|
|
|
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]); |
|
|
asprintf(&ret, "%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->ipv4)); |
|
|
asprintf(&ret, "%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->ipv4)); |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
c = tmp; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c->log_info = out[RE_UDP_UL_CALLID]; |
|
|
strdupfree(&c->called_agent, "UNKNOWN(udp)"); |
|
|
strdupfree(&c->called_agent, "UNKNOWN(udp)"); |
|
|
|
|
|
|
|
|
if (addr_parse_udp(&st, out)) |
|
|
if (addr_parse_udp(&st, out)) |
|
|
@ -1397,12 +1357,14 @@ char *call_lookup_udp(const char **out, struct callmaster *m) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 1 : 0, out[RE_UDP_COOKIE], 1); |
|
|
ret = streams_print(c->callstreams, 1, (num >= 0) ? 1 : 0, out[RE_UDP_COOKIE], 1); |
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, VIA2STR(c->viabranch), ret); |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); |
|
|
|
|
|
c->log_info = NULL; |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
fail: |
|
|
fail: |
|
|
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); |
|
|
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); |
|
|
asprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); |
|
|
asprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); |
|
|
|
|
|
c->log_info = NULL; |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1425,7 +1387,7 @@ char *call_request(const char **out, struct callmaster *m) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, abs(num), (num >= 0) ? 0 : 1, NULL, 0); |
|
|
ret = streams_print(c->callstreams, abs(num), (num >= 0) ? 0 : 1, NULL, 0); |
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, VIA2STR(c->viabranch), ret); |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1437,7 +1399,7 @@ char *call_lookup(const char **out, struct callmaster *m) { |
|
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_TCP_RL_CALLID]); |
|
|
c = g_hash_table_lookup(m->callhash, out[RE_TCP_RL_CALLID]); |
|
|
if (!c) { |
|
|
if (!c) { |
|
|
mylog(LOG_WARNING, "[%s] Got LOOKUP for unknown call-id", out[RE_TCP_RL_CALLID]); |
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, LOG_PREFIX_C "Got LOOKUP for unknown call-id", out[RE_TCP_RL_CALLID]); |
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1452,50 +1414,40 @@ char *call_lookup(const char **out, struct callmaster *m) { |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
ret = streams_print(c->callstreams, abs(num), (num >= 0) ? 1 : 0, NULL, 0); |
|
|
ret = streams_print(c->callstreams, abs(num), (num >= 0) ? 1 : 0, NULL, 0); |
|
|
mylog(LOG_INFO, "[%s - %s] Returning to SIP proxy: %s", c->callid, VIA2STR(c->viabranch), ret); |
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
char *call_delete_udp(const char **out, struct callmaster *m) { |
|
|
char *call_delete_udp(const char **out, struct callmaster *m) { |
|
|
struct call *c, *next; |
|
|
|
|
|
|
|
|
struct call *c; |
|
|
char *ret; |
|
|
char *ret; |
|
|
|
|
|
|
|
|
DBG("got delete for callid '%s' and viabranch '%s'", |
|
|
DBG("got delete for callid '%s' and viabranch '%s'", |
|
|
out[RE_UDP_D_CALLID], out[RE_UDP_D_VIABRANCH] ? out[RE_UDP_D_VIABRANCH] : "<none>"); |
|
|
|
|
|
|
|
|
out[RE_UDP_D_CALLID], out[RE_UDP_D_VIABRANCH]); |
|
|
|
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_D_CALLID]); |
|
|
c = g_hash_table_lookup(m->callhash, out[RE_UDP_D_CALLID]); |
|
|
if (!c) |
|
|
if (!c) |
|
|
goto err; |
|
|
goto err; |
|
|
|
|
|
c->log_info = out[RE_UDP_D_VIABRANCH]; |
|
|
|
|
|
|
|
|
if(out[RE_UDP_D_VIABRANCH]) { |
|
|
|
|
|
/* search given branch */ |
|
|
|
|
|
while(c) { |
|
|
|
|
|
next = c->next; |
|
|
|
|
|
DBG("comparing passed viabranch '%s' with stored viabranch '%s' for removal", |
|
|
|
|
|
VIA2STR(out[RE_UDP_D_VIABRANCH]), VIA2STR(c->viabranch)); |
|
|
|
|
|
if(g_strcmp0(out[RE_UDP_D_VIABRANCH], c->viabranch) == 0) { |
|
|
|
|
|
if(!c->prev && !c->next) { |
|
|
|
|
|
mylog(LOG_INFO, "[%s - %s] Deleting full call because there is only one branch", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
call_destroy_all_branches(c); |
|
|
|
|
|
} else { |
|
|
|
|
|
mylog(LOG_INFO, "[%s - %s] Deleting selective call branch", |
|
|
|
|
|
c->callid, VIA2STR(c->viabranch)); |
|
|
|
|
|
call_destroy(c); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} else { |
|
|
|
|
|
DBG("passed viabranch '%s' doesn't match stored viabranch '%s'", |
|
|
|
|
|
VIA2STR(out[RE_UDP_D_VIABRANCH]), VIA2STR(c->viabranch)); |
|
|
|
|
|
} |
|
|
|
|
|
c = next; |
|
|
|
|
|
|
|
|
if (out[RE_UDP_D_VIABRANCH]) { |
|
|
|
|
|
if (!g_hash_table_remove(c->branches, out[RE_UDP_D_VIABRANCH])) { |
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Branch to delete doesn't exist", c->callid, out[RE_UDP_D_VIABRANCH]); |
|
|
|
|
|
goto err; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
mylog(LOG_INFO, "[%s] Deleting full call", c->callid); |
|
|
|
|
|
call_destroy_all_branches(c); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_CI "Branch deleted", LOG_PARAMS_CI(c)); |
|
|
|
|
|
if (g_hash_table_size(c->branches)) |
|
|
|
|
|
goto success; |
|
|
|
|
|
else |
|
|
|
|
|
DBG("no branches left, deleting full call"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mylog(LOG_INFO, LOG_PREFIX_C "Deleting full call", c->callid); |
|
|
|
|
|
call_destroy(c); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
success: |
|
|
asprintf(&ret, "%s 0\n", out[RE_UDP_COOKIE]); |
|
|
asprintf(&ret, "%s 0\n", out[RE_UDP_COOKIE]); |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
|
|
|
@ -1506,6 +1458,7 @@ err: |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
|
|
|
out: |
|
|
out: |
|
|
|
|
|
c->log_info = NULL; |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|