diff --git a/daemon/call.c b/daemon/call.c index e69b13870..28194c5a6 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1803,37 +1803,37 @@ char *call_delete_udp(const char **out, struct callmaster *m) { struct peer *p, *px; DBG("got delete for callid '%s' and viabranch '%s'", - out[RE_UDP_D_CALLID], out[RE_UDP_D_VIABRANCH]); + out[RE_UDP_DQ_CALLID], out[RE_UDP_DQ_VIABRANCH]); rwlock_lock_r(&m->hashlock); - c = g_hash_table_lookup(m->callhash, out[RE_UDP_D_CALLID]); + c = g_hash_table_lookup(m->callhash, out[RE_UDP_DQ_CALLID]); if (!c) { rwlock_unlock_r(&m->hashlock); - mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", out[RE_UDP_D_CALLID]); + mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", out[RE_UDP_DQ_CALLID]); goto err; } obj_hold(c); mutex_lock(&c->lock); rwlock_unlock_r(&m->hashlock); - log_info = out[RE_UDP_D_VIABRANCH]; + log_info = out[RE_UDP_DQ_VIABRANCH]; - if (out[RE_UDP_D_FROMTAG] && *out[RE_UDP_D_FROMTAG]) { + if (out[RE_UDP_DQ_FROMTAG] && *out[RE_UDP_DQ_FROMTAG]) { for (l = c->callstreams->head; l; l = l->next) { cs = l->data; for (i = 0; i < 2; i++) { p = &cs->peers[i]; if (!p->tag) continue; - if (strcmp(p->tag, out[RE_UDP_D_FROMTAG])) + if (strcmp(p->tag, out[RE_UDP_DQ_FROMTAG])) continue; - if (!out[RE_UDP_D_TOTAG] || !*out[RE_UDP_D_TOTAG]) + 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_D_TOTAG])) + if (strcmp(px->tag, out[RE_UDP_DQ_TOTAG])) continue; goto tag_match; @@ -1845,9 +1845,9 @@ char *call_delete_udp(const char **out, struct callmaster *m) { goto err; tag_match: - if (out[RE_UDP_D_VIABRANCH] && *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]); + 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]); goto err; } @@ -1882,6 +1882,91 @@ out: return ret; } +char *call_query_udp(const char **out, struct callmaster *m) { + struct call *c; + char *ret; + struct callstream *cs; + long long unsigned int pcs[4] = {0,0,0,0}; + time_t newest = 0; + int i; + GList *l; + struct peer *p, *px; + + DBG("got query for callid '%s'", out[RE_UDP_DQ_CALLID]); + + rwlock_lock_r(&m->hashlock); + c = g_hash_table_lookup(m->callhash, out[RE_UDP_DQ_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]); + goto err; + } + obj_hold(c); + mutex_lock(&c->lock); + rwlock_unlock_r(&m->hashlock); + + for (l = c->callstreams->head; l; l = l->next) { + cs = l->data; + + if (!out[RE_UDP_DQ_FROMTAG] || !*out[RE_UDP_DQ_FROMTAG]) { + pcs[0] += cs->peers[0].rtps[0].stats.packets; + pcs[1] += cs->peers[1].rtps[0].stats.packets; + pcs[2] += cs->peers[0].rtps[1].stats.packets; + pcs[3] += cs->peers[1].rtps[1].stats.packets; + continue; + } + + for (i = 0; i < 2; i++) { + p = &cs->peers[i]; + px = &cs->peers[i ^ 1]; + + if (p->rtps[0].last > newest) + newest = p->rtps[0].last; + if (p->rtps[1].last > newest) + newest = p->rtps[1].last; + + 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])) + 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])) + continue; + +tag_match: + pcs[0] += p->rtps[0].stats.packets; + pcs[1] += px->rtps[0].stats.packets; + pcs[2] += p->rtps[1].stats.packets; + pcs[3] += px->rtps[1].stats.packets; + } + } + + mutex_unlock(&c->lock); + + xasprintf(&ret, "%s %lld %llu %llu %llu %llu\n", out[RE_UDP_COOKIE], + (long long int) (poller_now - newest), + pcs[0], pcs[1], pcs[2], pcs[3]); + goto out; + +err: + if (c) + mutex_unlock(&c->lock); + xasprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); + goto out; + +out: + if (c) + obj_put(c); + return ret; +} + void call_delete(const char **out, struct callmaster *m) { struct call *c; diff --git a/daemon/call.h b/daemon/call.h index 0bc6a75bc..39cf86f5b 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -128,6 +128,7 @@ char *call_lookup(const char **, struct callmaster *); char *call_lookup_udp(const char **, struct callmaster *); void call_delete(const char **, struct callmaster *); char *call_delete_udp(const char **, struct callmaster *); +char *call_query_udp(const char **, struct callmaster *); void calls_status(struct callmaster *, struct control_stream *); diff --git a/daemon/control_udp.c b/daemon/control_udp.c index d040983e2..6d25cd990 100644 --- a/daemon/control_udp.c +++ b/daemon/control_udp.c @@ -134,8 +134,10 @@ restart: reply = call_update_udp(out, u->callmaster); else if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L') reply = call_lookup_udp(out, u->callmaster); - else if (chrtoupper(out[RE_UDP_D_CMD][0]) == 'D') + else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'D') reply = call_delete_udp(out, u->callmaster); + else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'Q') + reply = call_query_udp(out, u->callmaster); else if (chrtoupper(out[RE_UDP_V_CMD][0]) == 'V') { ZERO(mh); mh.msg_name = &sin; @@ -237,8 +239,8 @@ struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int1 "(?:([\\d.]+)|([\\da-f:]+(?::ffff:[\\d.]+)?))" \ /* port fromtag num totag:11 */ "\\s+(\\d+)\\s+(\\S+?);(\\d+)(?:\\s+(\\S+?);\\d+(?:\\s+.*)?)?\r?\n?$" \ - /* "d" flags callid viabranch fromtag totag:17 */ - "|(d)(\\S*)\\s+([^;\\s]+)(?:;(\\S+))?\\s+(\\S+?)(?:\\s+(\\S+?))?\r?\n?$" \ + /* "d/q" flags callid viabranch fromtag totag:17 */ + "|([dq])(\\S*)\\s+([^;\\s]+)(?:;(\\S+))?\\s+(\\S+?)(?:;\\d+)?(?:\\s+(\\S+?);\\d+)?\r?\n?$" \ /* v flags params:20 */ "|(v)(\\S*)(?:\\s+(\\S+))?)", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL | PCRE_CASELESS, &errptr, &erroff, NULL); diff --git a/daemon/control_udp.h b/daemon/control_udp.h index ca0d8e100..2c18fef9f 100644 --- a/daemon/control_udp.h +++ b/daemon/control_udp.h @@ -25,12 +25,12 @@ #define RE_UDP_UL_FROMTAG 9 #define RE_UDP_UL_NUM 10 #define RE_UDP_UL_TOTAG 11 -#define RE_UDP_D_CMD 12 -#define RE_UDP_D_FLAGS 13 -#define RE_UDP_D_CALLID 14 -#define RE_UDP_D_VIABRANCH 15 -#define RE_UDP_D_FROMTAG 16 -#define RE_UDP_D_TOTAG 17 +#define RE_UDP_DQ_CMD 12 +#define RE_UDP_DQ_FLAGS 13 +#define RE_UDP_DQ_CALLID 14 +#define RE_UDP_DQ_VIABRANCH 15 +#define RE_UDP_DQ_FROMTAG 16 +#define RE_UDP_DQ_TOTAG 17 #define RE_UDP_V_CMD 18 #define RE_UDP_V_FLAGS 19 #define RE_UDP_V_PARMS 20