[asterisk-commits] mmichelson: branch mmichelson/pool_shark2 r381641 - in /team/mmichelson/pool_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Feb 18 11:03:46 CST 2013


Author: mmichelson
Date: Mon Feb 18 11:03:41 2013
New Revision: 381641

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381641
Log:
Resolve conflict and reset automerge...again.


Modified:
    team/mmichelson/pool_shark2/   (props changed)
    team/mmichelson/pool_shark2/apps/app_confbridge.c
    team/mmichelson/pool_shark2/channels/chan_gulp.c
    team/mmichelson/pool_shark2/channels/chan_sip.c
    team/mmichelson/pool_shark2/configs/res_sip.conf.sample
    team/mmichelson/pool_shark2/include/asterisk/res_sip.h
    team/mmichelson/pool_shark2/include/asterisk/res_sip_session.h
    team/mmichelson/pool_shark2/include/asterisk/sorcery.h
    team/mmichelson/pool_shark2/main/sorcery.c
    team/mmichelson/pool_shark2/res/res_sip/sip_configuration.c
    team/mmichelson/pool_shark2/res/res_sip_sdp_audio.c
    team/mmichelson/pool_shark2/res/res_sip_session.c
    team/mmichelson/pool_shark2/res/res_sorcery_config.c
    team/mmichelson/pool_shark2/res/res_sorcery_memory.c
    team/mmichelson/pool_shark2/tests/test_sorcery.c

Propchange: team/mmichelson/pool_shark2/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/mmichelson/pool_shark2/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/mmichelson/pool_shark2/
------------------------------------------------------------------------------
--- pool_shark2-integrated (original)
+++ pool_shark2-integrated Mon Feb 18 11:03:41 2013
@@ -1,1 +1,1 @@
-/team/group/pimp_my_sip:1-381600
+/team/group/pimp_my_sip:1-381640

Propchange: team/mmichelson/pool_shark2/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Feb 18 11:03:41 2013
@@ -1,1 +1,1 @@
-/trunk:1-381597
+/trunk:1-381630

Modified: team/mmichelson/pool_shark2/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/apps/app_confbridge.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/apps/app_confbridge.c (original)
+++ team/mmichelson/pool_shark2/apps/app_confbridge.c Mon Feb 18 11:03:41 2013
@@ -2157,10 +2157,10 @@
 	struct conference_bridge *bridge = NULL;
 	char *res = NULL;
 	int wordlen = strlen(word);
-	struct ao2_iterator i;
-
-	i = ao2_iterator_init(conference_bridges, 0);
-	while ((bridge = ao2_iterator_next(&i))) {
+	struct ao2_iterator iter;
+
+	iter = ao2_iterator_init(conference_bridges, 0);
+	while ((bridge = ao2_iterator_next(&iter))) {
 		if (!strncasecmp(bridge->name, word, wordlen) && ++which > state) {
 			res = ast_strdup(bridge->name);
 			ao2_ref(bridge, -1);
@@ -2168,7 +2168,7 @@
 		}
 		ao2_ref(bridge, -1);
 	}
-	ao2_iterator_destroy(&i);
+	ao2_iterator_destroy(&iter);
 
 	return res;
 }
@@ -2236,10 +2236,7 @@
 
 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct ao2_iterator i;
