5 * Routines for RTCP dissection
6 * RTCP = Real-time Transport Control Protocol
8 * Copyright 2000, Philips Electronics N.V.
9 * Written by Andreas Sikkema <h323@ramdyne.nl>
11 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
13 * Copyright 2005, Nagarjuna Venna <nvenna@brixnet.com>
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 * This dissector tries to dissect the RTCP protocol according to Annex A
36 * of ITU-T Recommendation H.225.0 (02/98) and RFC 1889
37 * H.225.0 literally copies RFC 1889, but omitting a few sections.
39 * RTCP traffic is handled by an uneven UDP portnumber. This can be any
40 * port number, but there is a registered port available, port 5005
41 * See Annex B of ITU-T Recommendation H.225.0, section B.7
43 * Information on PoC can be found from http://www.openmobilealliance.org/
45 * RTCP XR is specified in RFC 3611.
47 * See also http://www.iana.org/assignments/rtp-parameters
56 #include <epan/packet.h>
61 #include "packet-rtcp.h"
62 #include "packet-ntp.h"
63 #include <epan/conversation.h>
65 #include <epan/prefs.h>
66 #include <epan/emem.h>
67 #include <epan/expert.h>
70 /* Version is the first 2 bits of the first octet*/
71 #define RTCP_VERSION(octet) ((octet) >> 6)
73 /* Padding is the third bit; no need to shift, because true is any value
75 #define RTCP_PADDING(octet) ((octet) & 0x20)
77 /* Receiver/ Sender count is the 5 last bits */
78 #define RTCP_COUNT(octet) ((octet) & 0x1F)
80 static dissector_handle_t rtcp_handle;
82 static const value_string rtcp_version_vals[] =
84 { 0, "Old VAT Version" },
85 { 1, "First Draft Version" },
86 { 2, "RFC 1889 Version" },
90 /* RTCP packet types according to Section A.11.1 */
91 /* And http://www.iana.org/assignments/rtp-parameters */
97 #define RTCP_RTPFB 205
100 /* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
102 #define RTCP_NACK 193
104 static const value_string rtcp_packet_type_vals[] =
106 { RTCP_SR, "Sender Report" },
107 { RTCP_RR, "Receiver Report" },
108 { RTCP_SDES, "Source description" },
109 { RTCP_BYE, "Goodbye" },
110 { RTCP_APP, "Application specific" },
111 { RTCP_FIR, "Full Intra-frame Request (H.261)" },
112 { RTCP_NACK, "Negative Acknowledgement (H.261)" },
113 { RTCP_RTPFB, "Generic RTP Feedback" },
114 { RTCP_PSFB, "Payload-specific" },
115 { RTCP_XR, "Extended report (RFC 3611)"},
119 /* RTCP SDES types (Section A.11.2) */
120 #define RTCP_SDES_END 0
121 #define RTCP_SDES_CNAME 1
122 #define RTCP_SDES_NAME 2
123 #define RTCP_SDES_EMAIL 3
124 #define RTCP_SDES_PHONE 4
125 #define RTCP_SDES_LOC 5
126 #define RTCP_SDES_TOOL 6
127 #define RTCP_SDES_NOTE 7
128 #define RTCP_SDES_PRIV 8
129 #define RTCP_SDES_H323_CADDR 9
131 static const value_string rtcp_sdes_type_vals[] =
133 { RTCP_SDES_END, "END" },
134 { RTCP_SDES_CNAME, "CNAME (user and domain)" },
135 { RTCP_SDES_NAME, "NAME (common name)" },
136 { RTCP_SDES_EMAIL, "EMAIL (e-mail address)" },
137 { RTCP_SDES_PHONE, "PHONE (phone number)" },
138 { RTCP_SDES_LOC, "LOC (geographic location)" },
139 { RTCP_SDES_TOOL, "TOOL (name/version of source app)" },
140 { RTCP_SDES_NOTE, "NOTE (note about source)" },
141 { RTCP_SDES_PRIV, "PRIV (private extensions)" },
142 { RTCP_SDES_H323_CADDR,"H323-CADDR (H.323 callable address)"},
146 /* RTCP XR Blocks (Section 4, RTC 3611) */
147 #define RTCP_XR_LOSS_RLE 1
148 #define RTCP_XR_DUP_RLE 2
149 #define RTCP_XR_PKT_RXTIMES 3
150 #define RTCP_XR_REF_TIME 4
151 #define RTCP_XR_DLRR 5
152 #define RTCP_XR_STATS_SUMRY 6
153 #define RTCP_XR_VOIP_METRCS 7
155 static const value_string rtcp_xr_type_vals[] =
157 { RTCP_XR_LOSS_RLE, "Loss Run Length Encoding Report Block" },
158 { RTCP_XR_DUP_RLE, "Duplicate Run Length Encoding Report Block" },
159 { RTCP_XR_PKT_RXTIMES, "Packet Receipt Times Report Block" },
160 { RTCP_XR_REF_TIME, "Receiver Reference Time Report Block" },
161 { RTCP_XR_DLRR, "DLRR Report Block" },
162 { RTCP_XR_STATS_SUMRY, "Statistics Summary Report Block" },
163 { RTCP_XR_VOIP_METRCS, "VoIP Metrics Report Block" },
167 /* XR VoIP Metrics Block - PLC Algorithms */
168 static const value_string rtcp_xr_plc_algo_vals[] =
170 { 0, "Unspecified" },
177 /* XR VoIP Metrics Block - JB Adaptive */
178 static const value_string rtcp_xr_jb_adaptive_vals[] =
182 { 2, "Non-Adaptive" },
187 /* XR Stats Summary Block - IP TTL or Hop Limit */
188 static const value_string rtcp_xr_ip_ttl_vals[] =
190 { 0, "No TTL Values" },
197 /* RTCP Application PoC1 Value strings
198 * OMA-TS-PoC-UserPlane-V1_0-20060609-A
201 #define TBCP_BURST_REQUEST 0
202 #define TBCP_BURST_GRANTED 1
203 #define TBCP_BURST_TAKEN_EXPECT_NO_REPLY 2
204 #define TBCP_BURST_DENY 3
205 #define TBCP_BURST_RELEASE 4
206 #define TBCP_BURST_IDLE 5
207 #define TBCP_BURST_REVOKE 6
208 #define TBCP_BURST_ACKNOWLEDGMENT 7
209 #define TBCP_QUEUE_STATUS_REQUEST 8
210 #define TBCP_QUEUE_STATUS_RESPONSE 9
211 #define TBCP_DISCONNECT 11
212 #define TBCP_CONNECT 15
213 #define TBCP_BURST_TAKEN_EXPECT_REPLY 18
216 static const value_string rtcp_app_poc1_floor_cnt_type_vals[] =
218 { TBCP_BURST_REQUEST, "TBCP Talk Burst Request"},
219 { TBCP_BURST_GRANTED, "TBCP Talk Burst Granted"},
220 { TBCP_BURST_TAKEN_EXPECT_NO_REPLY, "TBCP Talk Burst Taken (no ack expected)"},
221 { TBCP_BURST_DENY, "TBCP Talk Burst Deny"},
222 { TBCP_BURST_RELEASE, "TBCP Talk Burst Release"},
223 { TBCP_BURST_IDLE, "TBCP Talk Burst Idle"},
224 { TBCP_BURST_REVOKE, "TBCP Talk Burst Revoke"},
225 { TBCP_BURST_ACKNOWLEDGMENT, "TBCP Talk Burst Acknowledgement"},
226 { TBCP_QUEUE_STATUS_REQUEST, "TBCP Queue Status Request"},
227 { TBCP_QUEUE_STATUS_RESPONSE, "TBCP Queue Status Response"},
228 { TBCP_DISCONNECT, "TBCP Disconnect"},
229 { TBCP_CONNECT, "TBCP Connect"},
230 { TBCP_BURST_TAKEN_EXPECT_REPLY, "TBCP Talk Burst Taken (ack expected)"},
234 static const value_string rtcp_app_poc1_reason_code1_vals[] =
236 { 1, "Another PoC User has permission"},
237 { 2, "Internal PoC server error"},
238 { 3, "Only one participant in the group"},
239 { 4, "Retry-after timer has not expired"},
244 static const value_string rtcp_app_poc1_reason_code2_vals[] =
246 { 1, "Only one user"},
247 { 2, "Talk burst too long"},
248 { 3, "No permission to send a Talk Burst"},
249 { 4, "Talk burst pre-empted"},
253 static const value_string rtcp_app_poc1_reason_code_ack_vals[] =
257 { 2, "Not accepted"},
260 static const value_string rtcp_app_poc1_conn_sess_type_vals[] =
265 { 3, "Pre-arranged"},
270 static const value_string rtcp_app_poc1_qsresp_priority_vals[] =
272 { 0, "No priority (un-queued)"},
273 { 1, "Normal priority"},
274 { 2, "High priority"},
275 { 3, "Pre-emptive priority"},
279 /* RTCP header fields */
280 static int proto_rtcp = -1;
281 static int hf_rtcp_version = -1;
282 static int hf_rtcp_padding = -1;
283 static int hf_rtcp_rc = -1;
284 static int hf_rtcp_sc = -1;
285 static int hf_rtcp_pt = -1;
286 static int hf_rtcp_length = -1;
287 static int hf_rtcp_ssrc_sender = -1;
288 static int hf_rtcp_ntp = -1;
289 static int hf_rtcp_ntp_msw = -1;
290 static int hf_rtcp_ntp_lsw = -1;
291 static int hf_rtcp_rtp_timestamp = -1;
292 static int hf_rtcp_sender_pkt_cnt = -1;
293 static int hf_rtcp_sender_oct_cnt = -1;
294 static int hf_rtcp_ssrc_source = -1;
295 static int hf_rtcp_ssrc_fraction = -1;
296 static int hf_rtcp_ssrc_cum_nr = -1;
297 static int hf_rtcp_ssrc_discarded = -1;
298 /* First the 32 bit number, then the split
299 * up 16 bit values */
300 /* These two are added to a subtree */
301 static int hf_rtcp_ssrc_ext_high_seq = -1;
302 static int hf_rtcp_ssrc_high_seq = -1;
303 static int hf_rtcp_ssrc_high_cycles = -1;
304 static int hf_rtcp_ssrc_jitter = -1;
305 static int hf_rtcp_ssrc_lsr = -1;
306 static int hf_rtcp_ssrc_dlsr = -1;
307 static int hf_rtcp_ssrc_csrc = -1;
308 static int hf_rtcp_sdes_type = -1;
309 static int hf_rtcp_sdes_length = -1;
310 static int hf_rtcp_sdes_text = -1;
311 static int hf_rtcp_sdes_prefix_len = -1;
312 static int hf_rtcp_sdes_prefix_string= -1;
313 static int hf_rtcp_subtype = -1;
314 static int hf_rtcp_name_ascii = -1;
315 static int hf_rtcp_app_data = -1;
316 static int hf_rtcp_fsn = -1;
317 static int hf_rtcp_blp = -1;
318 static int hf_rtcp_padding_count = -1;
319 static int hf_rtcp_padding_data = -1;
320 static int hf_rtcp_profile_specific_extension = -1;
321 static int hf_rtcp_app_poc1 = -1;
322 static int hf_rtcp_app_poc1_subtype = -1;
323 static int hf_rtcp_app_poc1_sip_uri = -1;
324 static int hf_rtcp_app_poc1_disp_name = -1;
325 static int hf_rtcp_app_poc1_priority = -1;
326 static int hf_rtcp_app_poc1_request_ts = -1;
327 static int hf_rtcp_app_poc1_stt = -1;
328 static int hf_rtcp_app_poc1_partic = -1;
329 static int hf_rtcp_app_poc1_ssrc_granted = -1;
330 static int hf_rtcp_app_poc1_last_pkt_seq_no = -1;
331 static int hf_rtcp_app_poc1_ignore_seq_no = -1;
332 static int hf_rtcp_app_poc1_reason_code1 = -1;
333 static int hf_rtcp_app_poc1_reason1_phrase = -1;
334 static int hf_rtcp_app_poc1_reason_code2 = -1;
335 static int hf_rtcp_app_poc1_new_time_request = -1;
336 static int hf_rtcp_app_poc1_ack_subtype = -1;
337 static int hf_rtcp_app_poc1_ack_reason_code = -1;
338 static int hf_rtcp_app_poc1_qsresp_priority = -1;
339 static int hf_rtcp_app_poc1_qsresp_position = -1;
340 static int hf_rtcp_app_poc1_conn_content[5] = { -1, -1, -1, -1, -1 };
341 static int hf_rtcp_app_poc1_conn_session_type = -1;
342 static int hf_rtcp_app_poc1_conn_add_ind_mao = -1;
343 static int hf_rtcp_app_poc1_conn_sdes_items[5] = { -1, -1, -1, -1, -1 };
344 static int hf_rtcp_xr_block_type = -1;
345 static int hf_rtcp_xr_block_specific = -1;
346 static int hf_rtcp_xr_block_length = -1;
347 static int hf_rtcp_xr_thinning = -1;
348 static int hf_rtcp_xr_voip_metrics_burst_density = -1;
349 static int hf_rtcp_xr_voip_metrics_gap_density = -1;
350 static int hf_rtcp_xr_voip_metrics_burst_duration = -1;
351 static int hf_rtcp_xr_voip_metrics_gap_duration = -1;
352 static int hf_rtcp_xr_voip_metrics_rtdelay = -1;
353 static int hf_rtcp_xr_voip_metrics_esdelay = -1;
354 static int hf_rtcp_xr_voip_metrics_siglevel = -1;
355 static int hf_rtcp_xr_voip_metrics_noiselevel = -1;
356 static int hf_rtcp_xr_voip_metrics_rerl = -1;
357 static int hf_rtcp_xr_voip_metrics_gmin = -1;
358 static int hf_rtcp_xr_voip_metrics_rfactor = -1;
359 static int hf_rtcp_xr_voip_metrics_extrfactor = -1;
360 static int hf_rtcp_xr_voip_metrics_moslq = -1;
361 static int hf_rtcp_xr_voip_metrics_moscq = -1;
362 static int hf_rtcp_xr_voip_metrics_plc = -1;
363 static int hf_rtcp_xr_voip_metrics_jbadaptive = -1;
364 static int hf_rtcp_xr_voip_metrics_jbrate = -1;
365 static int hf_rtcp_xr_voip_metrics_jbnominal = -1;
366 static int hf_rtcp_xr_voip_metrics_jbmax = -1;
367 static int hf_rtcp_xr_voip_metrics_jbabsmax = -1;
368 static int hf_rtcp_xr_stats_loss_flag = -1;
369 static int hf_rtcp_xr_stats_dup_flag = -1;
370 static int hf_rtcp_xr_stats_jitter_flag = -1;
371 static int hf_rtcp_xr_stats_ttl = -1;
372 static int hf_rtcp_xr_beginseq = -1;
373 static int hf_rtcp_xr_endseq = -1;
374 static int hf_rtcp_xr_stats_lost = -1;
375 static int hf_rtcp_xr_stats_dups = -1;
376 static int hf_rtcp_xr_stats_minjitter = -1;
377 static int hf_rtcp_xr_stats_maxjitter = -1;
378 static int hf_rtcp_xr_stats_meanjitter = -1;
379 static int hf_rtcp_xr_stats_devjitter = -1;
380 static int hf_rtcp_xr_stats_minttl = -1;
381 static int hf_rtcp_xr_stats_maxttl = -1;
382 static int hf_rtcp_xr_stats_meanttl = -1;
383 static int hf_rtcp_xr_stats_devttl = -1;
384 static int hf_rtcp_xr_lrr = -1;
385 static int hf_rtcp_xr_dlrr = -1;
386 static int hf_rtcp_length_check = -1;
388 /* RTCP setup fields */
389 static int hf_rtcp_setup = -1;
390 static int hf_rtcp_setup_frame = -1;
391 static int hf_rtcp_setup_method = -1;
393 /* RTCP roundtrip delay fields */
394 static int hf_rtcp_last_sr_timestamp_frame = -1;
395 static int hf_rtcp_roundtrip_delay = -1;
399 /* RTCP fields defining a sub tree */
400 static gint ett_rtcp = -1;
401 static gint ett_ssrc = -1;
402 static gint ett_ssrc_item = -1;
403 static gint ett_ssrc_ext_high = -1;
404 static gint ett_sdes = -1;
405 static gint ett_sdes_item = -1;
406 static gint ett_PoC1 = -1;
407 static gint ett_rtcp_setup = -1;
408 static gint ett_rtcp_roundtrip_delay = -1;
409 static gint ett_xr_block = -1;
410 static gint ett_xr_block_contents = -1;
411 static gint ett_xr_ssrc = -1;
412 static gint ett_xr_loss_chunk = -1;
413 static gint ett_poc1_conn_contents = -1;
415 /* Protocol registration */
416 void proto_register_rtcp(void);
417 void proto_reg_handoff_rtcp(void);
419 /* Main dissection function */
420 static void dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo,
423 /* Heuristic dissection */
424 static gboolean global_rtcp_heur = FALSE;
425 static gboolean dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo,
428 /* Displaying set info */
429 static gboolean global_rtcp_show_setup_info = TRUE;
430 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
432 /* Related to roundtrip calculation (using LSR and DLSR) */
433 static gboolean global_rtcp_show_roundtrip_calculation = FALSE;
434 #define MIN_ROUNDTRIP_TO_REPORT_DEFAULT 10
435 static guint global_rtcp_show_roundtrip_calculation_minimum = MIN_ROUNDTRIP_TO_REPORT_DEFAULT;
436 static void remember_outgoing_sr(packet_info *pinfo, long lsr);
437 static void calculate_roundtrip_delay(tvbuff_t *tvb, packet_info *pinfo,
438 proto_tree *tree, guint32 lsr, guint32 dlsr);
439 static void add_roundtrip_delay_info(tvbuff_t *tvb, packet_info *pinfo,
440 proto_tree *tree, guint frame, guint delay);
443 /* Set up an RTCP conversation using the info given */
444 void rtcp_add_address( packet_info *pinfo,
445 address *addr, int port,
447 const gchar *setup_method, guint32 setup_frame_number)
450 conversation_t* p_conv;
451 struct _rtcp_conversation_info *p_conv_data = NULL;
454 * If this isn't the first time this packet has been processed,
455 * we've already done this work, so we don't need to do it
458 if (pinfo->fd->flags.visited)
463 SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
466 * Check if the ip address and port combination is not
467 * already registered as a conversation.
469 p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_UDP, port, other_port,
470 NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
473 * If not, create a new conversation.
476 p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_UDP,
477 (guint32)port, (guint32)other_port,
478 NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
482 conversation_set_dissector(p_conv, rtcp_handle);
485 * Check if the conversation has data associated with it.
487 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
490 * If not, add a new data item.
492 if ( ! p_conv_data ) {
493 /* Create conversation data */
494 p_conv_data = se_alloc(sizeof(struct _rtcp_conversation_info));
499 memset(p_conv_data, 0, sizeof(struct _rtcp_conversation_info));
500 conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
504 * Update the conversation data.
506 p_conv_data->setup_method_set = TRUE;
507 strncpy(p_conv_data->setup_method, setup_method, MAX_RTCP_SETUP_METHOD_SIZE);
508 p_conv_data->setup_method[MAX_RTCP_SETUP_METHOD_SIZE] = '\0';
509 p_conv_data->setup_frame_number = setup_frame_number;
513 dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
515 unsigned int offset = 0;
516 unsigned int first_byte;
517 unsigned int packet_type;
519 /* This is a heuristic dissector, which means we get all the UDP
520 * traffic not sent to a known dissector and not claimed by
521 * a heuristic dissector called before us!
524 if (!global_rtcp_heur)
529 /* Was it sent between 2 odd-numbered ports? */
530 if (!(pinfo->srcport % 2) || !(pinfo->destport % 2))
535 /* Look at first byte */
536 first_byte = tvb_get_guint8(tvb, offset);
538 /* Are version bits set to 2? */
539 if (((first_byte & 0xC0) >> 6) != 2)
544 /* Look at packet type */
545 packet_type = tvb_get_guint8(tvb, offset + 1);
547 /* First packet within compound packet is supposed to be a sender
549 - allow BYE because this happens anyway
550 - allow APP because TBCP ("PoC1") packets aren't compound... */
551 if (!((packet_type == RTCP_SR) || (packet_type == RTCP_RR) ||
552 (packet_type == RTCP_BYE) || (packet_type == RTCP_APP)))
557 /* Overall length must be a multiple of 4 bytes */
558 if (tvb_length(tvb) % 4)
563 /* OK, dissect as RTCP */
564 dissect_rtcp(tvb, pinfo, tree);
570 dissect_rtcp_nack( tvbuff_t *tvb, int offset, proto_tree *tree )
572 /* Packet type = FIR (H261) */
573 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
575 /* Packet type, 8 bits = APP */
576 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
579 /* Packet length in 32 bit words minus one */
580 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
584 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
588 proto_tree_add_uint( tree, hf_rtcp_fsn, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
592 proto_tree_add_uint( tree, hf_rtcp_blp, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
599 dissect_rtcp_fir( tvbuff_t *tvb, int offset, proto_tree *tree )
601 /* Packet type = FIR (H261) */
602 proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
604 /* Packet type, 8 bits = APP */
605 proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
608 /* Packet length in 32 bit words minus one */
609 proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
613 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
620 dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree,
621 unsigned int padding, unsigned int packet_len, guint rtcp_subtype, guint32 app_length )
623 unsigned int counter = 0;
627 guint items_start_offset;
628 proto_tree *PoC1_tree;
629 proto_item *PoC1_item;
631 /* XXX If more application types are to be dissected it may be useful to use a table like in packet-sip.c */
632 static const char poc1_app_name_str[] = "PoC1";
636 proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
640 /* Application Name (ASCII) */
641 for( counter = 0; counter < 4; counter++ )
642 ascii_name[ counter ] = tvb_get_guint8( tvb, offset + counter );
643 /* strncpy( ascii_name, pd + offset, 4 ); */
644 ascii_name[4] = '\0';
645 proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
648 /* See if we can handle this application type */
649 if ( strncasecmp(ascii_name, poc1_app_name_str,4 ) == 0 )
651 /* PoC1 Application */
652 guint8 t2timer_code, participants_code;
654 item = proto_tree_add_uint( tree, hf_rtcp_app_poc1_subtype, tvb, offset - 8, 1, rtcp_subtype );
655 PROTO_ITEM_SET_GENERATED(item);
656 if (check_col(pinfo->cinfo, COL_INFO))
657 col_append_fstr(pinfo->cinfo, COL_INFO,"(%s) %s",ascii_name,
658 val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
661 app_length = app_length -8;
662 if ( packet_len == 0 )
663 return offset; /* No more data */
664 /* Applications specific data */
666 /* If there's padding present, we have to remove that from the data part
667 * The last octet of the packet contains the length of the padding
669 packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
671 /* Create a subtree for the PoC1 Application items; we don't yet know
673 items_start_offset = offset;
675 /* Top-level poc tree */
676 PoC1_item = proto_tree_add_item(tree, hf_rtcp_app_poc1, tvb, offset, packet_len, FALSE);
677 PoC1_tree = proto_item_add_subtree( PoC1_item, ett_PoC1 );
679 /* Dissect it according to its subtype */
680 switch ( rtcp_subtype ) {
682 case TBCP_BURST_REQUEST:
687 /* Both items here are optional */
688 if (tvb_reported_length_remaining( tvb, offset) == 0)
693 /* Look for a code in the first byte */
694 code = tvb_get_guint8(tvb, offset);
698 /* Priority (optional) */
701 item_len = tvb_get_guint8(tvb, offset);
704 if (item_len != 2) /* SHALL be 2 */
707 priority = tvb_get_ntohs(tvb, offset);
708 proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_priority, tvb, offset, 2, FALSE );
712 if (check_col(pinfo->cinfo, COL_INFO))
714 col_append_fstr(pinfo->cinfo, COL_INFO,
717 rtcp_app_poc1_qsresp_priority_vals,
721 /* Look for (optional) next code */
722 if (tvb_reported_length_remaining( tvb, offset) == 0)
726 code = tvb_get_guint8(tvb, offset);
732 /* Request timestamp (optional) */
736 item_len = tvb_get_guint8(tvb, offset);
739 if (item_len != 8) /* SHALL be 8 */
742 buff = ntp_fmt_ts(tvb_get_ptr(tvb, offset, 8));
743 proto_tree_add_string_format(PoC1_tree, hf_rtcp_app_poc1_request_ts,
744 tvb, offset, 8, ( const char* ) buff,
745 "Request timestamp: %s", buff );
749 if (check_col(pinfo->cinfo, COL_INFO))
751 col_append_fstr(pinfo->cinfo, COL_INFO, " ts=\"%s\"", buff);
757 case TBCP_BURST_GRANTED:
760 guint16 stop_talking_time;
761 guint16 participants;
763 /* Stop talking timer (now mandatory) */
764 t2timer_code = tvb_get_guint8(tvb, offset);
767 if (t2timer_code != 101) /* SHALL be 101 */
770 item_len = tvb_get_guint8(tvb, offset);
773 if (item_len != 2) /* SHALL be 2 */
776 stop_talking_time = tvb_get_ntohs(tvb, offset);
777 ti = proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_stt, tvb, offset, 2, FALSE );
779 /* Append text with meanings of value */
780 switch (stop_talking_time)
783 proto_item_append_text(ti, " unknown");
786 proto_item_append_text(ti, " infinity");
789 proto_item_append_text(ti, " seconds");
793 packet_len -= item_len;
795 if (check_col(pinfo->cinfo, COL_INFO))
797 col_append_fstr(pinfo->cinfo, COL_INFO, " stop-talking-time=%u",
801 /* Participants (optional) */
802 if (tvb_reported_length_remaining( tvb, offset) == 0)
806 participants_code = tvb_get_guint8(tvb, offset);
809 if (participants_code != 100) /* SHALL be 100 */
812 item_len = tvb_get_guint8(tvb, offset);
815 if (item_len != 2) /* SHALL be 2 */
818 participants = tvb_get_ntohs(tvb, offset);
819 ti = proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_partic, tvb, offset, 2, FALSE );
821 /* Append text with meanings of extreme values */
822 switch (participants)
825 proto_item_append_text(ti, " (not known)");
828 proto_item_append_text(ti, " (or more)");
834 packet_len -= item_len;
836 if (check_col(pinfo->cinfo, COL_INFO))
838 col_append_fstr(pinfo->cinfo, COL_INFO, " participants=%u",
845 case TBCP_BURST_TAKEN_EXPECT_NO_REPLY:
846 case TBCP_BURST_TAKEN_EXPECT_REPLY:
848 guint16 participants;
851 /* SSRC of PoC client */
852 proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_ssrc_granted, tvb, offset, 4, FALSE );
856 /* SDES type (must be CNAME) */
857 sdes_type = tvb_get_guint8( tvb, offset );
858 proto_tree_add_item( PoC1_tree, hf_rtcp_sdes_type, tvb, offset, 1, FALSE );
861 if (sdes_type != RTCP_SDES_CNAME)
866 /* Item length, 8 bits */
867 item_len = tvb_get_guint8( tvb, offset );
868 proto_tree_add_item( PoC1_tree, hf_rtcp_sdes_length, tvb, offset, 1, FALSE );
873 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_sip_uri, tvb, offset, item_len, FALSE );
875 if (check_col(pinfo->cinfo, COL_INFO))
877 col_append_fstr(pinfo->cinfo, COL_INFO, " CNAME=\"%s\"",
878 tvb_get_ephemeral_string(tvb, offset, item_len));
881 offset = offset + item_len;
882 packet_len = packet_len - item_len;
884 /* In the application dependent data, the TBCP Talk Burst Taken message SHALL carry
885 * a SSRC field and SDES items, CNAME and MAY carry SDES item NAME to identify the
886 * PoC Client that has been granted permission to send a Talk Burst.
888 * The SDES item NAME SHALL be included if it is known by the PoC Server.
889 * Therefore the length of the packet will vary depending on number of SDES items
890 * and the size of the SDES items.
892 if ( packet_len == 0 )
895 /* SDES type (must be NAME if present) */
896 sdes_type = tvb_get_guint8( tvb, offset );
897 if (sdes_type == RTCP_SDES_NAME)
899 proto_tree_add_item( PoC1_tree, hf_rtcp_sdes_type, tvb, offset, 1, FALSE );
903 /* Item length, 8 bits */
904 item_len = tvb_get_guint8( tvb, offset );
905 proto_tree_add_item( PoC1_tree, hf_rtcp_sdes_length, tvb, offset, 1, FALSE );
911 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_disp_name, tvb, offset, item_len, FALSE );
912 offset = offset + item_len;
913 packet_len = packet_len - item_len;
919 /* Participants (optional) */
920 if (tvb_reported_length_remaining( tvb, offset) == 0)
924 participants_code = tvb_get_guint8(tvb, offset);
927 if (participants_code != 100) /* SHALL be 100 */
929 item_len = tvb_get_guint8(tvb, offset);
932 if (item_len != 2) /* SHALL be 2 */
935 participants = tvb_get_ntohs(tvb, offset);
936 ti = proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_partic, tvb, offset, 2, FALSE );
938 /* Append text with meanings of extreme values */
939 switch (participants)
942 proto_item_append_text(ti, " (not known)");
945 proto_item_append_text(ti, " (or more)");
952 packet_len -= item_len;
956 case TBCP_BURST_DENY:
961 reason_code = tvb_get_guint8(tvb, offset);
962 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code1, tvb, offset, 1, FALSE );
966 if (check_col(pinfo->cinfo, COL_INFO))
968 col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
969 val_to_str(reason_code,
970 rtcp_app_poc1_reason_code1_vals,
975 item_len = tvb_get_guint8( tvb, offset );
977 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason1_phrase, tvb, offset, 1, FALSE );
979 offset += (item_len+1);
980 packet_len -= (item_len+1);
984 case TBCP_BURST_RELEASE:
987 guint8 ignore_last_seq_no;
989 /* Sequence number of last RTP packet in burst */
990 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_last_pkt_seq_no, tvb, offset, 2, FALSE );
991 last_seq_no = tvb_get_ntohs(tvb, offset);
993 /* Bit 16 is ignore flag */
995 proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_ignore_seq_no, tvb, offset, 2, FALSE );
996 ignore_last_seq_no = (tvb_get_ntohs(tvb, offset) & 0x8000);
998 if (!ignore_last_seq_no && check_col(pinfo->cinfo, COL_INFO))
1000 col_append_fstr(pinfo->cinfo, COL_INFO, " last_rtp_seq_no=%u",
1004 /* 15 bits of padding follows */
1011 case TBCP_BURST_IDLE:
1014 case TBCP_BURST_REVOKE:
1017 guint16 reason_code = tvb_get_ntohs(tvb, offset);
1018 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code2, tvb, offset, 2, FALSE );
1020 /* The meaning of this field depends upon the reason code... */
1021 switch (reason_code)
1023 case 1: /* Only one user */
1024 /* No additional info */
1026 case 2: /* Talk burst too long */
1027 /* Additional info is 16 bits with time (in seconds) client can request */
1028 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_new_time_request, tvb, offset + 2, 2, FALSE );
1030 case 3: /* No permission */
1031 /* No additional info */
1033 case 4: /* Pre-empted */
1034 /* No additional info */
1038 if (check_col(pinfo->cinfo, COL_INFO))
1040 col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
1041 val_to_str(reason_code,
1042 rtcp_app_poc1_reason_code2_vals,
1050 case TBCP_BURST_ACKNOWLEDGMENT:
1054 /* Code of message being acknowledged */
1055 subtype = (tvb_get_guint8(tvb, offset) & 0xf8) >> 3;
1056 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_ack_subtype, tvb, offset, 1, FALSE );
1058 if (check_col(pinfo->cinfo, COL_INFO))
1060 col_append_fstr(pinfo->cinfo, COL_INFO, " (for %s)",
1062 rtcp_app_poc1_floor_cnt_type_vals,
1066 /* Reason code only seen if subtype was Connect */
1067 if (subtype == TBCP_CONNECT)
1069 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_ack_reason_code, tvb, offset, 2, FALSE );
1072 /* 16 bits of padding follow */
1078 case TBCP_QUEUE_STATUS_REQUEST:
1081 case TBCP_QUEUE_STATUS_RESPONSE:
1087 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_qsresp_priority, tvb, offset, 1, FALSE );
1089 /* Queue position. 65535 indicates 'position not available' */
1090 position = tvb_get_ntohs(tvb, offset+1);
1091 ti = proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_qsresp_position, tvb, offset+1, 2, FALSE );
1094 proto_item_append_text(ti, " (client is un-queued)");
1096 if (position == 65535)
1098 proto_item_append_text(ti, " (position not available)");
1101 if (check_col(pinfo->cinfo, COL_INFO))
1103 col_append_fstr(pinfo->cinfo, COL_INFO, " position=%u", position);
1106 /* 1 bytes of padding follows */
1113 case TBCP_DISCONNECT:
1118 proto_item *content = proto_tree_add_text(PoC1_tree, tvb, offset, 2, "SDES item content");
1119 gboolean contents[5];
1121 guint8 items_set = 0;
1123 proto_tree *content_tree = proto_item_add_subtree(content, ett_poc1_conn_contents);
1124 guint16 items_field = tvb_get_ntohs(tvb, offset );
1126 /* Dissect each defined bit flag in the SDES item content */
1128 i < sizeof(contents) / sizeof(contents[0]) &&
1129 i < sizeof(hf_rtcp_app_poc1_conn_content) /
1130 sizeof(hf_rtcp_app_poc1_conn_content[0]);
1133 proto_tree_add_item( content_tree, hf_rtcp_app_poc1_conn_content[i], tvb, offset, 2, FALSE );
1134 contents[i] = items_field & (1 << (15-i));
1135 if (contents[i]) ++items_set;
1138 /* Show how many flags were set */
1139 proto_item_append_text(content, " (%u items)", items_set);
1142 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_conn_session_type, tvb, offset + 2, 1, FALSE );
1144 /* Additional indications */
1145 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_conn_add_ind_mao, tvb, offset + 3, 1, FALSE );
1150 /* One SDES item for every set flag in contents array */
1152 i < sizeof(contents) / sizeof(contents[0]);
1154 if ( contents[i] ) {
1155 guint sdes_type, sdes_len;
1156 /* (sdes_type not currently used...). Could complain if type
1157 doesn't match expected for item... */
1158 sdes_type = tvb_get_guint8( tvb, offset++ );
1159 sdes_len = tvb_get_guint8( tvb, offset );
1161 /* Add SDES field indicated as present */
1162 proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_conn_sdes_items[i], tvb, offset, 1, FALSE );
1164 /* Move past field */
1165 offset += sdes_len + 1;
1166 packet_len -= (sdes_len + 2);
1175 offset += packet_len;
1180 /* Unhandled application type, just show app name and raw data */
1181 if (check_col(pinfo->cinfo, COL_INFO))
1182 col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
1185 /* Applications specific data */
1187 /* If there's padding present, we have to remove that from the data part
1188 * The last octet of the packet contains the length of the padding
1190 packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
1192 proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
1193 offset += packet_len;
1202 dissect_rtcp_bye( tvbuff_t *tvb, int offset, proto_tree *tree,
1203 unsigned int count )
1205 unsigned int chunk = 1;
1206 unsigned int reason_length = 0;
1207 char* reason_text = NULL;
1209 while ( chunk <= count ) {
1210 /* source identifier, 32 bits */
1211 proto_tree_add_item( tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1216 if ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
1217 /* Bye reason consists of an 8 bit length l and a string with length l */
1218 reason_length = tvb_get_guint8( tvb, offset );
1219 proto_tree_add_item( tree, hf_rtcp_sdes_length, tvb, offset, 1, FALSE );
1222 reason_text = (char*)tvb_get_ephemeral_string(tvb, offset, reason_length);
1223 proto_tree_add_string( tree, hf_rtcp_sdes_text, tvb, offset, reason_length, reason_text );
1224 /* Allow for terminating null character */
1225 offset += (reason_length+1);
1228 /* BYE packet padded out if string (including null) didn't fit in previous word */
1231 offset += (4 - (offset % 4));
1238 dissect_rtcp_sdes( tvbuff_t *tvb, int offset, proto_tree *tree,
1239 unsigned int count )
1241 unsigned int chunk = 1;
1242 proto_item *sdes_item;
1243 proto_tree *sdes_tree;
1244 proto_tree *sdes_item_tree;
1247 int items_start_offset;
1249 unsigned int item_len = 0;
1250 unsigned int sdes_type = 0;
1251 unsigned int prefix_len = 0;
1253 while ( chunk <= count ) {
1254 /* Create a subtree for this chunk; we don't yet know
1256 start_offset = offset;
1258 ssrc = tvb_get_ntohl( tvb, offset );
1259 sdes_item = proto_tree_add_text(tree, tvb, offset, -1,
1260 "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
1261 sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
1263 /* SSRC_n source identifier, 32 bits */
1264 proto_tree_add_uint( sdes_tree, hf_rtcp_ssrc_source, tvb, offset, 4, ssrc );
1267 /* Create a subtree for the SDES items; we don't yet know
1269 items_start_offset = offset;
1270 ti = proto_tree_add_text(sdes_tree, tvb, offset, -1,
1272 sdes_item_tree = proto_item_add_subtree( ti, ett_sdes_item );
1275 * Not every message is ended with "null" bytes, so check for
1276 * end of frame as well.
1278 while ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
1280 sdes_type = tvb_get_guint8( tvb, offset );
1281 proto_tree_add_item( sdes_item_tree, hf_rtcp_sdes_type, tvb, offset, 1, FALSE );
1284 if ( sdes_type == RTCP_SDES_END ) {
1289 /* Item length, 8 bits */
1290 item_len = tvb_get_guint8( tvb, offset );
1291 proto_tree_add_item( sdes_item_tree, hf_rtcp_sdes_length, tvb, offset, 1, FALSE );
1294 if ( item_len != 0 ) {
1295 if ( sdes_type == RTCP_SDES_PRIV ) {
1296 /* PRIV adds two items between the
1297 * SDES length and value - an 8 bit
1298 * length giving the length of a
1299 * "prefix string", and the string.
1301 prefix_len = tvb_get_guint8( tvb, offset );
1302 if ( prefix_len + 1 > item_len ) {
1303 proto_tree_add_uint_format( sdes_item_tree,
1304 hf_rtcp_sdes_prefix_len, tvb,
1305 offset, 1, prefix_len,
1306 "Prefix length: %u (bogus, must be <= %u)",
1307 prefix_len, item_len - 1);
1311 proto_tree_add_item( sdes_item_tree, hf_rtcp_sdes_prefix_len, tvb, offset, 1, FALSE );
1314 proto_tree_add_item( sdes_item_tree, hf_rtcp_sdes_prefix_string, tvb, offset, prefix_len, FALSE );
1315 offset += prefix_len;
1316 item_len -= prefix_len +1;
1317 if ( item_len == 0 )
1320 proto_tree_add_item( sdes_item_tree, hf_rtcp_sdes_text, tvb, offset, item_len, FALSE );
1325 /* Set the length of the items subtree. */
1326 proto_item_set_len(ti, offset - items_start_offset);
1328 /* 32 bits = 4 bytes, so.....
1329 * If offset % 4 != 0, we divide offset by 4, add one and then
1330 * multiply by 4 again to reach the boundary
1332 if ( offset % 4 != 0 )
1333 offset = ((offset / 4) + 1 ) * 4;
1335 /* Set the length of this chunk. */
1336 proto_item_set_len(sdes_item, offset - start_offset);
1342 static void parse_xr_type_specific_field(tvbuff_t *tvb, gint offset, guint block_type, proto_tree *tree)
1344 guint8 flags = tvb_get_guint8(tvb, offset);
1346 switch (block_type) {
1347 case RTCP_XR_LOSS_RLE:
1348 case RTCP_XR_DUP_RLE:
1349 case RTCP_XR_PKT_RXTIMES:
1350 proto_tree_add_uint(tree, hf_rtcp_xr_thinning, tvb, offset, 1, flags);
1353 case RTCP_XR_STATS_SUMRY:
1354 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_loss_flag, tvb, offset, 1, flags);
1355 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_dup_flag, tvb, offset, 1, flags);
1356 proto_tree_add_boolean(tree, hf_rtcp_xr_stats_jitter_flag, tvb, offset, 1, flags);
1357 proto_tree_add_uint(tree, hf_rtcp_xr_stats_ttl, tvb, offset, 1, flags);
1361 proto_tree_add_uint(tree, hf_rtcp_xr_block_specific, tvb, offset, 1, flags);
1366 static gboolean validate_xr_block_length(tvbuff_t *tvb, int offset, guint block_type, guint block_len, proto_tree *tree)
1368 proto_tree_add_uint(tree, hf_rtcp_xr_block_length, tvb, offset, 2, block_len);
1369 switch (block_type) {
1370 case RTCP_XR_REF_TIME:
1372 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 2");
1375 case RTCP_XR_STATS_SUMRY:
1377 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 9");
1380 case RTCP_XR_VOIP_METRCS:
1382 proto_tree_add_text(tree, tvb, offset, 2, "Invalid block length, should be 8");
1392 dissect_rtcp_xr(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, gint packet_len)
1394 guint block_num = 1;
1396 /* Packet length should at least be 4 */
1397 if (packet_len < 4) {
1398 proto_tree_add_text(tree, tvb, offset, packet_len, "Missing Sender SSRC");
1399 return offset + packet_len;
1403 proto_tree_add_item( tree, hf_rtcp_ssrc_sender, tvb, offset, 4, FALSE );
1407 for(;packet_len > 0; block_num++) {
1408 guint block_type = tvb_get_guint8(tvb, offset), block_length = 0;
1409 gint content_length = 0;
1410 gboolean valid = TRUE;
1412 /* Create a subtree for this block, dont know the length yet*/
1413 proto_item *block = proto_tree_add_text(tree, tvb, offset, -1, "Block %u", block_num);
1414 proto_tree *xr_block_tree = proto_item_add_subtree(block, ett_xr_block);
1415 proto_item *contents = NULL;
1416 proto_item *content_tree = NULL;
1418 proto_tree_add_item(xr_block_tree, hf_rtcp_xr_block_type, tvb, offset, 1, FALSE);
1420 if (packet_len >= 2) {
1421 parse_xr_type_specific_field(tvb, offset + 1, block_type, xr_block_tree);
1422 if (packet_len >= 4) {
1423 block_length = tvb_get_ntohs(tvb, offset + 2);
1424 valid = validate_xr_block_length(tvb, offset + 2, block_type, block_length, xr_block_tree);
1427 proto_tree_add_text(xr_block_tree, tvb, offset + 1, packet_len, "Missing Required Block Headers");
1428 return offset + packet_len;
1431 content_length = block_length * 4;
1432 proto_item_set_len(block, content_length + 4);
1434 if (content_length > packet_len) {
1435 proto_tree_add_text(xr_block_tree, tvb, offset + 2, 2, "Block length is greater than packet length");
1441 contents = proto_tree_add_text(xr_block_tree, tvb, offset, content_length, "Contents");
1442 content_tree = proto_item_add_subtree(contents, ett_xr_block_contents);
1444 switch (block_type) {
1445 case RTCP_XR_VOIP_METRCS: {
1446 guint fraction_rate, value;
1449 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1453 fraction_rate = tvb_get_guint8(tvb, offset);
1454 proto_tree_add_uint_format(content_tree, hf_rtcp_ssrc_fraction, tvb, offset, 1,
1455 fraction_rate, "Fraction lost: %u / 256", fraction_rate);
1459 fraction_rate = tvb_get_guint8(tvb, offset);
1460 proto_tree_add_uint_format(content_tree, hf_rtcp_ssrc_discarded, tvb, offset, 1,
1461 fraction_rate, "Fraction Discarded: %u / 256", fraction_rate);
1465 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_burst_density, tvb, offset, 1, FALSE);
1469 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gap_density, tvb, offset, 1, FALSE);
1472 /* Burst Duration */
1473 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_burst_duration, tvb, offset, 2, FALSE);
1477 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gap_duration, tvb, offset, 2, FALSE);
1480 /* Round Trip Delay */
1481 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rtdelay, tvb, offset, 2, FALSE);
1484 /* End System Delay */
1485 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_esdelay, tvb, offset, 2, FALSE);
1489 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_siglevel, tvb, offset, 1, FALSE);
1493 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_noiselevel, tvb, offset, 1, FALSE);
1497 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rerl, tvb, offset, 1, FALSE);
1501 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_gmin, tvb, offset, 1, FALSE);
1505 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_rfactor, tvb, offset, 1, FALSE);
1508 /* external R Factor */
1509 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_extrfactor, tvb, offset, 1, FALSE);
1513 proto_tree_add_float(content_tree, hf_rtcp_xr_voip_metrics_moslq, tvb, offset, 1,
1514 (gfloat)(int)(tvb_get_guint8(tvb, offset) / 10));
1518 proto_tree_add_float(content_tree, hf_rtcp_xr_voip_metrics_moscq, tvb, offset, 1,
1519 (gfloat)(int)(tvb_get_guint8(tvb, offset) / 10));
1522 /* PLC, JB Adaptive, JB Rate */
1523 value = tvb_get_guint8(tvb, offset);
1524 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_plc, tvb, offset, 1, value);
1525 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_jbadaptive, tvb, offset, 1, value);
1526 proto_tree_add_uint(content_tree, hf_rtcp_xr_voip_metrics_jbrate, tvb, offset, 1, value);
1527 offset += 2; /* skip over reseved bit */
1530 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbnominal, tvb, offset, 2, FALSE);
1534 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbmax, tvb, offset, 2, FALSE);
1538 proto_tree_add_item(content_tree, hf_rtcp_xr_voip_metrics_jbabsmax, tvb, offset, 2, FALSE);
1544 case RTCP_XR_STATS_SUMRY: {
1546 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1550 proto_tree_add_item(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, FALSE);
1554 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1558 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_lost, tvb, offset, 4, FALSE);
1562 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_dups, tvb, offset, 4, FALSE);
1566 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_minjitter, tvb, offset, 4, FALSE);
1570 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_maxjitter, tvb, offset, 4, FALSE);
1574 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_meanjitter, tvb, offset, 4, FALSE);
1578 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_devjitter, tvb, offset, 4, FALSE);
1582 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_minttl, tvb, offset, 1, FALSE);
1586 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_maxttl, tvb, offset, 1, FALSE);
1590 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_meanttl, tvb, offset, 1, FALSE);
1594 proto_tree_add_item(content_tree, hf_rtcp_xr_stats_devttl, tvb, offset, 1, FALSE);
1600 case RTCP_XR_REF_TIME: {
1601 guint32 ts_msw, ts_lsw;
1603 ts_msw = tvb_get_ntohl(tvb, offset);
1604 proto_tree_add_text(content_tree, tvb, offset, 4, "Timestamp, MSW: %u", ts_msw);
1606 ts_lsw = tvb_get_ntohl(tvb, offset);
1607 proto_tree_add_text(content_tree, tvb, offset, 4, "Timestamp, LSW: %u", ts_lsw);
1613 case RTCP_XR_DLRR: {
1614 /* Each report block is 12 bytes */
1615 gint sources = content_length / 12;
1617 for(counter = 0; counter < sources; counter++) {
1618 /* Create a new subtree for a length of 12 bytes */
1619 proto_tree *ti = proto_tree_add_text(content_tree, tvb, offset, 12, "Source %u", counter + 1);
1620 proto_tree *ssrc_tree = proto_item_add_subtree(ti, ett_xr_ssrc);
1622 /* SSRC_n source identifier, 32 bits */
1623 proto_tree_add_item(ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1626 /* Last RR timestamp */
1627 proto_tree_add_item(ssrc_tree, hf_rtcp_xr_lrr, tvb, offset, 4, FALSE);
1630 /* Delay since last RR timestamp */
1631 proto_tree_add_item(ssrc_tree, hf_rtcp_xr_dlrr, tvb, offset, 4, FALSE);
1635 if (content_length % 12 != 0)
1636 offset += content_length % 12;
1640 case RTCP_XR_PKT_RXTIMES: {
1641 /* 8 bytes of fixed header */
1642 gint count = 0, skip = 8;
1646 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1650 begin = tvb_get_ntohs(tvb, offset);
1651 proto_tree_add_uint(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, begin);
1655 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1658 for(count = 0; skip < content_length; skip += 4, count++) {
1659 proto_tree_add_text(content_tree, tvb, offset, 4, "Seq: %u, Timestamp: %u",
1660 (begin + count) % 65536, FALSE);
1666 case RTCP_XR_LOSS_RLE:
1667 case RTCP_XR_DUP_RLE: {
1668 /* 8 bytes of fixed header */
1669 gint count = 0, skip = 8;
1671 proto_item *chunks_item;
1672 proto_tree *chunks_tree;
1675 proto_tree_add_item(content_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
1679 begin = tvb_get_ntohs(tvb, offset);
1680 proto_tree_add_uint(content_tree, hf_rtcp_xr_beginseq, tvb, offset, 2, begin);
1684 proto_tree_add_item(content_tree, hf_rtcp_xr_endseq, tvb, offset, 2, FALSE);
1688 chunks_item = proto_tree_add_text(content_tree, tvb, offset, content_length,"Report Chunks");
1689 chunks_tree = proto_item_add_subtree(chunks_item, ett_xr_loss_chunk);
1691 for(count = 1; skip < content_length; skip += 2, count++) {
1692 guint value = tvb_get_ntohs(tvb, offset);
1695 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1696 "Chunk: %u -- Null Terminator ",
1698 } else if ( ! ( value & 0x8000 )) {
1699 const gchar* run_type = (value & 0x4000) ? "1s" : "0s";
1701 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1702 "Chunk: %u -- Length Run %s, length: %u",
1703 count, run_type, value);
1706 other_decode_bitfield_value(bits, value, 0x00007FFF, 16);
1707 proto_tree_add_text(chunks_tree, tvb, offset, 2,
1708 "Chunk: %u -- Bit Vector, bits: %s",
1718 /* skip over the unknown block */
1719 offset += content_length;
1722 packet_len -= content_length;
1728 dissect_rtcp_rr( packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree,
1729 unsigned int count, unsigned int packet_length )
1731 unsigned int counter = 1;
1732 proto_tree *ssrc_tree = (proto_tree*) NULL;
1733 proto_tree *ssrc_sub_tree = (proto_tree*) NULL;
1734 proto_tree *high_sec_tree = (proto_tree*) NULL;
1735 proto_item *ti = (proto_item*) NULL;
1737 unsigned int cum_nr = 0;
1738 int rr_offset = offset;
1740 while ( counter <= count ) {
1743 /* Create a new subtree for a length of 24 bytes */
1744 ti = proto_tree_add_text(tree, tvb, offset, 24,
1745 "Source %u", counter );
1746 ssrc_tree = proto_item_add_subtree( ti, ett_ssrc );
1748 /* SSRC_n source identifier, 32 bits */
1749 proto_tree_add_item( ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE );
1752 ti = proto_tree_add_text(ssrc_tree, tvb, offset, 20, "SSRC contents" );
1753 ssrc_sub_tree = proto_item_add_subtree( ti, ett_ssrc_item );
1755 /* Fraction lost, 8bits */
1756 rr_flt = tvb_get_guint8( tvb, offset );
1757 proto_tree_add_uint_format( ssrc_sub_tree, hf_rtcp_ssrc_fraction, tvb,
1758 offset, 1, rr_flt, "Fraction lost: %u / 256", rr_flt );
1761 /* Cumulative number of packets lost, 24 bits */
1762 cum_nr = tvb_get_ntohl( tvb, offset ) >> 8;
1763 proto_tree_add_uint( ssrc_sub_tree, hf_rtcp_ssrc_cum_nr, tvb,
1764 offset, 3, cum_nr );
1767 /* Extended highest sequence nr received, 32 bits
1768 * Just for the sake of it, let's add another subtree
1769 * because this might be a little clearer
1771 ti = proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_ext_high_seq,
1772 tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1773 high_sec_tree = proto_item_add_subtree( ti, ett_ssrc_ext_high );
1774 /* Sequence number cycles */
1775 proto_tree_add_item( high_sec_tree, hf_rtcp_ssrc_high_cycles,
1776 tvb, offset, 2, FALSE );
1778 /* highest sequence number received */
1779 proto_tree_add_item( high_sec_tree, hf_rtcp_ssrc_high_seq,
1780 tvb, offset, 2, FALSE );
1783 /* Interarrival jitter */
1784 proto_tree_add_item( ssrc_tree, hf_rtcp_ssrc_jitter, tvb,
1788 /* Last SR timestamp */
1789 lsr = tvb_get_ntohl( tvb, offset );
1790 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_lsr, tvb,
1794 /* Delay since last SR timestamp */
1795 dlsr = tvb_get_ntohl( tvb, offset );
1796 proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_dlsr, tvb,
1800 /* Do roundtrip calculation */
1801 if (global_rtcp_show_roundtrip_calculation)
1803 /* Based on delay since SR was sent in other direction */
1804 calculate_roundtrip_delay(tvb, pinfo, ssrc_tree, lsr, dlsr);
1810 /* If length remaining, assume profile-specific extension bytes */
1811 if ((offset-rr_offset) < (int)packet_length)
1813 proto_tree_add_item(tree, hf_rtcp_profile_specific_extension, tvb, offset,
1814 packet_length - (offset - rr_offset), FALSE);
1815 offset = rr_offset + packet_length;
1822 dissect_rtcp_sr( packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree,
1823 unsigned int count, unsigned int packet_length )
1826 guint32 ts_msw, ts_lsw;
1828 int sr_offset = offset;
1831 ts_msw = tvb_get_ntohl(tvb, offset);
1832 proto_tree_add_item(tree, hf_rtcp_ntp_msw, tvb, offset, 4, FALSE);
1834 ts_lsw = tvb_get_ntohl(tvb, offset+4);
1835 proto_tree_add_item(tree, hf_rtcp_ntp_lsw, tvb, offset+4, 4, FALSE);
1837 buff=ntp_fmt_ts(tvb_get_ptr( tvb, offset, 8 ));
1838 item = proto_tree_add_string_format( tree, hf_rtcp_ntp, tvb, offset, 8, ( const char* ) buff, "MSW and LSW as NTP timestamp: %s", buff );
1839 PROTO_ITEM_SET_GENERATED(item);
1842 /* RTP timestamp, 32 bits */
1843 proto_tree_add_uint( tree, hf_rtcp_rtp_timestamp, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1845 /* Sender's packet count, 32 bits */
1846 proto_tree_add_uint( tree, hf_rtcp_sender_pkt_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1848 /* Sender's octet count, 32 bits */
1849 proto_tree_add_uint( tree, hf_rtcp_sender_oct_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
1852 /* Record the time of this packet in the sender's conversation */
1853 if (global_rtcp_show_roundtrip_calculation)
1855 /* Use middle 32 bits of 64-bit time value */
1856 guint32 lsr = ((ts_msw & 0x0000ffff) << 16 | (ts_lsw & 0xffff0000) >> 16);
1858 /* Record the time that we sent this in appropriate conversation */
1859 remember_outgoing_sr(pinfo, lsr);
1862 /* The rest of the packet is equal to the RR packet */
1864 offset = dissect_rtcp_rr( pinfo, tvb, offset, tree, count, packet_length-(offset-sr_offset) );
1867 /* If length remaining, assume profile-specific extension bytes */
1868 if ((offset-sr_offset) < (int)packet_length)
1870 proto_tree_add_item(tree, hf_rtcp_profile_specific_extension, tvb, offset,
1871 packet_length - (offset - sr_offset), FALSE);
1872 offset = sr_offset + packet_length;
1879 /* Look for conversation info and display any setup info found */
1880 void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1882 /* Conversation and current data */
1883 conversation_t *p_conv = NULL;
1884 struct _rtcp_conversation_info *p_conv_data = NULL;
1886 /* Use existing packet data if available */
1887 p_conv_data = p_get_proto_data(pinfo->fd, proto_rtcp);
1891 /* First time, get info from conversation */
1892 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
1894 pinfo->destport, pinfo->srcport, NO_ADDR_B);
1898 /* Look for data in conversation */
1899 struct _rtcp_conversation_info *p_conv_packet_data;
1900 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
1904 /* Save this conversation info into packet info */
1905 p_conv_packet_data = se_alloc(sizeof(struct _rtcp_conversation_info));
1906 if (!p_conv_packet_data)
1910 memcpy(p_conv_packet_data, p_conv_data,
1911 sizeof(struct _rtcp_conversation_info));
1913 p_add_proto_data(pinfo->fd, proto_rtcp, p_conv_packet_data);
1918 /* Create setup info subtree with summary info. */
1919 if (p_conv_data && p_conv_data->setup_method_set)
1921 proto_tree *rtcp_setup_tree;
1922 proto_item *ti = proto_tree_add_string_format(tree, hf_rtcp_setup, tvb, 0, 0,
1924 "Stream setup by %s (frame %u)",
1925 p_conv_data->setup_method,
1926 p_conv_data->setup_frame_number);
1927 PROTO_ITEM_SET_GENERATED(ti);
1928 rtcp_setup_tree = proto_item_add_subtree(ti, ett_rtcp_setup);
1929 if (rtcp_setup_tree)
1931 /* Add details into subtree */
1932 proto_item* item = proto_tree_add_uint(rtcp_setup_tree, hf_rtcp_setup_frame,
1933 tvb, 0, 0, p_conv_data->setup_frame_number);
1934 PROTO_ITEM_SET_GENERATED(item);
1935 item = proto_tree_add_string(rtcp_setup_tree, hf_rtcp_setup_method,
1936 tvb, 0, 0, p_conv_data->setup_method);
1937 PROTO_ITEM_SET_GENERATED(item);
1943 /* Update conversation data to record time that outgoing rr/sr was sent */
1944 static void remember_outgoing_sr(packet_info *pinfo, long lsr)
1946 conversation_t *p_conv = NULL;
1947 struct _rtcp_conversation_info *p_conv_data = NULL;
1948 struct _rtcp_conversation_info *p_packet_data = NULL;
1950 /* This information will be accessed when an incoming packet comes back to
1951 the side that sent this packet, so no use storing in the packet
1952 info. However, do store the fact that we've already set this info
1956 /**************************************************************************/
1957 /* First of all, see if we've already stored this information for this sr */
1959 /* Look first in packet info */
1960 p_packet_data = p_get_proto_data(pinfo->fd, proto_rtcp);
1961 if (p_packet_data && p_packet_data->last_received_set &&
1962 p_packet_data->last_received_frame_number >= pinfo->fd->num)
1964 /* We already did this, OK */
1969 /**************************************************************************/
1970 /* Otherwise, we want to find/create the conversation and update it */
1972 /* First time, get info from conversation.
1973 Even though we think of this as an outgoing packet being sent,
1974 we store the time as being received by the destination. */
1975 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
1977 pinfo->destport, pinfo->srcport, NO_ADDR_B);
1979 /* If the conversation doesn't exist, create it now. */
1982 p_conv = conversation_new(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src, PT_UDP,
1983 pinfo->destport, pinfo->srcport,
1987 /* Give up if can't create it */
1993 /****************************************************/
1994 /* Now find/create conversation data */
1995 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
1998 /* Allocate memory for data */
1999 p_conv_data = se_alloc(sizeof(struct _rtcp_conversation_info));
2002 /* Give up if couldn't allocate space for memory */
2005 memset(p_conv_data, 0, sizeof(struct _rtcp_conversation_info));
2007 /* Add it to conversation. */
2008 conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
2011 /*******************************************************/
2012 /* Update conversation data */
2013 p_conv_data->last_received_set = TRUE;
2014 p_conv_data->last_received_frame_number = pinfo->fd->num;
2015 p_conv_data->last_received_timestamp = pinfo->fd->abs_ts;
2016 p_conv_data->last_received_ts = lsr;
2019 /****************************************************************/
2020 /* Update packet info to record conversation state */
2022 /* Will use/create packet info */
2025 p_packet_data = se_alloc(sizeof(struct _rtcp_conversation_info));
2028 /* Give up if allocation fails */
2031 memset(p_packet_data, 0, sizeof(struct _rtcp_conversation_info));
2033 p_add_proto_data(pinfo->fd, proto_rtcp, p_packet_data);
2036 /* Copy current conversation data into packet info */
2037 p_packet_data->last_received_set = TRUE;
2038 p_packet_data->last_received_frame_number = p_conv_data->last_received_frame_number;
2039 p_packet_data->last_received_timestamp = p_conv_data->last_received_timestamp;
2043 /* Use received sr to work out what the roundtrip delay is
2044 (at least between capture point and the other endpoint involved in
2045 the conversation) */
2046 static void calculate_roundtrip_delay(tvbuff_t *tvb, packet_info *pinfo,
2047 proto_tree *tree, guint32 lsr, guint32 dlsr)
2049 /*****************************************************/
2050 /* This is called dissecting an SR. We need to:
2051 - look in the packet info for stored calculation. If found, use.
2052 - look up the conversation of the sending side to see when the
2053 'last SR' was detected (received)
2054 - calculate the network delay using the that packet time,
2055 this packet time, and dlsr
2056 *****************************************************/
2058 conversation_t *p_conv = NULL;
2059 struct _rtcp_conversation_info *p_conv_data = NULL;
2060 struct _rtcp_conversation_info *p_packet_data = NULL;
2063 /*************************************************/
2064 /* Look for previous result */
2065 p_packet_data = p_get_proto_data(pinfo->fd, proto_rtcp);
2066 if (p_packet_data && p_packet_data->lsr_matched)
2069 add_roundtrip_delay_info(tvb, pinfo, tree,
2070 p_packet_data->calculated_delay_used_frame,
2071 p_packet_data->calculated_delay);
2076 /********************************************************************/
2077 /* Look for captured timestamp of last SR in conversation of sender */
2078 /* of this packet */
2079 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_src, &pinfo->net_dst,
2081 pinfo->srcport, pinfo->destport, NO_ADDR_B);
2087 /* Look for conversation data */
2088 p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
2094 if (p_conv_data->last_received_set)
2096 /* Store result of calculation in packet info */
2099 /* Create packet info if it doesn't exist */
2100 p_packet_data = se_alloc(sizeof(struct _rtcp_conversation_info));
2103 /* Give up if allocation fails */
2107 memset(p_packet_data, 0, sizeof(struct _rtcp_conversation_info));
2109 /* Set as packet info */
2110 p_add_proto_data(pinfo->fd, proto_rtcp, p_packet_data);
2113 /* Don't allow match seemingly calculated from same frame! */
2114 if (pinfo->fd->num == p_conv_data->last_received_frame_number)
2119 /* Any previous report must match the lsr given here */
2120 if (p_conv_data->last_received_ts == lsr)
2122 /* Look at time of since original packet was sent */
2123 gint seconds_between_packets =
2124 pinfo->fd->abs_ts.secs - p_conv_data->last_received_timestamp.secs;
2125 gint nseconds_between_packets =
2126 pinfo->fd->abs_ts.nsecs - p_conv_data->last_received_timestamp.nsecs;
2128 gint total_gap = (seconds_between_packets*1000) +
2129 (nseconds_between_packets / 1000000);
2130 gint dlsr_ms = (int)(((double)dlsr/(double)65536) * 1000.0);
2133 if (dlsr_ms > total_gap)
2139 /* Delay is gap - dlsr */
2140 delay = total_gap - dlsr_ms;
2143 /* Record that the LSR matches */
2144 p_packet_data->lsr_matched = TRUE;
2146 /* No useful calculation can be done if dlsr not set... */
2149 p_packet_data->calculated_delay = delay;
2150 p_packet_data->calculated_delay_used_frame = p_conv_data->last_received_frame_number;
2154 add_roundtrip_delay_info(tvb, pinfo, tree, p_conv_data->last_received_frame_number, delay);
2159 /* Show the calcaulted roundtrip delay info by adding protocol tree items
2160 and appending text to the info column */
2161 static void add_roundtrip_delay_info(tvbuff_t *tvb, packet_info *pinfo,
2162 proto_tree *tree, guint frame, guint delay)
2164 /* 'Last SR' frame used in calculation. Show this even if no delay shown */
2165 proto_item* item = proto_tree_add_uint(tree,
2166 hf_rtcp_last_sr_timestamp_frame,
2168 PROTO_ITEM_SET_GENERATED(item);
2170 /* Don't report on calculated delays below the threshold.
2171 Won't report a delay of 0 (which also indicates no valid
2172 calculated value to report) */
2173 if (delay < global_rtcp_show_roundtrip_calculation_minimum)
2178 /* Calculated delay in ms */
2179 item = proto_tree_add_uint(tree, hf_rtcp_roundtrip_delay, tvb, 0, 0, delay);
2180 PROTO_ITEM_SET_GENERATED(item);
2182 /* Add to expert info */
2183 expert_add_info_format(pinfo, item,
2184 PI_SEQUENCE, PI_NOTE,
2185 "RTCP round-trip delay detected (%u ms)",
2188 /* Report delay in INFO column */
2189 if (check_col(pinfo->cinfo, COL_INFO))
2193 col_append_fstr(pinfo->cinfo, COL_INFO,
2194 " (roundtrip delay <-> %s = %ums, using frame %u)",
2195 address_to_str(&pinfo->net_src), delay, frame);
2203 dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
2205 proto_item *ti = NULL;
2206 proto_tree *rtcp_tree = NULL;
2207 unsigned int temp_byte = 0;
2208 unsigned int padding_set = 0;
2209 unsigned int elem_count = 0;
2210 unsigned int packet_type = 0;
2211 unsigned int offset = 0;
2212 guint16 packet_length = 0;
2213 guint16 total_packet_length = 0;
2214 guint rtcp_subtype = 0;
2215 guint32 app_length = 0;
2217 if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
2218 col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTCP" );
2221 if ( check_col( pinfo->cinfo, COL_INFO) ) {
2222 /* The second octet contains the packet type */
2223 /* switch ( pd[ offset + 1 ] ) { */
2224 switch ( tvb_get_guint8( tvb, 1 ) ) {
2226 col_set_str( pinfo->cinfo, COL_INFO, "Sender Report");
2229 col_set_str( pinfo->cinfo, COL_INFO, "Receiver Report");
2232 col_set_str( pinfo->cinfo, COL_INFO, "Source Description");
2235 col_set_str( pinfo->cinfo, COL_INFO, "Goodbye");
2238 col_set_str( pinfo->cinfo, COL_INFO, "Application");
2241 col_set_str( pinfo->cinfo, COL_INFO, "Extended report");
2244 col_set_str( pinfo->cinfo, COL_INFO, "Full Intra-frame Request (H.261)");
2247 col_set_str( pinfo->cinfo, COL_INFO, "Negative Acknowledgement (H.261)");
2250 col_set_str( pinfo->cinfo, COL_INFO, "Unknown packet type");
2256 * Check if there are at least 4 bytes left in the frame,
2257 * the last 16 bits of those is the length of the current
2258 * RTCP message. The last compound message contains padding,
2259 * that enables us to break from the while loop.
2261 while ( tvb_bytes_exist( tvb, offset, 4) ) {
2263 * First retreive the packet_type
2265 packet_type = tvb_get_guint8( tvb, offset + 1 );
2268 * Check if it's a valid type
2270 if ( ( packet_type < 192 ) || ( packet_type > 207 ) )
2274 * get the packet-length for the complete RTCP packet
2276 packet_length = ( tvb_get_ntohs( tvb, offset + 2 ) + 1 ) * 4;
2277 total_packet_length += packet_length;
2279 ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
2280 proto_item_append_text(ti, " (%s)",
2281 val_to_str(packet_type,
2282 rtcp_packet_type_vals,
2285 rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
2287 /* Conversation setup info */
2288 if (global_rtcp_show_setup_info)
2290 show_setup_info(tvb, pinfo, rtcp_tree);
2294 temp_byte = tvb_get_guint8( tvb, offset );
2296 proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
2297 offset, 1, temp_byte);
2298 padding_set = RTCP_PADDING( temp_byte );
2300 proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
2301 offset, 1, temp_byte );
2302 elem_count = RTCP_COUNT( temp_byte );
2304 switch ( packet_type ) {
2307 /* Receiver report count, 5 bits */
2308 proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, temp_byte );
2310 /* Packet type, 8 bits */
2311 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
2313 /* Packet length in 32 bit words MINUS one, 16 bits */
2314 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
2316 /* Sender Synchronization source, 32 bits */
2317 proto_tree_add_uint( rtcp_tree, hf_rtcp_ssrc_sender, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
2320 if ( packet_type == RTCP_SR )
2321 offset = dissect_rtcp_sr( pinfo, tvb, offset, rtcp_tree, elem_count, packet_length-8 );
2323 offset = dissect_rtcp_rr( pinfo, tvb, offset, rtcp_tree, elem_count, packet_length-8 );
2326 /* Source count, 5 bits */
2327 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
2329 /* Packet type, 8 bits */
2330 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
2332 /* Packet length in 32 bit words MINUS one, 16 bits */
2333 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
2335 dissect_rtcp_sdes( tvb, offset, rtcp_tree, elem_count );
2336 offset += packet_length - 4;
2339 /* Source count, 5 bits */
2340 proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
2342 /* Packet type, 8 bits */
2343 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
2345 /* Packet length in 32 bit words MINUS one, 16 bits */
2346 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
2348 offset = dissect_rtcp_bye( tvb, offset, rtcp_tree, elem_count );
2351 /* Subtype, 5 bits */
2352 rtcp_subtype = elem_count;
2353 proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
2355 /* Packet type, 8 bits */
2356 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
2358 /* Packet length in 32 bit words MINUS one, 16 bits */
2359 app_length = tvb_get_ntohs( tvb, offset ) <<2;
2360 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
2362 offset = dissect_rtcp_app( tvb, pinfo, offset,rtcp_tree, padding_set, packet_length - 4, rtcp_subtype, app_length);
2365 /* Reserved, 5 bits, Ignore */
2367 /* Packet type, 8 bits */
2368 proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
2370 /* Packet length in 32 bit words MINUS one, 16 bits */
2371 proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
2373 offset = dissect_rtcp_xr( tvb, pinfo, offset, rtcp_tree, packet_length - 4 );
2376 offset = dissect_rtcp_fir( tvb, offset, rtcp_tree );
2379 offset = dissect_rtcp_nack( tvb, offset, rtcp_tree );
2383 * To prevent endless loops in case of an unknown message type
2384 * increase offset. Some time the while will end :-)
2390 /* If the padding bit is set, the last octet of the
2391 * packet contains the length of the padding
2392 * We only have to check for this at the end of the LAST RTCP message
2394 if ( padding_set ) {
2395 /* If everything went according to plan offset should now point to the
2396 * first octet of the padding
2398 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_data, tvb, offset, tvb_length_remaining( tvb, offset) - 1, FALSE );
2399 offset += tvb_length_remaining( tvb, offset) - 1;
2400 proto_tree_add_item( rtcp_tree, hf_rtcp_padding_count, tvb, offset, 1, FALSE );
2403 /* offset should be total_packet_length by now... */
2404 if (offset == (int)total_packet_length)
2406 ti = proto_tree_add_boolean_format_value(tree, hf_rtcp_length_check, tvb,
2407 0, 0, TRUE, "OK - %u bytes",
2409 /* Hidden might be less annoying here...? */
2410 PROTO_ITEM_SET_GENERATED(ti);
2414 ti = proto_tree_add_boolean_format_value(tree, hf_rtcp_length_check, tvb,
2416 "Wrong (expected %u bytes, found %d)",
2417 total_packet_length, offset);
2418 PROTO_ITEM_SET_GENERATED(ti);
2420 expert_add_info_format(pinfo, ti,
2421 PI_MALFORMED, PI_WARN,
2422 "Incorrect RTCP packet length information (expected %u bytes, found %d)",
2423 total_packet_length, offset);
2428 proto_register_rtcp(void)
2430 static hf_register_info hf[] =
2439 VALS(rtcp_version_vals),
2459 "Reception report count",
2487 VALS( rtcp_packet_type_vals ),
2501 "32-bit words (-1) in packet", HFILL
2505 &hf_rtcp_ssrc_sender,
2520 "rtcp.timestamp.ntp.msw",
2532 "rtcp.timestamp.ntp.lsw",
2544 "rtcp.timestamp.ntp",
2553 &hf_rtcp_rtp_timestamp,
2556 "rtcp.timestamp.rtp",
2565 &hf_rtcp_sender_pkt_cnt,
2567 "Sender's packet count",
2568 "rtcp.sender.packetcount",
2577 &hf_rtcp_sender_oct_cnt,
2579 "Sender's octet count",
2580 "rtcp.sender.octetcount",
2589 &hf_rtcp_ssrc_source,
2592 "rtcp.ssrc.identifier",
2601 &hf_rtcp_ssrc_fraction,
2604 "rtcp.ssrc.fraction",
2613 &hf_rtcp_ssrc_cum_nr,
2615 "Cumulative number of packets lost",
2625 &hf_rtcp_ssrc_ext_high_seq,
2627 "Extended highest sequence number received",
2628 "rtcp.ssrc.ext_high",
2637 &hf_rtcp_ssrc_high_seq,
2639 "Highest sequence number received",
2640 "rtcp.ssrc.high_seq",
2649 &hf_rtcp_ssrc_high_cycles,
2651 "Sequence number cycles count",
2652 "rtcp.ssrc.high_cycles",
2661 &hf_rtcp_ssrc_jitter,
2663 "Interarrival jitter",
2675 "Last SR timestamp",
2687 "Delay since last SR timestamp",
2699 "SSRC / CSRC identifier",
2700 "rtcp.sdes.ssrc_csrc",
2715 VALS( rtcp_sdes_type_vals ),
2721 &hf_rtcp_sdes_length,
2745 &hf_rtcp_sdes_prefix_len,
2748 "rtcp.sdes.prefix.length",
2757 &hf_rtcp_sdes_prefix_string,
2760 "rtcp.sdes.prefix.string",
2781 &hf_rtcp_name_ascii,
2795 "Application specific data",
2807 "PoC1 Application specific data",
2817 &hf_rtcp_app_poc1_subtype,
2820 "rtcp.app.PoC1.subtype",
2823 VALS(rtcp_app_poc1_floor_cnt_type_vals),
2829 &hf_rtcp_app_poc1_sip_uri,
2832 "rtcp.app.poc1.sip.uri",
2841 &hf_rtcp_app_poc1_disp_name,
2844 "rtcp.app.poc1.disp.name",
2853 &hf_rtcp_app_poc1_priority,
2856 "rtcp.app.poc1.priority",
2859 VALS(rtcp_app_poc1_qsresp_priority_vals),
2865 &hf_rtcp_app_poc1_request_ts,
2867 "Talk Burst Requst Timestamp",
2868 "rtcp.app.poc1.request.ts",
2877 &hf_rtcp_app_poc1_stt,
2879 "Stop talking timer",
2880 "rtcp.app.poc1.stt",
2889 &hf_rtcp_app_poc1_partic,
2891 "Number of participants",
2892 "rtcp.app.poc1.participants",
2901 &hf_rtcp_app_poc1_ssrc_granted,
2903 "SSRC of client granted permission to talk",
2904 "rtcp.app.poc1.ssrc.granted",
2913 &hf_rtcp_app_poc1_last_pkt_seq_no,
2915 "Sequence number of last RTP packet",
2916 "rtcp.app.poc1.last.pkt.seq.no",
2925 &hf_rtcp_app_poc1_ignore_seq_no,
2927 "Ignore sequence number field",
2928 "rtcp.app.poc1.ignore.seq.no",
2937 &hf_rtcp_app_poc1_reason_code1,
2940 "rtcp.app.poc1.reason.code",
2943 VALS(rtcp_app_poc1_reason_code1_vals),
2949 &hf_rtcp_app_poc1_reason1_phrase,
2952 "rtcp.app.poc1.reason.phrase",
2961 &hf_rtcp_app_poc1_reason_code2,
2964 "rtcp.app.poc1.reason.code",
2967 VALS(rtcp_app_poc1_reason_code2_vals),
2973 &hf_rtcp_app_poc1_new_time_request,
2975 "New time client can request (seconds)",
2976 "rtcp.app.poc1.new.time.request",
2981 "Time in seconds client can request for", HFILL
2985 &hf_rtcp_app_poc1_ack_subtype,
2988 "rtcp.app.poc1.ack.subtype",
2991 VALS(rtcp_app_poc1_floor_cnt_type_vals),
2997 &hf_rtcp_app_poc1_ack_reason_code,
3000 "rtcp.app.poc1.ack.reason.code",
3003 VALS(rtcp_app_poc1_reason_code_ack_vals),
3009 &hf_rtcp_app_poc1_qsresp_priority,
3012 "rtcp.app.poc1.qsresp.priority",
3015 VALS(rtcp_app_poc1_qsresp_priority_vals),
3021 &hf_rtcp_app_poc1_qsresp_position,
3023 "Position (number of clients ahead)",
3024 "rtcp.app.poc1.qsresp.position",
3033 &hf_rtcp_app_poc1_conn_content[0],
3035 "Identity of inviting client",
3036 "rtcp.app.poc1.conn.content.a.id",
3045 &hf_rtcp_app_poc1_conn_content[1],
3047 "Nick name of inviting client",
3048 "rtcp.app.poc1.conn.content.a.dn",
3057 &hf_rtcp_app_poc1_conn_content[2],
3060 "rtcp.app.poc1.conn.content.sess.id",
3069 &hf_rtcp_app_poc1_conn_content[3],
3072 "rtcp.app.poc1.conn.content.grp.dn",
3081 &hf_rtcp_app_poc1_conn_content[4],
3084 "rtcp.app.poc1.conn.content.grp.id",
3093 &hf_rtcp_app_poc1_conn_session_type,
3096 "rtcp.app.poc1.conn.session.type",
3099 VALS(rtcp_app_poc1_conn_sess_type_vals),
3105 &hf_rtcp_app_poc1_conn_add_ind_mao,
3107 "Manual answer override",
3108 "rtcp.app.poc1.conn.add.ind.mao",
3117 &hf_rtcp_app_poc1_conn_sdes_items[0],
3119 "Identity of inviting client",
3120 "rtcp.app.poc1.conn.sdes.a.id",
3129 &hf_rtcp_app_poc1_conn_sdes_items[1],
3131 "Nick name of inviting client",
3132 "rtcp.app.poc1.conn.sdes.a.dn",
3141 &hf_rtcp_app_poc1_conn_sdes_items[2],
3144 "rtcp.app.poc1.conn.sdes.sess.id",
3153 &hf_rtcp_app_poc1_conn_sdes_items[3],
3156 "rtcp.app.poc1.conn.sdes.grp.dn",
3165 &hf_rtcp_app_poc1_conn_sdes_items[4],
3168 "rtcp.app.poc1.conn.sdes.grp.id",
3179 "First sequence number",
3191 "Bitmask of following lost packets",
3201 &hf_rtcp_padding_count,
3204 "rtcp.padding.count",
3213 &hf_rtcp_padding_data,
3216 "rtcp.padding.data",
3225 &hf_rtcp_profile_specific_extension,
3227 "Profile-specific extension",
3228 "rtcp.profile-specific-extension",
3233 "Profile-specific extension", HFILL
3245 "Stream setup, method and frame number", HFILL
3249 &hf_rtcp_setup_frame,
3257 "Frame that set up this stream", HFILL
3261 &hf_rtcp_setup_method,
3264 "rtcp.setup-method",
3269 "Method used to set up this stream", HFILL
3273 &hf_rtcp_last_sr_timestamp_frame,
3275 "Frame matching Last SR timestamp",
3281 "Frame matching LSR field (used to calculate roundtrip delay)", HFILL
3285 &hf_rtcp_roundtrip_delay,
3287 "Roundtrip Delay(ms)",
3288 "rtcp.roundtrip-delay",
3293 "Calculated roundtrip delay in ms", HFILL
3297 &hf_rtcp_xr_block_type,
3303 VALS(rtcp_xr_type_vals),
3309 &hf_rtcp_xr_block_specific,
3321 &hf_rtcp_xr_block_length,
3329 "Block Length", HFILL
3333 &hf_rtcp_ssrc_discarded,
3335 "Fraction discarded",
3336 "rtcp.ssrc.discarded",
3341 "Discard Rate", HFILL
3345 &hf_rtcp_xr_voip_metrics_burst_density,
3348 "rtcp.xr.voipmetrics.burstdensity",
3357 &hf_rtcp_xr_voip_metrics_gap_density,
3360 "rtcp.xr.voipmetrics.gapdensity",
3369 &hf_rtcp_xr_voip_metrics_burst_duration,
3371 "Burst Duration(ms)",
3372 "rtcp.xr.voipmetrics.burstduration",
3381 &hf_rtcp_xr_voip_metrics_gap_duration,
3384 "rtcp.xr.voipmetrics.gapduration",
3393 &hf_rtcp_xr_voip_metrics_rtdelay,
3395 "Round Trip Delay(ms)",
3396 "rtcp.xr.voipmetrics.rtdelay",
3405 &hf_rtcp_xr_voip_metrics_esdelay,
3407 "End System Delay(ms)",
3408 "rtcp.xr.voipmetrics.esdelay",
3417 &hf_rtcp_xr_voip_metrics_siglevel,
3420 "rtcp.xr.voipmetrics.signallevel",
3425 "Signal level of 127 indicates this parameter is unavailable", HFILL
3429 &hf_rtcp_xr_voip_metrics_noiselevel,
3432 "rtcp.xr.voipmetrics.noiselevel",
3437 "Noise level of 127 indicates this parameter is unavailable", HFILL
3441 &hf_rtcp_xr_voip_metrics_rerl,
3443 "Residual Echo Return Loss",
3444 "rtcp.xr.voipmetrics.rerl",
3453 &hf_rtcp_xr_voip_metrics_gmin,
3456 "rtcp.xr.voipmetrics.gmin",
3465 &hf_rtcp_xr_voip_metrics_rfactor,
3468 "rtcp.xr.voipmetrics.rfactor",
3473 "R Factor is in the range of 0 to 100; 127 indicates this parameter is unavailable", HFILL
3477 &hf_rtcp_xr_voip_metrics_extrfactor,
3479 "External R Factor",
3480 "rtcp.xr.voipmetrics.extrfactor",
3485 "R Factor is in the range of 0 to 100; 127 indicates this parameter is unavailable", HFILL
3489 &hf_rtcp_xr_voip_metrics_moslq,
3491 "MOS - Listening Quality",
3492 "rtcp.xr.voipmetrics.moslq",
3497 "MOS is in the range of 1 to 5; 127 indicates this parameter is unavailable", HFILL
3501 &hf_rtcp_xr_voip_metrics_moscq,
3503 "MOS - Conversational Quality",
3504 "rtcp.xr.voipmetrics.moscq",
3509 "MOS is in the range of 1 to 5; 127 indicates this parameter is unavailable", HFILL
3513 &hf_rtcp_xr_voip_metrics_plc,
3515 "Packet Loss Conealment Algorithm",
3516 "rtcp.xr.voipmetrics.plc",
3519 VALS(rtcp_xr_plc_algo_vals),
3525 &hf_rtcp_xr_voip_metrics_jbadaptive,
3527 "Adaptive Jitter Buffer Algorithm",
3528 "rtcp.xr.voipmetrics.jba",
3531 VALS(rtcp_xr_jb_adaptive_vals),
3537 &hf_rtcp_xr_voip_metrics_jbrate,
3539 "Jitter Buffer Rate",
3540 "rtcp.xr.voipmetrics.jbrate",
3549 &hf_rtcp_xr_voip_metrics_jbnominal,
3551 "Nominal Jitter Buffer Size",
3552 "rtcp.xr.voipmetrics.jbnominal",
3561 &hf_rtcp_xr_voip_metrics_jbmax,
3563 "Maximum Jitter Buffer Size",
3564 "rtcp.xr.voipmetrics.jbmax",
3573 &hf_rtcp_xr_voip_metrics_jbabsmax,
3575 "Absolute Maximum Jitter Buffer Size",
3576 "rtcp.xr.voipmetrics.jbabsmax",
3585 &hf_rtcp_xr_thinning,
3597 &hf_rtcp_xr_stats_loss_flag,
3600 "rtcp.xr.stats.lrflag",
3609 &hf_rtcp_xr_stats_dup_flag,
3611 "Duplicates Report Flag",
3612 "rtcp.xr.stats.dupflag",
3621 &hf_rtcp_xr_stats_jitter_flag,
3623 "Jitter Report Flag",
3624 "rtcp.xr.stats.jitterflag",
3633 &hf_rtcp_xr_stats_ttl,
3635 "TTL or Hop Limit Flag",
3636 "rtcp.xr.stats.ttl",
3639 VALS(rtcp_xr_ip_ttl_vals),
3647 "End Sequence Number",
3657 &hf_rtcp_xr_beginseq,
3659 "Begin Sequence Number",
3669 &hf_rtcp_xr_stats_lost,
3672 "rtcp.xr.stats.lost",
3681 &hf_rtcp_xr_stats_dups,
3683 "Duplicate Packets",
3684 "rtcp.xr.stats.dups",
3693 &hf_rtcp_xr_stats_minjitter,
3696 "rtcp.xr.stats.minjitter",
3705 &hf_rtcp_xr_stats_maxjitter,
3708 "rtcp.xr.stats.maxjitter",
3717 &hf_rtcp_xr_stats_meanjitter,
3720 "rtcp.xr.stats.meanjitter",
3729 &hf_rtcp_xr_stats_devjitter,
3731 "Standard Deviation of Jitter",
3732 "rtcp.xr.stats.devjitter",
3741 &hf_rtcp_xr_stats_minttl,
3743 "Minimum TTL or Hop Limit",
3744 "rtcp.xr.stats.minttl",
3753 &hf_rtcp_xr_stats_maxttl,
3755 "Maximum TTL or Hop Limit",
3756 "rtcp.xr.stats.maxttl",
3765 &hf_rtcp_xr_stats_meanttl,
3767 "Mean TTL or Hop Limit",
3768 "rtcp.xr.stats.meanttl",
3777 &hf_rtcp_xr_stats_devttl,
3779 "Standard Deviation of TTL",
3780 "rtcp.xr.stats.devttl",
3791 "Last RR timestamp",
3803 "Delay since last RR timestamp",
3813 &hf_rtcp_length_check,
3815 "RTCP frame length check",
3816 "rtcp.length_check",
3821 "RTCP frame length check", HFILL
3826 static gint *ett[] =
3836 &ett_rtcp_roundtrip_delay,
3838 &ett_xr_block_contents,
3841 &ett_poc1_conn_contents
3844 module_t *rtcp_module;
3846 proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol",
3848 proto_register_field_array(proto_rtcp, hf, array_length(hf));
3849 proto_register_subtree_array(ett, array_length(ett));
3851 register_dissector("rtcp", dissect_rtcp, proto_rtcp);
3853 rtcp_module = prefs_register_protocol(proto_rtcp, NULL);
3855 prefs_register_bool_preference(rtcp_module, "show_setup_info",
3856 "Show stream setup information",
3857 "Where available, show which protocol and frame caused "
3858 "this RTCP stream to be created",
3859 &global_rtcp_show_setup_info);
3861 prefs_register_bool_preference(rtcp_module, "heuristic_rtcp",
3862 "Try to decode RTCP outside of conversations ",
3863 "If call control SIP/H.323/RTSP/.. messages are missing in the trace, "
3864 "RTCP isn't decoded without this",
3867 prefs_register_bool_preference(rtcp_module, "show_roundtrip_calculation",
3868 "Show relative roundtrip calculations",
3869 "Try to work out network delay by comparing time between packets "
3870 "as captured and delays as seen by endpoint",
3871 &global_rtcp_show_roundtrip_calculation);
3873 prefs_register_uint_preference(rtcp_module, "roundtrip_min_threshhold",
3874 "Minimum roundtrip calculations to report (ms)",
3875 "Minimum calculated roundtrip delay time in milliseconds that "
3876 "should be reported",
3877 10, &global_rtcp_show_roundtrip_calculation_minimum);
3883 proto_reg_handoff_rtcp(void)
3886 * Register this dissector as one that can be selected by a
3889 rtcp_handle = find_dissector("rtcp");
3890 dissector_add_handle("udp.port", rtcp_handle);
3892 heur_dissector_add( "udp", dissect_rtcp_heur, proto_rtcp);