|
|
|
|
@ -115,6 +115,10 @@ const struct transport_protocol transport_protocols[] = {
|
|
|
|
|
};
|
|
|
|
|
const int num_transport_protocols = G_N_ELEMENTS(transport_protocols);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rwlock_t rtpe_callhash_lock;
|
|
|
|
|
GHashTable *rtpe_callhash;
|
|
|
|
|
|
|
|
|
|
/* ********** */
|
|
|
|
|
|
|
|
|
|
static void __monologue_destroy(struct call_monologue *monologue);
|
|
|
|
|
@ -477,14 +481,14 @@ static void callmaster_timer(void *ptr) {
|
|
|
|
|
hlp.addr_sfd = g_hash_table_new(g_endpoint_hash, g_endpoint_eq);
|
|
|
|
|
|
|
|
|
|
/* obtain the call list and make a copy from it so not to hold the lock */
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
l = g_hash_table_get_values(m->callhash);
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
l = g_hash_table_get_values(rtpe_callhash);
|
|
|
|
|
if (l) {
|
|
|
|
|
calls = g_list_copy(l);
|
|
|
|
|
g_list_free(l);
|
|
|
|
|
g_list_foreach(calls, call_obj_get, NULL);
|
|
|
|
|
}
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
|
|
|
|
|
if (calls) {
|
|
|
|
|
g_list_foreach(calls, call_timer_iterator, &hlp);
|
|
|
|
|
@ -611,11 +615,11 @@ struct callmaster *callmaster_new(struct poller *p) {
|
|
|
|
|
|
|
|
|
|
c = obj_alloc0("callmaster", sizeof(*c), NULL);
|
|
|
|
|
|
|
|
|
|
c->callhash = g_hash_table_new(str_hash, str_equal);
|
|
|
|
|
if (!c->callhash)
|
|
|
|
|
rtpe_callhash = g_hash_table_new(str_hash, str_equal);
|
|
|
|
|
if (!rtpe_callhash)
|
|
|
|
|
goto fail;
|
|
|
|
|
c->poller = p;
|
|
|
|
|
rwlock_init(&c->hashlock);
|
|
|
|
|
rwlock_init(&rtpe_callhash_lock);
|
|
|
|
|
|
|
|
|
|
c->info_re = pcre_compile("^([^:,]+)(?::(.*?))?(?:$|,)", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL, &errptr, &erroff, NULL);
|
|
|
|
|
if (!c->info_re)
|
|
|
|
|
@ -1755,8 +1759,8 @@ static struct timeval add_ongoing_calls_dur_in_interval(struct callmaster *m,
|
|
|
|
|
struct call *call;
|
|
|
|
|
struct call_monologue *ml;
|
|
|
|
|
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
g_hash_table_iter_init(&iter, m->callhash);
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
g_hash_table_iter_init(&iter, rtpe_callhash);
|
|
|
|
|
|
|
|
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
|
|
|
call = (struct call*) value;
|
|
|
|
|
@ -1770,7 +1774,7 @@ static struct timeval add_ongoing_calls_dur_in_interval(struct callmaster *m,
|
|
|
|
|
timeval_add(&res, &res, &call_duration);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1794,11 +1798,11 @@ void call_destroy(struct call *c) {
|
|
|
|
|
m = c->callmaster;
|
|
|
|
|
p = m->poller;
|
|
|
|
|
|
|
|
|
|
rwlock_lock_w(&m->hashlock);
|
|
|
|
|
ret = (g_hash_table_lookup(m->callhash, &c->callid) == c);
|
|
|
|
|
rwlock_lock_w(&rtpe_callhash_lock);
|
|
|
|
|
ret = (g_hash_table_lookup(rtpe_callhash, &c->callid) == c);
|
|
|
|
|
if (ret)
|
|
|
|
|
g_hash_table_remove(m->callhash, &c->callid);
|
|
|
|
|
rwlock_unlock_w(&m->hashlock);
|
|
|
|
|
g_hash_table_remove(rtpe_callhash, &c->callid);
|
|
|
|
|
rwlock_unlock_w(&rtpe_callhash_lock);
|
|
|
|
|
|
|
|
|
|
// if call not found in callhash => previously deleted
|
|
|
|
|
if (!ret)
|
|
|
|
|
@ -2047,20 +2051,20 @@ struct call *call_get_or_create(const str *callid, struct callmaster *m, enum ca
|
|
|
|
|
struct call *c;
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
c = g_hash_table_lookup(m->callhash, callid);
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
c = g_hash_table_lookup(rtpe_callhash, callid);
|
|
|
|
|
if (!c) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
/* completely new call-id, create call */
|
|
|
|
|
c = call_create(callid, m);
|
|
|
|
|
rwlock_lock_w(&m->hashlock);
|
|
|
|
|
if (g_hash_table_lookup(m->callhash, callid)) {
|
|
|
|
|
rwlock_lock_w(&rtpe_callhash_lock);
|
|
|
|
|
if (g_hash_table_lookup(rtpe_callhash, callid)) {
|
|
|
|
|
/* preempted */
|
|
|
|
|
rwlock_unlock_w(&m->hashlock);
|
|
|
|
|
rwlock_unlock_w(&rtpe_callhash_lock);
|
|
|
|
|
obj_put(c);
|
|
|
|
|
goto restart;
|
|
|
|
|
}
|
|
|
|
|
g_hash_table_insert(m->callhash, &c->callid, obj_get(c));
|
|
|
|
|
g_hash_table_insert(rtpe_callhash, &c->callid, obj_get(c));
|
|
|
|
|
|
|
|
|
|
if (type == CT_FOREIGN_CALL) /* foreign call*/
|
|
|
|
|
c->foreign_call = 1;
|
|
|
|
|
@ -2068,12 +2072,12 @@ restart:
|
|
|
|
|
statistics_update_foreignown_inc(m,c);
|
|
|
|
|
|
|
|
|
|
rwlock_lock_w(&c->master_lock);
|
|
|
|
|
rwlock_unlock_w(&m->hashlock);
|
|
|
|
|
rwlock_unlock_w(&rtpe_callhash_lock);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
obj_hold(c);
|
|
|
|
|
rwlock_lock_w(&c->master_lock);
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_info_call(c);
|
|
|
|
|
@ -2084,16 +2088,16 @@ restart:
|
|
|
|
|
struct call *call_get(const str *callid, struct callmaster *m) {
|
|
|
|
|
struct call *ret;
|
|
|
|
|
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
ret = g_hash_table_lookup(m->callhash, callid);
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
ret = g_hash_table_lookup(rtpe_callhash, callid);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rwlock_lock_w(&ret->master_lock);
|
|
|
|
|
obj_hold(ret);
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
|
|
|
|
|
log_info_call(ret);
|
|
|
|
|
return ret;
|
|
|
|
|
@ -2488,57 +2492,12 @@ static void callmaster_get_all_calls_interator(void *key, void *val, void *ptr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void callmaster_get_all_calls(struct callmaster *m, GQueue *q) {
|
|
|
|
|
rwlock_lock_r(&m->hashlock);
|
|
|
|
|
g_hash_table_foreach(m->callhash, callmaster_get_all_calls_interator, q);
|
|
|
|
|
rwlock_unlock_r(&m->hashlock);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rwlock_lock_r(&rtpe_callhash_lock);
|
|
|
|
|
g_hash_table_foreach(rtpe_callhash, callmaster_get_all_calls_interator, q);
|
|
|
|
|
rwlock_unlock_r(&rtpe_callhash_lock);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// unused
|
|
|
|
|
// simplifty redis_write <> redis if put back into use
|
|
|
|
|
static void calls_dump_iterator(void *key, void *val, void *ptr) {
|
|
|
|
|
struct call *c = val;
|
|
|
|
|
struct callmaster *m = c->callmaster;
|
|
|
|
|
|
|
|
|
|
if (m->conf.redis_write) {
|
|
|
|
|
redis_update(c, m->conf.redis_write);
|
|
|
|
|
} else if (m->conf.redis) {
|
|
|
|
|
redis_update(c, m->conf.redis);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void calls_dump_redis(struct callmaster *m) {
|
|
|
|
|
if (!m->conf.redis)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Start dumping all call data to Redis...\n");
|
|
|
|
|
redis_wipe(m->conf.redis);
|
|
|
|
|
g_hash_table_foreach(m->callhash, calls_dump_iterator, NULL);
|
|
|
|
|
ilog(LOG_DEBUG, "Finished dumping all call data to Redis\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void calls_dump_redis_read(struct callmaster *m) {
|
|
|
|
|
if (!m->conf.redis_read)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Start dumping all call data to read Redis...\n");
|
|
|
|
|
redis_wipe(m->conf.redis_read);
|
|
|
|
|
g_hash_table_foreach(m->callhash, calls_dump_iterator, NULL);
|
|
|
|
|
ilog(LOG_DEBUG, "Finished dumping all call data to read Redis\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void calls_dump_redis_write(struct callmaster *m) {
|
|
|
|
|
if (!m->conf.redis_write)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Start dumping all call data to write Redis...\n");
|
|
|
|
|
redis_wipe(m->conf.redis_write);
|
|
|
|
|
g_hash_table_foreach(m->callhash, calls_dump_iterator, NULL);
|
|
|
|
|
ilog(LOG_DEBUG, "Finished dumping all call data to write Redis\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
const struct transport_protocol *transport_protocol(const str *s) {
|
|
|
|
|
int i;
|
|
|
|
|
|