// RFC3550 6.6 BYE: Goodbye RTCP Packet #include "rtp-internal.h" #include "rtp-util.h" void rtcp_bye_unpack(struct rtp_context *ctx, const rtcp_header_t *header, const uint8_t* ptr, size_t bytes) { uint32_t i; struct rtcp_msg_t msg; assert(bytes >= header->rc * 4); if(header->rc < 1 || header->rc * 4 > bytes) return; // A count value of zero is valid, but useless (p43) msg.ssrc = nbo_r32(ptr); msg.type = RTCP_BYE; rtp_member_list_delete(ctx->members, msg.ssrc); rtp_member_list_delete(ctx->senders, msg.ssrc); if(bytes > header->rc * 4 + 1) { msg.u.bye.bytes = ptr[header->rc * 4]; msg.u.bye.reason = ptr + header->rc * 4 + 1; if (1 + msg.u.bye.bytes + header->rc * 4 > bytes) { assert(0); msg.u.bye.bytes = 0; msg.u.bye.reason = NULL; } } else { msg.u.bye.bytes = 0; msg.u.bye.reason = NULL; } ctx->handler.on_rtcp(ctx->cbparam, &msg); // other SSRC/CSRC for (i = 0; i < header->rc /*source count*/; i++) { msg.ssrc = nbo_r32(ptr + 4 + i * 4); rtp_member_list_delete(ctx->members, msg.ssrc); rtp_member_list_delete(ctx->senders, msg.ssrc); ctx->handler.on_rtcp(ctx->cbparam, &msg); } } int rtcp_bye_pack(struct rtp_context *ctx, uint8_t* ptr, int bytes) { rtcp_header_t header; if(bytes < 8) return 8; header.v = 2; header.p = 0; header.pt = RTCP_BYE; header.rc = 1; // self only header.length = 1; nbo_write_rtcp_header(ptr, &header); nbo_w32(ptr+4, ctx->self->ssrc); assert(8 == (header.length+1)*4); return 8; }