Fix Bug 9920 Buildbot crash due to SDP/RTP mismatch

For details see comments in Bug 9920.

The executive summary:
Bug 9920 is a crash caused by a couple of issues:

1) The memory ownership model for the rtp_dyn_payload hashtable is split: SDP
creates the rtp_dyn_payload hashtable, but RTP can free it. Since there isn't
*one* pointer to the hashtable, RTP freeing it means SDP has a dangling
pointer.

2) Either the SDP dissector shouldn't be creating two separate, unique
hashtables for multiple media channels of the same addr:port, or RTP shouldn't
be free'ing the previous one.

Change-Id: I436e67de6882f84aa82dcbdfe60bf313fe4fd99c
Reviewed-on: https://code.wireshark.org/review/918
Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Hadriel Kaplan 2014-04-02 02:07:16 -04:00 committed by Anders Broman
parent df80f3133c
commit 04c05a21e3
8 changed files with 395 additions and 196 deletions

View File

@ -341,8 +341,7 @@ static void update_unicast_addr(unicast_addr_t *req_addr, unicast_addr_t *ack_ad
static void h245_setup_channels(packet_info *pinfo, channel_info_t *upcoming_channel_lcl)
{
gint *key;
GHashTable *rtp_dyn_payload = NULL;
rtp_dyn_payload_t *rtp_dyn_payload = NULL;
struct srtp_info *dummy_srtp_info = NULL;
if (!upcoming_channel_lcl) return;
@ -359,13 +358,8 @@ static void h245_setup_channels(packet_info *pinfo, channel_info_t *upcoming_cha
/* (S)RTP, (S)RTCP */
if (upcoming_channel_lcl->rfc2198 > 0) {
encoding_name_and_rate_t *encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
rtp_dyn_payload = g_hash_table_new(g_int_hash, g_int_equal);
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), "red");
encoding_name_and_rate->sample_rate = 8000;
key = wmem_new(wmem_file_scope(), gint);
*key = upcoming_channel_lcl->rfc2198;
g_hash_table_insert(rtp_dyn_payload, key, encoding_name_and_rate);
rtp_dyn_payload = rtp_dyn_payload_new();
rtp_dyn_payload_insert(rtp_dyn_payload, upcoming_channel_lcl->rfc2198, "red", 8000);
}
if (upcoming_channel_lcl->srtp_flag) {

View File

@ -6905,11 +6905,9 @@ elem_a2p_bearer_format(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
gboolean first_assigned_found;
gboolean rtp_dyn_payload_used;
guint8 rtp_payload_type;
GHashTable *rtp_dyn_payload;
gint *key;
encoding_name_and_rate_t *encoding_name_and_rate;
rtp_dyn_payload_t *rtp_dyn_payload;
rtp_dyn_payload = g_hash_table_new(g_int_hash, g_int_equal);
rtp_dyn_payload = rtp_dyn_payload_new();
rtp_dyn_payload_used = FALSE;
first_assigned_found = FALSE;
@ -7066,14 +7064,7 @@ elem_a2p_bearer_format(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
if (format_assigned &&
(first_assigned_found == FALSE))
{
key = wmem_new(wmem_file_scope(), gint);
*key = rtp_payload_type;
encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), mime_type);
encoding_name_and_rate->sample_rate = sample_rate;
g_hash_table_insert(rtp_dyn_payload, key, encoding_name_and_rate);
rtp_dyn_payload_insert(rtp_dyn_payload, rtp_payload_type, mime_type, sample_rate);
rtp_dyn_payload_used = TRUE;
first_assigned_found = TRUE;
@ -7083,14 +7074,7 @@ elem_a2p_bearer_format(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
if (in_band_format_assigned)
{
key = (gint *) wmem_alloc(wmem_file_scope(), sizeof(gint));
*key = rtp_payload_type;
encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), "telephone-event");
encoding_name_and_rate->sample_rate = sample_rate;
g_hash_table_insert(rtp_dyn_payload, key, encoding_name_and_rate);
rtp_dyn_payload_insert(rtp_dyn_payload, rtp_payload_type, "telephone-event", sample_rate);
rtp_dyn_payload_used = TRUE;
}
@ -7099,7 +7083,7 @@ elem_a2p_bearer_format(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
if (rtp_dyn_payload_used == FALSE)
{
rtp_free_hash_dyn_payload(rtp_dyn_payload);
rtp_dyn_payload_free(rtp_dyn_payload);
}
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);

View File

@ -285,9 +285,7 @@ dissect_applemidi_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
guint16 command;
conversation_t *p_conv;
/*struct _rtp_conversation_info *p_conv_data = NULL;*/
encoding_name_and_rate_t *encoding_name_and_rate = NULL;
GHashTable *rtp_dyn_payload = NULL;
gint *key;
rtp_dyn_payload_t *rtp_dyn_payload = NULL;
if ( tvb_length( tvb ) < 4)
return FALSE; /* not enough bytes to check */
@ -299,13 +297,8 @@ dissect_applemidi_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
/* set dynamic payload-type 97 which is used by Apple for their RTP-MIDI implementation for this
address/port-tuple to cause RTP-dissector to call the RTP-MIDI-dissector for payload-decoding */
encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
rtp_dyn_payload = g_hash_table_new( g_int_hash, g_int_equal );
encoding_name_and_rate->encoding_name = wmem_strdup( wmem_file_scope(), "rtp-midi" );
encoding_name_and_rate->sample_rate = 10000;
key = wmem_new(wmem_file_scope(), gint);
*key = 97;
g_hash_table_insert( rtp_dyn_payload, key, encoding_name_and_rate );
rtp_dyn_payload = rtp_dyn_payload_new();
rtp_dyn_payload_insert(rtp_dyn_payload, 97, "rtp-midi", 10000);
rtp_add_address( pinfo, &pinfo->src, pinfo->srcport, 0, APPLEMIDI_DISSECTOR_SHORTNAME,
pinfo->fd->num, FALSE, rtp_dyn_payload);

View File

@ -472,8 +472,7 @@ static void update_unicast_addr(unicast_addr_t *req_addr, unicast_addr_t *ack_ad
static void h245_setup_channels(packet_info *pinfo, channel_info_t *upcoming_channel_lcl)
{
gint *key;
GHashTable *rtp_dyn_payload = NULL;
rtp_dyn_payload_t *rtp_dyn_payload = NULL;
struct srtp_info *dummy_srtp_info = NULL;
if (!upcoming_channel_lcl) return;
@ -490,13 +489,8 @@ static void h245_setup_channels(packet_info *pinfo, channel_info_t *upcoming_cha
/* (S)RTP, (S)RTCP */
if (upcoming_channel_lcl->rfc2198 > 0) {
encoding_name_and_rate_t *encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
rtp_dyn_payload = g_hash_table_new(g_int_hash, g_int_equal);
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), "red");
encoding_name_and_rate->sample_rate = 8000;
key = wmem_new(wmem_file_scope(), gint);
*key = upcoming_channel_lcl->rfc2198;
g_hash_table_insert(rtp_dyn_payload, key, encoding_name_and_rate);
rtp_dyn_payload = rtp_dyn_payload_new();
rtp_dyn_payload_insert(rtp_dyn_payload, upcoming_channel_lcl->rfc2198, "red", 8000);
}
if (upcoming_channel_lcl->srtp_flag) {
@ -1926,7 +1920,7 @@ static int hf_h245_encrypted = -1; /* OCTET_STRING */
static int hf_h245_encryptedAlphanumeric = -1; /* EncryptedAlphanumeric */
/*--- End of included file: packet-h245-hf.c ---*/
#line 392 "../../asn1/h245/packet-h245-template.c"
#line 386 "../../asn1/h245/packet-h245-template.c"
/* Initialize the subtree pointers */
static int ett_h245 = -1;
@ -2427,7 +2421,7 @@ static gint ett_h245_FlowControlIndication = -1;
static gint ett_h245_MobileMultilinkReconfigurationIndication = -1;
/*--- End of included file: packet-h245-ett.c ---*/
#line 397 "../../asn1/h245/packet-h245-template.c"
#line 391 "../../asn1/h245/packet-h245-template.c"
/* Forward declarations */
static int dissect_h245_MultimediaSystemControlMessage(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
@ -14494,7 +14488,7 @@ static void dissect_OpenLogicalChannel_PDU(tvbuff_t *tvb _U_, packet_info *pinfo
/*--- End of included file: packet-h245-fn.c ---*/
#line 406 "../../asn1/h245/packet-h245-template.c"
#line 400 "../../asn1/h245/packet-h245-template.c"
static void
dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
@ -20188,7 +20182,7 @@ void proto_register_h245(void) {
NULL, HFILL }},
/*--- End of included file: packet-h245-hfarr.c ---*/
#line 487 "../../asn1/h245/packet-h245-template.c"
#line 481 "../../asn1/h245/packet-h245-template.c"
};
/* List of subtrees */
@ -20691,7 +20685,7 @@ void proto_register_h245(void) {
&ett_h245_MobileMultilinkReconfigurationIndication,
/*--- End of included file: packet-h245-ettarr.c ---*/
#line 494 "../../asn1/h245/packet-h245-template.c"
#line 488 "../../asn1/h245/packet-h245-template.c"
};
module_t *h245_module;

View File

@ -102,6 +102,17 @@ typedef struct _rtp_private_conv_info {
wmem_tree_t *multisegment_pdus;
} rtp_private_conv_info;
typedef struct {
char *encoding_name;
int sample_rate;
} encoding_name_and_rate_t;
struct _rtp_dyn_payload_t
{
GHashTable *table;
size_t ref_count;
};
static reassembly_table rtp_reassembly_table;
static int hf_rtp_fragments = -1;
@ -809,11 +820,11 @@ static const value_string srtp_auth_alg_vals[] =
#ifdef DEBUG_CONVERSATION
/* Called for each entry in the rtp_dyn_payload hash table. */
static void
rtp_dyn_payload_table_foreach_func (gpointer key, gpointer value, gpointer user_data _U_) {
gint* pt = (gint*) key;
rtp_dyn_payload_table_foreach_func(gpointer key, gpointer value, gpointer user_data _U_) {
guint pt = GPOINTER_TO_UINT(key);
encoding_name_and_rate_t *encoding = (encoding_name_and_rate_t*) value;
DPRINT2(("pt=%d",*pt));
DPRINT2(("pt=%d",pt));
if (encoding) {
DPRINT2(("encoding_name=%s",
encoding->encoding_name ? encoding->encoding_name : "NULL"));
@ -822,19 +833,27 @@ rtp_dyn_payload_table_foreach_func (gpointer key, gpointer value, gpointer user_
DPRINT2(("encoding=NULL"));
}
}
static void rtp_dump_dyn_payload(GHashTable *rtp_dyn_payload) {
void
rtp_dump_dyn_payload(rtp_dyn_payload_t *rtp_dyn_payload) {
DPRINT2(("rtp_dyn_payload hash table contents:"));
DINDENT();
if (!rtp_dyn_payload) {
DPRINT2(("null rtp_dyn_payload"));
DENDENT();
return;
}
if (g_hash_table_size(rtp_dyn_payload) == 0) {
DPRINT2(("rtp_dyn_payload is empty"));
} else {
g_hash_table_foreach(rtp_dyn_payload, rtp_dyn_payload_table_foreach_func, NULL);
}
if (!rtp_dyn_payload) {
DPRINT2(("null pointer to rtp_dyn_payload"));
DENDENT();
return;
}
DPRINT2(("ref_count=%" G_GSIZE_FORMAT, rtp_dyn_payload->ref_count));
if (!rtp_dyn_payload->table) {
DPRINT2(("null rtp_dyn_payload table"));
DENDENT();
return;
}
if (g_hash_table_size(rtp_dyn_payload->table) == 0) {
DPRINT2(("rtp_dyn_payload has no entries"));
} else {
g_hash_table_foreach(rtp_dyn_payload->table, rtp_dyn_payload_table_foreach_func, NULL);
}
DENDENT();
}
#endif /* DEBUG_CONVERSATION */
@ -847,14 +866,225 @@ rtp_fragment_init(void)
&addresses_reassembly_table_functions);
}
void
rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload)
/* A single hash table to hold pointers to all the rtp_dyn_payload_t's we create/destroy.
This is necessary because we need to g_hash_table_destroy() them, either individually or
all at once at the end of the wmem file scope. Since rtp_dyn_payload_free() removes them
individually, we need to remove those then; and when the file scope is over, we have a
single registered callback walk this GHashTable and destroy each member as well as this
GHashTable.
*/
static GHashTable *rtp_dyn_payloads = NULL;
/* the following is the GDestroyNotify function used when the individual rtp_dyn_payload_t
GHashTables are destroyed */
static void
rtp_dyn_payload_value_destroy(gpointer data)
{
if (rtp_dyn_payload == NULL) return;
g_hash_table_destroy(rtp_dyn_payload);
rtp_dyn_payload = NULL;
encoding_name_and_rate_t *encoding_name_and_rate_pt = (encoding_name_and_rate_t*) data;
wmem_free(wmem_file_scope(), encoding_name_and_rate_pt->encoding_name);
wmem_free(wmem_file_scope(), encoding_name_and_rate_pt);
}
/* this gets called by wmem_rtp_dyn_payload_destroy_cb */
static gboolean
rtp_dyn_payloads_table_steal_func(gpointer key _U_, gpointer value, gpointer user_data _U_)
{
rtp_dyn_payload_t *rtp_dyn_payload = (rtp_dyn_payload_t *)value;
#ifdef DEBUG_CONVERSATION
DPRINT(("about to steal_all and destroy the following:"));
DINDENT();
rtp_dump_dyn_payload(rtp_dyn_payload);
DENDENT();
#endif
if (rtp_dyn_payload->ref_count == 0) {
/* this shouldn't happen */
g_error("rtp_dyn_payload cannot be free'd because it should already have been!\n");
}
else if (rtp_dyn_payload->table) {
/* each member was created with a wmem file scope, so there's no point in calling the
destroy functions for the GHashTable entries, so we steal them instead */
g_hash_table_steal_all(rtp_dyn_payload->table);
g_hash_table_destroy(rtp_dyn_payload->table);
}
return TRUE;
}
/* the following is used as the wmem callback to destroy *all* alive rtp_dyn_payload_t's,
which are pointed to by the single rtp_dyn_payloads GHashTable above.
*/
static gboolean
wmem_rtp_dyn_payload_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
void *user_data _U_)
{
g_assert(rtp_dyn_payloads);
DPRINT(("destroying %u remaining rtp_dyn_payload_t's", g_hash_table_size(rtp_dyn_payloads)));
/* each member was created with a wmem file scope, so there's no point in calling the
destroy functions for the GHashTable entries, so we steal them instead */
g_hash_table_foreach_steal(rtp_dyn_payloads, rtp_dyn_payloads_table_steal_func, NULL);
g_hash_table_destroy(rtp_dyn_payloads);
rtp_dyn_payloads = NULL;
/* remove this callback? */
return FALSE;
}
/* the following initializes the single GHashTable - this is invoked as an init_routine,
but those are called both at init and cleanup times, and the cleanup time is before
wmem scope is exited, so we ignore this if rtp_dyn_payloads is not NULL.
*/
static void
rtp_dyn_payloads_init(void)
{
if (rtp_dyn_payloads == NULL) {
rtp_dyn_payloads = g_hash_table_new(NULL, NULL);
wmem_register_callback(wmem_file_scope(), wmem_rtp_dyn_payload_destroy_cb, NULL);
}
}
/* creates a new hashtable and sets ref_count to 1, returning the newly created object */
rtp_dyn_payload_t* rtp_dyn_payload_new(void)
{
/* create the new entry */
rtp_dyn_payload_t * rtp_dyn_payload = wmem_new(wmem_file_scope(), rtp_dyn_payload_t);
rtp_dyn_payload->table = g_hash_table_new_full(NULL, NULL, NULL, rtp_dyn_payload_value_destroy);
rtp_dyn_payload->ref_count = 1;
/* now put it in our single rtp_dyn_payloads GHashTable */
g_hash_table_insert(rtp_dyn_payloads, rtp_dyn_payload, rtp_dyn_payload);
return rtp_dyn_payload;
}
static rtp_dyn_payload_t*
rtp_dyn_payload_ref(rtp_dyn_payload_t *rtp_dyn_payload)
{
if (rtp_dyn_payload) {
rtp_dyn_payload->ref_count++;
}
return rtp_dyn_payload;
}
/* Inserts the given payload type key, for the encoding name and sample rate, into the hash table.
This makes copies of the encoding name, scoped to the life of the capture file or sooner if
rtp_dyn_payload_free is called. */
void
rtp_dyn_payload_insert(rtp_dyn_payload_t *rtp_dyn_payload,
const guint8 pt,
const gchar* encoding_name,
const int sample_rate)
{
if (rtp_dyn_payload && rtp_dyn_payload->table) {
encoding_name_and_rate_t *encoding_name_and_rate_pt =
wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
encoding_name_and_rate_pt->encoding_name = wmem_strdup(wmem_file_scope(), encoding_name);
encoding_name_and_rate_pt->sample_rate = sample_rate;
g_hash_table_insert(rtp_dyn_payload->table, GUINT_TO_POINTER(pt), encoding_name_and_rate_pt);
}
}
/* Replaces the given payload type key in the hash table, with the encoding name and sample rate.
This makes copies of the encoding name, scoped to the life of the capture file or sooner if
rtp_dyn_payload_free is called. */
void
rtp_dyn_payload_replace(rtp_dyn_payload_t *rtp_dyn_payload,
const guint8 pt,
const gchar* encoding_name,
const int sample_rate)
{
if (rtp_dyn_payload && rtp_dyn_payload->table) {
encoding_name_and_rate_t *encoding_name_and_rate_pt =
wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
encoding_name_and_rate_pt->encoding_name = wmem_strdup(wmem_file_scope(), encoding_name);
encoding_name_and_rate_pt->sample_rate = sample_rate;
g_hash_table_replace(rtp_dyn_payload->table, GUINT_TO_POINTER(pt), encoding_name_and_rate_pt);
}
}
/* removes the given payload type */
gboolean
rtp_dyn_payload_remove(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt)
{
return (rtp_dyn_payload && rtp_dyn_payload->table &&
g_hash_table_remove(rtp_dyn_payload->table, GUINT_TO_POINTER(pt)));
}
/* retrieves the encoding name for the given payload type */
const gchar*
rtp_dyn_payload_get_name(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt)
{
encoding_name_and_rate_t *encoding_name_and_rate_pt;
if (!rtp_dyn_payload || !rtp_dyn_payload->table) return NULL;
encoding_name_and_rate_pt = (encoding_name_and_rate_t*)g_hash_table_lookup(rtp_dyn_payload->table,
GUINT_TO_POINTER(pt));
return (encoding_name_and_rate_pt ? encoding_name_and_rate_pt->encoding_name : NULL);
}
/* retrieves the encoding name and sample rate for the given payload type, returning TRUE if
successful, else FALSE. The encoding string pointed to is only valid until the entry is
replaced, removed, or the hash table is destroyed, so duplicate it if you need it long. */
gboolean
rtp_dyn_payload_get_full(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt,
const gchar **encoding_name, int *sample_rate)
{
encoding_name_and_rate_t *encoding_name_and_rate_pt;
*encoding_name = NULL;
*sample_rate = 0;
if (!rtp_dyn_payload || !rtp_dyn_payload->table) return FALSE;
encoding_name_and_rate_pt = (encoding_name_and_rate_t*)g_hash_table_lookup(rtp_dyn_payload->table,
GUINT_TO_POINTER(pt));
if (encoding_name_and_rate_pt) {
*encoding_name = encoding_name_and_rate_pt->encoding_name;
*sample_rate = encoding_name_and_rate_pt->sample_rate;
}
return (encoding_name_and_rate_pt != NULL);
}
/* Free's and destroys the dyn_payload hash table; internally this decrements the ref_count
and only free's it if the ref_count == 0. */
void
rtp_dyn_payload_free(rtp_dyn_payload_t *rtp_dyn_payload)
{
if (!rtp_dyn_payload) return;
if (rtp_dyn_payload->ref_count > 0)
--(rtp_dyn_payload->ref_count);
if (rtp_dyn_payload->ref_count == 0) {
#ifdef DEBUG_CONVERSATION
DPRINT(("free'ing the following rtp_dyn_payload:"));
DINDENT();
rtp_dump_dyn_payload(rtp_dyn_payload);
DENDENT();
#endif
/* remove it from the single rtp_dyn_payloads GHashTable */
g_assert(rtp_dyn_payloads);
if (!g_hash_table_remove(rtp_dyn_payloads, rtp_dyn_payload)) {
g_error("rtp_dyn_payload not found in rtp_dyn_payloads table to remove!");
}
/* destroy the table GHashTable in it - this automatically deletes the
members too, because we used destroy function callbacks */
if (rtp_dyn_payload->table)
g_hash_table_destroy(rtp_dyn_payload->table);
/* free the object itself */
wmem_free(wmem_file_scope(), rtp_dyn_payload);
}
}
void
bluetooth_add_address(packet_info *pinfo, address *addr,
@ -928,7 +1158,7 @@ bluetooth_add_address(packet_info *pinfo, address *addr,
* Update the conversation data.
*/
/* Free the hash if already exists */
rtp_free_hash_dyn_payload(p_conv_data->rtp_dyn_payload);
rtp_dyn_payload_free(p_conv_data->rtp_dyn_payload);
g_strlcpy(p_conv_data->method, setup_method, MAX_RTP_SETUP_METHOD_SIZE+1);
p_conv_data->frame_number = setup_frame_number;
@ -941,7 +1171,7 @@ bluetooth_add_address(packet_info *pinfo, address *addr,
void
srtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
const gchar *setup_method, guint32 setup_frame_number,
gboolean is_video _U_, GHashTable *rtp_dyn_payload,
gboolean is_video _U_, rtp_dyn_payload_t *rtp_dyn_payload,
struct srtp_info *srtp_info)
{
address null_addr;
@ -1022,13 +1252,16 @@ srtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
* Update the conversation data.
*/
/* Free the hash if a different one already exists */
if (p_conv_data->rtp_dyn_payload != rtp_dyn_payload)
rtp_free_hash_dyn_payload(p_conv_data->rtp_dyn_payload);
if (p_conv_data->rtp_dyn_payload != rtp_dyn_payload) {
rtp_dyn_payload_free(p_conv_data->rtp_dyn_payload);
p_conv_data->rtp_dyn_payload = rtp_dyn_payload_ref(rtp_dyn_payload);
} else {
DPRINT(("passed-in rtp_dyn_payload is the same as in the conversation"));
}
g_strlcpy(p_conv_data->method, setup_method, MAX_RTP_SETUP_METHOD_SIZE+1);
p_conv_data->frame_number = setup_frame_number;
p_conv_data->is_video = is_video;
p_conv_data->rtp_dyn_payload = rtp_dyn_payload;
p_conv_data->srtp_info = srtp_info;
p_conv_data->bta2dp_info = NULL;
p_conv_data->btvdp_info = NULL;
@ -1038,7 +1271,7 @@ srtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
void
rtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
const gchar *setup_method, guint32 setup_frame_number,
gboolean is_video , GHashTable *rtp_dyn_payload)
gboolean is_video , rtp_dyn_payload_t *rtp_dyn_payload)
{
srtp_add_address(pinfo, addr, port, other_port, setup_method, setup_frame_number, is_video, rtp_dyn_payload, NULL);
}
@ -1163,13 +1396,8 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
payload_type >= PT_UNDF_96 && payload_type <= PT_UNDF_127) {
/* if the payload type is dynamic, we check if the conv is set and we look for the pt definition */
if (p_conv_data && p_conv_data->rtp_dyn_payload) {
gchar *payload_type_str = NULL;
encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
encoding_name_and_rate_pt = (encoding_name_and_rate_t *)g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &payload_type);
if (encoding_name_and_rate_pt) {
payload_type_str = encoding_name_and_rate_pt->encoding_name;
}
if (payload_type_str){
const gchar *payload_type_str = rtp_dyn_payload_get_name(p_conv_data->rtp_dyn_payload, payload_type);
if (payload_type_str) {
found_match = dissector_try_string(rtp_dyn_pt_dissector_table,
payload_type_str, newtvb, pinfo, tree, NULL);
/* If payload type string set from conversation and
@ -1452,7 +1680,7 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
rfc2198_hdr *hdr_last, *hdr_new;
rfc2198_hdr *hdr_chain = NULL;
struct _rtp_conversation_info *p_conv_data= NULL;
gchar *payload_type_str;
const gchar *payload_type_str;
/* Retrieve RTPs idea of a converation */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rtp, 0);
@ -1477,11 +1705,7 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* if it is dynamic payload, let use the conv data to see if it is defined */
if ((hdr_new->pt > 95) && (hdr_new->pt < 128)) {
if (p_conv_data && p_conv_data->rtp_dyn_payload){
encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
encoding_name_and_rate_pt = (encoding_name_and_rate_t *)g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &hdr_new->pt);
if (encoding_name_and_rate_pt) {
payload_type_str = encoding_name_and_rate_pt->encoding_name;
}
payload_type_str = rtp_dyn_payload_get_name(p_conv_data->rtp_dyn_payload, hdr_new->pt);
}
}
/* Add a subtree for this header and add items */
@ -1645,7 +1869,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
unsigned int csrc_count;
gboolean marker_set;
unsigned int payload_type;
gchar *payload_type_str = NULL;
const gchar *payload_type_str = NULL;
gboolean is_srtp = FALSE;
unsigned int i = 0;
unsigned int hdr_extension_len= 0;
@ -1826,24 +2050,20 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
/* if it is dynamic payload, let use the conv data to see if it is defined */
if ( (payload_type>95) && (payload_type<128) ) {
if (p_conv_data && p_conv_data->rtp_dyn_payload){
encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
if (p_conv_data && p_conv_data->rtp_dyn_payload) {
int sample_rate = 0;
#ifdef DEBUG_CONVERSATION
rtp_dump_dyn_payload(p_conv_data->rtp_dyn_payload);
#endif
DPRINT(("looking up conversation data for dyn_pt=%d", payload_type));
encoding_name_and_rate_pt = (encoding_name_and_rate_t *)g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &payload_type);
DPRINT(("did %sfind conversation data for dyn_pt=%d",
encoding_name_and_rate_pt?"":"not ", payload_type));
if (encoding_name_and_rate_pt) {
if (rtp_dyn_payload_get_full(p_conv_data->rtp_dyn_payload, payload_type,
&payload_type_str, &sample_rate)) {
DPRINT(("found conversation data for dyn_pt=%d, enc_name=%s",
payload_type,encoding_name_and_rate_pt->encoding_name));
rtp_info->info_payload_type_str = payload_type_str = encoding_name_and_rate_pt->encoding_name;
rtp_info->info_payload_rate = encoding_name_and_rate_pt->sample_rate;
payload_type, payload_type_str));
rtp_info->info_payload_type_str = payload_type_str;
rtp_info->info_payload_rate = sample_rate;
}
}
}
@ -2316,15 +2536,18 @@ get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info)
guint32 seqno;
/* Save this conversation info into packet info */
/* XXX: why is this file pool not pinfo->pool? */
p_conv_packet_data = wmem_new(wmem_file_scope(), struct _rtp_conversation_info);
g_strlcpy(p_conv_packet_data->method, p_conv_data->method, MAX_RTP_SETUP_METHOD_SIZE+1);
p_conv_packet_data->frame_number = p_conv_data->frame_number;
p_conv_packet_data->is_video = p_conv_data->is_video;
/* do not increment ref count for the rtp_dyn_payload */
p_conv_packet_data->rtp_dyn_payload = p_conv_data->rtp_dyn_payload;
p_conv_packet_data->rtp_conv_info = p_conv_data->rtp_conv_info;
p_conv_packet_data->srtp_info = p_conv_data->srtp_info;
p_conv_packet_data->bta2dp_info = p_conv_data->bta2dp_info;
p_conv_packet_data->btvdp_info = p_conv_data->btvdp_info;
/* XXX: why is this file pool not pinfo->pool? */
p_add_proto_data(wmem_file_scope(), pinfo, proto_rtp, 0, p_conv_packet_data);
/* calculate extended sequence number */
@ -3338,6 +3561,7 @@ proto_register_rtp(void)
&rtp_rfc2198_pt);
register_init_routine(rtp_fragment_init);
register_init_routine(rtp_dyn_payloads_init);
}
void

