]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7499: properly decode rtcp
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 3 Dec 2014 00:40:47 +0000 (18:40 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:46:49 +0000 (12:46 -0500)
src/switch_rtp.c

index 7f472d69a244be39694f9daa1a9a7d738fdc553f..87e4ac14cdd6298bef0dc86b5a1e63fbdef91ac8 100644 (file)
@@ -4873,6 +4873,22 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
                                rtp_session->rtcp_recv_msg_p->header.version == 2 && 
                                rtp_session->rtcp_recv_msg_p->header.type > 199 && rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
                                *flags |= SFF_RTCP;
+
+                               if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV]) {
+                                       int sbytes = (int) *bytes;
+                                       err_status_t stat = 0;
+                                       
+                                       
+                                       if ((stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes))) {
+                                               //++rtp_session->srtp_errs[rtp_session->srtp_idx_rtp]++;
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "RTCP UNPROTECT ERR\n");
+                                       } else {
+                                               //rtp_session->srtp_errs[rtp_session->srtp_idx_rtp] = 0;
+                                       }
+                                       
+                                       *bytes = sbytes;
+                               }
+
                                return SWITCH_STATUS_SUCCESS;
                        }
                }
@@ -5182,32 +5198,28 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
        return status;
 }
 
-static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes)
+static switch_status_t process_rtcp_report(switch_rtp_t *rtp_session, rtcp_msg_t *msg, switch_size_t bytes)
 {
        switch_status_t status = SWITCH_STATUS_FALSE;
 
-       if (rtp_session->rtcp_recv_msg_p->header.version == 2) {
-
-
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,
-                                                 "RTCP packet bytes %" SWITCH_SIZE_T_FMT " type %d\n", *bytes, rtp_session->rtcp_recv_msg_p->header.type);
 
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT,
+                                         "RTCP packet bytes %" SWITCH_SIZE_T_FMT " type %d pad %d\n", 
+                                         bytes, msg->header.type, msg->header.p);
+       
+       if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && 
+               (msg->header.type == 205 || //RTPFB
+                msg->header.type == 206)) {//PSFB
+               rtcp_ext_msg_t *extp = (rtcp_ext_msg_t *) msg;                  
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "PICKED UP XRTCP type: %d fmt: %d\n", 
+                                                 msg->header.type, extp->header.fmt);
+               
+               if ((extp->header.fmt == 4) || (extp->header.fmt == 1)) { /* FIR || PLI */
+                       switch_core_media_gen_key_frame(rtp_session->session);
+               }
+       } else
 