-	struct conference_bridge *bridge = NULL;
-	struct conference_bridge tmp;
-	struct conference_bridge_user *participant = NULL;
+	struct conference_bridge *bridge;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -2256,18 +2253,23 @@
 	}
 
 	if (a->argc == 2) {
+		struct ao2_iterator iter;
+
 		ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
 		ast_cli(a->fd, "================================ ====== ====== ========\n");
-		i = ao2_iterator_init(conference_bridges, 0);
-		while ((bridge = ao2_iterator_next(&i))) {
+		iter = ao2_iterator_init(conference_bridges, 0);
+		while ((bridge = ao2_iterator_next(&iter))) {
 			ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->activeusers + bridge->waitingusers, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
 			ao2_ref(bridge, -1);
 		}
-		ao2_iterator_destroy(&i);
+		ao2_iterator_destroy(&iter);
 		return CLI_SUCCESS;
 	}
 
 	if (a->argc == 3) {
+		struct conference_bridge_user *participant;
+		struct conference_bridge tmp;
+
 		ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
 		bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
 		if (!bridge) {
@@ -2657,7 +2659,7 @@
 {
 	const char *actionid = astman_get_header(m, "ActionID");
 	struct conference_bridge *bridge = NULL;
-	struct ao2_iterator i;
+	struct ao2_iterator iter;
 	char id_text[512] = "";
 	int totalitems = 0;
 
@@ -2673,8 +2675,8 @@
 	astman_send_listack(s, m, "Confbridge conferences will follow", "start");
 
 	/* Traverse the conference list */
-	i = ao2_iterator_init(conference_bridges, 0);
-	while ((bridge = ao2_iterator_next(&i))) {
+	iter = ao2_iterator_init(conference_bridges, 0);
+	while ((bridge = ao2_iterator_next(&iter))) {
 		totalitems++;
 
 		ao2_lock(bridge);
@@ -2695,7 +2697,7 @@
 
 		ao2_ref(bridge, -1);
 	}
-	ao2_iterator_destroy(&i);
+	ao2_iterator_destroy(&iter);
 
 	/* Send final confirmation */
 	astman_append(s,

Modified: team/mmichelson/pool_shark2/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/channels/chan_gulp.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/channels/chan_gulp.c (original)
+++ team/mmichelson/pool_shark2/channels/chan_gulp.c Mon Feb 18 11:03:41 2013
@@ -108,10 +108,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 */
@@ -157,11 +166,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);
 	}
@@ -217,16 +221,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);
@@ -257,8 +261,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:
@@ -450,7 +454,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:
@@ -474,7 +480,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:
@@ -865,11 +873,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/mmichelson/pool_shark2/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/channels/chan_sip.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/channels/chan_sip.c (original)
+++ team/mmichelson/pool_shark2/channels/chan_sip.c Mon Feb 18 11:03:41 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/mmichelson/pool_shark2/configs/res_sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/configs/res_sip.conf.sample?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/configs/res_sip.conf.sample (original)
+++ team/mmichelson/pool_shark2/configs/res_sip.conf.sample Mon Feb 18 11:03:41 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/mmichelson/pool_shark2/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/include/asterisk/res_sip.h?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/include/asterisk/res_sip.h (original)
+++ team/mmichelson/pool_shark2/include/asterisk/res_sip.h Mon Feb 18 11:03:41 2013
@@ -213,6 +213,8 @@
 		AST_STRING_FIELD(context);
 		/*! Name of an explicit transport to use */
 		AST_STRING_FIELD(transport);
+                /*! 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;
@@ -230,12 +232,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. */

Modified: team/mmichelson/pool_shark2/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/include/asterisk/res_sip_session.h?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/include/asterisk/res_sip_session.h (original)
+++ team/mmichelson/pool_shark2/include/asterisk/res_sip_session.h Mon Feb 18 11:03:41 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];
 	/* Serializer for tasks relating to this SIP session */
 	struct ast_taskprocessor *serializer;
 };
@@ -158,6 +172,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
@@ -168,6 +191,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, 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/mmichelson/pool_shark2/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/include/asterisk/sorcery.h?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/include/asterisk/sorcery.h (original)
+++ team/mmichelson/pool_shark2/include/asterisk/sorcery.h Mon Feb 18 11:03:41 2013
@@ -202,6 +202,9 @@
 	/*! \brief Callback for retrieving an object using an id */
 	void *(*retrieve_id)(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id);
 
+	/*! \brief Callback for retrieving multiple objects using a regex on their id */
+	void (*retrieve_regex)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
+
 	/*! \brief Optional callback for retrieving an object using fields */
 	void *(*retrieve_fields)(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields);
 
@@ -554,6 +557,20 @@
 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields);
 
 /*!
+ * \brief Retrieve multiple objects using a regular expression on their id
+ *
+ * \param sorcery Pointer to a sorcery structure
+ * \param type Type of object to retrieve
+ * \param regex Regular expression
+ *
+ * \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);
+
+/*!
  * \brief Update an object
  *
  * \param sorcery Pointer to a sorcery structure

Modified: team/mmichelson/pool_shark2/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/main/sorcery.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/main/sorcery.c (original)
+++ team/mmichelson/pool_shark2/main/sorcery.c Mon Feb 18 11:03:41 2013
@@ -960,6 +960,30 @@
 	return object;
 }
 
+struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
+{
+	RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+	struct ao2_container *objects;
+	struct ao2_iterator i;
+	struct ast_sorcery_object_wizard *wizard;
+
+	if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
+		return NULL;
+	}
+
+	i = ao2_iterator_init(object_type->wizards, 0);
+	for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
+		if (!wizard->wizard->retrieve_regex) {
+			continue;
+		}
+
+		wizard->wizard->retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
+	}
+	ao2_iterator_destroy(&i);
+
+	return objects;
+}
+
 /*! \brief Internal function which returns if the wizard has created the object */
 static int sorcery_wizard_create(void *obj, void *arg, int flags)
 {

Modified: team/mmichelson/pool_shark2/res/res_sip/sip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/res/res_sip/sip_configuration.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/res/res_sip/sip_configuration.c (original)
+++ team/mmichelson/pool_shark2/res/res_sip/sip_configuration.c Mon Feb 18 11:03:41 2013
@@ -277,7 +277,11 @@
 	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", "host", "", host_handler, NULL, 0, 0);
 	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", "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/mmichelson/pool_shark2/res/res_sip_sdp_audio.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/pool_shark2/res/res_sip_sdp_audio.c?view=diff&rev=381641&r1=381640&r2=381641
==============================================================================
--- team/mmichelson/pool_shark2/res/res_sip_sdp_audio.c (original)
+++ team/mmichelson/pool_shark2/res/res_sip_sdp_audio.c Mon Feb 18 11:03:41 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, 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,137 +92,56 @@
 		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, struct pjmedia_sdp_session *sdp)
 {
+	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 };
 	pj_pool_t *pool = session->inv_session->pool_active;
 	pjmedia_sdp_media *media;
 	struct ast_sockaddr addr;
@@ -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);
+
+		ast_rtp_codecs_payloads_destroy(&codecs);
+		return -1;
+	}
+
+	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session->media[AST_SIP_MEDIA_AUDIO].rtp),
+				     session->media[AST_SIP_MEDIA_AUDIO].rtp);
+
+	/* 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_format_copy(ast_channel_rawwriteformat(session->channel), &fmt);
+	ast_format_copy(ast_channel_rawreadformat(session->channel), &fmt);
+	ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
+	ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+
+	ast_channel_set_fd(session->channel, 0, ast_rtp_instance_fd(session->media[AST_SIP_MEDIA_AUDIO].rtp, 0));
+	ast_channel_set_fd(session->channel, 1, ast_rtp_instance_fd(session->media[AST_SIP_MEDIA_AUDIO].rtp, 1));
+
+	if (session->media[AST_SIP_MEDIA_AUDIO].held && (!ast_sockaddr_isnull(addrs) ||

[... 538 lines stripped ...]



More information about the asterisk-commits mailing list