aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-sdp.c
diff options
context:
space:
mode:
authorRobert Jongbloed <robertj@voxlucida.com.au>2018-01-23 12:13:43 +0000
committerAnders Broman <a.broman58@gmail.com>2018-01-30 05:43:54 +0000
commit94d7500a7d2589548f210ef0e9cb6d9eba796239 (patch)
treea6c08f1c5a8290090f6f9f18c1424a6d90694560 /epan/dissectors/packet-sdp.c
parentd328a58fc6ef90db94bb591b949802abbc91a332 (diff)
SDP/RTP: Support for "bundled" media.
Modern SDP usage (e.g. SIP, WebRTC) can "bundle" multiple RTP media streams on a single port. Thus the RTP dissector has to be able to handle audio and video at the same time, so the gboolean flag in _rtp_info was changed to a bit mask. The SDP parsing was then changed to detect multiple "m=" lines using the same port, and combine their audio/video bit masks, and the rtp_dyn_payload used has all the audio and video payload descriptions. Change-Id: Ifa3c034260f892ed005fe28647d28f3b0b1b05cf Reviewed-on: https://code.wireshark.org/review/25431 Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-sdp.c')
-rw-r--r--epan/dissectors/packet-sdp.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c
index 1a3e2cc1eb..928a5d02c2 100644
--- a/epan/dissectors/packet-sdp.c
+++ b/epan/dissectors/packet-sdp.c
@@ -248,7 +248,8 @@ typedef struct {
*/
typedef struct {
transport_proto_t proto; /**< Protocol, parsed from "m=" line. */
- gboolean is_video; /**< Whether "m=video" */
+ guint32 media_types; /**< Whether "m=video" or others */
+ gboolean bundled; /**< "m=" lines are "bundled", that is, all on same port */
guint16 media_port; /**< Port number, parsed from "m=" line. */
guint16 control_port; /**< Port number, parsed from "a=rtcp" or "a=rtcp-mux" line. */
address conn_addr; /**< The address from the "c=" line (default
@@ -1026,7 +1027,12 @@ dissect_sdp_media(tvbuff_t *tvb, packet_info* pinfo, proto_item *ti,
ENC_UTF_8|ENC_NA, wmem_packet_scope(), &media_type_str);
if (media_desc) {
/* for RTP statistics (supposedly?) */
- media_desc->is_video = strcmp(media_type_str, "video") == 0;
+ if (strcmp(media_type_str, "audio") == 0)
+ media_desc->media_types |= RTP_MEDIA_AUDIO;
+ else if (strcmp(media_type_str, "video") == 0)
+ media_desc->media_types |= RTP_MEDIA_VIDEO;
+ else
+ media_desc->media_types |= RTP_MEDIA_OTHER;
}
DPRINT(("parsed media_type=%s", media_type_str));
@@ -2101,16 +2107,52 @@ complete_descriptions(transport_info_t *transport_info, guint answer_offset)
{
guint media_count = wmem_array_get_count(transport_info->media_descriptions);
media_description_t *media_descs = (media_description_t *)wmem_array_get_raw(transport_info->media_descriptions);
+ media_description_t *bundle_media_desc = NULL;
DPRINT(("complete_descriptions called with answer_offset=%d media_count=%d",
answer_offset, media_count));
+ for (guint i = answer_offset; i < media_count && !bundle_media_desc; i++) {
+ for (guint j = i+1; j < media_count && !bundle_media_desc; j++) {
+ if (media_descs[i].media_port == media_descs[j].media_port)
+ bundle_media_desc = &media_descs[i];
+ }
+ }
+
+ if (bundle_media_desc) {
+ /* We have "bundling" of media, so now combine all the media bit masks
+ and merge the rtp_dyn_payload so that the first media description
+ has all the data for every media desciption. */
+ for (guint i = answer_offset; i < media_count; i++) {
+ media_description_t *media_desc = &media_descs[i];
+
+ if (bundle_media_desc->media_port == media_desc->media_port) {
+ media_desc->bundled = TRUE;
+
+ if (media_desc != bundle_media_desc) {
+ bundle_media_desc->media_types |= media_desc->media_types;
+ for (guint pt = 0; pt < 128; ++pt) {
+ const char * encoding_name;
+ int sample_rate;
+ if (rtp_dyn_payload_get_full(media_desc->media.rtp_dyn_payload,
+ pt, &encoding_name, &sample_rate))
+ rtp_dyn_payload_insert(bundle_media_desc->media.rtp_dyn_payload,
+ pt, encoding_name, sample_rate);
+ }
+ }
+ }
+ }
+ }
+
for (guint i = answer_offset; i < media_count; i++) {
media_description_t *media_desc = &media_descs[i];
if (media_desc->control_port == 0)
media_desc->control_port = media_desc->media_port + 1;
+ if (media_desc->control_port == 0)
+ media_desc->control_port = media_desc->media_port + 1;
+
/* If this is an answer to a previous offer... */
if (answer_offset > 0) {
/* A zero port removes the media stream (RFC 3264, Section 8.2) */
@@ -2169,6 +2211,8 @@ apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int re
establish_frame = request_frame;
}
+ gboolean bundled_media_set = FALSE;
+
for (guint i = 0; i < wmem_array_get_count(transport_info->media_descriptions); i++) {
media_description_t *media_desc =
(media_description_t *)wmem_array_index(transport_info->media_descriptions, i);
@@ -2176,11 +2220,20 @@ apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int re
/* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
if ((media_desc->media_port != 0) &&
+ !media_desc->media.set_rtp &&
(media_desc->proto == SDP_PROTO_RTP ||
media_desc->proto == SDP_PROTO_SRTP) &&
(media_desc->conn_addr.type == AT_IPv4 ||
media_desc->conn_addr.type == AT_IPv6)) {
+ media_desc->media.set_rtp = TRUE;
+
+ if (media_desc->bundled) {
+ if (bundled_media_set)
+ continue;
+ bundled_media_set = TRUE;
+ }
+
if (media_desc->proto == SDP_PROTO_SRTP) {
srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
@@ -2196,7 +2249,7 @@ apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int re
/* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number,
because that's where the RTP flow started, and thus conversation needs to check against */
srtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame,
- media_desc->is_video,
+ media_desc->media_types,
media_desc->media.rtp_dyn_payload, srtp_info);
DENDENT();
} else {
@@ -2204,23 +2257,22 @@ apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int re
i, media_desc->media_port));
DINDENT();
rtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame,
- media_desc->is_video,
+ media_desc->media_types,
media_desc->media.rtp_dyn_payload);
DENDENT();
}
- media_desc->media.set_rtp = TRUE;
/* SPRT might use the same port... */
current_rtp_port = media_desc->media_port;
if (rtcp_handle && media_desc->media_port != media_desc->control_port) {
if (media_desc->proto == SDP_PROTO_SRTP) {
- DPRINT(("calling rtcp_add_address, channel=%d, media_port=%d",
+ DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
i, media_desc->control_port));
DINDENT();
srtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame, srtp_info);
DENDENT();
} else {
- DPRINT(("calling rtcp_add_address, channel=%d, media_port=%d",
+ DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
i, media_desc->control_port));
DINDENT();
rtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame);