[asterisk-commits] file: branch file/pimp_sip_location r381629 - in /team/file/pimp_sip_location...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Feb 16 15:07:30 CST 2013


Author: file
Date: Sat Feb 16 15:07:22 2013
New Revision: 381629

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381629
Log:
Multiple revisions 381598,381610,381618

........
  r381598 | root | 2013-02-15 20:18:02 -0400 (Fri, 15 Feb 2013) | 22 lines
  
  Merged revisions 381595 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381595 | mjordan | 2013-02-15 17:29:28 -0600 (Fri, 15 Feb 2013) | 15 lines
    
    Fix crash in PresenceState AMI action when specifying an invalid provider
    
    This patch fixes a crash in Asterisk that could be caused by using the
    PresenceState AMI action while providing an invalid provider. This patch
    also adds some additional warnings when a user attempts to provide the
    PresenceState action with invalid data, and removes some NOTICE statements
    that were still lurking in the code from testing.
    
    (closes issue AST-1084)
    Reported by: John Bigelow
    Tested by: John Bigelow
    ........
    
    Merged revisions 381594 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
........
  r381610 | file | 2013-02-16 12:15:22 -0400 (Sat, 16 Feb 2013) | 11 lines
  
  Improve media handling and add some additional functionality.
  
  1. The act of negotiating a media stream and applying the negotiated stream are now separate operations.
  2. Hold/unhold is now implemented.
  3. RTP over IPv6 is now implemented.
  4. Use of the ptime attribute works.
  5. Local Packet2Packet bridging works.
  6. Symmetric RTP can now be enabled on a per-endpoint basis.
  
  Review: https://reviewboard.asterisk.org/r/2318/
........
  r381618 | root | 2013-02-16 13:17:59 -0400 (Sat, 16 Feb 2013) | 28 lines
  
  Merged revisions 381614-381615 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381614 | file | 2013-02-16 10:24:21 -0600 (Sat, 16 Feb 2013) | 4 lines
    
    Add support for retrieving multiple objects from sorcery using a regex on their id.
    
    Review: https://reviewboard.asterisk.org/r/2329/
  ................
    r381615 | mjordan | 2013-02-16 10:28:43 -0600 (Sat, 16 Feb 2013) | 15 lines
    
    Don't send presencestate information if the state is invalid
    
    Previously, presencestate information was sent whenever the state was not
    NOT_SET. When r381594 actually returned INVALID presence state in all the
    places it was supposed to, it caused chan_sip to start adding presence
    state information to NOTIFY requests that it previously would not have
    added. chan_sip shouldn't be adding presence state information when the
    provider is in an invalid state; users can't set the state to invalid and
    an invalid state always implies that the provider is in an error condition.
    
    (issue AST-1084)
    ........
    
    Merged revisions 381613 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
........

Merged revisions 381598,381610,381618 from http://svn.asterisk.org/svn/asterisk/team/group/pimp_my_sip

Modified:
    team/file/pimp_sip_location/   (props changed)
    team/file/pimp_sip_location/channels/chan_gulp.c
    team/file/pimp_sip_location/channels/chan_sip.c
    team/file/pimp_sip_location/configs/res_sip.conf.sample
    team/file/pimp_sip_location/funcs/func_presencestate.c
    team/file/pimp_sip_location/include/asterisk/res_sip.h
    team/file/pimp_sip_location/include/asterisk/res_sip_session.h
    team/file/pimp_sip_location/include/asterisk/sorcery.h
    team/file/pimp_sip_location/main/manager.c
    team/file/pimp_sip_location/main/presencestate.c
    team/file/pimp_sip_location/res/res_sip/sip_configuration.c
    team/file/pimp_sip_location/res/res_sip_sdp_audio.c
    team/file/pimp_sip_location/res/res_sip_session.c
    team/file/pimp_sip_location/res/res_sorcery_config.c
    team/file/pimp_sip_location/res/res_sorcery_memory.c

Propchange: team/file/pimp_sip_location/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/file/pimp_sip_location/
------------------------------------------------------------------------------
--- pimp-integrated (original)
+++ pimp-integrated Sat Feb 16 15:07:22 2013
@@ -1,1 +1,1 @@
-/team/group/pimp_my_sip:1-381580
+/team/group/pimp_my_sip:1-381628

Modified: team/file/pimp_sip_location/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/channels/chan_gulp.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/channels/chan_gulp.c (original)
+++ team/file/pimp_sip_location/channels/chan_gulp.c Sat Feb 16 15:07:22 2013
@@ -107,10 +107,19 @@
 	.incoming_response = gulp_incoming_response,
 };
 
