aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZHANG Rui <rzhang@grandstream.cn>2018-01-18 17:45:49 +0800
committerAnders Broman <a.broman58@gmail.com>2018-01-30 05:46:47 +0000
commita584eab239d55e441433ead40c993e08a24c59fe (patch)
tree1d3b9344eb9559271a48038742f32da037e3c4af
parent27ae22bd2538ff7391a5e56723715932ecf80b0e (diff)
New RTCP dissector for transport-cc
Bug: 14332 Change-Id: I49642a9880fc03d38942eebfd6b1015894fef23d Reviewed-on: https://code.wireshark.org/review/25255 Reviewed-by: Michael Mann <mmann78@netscape.net> Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--epan/dissectors/packet-rtcp.c361
1 files changed, 359 insertions, 2 deletions
diff --git a/epan/dissectors/packet-rtcp.c b/epan/dissectors/packet-rtcp.c
index cacad6f12c..b7e42a0e1a 100644
--- a/epan/dissectors/packet-rtcp.c
+++ b/epan/dissectors/packet-rtcp.c
@@ -359,6 +359,7 @@ static const value_string rtcp_rtpfb_fmt_vals[] =
{ 1, "Generic negative acknowledgement (NACK)"},
{ 3, "Temporary Maximum Media Stream Bit Rate Request (TMMBR)"},
{ 4, "Temporary Maximum Media Stream Bit Rate Notification (TMMBN)"},
+ { 15, "Transport-wide Congestion Control (Transport-cc)"}, /*https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01*/
{ 31, "Reserved for future extensions"},
{ 0, NULL }
};
@@ -546,6 +547,14 @@ static int hf_rtcp_length_check = -1;
static int hf_rtcp_rtpfb_fmt = -1;
static int hf_rtcp_rtpfb_nack_pid = -1;
static int hf_rtcp_rtpfb_nack_blp = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_base_seq = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_pkt_stats_cnt = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_ref_time = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_fb_pkt_cnt = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_pkt_chunk = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_recv_delta_1_byte = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_recv_delta_2_bytes = -1;
+static int hf_rtcp_rtpfb_transport_cc_fci_recv_delta_padding = -1;
static int hf_rtcp_psfb_fmt = -1;
static int hf_rtcp_fci = -1;
static int hf_rtcp_psfb_fir_fci_ssrc = -1;
@@ -1111,6 +1120,255 @@ dissect_rtcp_psfb_remb( tvbuff_t *tvb, int offset, proto_tree *rtcp_tree, proto_
return offset;
}
+#define RTCP_HEADER_LENGTH 12
+
+static int
+dissect_rtcp_rtpfb_transport_cc( tvbuff_t *tvb, int offset, proto_tree *rtcp_tree, int pkt_len)
+{
+ proto_tree *fci_tree, *pkt_chunk_tree, *recv_delta_tree;
+ proto_item *item = NULL;
+ guint8 *delta_array;
+ guint16 *pkt_seq_array;
+ guint32 i, pkt_base_seq, pkt_seq_num, pkt_count;
+ gint fci_length = pkt_len - RTCP_HEADER_LENGTH;
+ int delta_index = 0;
+ int padding_length = offset;
+
+ fci_tree = proto_tree_add_subtree_format( rtcp_tree, tvb, offset, fci_length, ett_ssrc, NULL, "Transport-cc" );
+
+ /* base sequence number */
+ proto_tree_add_item_ret_uint( fci_tree, hf_rtcp_rtpfb_transport_cc_fci_base_seq, tvb, offset, 2, ENC_BIG_ENDIAN, &pkt_base_seq );
+ offset += 2;
+ pkt_seq_num = pkt_base_seq;
+
+ /* packet status count */
+ proto_tree_add_item_ret_uint( fci_tree, hf_rtcp_rtpfb_transport_cc_fci_pkt_stats_cnt, tvb, offset, 2, ENC_BIG_ENDIAN, &pkt_count );
+ offset += 2;
+
+ delta_array = wmem_alloc0_array( wmem_packet_scope(), gint8, pkt_count );
+ pkt_seq_array = wmem_alloc0_array( wmem_packet_scope(), gint16, pkt_count );
+
+ /* reference time */
+ proto_tree_add_item( fci_tree, hf_rtcp_rtpfb_transport_cc_fci_ref_time, tvb, offset, 3, ENC_BIG_ENDIAN );
+ offset += 3;
+
+ /* feedback packet count */
+ proto_tree_add_item( fci_tree, hf_rtcp_rtpfb_transport_cc_fci_fb_pkt_cnt, tvb, offset, 1, ENC_BIG_ENDIAN );
+ offset += 1;
+
+ /* packet chunk */
+ pkt_chunk_tree = proto_tree_add_subtree_format( fci_tree, tvb, offset, 0, ett_ssrc, NULL, "Packet Chunks" );
+
+ for (i = 0; i < pkt_count; )
+ {
+ guint32 chunk = 0;
+ item = proto_tree_add_item_ret_uint( pkt_chunk_tree, hf_rtcp_rtpfb_transport_cc_fci_pkt_chunk, tvb, offset, 2, ENC_BIG_ENDIAN, &chunk );
+
+ /* Packet Status Symbols */
+ /**
+ * 00 Packet not received
+ * 01 Packet received, small delta
+ * 10 Packet received, large or negative delta
+ * 11 [Reserved]
+ */
+ if ( !(chunk & 0x8000) )
+ {
+ /* Run length chunk, first bit is zero */
+ int length = chunk & 0x1FFF;
+
+ if ( length <= 0 )
+ {
+ /*Malfromed Packet, stop parse it*/
+ delta_array = NULL;
+ pkt_seq_array = NULL;
+
+ offset += 2;
+ return offset;
+ }
+
+ if ( !(chunk & 0x6000) )
+ {
+ proto_item_append_text( item, " [Run Length Chunk] Packet not received. Length : %d", length);
+ pkt_seq_num += length;
+ }
+ else if ( chunk & 0x2000 )
+ {
+ proto_item_append_text( item, " [Run Length Chunk] Small Delta. Length : %d", length);
+ for (int j = 0; j < length; j++)
+ {
+ /*1 means 1 byte delta, 2 means 2 bytes delta*/
+ delta_array[delta_index+j] = 1;
+ pkt_seq_array[delta_index+j] = pkt_seq_num++;
+ }
+ delta_index += length;
+ }
+ else if ( chunk & 0x4000 )
+ {
+ proto_item_append_text( item, " [Run Length Chunk] Large or Negative Delta. Length : %d", length);
+ for (int j = 0; j < length; j++)
+ {
+ delta_array[delta_index+j] = 2;
+ pkt_seq_array[delta_index+j] = pkt_seq_num++;
+ }
+ delta_index += length;
+ }
+ else
+ {
+ proto_item_append_text( item, " [Run Length Chunk] [Reserved]. Length : %d", length);
+ pkt_seq_num += length;
+ }
+
+ i += length;
+
+ }
+ else
+ {
+ wmem_strbuf_t* status = wmem_strbuf_new(wmem_packet_scope(), "|");
+
+ /* Status Vector Chunk, first bit is one */
+ if ( !(chunk & 0x4000) )
+ {
+ /* 1 bit symbols */
+
+ int data = chunk & 0x3FFF;
+ int chunk_count = 14;
+
+ for (int k = 0; k < chunk_count; k++)
+ {
+ if ( (data & (0x2000>>k)) == 0 )
+ {
+ if ( i + k < pkt_count )
+ {
+ wmem_strbuf_append(status, " N |");
+ pkt_seq_num++;
+ }
+ else
+ {
+ /* padding */
+ wmem_strbuf_append(status, " _ |");
+ }
+ }
+ else
+ {
+ wmem_strbuf_append(status, " R |");
+ delta_array[delta_index] = 1;
+ pkt_seq_array[delta_index] = pkt_seq_num++;
+ delta_index++;
+ }
+ }
+ proto_item_append_text( item, " [1 bit Status Vector Chunk]: %s", wmem_strbuf_get_str(status));
+ i += chunk_count;
+ }
+ else
+ {
+ /* 2 bits symbols */
+ int chunk_count = 7;
+ int data = chunk & 0x3FFF;
+
+ for (int k = 0; k < chunk_count; k++)
+ {
+ switch ( (data & (0x3000 >> (2*k))) >> ( 2 * (6-k) ) )
+ {
+ case 0: /*00 packet not received*/
+ if ( i + k < pkt_count )
+ {
+ wmem_strbuf_append(status, " NR |");
+ pkt_seq_num++;
+ }
+ else
+ {
+ /*padding*/
+ wmem_strbuf_append(status, " __ |");
+ }
+ break;
+
+ case 1: /*01 Packet received, small delta*/
+ wmem_strbuf_append(status, " SD |");
+ delta_array[delta_index] = 1;
+ pkt_seq_array[delta_index] = pkt_seq_num++;
+ delta_index++;
+ break;
+
+ case 2: /*10 Packet received, large or negative delta*/
+ wmem_strbuf_append(status, " LD |");
+ delta_array[delta_index] = 2;
+ pkt_seq_array[delta_index] = pkt_seq_num++;
+ delta_index++;
+ break;
+
+ case 3: /*11 packet received, w/o(wrong? overflow?) timestamp*/
+ default:
+ /*TODO: process overflow status which is not details on draft.*/
+ wmem_strbuf_append(status, " WO |");
+ pkt_seq_num++;
+ break;
+
+ }
+ }
+
+ proto_item_append_text( item, " [2 bits Status Vector Chunk]: %s", wmem_strbuf_get_str(status));
+ i += chunk_count;
+ }
+
+ }
+
+ offset += 2;
+ }
+
+ /* recv delta */
+ recv_delta_tree = proto_tree_add_subtree_format( fci_tree, tvb, offset, 0, ett_ssrc, NULL, "Recv Delta" );
+ for (i = 0; i < pkt_count; i++ )
+ {
+ if ( delta_array[i] == 1 )
+ {
+ /*1 byte delta*/
+ guint32 delta;
+ item = proto_tree_add_item_ret_uint( recv_delta_tree, hf_rtcp_rtpfb_transport_cc_fci_recv_delta_1_byte, tvb, offset, 1, ENC_BIG_ENDIAN, &delta );
+
+ proto_item_append_text( item, " Small Delta: [seq: %d] %lf ms", pkt_seq_array[i], delta*250.0/1000);
+
+ offset += 1;
+ }
+ else if ( delta_array[i] == 2 )
+ {
+ /*2 bytes delta*/
+ gint16 delta;
+ item = proto_tree_add_item( recv_delta_tree, hf_rtcp_rtpfb_transport_cc_fci_recv_delta_2_bytes, tvb, offset, 2, ENC_BIG_ENDIAN);
+ delta = tvb_get_ntohs(tvb, offset);
+
+ if ( delta < 0 )
+ {
+ proto_item_append_text( item, " Negative Delta: [seq: %d] %lf ms", pkt_seq_array[i], delta*250.0/1000 );
+ }
+ else
+ {
+ proto_item_append_text( item, " Large Delta: [seq: %d] %lf ms", pkt_seq_array[i], delta*250.0/1000 );
+ }
+
+ offset += 2;
+ }
+ else
+ {
+ /*End with 0*/
+ break;
+ }
+ }
+
+ /* padding */
+ padding_length = fci_length - (offset - padding_length);
+ if ( padding_length > 0 )
+ {
+ proto_tree_add_item( recv_delta_tree, hf_rtcp_rtpfb_transport_cc_fci_recv_delta_padding, tvb, offset, padding_length, ENC_BIG_ENDIAN );
+ offset += padding_length;
+ }
+
+ /* delta_array / pkt_seq_array will be freed out of wmem_packet_scope*/
+ delta_array = NULL;
+ pkt_seq_array = NULL;
+
+ return offset;
+}
+
static int
dissect_rtcp_rtpfb_nack( tvbuff_t *tvb, int offset, proto_tree *rtcp_tree, proto_item *top_item)
{
@@ -1203,6 +1461,9 @@ dissect_rtcp_rtpfb( tvbuff_t *tvb, int offset, proto_tree *rtcp_tree, proto_item
offset = dissect_rtcp_rtpfb_tmmbr(tvb, offset, rtcp_tree, top_item, counter, 0);
} else if (rtcp_rtpfb_fmt == 4) {
offset = dissect_rtcp_rtpfb_tmmbr(tvb, offset, rtcp_tree, top_item, counter, 1);
+ } else if (rtcp_rtpfb_fmt == 15) {
+ /* Handle transport-cc (RTP Extensions for Transport-wide Congestion Control) - https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 */
+ offset = dissect_rtcp_rtpfb_transport_cc( tvb, offset, rtcp_tree, packet_length);
} else {
/* Unknown FMT */
proto_tree_add_item(rtcp_tree, hf_rtcp_fci, tvb, offset, start_offset + packet_length - offset, ENC_NA );
@@ -3573,7 +3834,7 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
/* offset should be total_packet_length by now... */
else if (offset == total_packet_length)
{
- ti = proto_tree_add_boolean_format_value(tree, hf_rtcp_length_check, tvb,
+ ti = proto_tree_add_boolean_format_value(rtcp_tree, hf_rtcp_length_check, tvb,
0, 0, TRUE, "OK - %u bytes",
offset);
/* Hidden might be less annoying here...? */
@@ -3581,7 +3842,7 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
}
else
{
- ti = proto_tree_add_boolean_format_value(tree, hf_rtcp_length_check, tvb,
+ ti = proto_tree_add_boolean_format_value(rtcp_tree, hf_rtcp_length_check, tvb,
0, 0, FALSE,
"Wrong (expected %u bytes, found %d)",
total_packet_length, offset);
@@ -5507,6 +5768,102 @@ proto_register_rtcp(void)
NULL, HFILL
}
},
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_base_seq,
+ {
+ "Base Sequence Number",
+ "rtcp.rtpfb.transportcc.baseseq",
+ FT_UINT16,
+ BASE_DEC_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_pkt_stats_cnt,
+ {
+ "Packet Status Count",
+ "rtcp.rtpfb.transportcc.statuscount",
+ FT_UINT16,
+ BASE_DEC_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_ref_time,
+ {
+ "Reference Time",
+ "rtcp.rtpfb.transportcc.reftime",
+ FT_UINT24,
+ BASE_DEC_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_fb_pkt_cnt,
+ {
+ "Feedback Packets Count",
+ "rtcp.rtpfb.transportcc.pktcount",
+ FT_UINT8,
+ BASE_DEC_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_pkt_chunk,
+ {
+ "Packet Chunk",
+ "rtcp.rtpfb.transportcc.pktchunk",
+ FT_UINT16,
+ BASE_DEC_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_recv_delta_1_byte,
+ {
+ "Recv Delta",
+ "rtcp.rtpfb.transportcc.recv_delta",
+ FT_UINT8,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_recv_delta_2_bytes,
+ {
+ "Recv Delta",
+ "rtcp.rtpfb.transportcc.recv_delta",
+ FT_UINT16,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtpfb_transport_cc_fci_recv_delta_padding,
+ {
+ "Recv Delta Padding",
+ "rtcp.rtpfb.transportcc.recv_delta.padding",
+ FT_UINT16,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ NULL, HFILL
+ }
+ },
{