-               //DFF
-               if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && *bytes > 94) {
-                       //(rtp_session->rtcp_recv_msg_p->header.type == 205 || //RTPFB
-                       //rtp_session->rtcp_recv_msg_p->header.type == 206)) {//PSFB
-                       
-                       rtcp_ext_msg_t *extp = (rtcp_ext_msg_t *) rtp_session->rtcp_recv_msg_p;                 
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "PICKED UP XRTCP type: %d fmt: %d\n", 
-                                                         rtp_session->rtcp_recv_msg_p->header.type, extp->header.fmt);
-                       
-                       if ((extp->header.fmt == 4) || (extp->header.fmt == 1)) { /* FIR || PLI */
-                               switch_core_media_gen_key_frame(rtp_session->session);
-                       }
-               } else
-
-               if (rtp_session->rtcp_recv_msg_p->header.type == 200 || rtp_session->rtcp_recv_msg_p->header.type == 201) {
+               if (msg->header.type == 200 || msg->header.type == 201) {
                        struct switch_rtcp_report_block *report_block;
                        switch_time_t now;
                        switch_time_exp_t now_hr;
@@ -5220,8 +5232,8 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                        ntp_usec = (uint32_t)(now - (sec*1000000)); /* micro seconds */
                        lsr_now = (uint32_t)(ntp_usec*0.065536) | (ntp_sec&0x0000ffff)<<16; // 0.065536 is used for convertion from useconds 
 
-                       if (rtp_session->rtcp_recv_msg_p->header.type == 200) { /* Sender report */
-                               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)rtp_session->rtcp_recv_msg_p->body;
+                       if (msg->header.type == 200) { /* Sender report */
+                               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)msg->body;
                                
                                report_block = &sr->report_block;
                                rtp_session->stats.rtcp.packet_count += ntohl(sr->sender_info.pc);
@@ -5232,23 +5244,23 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                                rtp_session->stats.rtcp.last_recv_lsr_peer = htonl(lsr);  /* Save it include it in the next SR */
                                rtp_session->stats.rtcp.last_recv_lsr_local = lsr_now;    /* Save it to calculate DLSR when generating next SR */
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG10,"Received a SR with %d report blocks, " \
-                                                         "length in words = %d, " \
-                                                         "SSRC = 0x%X, " \
-                                                         "NTP MSW = %u, " \
-                                                         "NTP LSW = %u, " \
-                                                         "RTP timestamp = %u, " \
-                                                         "Sender Packet Count = %u, " \
-                                                         "Sender Octet Count = %u\n",
-                                                         rtp_session->rtcp_recv_msg_p->header.count,
-                                                         ntohs((uint16_t)rtp_session->rtcp_recv_msg_p->header.length),
-                                                         ntohl(sr->ssrc),
-                                                         ntohl(sr->sender_info.ntp_msw),
-                                                         ntohl(sr->sender_info.ntp_lsw),
-                                                         ntohl(sr->sender_info.ts),
-                                                         ntohl(sr->sender_info.pc),
-                                                         ntohl(sr->sender_info.oc));
+                                                                 "length in words = %d, " \
+                                                                 "SSRC = 0x%X, " \
+                                                                 "NTP MSW = %u, " \
+                                                                 "NTP LSW = %u, " \
+                                                                 "RTP timestamp = %u, " \
+                                                                 "Sender Packet Count = %u, " \
+                                                                 "Sender Octet Count = %u\n",
+                                                                 msg->header.count,
+                                                                 ntohs((uint16_t)msg->header.length),
+                                                                 ntohl(sr->ssrc),
+                                                                 ntohl(sr->sender_info.ntp_msw),
+                                                                 ntohl(sr->sender_info.ntp_lsw),
+                                                                 ntohl(sr->sender_info.ts),
+                                                                 ntohl(sr->sender_info.pc),
+                                                                 ntohl(sr->sender_info.oc));
                        } else { /* Receiver report */
-                               struct switch_rtcp_receiver_report* rr = (struct switch_rtcp_receiver_report*)rtp_session->rtcp_recv_msg_p->body;
+                               struct switch_rtcp_receiver_report* rr = (struct switch_rtcp_receiver_report*)msg->body;
                                report_block = &rr->report_block;
                                packet_ssrc = rr->ssrc;
                        }
@@ -5269,27 +5281,66 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                        rtp_session->stats.rtcp.peer_ssrc = ntohl(packet_ssrc);
                        status = SWITCH_STATUS_SUCCESS;
                }
-       } else {
-               if (rtp_session->rtcp_recv_msg_p->header.version != 2) {
-                       if (rtp_session->rtcp_recv_msg_p->header.version == 0) {
-                               if (rtp_session->ice.ice_user) {
-                                       handle_ice(rtp_session, &rtp_session->rtcp_ice, (void *) rtp_session->rtcp_recv_msg_p, *bytes);
-                               }
-                       } else {
 
-                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session),
-                                               SWITCH_LOG_DEBUG, "Received an unsupported RTCP packet version %d\nn", rtp_session->rtcp_recv_msg_p->header.version);
+
+       return status;
+}
+
+
+static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes)
+{
+       switch_size_t len;
+       switch_size_t remain = *bytes;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       rtcp_msg_t *msg = rtp_session->rtcp_recv_msg_p;
+       
+       if (msg->header.version != 2) {
+               if (msg->header.version == 0) {
+                       if (rtp_session->ice.ice_user) {
+                               handle_ice(rtp_session, &rtp_session->rtcp_ice, (void *) msg, *bytes);
                        }
+                       return SWITCH_STATUS_SUCCESS;
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session),
+                                                         SWITCH_LOG_WARNING, "Received an unsupported RTCP packet version %d\n", msg->header.version);
+                       return SWITCH_STATUS_FALSE;
                }