-/*! \brief Function called by RTP engine to get local RTP peer */
+/*! \brief Function called by RTP engine to get local audio RTP peer */
 static enum ast_rtp_glue_result gulp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
-	return AST_RTP_GLUE_RESULT_FORBID;
+	struct ast_sip_session *session = ast_channel_tech_pvt(chan);
+
+	if (!session || !session->media[AST_SIP_MEDIA_AUDIO].rtp) {
+		return AST_RTP_GLUE_RESULT_FORBID;
+	}
+
+	ao2_ref(session->media[AST_SIP_MEDIA_AUDIO].rtp, +1);
+	*instance = session->media[AST_SIP_MEDIA_AUDIO].rtp;
+
+	return AST_RTP_GLUE_RESULT_LOCAL;
 }
 
 /*! \brief Function called by RTP engine to get peer capabilities */
@@ -162,11 +171,6 @@
 	ast_format_copy(ast_channel_readformat(chan), &fmt);
 	ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
 
-	if (session->media.audio) {
-		ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->media.audio, 0));
-		ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->media.audio, 1));
-	}
-
 	if (state == AST_STATE_RING) {
 		ast_channel_rings_set(chan, 1);
 	}
@@ -222,16 +226,16 @@
 
 	switch (ast_channel_fdno(ast)) {
 	case 0:
-		f = ast_rtp_instance_read(session->media.audio, 0);
+		f = ast_rtp_instance_read(session->media[AST_SIP_MEDIA_AUDIO].rtp, 0);
 		break;
 	case 1:
-		f = ast_rtp_instance_read(session->media.audio, 1);
+		f = ast_rtp_instance_read(session->media[AST_SIP_MEDIA_AUDIO].rtp, 1);
 		break;
 	default:
 		f = &ast_null_frame;
 	}
 
-	if (f->frametype == AST_FRAME_VOICE) {
+	if (f && f->frametype == AST_FRAME_VOICE) {
 		if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
 			ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
 			ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
@@ -262,8 +266,8 @@
 				ast_getformatname(ast_channel_writeformat(ast)));
 			return 0;
 		}
