|
|
|
|
@ -513,6 +513,13 @@ static void print_rtcp_rr_list_start(pjmedia_rtcp_common *common, GString *json)
|
|
|
|
|
common->count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_rtcp_sdes_list_start(pjmedia_rtcp_common *common, GString *json) {
|
|
|
|
|
if (json)
|
|
|
|
|
g_string_append_printf(json, "\"sdes_ssrc\":%u,\"sdes_report_count\":%u,\"sdes_information\": [ ",
|
|
|
|
|
ntohl(common->ssrc),
|
|
|
|
|
common->count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_rtcp_rr(GString *log, const pjmedia_rtcp_rr* rr, GString *json) {
|
|
|
|
|
/* Get packet loss */
|
|
|
|
|
u_int32_t packet_loss=0;
|
|
|
|
|
@ -543,12 +550,55 @@ static void print_rtcp_rr(GString *log, const pjmedia_rtcp_rr* rr, GString *json
|
|
|
|
|
ntohl(rr->dlsr));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_rtcp_sdes_item(GString *json, const rtcp_sdes_chunk_t *chunk, const rtcp_sdes_item_t *item,
|
|
|
|
|
const char *data)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (json) {
|
|
|
|
|
g_string_append_printf(json, "{\"sdes_chunk_ssrc\":%u,\"type\":%u,\"text\":\"",
|
|
|
|
|
htonl(chunk->csrc),
|
|
|
|
|
item->type);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < item->len; i++) {
|
|
|
|
|
switch (data[i]) {
|
|
|
|
|
case '"':
|
|
|
|
|
g_string_append(json, "\\\"");
|
|
|
|
|
break;
|
|
|
|
|
case '\\':
|
|
|
|
|
g_string_append(json, "\\\\");
|
|
|
|
|
break;
|
|
|
|
|
case '\b':
|
|
|
|
|
g_string_append(json, "\\b");
|
|
|
|
|
break;
|
|
|
|
|
case '\f':
|
|
|
|
|
g_string_append(json, "\\f");
|
|
|
|
|
break;
|
|
|
|
|
case '\n':
|
|
|
|
|
g_string_append(json, "\\n");
|
|
|
|
|
break;
|
|
|
|
|
case '\r':
|
|
|
|
|
g_string_append(json, "\\r");
|
|
|
|
|
break;
|
|
|
|
|
case '\t':
|
|
|
|
|
g_string_append(json, "\\t");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_string_append_c(json, data[i]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append(json, "\"},");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void str_sanitize(GString *s) {
|
|
|
|
|
while (s->len > 0 && (s->str[s->len - 1] == ' ' || s->str[s->len - 1] == ','))
|
|
|
|
|
g_string_truncate(s, s->len - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_rtcp_rr_list_end(pjmedia_rtcp_common *common, GString *json) {
|
|
|
|
|
static void print_rtcp_list_end(GString *json) {
|
|
|
|
|
if (json) {
|
|
|
|
|
str_sanitize(json);
|
|
|
|
|
g_string_append_printf(json, "],");
|
|
|
|
|
@ -560,8 +610,10 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en
|
|
|
|
|
GString *log;
|
|
|
|
|
str iter_s, comp_s;
|
|
|
|
|
pjmedia_rtcp_common *common;
|
|
|
|
|
const pjmedia_rtcp_rr *rr = NULL;
|
|
|
|
|
const pjmedia_rtcp_sr *sr = NULL;
|
|
|
|
|
const pjmedia_rtcp_rr *rr;
|
|
|
|
|
const pjmedia_rtcp_sr *sr;
|
|
|
|
|
const rtcp_sdes_chunk_t *sdes_chunk;
|
|
|
|
|
const rtcp_sdes_item_t *sdes_item;
|
|
|
|
|
GString *json;
|
|
|
|
|
struct call *c = sfd->call;
|
|
|
|
|
struct callmaster *cm = c->callmaster;
|
|
|
|
|
@ -615,12 +667,56 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en
|
|
|
|
|
print_rtcp_rr(log, rr, json);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_rtcp_rr_list_end(common, json);
|
|
|
|
|
print_rtcp_list_end(json);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RTCP_PT_XR:
|
|
|
|
|
pjmedia_rtcp_xr_rx_rtcp_xr(log, common, &comp_s);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RTCP_PT_SDES:
|
|
|
|
|
print_rtcp_sdes_list_start(common, json);
|
|
|
|
|
|
|
|
|
|
// the "common" header actually includes the SDES
|
|
|
|
|
// SSRC/CSRC chunk header, so we set our chunk header
|
|
|
|
|
// to its SDES field
|
|
|
|
|
sdes_chunk = (rtcp_sdes_chunk_t *) &common->ssrc;
|
|
|
|
|
// comp_s then points into the first SDES item
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
while (comp_s.len) {
|
|
|
|
|
sdes_item = (rtcp_sdes_item_t *) comp_s.s;
|
|
|
|
|
// check for zero type first
|
|
|
|
|
if (str_shift(&comp_s, 1))
|
|
|
|
|
break;
|
|
|
|
|
if (!sdes_item->type)
|
|
|
|
|
break;
|
|
|
|
|
if (str_shift(&comp_s, sizeof(*sdes_item) - 1))
|
|
|
|
|
break;
|
|
|
|
|
if (comp_s.len < sdes_item->len)
|
|
|
|
|
break;
|
|
|
|
|
print_rtcp_sdes_item(json, sdes_chunk, sdes_item, comp_s.s);
|
|
|
|
|
str_shift(&comp_s, sdes_item->len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove padding to next chunk
|
|
|
|
|
while (comp_s.len % 4 != 0)
|
|
|
|
|
str_shift(&comp_s, 1);
|
|
|
|
|
|
|
|
|
|
// more chunks? set chunk header
|
|
|
|
|
i++;
|
|
|
|
|
if (i >= common->count)
|
|
|
|
|
break;
|
|
|
|
|
sdes_chunk = (rtcp_sdes_chunk_t *) comp_s.s;
|
|
|
|
|
if (str_shift(&comp_s, sizeof(*sdes_chunk)))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_rtcp_list_end(json);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|