From: Matthew Jordan Date: Fri, 24 Aug 2012 13:55:18 +0000 (+0000) Subject: Merge patches for 1.8.11-cert6 X-Git-Tag: certified/1.8.11-cert6~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3afd7feda34f0274286fff8f89b3cbd092ccbae4;p=thirdparty%2Fasterisk.git Merge patches for 1.8.11-cert6 This includes the following * r369351 for AST-883 * r368807 for AST-884 * r356604, r356650, r364203 for AST-890 * r370618 for AST-896 * r370205, r370273, r370360 for AST-916 * r371469 for AST-932 git-svn-id: https://origsvn.digium.com/svn/asterisk/certified/branches/1.8.11@371651 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index bd80394ec1..456d5fa7e7 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -9034,6 +9034,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action int video = FALSE; int image = FALSE; int text = FALSE; + int processed_crypto = FALSE; char protocol[5] = {0,}; int x; @@ -9208,28 +9209,34 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action case 'a': /* Audio specific scanning */ if (audio) { - if (process_sdp_a_sendonly(value, &sendonly)) + if (process_sdp_a_sendonly(value, &sendonly)) { processed = TRUE; - else if (process_crypto(p, p->rtp, &p->srtp, value)) + } else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) { + processed_crypto = TRUE; processed = TRUE; - else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) + } else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) { processed = TRUE; + } } /* Video specific scanning */ else if (video) { - if (process_sdp_a_sendonly(value, &vsendonly)) + if (process_sdp_a_sendonly(value, &vsendonly)) { processed = TRUE; - else if (process_crypto(p, p->vrtp, &p->vsrtp, value)) + } else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) { + processed_crypto = TRUE; processed = TRUE; - else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) + } else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) { processed = TRUE; + } } /* Text (T.140) specific scanning */ else if (text) { - if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) + if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) { processed = TRUE; - else if (process_crypto(p, p->trtp, &p->tsrtp, value)) + } else if (!processed_crypto && process_crypto(p, p->trtp, &p->tsrtp, value)) { + processed_crypto = TRUE; processed = TRUE; + } } /* Image (T.38 FAX) specific scanning */ else if (image) { @@ -16251,11 +16258,12 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, } if (!ast_strlen_zero(peer->cid_name)) ast_string_field_set(p, cid_name, peer->cid_name); - if (!ast_strlen_zero(peer->cid_tag)) - ast_string_field_set(p, cid_tag, peer->cid_tag); if (peer->callingpres) p->callingpres = peer->callingpres; } + if (!ast_strlen_zero(peer->cid_tag)) { + ast_string_field_set(p, cid_tag, peer->cid_tag); + } ast_string_field_set(p, fullcontact, peer->fullcontact); if (!ast_strlen_zero(peer->context)) { @@ -27318,6 +27326,10 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask } else if (!strcasecmp(word, "nonat")) { ast_set_flag(&flags[0], SIP_DIRECT_MEDIA); ast_clear_flag(&flags[0], SIP_DIRECT_MEDIA_NAT); + } else if (!strcasecmp(word, "outgoing")) { + ast_set_flag(&flags[0], SIP_DIRECT_MEDIA); + ast_set_flag(&mask[2], SIP_PAGE3_DIRECT_MEDIA_OUTGOING); + ast_set_flag(&flags[2], SIP_PAGE3_DIRECT_MEDIA_OUTGOING); } else { ast_log(LOG_WARNING, "Unknown directmedia mode '%s' on line %d\n", v->value, v->lineno); } @@ -29747,6 +29759,18 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i p->redircodecs = codecs; changed = 1; } + + if (ast_test_flag(&p->flags[2], SIP_PAGE3_DIRECT_MEDIA_OUTGOING) && !p->outgoing_call) { + /* We only wish to withhold sending the initial direct media reinvite on the incoming dialog. + * Further direct media reinvites beyond the initial should be sent. In order to allow further + * direct media reinvites to be sent, we clear this flag. + */ + ast_clear_flag(&p->flags[2], SIP_PAGE3_DIRECT_MEDIA_OUTGOING); + sip_pvt_unlock(p); + ast_channel_unlock(chan); + return 0; + } + if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { if (chan->_state != AST_STATE_UP) { /* We are in early state */ if (p->do_history) @@ -30115,12 +30139,6 @@ static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struc } } - /* For now, when we receive an INVITE just take the first successful crypto line */ - if ((*srtp)->crypto && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { - ast_debug(3, "We've already processed a crypto attribute, skipping '%s'\n", a); - return FALSE; - } - if (!(*srtp)->crypto && !((*srtp)->crypto = sdp_crypto_setup())) { return FALSE; } diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index f839cf0b0f..a5b9686fe5 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -359,9 +359,10 @@ #define SIP_PAGE3_SNOM_AOC (1 << 0) /*!< DPG: Allow snom aoc messages */ +#define SIP_PAGE3_DIRECT_MEDIA_OUTGOING (1 << 1) /*!< DP: Only send direct media reinvites on outgoing calls */ #define SIP_PAGE3_FLAGS_TO_COPY \ - (SIP_PAGE3_SNOM_AOC) + (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_DIRECT_MEDIA_OUTGOING) /*@}*/ diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index a10c224a9d..a461b01c2c 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -889,6 +889,13 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; instead of INVITE. This can be combined with 'nonat', as ; 'directmedia=update,nonat'. It implies 'yes'. +;directmedia=outgoing ; When sending directmedia reinvites, do not send an immediate + ; reinvite on an incoming call leg. This option is useful when + ; peered with another SIP user agent that is known to send + ; immediate direct media reinvites upon call establishment. Setting + ; the option in this situation helps to prevent potential glares. + ; Setting this option implies 'yes'. + ;directrtpsetup=yes ; Enable the new experimental direct RTP setup. This sets up ; the call directly with media peer-2-peer without re-invites. ; Will not work for video and cases where the callee sends diff --git a/main/cel.c b/main/cel.c index 35e851b03c..4bedc34737 100644 --- a/main/cel.c +++ b/main/cel.c @@ -398,6 +398,14 @@ void ast_cel_check_retire_linkedid(struct ast_channel *chan) } } +/* Note that no 'chan_fixup' function is provided for this datastore type, + * because the channels that will use it will never be involved in masquerades. + */ +static const struct ast_datastore_info fabricated_channel_datastore = { + .type = "CEL fabricated channel", + .destroy = ast_free_ptr, +}; + struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event) { struct varshead *headp; @@ -407,6 +415,8 @@ struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event struct ast_cel_event_record record = { .version = AST_CEL_EVENT_RECORD_VERSION, }; + struct ast_datastore *datastore; + char *app_data; /* do not call ast_channel_alloc because this is not really a real channel */ if (!(tchan = ast_dummy_channel_alloc())) { @@ -469,10 +479,42 @@ struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event AST_LIST_INSERT_HEAD(headp, newvariable, entries); } - tchan->appl = ast_strdup(record.application_name); - tchan->data = ast_strdup(record.application_data); tchan->amaflags = record.amaflag; + /* We need to store an 'application name' and 'application + * data' on the channel for logging purposes, but the channel + * structure only provides a place to store pointers, and it + * expects these pointers to be pointing to data that does not + * need to be freed. This means that the channel's destructor + * does not attempt to free any storage that these pointers + * point to. However, we can't provide data in that form directly for + * these structure members. In order to ensure that these data + * elements have a lifetime that matches the channel's + * lifetime, we'll put them in a datastore attached to the + * channel, and set's the channel's pointers to point into the + * datastore. The datastore will then be automatically destroyed + * when the channel is destroyed. + */ + + if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) { + ast_channel_unref(tchan); + return NULL; + } + + if (!(app_data = ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) { + ast_datastore_free(datastore); + ast_channel_unref(tchan); + return NULL; + } + + tchan->appl = app_data; + tchan->data = app_data + strlen(record.application_name) + 1; + + strcpy((char *) tchan->appl, record.application_name); + strcpy((char *) tchan->data, record.application_data); + datastore->data = app_data; + ast_channel_datastore_add(tchan, datastore); + return tchan; } diff --git a/main/channel.c b/main/channel.c index f00c400345..90fdeabe55 100644 --- a/main/channel.c +++ b/main/channel.c @@ -2484,6 +2484,13 @@ static void ast_dummy_channel_destructor(void *obj) struct ast_channel *chan = obj; struct ast_var_t *vardata; struct varshead *headp; + struct ast_datastore *datastore; + + /* Get rid of each of the data stores on the channel */ + while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) { + /* Free the data store */ + ast_datastore_free(datastore); + } headp = &chan->varshead; diff --git a/main/xmldoc.c b/main/xmldoc.c index 239e867ed4..38b15cb519 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -1784,14 +1784,16 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o { struct ast_xml_node *tmp; const char *notcleanret, *tmpstr; - struct ast_str *ret = ast_str_create(128); + struct ast_str *ret; if (raw_output) { + /* xmldoc_string_cleanup will allocate the ret object */ notcleanret = ast_xml_get_text(node); tmpstr = notcleanret; xmldoc_string_cleanup(ast_skip_blanks(notcleanret), &ret, 0); ast_xml_free_text(tmpstr); } else { + ret = ast_str_create(128); for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) { /* if found, parse a element. */ if (xmldoc_parse_para(tmp, "", "\n", &ret)) {