-		if (session->media.audio) {
-			res = ast_rtp_instance_write(session->media.audio, frame);
+		if (session->media[AST_SIP_MEDIA_AUDIO].rtp) {
+			res = ast_rtp_instance_write(session->media[AST_SIP_MEDIA_AUDIO].rtp, frame);
 		}
 		break;
 	default:
@@ -455,7 +459,9 @@
 
 	switch (session->endpoint->dtmf) {
 	case AST_SIP_DTMF_RFC_4733:
-		ast_rtp_instance_dtmf_begin(session->media.audio, digit);
+		if (session->media[AST_SIP_MEDIA_AUDIO].rtp) {
+			ast_rtp_instance_dtmf_begin(session->media[AST_SIP_MEDIA_AUDIO].rtp, digit);
+		}
 	case AST_SIP_DTMF_NONE:
 		break;
 	case AST_SIP_DTMF_INBAND:
@@ -479,7 +485,9 @@
 		/* TODO: Send INFO dtmf here */
 		break;
 	case AST_SIP_DTMF_RFC_4733:
-		ast_rtp_instance_dtmf_end_with_duration(session->media.audio, digit, duration);
+		if (session->media[AST_SIP_MEDIA_AUDIO].rtp) {
+			ast_rtp_instance_dtmf_end_with_duration(session->media[AST_SIP_MEDIA_AUDIO].rtp, digit, duration);
+		}
 	case AST_SIP_DTMF_NONE:
 		break;
 	case AST_SIP_DTMF_INBAND:
@@ -880,11 +888,9 @@
 		}
 		break;
 	case 183:
-		ast_rtp_instance_activate(session->media.audio);
 		ast_queue_control(session->channel, AST_CONTROL_PROGRESS);
 		break;
 	case 200:
-		ast_rtp_instance_activate(session->media.audio);
 		ast_queue_control(session->channel, AST_CONTROL_ANSWER);
 		break;
 	default:

Modified: team/file/pimp_sip_location/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/channels/chan_sip.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/channels/chan_sip.c (original)
+++ team/file/pimp_sip_location/channels/chan_sip.c Sat Feb 16 15:07:22 2013
@@ -14531,7 +14531,8 @@
 		else
 			ast_str_append(tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
 
-		if (allow_notify_user_presence(p) && (data->presence_state > 0)) {
+		if (allow_notify_user_presence(p) && (data->presence_state != AST_PRESENCE_INVALID)
+				&& (data->presence_state != AST_PRESENCE_NOT_SET)) {
 			ast_str_append(tmp, 0, "</tuple>\n");
 			ast_str_append(tmp, 0, "<tuple id=\"digium-presence\">\n");
 			ast_str_append(tmp, 0, "<status>\n");

Modified: team/file/pimp_sip_location/configs/res_sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/configs/res_sip.conf.sample?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/configs/res_sip.conf.sample (original)
+++ team/file/pimp_sip_location/configs/res_sip.conf.sample Sat Feb 16 15:07:22 2013
@@ -18,3 +18,7 @@
 ;timers=yes               ; Enable or disable session timers support - valid options are: yes, no, required, forced
 ;timers_min_se=90         ; Minimum session timers expiration period, in seconds
 ;timers_sess_expires=1800 ; Session timers expiration period, in seconds
+;mohsuggest=example	      ; What musiconhold class to suggest that the peer channel use when this endpoint places them on hold
+;rtp_ipv6=yes             ; Force IPv6 for RTP transport
+;rtp_symmetric=yes        ; Enable symmetric RTP support
+;use_ptime=yes            ; Whether to use the ptime value received from the endpoint or not

Modified: team/file/pimp_sip_location/funcs/func_presencestate.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/funcs/func_presencestate.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/funcs/func_presencestate.c (original)
+++ team/file/pimp_sip_location/funcs/func_presencestate.c Sat Feb 16 15:07:22 2013
@@ -243,7 +243,7 @@
 	ast_db_get(astdb_family, data, buf, sizeof(buf));
 
 	if (parse_data(buf, &state, &_subtype, &_message, &_options)) {
-		return -1;
+		return AST_PRESENCE_INVALID;
 	}
 
 	if ((strchr(_options, 'e'))) {
@@ -252,7 +252,6 @@
 			*subtype = NULL;
 		} else {
 			memset(tmp, 0, sizeof(tmp));
-			ast_log(LOG_NOTICE, "Hey there, I'm doing some base64 decoding\n");
 			ast_base64decode((unsigned char *) tmp, _subtype, sizeof(tmp) - 1);
 			*subtype = ast_strdup(tmp);
 		}
@@ -261,12 +260,10 @@
 			*message = NULL;
 		} else {
 			memset(tmp, 0, sizeof(tmp));
-			ast_log(LOG_NOTICE, "Hey there, I'm doing some more base64 decoding\n");
 			ast_base64decode((unsigned char *) tmp, _message, sizeof(tmp) - 1);
 			*message = ast_strdup(tmp);
 		}
 	} else {
-		ast_log(LOG_NOTICE, "Not doing any base64 decoding\n");
 		*subtype = ast_strlen_zero(_subtype) ? NULL : ast_strdup(_subtype);
 		*message = ast_strlen_zero(_message) ? NULL : ast_strdup(_message);
 	}

Modified: team/file/pimp_sip_location/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/include/asterisk/res_sip.h?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/include/asterisk/res_sip.h (original)
+++ team/file/pimp_sip_location/include/asterisk/res_sip.h Sat Feb 16 15:07:22 2013
@@ -220,6 +220,8 @@
 		AST_STRING_FIELD(outbound_proxy);
 		/*! Explicit AORs to dial if none are specified */
 		AST_STRING_FIELD(aors);
+                /*! Musiconhold class to suggest that the other side use when placing on hold */
+                AST_STRING_FIELD(mohsuggest);
 	);
 	/*! Identification information for this endpoint */
 	struct ast_party_id id;
@@ -237,12 +239,18 @@
 	size_t num_auths;
 	/*! DTMF mode to use with this endpoint */
 	enum ast_sip_dtmf_mode dtmf;
+	/*! Whether IPv6 RTP is enabled or not */
+	unsigned int rtp_ipv6;
+	/*! Whether symmetric RTP is enabled or not */
+	unsigned int rtp_symmetric;
+	/*! Whether to use the "ptime" attribute received from the endpoint or not */
+	unsigned int use_ptime;
 	/*! Enabled SIP extensions */
 	unsigned int extensions;
 	/*! Minimum session expiration period, in seconds */
-	unsigned min_se;
+	unsigned int min_se;
 	/*! Session expiration period, in seconds */
-	unsigned sess_expires;
+	unsigned int sess_expires;
 	/*! List of outbound registrations */
 	AST_LIST_HEAD_NOLOCK(, ast_sip_registration) registrations;
 	/*! Frequency to send OPTIONS requests to endpoint. 0 is disabled. */
@@ -424,7 +432,6 @@
 int ast_sip_initialize_sorcery_transport(struct ast_sorcery *sorcery);
 
 /*!
-<<<<<<< .working
  * \brief Initialize location support on a sorcery instance
  *
  * \param sorcery The sorcery instance
@@ -497,7 +504,6 @@
 int ast_sip_location_delete_contact(struct ast_sip_contact *contact);
 
 /*!
-=======
  * \page Threading model for SIP
  *
  * There are three major types of threads that SIP will have to deal with:

Modified: team/file/pimp_sip_location/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/include/asterisk/res_sip_session.h?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/include/asterisk/res_sip_session.h (original)
+++ team/file/pimp_sip_location/include/asterisk/res_sip_session.h Sat Feb 16 15:07:22 2013
@@ -38,11 +38,25 @@
 struct ast_rtp_instance;
 
 /*!
+ * \brief Positions of various media
+ */
+enum ast_sip_session_media_position {
+	/*! \brief First is audio */
+	AST_SIP_MEDIA_AUDIO = 0,
+	/*! \brief Second is video */
+	AST_SIP_MEDIA_VIDEO,
+	/*! \brief Last is the size for media details */
+	AST_SIP_MEDIA_SIZE,
+};
+
+/*!
  * \brief A structure containing SIP session media information
  */
 struct ast_sip_session_media {
-	/* RTP instance for audio */
-	struct ast_rtp_instance *audio;
+	/*! \brief RTP instance itself */
+	struct ast_rtp_instance *rtp;
+	/*! \brief Stream is on hold */
+	unsigned int held:1;
 };
 
 /*!
@@ -66,8 +80,8 @@
 	AST_LIST_HEAD(, ast_sip_session_supplement) supplements;
 	/* Datastores added to the session by supplements to the session */
 	struct ao2_container *datastores;
-	/* Media information */
-	struct ast_sip_session_media media;
+	/* Media streams */
+	struct ast_sip_session_media media[AST_SIP_MEDIA_SIZE];
 	/* Active invite session legs */
 	struct ao2_container *legs;
 	/* Workspace for tasks relating to this SIP session */
@@ -160,6 +174,15 @@
 	 * \retval <0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned.
 	 * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called.
 	 */
+	int (*negotiate_incoming_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
+	/*!
+	 * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer
+	 * \param session The session for which media is being added
+	 * \param stream The stream on which to operate
+	 * \retval 0 The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called.
+	 * \retval <0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned.
+	 * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called.
+	 */
 	int (*handle_incoming_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream);
 	/*!
 	 * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer
@@ -171,6 +194,19 @@
 	 * \retval >0 The handler has a stream to be added to the SDP. No further handler of this stream type will be called.
 	 */
 	int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, pjsip_inv_session *inv_session, struct pjmedia_sdp_session *sdp);
+	/*!
+	 * \brief Apply a negotiated SDP media stream
+	 * \param session The session for which media is being applied
+	 * \param local The entire local negotiated SDP
+	 * \param local_stream The local stream which to apply
+	 * \param remote The entire remote negotiated SDP
+	 * \param remote_stream The remote stream which to apply
+	 * \retval 0 The stream was not applied by this handler. If there are other registered handlers for this stream type, they will be called.
+	 * \retval <0 There was an error encountered. No further operation will take place and the current application will be abandoned.
+	 * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called.
+	 */
+	int (*apply_negotiated_sdp_stream)(struct ast_sip_session *session, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream,
+		const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream);
 	/*! Next item int he list. */
 	AST_LIST_ENTRY(ast_sip_session_sdp_handler) next;
 };