View File

@ -100,6 +100,72 @@ struct srtp_info
#endif
};
/* an opaque object holding the hash table - use accessor functions to create/destroy/find */
typedef struct _rtp_dyn_payload_t rtp_dyn_payload_t;
/* RTP dynamic payload handling - use the following to create, insert, lookup, and free the
dynamic payload information. Internally, RTP creates the GHashTable with a wmem file scope
and increments the ref_count when it saves the info to conversations later. The calling
dissector (SDP, H.245, etc.) uses these functions as an interface. If the calling dissector
is done with the rtp_dyn_payload_t* for good, it should call rtp_dyn_payload_free() which
will decrement the ref_count and free's it if the ref_count is 0. In the worst case, it
will get free'd when the wmem file scope is over.
This was changed because there were too many bugs with SDP's handling of memory ownership
of the GHashTable, with RTP freeing things SDP didn't think were free'ed. And also because
the GHashTables never got free'd in many cases by several dissectors.
*/
/* creates a new hashtable and sets ref_count to 1, returning the newly created object */
WS_DLL_PUBLIC
rtp_dyn_payload_t* rtp_dyn_payload_new(void);
/* Inserts the given payload type key, for the encoding name and sample rate, into the hash table.
This makes copies of the encoding name, scoped to the life of the capture file or sooner if
rtp_dyn_payload_free is called. */
WS_DLL_PUBLIC
void rtp_dyn_payload_insert(rtp_dyn_payload_t *rtp_dyn_payload,
const guint8 pt,
const gchar* encoding_name,
const int sample_rate);
/* Replaces the given payload type key in the hash table, with the encoding name and sample rate.
This makes copies of the encoding name, scoped to the life of the capture file or sooner if
rtp_dyn_payload_free is called. The replaced encoding name is free'd immediately. */
WS_DLL_PUBLIC
void rtp_dyn_payload_replace(rtp_dyn_payload_t *rtp_dyn_payload,
const guint8 pt,
const gchar* encoding_name,
const int sample_rate);
/* removes the given payload type */
WS_DLL_PUBLIC
gboolean rtp_dyn_payload_remove(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt);
/* retrieves the encoding name for the given payload type; the string returned is only valid
until the entry is replaced, removed, or the hash table is destroyed, so duplicate it if
you need it long. */
WS_DLL_PUBLIC
const gchar* rtp_dyn_payload_get_name(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt);
/* retrieves the encoding name and sample rate for the given payload type, returning TRUE if
successful, else FALSE. The encoding string pointed to is only valid until the entry is
replaced, removed, or the hash table is destroyed, so duplicate it if you need it long. */
WS_DLL_PUBLIC
gboolean rtp_dyn_payload_get_full(rtp_dyn_payload_t *rtp_dyn_payload, const guint8 pt,
const gchar **encoding_name, int *sample_rate);
/* Free's and destroys the dyn_payload hash table; internally this decrements the ref_count
and only free's it if the ref_count == 0. */
WS_DLL_PUBLIC
void rtp_dyn_payload_free(rtp_dyn_payload_t *rtp_dyn_payload);
#ifdef DEBUG_CONVERSATION
/* used for printing out debugging info, if DEBUG_CONVERSATION is defined */
void rtp_dump_dyn_payload(rtp_dyn_payload_t *rtp_dyn_payload);
#endif
/* Info to save in RTP conversation / packet-info */
#define MAX_RTP_SETUP_METHOD_SIZE 7
struct _rtp_conversation_info
@ -107,7 +173,7 @@ struct _rtp_conversation_info
gchar method[MAX_RTP_SETUP_METHOD_SIZE + 1];
guint32 frame_number; /* the frame where this conversation is started */
gboolean is_video;
GHashTable *rtp_dyn_payload; /* a hash table with the dynamic RTP payload */
rtp_dyn_payload_t *rtp_dyn_payload; /* the dynamic RTP payload info - see comments above */
guint32 extended_seqno; /* the sequence number, extended to a 32-bit
* int to guarantee it increasing monotonically
@ -121,11 +187,6 @@ struct _rtp_conversation_info
btvdp_codec_info_t *btvdp_info;
};
typedef struct {
char *encoding_name;
int sample_rate;
} encoding_name_and_rate_t;
/* Add an RTP conversation with the given details */
WS_DLL_PUBLIC
void rtp_add_address(packet_info *pinfo,
@ -134,7 +195,7 @@ void rtp_add_address(packet_info *pinfo,
const gchar *setup_method,
guint32 setup_frame_number,
gboolean is_video,
GHashTable *rtp_dyn_payload);
rtp_dyn_payload_t *rtp_dyn_payload);
/* Add an SRTP conversation with the given details */
WS_DLL_PUBLIC
@ -144,7 +205,7 @@ void srtp_add_address(packet_info *pinfo,
const gchar *setup_method,
guint32 setup_frame_number,
gboolean is_video,
GHashTable *rtp_dyn_payload,
rtp_dyn_payload_t *rtp_dyn_payload,
struct srtp_info *srtp_info);
/* Add an Bluetooth conversation with the given details */
@ -152,8 +213,3 @@ void
bluetooth_add_address(packet_info *pinfo, address *addr,
const gchar *setup_method, guint32 setup_frame_number,
gboolean is_video, void *data);
/* Free and destroy the dyn_payload hash table */
WS_DLL_PUBLIC
void rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload);

