|
|
|
|
@ -422,7 +422,7 @@ str *call_query_udp(char **out) {
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ng_call_stats(c, &fromtag, &totag, NULL, &stats);
|
|
|
|
|
ng_call_stats(NULL, c, &fromtag, &totag, &stats);
|
|
|
|
|
|
|
|
|
|
rwlock_unlock_w(&c->master_lock);
|
|
|
|
|
|
|
|
|
|
@ -485,14 +485,14 @@ static void call_release_ref(void *p) {
|
|
|
|
|
call_t *c = p;
|
|
|
|
|
obj_put(c);
|
|
|
|
|
}
|
|
|
|
|
INLINE void call_bencode_hold_ref(call_t *c, bencode_item_t *bi) {
|
|
|
|
|
INLINE void call_bencode_hold_ref(call_t *c, bencode_buffer_t *buf) {
|
|
|
|
|
/* We cannot guarantee that the "call" structures are still around at the time
|
|
|
|
|
* when the bencode reply is finally read and sent out. Since we use scatter/gather
|
|
|
|
|
* to avoid duplication of strings and stuff, we reserve a reference to the call
|
|
|
|
|
* structs and have it released when the bencode buffer is destroyed. This is
|
|
|
|
|
* necessary every time the bencode response may reference strings contained
|
|
|
|
|
* within the call structs. */
|
|
|
|
|
bencode_buffer_destroy_add(bi->buffer, call_release_ref, obj_get(c));
|
|
|
|
|
bencode_buffer_destroy_add(buf, call_release_ref, obj_get(c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INLINE void str_hyphenate(str *s_ori) {
|
|
|
|
|
@ -2196,7 +2196,7 @@ static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode o
|
|
|
|
|
|
|
|
|
|
/* At least the random ICE strings are contained within the call struct, so we
|
|
|
|
|
* need to hold a ref until we're done sending the reply */
|
|
|
|
|
call_bencode_hold_ref(call, output);
|
|
|
|
|
call_bencode_hold_ref(call, &ctx->ngbuf->buffer);
|
|
|
|
|
|
|
|
|
|
errstr = "Invalid dialogue association";
|
|
|
|
|
if (call_get_mono_dialogue(monologues, call, &flags.from_tag, &flags.to_tag,
|
|
|
|
|
@ -2324,7 +2324,7 @@ const char *call_delete_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
if (discard)
|
|
|
|
|
recording_discard(c);
|
|
|
|
|
|
|
|
|
|
if (call_delete_branch(c, &viabranch, &fromtag, &totag, output, delete_delay))
|
|
|
|
|
if (call_delete_branch(c, &viabranch, &fromtag, &totag, ctx, delete_delay))
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
@ -2332,7 +2332,7 @@ const char *call_delete_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
err:
|
|
|
|
|
if (fatal)
|
|
|
|
|
return "Call-ID not found or tags didn't match";
|
|
|
|
|
bencode_dictionary_add_string(output, "warning", "Call-ID not found or tags didn't match");
|
|
|
|
|
ctx->parser->dict_add_string(output, "warning", "Call-ID not found or tags didn't match");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -2347,10 +2347,10 @@ static void ng_stats(bencode_item_t *d, const struct stream_stats *s, struct str
|
|
|
|
|
atomic64_add_na(&totals->errors, atomic64_get(&s->errors));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ng_stats_endpoint(bencode_item_t *dict, const endpoint_t *ep) {
|
|
|
|
|
static void ng_stats_endpoint(const ng_parser_t *parser, bencode_item_t *dict, const endpoint_t *ep) {
|
|
|
|
|
if (!ep->address.family)
|
|
|
|
|
return;
|
|
|
|
|
bencode_dictionary_add_string(dict, "family", ep->address.family->name);
|
|
|
|
|
parser->dict_add_string(dict, "family", ep->address.family->name);
|
|
|
|
|
bencode_dictionary_add_str_dup(dict, "address", &STR(sockaddr_print_buf(&ep->address)));
|
|
|
|
|
bencode_dictionary_add_integer(dict, "port", ep->port);
|
|
|
|
|
}
|
|
|
|
|
@ -2377,7 +2377,7 @@ static void ng_stats_stream_ssrc(bencode_item_t *dict, struct ssrc_ctx *const ss
|
|
|
|
|
|
|
|
|
|
#define BF_PS(k, f) if (PS_ISSET(ps, f)) bencode_list_add_string(flags, k)
|
|
|
|
|
|
|
|
|
|
static void ng_stats_stream(bencode_item_t *list, const struct packet_stream *ps,
|
|
|
|
|
static void ng_stats_stream(const ng_parser_t *parser, bencode_item_t *list, const struct packet_stream *ps,
|
|
|
|
|
struct call_stats *totals)
|
|
|
|
|
{
|
|
|
|
|
bencode_item_t *dict = NULL, *flags;
|
|
|
|
|
@ -2392,13 +2392,13 @@ static void ng_stats_stream(bencode_item_t *list, const struct packet_stream *ps
|
|
|
|
|
bencode_dictionary_add_integer(dict, "local port", ps->selected_sfd->socket.local.port);
|
|
|
|
|
bencode_dictionary_add_str_dup(dict, "local address",
|
|
|
|
|
&STR(sockaddr_print_buf(&ps->selected_sfd->socket.local.address)));
|
|
|
|
|
bencode_dictionary_add_string(dict, "family", ps->selected_sfd->socket.local.address.family->name);
|
|
|
|
|
parser->dict_add_string(dict, "family", ps->selected_sfd->socket.local.address.family->name);
|
|
|
|
|
}
|
|
|
|
|
ng_stats_endpoint(bencode_dictionary_add_dictionary(dict, "endpoint"), &ps->endpoint);
|
|
|
|
|
ng_stats_endpoint(bencode_dictionary_add_dictionary(dict, "advertised endpoint"),
|
|
|
|
|
ng_stats_endpoint(parser, bencode_dictionary_add_dictionary(dict, "endpoint"), &ps->endpoint);
|
|
|
|
|
ng_stats_endpoint(parser, bencode_dictionary_add_dictionary(dict, "advertised endpoint"),
|
|
|
|
|
&ps->advertised_endpoint);
|
|
|
|
|
if (ps->crypto.params.crypto_suite)
|
|
|
|
|
bencode_dictionary_add_string(dict, "crypto suite",
|
|
|
|
|
parser->dict_add_string(dict, "crypto suite",
|
|
|
|
|
ps->crypto.params.crypto_suite->name);
|
|
|
|
|
bencode_dictionary_add_integer(dict, "last packet", packet_stream_last_packet(ps));
|
|
|
|
|
bencode_dictionary_add_integer(dict, "last kernel packet", atomic64_get_na(&ps->stats_in->last_packet));
|
|
|
|
|
@ -2435,7 +2435,7 @@ stats:
|
|
|
|
|
|
|
|
|
|
#define BF_M(k, f) if (MEDIA_ISSET(m, f)) bencode_list_add_string(flags, k)
|
|
|
|
|
|
|
|
|
|
static void ng_stats_media(bencode_item_t *list, const struct call_media *m,
|
|
|
|
|
static void ng_stats_media(const ng_parser_t *parser, bencode_item_t *list, const struct call_media *m,
|
|
|
|
|
struct call_stats *totals)
|
|
|
|
|
{
|
|
|
|
|
bencode_item_t *dict, *streams = NULL, *flags;
|
|
|
|
|
@ -2452,7 +2452,7 @@ static void ng_stats_media(bencode_item_t *list, const struct call_media *m,
|
|
|
|
|
bencode_dictionary_add_integer(dict, "index", m->index);
|
|
|
|
|
bencode_dictionary_add_str(dict, "type", &m->type);
|
|
|
|
|
if (m->protocol)
|
|
|
|
|
bencode_dictionary_add_string(dict, "protocol", m->protocol->name);
|
|
|
|
|
parser->dict_add_string(dict, "protocol", m->protocol->name);
|
|
|
|
|
if (rtp_pt)
|
|
|
|
|
bencode_dictionary_add_str_dup(dict, "codec", &rtp_pt->encoding_with_params);
|
|
|
|
|
|
|
|
|
|
@ -2493,11 +2493,11 @@ static void ng_stats_media(bencode_item_t *list, const struct call_media *m,
|
|
|
|
|
stats:
|
|
|
|
|
for (auto_iter(l, m->streams.head); l; l = l->next) {
|
|
|
|
|
ps = l->data;
|
|
|
|
|
ng_stats_stream(streams, ps, totals);
|
|
|
|
|
ng_stats_stream(parser, streams, ps, totals);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue *ml,
|
|
|
|
|
static void ng_stats_monologue(const ng_parser_t *parser, bencode_item_t *dict, const struct call_monologue *ml,
|
|
|
|
|
struct call_stats *totals, bencode_item_t *ssrc)
|
|
|
|
|
{
|
|
|
|
|
bencode_item_t *sub, *medias = NULL;
|
|
|
|
|
@ -2542,7 +2542,7 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue
|
|
|
|
|
if (!g_queue_find(&mls_subscriptions, ms->monologue)) {
|
|
|
|
|
bencode_item_t *sub1 = bencode_list_add_dictionary(b_subscriptions);
|
|
|
|
|
bencode_dictionary_add_str(sub1, "tag", &ms->monologue->tag);
|
|
|
|
|
bencode_dictionary_add_string(sub1, "type", ms->attrs.offer_answer ? "offer/answer" : "pub/sub");
|
|
|
|
|
parser->dict_add_string(sub1, "type", ms->attrs.offer_answer ? "offer/answer" : "pub/sub");
|
|
|
|
|
g_queue_push_tail(&mls_subscriptions, ms->monologue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -2554,7 +2554,7 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue
|
|
|
|
|
if (!g_queue_find(&mls_subscribers, ms->monologue)) {
|
|
|
|
|
bencode_item_t *sub1 = bencode_list_add_dictionary(b_subscribers);
|
|
|
|
|
bencode_dictionary_add_str(sub1, "tag", &ms->monologue->tag);
|
|
|
|
|
bencode_dictionary_add_string(sub1, "type", ms->attrs.offer_answer ? "offer/answer" : "pub/sub");
|
|
|
|
|
parser->dict_add_string(sub1, "type", ms->attrs.offer_answer ? "offer/answer" : "pub/sub");
|
|
|
|
|
g_queue_push_tail(&mls_subscribers, ms->monologue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -2572,7 +2572,7 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue
|
|
|
|
|
bencode_item_t *vsc = bencode_list_add_dictionary(list);
|
|
|
|
|
const char *type = dtmf_trigger_types[state->type];
|
|
|
|
|
if (type)
|
|
|
|
|
bencode_dictionary_add_string(vsc, "type", type);
|
|
|
|
|
parser->dict_add_string(vsc, "type", type);
|
|
|
|
|
bencode_dictionary_add_str(vsc, "trigger", &state->trigger);
|
|
|
|
|
bencode_dictionary_add_integer(vsc, "active", !state->inactive);
|
|
|
|
|
}
|
|
|
|
|
@ -2588,7 +2588,7 @@ stats:
|
|
|
|
|
m = ml->medias->pdata[i];
|
|
|
|
|
if (!m)
|
|
|
|
|
continue;
|
|
|
|
|
ng_stats_media(medias, m, totals);
|
|
|
|
|
ng_stats_media(parser, medias, m, totals);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -2665,7 +2665,7 @@ static void ng_stats_ssrc(bencode_item_t *dict, struct ssrc_hash *ht) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* call must be locked */
|
|
|
|
|
void ng_call_stats(call_t *call, const str *fromtag, const str *totag, bencode_item_t *output,
|
|
|
|
|
void ng_call_stats(ng_parser_ctx_t *ctx, call_t *call, const str *fromtag, const str *totag,
|
|
|
|
|
struct call_stats *totals)
|
|
|
|
|
{
|
|
|
|
|
bencode_item_t *tags = NULL, *dict;
|
|
|
|
|
@ -2678,18 +2678,18 @@ void ng_call_stats(call_t *call, const str *fromtag, const str *totag, bencode_i
|
|
|
|
|
totals = &t_b;
|
|
|
|
|
ZERO(*totals);
|
|
|
|
|
|
|
|
|
|
if (!output)
|
|
|
|
|
if (!ctx)
|
|
|
|
|
goto stats;
|
|
|
|
|
|
|
|
|
|
call_bencode_hold_ref(call, output);
|
|
|
|
|
call_bencode_hold_ref(call, &ctx->ngbuf->buffer);
|
|
|
|
|
|
|
|
|
|
bencode_dictionary_add_integer(output, "created", call->created.tv_sec);
|
|
|
|
|
bencode_dictionary_add_integer(output, "created_us", call->created.tv_usec);
|
|
|
|
|
bencode_dictionary_add_integer(output, "last signal", call->last_signal);
|
|
|
|
|
bencode_dictionary_add_integer(output, "last redis update", atomic64_get_na(&call->last_redis_update));
|
|
|
|
|
bencode_dictionary_add_integer(ctx->resp, "created", call->created.tv_sec);
|
|
|
|
|
bencode_dictionary_add_integer(ctx->resp, "created_us", call->created.tv_usec);
|
|
|
|
|
bencode_dictionary_add_integer(ctx->resp, "last signal", call->last_signal);
|
|
|
|
|
bencode_dictionary_add_integer(ctx->resp, "last redis update", atomic64_get_na(&call->last_redis_update));
|
|
|
|
|
|
|
|
|
|
ssrc = bencode_dictionary_add_dictionary(output, "SSRC");
|
|
|
|
|
tags = bencode_dictionary_add_dictionary(output, "tags");
|
|
|
|
|
ssrc = bencode_dictionary_add_dictionary(ctx->resp, "SSRC");
|
|
|
|
|
tags = bencode_dictionary_add_dictionary(ctx->resp, "tags");
|
|
|
|
|
|
|
|
|
|
stats:
|
|
|
|
|
match_tag = (totag && totag->s && totag->len) ? totag : fromtag;
|
|
|
|
|
@ -2697,13 +2697,13 @@ stats:
|
|
|
|
|
if (!match_tag || !match_tag->len) {
|
|
|
|
|
for (__auto_type l = call->monologues.head; l; l = l->next) {
|
|
|
|
|
ml = l->data;
|
|
|
|
|
ng_stats_monologue(tags, ml, totals, ssrc);
|
|
|
|
|
ng_stats_monologue(ctx->parser, tags, ml, totals, ssrc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ml = call_get_monologue(call, match_tag);
|
|
|
|
|
if (ml) {
|
|
|
|
|
ng_stats_monologue(tags, ml, totals, ssrc);
|
|
|
|
|
ng_stats_monologue(ctx->parser, tags, ml, totals, ssrc);
|
|
|
|
|
g_auto(GQueue) mls = G_QUEUE_INIT; /* to avoid duplications */
|
|
|
|
|
for (int i = 0; i < ml->medias->len; i++)
|
|
|
|
|
{
|
|
|
|
|
@ -2717,7 +2717,7 @@ stats:
|
|
|
|
|
{
|
|
|
|
|
struct media_subscription * ms = subscription->data;
|
|
|
|
|
if (!g_queue_find(&mls, ms->monologue)) {
|
|
|
|
|
ng_stats_monologue(tags, ms->monologue, totals, ssrc);
|
|
|
|
|
ng_stats_monologue(ctx->parser, tags, ms->monologue, totals, ssrc);
|
|
|
|
|
g_queue_push_tail(&mls, ms->monologue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -2725,15 +2725,15 @@ stats:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!output)
|
|
|
|
|
if (!ctx)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
dict = bencode_dictionary_add_dictionary(output, "totals");
|
|
|
|
|
dict = bencode_dictionary_add_dictionary(ctx->resp, "totals");
|
|
|
|
|
ng_stats(bencode_dictionary_add_dictionary(dict, "RTP"), &totals->totals[0], NULL);
|
|
|
|
|
ng_stats(bencode_dictionary_add_dictionary(dict, "RTCP"), &totals->totals[1], NULL);
|
|
|
|
|
|
|
|
|
|
if (call->recording) {
|
|
|
|
|
bencode_item_t *rec = bencode_dictionary_add_dictionary(output, "recording");
|
|
|
|
|
bencode_item_t *rec = bencode_dictionary_add_dictionary(ctx->resp, "recording");
|
|
|
|
|
bencode_dictionary_add_integer(rec, "call recording", !!CALL_ISSET(call, RECORDING_ON));
|
|
|
|
|
bencode_dictionary_add_integer(rec, "forwarding", !!CALL_ISSET(call, REC_FORWARDING));
|
|
|
|
|
}
|
|
|
|
|
@ -2759,7 +2759,6 @@ const char *call_query_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
str callid, fromtag, totag;
|
|
|
|
|
call_t *call;
|
|
|
|
|
bencode_item_t *input = ctx->req;
|
|
|
|
|
bencode_item_t *output = ctx->resp;
|
|
|
|
|
|
|
|
|
|
if (!ctx->parser->dict_get_str(input, "call-id", &callid))
|
|
|
|
|
return "No call-id in message";
|
|
|
|
|
@ -2769,7 +2768,7 @@ const char *call_query_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
ctx->parser->dict_get_str(input, "from-tag", &fromtag);
|
|
|
|
|
ctx->parser->dict_get_str(input, "to-tag", &totag);
|
|
|
|
|
|
|
|
|
|
ng_call_stats(call, &fromtag, &totag, output, NULL);
|
|
|
|
|
ng_call_stats(ctx, call, &fromtag, &totag, NULL);
|
|
|
|
|
rwlock_unlock_w(&call->master_lock);
|
|
|
|
|
obj_put(call);
|
|
|
|
|
|
|
|
|
|
@ -3772,7 +3771,7 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
bencode_dictionary_add_integer(med_ent, "index", media->index);
|
|
|
|
|
bencode_dictionary_add_str(med_ent, "type", &media->type);
|
|
|
|
|
bencode_dictionary_add_str(med_ent, "label", &media->label);
|
|
|
|
|
bencode_dictionary_add_string(med_ent, "mode", sdp_get_sendrecv(media));
|
|
|
|
|
ctx->parser->dict_add_string(med_ent, "mode", sdp_get_sendrecv(media));
|
|
|
|
|
|
|
|
|
|
if (media_labels) {
|
|
|
|
|
bencode_item_t *label =
|
|
|
|
|
@ -3782,7 +3781,7 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) {
|
|
|
|
|
bencode_dictionary_add_str(label, "type", &media->type);
|
|
|
|
|
if (source_ml->label.len)
|
|
|
|
|
bencode_dictionary_add_str(label, "label", &source_ml->label);
|
|
|
|
|
bencode_dictionary_add_string(label, "mode", sdp_get_sendrecv(media));
|
|
|
|
|
ctx->parser->dict_add_string(label, "mode", sdp_get_sendrecv(media));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|