Modified: team/file/pimp_sip_location/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/include/asterisk/sorcery.h?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/include/asterisk/sorcery.h (original)
+++ team/file/pimp_sip_location/include/asterisk/sorcery.h Sat Feb 16 15:07:22 2013
@@ -565,6 +565,8 @@
  *
  * \retval non-NULL if error occurs
  * \retval NULL success
+ *
+ * \note The provided regex is treated as extended case sensitive.
  */
 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex);
 

Modified: team/file/pimp_sip_location/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/main/manager.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/main/manager.c (original)
+++ team/file/pimp_sip_location/main/manager.c Sat Feb 16 15:07:22 2013
@@ -2280,6 +2280,7 @@
 {
 	va_list ap;
 	struct ast_str *buf;
+	char *msg;
 
 	if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
 		return;
@@ -2289,8 +2290,13 @@
 	ast_str_set_va(&buf, 0, fmt, ap);
 	va_end(ap);
 
-	astman_send_response_full(s, m, "Error", ast_str_buffer(buf), NULL);
-	ast_free(buf);
+	/* astman_append will use the same underlying buffer, so copy the message out
+	 * before sending the response */
+	msg = ast_str_buffer(buf);
+	if (msg) {
+		msg = ast_strdupa(msg);
+	}
+	astman_send_response_full(s, m, "Error", msg, NULL);
 }
 
 void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
