diff options
author | Robert Jongbloed <robertj@voxlucida.com.au> | 2018-01-23 12:13:43 +0000 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-01-30 05:43:54 +0000 |
commit | 94d7500a7d2589548f210ef0e9cb6d9eba796239 (patch) | |
tree | a6c08f1c5a8290090f6f9f18c1424a6d90694560 /epan/dissectors/packet-sdp.c | |
parent | d328a58fc6ef90db94bb591b949802abbc91a332 (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.c | 66 |
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); |