-               
-               status = SWITCH_STATUS_SUCCESS;
        }
 
-       return status;
-}
+       do {
+               len = ((switch_size_t)ntohs(msg->header.length) * 4) + 4;
+
+               if (msg->header.version != 2 || !(msg->header.type > 199 && msg->header.type < 208)) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, 
+                                                         "INVALID RTCP PACKET TYPE %d VER %d LEN %ld\n", msg->header.type, 
+                                                         msg->header.version, len);
+                       status = SWITCH_STATUS_BREAK;
+                       break;
+               }
+
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, 
+                                                 "WTF BYTES %ld REMAIN %ld PACKET TYPE %d LEN %ld\n", *bytes, remain, msg->header.type, len);
+
+               if (len > remain) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, 
+                                                         "RTCP INVALID LENGTH %" SWITCH_SIZE_T_FMT "\n", len);
+                       len = remain;
+               }
 
+               status = process_rtcp_report(rtp_session, msg, len);
 
+               if (remain > len) {
+                       unsigned char *p = (unsigned char *) msg;
+                       p += len;
+                       msg = (rtcp_msg_t *) p;
+               }
+
+               remain -= len;
 
+       } while (remain >= 4);
+
+       return status;
+}
 
 static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags)
 {
@@ -5715,7 +5766,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                                
                                if (rtcp_status == SWITCH_STATUS_SUCCESS) {
                                        switch_rtp_reset_media_timer(rtp_session);
-
+                                       
                                        if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
                                                switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
                                                const char *uuid = switch_channel_get_partner_uuid(channel);
@@ -5783,15 +5834,14 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                                        }
 
                                        if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
-                                               process_rtcp_packet(rtp_session, &bytes);
+                                               process_rtcp_packet(rtp_session, &rtcp_bytes);
                                                ret = 1;
                                        
                                                if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && rtp_session->timer.interval) {
                                                        switch_core_timer_sync(&rtp_session->timer);
                                                        reset_jitter_seq(rtp_session);
                                                }
-
-
+                                               
                                                goto recvfrom;
                                        }
                                }
@@ -6304,18 +6354,28 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
        bytes = rtp_common_read(rtp_session, &frame->payload, &frame->pmap, &frame->flags, io_flags);
 
        frame->data = RTP_BODY(rtp_session);
-       frame->packet = &rtp_session->recv_msg;
-       frame->packetlen = bytes;
-       frame->source = __FILE__;
-
-       switch_set_flag(frame, SFF_RAW_RTP);
-       if (frame->payload == rtp_session->recv_te) {
-               switch_set_flag(frame, SFF_RFC2833);
-       }
-       frame->timestamp = ntohl(rtp_session->recv_msg.header.ts);
-       frame->seq = (uint16_t) ntohs((uint16_t) rtp_session->recv_msg.header.seq);
-       frame->ssrc = ntohl(rtp_session->recv_msg.header.ssrc);
-       frame->m = rtp_session->recv_msg.header.m ? SWITCH_TRUE : SWITCH_FALSE;
+
+       if (bytes < rtp_header_len || switch_test_flag(frame, SFF_CNG)) {
+               frame->packet = NULL;
+               frame->timestamp = 0;
+               frame->seq = 0;
+               frame->ssrc = 0;
+               frame->m = 0;
+       } else {
+
+               frame->packet = &rtp_session->recv_msg;
+               frame->packetlen = bytes;
+               frame->source = __FILE__;
+
+               switch_set_flag(frame, SFF_RAW_RTP);
+               if (frame->payload == rtp_session->recv_te) {
+                       switch_set_flag(frame, SFF_RFC2833);
+               }
+               frame->timestamp = ntohl(rtp_session->recv_msg.header.ts);
+               frame->seq = (uint16_t) ntohs((uint16_t) rtp_session->recv_msg.header.seq);
+               frame->ssrc = ntohl(rtp_session->recv_msg.header.ssrc);
+               frame->m = rtp_session->recv_msg.header.m ? SWITCH_TRUE : SWITCH_FALSE;
+       }
        
 #ifdef ENABLE_ZRTP
        if (zrtp_on && rtp_session->flags[SWITCH_ZRTP_FLAG_SECURE_MITM_RECV]) {