@@ -3378,7 +3384,7 @@
 
 	/* if regex compilation fails, hangup fails */
 	if (regcomp(&regexbuf, ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
-		astman_send_error_va(s, m, "Regex compile failed on: %s\n", name_or_regex);
+		astman_send_error_va(s, m, "Regex compile failed on: %s", name_or_regex);
 		ast_free(regex_string);
 		return 0;
 	}
@@ -4610,6 +4616,10 @@
 	}
 
 	state = ast_presence_state(provider, &subtype, &message);
+	if (state == AST_PRESENCE_INVALID) {
+		astman_send_error_va(s, m, "Invalid provider %s or provider in invalid state", provider);
+		return 0;
+	}
 
 	if (!ast_strlen_zero(subtype)) {
 		snprintf(subtype_header, sizeof(subtype_header),

Modified: team/file/pimp_sip_location/main/presencestate.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/main/presencestate.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/main/presencestate.c (original)
+++ team/file/pimp_sip_location/main/presencestate.c Sat Feb 16 15:07:22 2013
@@ -159,6 +159,9 @@
 	}
 	AST_RWLIST_UNLOCK(&presence_state_providers);
 
+	if (!provider) {
+		ast_log(LOG_WARNING, "No provider found for label %s\n", label);
+	}
 
 	return res;
 }

Modified: team/file/pimp_sip_location/res/res_sip/sip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/res/res_sip/sip_configuration.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/res/res_sip/sip_configuration.c (original)
+++ team/file/pimp_sip_location/res/res_sip/sip_configuration.c Sat Feb 16 15:07:22 2013
@@ -193,8 +193,12 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, prefs, codecs));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_endpoint, qualify_frequency), 0, 86400);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmfmode", "rfc4733", dtmf_handler, NULL, 0, 0);
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_ipv6));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_symmetric));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_ptime", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, use_ptime));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, transport));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, outbound_proxy));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mohsuggest", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mohsuggest));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "100rel", "yes", prack_handler, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, NULL, 0, 0);
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, min_se));

Modified: team/file/pimp_sip_location/res/res_sip_sdp_audio.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/res/res_sip_sdp_audio.c?view=diff&rev=381629&r1=381628&r2=381629
==============================================================================
--- team/file/pimp_sip_location/res/res_sip_sdp_audio.c (original)
+++ team/file/pimp_sip_location/res/res_sip_sdp_audio.c Sat Feb 16 15:07:22 2013
@@ -54,24 +54,35 @@
 static struct ast_sched_context *sched;
 
 /*! \brief Forward declarations for SDP handler functions */
-static int audio_handle_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream);
+static int audio_negotiate_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
 static int audio_create_outgoing_sdp_stream(struct ast_sip_session *session, pjsip_inv_session *inv_session, struct pjmedia_sdp_session *sdp);
+static int audio_apply_negotiated_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream,
+	const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream);
+
+/*! \brief Forward declaration for session supplement functions */
+static void audio_session_destroy(struct ast_sip_session *session);
 
 /*! \brief SDP handler for 'audio' media stream */
 static struct ast_sip_session_sdp_handler audio_sdp_handler = {
 	.id = "audio",
-	.handle_incoming_sdp_stream = audio_handle_incoming_sdp_stream,
+	.negotiate_incoming_sdp_stream = audio_negotiate_incoming_sdp_stream,
 	.create_outgoing_sdp_stream = audio_create_outgoing_sdp_stream,
+	.apply_negotiated_sdp_stream = audio_apply_negotiated_sdp_stream,
 };
 
+/*! \brief Session supplement for 'audio' media stream */
+static struct ast_sip_session_supplement audio_session_supplement = {
+	.session_destroy = audio_session_destroy,
+};
+
 /*! \brief Internal function which creates an RTP instance */
-static int audio_create_rtp(struct ast_sip_session *session)
+static int audio_create_rtp(struct ast_sip_session *session, unsigned int ipv6)
 {
 	pj_sockaddr addr;
 	char hostip[PJ_INET6_ADDRSTRLEN+2];
 	struct ast_sockaddr tmp;
 
-	if (pj_gethostip(pj_AF_INET(), &addr) != PJ_SUCCESS) {
+	if (pj_gethostip(ipv6 ? pj_AF_INET6() : pj_AF_INET(), &addr) != PJ_SUCCESS) {
 		return -1;
 	}
 
@@ -81,138 +92,57 @@
 		return -1;
 	}
 
-	if (!(session->media.audio = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
-		return -1;
-	}
-
-	ast_rtp_instance_set_prop(session->media.audio, AST_RTP_PROPERTY_RTCP, 1);
-
-	ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->media.audio), session->media.audio, &session->endpoint->prefs);
-	
+	if (!(session->media[AST_SIP_MEDIA_AUDIO].rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
+		return -1;
+	}
+
+	ast_rtp_instance_set_prop(session->media[AST_SIP_MEDIA_AUDIO].rtp, AST_RTP_PROPERTY_RTCP, 1);
+	ast_rtp_instance_set_prop(session->media[AST_SIP_MEDIA_AUDIO].rtp, AST_RTP_PROPERTY_NAT, session->endpoint->rtp_symmetric);
+
+	ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp),
+					 session->media[AST_SIP_MEDIA_AUDIO].rtp, &session->endpoint->prefs);
+
 	return 0;
 }
 
