From 1ef1c87545a258345ebfbdceecd11f3f7b1ad1f0 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 7 Feb 2013 10:51:01 -0500 Subject: [PATCH] add a prelim NG query command --- daemon/call.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ daemon/call.h | 2 + daemon/control_ng.c | 2 + 3 files changed, 127 insertions(+) diff --git a/daemon/call.c b/daemon/call.c index 4ab2f90bf..617210b62 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2314,3 +2314,126 @@ void callmaster_exclude_port(struct callmaster *m, u_int16_t p) { bit_array_set(m->ports_used, p); mutex_unlock(&m->portlock); } + +static bencode_item_t *peer_address(bencode_buffer_t *b, struct stream *s) { + bencode_item_t *d; + char buf[64]; + + d = bencode_dictionary(b); + if (IN6_IS_ADDR_V4MAPPED(&s->ip46)) { + bencode_dictionary_add_string(d, "family", "IPv4"); + inet_ntop(AF_INET, &(s->ip46.s6_addr32[3]), buf, sizeof(buf)); + } + else { + bencode_dictionary_add_string(d, "family", "IPv6"); + inet_ntop(AF_INET6, &s->ip46, buf, sizeof(buf)); + } + bencode_dictionary_add(d, "address", bencode_string_dup(b, buf)); + bencode_dictionary_add_integer(d, "port", s->port); + + return d; +} + +static bencode_item_t *streamrelay_stats(bencode_buffer_t *b, struct streamrelay *r) { + bencode_item_t *d, *s; + + d = bencode_dictionary(b); + + s = bencode_dictionary_add(d, "stats", bencode_dictionary(b)); + bencode_dictionary_add_integer(s, "packets", r->stats.packets); + bencode_dictionary_add_integer(s, "bytes", r->stats.bytes); + bencode_dictionary_add_integer(s, "errors", r->stats.errors); + + bencode_dictionary_add(d, "peer address", peer_address(b, &r->peer)); + bencode_dictionary_add(d, "advertised peer address", peer_address(b, &r->peer_advertised)); + + bencode_dictionary_add_integer(d, "local port", r->fd.localport); + + return d; +} + +static bencode_item_t *peer_stats(bencode_buffer_t *b, struct peer *p) { + bencode_item_t *d, *s; + + d = bencode_dictionary(b); + + bencode_dictionary_add_str(d, "tag", &p->tag); + if (p->codec) + bencode_dictionary_add_string(d, "codec", p->codec); + if (p->kernelized) + bencode_dictionary_add_string(d, "status", "in kernel"); + else if (p->confirmed) + bencode_dictionary_add_string(d, "status", "confirmed peer address"); + else if (p->filled) + bencode_dictionary_add_string(d, "status", "known but unconfirmed peer address"); + else + bencode_dictionary_add_string(d, "status", "unknown peer address"); + + s = bencode_dictionary_add(d, "stats", bencode_dictionary(b)); + bencode_dictionary_add(s, "rtp", streamrelay_stats(b, &p->rtps[0])); + bencode_dictionary_add(s, "rtcp", streamrelay_stats(b, &p->rtps[1])); + + return d; +} + +const char *call_query_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { + str callid, fromtag, totag; + struct call *call; + GList *l; + struct callstream *cs; + bencode_item_t *streams, *stream; + struct peer *p, *px; + unsigned long long totals[4] = {0,0,0,0}; + int i; + + if (!bencode_dictionary_get_str(input, "call-id", &callid)) + return "No call-id in message"; + call = call_get_opmode(&callid, NULL, m, OP_OTHER); + if (!call) + return "Unknown call-id"; + bencode_dictionary_get_str(input, "from-tag", &fromtag); + bencode_dictionary_get_str(input, "to-tag", &totag); + + bencode_dictionary_add_string(output, "result", "ok"); + bencode_dictionary_add_integer(output, "created", call->created); + streams = bencode_dictionary_add(output, "streams", bencode_list(output->buffer)); + + for (l = call->callstreams->head; l; l = l->next) { + cs = l->data; + mutex_lock(&cs->lock); + + for (i = 0; i < 2; i++) { + p = &cs->peers[i]; + px = &cs->peers[i ^ 1]; + + if (!fromtag.len) + goto tag_match; + + if (str_cmp_str(&p->tag, &fromtag)) + continue; + if (!totag.len) + goto tag_match; + + if (str_cmp_str(&px->tag, &totag)) + continue; + +tag_match: + stream = bencode_list_add(streams, bencode_list(output->buffer)); + bencode_list_add(stream, peer_stats(output->buffer, p)); + bencode_list_add(stream, peer_stats(output->buffer, px)); + + totals[0] += p->rtps[0].stats.packets; + totals[1] += px->rtps[0].stats.packets; + totals[2] += p->rtps[1].stats.packets; + totals[3] += px->rtps[1].stats.packets; + + break; + } + + mutex_unlock(&cs->lock); + } + + mutex_unlock(&call->lock); + + return NULL; +} diff --git a/daemon/call.h b/daemon/call.h index 12d88fc3d..f59c2e1bc 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -43,6 +43,7 @@ enum stream_direction { enum call_opmode { OP_OFFER = 0, OP_ANSWER = 1, + OP_OTHER, }; struct stats { @@ -157,6 +158,7 @@ str *call_query_udp(char **, struct callmaster *); const char *call_offer_ng(bencode_item_t *, struct callmaster *, bencode_item_t *); const char *call_answer_ng(bencode_item_t *, struct callmaster *, bencode_item_t *); const char *call_delete_ng(bencode_item_t *, struct callmaster *, bencode_item_t *); +const char *call_query_ng(bencode_item_t *, struct callmaster *, bencode_item_t *); void calls_dump_redis(struct callmaster *); diff --git a/daemon/control_ng.c b/daemon/control_ng.c index f93f0fcca..8c46af77c 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -65,6 +65,8 @@ static void control_ng_incoming(struct obj *obj, str *buf, struct sockaddr_in6 * errstr = call_answer_ng(dict, c->callmaster, resp); else if (!str_cmp(&cmd, "delete")) errstr = call_delete_ng(dict, c->callmaster, resp); + else if (!str_cmp(&cmd, "query")) + errstr = call_query_ng(dict, c->callmaster, resp); else errstr = "Unrecognized command";