View File

@ -41,6 +41,11 @@
#include <epan/addr_resolv.h>
#include "packet-sdp.h"
/* un-comment the following as well as this line in conversation.c, to enable debug printing */
/* #define DEBUG_CONVERSATION */
#include "conversation_debug.h"
#include "packet-rtp.h"
#include "packet-rtcp.h"
@ -52,10 +57,6 @@
#include "packet-h264.h"
#include "packet-mp4ves.h"
/* un-comment the following as well as this line in conversation.c, to enable debug printing */
/* #define DEBUG_CONVERSATION */
#include "conversation_debug.h"
void proto_register_sdp(void);
void proto_reg_handoff_sdp(void);
@ -208,7 +209,7 @@ static expert_field ei_sdp_invalid_line = EI_INIT;
typedef struct {
gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
gint8 pt_count;
GHashTable *rtp_dyn_payload;
rtp_dyn_payload_t *rtp_dyn_payload;
gboolean set_rtp;
} transport_media_pt_t;
@ -254,24 +255,6 @@ typedef struct {
/* here lie the debugging dumper functions */
#ifdef DEBUG_CONVERSATION
/* Called for each entry in the rtp_dyn_payload hash table. */
static void
rtp_dyn_payload_table_foreach_func (gpointer key, gpointer value, gpointer user_data _U_) {
gint* pt = (gint*) key;
encoding_name_and_rate_t *encoding = (encoding_name_and_rate_t*) value;
DPRINT2(("pt=%d",*pt));
DINDENT();
if (encoding) {
DPRINT2(("encoding_name=%s",
encoding->encoding_name ? encoding->encoding_name : "NULL"));
DPRINT2(("sample_rate=%d", encoding->sample_rate));
} else {
DPRINT2(("encoding=NULL"));
}
DENDENT();
}
static void sdp_dump_transport_media(const transport_media_pt_t* media) {
int i;
int count;
@ -291,14 +274,7 @@ static void sdp_dump_transport_media(const transport_media_pt_t* media) {
DENDENT();
DPRINT2(("rtp_dyn_payload hashtable=%s", media->rtp_dyn_payload ? "YES" : "NO"));
if (media->rtp_dyn_payload) {
DPRINT2(("rtp_dyn_payload hash table contents:"));
DINDENT();
if (g_hash_table_size(media->rtp_dyn_payload) == 0) {
DPRINT2(("rtp_dyn_payload is empty"));
} else {
g_hash_table_foreach(media->rtp_dyn_payload, rtp_dyn_payload_table_foreach_func, NULL);
}
DENDENT();
rtp_dump_dyn_payload(media->rtp_dyn_payload);
}
DPRINT2(("set_rtp=%s", media->set_rtp ? "TRUE" : "FALSE"));
DENDENT();
@ -1289,7 +1265,6 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
/*??guint8 *field_name;*/
guint8 *payload_type;
guint8 *attribute_value;
gint *key;
guint8 pt;
gint sdp_media_attrbute_code;
const char *msrp_res = "msrp://";
@ -1297,7 +1272,6 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
gboolean has_more_pars = TRUE;
tvbuff_t *h245_tvb;
guint8 master_key_length = 0, master_salt_length = 0;
encoding_name_and_rate_t *encoding_name_and_rate;
offset = 0;
@ -1364,9 +1338,6 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
return; /* Invalid */
}
key = wmem_new(wmem_file_scope(), gint);
*key = (gint)strtol((char*)payload_type, NULL, 10);
transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
next_offset = next_offset + 1;
@ -1399,30 +1370,17 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
*/
if (transport_info->media_count < 0) {
for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
if (n == 0) {
g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
key, encoding_name_and_rate);
} else { /* we create a new key and encoding_name to assign to the other hash tables */
gint *key2;
key2 = wmem_new(wmem_file_scope(), gint);
*key2 = (gint)strtol((char*)payload_type, NULL, 10);
g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
key2, encoding_name_and_rate);
}
rtp_dyn_payload_insert(transport_info->media[n].rtp_dyn_payload,
pt,
transport_info->encoding_name[pt],
transport_info->sample_rate[pt]);
}
return;
/* if the "a=" is after an "m=", only apply to this "m=" */
} else
/* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
}
encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
key, encoding_name_and_rate);
rtp_dyn_payload_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
pt, transport_info->encoding_name[pt], transport_info->sample_rate[pt]);
break;
case SDP_FMTP:
if (sdp_media_attribute_tree) {
@ -1917,8 +1875,7 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
transport_info->encoding_name[n] = (char*)UNKNOWN_ENCODING;
}
for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
transport_info->media[n].rtp_dyn_payload =
g_hash_table_new(g_int_hash, g_int_equal);
transport_info->media[n].rtp_dyn_payload = rtp_dyn_payload_new();
transport_info->media[n].set_rtp = FALSE;
}
@ -1955,7 +1912,7 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
(transport_info->sdp_status == SDP_EXCHANGE_OFFER)) {
for (n = start_transport_info_count; n < SDP_MAX_RTP_CHANNELS; n++) {
if (!transport_info->media[n].rtp_dyn_payload)
transport_info->media[n].rtp_dyn_payload = g_hash_table_new(g_int_hash, g_int_equal);
transport_info->media[n].rtp_dyn_payload = rtp_dyn_payload_new();
}
}
@ -2160,10 +2117,10 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
/* Free the hash table if we did't assigned it to a conv use it */
if (!transport_info->media[n].set_rtp)
{
DPRINT(("set_rtp is not set, calling rtp_free_hash_dyn_payload, "
DPRINT(("set_rtp is not set, calling rtp_dyn_payload_free, "
"channel=%d, media_port=%d",
n, transport_info->media_port[n]));
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
@ -2176,10 +2133,10 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
{
if (!transport_info->media[n].set_rtp)
{
DPRINT(("media_count == -1, calling rtp_free_hash_dyn_payload, "
DPRINT(("media_count == -1, calling rtp_dyn_payload_free, "
"channel=%d, media_port=%d",
n, transport_info->media_port[n]));
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
}
@ -2190,10 +2147,10 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
{
if (!transport_info->media[n].set_rtp)
{
DPRINT(("media_count != -1, calling rtp_free_hash_dyn_payload, "
DPRINT(("media_count != -1, calling rtp_dyn_payload_free, "
"channel=%d, media_port=%d",
n, transport_info->media_port[n]));
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
}
@ -2208,7 +2165,7 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex
{
if (!transport_info->media[n].set_rtp)
{
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
}
@ -2281,8 +2238,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
local_transport_info.encoding_name[n] = (char*)UNKNOWN_ENCODING;
}
for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
local_transport_info.media[n].rtp_dyn_payload =
g_hash_table_new(g_int_hash, g_int_equal);
local_transport_info.media[n].rtp_dyn_payload = rtp_dyn_payload_new();
local_transport_info.media[n].set_rtp = FALSE;
}
@ -2559,14 +2515,13 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
i, local_transport_info.media[n].pt[i]));
/* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
if ((local_transport_info.media[n].pt[i] >= 96) && (local_transport_info.media[n].pt[i] <= 127)) {
encoding_name_and_rate_t *encoding_name_and_rate_pt =
(encoding_name_and_rate_t *)g_hash_table_lookup(
const gchar *payload_type_str = rtp_dyn_payload_get_name(
local_transport_info.media[n].rtp_dyn_payload,
&local_transport_info.media[n].pt[i]);
if (encoding_name_and_rate_pt) {
local_transport_info.media[n].pt[i]);
if (payload_type_str) {
if (strlen(sdp_pi->summary_str))
g_strlcat(sdp_pi->summary_str, " ", 50);
g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
g_strlcat(sdp_pi->summary_str, payload_type_str, 50);
} else {
char num_pt[10];
g_snprintf(num_pt, 10, "%u", local_transport_info.media[n].pt[i]);
@ -2589,7 +2544,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if ((transport_info == &local_transport_info) &&
!transport_info->media[n].set_rtp)
{
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
@ -2611,7 +2566,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (!transport_info->media[n].set_rtp)
{
rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
transport_info->media[n].rtp_dyn_payload = NULL;
}
}

View File

@ -563,10 +563,9 @@ RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void cons
/* Use existing packet info if available */
p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name("rtp"), 0);
if (p_conv_data && p_conv_data->rtp_dyn_payload) {
encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
encoding_name_and_rate_pt = (encoding_name_and_rate_t *)g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt);
if (encoding_name_and_rate_pt) {
strinfo->pt_str = g_strdup(encoding_name_and_rate_pt->encoding_name);
const gchar *encoding_name = rtp_dyn_payload_get_name(p_conv_data->rtp_dyn_payload, strinfo->pt);
if (encoding_name) {
strinfo->pt_str = g_strdup(encoding_name);
}
}
}