-/*! \brief Function which handles an incoming 'audio' stream */
-static int audio_handle_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream)
-{
-	int res = 1, addrs_cnt, format, othercapability = 0;
+/*! \brief Function which negotiates an incoming 'audio' stream */
+static int audio_negotiate_incoming_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
+{
 	char host[NI_MAXHOST];
-	struct ast_sockaddr *addrs;
-	struct ast_rtp_codecs codecs;
-	const pjmedia_sdp_attr *attr;
-	struct ast_format_cap *cap, *jointcap = NULL, *peercap = NULL;
-//	struct ast_format fmt;
-
-	/* If the stream has been rejected stop media if active */
-	if (!stream->desc.port) {
-		if (session->media.audio) {
-			ast_rtp_instance_stop(session->media.audio);
-		}
-
-		return 1;
-	}
-
-	/* Create an RTP instance if need be */
-	if (!session->media.audio && audio_create_rtp(session)) {
-		return -1;
-	}
-
-	if (!stream->conn) {
-		snprintf(host, sizeof(host), "%.*s", (int) pj_strlen(&sdp->conn->addr), pj_strbuf(&sdp->conn->addr));
-	} else {
-		snprintf(host, sizeof(host), "%.*s", (int) pj_strlen(&stream->conn->addr), pj_strbuf(&stream->conn->addr));
-	}
+	RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
+
+	/* If no audio formats have been configured reject this stream */
+	if (!ast_format_cap_has_type(session->endpoint->codecs, AST_FORMAT_TYPE_AUDIO)) {
+		return 0;
+	}
+
+	ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
 
 	/* Ensure that the address provided is valid */
-	if ((addrs_cnt = ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC)) <= 0) {
-		ast_log(LOG_ERROR, "Failed to resolve %s\n", host);
-		/* The provided host was actually invalid so we kill the session as it would just end up being broken */
-		if (session->channel) {
-			ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-		}
-		return -1;
-	}
-
-	/* To properly apply formats to the channel we need to keep track of capabilities */
-	if (!(cap = ast_format_cap_alloc_nolock()) ||
-	    !(peercap = ast_format_cap_alloc_nolock())) {
-		ast_log(LOG_ERROR, "Failed to allocate audio capabilities\n");
-		res = -1;
-		goto cleanup;
-	}
-
-	/* Apply connection information to the RTP instance */
-	ast_sockaddr_set_port(addrs, stream->desc.port);
-	ast_rtp_instance_set_remote_address(session->media.audio, addrs);
-	ast_free(addrs);
-
-	ast_rtp_codecs_payloads_initialize(&codecs);
-
-	/* Iterate through provided formats */
-	for (format = 0; format < stream->desc.fmt_count; format++) {
-		/* The payload is kept as a string for things like t38 but for audio it is always numerical */
-		ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]));
-
-		/* Look for the optional rtpmap attribute */
-		if ((attr = pjmedia_sdp_media_find_attr2(stream, "rtpmap", &stream->desc.fmt[format]))) {
-			pjmedia_sdp_rtpmap *rtpmap;
-
-			/* Interpret the attribute as an rtpmap */
-			if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_active, attr, &rtpmap)) == PJ_SUCCESS) {
-				char name[32];
-
-				snprintf(name, sizeof(name), "%.*s", (int) pj_strlen(&rtpmap->enc_name), pj_strbuf(&rtpmap->enc_name));
-				ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, pj_strtoul(&stream->desc.fmt[format]),
-									     "audio", name, 0, rtpmap->clock_rate);
-			}
-		}
-	}
-
-	ast_rtp_codecs_payload_formats(&codecs, peercap, &othercapability);
-
-	/* Using the configured codecs and the codecs in this SDP we determine the joint formats for *audio only* */
-	ast_format_cap_copy(cap, session->endpoint->codecs);
-	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_VIDEO);
-
-	if (!(jointcap = ast_format_cap_joint(cap, peercap))) {
-		char usbuf[64];
-		char thembuf[64];
-		if (session->channel) {
-			ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-		}
-		ast_getformatname_multiple(usbuf, sizeof(usbuf), cap);
-		ast_getformatname_multiple(thembuf, sizeof(thembuf), peercap);
-		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
-		res = -1;
-		goto cleanup;
-	}
-
-	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session->media.audio), session->media.audio);
-
-	/* Now that we have joint formats for audio remove the existing ones from the channel and add the new ones */
-//	ast_format_cap_copy(cap, ast_channel_nativeformats(session->channel));
-//	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_AUDIO);
-//	ast_format_cap_append(cap, jointcap);
-
-	/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
-//	ast_format_cap_copy(ast_channel_nativeformats(session->channel), cap);
-//	ast_codec_choose(&session->endpoint->prefs, cap, 1, &fmt);
-//	ast_set_read_format(session->channel, &fmt);
-//	ast_set_write_format(session->channel, &fmt);
-
-cleanup:
-	ast_format_cap_destroy(peercap);
-	ast_format_cap_destroy(jointcap);
-	ast_format_cap_destroy(cap);
-	ast_rtp_codecs_payloads_destroy(&codecs);
-
-	return res;
+	if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
+		/* The provided host was actually invalid so we error out this negotiation */
+		return -1;
+	}
+
+	/* Using the connection information create an appropriate RTP instance */
+	if (!session->media[AST_SIP_MEDIA_AUDIO].rtp && audio_create_rtp(session, ast_sockaddr_is_ipv6(addrs))) {
+		return -1;
+	}
+
+	/* pjmedia takes care of the formats and such */
+	return 1;
 }
 
 /*! \brief Function which creates an outgoing 'audio' stream */
 static int audio_create_outgoing_sdp_stream(struct ast_sip_session *session, pjsip_inv_session *inv_session, struct pjmedia_sdp_session *sdp)
 {
 	pj_pool_t *pool = inv_session->pool_active;
+	static const pj_str_t STR_AUDIO = { "audio", 5};
+	static const pj_str_t STR_IN = { "IN", 2 };
+	static const pj_str_t STR_IP4 = { "IP4", 3};
+	static const pj_str_t STR_IP6 = { "IP6", 3};
+	static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
+	static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
 	pjmedia_sdp_media *media;
 	struct ast_sockaddr addr;
 	char tmp[32];
@@ -223,7 +153,7 @@
 	if (!ast_format_cap_has_type(session->endpoint->codecs, AST_FORMAT_TYPE_AUDIO)) {
 		/* If no audio formats are configured don't add a stream */
 		return 0;
-	} else if (!session->media.audio && audio_create_rtp(session)) {
+	} else if (!session->media[AST_SIP_MEDIA_AUDIO].rtp && audio_create_rtp(session, session->endpoint->rtp_ipv6)) {
 		return -1;
 	}
 
@@ -233,13 +163,13 @@
 	}
 
 	/* TODO: This should eventually support SRTP */
