From 223c7f17dd8d5aac19eeee1f0412700e160bffc8 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 30 Mar 2017 13:01:20 -0400 Subject: [PATCH] TT#12800 abstractize rtcp parsing and logging functions Change-Id: I26e02a6851a51ea0720ac8ce1fc4a9e27d2ffec4 --- daemon/call.c | 1 + daemon/call.h | 3 - daemon/homer.c | 34 ++-- daemon/homer.h | 8 +- daemon/main.c | 5 +- daemon/rtcp.c | 446 ++++++++++++++++++++++++++++++----------------- daemon/rtcp.h | 2 + daemon/rtcp_xr.c | 2 +- daemon/rtcp_xr.h | 2 +- 9 files changed, 324 insertions(+), 179 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 02f151cbc..49eb8c529 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -882,6 +882,7 @@ static void __fill_stream(struct packet_stream *ps, const struct endpoint *epp, if (PS_ISSET(ps, FILLED)) { /* we reset crypto params whenever the endpoint changes */ + // XXX fix WRT SSRC handling crypto_reset(&ps->crypto); dtls_shutdown(ps); } diff --git a/daemon/call.h b/daemon/call.h index dae947051..01a02a11e 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -203,7 +203,6 @@ struct sdp_ng_flags; struct local_interface; struct call_monologue; struct ice_agent; -struct homer_sender; struct ssrc_hash; @@ -436,8 +435,6 @@ struct callmaster { struct callmaster_config conf; struct timeval latest_graphite_interval_start; - - struct homer_sender *homer; }; struct callmaster *callmaster_new(struct poller *); diff --git a/daemon/homer.c b/daemon/homer.c index e9d49c881..ee067e00a 100644 --- a/daemon/homer.c +++ b/daemon/homer.c @@ -38,6 +38,10 @@ struct homer_sender { +static struct homer_sender *main_homer_sender; + + + static int send_hepv3 (GString *s, const str *id, int, const endpoint_t *src, const endpoint_t *dst, const struct timeval *); @@ -178,11 +182,13 @@ static int __no_socket(struct homer_sender *hs) { return __check_conn(hs, ret); } -struct homer_sender *homer_sender_new(const endpoint_t *ep, int protocol, int capture_id) { +void homer_sender_init(const endpoint_t *ep, int protocol, int capture_id) { struct homer_sender *ret; if (is_addr_unspecified(&ep->address)) - return NULL; + return; + if (main_homer_sender) + return; ret = malloc(sizeof(*ret)); ZERO(*ret); @@ -194,14 +200,16 @@ struct homer_sender *homer_sender_new(const endpoint_t *ep, int protocol, int ca ret->state = __no_socket; - return ret; + main_homer_sender = ret; + + return; } // takes over the GString -int homer_send(struct homer_sender *hs, GString *s, const str *id, const endpoint_t *src, +int homer_send(GString *s, const str *id, const endpoint_t *src, const endpoint_t *dst, const struct timeval *tv) { - if (!hs) + if (!main_homer_sender) goto out; if (!s) goto out; @@ -210,18 +218,18 @@ int homer_send(struct homer_sender *hs, GString *s, const str *id, const endpoin ilog(LOG_DEBUG, "JSON to send to Homer: '"STR_FORMAT"'", G_STR_FMT(s)); - if (send_hepv3(s, id, hs->capture_id, src, dst, tv)) + if (send_hepv3(s, id, main_homer_sender->capture_id, src, dst, tv)) goto out; - mutex_lock(&hs->lock); - if (hs->send_queue.length < SEND_QUEUE_LIMIT) { - g_queue_push_tail(&hs->send_queue, s); + mutex_lock(&main_homer_sender->lock); + if (main_homer_sender->send_queue.length < SEND_QUEUE_LIMIT) { + g_queue_push_tail(&main_homer_sender->send_queue, s); s = NULL; } else ilog(LOG_ERR, "Send queue length limit (%i) reached, dropping Homer message", SEND_QUEUE_LIMIT); - hs->state(hs); - mutex_unlock(&hs->lock); + main_homer_sender->state(main_homer_sender); + mutex_unlock(&main_homer_sender->lock); out: if (s) @@ -557,3 +565,7 @@ static int send_hepv3 (GString *s, const str *id, int capt_id, const endpoint_t return 0; } + +int has_homer() { + return main_homer_sender ? 1 : 0; +} diff --git a/daemon/homer.h b/daemon/homer.h index 690bc200e..ef9345cd6 100644 --- a/daemon/homer.h +++ b/daemon/homer.h @@ -4,12 +4,10 @@ #include "socket.h" -struct homer_sender; - - -struct homer_sender *homer_sender_new(const endpoint_t *, int, int); -int homer_send(struct homer_sender *, GString *, const str *, const endpoint_t *, const endpoint_t *, +void homer_sender_init(const endpoint_t *, int, int); +int homer_send(GString *, const str *, const endpoint_t *, const endpoint_t *, const struct timeval *tv); +int has_homer(); #endif diff --git a/daemon/main.c b/daemon/main.c index 10217dc94..d08ae44e8 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -32,6 +32,7 @@ #include "homer.h" #include "recording.h" #include "auxlib.h" +#include "rtcp.h" @@ -594,7 +595,9 @@ no_kernel: daemonize(); wpidfile(); - ctx->m->homer = homer_sender_new(&homer_ep, homer_protocol, homer_id); + homer_sender_init(&homer_ep, homer_protocol, homer_id); + + rtcp_init(); // must come after Homer init if (mc.redis) { // start redis restore timer diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 0c5921869..fa9e045a0 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -130,6 +130,117 @@ struct rtcp_chain_element { } u; }; +// log handlers +// struct defs +// context to hold state variables +struct rtcp_process_ctx { + u_int32_t scratch; + GString *log; + GString *json; +}; +// all available methods +struct rtcp_handler { + void (*init)(struct rtcp_process_ctx *); + void (*start)(struct rtcp_process_ctx *, struct call *); + void (*common)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); + void (*sr)(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); + void (*rr_list_start)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); + void (*rr)(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); + void (*rr_list_end)(struct rtcp_process_ctx *); + void (*xr)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *, str *); + void (*sdes_list_start)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); + void (*sdes_item)(struct rtcp_process_ctx *, const rtcp_sdes_chunk_t *, const rtcp_sdes_item_t *, + const char *); + void (*sdes_list_end)(struct rtcp_process_ctx *); + void (*finish)(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *, + const struct timeval *); + void (*destroy)(struct rtcp_process_ctx *); +}; +// collection of all handler types +struct rtcp_handlers { + const struct rtcp_handler + *scratch, + *logging, + *homer; +}; + +// log handler function prototypes +static void dummy_handler(); + +// scratch area (prepare/parse packet) +static void scratch_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); + +// homer functions +static void homer_init(struct rtcp_process_ctx *); +static void homer_sr(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); +static void homer_rr_list_start(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); +static void homer_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); +static void homer_rr_list_end(struct rtcp_process_ctx *); +static void homer_sdes_list_start(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); +static void homer_sdes_item(struct rtcp_process_ctx *, const rtcp_sdes_chunk_t *, const rtcp_sdes_item_t *, + const char *); +static void homer_sdes_list_end(struct rtcp_process_ctx *); +static void homer_finish(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *, + const struct timeval *); + +// syslog functions +static void logging_init(struct rtcp_process_ctx *); +static void logging_start(struct rtcp_process_ctx *, struct call *); +static void logging_common(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); +static void logging_sr(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); +static void logging_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); +static void logging_xr(struct rtcp_process_ctx *, const pjmedia_rtcp_common *, str *); +static void logging_finish(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *, + const struct timeval *); +static void logging_destroy(struct rtcp_process_ctx *); + +// structs for each handler type +static struct rtcp_handler dummy_handlers; +static struct rtcp_handler scratch_handlers = { + .rr = scratch_rr, +}; +static struct rtcp_handler log_handlers = { + .init = logging_init, + .start = logging_start, + .common = logging_common, + .sr = logging_sr, + .rr = logging_rr, + .xr = logging_xr, + .finish = logging_finish, + .destroy = logging_destroy, +}; +static struct rtcp_handler homer_handlers = { + .init = homer_init, + .sr = homer_sr, + .rr_list_start = homer_rr_list_start, + .rr = homer_rr, + .rr_list_end = homer_rr_list_end, + .sdes_list_start = homer_sdes_list_start, + .sdes_item = homer_sdes_item, + .sdes_list_end = homer_sdes_list_end, + .finish = homer_finish, +}; + +// main var to hold references +static struct rtcp_handlers rtcp_handlers = { + .scratch = &scratch_handlers, +}; + +// list of all handlers +static struct rtcp_handler *all_handlers[] = { + &dummy_handlers, + &scratch_handlers, + &log_handlers, + &homer_handlers, +}; + +// macro to call all function handlers in one go +#define CAH(func, ...) do { \ + rtcp_handlers.scratch->func(&log_ctx, ##__VA_ARGS__); \ + rtcp_handlers.logging->func(&log_ctx, ##__VA_ARGS__); \ + rtcp_handlers.homer->func(&log_ctx, ##__VA_ARGS__); \ + } while (0) + @@ -255,6 +366,7 @@ static void rtcp_list_free(GQueue *q) { g_queue_clear_full(q, rtcp_ce_free); } +// XXX do this only once for each RTCP packet and use the resulting list for everything static int rtcp_parse(GQueue *q, str *_s) { struct rtcp_packet *hdr; struct rtcp_chain_element *el; @@ -467,161 +579,28 @@ error: } -static void print_rtcp_common(GString *log, const pjmedia_rtcp_common *common) { - if (log) - g_string_append_printf(log,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", - common->version, - common->p, - common->count, - common->pt, - ntohl(common->length), - ntohl(common->ssrc)); -} - -static void print_rtcp_sr(GString *log, const pjmedia_rtcp_sr* sr, GString *json) { - if (log) - g_string_append_printf(log,"ntp_sec=%u, ntp_fractions=%u, rtp_ts=%u, sender_packets=%u, sender_bytes=%u, ", - ntohl(sr->ntp_sec), - ntohl(sr->ntp_frac), - ntohl(sr->rtp_ts), - ntohl(sr->sender_pcount), - ntohl(sr->sender_bcount)); - - if (json) - g_string_append_printf(json, "\"sender_information\":{\"ntp_timestamp_sec\":%u," - "\"ntp_timestamp_usec\":%u,\"octets\":%u,\"rtp_timestamp\":%u, \"packets\":%u},", - ntohl(sr->ntp_sec), - ntohl(sr->ntp_frac), - ntohl(sr->sender_bcount), - ntohl(sr->rtp_ts), - ntohl(sr->sender_pcount)); -} - -static void print_rtcp_rr_list_start(pjmedia_rtcp_common *common, GString *json) { - if (json) - g_string_append_printf(json, "\"ssrc\":%u,\"type\":%u,\"report_count\":%u,\"report_blocks\":[", - ntohl(common->ssrc), - common->pt, - 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; - packet_loss = (rr->total_lost_2 << 16) + - (rr->total_lost_1 << 8) + - rr->total_lost_0; - - if (log) - g_string_append_printf(log,"ssrc=%u, fraction_lost=%u, packet_loss=%u, last_seq=%u, jitter=%u, last_sr=%u, delay_since_last_sr=%u, ", - ntohl(rr->ssrc), - rr->fract_lost, - packet_loss, - ntohl(rr->last_seq), - ntohl(rr->jitter), - ntohl(rr->lsr), - ntohl(rr->dlsr)); - - if (json) - g_string_append_printf(json, "{\"source_ssrc\":%u," - "\"highest_seq_no\":%u,\"fraction_lost\":%u,\"ia_jitter\":%u," - "\"packets_lost\":%u,\"lsr\":%u,\"dlsr\":%u},", - ntohl(rr->ssrc), - ntohl(rr->last_seq), - rr->fract_lost, - ntohl(rr->jitter), - packet_loss, - ntohl(rr->lsr), - 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_list_end(GString *json) { - if (json) { - str_sanitize(json); - g_string_append_printf(json, "],"); - } -} - void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const endpoint_t *src, const struct timeval *tv) { - GString *log; str iter_s, comp_s; pjmedia_rtcp_common *common; 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; int i; + struct rtcp_process_ctx log_ctx; - log = _log_facility_rtcp ? g_string_new(NULL) : NULL; - json = cm->homer ? g_string_new("{ ") : NULL; - - // anything to do? - if (!log && !json) - return; - - if (log) - g_string_append_printf(log, "["STR_FORMAT"] ", STR_FMT(&sfd->stream->call->callid)); + ZERO(log_ctx); + CAH(init); + CAH(start, c); iter_s = *ori_s; @@ -639,7 +618,7 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en if (str_shift(&iter_s, (ntohs(common->length) + 1) << 2)) // puts iter_s on the next compound packet break; - print_rtcp_common(log, common); + CAH(common, common); /* Parse RTCP */ switch (common->pt) { @@ -648,28 +627,28 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en if (str_shift(&comp_s, sizeof(*sr))) break; - print_rtcp_sr(log, sr, json); + CAH(sr, sr); // fall through to RTCP_PT_RR case RTCP_PT_RR: - print_rtcp_rr_list_start(common, json); + CAH(rr_list_start, common); for (i = 0; i < common->count; i++) { rr = (pjmedia_rtcp_rr*)((comp_s.s)); if (str_shift(&comp_s, sizeof(*rr))) break; - print_rtcp_rr(log, rr, json); + CAH(rr, rr); } - print_rtcp_list_end(json); + CAH(rr_list_end); break; case RTCP_PT_XR: - pjmedia_rtcp_xr_rx_rtcp_xr(log, common, &comp_s); + CAH(xr, common, &comp_s); break; case RTCP_PT_SDES: - print_rtcp_sdes_list_start(common, json); + CAH(sdes_list_start, common); // the "common" header actually includes the SDES // SSRC/CSRC chunk header, so we set our chunk header @@ -690,7 +669,7 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en break; if (comp_s.len < sdes_item->len) break; - print_rtcp_sdes_item(json, sdes_chunk, sdes_item, comp_s.s); + CAH(sdes_item, sdes_chunk, sdes_item, comp_s.s); str_shift(&comp_s, sdes_item->len); } @@ -708,24 +687,177 @@ void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const en } - print_rtcp_list_end(json); + CAH(sdes_list_end); break; } } - if (log) { - str_sanitize(log); - rtcplog(log->str); - } + CAH(finish, c, src, &sfd->socket.local, tv); + CAH(destroy); +} + +static void dummy_handler() { + return; +} + +static void scratch_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { + ctx->scratch = (rr->total_lost_2 << 16) + (rr->total_lost_1 << 8) + rr->total_lost_0; +} - if (json) { - str_sanitize(json); - g_string_append(json, " }"); - homer_send(cm->homer, json, &c->callid, src, &sfd->socket.local, tv); - json = NULL; +static void homer_init(struct rtcp_process_ctx *ctx) { + ctx->json = g_string_new("{ "); +} +static void homer_sr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_sr* sr) { + g_string_append_printf(ctx->json, "\"sender_information\":{\"ntp_timestamp_sec\":%u," + "\"ntp_timestamp_usec\":%u,\"octets\":%u,\"rtp_timestamp\":%u, \"packets\":%u},", + ntohl(sr->ntp_sec), + ntohl(sr->ntp_frac), + ntohl(sr->sender_bcount), + ntohl(sr->rtp_ts), + ntohl(sr->sender_pcount)); +} +static void homer_rr_list_start(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common) { + g_string_append_printf(ctx->json, "\"ssrc\":%u,\"type\":%u,\"report_count\":%u,\"report_blocks\":[", + ntohl(common->ssrc), + common->pt, + common->count); +} +static void homer_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { + g_string_append_printf(ctx->json, "{\"source_ssrc\":%u," + "\"highest_seq_no\":%u,\"fraction_lost\":%u,\"ia_jitter\":%u," + "\"packets_lost\":%u,\"lsr\":%u,\"dlsr\":%u},", + ntohl(rr->ssrc), + ntohl(rr->last_seq), + rr->fract_lost, + ntohl(rr->jitter), + ctx->scratch, + ntohl(rr->lsr), + ntohl(rr->dlsr)); +} +static void homer_rr_list_end(struct rtcp_process_ctx *ctx) { + str_sanitize(ctx->json); + g_string_append_printf(ctx->json, "],"); +} +static void homer_sdes_list_start(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common) { + g_string_append_printf(ctx->json, "\"sdes_ssrc\":%u,\"sdes_report_count\":%u,\"sdes_information\": [ ", + ntohl(common->ssrc), + common->count); +} +static void homer_sdes_item(struct rtcp_process_ctx *ctx, const rtcp_sdes_chunk_t *chunk, + const rtcp_sdes_item_t *item, const char *data) +{ + int i; + + g_string_append_printf(ctx->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(ctx->json, "\\\""); + break; + case '\\': + g_string_append(ctx->json, "\\\\"); + break; + case '\b': + g_string_append(ctx->json, "\\b"); + break; + case '\f': + g_string_append(ctx->json, "\\f"); + break; + case '\n': + g_string_append(ctx->json, "\\n"); + break; + case '\r': + g_string_append(ctx->json, "\\r"); + break; + case '\t': + g_string_append(ctx->json, "\\t"); + break; + default: + g_string_append_c(ctx->json, data[i]); + break; + } } - if (log) - g_string_free(log, TRUE); + g_string_append(ctx->json, "\"},"); +} +static void homer_sdes_list_end(struct rtcp_process_ctx *ctx) { + str_sanitize(ctx->json); + g_string_append_printf(ctx->json, "],"); +} +static void homer_finish(struct rtcp_process_ctx *ctx, struct call *c, const endpoint_t *src, + const endpoint_t *dst, const struct timeval *tv) +{ + str_sanitize(ctx->json); + g_string_append(ctx->json, " }"); + homer_send(ctx->json, &c->callid, src, dst, tv); + ctx->json = NULL; +} + +static void logging_init(struct rtcp_process_ctx *ctx) { + ctx->log = g_string_new(NULL); +} +static void logging_start(struct rtcp_process_ctx *ctx, struct call *c) { + g_string_append_printf(ctx->log, "["STR_FORMAT"] ", STR_FMT(&c->callid)); +} +static void logging_common(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common) { + g_string_append_printf(ctx->log,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", + common->version, + common->p, + common->count, + common->pt, + ntohl(common->length), + ntohl(common->ssrc)); +} +static void logging_sr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_sr* sr) { + g_string_append_printf(ctx->log,"ntp_sec=%u, ntp_fractions=%u, rtp_ts=%u, sender_packets=%u, sender_bytes=%u, ", + ntohl(sr->ntp_sec), + ntohl(sr->ntp_frac), + ntohl(sr->rtp_ts), + ntohl(sr->sender_pcount), + ntohl(sr->sender_bcount)); +} +static void logging_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { + g_string_append_printf(ctx->log,"ssrc=%u, fraction_lost=%u, packet_loss=%u, last_seq=%u, jitter=%u, last_sr=%u, delay_since_last_sr=%u, ", + ntohl(rr->ssrc), + rr->fract_lost, + ctx->scratch, + ntohl(rr->last_seq), + ntohl(rr->jitter), + ntohl(rr->lsr), + ntohl(rr->dlsr)); +} +static void logging_xr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common, str *comp_s) { + pjmedia_rtcp_xr_rx_rtcp_xr(ctx->log, common, comp_s); +} +static void logging_finish(struct rtcp_process_ctx *ctx, struct call *c, const endpoint_t *src, + const endpoint_t *dst, const struct timeval *tv) +{ + str_sanitize(ctx->log); + rtcplog(ctx->log->str); +} +static void logging_destroy(struct rtcp_process_ctx *ctx) { + g_string_free(ctx->log, TRUE); +} + + + +void rtcp_init() { + rtcp_handlers.logging = _log_facility_rtcp ? &log_handlers : &dummy_handlers; + rtcp_handlers.homer = has_homer() ? &homer_handlers : &dummy_handlers; + + // walk through list of handlers and fill missing entries to dummy handler + void *dummy = dummy_handler; + for (int i = 0; i < G_N_ELEMENTS(all_handlers); i++) { + struct rtcp_handler *lh = all_handlers[i]; + for (int j = 0; j < (sizeof(*lh) / sizeof(void *)); j++) { + void **ptr = (void *) lh; + ptr += j; + if (*ptr == NULL) + *ptr = dummy; + } + } } diff --git a/daemon/rtcp.h b/daemon/rtcp.h index 56637947b..8ca5b57c6 100644 --- a/daemon/rtcp.h +++ b/daemon/rtcp.h @@ -88,4 +88,6 @@ int rtcp_savp2avp(str *, struct crypto_context *); void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *, const endpoint_t *, const struct timeval *); +void rtcp_init(); + #endif diff --git a/daemon/rtcp_xr.c b/daemon/rtcp_xr.c index db90dd250..ca49be370 100644 --- a/daemon/rtcp_xr.c +++ b/daemon/rtcp_xr.c @@ -95,7 +95,7 @@ void print_rtcp_xr_rb_voip_mtc(GString *log, const pjmedia_rtcp_xr_rb_voip_mtc * ntohs(rb_voip_mtc->jb_abs_max)); } -void pjmedia_rtcp_xr_rx_rtcp_xr(GString *log, pjmedia_rtcp_common *common, str *s) { +void pjmedia_rtcp_xr_rx_rtcp_xr(GString *log, const pjmedia_rtcp_common *common, str *s) { const pjmedia_rtcp_xr_rb_rr_time *rb_rr_time; const pjmedia_rtcp_xr_rb_dlrr *rb_dlrr; diff --git a/daemon/rtcp_xr.h b/daemon/rtcp_xr.h index 01a5e136c..9249aeedc 100644 --- a/daemon/rtcp_xr.h +++ b/daemon/rtcp_xr.h @@ -191,7 +191,7 @@ typedef struct pjmedia_rtcp_xr_rb_voip_mtc * @param rtcp_pkt The received RTCP XR packet. * @param size Size of the incoming packet. */ -void pjmedia_rtcp_xr_rx_rtcp_xr(GString *, pjmedia_rtcp_common *common, str *s); +void pjmedia_rtcp_xr_rx_rtcp_xr(GString *, const pjmedia_rtcp_common *common, str *s); #pragma pack()