TT#12800 consolidate and combine RTCP parsing and logging

Change-Id: I8690b5d180b3eaf1c1b0b4295734609c5125a453
changes/68/12468/21
Richard Fuchs 9 years ago
parent 223c7f17dd
commit c1711ea948

@ -576,7 +576,7 @@ static int aes_f8_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r,
memset(iv, 0, 4); memset(iv, 0, 4);
i = htonl(0x80000000ULL | idx); i = htonl(0x80000000ULL | idx);
memcpy(&iv[4], &i, 4); memcpy(&iv[4], &i, 4);
memcpy(&iv[8], &r->header.v_p_x, 8); /* v, p, rc, pt, length, ssrc */ memcpy(&iv[8], r, 8); /* v, p, rc, pt, length, ssrc */
aes_128_f8_encrypt(c, iv, s); aes_128_f8_encrypt(c, iv, s);

@ -34,7 +34,8 @@
#endif #endif
typedef int (*rewrite_func)(str *, struct packet_stream *); typedef int (*rewrite_func)(str *, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
struct streamhandler_io { struct streamhandler_io {
@ -54,13 +55,21 @@ static int __k_null(struct rtpengine_srtp *s, struct packet_stream *);
static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *);
static int __k_srtp_decrypt(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_decrypt(struct rtpengine_srtp *s, struct packet_stream *);
static int call_avp2savp_rtp(str *s, struct packet_stream *); static int call_noop_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
static int call_savp2avp_rtp(str *s, struct packet_stream *); const struct timeval *);
static int call_avp2savp_rtcp(str *s, struct packet_stream *); static int call_avp2savp_rtp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
static int call_savp2avp_rtcp(str *s, struct packet_stream *); const struct timeval *);
static int call_avpf2avp_rtcp(str *s, struct packet_stream *); static int call_savp2avp_rtp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
static int call_avp2savp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
static int call_savp2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
static int call_avpf2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
//static int call_avpf2savp_rtcp(str *s, struct packet_stream *); //static int call_avpf2savp_rtcp(str *s, struct packet_stream *);
static int call_savpf2avp_rtcp(str *s, struct packet_stream *); static int call_savpf2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *,
const struct timeval *);
//static int call_savpf2savp_rtcp(str *s, struct packet_stream *); //static int call_savpf2savp_rtcp(str *s, struct packet_stream *);
@ -70,6 +79,10 @@ static int call_savpf2avp_rtcp(str *s, struct packet_stream *);
static const struct streamhandler_io __shio_noop = { static const struct streamhandler_io __shio_noop = {
.kernel = __k_null, .kernel = __k_null,
}; };
static const struct streamhandler_io __shio_noop_rtp = {
.kernel = __k_null,
.rtcp = call_noop_rtcp,
};
static const struct streamhandler_io __shio_decrypt = { static const struct streamhandler_io __shio_decrypt = {
.kernel = __k_srtp_decrypt, .kernel = __k_srtp_decrypt,
.rtp = call_savp2avp_rtp, .rtp = call_savp2avp_rtp,
@ -96,12 +109,16 @@ static const struct streamhandler __sh_noop = {
.in = &__shio_noop, .in = &__shio_noop,
.out = &__shio_noop, .out = &__shio_noop,
}; };
static const struct streamhandler __sh_noop_rtp = {
.in = &__shio_noop_rtp,
.out = &__shio_noop,
};
static const struct streamhandler __sh_savp2avp = { static const struct streamhandler __sh_savp2avp = {
.in = &__shio_decrypt, .in = &__shio_decrypt,
.out = &__shio_noop, .out = &__shio_noop,
}; };
static const struct streamhandler __sh_avp2savp = { static const struct streamhandler __sh_avp2savp = {
.in = &__shio_noop, .in = &__shio_noop_rtp,
.out = &__shio_encrypt, .out = &__shio_encrypt,
}; };
static const struct streamhandler __sh_avpf2avp = { static const struct streamhandler __sh_avpf2avp = {
@ -128,8 +145,8 @@ static const struct streamhandler __sh_savpf2savp = {
/* ********** */ /* ********** */
static const struct streamhandler * const __sh_matrix_in_rtp_avp[__PROTO_LAST] = { static const struct streamhandler * const __sh_matrix_in_rtp_avp[__PROTO_LAST] = {
[PROTO_RTP_AVP] = &__sh_noop, [PROTO_RTP_AVP] = &__sh_noop_rtp,
[PROTO_RTP_AVPF] = &__sh_noop, [PROTO_RTP_AVPF] = &__sh_noop_rtp,
[PROTO_RTP_SAVP] = &__sh_avp2savp, [PROTO_RTP_SAVP] = &__sh_avp2savp,
[PROTO_RTP_SAVPF] = &__sh_avp2savp, [PROTO_RTP_SAVPF] = &__sh_avp2savp,
[PROTO_UDP_TLS_RTP_SAVP] = &__sh_avp2savp, [PROTO_UDP_TLS_RTP_SAVP] = &__sh_avp2savp,
@ -138,7 +155,7 @@ static const struct streamhandler * const __sh_matrix_in_rtp_avp[__PROTO_LAST] =
}; };
static const struct streamhandler * const __sh_matrix_in_rtp_avpf[__PROTO_LAST] = { static const struct streamhandler * const __sh_matrix_in_rtp_avpf[__PROTO_LAST] = {
[PROTO_RTP_AVP] = &__sh_avpf2avp, [PROTO_RTP_AVP] = &__sh_avpf2avp,
[PROTO_RTP_AVPF] = &__sh_noop, [PROTO_RTP_AVPF] = &__sh_noop_rtp,
[PROTO_RTP_SAVP] = &__sh_avpf2savp, [PROTO_RTP_SAVP] = &__sh_avpf2savp,
[PROTO_RTP_SAVPF] = &__sh_avp2savp, [PROTO_RTP_SAVPF] = &__sh_avp2savp,
[PROTO_UDP_TLS_RTP_SAVP] = &__sh_avpf2savp, [PROTO_UDP_TLS_RTP_SAVP] = &__sh_avpf2savp,
@ -148,17 +165,17 @@ static const struct streamhandler * const __sh_matrix_in_rtp_avpf[__PROTO_LAST]
static const struct streamhandler * const __sh_matrix_in_rtp_savp[__PROTO_LAST] = { static const struct streamhandler * const __sh_matrix_in_rtp_savp[__PROTO_LAST] = {
[PROTO_RTP_AVP] = &__sh_savp2avp, [PROTO_RTP_AVP] = &__sh_savp2avp,
[PROTO_RTP_AVPF] = &__sh_savp2avp, [PROTO_RTP_AVPF] = &__sh_savp2avp,
[PROTO_RTP_SAVP] = &__sh_noop, [PROTO_RTP_SAVP] = &__sh_noop_rtp,
[PROTO_RTP_SAVPF] = &__sh_noop, [PROTO_RTP_SAVPF] = &__sh_noop_rtp,
[PROTO_UDP_TLS_RTP_SAVP] = &__sh_noop, [PROTO_UDP_TLS_RTP_SAVP] = &__sh_noop_rtp,
[PROTO_UDP_TLS_RTP_SAVPF] = &__sh_noop, [PROTO_UDP_TLS_RTP_SAVPF] = &__sh_noop_rtp,
[PROTO_UDPTL] = &__sh_noop, [PROTO_UDPTL] = &__sh_noop,
}; };
static const struct streamhandler * const __sh_matrix_in_rtp_savpf[__PROTO_LAST] = { static const struct streamhandler * const __sh_matrix_in_rtp_savpf[__PROTO_LAST] = {
[PROTO_RTP_AVP] = &__sh_savpf2avp, [PROTO_RTP_AVP] = &__sh_savpf2avp,
[PROTO_RTP_AVPF] = &__sh_savp2avp, [PROTO_RTP_AVPF] = &__sh_savp2avp,
[PROTO_RTP_SAVP] = &__sh_savpf2savp, [PROTO_RTP_SAVP] = &__sh_savpf2savp,
[PROTO_RTP_SAVPF] = &__sh_noop, [PROTO_RTP_SAVPF] = &__sh_noop_rtp,
[PROTO_UDP_TLS_RTP_SAVP] = &__sh_savpf2savp, [PROTO_UDP_TLS_RTP_SAVP] = &__sh_savpf2savp,
[PROTO_UDP_TLS_RTP_SAVPF] = &__sh_noop, [PROTO_UDP_TLS_RTP_SAVPF] = &__sh_noop,
[PROTO_UDPTL] = &__sh_noop, [PROTO_UDPTL] = &__sh_noop,
@ -787,27 +804,49 @@ static int rtcp_demux(str *s, struct call_media *media) {
return rtcp_demux_is_rtcp(s) ? 2 : 1; return rtcp_demux_is_rtcp(s) ? 2 : 1;
} }
static int call_avpf2avp_rtcp(str *s, struct packet_stream *stream) { static int call_noop_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
return rtcp_avpf2avp(s); const struct timeval *tv)
{
rtcp_parse(s, sfd, src, tv);
return 0;
}
static int call_avpf2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
return rtcp_avpf2avp(s, sfd, src, tv); // also does rtcp_parse
} }
static int call_avp2savp_rtp(str *s, struct packet_stream *stream) { static int call_avp2savp_rtp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
return rtp_avp2savp(s, &stream->crypto, stream->call->ssrc_hash, SSRC_DIR_OUTPUT); return rtp_avp2savp(s, &stream->crypto, stream->call->ssrc_hash, SSRC_DIR_OUTPUT);
} }
static int call_avp2savp_rtcp(str *s, struct packet_stream *stream) { static int call_avp2savp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
return rtcp_avp2savp(s, &stream->crypto); return rtcp_avp2savp(s, &stream->crypto);
} }
static int call_savp2avp_rtp(str *s, struct packet_stream *stream) { static int call_savp2avp_rtp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
return rtp_savp2avp(s, &stream->selected_sfd->crypto, stream->call->ssrc_hash, SSRC_DIR_INPUT); return rtp_savp2avp(s, &stream->selected_sfd->crypto, stream->call->ssrc_hash, SSRC_DIR_INPUT);
} }
static int call_savp2avp_rtcp(str *s, struct packet_stream *stream) { static int call_savp2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
return rtcp_savp2avp(s, &stream->selected_sfd->crypto); const struct timeval *tv)
{
int ret = rtcp_savp2avp(s, &stream->selected_sfd->crypto);
if (ret < 0)
return ret;
rtcp_parse(s, sfd, src, tv);
return ret;
} }
static int call_savpf2avp_rtcp(str *s, struct packet_stream *stream) { static int call_savpf2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
int ret; int ret;
ret = rtcp_savp2avp(s, &stream->selected_sfd->crypto); ret = rtcp_savp2avp(s, &stream->selected_sfd->crypto);
if (ret < 0) if (ret < 0)
return ret; return ret;
return rtcp_avpf2avp(s); return rtcp_avpf2avp(s, sfd, src, tv);
} }
@ -1237,7 +1276,7 @@ loop_ok:
/* return values are: 0 = forward packet, -1 = error/dont forward, /* return values are: 0 = forward packet, -1 = error/dont forward,
* 1 = forward and push update to redis */ * 1 = forward and push update to redis */
if (rwf_in) { if (rwf_in) {
handler_ret = rwf_in(s, in_srtp); handler_ret = rwf_in(s, in_srtp, sfd, fsin, tv);
} }
// If recording pcap dumper is set, then we record the call. // If recording pcap dumper is set, then we record the call.
@ -1246,10 +1285,8 @@ loop_ok:
} }
if (handler_ret >= 0) { if (handler_ret >= 0) {
if (rtcp)
parse_and_log_rtcp_report(sfd, s, fsin, tv);
if (rwf_out) if (rwf_out)
handler_ret += rwf_out(s, out_srtp); handler_ret += rwf_out(s, out_srtp, NULL, NULL, NULL);
} }
if (handler_ret > 0) { if (handler_ret > 0) {

@ -96,7 +96,6 @@ struct sdes_chunk {
struct source_description_packet { struct source_description_packet {
struct rtcp_header header; struct rtcp_header header;
struct sdes_chunk chunks[0]; struct sdes_chunk chunks[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct bye_packet { struct bye_packet {
@ -142,14 +141,14 @@ struct rtcp_process_ctx {
struct rtcp_handler { struct rtcp_handler {
void (*init)(struct rtcp_process_ctx *); void (*init)(struct rtcp_process_ctx *);
void (*start)(struct rtcp_process_ctx *, struct call *); void (*start)(struct rtcp_process_ctx *, struct call *);
void (*common)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); void (*common)(struct rtcp_process_ctx *, const struct rtcp_packet *);
void (*sr)(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); void (*sr)(struct rtcp_process_ctx *, const struct sender_report_packet *);
void (*rr_list_start)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); void (*rr_list_start)(struct rtcp_process_ctx *, const struct rtcp_packet *);
void (*rr)(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); void (*rr)(struct rtcp_process_ctx *, const struct report_block *);
void (*rr_list_end)(struct rtcp_process_ctx *); void (*rr_list_end)(struct rtcp_process_ctx *);
void (*xr)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *, str *); void (*xr)(struct rtcp_process_ctx *, const struct rtcp_packet *, str *);
void (*sdes_list_start)(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); void (*sdes_list_start)(struct rtcp_process_ctx *, const struct source_description_packet *);
void (*sdes_item)(struct rtcp_process_ctx *, const rtcp_sdes_chunk_t *, const rtcp_sdes_item_t *, void (*sdes_item)(struct rtcp_process_ctx *, const struct sdes_chunk *, const struct sdes_item *,
const char *); const char *);
void (*sdes_list_end)(struct rtcp_process_ctx *); void (*sdes_list_end)(struct rtcp_process_ctx *);
void (*finish)(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *, void (*finish)(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *,
@ -168,16 +167,16 @@ struct rtcp_handlers {
static void dummy_handler(); static void dummy_handler();
// scratch area (prepare/parse packet) // scratch area (prepare/parse packet)
static void scratch_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); static void scratch_rr(struct rtcp_process_ctx *, const struct report_block *);
// homer functions // homer functions
static void homer_init(struct rtcp_process_ctx *); static void homer_init(struct rtcp_process_ctx *);
static void homer_sr(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); static void homer_sr(struct rtcp_process_ctx *, const struct sender_report_packet *);
static void homer_rr_list_start(struct rtcp_process_ctx *, const pjmedia_rtcp_common *); static void homer_rr_list_start(struct rtcp_process_ctx *, const struct rtcp_packet *);
static void homer_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); static void homer_rr(struct rtcp_process_ctx *, const struct report_block *);
static void homer_rr_list_end(struct rtcp_process_ctx *); 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_list_start(struct rtcp_process_ctx *, const struct source_description_packet *);
static void homer_sdes_item(struct rtcp_process_ctx *, const rtcp_sdes_chunk_t *, const rtcp_sdes_item_t *, static void homer_sdes_item(struct rtcp_process_ctx *, const struct sdes_chunk *, const struct sdes_item *,
const char *); const char *);
static void homer_sdes_list_end(struct rtcp_process_ctx *); 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 *, static void homer_finish(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *,
@ -186,10 +185,11 @@ static void homer_finish(struct rtcp_process_ctx *, struct call *, const endpoin
// syslog functions // syslog functions
static void logging_init(struct rtcp_process_ctx *); static void logging_init(struct rtcp_process_ctx *);
static void logging_start(struct rtcp_process_ctx *, struct call *); 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_common(struct rtcp_process_ctx *, const struct rtcp_packet *);
static void logging_sr(struct rtcp_process_ctx *, const pjmedia_rtcp_sr *); static void logging_sdes_list_start(struct rtcp_process_ctx *, const struct source_description_packet *);
static void logging_rr(struct rtcp_process_ctx *, const pjmedia_rtcp_rr *); static void logging_sr(struct rtcp_process_ctx *, const struct sender_report_packet *);
static void logging_xr(struct rtcp_process_ctx *, const pjmedia_rtcp_common *, str *); static void logging_rr(struct rtcp_process_ctx *, const struct report_block *);
static void logging_xr(struct rtcp_process_ctx *, const struct rtcp_packet *, str *);
static void logging_finish(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *, static void logging_finish(struct rtcp_process_ctx *, struct call *, const endpoint_t *, const endpoint_t *,
const struct timeval *); const struct timeval *);
static void logging_destroy(struct rtcp_process_ctx *); static void logging_destroy(struct rtcp_process_ctx *);
@ -203,6 +203,7 @@ static struct rtcp_handler log_handlers = {
.init = logging_init, .init = logging_init,
.start = logging_start, .start = logging_start,
.common = logging_common, .common = logging_common,
.sdes_list_start = logging_sdes_list_start,
.sr = logging_sr, .sr = logging_sr,
.rr = logging_rr, .rr = logging_rr,
.xr = logging_xr, .xr = logging_xr,
@ -236,24 +237,22 @@ static struct rtcp_handler *all_handlers[] = {
// macro to call all function handlers in one go // macro to call all function handlers in one go
#define CAH(func, ...) do { \ #define CAH(func, ...) do { \
rtcp_handlers.scratch->func(&log_ctx, ##__VA_ARGS__); \ rtcp_handlers.scratch->func(log_ctx, ##__VA_ARGS__); \
rtcp_handlers.logging->func(&log_ctx, ##__VA_ARGS__); \ rtcp_handlers.logging->func(log_ctx, ##__VA_ARGS__); \
rtcp_handlers.homer->func(&log_ctx, ##__VA_ARGS__); \ rtcp_handlers.homer->func(log_ctx, ##__VA_ARGS__); \
} while (0) } while (0)
typedef struct rtcp_chain_element *(*rtcp_handler_func)(str *); typedef int (*rtcp_handler_func)(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_sr(str *s); static int rtcp_sr(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_rr(str *s); static int rtcp_rr(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_sdes(str *s); static int rtcp_sdes(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_bye(str *s); static int rtcp_xr(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_app(str *s); static int rtcp_generic(struct rtcp_chain_element *, struct rtcp_process_ctx *);
static struct rtcp_chain_element *rtcp_rtpfb(str *s);
static struct rtcp_chain_element *rtcp_psfb(str *s);
@ -263,10 +262,20 @@ static const rtcp_handler_func handler_funcs[] = {
[RTCP_PT_SR] = rtcp_sr, [RTCP_PT_SR] = rtcp_sr,
[RTCP_PT_RR] = rtcp_rr, [RTCP_PT_RR] = rtcp_rr,
[RTCP_PT_SDES] = rtcp_sdes, [RTCP_PT_SDES] = rtcp_sdes,
[RTCP_PT_BYE] = rtcp_bye, [RTCP_PT_BYE] = rtcp_generic,
[RTCP_PT_APP] = rtcp_app, [RTCP_PT_APP] = rtcp_generic,
[RTCP_PT_RTPFB] = rtcp_rtpfb, [RTCP_PT_RTPFB] = rtcp_generic,
[RTCP_PT_PSFB] = rtcp_psfb, [RTCP_PT_PSFB] = rtcp_generic,
[RTCP_PT_XR] = rtcp_xr,
};
static const int min_packet_sizes[] = {
[RTCP_PT_SR] = sizeof(struct sender_report_packet),
[RTCP_PT_RR] = sizeof(struct receiver_report_packet),
[RTCP_PT_SDES] = sizeof(struct source_description_packet),
[RTCP_PT_BYE] = sizeof(struct bye_packet),
[RTCP_PT_APP] = sizeof(struct app_packet),
[RTCP_PT_RTPFB] = sizeof(struct fb_packet),
[RTCP_PT_PSFB] = sizeof(struct fb_packet),
}; };
@ -274,7 +283,7 @@ static const rtcp_handler_func handler_funcs[] = {
static void *rtcp_length_check(str *s, size_t min_len, unsigned int *len_p) { static struct rtcp_header *rtcp_length_check(str *s, size_t min_len, unsigned int *len_p) {
struct rtcp_header *h; struct rtcp_header *h;
if (s->len < min_len) if (s->len < min_len)
@ -289,75 +298,106 @@ static void *rtcp_length_check(str *s, size_t min_len, unsigned int *len_p) {
return h; return h;
} }
static struct rtcp_chain_element *rtcp_new_element(void *p, unsigned int len, int type) { static struct rtcp_chain_element *rtcp_new_element(struct rtcp_header *p, unsigned int len) {
struct rtcp_chain_element *el; struct rtcp_chain_element *el;
el = g_slice_alloc(sizeof(*el)); el = g_slice_alloc(sizeof(*el));
el->type = type; el->type = p->pt;
el->len = len; el->len = len;
el->u.buf = p; el->u.buf = p;
return el; return el;
} }
static struct rtcp_chain_element *rtcp_generic(str *s, int type) { static int rtcp_generic(struct rtcp_chain_element *el, struct rtcp_process_ctx *log_ctx) {
struct rtcp_header *p; return 0;
unsigned int len;
if (!(p = rtcp_length_check(s, sizeof(*p), &len)))
return NULL;
return rtcp_new_element(p, len, type);
} }
static struct rtcp_chain_element *rtcp_Xr(str *s, int type, size_t struct_len) { static int rtcp_Xr(struct rtcp_chain_element *el) {
struct rtcp_packet *p; if (el->len < el->u.rtcp_packet->header.count * sizeof(struct report_block))
unsigned int len; return -1;
return 0;
}
if (!(p = rtcp_length_check(s, struct_len, &len))) static void rtcp_rr_list(const struct rtcp_packet *common, struct report_block *blocks,
return NULL; struct rtcp_process_ctx *log_ctx)
{
CAH(rr_list_start, common);
for (unsigned int i = 0; i < common->header.count; i++) {
struct report_block *block = &blocks[i];
CAH(rr, block);
}
CAH(rr_list_end);
}
if (len < (p->header.v_p_x & 0x1f) * sizeof(struct report_block))
return NULL;
return rtcp_new_element(p, len, type); static int rtcp_sr(struct rtcp_chain_element *el, struct rtcp_process_ctx *log_ctx) {
if (rtcp_Xr(el))
return -1;
CAH(common, &el->u.sr->rtcp);
CAH(sr, el->u.sr);
rtcp_rr_list(&el->u.sr->rtcp, el->u.sr->reports, log_ctx);
return 0;
} }
static struct rtcp_chain_element *rtcp_sr(str *s) { static int rtcp_rr(struct rtcp_chain_element *el, struct rtcp_process_ctx *log_ctx) {
return rtcp_Xr(s, RTCP_PT_SR, sizeof(struct sender_report_packet)); if (rtcp_Xr(el))
return -1;
CAH(common, &el->u.rr->rtcp);
rtcp_rr_list(&el->u.rr->rtcp, el->u.rr->reports, log_ctx);
return 0;
} }
static struct rtcp_chain_element *rtcp_rr(str *s) { static int rtcp_sdes(struct rtcp_chain_element *el, struct rtcp_process_ctx *log_ctx) {
return rtcp_Xr(s, RTCP_PT_RR, sizeof(struct receiver_report_packet)); str comp_s;
}
static struct rtcp_chain_element *rtcp_sdes(str *s) { CAH(sdes_list_start, el->u.sdes);
struct source_description_packet *p;
unsigned int len;
if (!(p = rtcp_length_check(s, sizeof(*p), &len))) str_init_len(&comp_s, (void *) el->u.sdes->chunks, el->len - sizeof(el->u.sdes->header));
return NULL; int i = 0;
while (1) {
struct sdes_chunk *sdes_chunk = (struct sdes_chunk *) comp_s.s;
if (str_shift(&comp_s, sizeof(*sdes_chunk)))
break;
while (comp_s.len) {
struct sdes_item *sdes_item = (struct sdes_item *) 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->length)
break;
CAH(sdes_item, sdes_chunk, sdes_item, comp_s.s);
str_shift(&comp_s, sdes_item->length);
}
/* sdes items ... */ // remove padding to next chunk
while (comp_s.len % 4 != 0)
str_shift(&comp_s, 1);
return rtcp_new_element(p, len, RTCP_PT_SDES); // more chunks? set chunk header
} i++;
if (i >= el->u.sdes->header.count)
break;
}
static struct rtcp_chain_element *rtcp_bye(str *s) { CAH(sdes_list_end);
return rtcp_generic(s, RTCP_PT_BYE);
}
static struct rtcp_chain_element *rtcp_app(str *s) { return 0;
return rtcp_generic(s, RTCP_PT_APP);
} }
static struct rtcp_chain_element *rtcp_rtpfb(str *s) { static int rtcp_xr(struct rtcp_chain_element *el, struct rtcp_process_ctx *log_ctx) {
return rtcp_generic(s, RTCP_PT_RTPFB); CAH(common, el->u.rtcp_packet);
str comp_s;
str_init_len(&comp_s, el->u.buf + sizeof(*el->u.rtcp_packet), el->len - sizeof(*el->u.rtcp_packet));
CAH(xr, el->u.rtcp_packet, &comp_s);
return 0;
} }
static struct rtcp_chain_element *rtcp_psfb(str *s) {
return rtcp_generic(s, RTCP_PT_PSFB);
}
static void rtcp_ce_free(void *p) { static void rtcp_ce_free(void *p) {
g_slice_free1(sizeof(struct rtcp_chain_element), p); g_slice_free1(sizeof(struct rtcp_chain_element), p);
@ -366,53 +406,99 @@ static void rtcp_list_free(GQueue *q) {
g_queue_clear_full(q, rtcp_ce_free); 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; static int __rtcp_parse(GQueue *q, const str *_s, struct stream_fd *sfd, const endpoint_t *src,
const struct timeval *tv)
{
struct rtcp_header *hdr;
struct rtcp_chain_element *el; struct rtcp_chain_element *el;
rtcp_handler_func func; rtcp_handler_func func;
str s = *_s; str s = *_s;
struct call *c = sfd->call;
struct rtcp_process_ctx log_ctx_s,
*log_ctx;
unsigned int len;
int ret;
int min_packet_size;
ZERO(log_ctx_s);
log_ctx = &log_ctx_s;
CAH(init);
CAH(start, c);
while (1) { while (1) {
if (s.len < sizeof(*hdr)) if (!(hdr = rtcp_length_check(&s, sizeof(*hdr), &len)))
break; break;
hdr = (void *) s.s; if (hdr->version != 2) {
ilog(LOG_WARN, "Unknown RTCP version %u", hdr->version);
if ((hdr->header.v_p_x & 0xc0) != 0x80) /* version 2 */
goto error; goto error;
}
if (hdr->header.pt >= G_N_ELEMENTS(handler_funcs)) min_packet_size = 0;
goto error; if (hdr->pt < G_N_ELEMENTS(min_packet_sizes))
func = handler_funcs[hdr->header.pt]; min_packet_size = min_packet_sizes[hdr->pt];
if (!func) if (len < min_packet_size) {
ilog(LOG_WARN, "Invalid RTCP packet type %u (short: %u < %i)",
hdr->pt, len, min_packet_size);
goto error; goto error;
}
el = rtcp_new_element(hdr, len);
if (hdr->pt >= G_N_ELEMENTS(handler_funcs)) {
ilog(LOG_INFO, "Ignoring unknown RTCP packet type %u", hdr->pt);
goto next;
}
func = handler_funcs[hdr->pt];
if (!func) {
ilog(LOG_INFO, "Ignoring unknown RTCP packet type %u", hdr->pt);
goto next;
}
el = func(&s); ilog(LOG_DEBUG, "Calling handler for RTCP packet type %u", hdr->pt);
if (!el) ret = func(el, log_ctx);
if (ret) {
ilog(LOG_WARN, "Failed to handle or parse RTCP packet type %u", hdr->pt);
rtcp_ce_free(el);
goto error; goto error;
}
next:
g_queue_push_tail(q, el); g_queue_push_tail(q, el);
if (str_shift(&s, el->len)) if (str_shift(&s, el->len))
abort(); abort();
} }
CAH(finish, c, src, &sfd->socket.local, tv);
CAH(destroy);
return 0; return 0;
error: error:
CAH(finish, c, src, &sfd->socket.local, tv);
CAH(destroy);
rtcp_list_free(q); rtcp_list_free(q);
return -1; return -1;
} }
int rtcp_avpf2avp(str *s) { void rtcp_parse(const str *s, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv) {
GQueue rtcp_list = G_QUEUE_INIT;
if (__rtcp_parse(&rtcp_list, s, sfd, src, tv))
return;
rtcp_list_free(&rtcp_list);
}
int rtcp_avpf2avp(str *s, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv) {
GQueue rtcp_list = G_QUEUE_INIT; GQueue rtcp_list = G_QUEUE_INIT;
GList *l; GList *l;
struct rtcp_chain_element *el; struct rtcp_chain_element *el;
void *start; void *start;
unsigned int removed, left; unsigned int removed, left;
if (rtcp_parse(&rtcp_list, s)) if (__rtcp_parse(&rtcp_list, s, sfd, src, tv))
return 0; return 0;
left = s->len; left = s->len;
@ -486,7 +572,7 @@ static int rtcp_payload(struct rtcp_packet **out, str *p, const str *s) {
rtcp = (void *) s->s; rtcp = (void *) s->s;
err = "invalid header version"; err = "invalid header version";
if ((rtcp->header.v_p_x & 0xc0) != 0x80) /* version 2 */ if (rtcp->header.version != 2) /* version 2 */
goto error; goto error;
err = "invalid packet type"; err = "invalid packet type";
if (rtcp->header.pt != RTCP_PT_SR if (rtcp->header.pt != RTCP_PT_SR
@ -584,152 +670,40 @@ static void str_sanitize(GString *s) {
g_string_truncate(s, s->len - 1); g_string_truncate(s, s->len - 1);
} }
void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *ori_s, const endpoint_t *src,
const struct timeval *tv)
{
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;
struct call *c = sfd->call;
int i;
struct rtcp_process_ctx log_ctx;
ZERO(log_ctx);
CAH(init);
CAH(start, c);
iter_s = *ori_s;
while (iter_s.len) {
// procedure throughout here: first assign, then str_shift with check for
// return value (does the length sanity check), then access values.
// we use iter_s to iterate compound packets and comp_s to access component
// data.
common = (pjmedia_rtcp_common*) iter_s.s;
comp_s = iter_s;
if (str_shift(&comp_s, sizeof(*common))) // puts comp_s just past the common header
break;
if (str_shift(&iter_s, (ntohs(common->length) + 1) << 2)) // puts iter_s on the next compound packet
break;
CAH(common, common);
/* Parse RTCP */
switch (common->pt) {
case RTCP_PT_SR:
sr = (pjmedia_rtcp_sr*) ((comp_s.s));
if (str_shift(&comp_s, sizeof(*sr)))
break;
CAH(sr, sr);
// fall through to RTCP_PT_RR
case RTCP_PT_RR:
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;
CAH(rr, rr);
}
CAH(rr_list_end);
break;
case RTCP_PT_XR:
CAH(xr, common, &comp_s);
break;
case RTCP_PT_SDES:
CAH(sdes_list_start, common);
// 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;
CAH(sdes_item, 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;
}
CAH(sdes_list_end);
break;
}
}
CAH(finish, c, src, &sfd->socket.local, tv);
CAH(destroy);
}
static void dummy_handler() { static void dummy_handler() {
return; return;
} }
static void scratch_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { static void scratch_rr(struct rtcp_process_ctx *ctx, const struct report_block *rr) {
ctx->scratch = (rr->total_lost_2 << 16) + (rr->total_lost_1 << 8) + rr->total_lost_0; ctx->scratch = (rr->number_lost[0] << 16) | (rr->number_lost[1] << 8) | rr->number_lost[2];
} }
static void homer_init(struct rtcp_process_ctx *ctx) { static void homer_init(struct rtcp_process_ctx *ctx) {
ctx->json = g_string_new("{ "); ctx->json = g_string_new("{ ");
} }
static void homer_sr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_sr* sr) { static void homer_sr(struct rtcp_process_ctx *ctx, const struct sender_report_packet *sr) {
g_string_append_printf(ctx->json, "\"sender_information\":{\"ntp_timestamp_sec\":%u," g_string_append_printf(ctx->json, "\"sender_information\":{\"ntp_timestamp_sec\":%u,"
"\"ntp_timestamp_usec\":%u,\"octets\":%u,\"rtp_timestamp\":%u, \"packets\":%u},", "\"ntp_timestamp_usec\":%u,\"octets\":%u,\"rtp_timestamp\":%u, \"packets\":%u},",
ntohl(sr->ntp_sec), ntohl(sr->ntp_msw),
ntohl(sr->ntp_frac), ntohl(sr->ntp_lsw),
ntohl(sr->sender_bcount), ntohl(sr->octet_count),
ntohl(sr->rtp_ts), ntohl(sr->timestamp),
ntohl(sr->sender_pcount)); ntohl(sr->packet_count));
} }
static void homer_rr_list_start(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common) { static void homer_rr_list_start(struct rtcp_process_ctx *ctx, const struct rtcp_packet *common) {
g_string_append_printf(ctx->json, "\"ssrc\":%u,\"type\":%u,\"report_count\":%u,\"report_blocks\":[", g_string_append_printf(ctx->json, "\"ssrc\":%u,\"type\":%u,\"report_count\":%u,\"report_blocks\":[",
ntohl(common->ssrc), ntohl(common->ssrc),
common->pt, common->header.pt,
common->count); common->header.count);
} }
static void homer_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { static void homer_rr(struct rtcp_process_ctx *ctx, const struct report_block *rr) {
g_string_append_printf(ctx->json, "{\"source_ssrc\":%u," g_string_append_printf(ctx->json, "{\"source_ssrc\":%u,"
"\"highest_seq_no\":%u,\"fraction_lost\":%u,\"ia_jitter\":%u," "\"highest_seq_no\":%u,\"fraction_lost\":%u,\"ia_jitter\":%u,"
"\"packets_lost\":%u,\"lsr\":%u,\"dlsr\":%u},", "\"packets_lost\":%u,\"lsr\":%u,\"dlsr\":%u},",
ntohl(rr->ssrc), ntohl(rr->ssrc),
ntohl(rr->last_seq), ntohl(rr->high_seq_received),
rr->fract_lost, rr->fraction_lost,
ntohl(rr->jitter), ntohl(rr->jitter),
ctx->scratch, ctx->scratch,
ntohl(rr->lsr), ntohl(rr->lsr),
@ -739,21 +713,20 @@ static void homer_rr_list_end(struct rtcp_process_ctx *ctx) {
str_sanitize(ctx->json); str_sanitize(ctx->json);
g_string_append_printf(ctx->json, "],"); g_string_append_printf(ctx->json, "],");
} }
static void homer_sdes_list_start(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common) { static void homer_sdes_list_start(struct rtcp_process_ctx *ctx, const struct source_description_packet *sdes) {
g_string_append_printf(ctx->json, "\"sdes_ssrc\":%u,\"sdes_report_count\":%u,\"sdes_information\": [ ", g_string_append_printf(ctx->json, "\"sdes_report_count\":%u,\"sdes_information\": [ ",
ntohl(common->ssrc), sdes->header.count);
common->count);
} }
static void homer_sdes_item(struct rtcp_process_ctx *ctx, const rtcp_sdes_chunk_t *chunk, static void homer_sdes_item(struct rtcp_process_ctx *ctx, const struct sdes_chunk *chunk,
const rtcp_sdes_item_t *item, const char *data) const struct sdes_item *item, const char *data)
{ {
int i; int i;
g_string_append_printf(ctx->json, "{\"sdes_chunk_ssrc\":%u,\"type\":%u,\"text\":\"", g_string_append_printf(ctx->json, "{\"sdes_chunk_ssrc\":%u,\"type\":%u,\"text\":\"",
htonl(chunk->csrc), htonl(chunk->ssrc),
item->type); item->type);
for (i = 0; i < item->len; i++) { for (i = 0; i < item->length; i++) {
switch (data[i]) { switch (data[i]) {
case '"': case '"':
g_string_append(ctx->json, "\\\""); g_string_append(ctx->json, "\\\"");
@ -803,34 +776,42 @@ static void logging_init(struct rtcp_process_ctx *ctx) {
static void logging_start(struct rtcp_process_ctx *ctx, struct call *c) { static void logging_start(struct rtcp_process_ctx *ctx, struct call *c) {
g_string_append_printf(ctx->log, "["STR_FORMAT"] ", STR_FMT(&c->callid)); 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) { static void logging_common(struct rtcp_process_ctx *ctx, const struct rtcp_packet *common) {
g_string_append_printf(ctx->log,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", g_string_append_printf(ctx->log,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ",
common->version, common->header.version,
common->p, common->header.p,
common->count, common->header.count,
common->pt, common->header.pt,
ntohl(common->length), ntohs(common->header.length),
ntohl(common->ssrc)); ntohl(common->ssrc));
} }
static void logging_sr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_sr* sr) { static void logging_sdes_list_start(struct rtcp_process_ctx *ctx, const struct source_description_packet *sdes) {
g_string_append_printf(ctx->log,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ",
sdes->header.version,
sdes->header.p,
sdes->header.count,
sdes->header.pt,
ntohs(sdes->header.length));
}
static void logging_sr(struct rtcp_process_ctx *ctx, const struct sender_report_packet *sr) {
g_string_append_printf(ctx->log,"ntp_sec=%u, ntp_fractions=%u, rtp_ts=%u, sender_packets=%u, sender_bytes=%u, ", 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_msw),
ntohl(sr->ntp_frac), ntohl(sr->ntp_lsw),
ntohl(sr->rtp_ts), ntohl(sr->timestamp),
ntohl(sr->sender_pcount), ntohl(sr->packet_count),
ntohl(sr->sender_bcount)); ntohl(sr->octet_count));
} }
static void logging_rr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_rr *rr) { static void logging_rr(struct rtcp_process_ctx *ctx, const struct report_block *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, ", 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), ntohl(rr->ssrc),
rr->fract_lost, rr->fraction_lost,
ctx->scratch, ctx->scratch,
ntohl(rr->last_seq), ntohl(rr->high_seq_received),
ntohl(rr->jitter), ntohl(rr->jitter),
ntohl(rr->lsr), ntohl(rr->lsr),
ntohl(rr->dlsr)); ntohl(rr->dlsr));
} }
static void logging_xr(struct rtcp_process_ctx *ctx, const pjmedia_rtcp_common *common, str *comp_s) { static void logging_xr(struct rtcp_process_ctx *ctx, const struct rtcp_packet *common, str *comp_s) {
pjmedia_rtcp_xr_rx_rtcp_xr(ctx->log, common, 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, static void logging_finish(struct rtcp_process_ctx *ctx, struct call *c, const endpoint_t *src,

@ -10,83 +10,12 @@ struct crypto_context;
/** int rtcp_avpf2avp(str *, struct stream_fd *sfd, const endpoint_t *, const struct timeval *);
* RTCP sender report.
*/
typedef struct pjmedia_rtcp_sr
{
u_int32_t ntp_sec; /**< NTP time, seconds part. */
u_int32_t ntp_frac; /**< NTP time, fractions part. */
u_int32_t rtp_ts; /**< RTP timestamp. */
u_int32_t sender_pcount; /**< Sender packet cound. */
u_int32_t sender_bcount; /**< Sender octet/bytes count. */
} __attribute__ ((packed)) pjmedia_rtcp_sr;
/**
* RTCP receiver report.
*/
typedef struct pjmedia_rtcp_rr
{
u_int32_t ssrc; /**< SSRC identification. */
#if G_BYTE_ORDER == G_BIG_ENDIAN
u_int32_t fract_lost:8; /**< Fraction lost. */
u_int32_t total_lost_2:8; /**< Total lost, bit 16-23. */
u_int32_t total_lost_1:8; /**< Total lost, bit 8-15. */
u_int32_t total_lost_0:8; /**< Total lost, bit 0-7. */
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
u_int32_t fract_lost:8; /**< Fraction lost. */
u_int32_t total_lost_2:8; /**< Total lost, bit 0-7. */
u_int32_t total_lost_1:8; /**< Total lost, bit 8-15. */
u_int32_t total_lost_0:8; /**< Total lost, bit 16-23. */
#else
#error "byte order unknown"
#endif
u_int32_t last_seq; /**< Last sequence number. */
u_int32_t jitter; /**< Jitter. */
u_int32_t lsr; /**< Last SR. */
u_int32_t dlsr; /**< Delay since last SR. */
} __attribute__ ((packed)) pjmedia_rtcp_rr;
typedef struct _rtcp_sdes_chunk
{
uint32_t csrc;
} __attribute__ ((packed)) rtcp_sdes_chunk_t;
typedef struct _rtcp_sdes_item
{
uint8_t type;
uint8_t len;
} __attribute__ ((packed)) rtcp_sdes_item_t;
/**
* RTCP common header.
*/
typedef struct pjmedia_rtcp_common
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
unsigned version:2; /**< packet type */
unsigned p:1; /**< padding flag */
unsigned count:5; /**< varies by payload type */
unsigned pt:8; /**< payload type */
#else
unsigned count:5; /**< varies by payload type */
unsigned p:1; /**< padding flag */
unsigned version:2; /**< packet type */
unsigned pt:8; /**< payload type */
#endif
unsigned length:16; /**< packet length */
u_int32_t ssrc; /**< SSRC identification */
} pjmedia_rtcp_common;
int rtcp_avpf2avp(str *);
int rtcp_avp2savp(str *, struct crypto_context *); int rtcp_avp2savp(str *, struct crypto_context *);
int rtcp_savp2avp(str *, struct crypto_context *); 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 parse_and_log_rtcp_report(struct stream_fd *sfd, const str *, const endpoint_t *, const struct timeval *);
void rtcp_parse(const str *, struct stream_fd *sfd, const endpoint_t *, const struct timeval *);
void rtcp_init(); void rtcp_init();

@ -8,6 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <glib.h> #include <glib.h>
#include "rtcplib.h"
/* RTCP XR payload type */ /* RTCP XR payload type */
#define RTCP_XR 207 #define RTCP_XR 207
@ -95,7 +96,7 @@ void print_rtcp_xr_rb_voip_mtc(GString *log, const pjmedia_rtcp_xr_rb_voip_mtc *
ntohs(rb_voip_mtc->jb_abs_max)); ntohs(rb_voip_mtc->jb_abs_max));
} }
void pjmedia_rtcp_xr_rx_rtcp_xr(GString *log, const pjmedia_rtcp_common *common, str *s) { void pjmedia_rtcp_xr_rx_rtcp_xr(GString *log, const struct rtcp_packet *common, str *s) {
const pjmedia_rtcp_xr_rb_rr_time *rb_rr_time; const pjmedia_rtcp_xr_rb_rr_time *rb_rr_time;
const pjmedia_rtcp_xr_rb_dlrr *rb_dlrr; const pjmedia_rtcp_xr_rb_dlrr *rb_dlrr;
@ -109,7 +110,7 @@ void pjmedia_rtcp_xr_rx_rtcp_xr(GString *log, const pjmedia_rtcp_common *common,
// packet length is guaranteed to be valid from upstream // packet length is guaranteed to be valid from upstream
pkt_len = (ntohs(common->length) + 1) << 2; pkt_len = (ntohs(common->header.length) + 1) << 2;
/* Parse report rpt_types */ /* Parse report rpt_types */
while (pkt_len >= sizeof(*rb_hdr)) while (pkt_len >= sizeof(*rb_hdr))

@ -191,7 +191,7 @@ typedef struct pjmedia_rtcp_xr_rb_voip_mtc
* @param rtcp_pkt The received RTCP XR packet. * @param rtcp_pkt The received RTCP XR packet.
* @param size Size of the incoming packet. * @param size Size of the incoming packet.
*/ */
void pjmedia_rtcp_xr_rx_rtcp_xr(GString *, const pjmedia_rtcp_common *common, str *s); void pjmedia_rtcp_xr_rx_rtcp_xr(GString *, const struct rtcp_packet *common, str *s);
#pragma pack() #pragma pack()

@ -1,12 +1,23 @@
#ifndef _RTCPLIB_H_ #ifndef _RTCPLIB_H_
#define _RTCPLIB_H_ #define _RTCPLIB_H_
#include <glib.h>
#include "str.h" #include "str.h"
#include "compat.h" #include "compat.h"
struct rtcp_header { struct rtcp_header {
unsigned char v_p_x; #if G_BYTE_ORDER == G_BIG_ENDIAN
unsigned version:2; /**< packet type */
unsigned p:1; /**< padding flag */
unsigned count:5; /**< varies by payload type */
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned count:5; /**< varies by payload type */
unsigned p:1; /**< padding flag */
unsigned version:2; /**< packet type */
#else
#error "byte order unknown"
#endif
unsigned char pt; unsigned char pt;
u_int16_t length; u_int16_t length;
} __attribute__ ((packed)); } __attribute__ ((packed));

Loading…
Cancel
Save