-	pj_strdup2(pool, &media->desc.media, "audio");
-	pj_strdup2(pool, &media->desc.transport, "RTP/AVP");
+	media->desc.media = STR_AUDIO;
+	media->desc.transport = STR_RTP_AVP;
 
 	/* Add connection level details */
-	ast_rtp_instance_get_local_address(session->media.audio, &addr);
-	pj_strdup2(pool, &media->conn->net_type, "IN");
-	pj_strdup2(pool, &media->conn->addr_type, (ast_sockaddr_is_ipv6(&addr) && !ast_sockaddr_is_ipv4_mapped(&addr)) ? "IP6" : "IP4");
+	ast_rtp_instance_get_local_address(session->media[AST_SIP_MEDIA_AUDIO].rtp, &addr);
+	media->conn->net_type = STR_IN;
+	media->conn->addr_type = (ast_sockaddr_is_ipv6(&addr) && !ast_sockaddr_is_ipv4_mapped(&addr)) ? STR_IP6 : STR_IP4;
 	pj_strdup2(pool, &media->conn->addr, ast_sockaddr_stringify_addr_remote(&addr));
 	media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
 	media->desc.port_count = 1;
@@ -249,13 +179,14 @@
 		struct ast_format format;
 		int rtp_code;
 		pjmedia_sdp_rtpmap rtpmap;
-		struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session->media.audio)->pref;
+		struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp)->pref;
 
 		if (!ast_codec_pref_index(&session->endpoint->prefs, index, &format)) {
 			break;
 		} else if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_AUDIO) {
 			continue;
-		} else if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session->media.audio), 1, &format, 0)) == -1) {
+		} else if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp),
+								   1, &format, 0)) == -1) {
 			return -1;
 		}
 
@@ -282,7 +213,8 @@
 		int rtp_code;
 		pjmedia_sdp_rtpmap rtpmap;
 
-		if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session->media.audio), 0, NULL, index)) == -1) {
+		if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp),
+										   0, NULL, index)) == -1) {
 			continue;
 		}
 
@@ -310,10 +242,167 @@
 		media->attr[media->attr_count++] = attr;
 	}
 
+	/* Add the sendrecv attribute - we purposely don't keep track because pjmedia-sdp will automatically change our offer for us */
+	attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
+	attr->name = STR_SENDRECV;
+	media->attr[media->attr_count++] = attr;
+
 	/* Add the media stream to the SDP */
 	sdp->media[sdp->media_count++] = media;
 
 	return 1;
+}
+
+/*! \brief Function which applies a negotiated SDP stream */
+static int audio_apply_negotiated_sdp_stream(struct ast_sip_session *session, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream,
+	const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
+{
+	int format, othercapability = 0;
+	char host[NI_MAXHOST];
+	RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
+	struct ast_rtp_codecs codecs;
+	const pjmedia_sdp_attr *attr;
+	RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
+	RAII_VAR(struct ast_format_cap *, jointcap, NULL, ast_format_cap_destroy);
+	RAII_VAR(struct ast_format_cap *, peercap, NULL, ast_format_cap_destroy);
+	struct ast_format fmt;
+
+	/* Create an RTP instance if need be */
+	if (!session->media[AST_SIP_MEDIA_AUDIO].rtp && audio_create_rtp(session, session->endpoint->rtp_ipv6)) {
+		return -1;
+	}
+
+	ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
+
+	/* Ensure that the address provided is valid */
+	if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
+		/* The provided host was actually invalid so we error out this negotiation */
+		return -1;
+	}
+
+	/* To properly apply formats to the channel we need to keep track of capabilities */
+	if (!(cap = ast_format_cap_alloc_nolock()) ||
+	    !(peercap = ast_format_cap_alloc_nolock())) {
+		ast_log(LOG_ERROR, "Failed to allocate audio capabilities\n");
+		return -1;
+	}
+
+	/* Apply connection information to the RTP instance */
+	ast_sockaddr_set_port(addrs, remote_stream->desc.port);
+	ast_rtp_instance_set_remote_address(session->media[AST_SIP_MEDIA_AUDIO].rtp, addrs);
+
+	ast_rtp_codecs_payloads_initialize(&codecs);
+
+	/* Iterate through provided formats */
+	for (format = 0; format < local_stream->desc.fmt_count; format++) {
+		/* The payload is kept as a string for things like t38 but for audio it is always numerical */
+		ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, pj_strtoul(&local_stream->desc.fmt[format]));
+
+		/* Look for the optional rtpmap attribute */
+		if ((attr = pjmedia_sdp_media_find_attr2(local_stream, "rtpmap", &local_stream->desc.fmt[format]))) {
+			pjmedia_sdp_rtpmap *rtpmap;
+
+			/* Interpret the attribute as an rtpmap */
+			if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_active, attr, &rtpmap)) == PJ_SUCCESS) {
+				char name[32];
+
+				ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name));
+				ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, pj_strtoul(&local_stream->desc.fmt[format]),
+									     "audio", name, 0, rtpmap->clock_rate);
+			}
+		}
+	}
+
+	ast_rtp_codecs_payload_formats(&codecs, peercap, &othercapability);
+
+	/* Apply packetization if available and configured to do so */
+	if (session->endpoint->use_ptime && (attr = pjmedia_sdp_media_find_attr2(remote_stream, "ptime", NULL))) {
+		pj_str_t value = attr->value;
+		unsigned long framing = pj_strtoul(pj_strltrim(&value));
+		int codec;
+		struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp)->pref;
+
+		for (codec = 0; codec < AST_RTP_MAX_PT; codec++) {
+			struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(
+				session->media[AST_SIP_MEDIA_AUDIO].rtp), codec);
+
+			if (!format.asterisk_format) {
+				continue;
+			}
+
+			ast_codec_pref_setsize(pref, &format.format, framing);
+		}
+
+		ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp),
+			session->media[AST_SIP_MEDIA_AUDIO].rtp, pref);
+	}
+
+	/* Using the configured codecs and the codecs in this SDP we determine the joint formats for *audio only* */
+	ast_format_cap_copy(cap, session->endpoint->codecs);
+	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_VIDEO);
+
+	if (!(jointcap = ast_format_cap_joint(cap, peercap))) {
+		char usbuf[64], thembuf[64];
+
+		ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+		ast_getformatname_multiple(usbuf, sizeof(usbuf), cap);
+		ast_getformatname_multiple(thembuf, sizeof(thembuf), peercap);
+		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
+

[... 270 lines stripped ...]



More information about the asterisk-commits mailing list