[svn-commits] mjordan: branch mjordan/12-messaging r418441 - in /team/mjordan/12-messaging:...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Jul 12 11:28:00 CDT 2014


Author: mjordan
Date: Sat Jul 12 11:27:56 2014
New Revision: 418441

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=418441
Log:
Add initial stuff

Added:
    team/mjordan/12-messaging/tests/test_message.c   (with props)
Modified:
    team/mjordan/12-messaging/channels/chan_iax2.c
    team/mjordan/12-messaging/channels/chan_motif.c
    team/mjordan/12-messaging/channels/chan_pjsip.c
    team/mjordan/12-messaging/channels/chan_sip.c
    team/mjordan/12-messaging/include/asterisk/channel.h
    team/mjordan/12-messaging/include/asterisk/endpoints.h
    team/mjordan/12-messaging/include/asterisk/json.h
    team/mjordan/12-messaging/include/asterisk/manager.h
    team/mjordan/12-messaging/include/asterisk/message.h
    team/mjordan/12-messaging/include/asterisk/vector.h
    team/mjordan/12-messaging/include/asterisk/xmpp.h
    team/mjordan/12-messaging/main/channel.c
    team/mjordan/12-messaging/main/channel_internal_api.c
    team/mjordan/12-messaging/main/endpoints.c
    team/mjordan/12-messaging/main/json.c
    team/mjordan/12-messaging/main/message.c
    team/mjordan/12-messaging/res/ari/ari_model_validators.c
    team/mjordan/12-messaging/res/ari/ari_model_validators.h
    team/mjordan/12-messaging/res/ari/resource_applications.h
    team/mjordan/12-messaging/res/ari/resource_channels.c
    team/mjordan/12-messaging/res/ari/resource_endpoints.c
    team/mjordan/12-messaging/res/ari/resource_endpoints.h
    team/mjordan/12-messaging/res/res_ari.c
    team/mjordan/12-messaging/res/res_ari_endpoints.c
    team/mjordan/12-messaging/res/res_pjsip_messaging.c
    team/mjordan/12-messaging/res/res_stasis.c
    team/mjordan/12-messaging/res/res_xmpp.c
    team/mjordan/12-messaging/res/stasis/app.c
    team/mjordan/12-messaging/rest-api/api-docs/applications.json
    team/mjordan/12-messaging/rest-api/api-docs/endpoints.json
    team/mjordan/12-messaging/rest-api/api-docs/events.json

Modified: team/mjordan/12-messaging/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/channels/chan_iax2.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/channels/chan_iax2.c (original)
+++ team/mjordan/12-messaging/channels/chan_iax2.c Sat Jul 12 11:27:56 2014
@@ -5777,20 +5777,38 @@
 /*! \brief  Create new call, interface with the PBX core */
 static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capability, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, unsigned int cachable)
 {
-	struct ast_channel *tmp;
+	struct ast_channel *tmp = NULL;
 	struct chan_iax2_pvt *i;
+	struct iax2_peer *peer;
 	struct ast_variable *v = NULL;
 	struct ast_format tmpfmt;
 	struct ast_callid *callid;
+	char *peer_name = NULL;
 
 	if (!(i = iaxs[callno])) {
 		ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
 		return NULL;
 	}
 
-	/* Don't hold call lock */
+	if (!ast_strlen_zero(i->peer)) {
+		peer_name = ast_strdupa(i->peer);
+	}
+
+	/* Don't hold call lock while making a channel or looking up a peer */
 	ast_mutex_unlock(&iaxsl[callno]);
-	tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
+
+	if (!ast_strlen_zero(peer_name)) {
+		peer = find_peer(peer_name, 1);
+		if (peer && peer->endpoint) {
+			tmp = ast_channel_alloc_with_endpoint(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, peer->endpoint, "IAX2/%s-%d", i->host, i->callno);
+		}
+		ao2_cleanup(peer);
+	}
+
+	if (!tmp) {
+		tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
+	}
+
 	ast_mutex_lock(&iaxsl[callno]);
 	if (i != iaxs[callno]) {
 		if (tmp) {

Modified: team/mjordan/12-messaging/channels/chan_motif.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/channels/chan_motif.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/channels/chan_motif.c (original)
+++ team/mjordan/12-messaging/channels/chan_motif.c Sat Jul 12 11:27:56 2014
@@ -76,6 +76,7 @@
 #include "asterisk/astobj.h"
 #include "asterisk/abstract_jb.h"
 #include "asterisk/xmpp.h"
+#include "asterisk/endpoints.h"
 #include "asterisk/stasis_channels.h"
 
 /*** DOCUMENTATION
@@ -782,7 +783,7 @@
 		return NULL;
 	}
 
-	if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
+	if (!(chan = ast_channel_alloc_with_endpoint(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, endpoint->connection->endpoint, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
 		return NULL;
 	}
 

Modified: team/mjordan/12-messaging/channels/chan_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/channels/chan_pjsip.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/channels/chan_pjsip.c (original)
+++ team/mjordan/12-messaging/channels/chan_pjsip.c Sat Jul 12 11:27:56 2014
@@ -364,7 +364,7 @@
 		return NULL;
 	}
 
-	if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), "", "", "", assignedids, requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
+	if (!(chan = ast_channel_alloc_with_endpoint(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), "", "", "", assignedids, requestor, 0, session->endpoint->persistent, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
 		(unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) {
 		return NULL;
 	}
@@ -441,8 +441,6 @@
 	if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
 		ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan));
 	}
-
-	ast_endpoint_add_channel(session->endpoint->persistent, chan);
 
 	return chan;
 }

Modified: team/mjordan/12-messaging/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/channels/chan_sip.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/channels/chan_sip.c (original)
+++ team/mjordan/12-messaging/channels/chan_sip.c Sat Jul 12 11:27:56 2014
@@ -8079,23 +8079,19 @@
 			my_name = ast_strdupa(i->fromdomain);
 		}
 
+		/* Don't hold a sip pvt lock while we allocate a channel */
 		sip_pvt_unlock(i);
-		/* Don't hold a sip pvt lock while we allocate a channel */
-		tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
+
+		if (i->relatedpeer && i->relatedpeer->endpoint) {
+			tmp = ast_channel_alloc_with_endpoint(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, i->relatedpeer->endpoint, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
+		} else {
+			tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
+		}
 	}
 	if (!tmp) {
 		ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n");
 		sip_pvt_lock(i);
 		return NULL;
-	}
-
-	if (i->relatedpeer && i->relatedpeer->endpoint) {
-		if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) {
-			ast_channel_unlock(tmp);
-			ast_channel_unref(tmp);
-			sip_pvt_lock(i);
-			return NULL;
-		}
 	}
 
 	ast_channel_stage_snapshot(tmp);
@@ -19139,25 +19135,6 @@
 		ast_string_field_set(p, context, sip_cfg.messagecontext);
 	}
 
-	switch (get_destination(p, NULL, NULL)) {
-	case SIP_GET_DEST_REFUSED:
-		/* Okay to send 403 since this is after auth processing */
-		transmit_response(p, "403 Forbidden", req);
-		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		return;
-	case SIP_GET_DEST_INVALID_URI:
-		transmit_response(p, "416 Unsupported URI Scheme", req);
-		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		return;
-	case SIP_GET_DEST_EXTEN_NOT_FOUND:
-	case SIP_GET_DEST_EXTEN_MATCHMORE:
-		transmit_response(p, "404 Not Found", req);
-		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		return;
-	case SIP_GET_DEST_EXTEN_FOUND:
-		break;
-	}
-
 	if (!(msg = ast_msg_alloc())) {
 		transmit_response(p, "500 Internal Server Error", req);
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -19182,7 +19159,9 @@
 	res |= ast_msg_set_context(msg, "%s", p->context);
 
 	res |= ast_msg_set_var(msg, "SIP_RECVADDR", ast_sockaddr_stringify(&p->recv));
+	res |= ast_msg_set_tech(msg, "%s", "SIP");
 	if (!ast_strlen_zero(p->peername)) {
+		res |= ast_msg_set_endpoint(msg, "%s", p->peername);
 		res |= ast_msg_set_var(msg, "SIP_PEERNAME", p->peername);
 	}
 
@@ -19195,12 +19174,38 @@
 	if (res) {
 		ast_msg_destroy(msg);
 		transmit_response(p, "500 Internal Server Error", req);
-	} else {
+		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+		return;
+	}
+
+	if (ast_msg_has_destination(msg)) {
 		ast_msg_queue(msg);
 		transmit_response(p, "202 Accepted", req);
-	}
-
+		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+		return;
+	}
+
+	/* Find a specific error cause to send */
+	switch (get_destination(p, NULL, NULL)) {
+	case SIP_GET_DEST_REFUSED:
+		/* Okay to send 403 since this is after auth processing */
+		transmit_response(p, "403 Forbidden", req);
+		break;
+	case SIP_GET_DEST_INVALID_URI:
+		transmit_response(p, "416 Unsupported URI Scheme", req);
+		break;
+	case SIP_GET_DEST_EXTEN_NOT_FOUND:
+	case SIP_GET_DEST_EXTEN_MATCHMORE:
+		transmit_response(p, "404 Not Found", req);
+		break;
+	case SIP_GET_DEST_EXTEN_FOUND:
+		/* We should have sent the message already! */
+		ast_assert(0);
+		transmit_response(p, "500 Internal Server Error", req);
+		break;
+	}
 	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+	ast_msg_destroy(msg);
 }
 
 /*! \brief  CLI Command to show calls within limits set by call_limit */

Modified: team/mjordan/12-messaging/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/channel.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/channel.h (original)
+++ team/mjordan/12-messaging/include/asterisk/channel.h Sat Jul 12 11:27:56 2014
@@ -1158,11 +1158,12 @@
  *       and "default" context.
  * \note Since 12.0.0 this function returns with the newly created channel locked.
  */
-struct ast_channel * attribute_malloc __attribute__((format(printf, 14, 15)))
+struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16)))
 	__ast_channel_alloc(int needqueue, int state, const char *cid_num,
 		const char *cid_name, const char *acctcode,
 		const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
 		const struct ast_channel *requestor, enum ama_flags amaflag,
+		struct ast_endpoint *endpoint,
 		const char *file, int line, const char *function,
 		const char *name_fmt, ...);
 
@@ -1178,8 +1179,13 @@
  * \note Since 12.0.0 this function returns with the newly created channel locked.
  */
 #define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, ...) \
-	__ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, \
+	__ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, NULL, \
 		__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+
+#define ast_channel_alloc_with_endpoint(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, endpoint, ...) \
+	__ast_channel_alloc((needqueue), (state), (cid_num), (cid_name), (acctcode), (exten), (context), (assignedids), (requestor), (amaflag), (endpoint), \
+		__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+
 
 #if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
 /*!

Modified: team/mjordan/12-messaging/include/asterisk/endpoints.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/endpoints.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/endpoints.h (original)
+++ team/mjordan/12-messaging/include/asterisk/endpoints.h Sat Jul 12 11:27:56 2014
@@ -77,11 +77,17 @@
 struct ast_endpoint;
 
 /*!
- * \brief Finds the endpoint with the given tech/resource id.
+ * \brief Finds the endpoint with the given tech[/resource] id.
  *
  * Endpoints are refcounted, so ao2_cleanup() when you're done.
  *
- * \param id Tech/resource id to look for.
+ * \note The resource portion of an ID is optional. If not provided,
+ *       an aggregate endpoint for the entire technology is returned.
+ *       These endpoints must not be modified, but can be subscribed
+ *       to in order to receive updates for all endpoints of a given
+ *       technology.
+ *
+ * \param id Tech[/resource] id to look for.
  * \return Associated endpoint.
  * \return \c NULL if not found.
  *
@@ -131,6 +137,9 @@
  *
  * This is unique for the endpoint's technology, and immutable.
  *
+ * \note If the endpoint being queried is a technology aggregate
+ *       endpoint, this will be an empty string.
+ *
  * \param endpoint The endpoint.
  * \return Resource name of the endpoint.
  * \return \c NULL if endpoint is \c NULL.

Modified: team/mjordan/12-messaging/include/asterisk/json.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/json.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/json.h (original)
+++ team/mjordan/12-messaging/include/asterisk/json.h Sat Jul 12 11:27:56 2014
@@ -462,7 +462,7 @@
  * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param array JSON array to modify.
- * \param value New JSON value to store at the end of \a array.
+ * \param value New JSON value to store at the fend of \a array.
  * \return 0 on success.
  * \return -1 on error.
  */
@@ -1010,6 +1010,8 @@
  */
 struct ast_json *ast_json_party_id(struct ast_party_id *party);
 
+int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
+
 /*!@}*/
 
 #endif /* _ASTERISK_JSON_H */

Modified: team/mjordan/12-messaging/include/asterisk/manager.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/manager.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/manager.h (original)
+++ team/mjordan/12-messaging/include/asterisk/manager.h Sat Jul 12 11:27:56 2014
@@ -94,8 +94,16 @@
 /*! \brief Export manager structures */
 #define AST_MAX_MANHEADERS 128
 
-/*! \brief Manager Helper Function */
-typedef int (*manager_hook_t)(int, const char *, char *);
+/*! \brief Manager Helper Function
+ *
+ * \param category The class authorization category of the event
+ * \param event The name of the event being raised
+ * \param body The body of the event
+ *
+ * \retval 0 Success
+ * \retval non-zero Error
+ */
+typedef int (*manager_hook_t)(int category, const char *event, char *body);
 
 struct manager_custom_hook {
 	/*! Identifier */

Modified: team/mjordan/12-messaging/include/asterisk/message.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/message.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/message.h (original)
+++ team/mjordan/12-messaging/include/asterisk/message.h Sat Jul 12 11:27:56 2014
@@ -25,8 +25,9 @@
  *
  * The purpose of this API is to provide support for text messages that
  * are not session based.  The messages are passed into the Asterisk core
- * to be routed through the dialplan and potentially sent back out through
- * a message technology that has been registered through this API.
+ * to be routed through the dialplan or another interface and potentially
+ * sent back out through a message technology that has been registered
+ * through this API.
  */
 
 #ifndef __AST_MESSAGE_H__
@@ -91,6 +92,64 @@
 int ast_msg_tech_unregister(const struct ast_msg_tech *tech);
 
 /*!
+ * \brief An external processor of received messages
+ * \since 12.5.0
+ */
+struct ast_msg_handler {
+	/*!
+	 * \brief Name of the message handler
+	 */
+	const char *name;
+
+	/*!
+	 * \brief The function callback that will handle the message
+	 *
+	 * \param msg The message to handle
+	 *
+	 * \retval 0 The handler processed the message successfull
+	 * \retval non-zero The handler passed or could not process the message
+	 */
+	int (* const handle_msg)(struct ast_msg *msg);
+
+	/*!
+	 * \brief Return whether or not the message has a valid destination
+	 *
+	 * A message may be delivered to the dialplan and/or other locations,
+	 * depending on whether or not other handlers have been registered. This
+	 * function is called by the message core to determine if any handler can
+	 * process a message.
+	 *
+	 * \param msg The message to inspect
+	 *
+	 * \retval 0 The message does not have a valid destination
+	 * \retval 1 The message has a valid destination
+	 */
+	int (* const has_destination)(const struct ast_msg *msg);
+};
+
+/*!
+ * \brief Register a \c ast_msg_handler
+ * \since 12.5.0
+ *
+ * \param handler The handler to register
+ *
+ * \retval 0 Success
+ * \retval non-zero Error
+ */
+int ast_msg_handler_register(const struct ast_msg_handler *handler);
+
+/*!
+ * \brief Unregister a \c ast_msg_handler
+ * \since 12.5.0
+ *
+ * \param handler The handler to unregister
+ *
+ * \retval 0 Success
+ * \retval non-zero Error
+ */
+int ast_msg_handler_unregister(const struct ast_msg_handler *handler);
+
+/*!
  * \brief Allocate a message.
  *
  * Allocate a message for the purposes of passing it into the Asterisk core
@@ -162,6 +221,12 @@
  */
 int __attribute__((format(printf, 2, 3)))
 		ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...);
+
+int __attribute__((format(printf, 2, 3)))
+		ast_msg_set_tech(struct ast_msg *msg, const char *fmt, ...);
+
+int __attribute__((format(printf, 2, 3)))
+		ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt, ...);
 	
 /*!
  * \brief Set a variable on the message going to the dialplan.
@@ -207,6 +272,42 @@
  * \return The body of the messsage, encoded in UTF-8.
  */
 const char *ast_msg_get_body(const struct ast_msg *msg);
+
+/*!
+ * \brief Retrieve the source of this message
+ * \since 12.5.0
+ *
+ * \param msg The message to get the soure from
+ *
+ * \retval The source of the message
+ * \retval NULL or empty string if the message has no source
+ */
+const char *ast_msg_get_from(const struct ast_msg *msg);
+
+/*!
+ * \brief Retrieve the destination of this message
+ * \since 12.5.0
+ *
+ * \param msg The message to get the destination from
+ *
+ * \retval The destination of the message
+ * \retval NULL or empty string if the message has no destination
+ */
+const char *ast_msg_get_to(const struct ast_msg *msg);
+
+const char *ast_msg_get_tech(const struct ast_msg *msg);
+const char *ast_msg_get_endpoint(const struct ast_msg *msg);
+
+/*!
+ * \brief Determine if a particular message has a destination via some handler
+ * \since 12.5.0
+ *
+ * \param msg The message to check
+ *
+ * \retval 0 if the message has no handler that can find a destination
+ * \retval 1 if the message has a handler that can find a destination
+ */
+int ast_msg_has_destination(const struct ast_msg *msg);
 
 /*!
  * \brief Queue a message for routing through the dialplan.

Modified: team/mjordan/12-messaging/include/asterisk/vector.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/vector.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/vector.h (original)
+++ team/mjordan/12-messaging/include/asterisk/vector.h Sat Jul 12 11:27:56 2014
@@ -61,7 +61,7 @@
 #define AST_VECTOR_INIT(vec, size) ({					\
 	size_t __size = (size);						\
 	size_t alloc_size = __size * sizeof(*((vec)->elems));		\
-	(vec)->elems = alloc_size ? ast_malloc(alloc_size) : NULL;	\
+	(vec)->elems = alloc_size ? ast_calloc(1, alloc_size) : NULL;	\
 	(vec)->current = 0;						\
 	if ((vec)->elems) {						\
 		(vec)->max = __size;					\
@@ -116,6 +116,48 @@
 })
 
 /*!
+ * \brief Insert an element at a specific position in a vector, growing the vector if needed.
+ *
+ * \param vec Vector to insert into.
+ * \param idx Position to insert at.
+ * \param elem Element to insert.
+ *
+ * \return 0 on success.
+ * \return Non-zero on failure.
+ *
+ * \warning This macro will overwrite anything already present at the position provided.
+ *
+ * \warning Use of this macro with the expectation that the element will remain at the provided
+ * index means you can not use the UNORDERED assortment of macros. These macros alter the ordering
+ * of the vector itself.
+ */
+#define AST_VECTOR_INSERT(vec, idx, elem) ({					\
+	int res = 0;												\
+	do {														\
+		if (((idx) + 1) > (vec)->max) {							\
+			size_t new_max = ((idx) + 1) * 2;					\
+			typeof((vec)->elems) new_elems = ast_calloc(1,		\
+				new_max * sizeof(*new_elems));					\
+			if (new_elems) {									\
+				memcpy(new_elems, (vec)->elems,					\
+					(vec)->current * sizeof(*new_elems));		\
+				ast_free((vec)->elems);							\
+				(vec)->elems = new_elems;						\
+				(vec)->max = new_max;							\
+			} else {											\
+				res = -1;										\
+				break;											\
+			}													\
+		}														\
+		(vec)->elems[(idx)] = (elem);							\
+		if (((idx) + 1) > (vec)->current) {						\
+			(vec)->current = (idx) + 1;							\
+		}														\
+	} while(0);													\
+	res;														\
+})
+
+/*!
  * \brief Remove an element from a vector by index.
  *
  * Note that elements in the vector may be reordered, so that the remove can

Modified: team/mjordan/12-messaging/include/asterisk/xmpp.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/include/asterisk/xmpp.h?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/include/asterisk/xmpp.h (original)
+++ team/mjordan/12-messaging/include/asterisk/xmpp.h Sat Jul 12 11:27:56 2014
@@ -106,6 +106,8 @@
 	AST_LIST_ENTRY(ast_xmpp_message) list; /*!< Linked list information */
 };
 
+struct ast_endpoint;
+
 /*! \brief XMPP Buddy */
 struct ast_xmpp_buddy {
 	char id[XMPP_MAX_JIDLEN];        /*!< JID of the buddy */
@@ -116,9 +118,11 @@
 /*! \brief XMPP Client Connection */
 struct ast_xmpp_client {
 	AST_DECLARE_STRING_FIELDS(
-		AST_STRING_FIELD(name); /*!< Name of the client configuration */
+		/*! Name of the client configuration */
+		AST_STRING_FIELD(name);
 		);
-	char mid[6]; /* Message ID */
+	/*! Message ID */
+	char mid[6];
 	iksid *jid;
 	iksparser *parser;
 	iksfilter *filter;
@@ -134,9 +138,14 @@
 	AST_LIST_HEAD(, ast_xmpp_message) messages;
 	pthread_t thread;
 	int timeout;
-	unsigned int reconnect:1; /*!< Reconnect this client */
-	struct stasis_subscription *mwi_sub; /*!< If distributing event information the MWI subscription */
-	struct stasis_subscription *device_state_sub; /*!< If distributing event information the device state subscription */
+	/*! Reconnect this client */
+	unsigned int reconnect:1;
+	/*! If distributing event information the MWI subscription */
+	struct stasis_subscription *mwi_sub;
+	/*! If distributing event information the device state subscription */
+	struct stasis_subscription *device_state_sub;
+	/*! The endpoint associated with this client */
+	struct ast_endpoint *endpoint;
 };
 
 /*!

Modified: team/mjordan/12-messaging/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/main/channel.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/main/channel.c (original)
+++ team/mjordan/12-messaging/main/channel.c Sat Jul 12 11:27:56 2014
@@ -855,10 +855,11 @@
 static void ast_dummy_channel_destructor(void *obj);
 
 /*! \brief Create a new channel structure */
-static struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 0)))
+static struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 0)))
 __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char *cid_name,
 		       const char *acctcode, const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
-		       const struct ast_channel *requestor, enum ama_flags amaflag, const char *file, int line,
+		       const struct ast_channel *requestor, enum ama_flags amaflag, struct ast_endpoint *endpoint,
+		       const char *file, int line,
 		       const char *function, const char *name_fmt, va_list ap)
 {
 	struct ast_channel *tmp;
@@ -1028,6 +1029,10 @@
 
 	ao2_link(channels, tmp);
 
+	if (endpoint) {
+		ast_endpoint_add_channel(endpoint, tmp);
+	}
+
 	/*
 	 * And now, since the channel structure is built, and has its name, let
 	 * the world know of its existance
@@ -1040,6 +1045,7 @@
 					const char *cid_name, const char *acctcode,
 					const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
 					const struct ast_channel *requestor, enum ama_flags amaflag,
+					struct ast_endpoint *endpoint,
 					const char *file, int line, const char *function,
 					const char *name_fmt, ...)
 {
@@ -1048,7 +1054,7 @@
 
 	va_start(ap, name_fmt);
 	result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context,
-					assignedids, requestor, amaflag, file, line, function, name_fmt, ap);
+					assignedids, requestor, amaflag, endpoint, file, line, function, name_fmt, ap);
 	va_end(ap);
 
 	return result;

Modified: team/mjordan/12-messaging/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/main/channel_internal_api.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/main/channel_internal_api.c (original)
+++ team/mjordan/12-messaging/main/channel_internal_api.c Sat Jul 12 11:27:56 2014
@@ -219,6 +219,7 @@
 	struct timeval sending_dtmf_tv;		/*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
 	struct stasis_cp_single *topics;		/*!< Topic for all channel's events */
 	struct stasis_forward *endpoint_forward;	/*!< Subscription for event forwarding to endpoint's topic */
+	struct stasis_forward *endpoint_cache_forward; /*!< Subscription for cache updates to endpoint's topic */
 };
 
 /*! \brief The monotonically increasing integer counter for channel uniqueids */
@@ -1502,6 +1503,7 @@
 	ast_string_field_free_memory(chan);
 
 	chan->endpoint_forward = stasis_forward_cancel(chan->endpoint_forward);
+	chan->endpoint_cache_forward = stasis_forward_cancel(chan->endpoint_cache_forward);
 
 	stasis_cp_single_unsubscribe(chan->topics);
 	chan->topics = NULL;
@@ -1544,8 +1546,14 @@
 	chan->endpoint_forward =
 		stasis_forward_all(ast_channel_topic(chan),
 			ast_endpoint_topic(endpoint));
-
-	if (chan->endpoint_forward == NULL) {
+	if (!chan->endpoint_forward) {
+		return -1;
+	}
+
+	chan->endpoint_cache_forward = stasis_forward_all(ast_channel_topic_cached(chan),
+		ast_endpoint_topic(endpoint));
+	if (!chan->endpoint_cache_forward) {
+		chan->endpoint_forward = stasis_forward_cancel(chan->endpoint_forward);
 		return -1;
 	}
 

Modified: team/mjordan/12-messaging/main/endpoints.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/main/endpoints.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/main/endpoints.c (original)
+++ team/mjordan/12-messaging/main/endpoints.c Sat Jul 12 11:27:56 2014
@@ -46,7 +46,12 @@
 /*! Buckets for endpoint hash. Keep it prime! */
 #define ENDPOINT_BUCKETS 127
 
+/*! Buckets for technology endpoints. */
+#define TECH_ENDPOINT_BUCKETS 11
+
 static struct ao2_container *endpoints;
+
+static struct ao2_container *tech_endpoints;
 
 struct ast_endpoint {
 	AST_DECLARE_STRING_FIELDS(
@@ -69,6 +74,8 @@
 	struct stasis_message_router *router;
 	/*! ast_str_container of channels associated with this endpoint */
 	struct ao2_container *channel_ids;
+	/*! Forwarding subscription from an endpoint to its tech endpoint */
+	struct stasis_forward *tech_forward;
 };
 
 static int endpoint_hash(const void *obj, int flags)
@@ -121,7 +128,13 @@
 
 struct ast_endpoint *ast_endpoint_find_by_id(const char *id)
 {
-	return ao2_find(endpoints, id, OBJ_KEY);
+	struct ast_endpoint *endpoint = ao2_find(endpoints, id, OBJ_KEY);
+
+	if (!endpoint) {
+		endpoint = ao2_find(tech_endpoints, id, OBJ_KEY);
+	}
+
+	return endpoint;
 }
 
 struct stasis_topic *ast_endpoint_topic(struct ast_endpoint *endpoint)
@@ -181,6 +194,8 @@
 	ao2_cleanup(endpoint->router);
 	endpoint->router = NULL;
 
+	endpoint->tech_forward = stasis_forward_cancel(endpoint->tech_forward);
+
 	stasis_cp_single_unsubscribe(endpoint->topics);
 	endpoint->topics = NULL;
 
@@ -196,6 +211,7 @@
 {
 	ast_assert(chan != NULL);
 	ast_assert(endpoint != NULL);
+	ast_assert(!ast_strlen_zero(endpoint->resource));
 
 	ast_channel_forward_endpoint(chan, endpoint);
 
@@ -242,19 +258,21 @@
 	}
 }
 
-struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource)
+static struct ast_endpoint *endpoint_internal_create(const char *tech, const char *resource)
 {
 	RAII_VAR(struct ast_endpoint *, endpoint, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_endpoint *, tech_endpoint, NULL, ao2_cleanup);
 	int r = 0;
 
-	if (ast_strlen_zero(tech)) {
-		ast_log(LOG_ERROR, "Endpoint tech cannot be empty\n");
-		return NULL;
-	}
-
-	if (ast_strlen_zero(resource)) {
-		ast_log(LOG_ERROR, "Endpoint resource cannot be empty\n");
-		return NULL;
+	/* Get/create the technology endpoint */
+	if (!ast_strlen_zero(resource)) {
+		tech_endpoint = ao2_find(tech_endpoints, tech, OBJ_KEY);
+		if (!tech_endpoint) {
+			tech_endpoint = endpoint_internal_create(tech, NULL);
+			if (!tech_endpoint) {
+				return NULL;
+			}
+		}
 	}
 
 	endpoint = ao2_alloc(sizeof(*endpoint), endpoint_dtor);
@@ -268,10 +286,12 @@
 	if (ast_string_field_init(endpoint, 80) != 0) {
 		return NULL;
 	}
-
 	ast_string_field_set(endpoint, tech, tech);
-	ast_string_field_set(endpoint, resource, resource);
-	ast_string_field_build(endpoint, id, "%s/%s", tech, resource);
+	ast_string_field_set(endpoint, resource, S_OR(resource, ""));
+	ast_string_field_build(endpoint, id, "%s%s%s",
+		tech,
+		!ast_strlen_zero(resource) ? "/" : "",
+		S_OR(resource, ""));
 
 	/* All access to channel_ids should be covered by the endpoint's
 	 * lock; no extra lock needed. */
@@ -287,22 +307,45 @@
 		return NULL;
 	}
 
-	endpoint->router = stasis_message_router_create(ast_endpoint_topic(endpoint));
-	if (!endpoint->router) {
-		return NULL;
-	}
-	r |= stasis_message_router_add(endpoint->router,
-		stasis_cache_clear_type(), endpoint_cache_clear,
-		endpoint);
-	r |= stasis_message_router_set_default(endpoint->router,
-		endpoint_default, endpoint);
-
-	endpoint_publish_snapshot(endpoint);
-
-	ao2_link(endpoints, endpoint);
+	if (!ast_strlen_zero(resource)) {
+		endpoint->router = stasis_message_router_create(ast_endpoint_topic(endpoint));
+		if (!endpoint->router) {
+			return NULL;
+		}
+		r |= stasis_message_router_add(endpoint->router,
+			stasis_cache_clear_type(), endpoint_cache_clear,
+			endpoint);
+		r |= stasis_message_router_set_default(endpoint->router,
+			endpoint_default, endpoint);
+		if (r) {
+			return NULL;
+		}
+
+		endpoint->tech_forward = stasis_forward_all(stasis_cp_single_topic(endpoint->topics),
+			stasis_cp_single_topic(tech_endpoint->topics));
+		endpoint_publish_snapshot(endpoint);
+		ao2_link(endpoints, endpoint);
+	} else {
+		ao2_link(tech_endpoints, endpoint);
+	}
 
 	ao2_ref(endpoint, +1);
 	return endpoint;
+}
+
+struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource)
+{
+	if (ast_strlen_zero(tech)) {
+		ast_log(LOG_ERROR, "Endpoint tech cannot be empty\n");
+		return NULL;
+	}
+
+	if (ast_strlen_zero(resource)) {
+		ast_log(LOG_ERROR, "Endpoint resource cannot be empty\n");
+		return NULL;
+	}
+
+	return endpoint_internal_create(tech, resource);
 }
 
 static struct stasis_message *create_endpoint_snapshot_message(struct ast_endpoint *endpoint)
@@ -368,6 +411,8 @@
 	enum ast_endpoint_state state)
 {
 	ast_assert(endpoint != NULL);
+	ast_assert(!ast_strlen_zero(endpoint->resource));
+
 	ao2_lock(endpoint);
 	endpoint->state = state;
 	ao2_unlock(endpoint);
@@ -378,6 +423,8 @@
 	int max_channels)
 {
 	ast_assert(endpoint != NULL);
+	ast_assert(!ast_strlen_zero(endpoint->resource));
+
 	ao2_lock(endpoint);
 	endpoint->max_channels = max_channels;
 	ao2_unlock(endpoint);
@@ -407,6 +454,9 @@
 	void *obj;
 	SCOPED_AO2LOCK(lock, endpoint);
 
+	ast_assert(endpoint != NULL);
+	ast_assert(!ast_strlen_zero(endpoint->resource));
+
 	channel_count = ao2_container_count(endpoint->channel_ids);
 
 	snapshot = ao2_alloc(
@@ -440,6 +490,9 @@
 {
 	ao2_cleanup(endpoints);
 	endpoints = NULL;
+
+	ao2_cleanup(tech_endpoints);
+	tech_endpoints = NULL;
 }
 
 int ast_endpoint_init(void)
@@ -448,10 +501,15 @@
 
 	endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, endpoint_hash,
 		endpoint_cmp);
-
 	if (!endpoints) {
 		return -1;
 	}
 
+	tech_endpoints = ao2_container_alloc(TECH_ENDPOINT_BUCKETS, endpoint_hash,
+		endpoint_cmp);
+	if (!tech_endpoints) {
+		return -1;
+	}
+
 	return 0;
 }

Modified: team/mjordan/12-messaging/main/json.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/main/json.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/main/json.c (original)
+++ team/mjordan/12-messaging/main/json.c Sat Jul 12 11:27:56 2014
@@ -881,3 +881,28 @@
 
 	return ast_json_ref(json_party_id);
 }
+
+int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
+{
+	struct ast_json_iter *it_json_var;
+
+	*variables = NULL;
+
+	for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
+		 it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
+		struct ast_variable *new_var;
+
+		new_var = ast_variable_new(ast_json_object_iter_key(it_json_var),
+								   ast_json_string_get(ast_json_object_iter_value(it_json_var)),
+								   "");
+		if (!new_var) {
+			ast_variables_destroy(*variables);
+			*variables = NULL;
+			return 1;
+		}
+
+		ast_variable_list_append(variables, new_var);
+	}
+
+	return 0;
+}

Modified: team/mjordan/12-messaging/main/message.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-messaging/main/message.c?view=diff&rev=418441&r1=418440&r2=418441
==============================================================================
--- team/mjordan/12-messaging/main/message.c (original)
+++ team/mjordan/12-messaging/main/message.c Sat Jul 12 11:27:56 2014
@@ -39,6 +39,7 @@
 #include "asterisk/manager.h"
 #include "asterisk/strings.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/vector.h"
 #include "asterisk/app.h"
 #include "asterisk/taskprocessor.h"
 #include "asterisk/message.h"
@@ -201,7 +202,7 @@
 		AST_STRING_FIELD(name);
 		AST_STRING_FIELD(value);
 	);
-	unsigned int send:1; /* Whether to send out on outbound messages */
+	unsigned int send; /* Whether to send out on outbound messages */
 };
 
 AST_LIST_HEAD_NOLOCK(outhead, msg_data);
@@ -212,26 +213,29 @@
  * \todo Consider whether stringfields would be an appropriate optimization here.
  */
 struct ast_msg {
-	struct ast_str *to;
-	struct ast_str *from;
-	struct ast_str *body;
-	struct ast_str *context;
-	struct ast_str *exten;
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(to);
+		AST_STRING_FIELD(from);
+		AST_STRING_FIELD(body);
+		AST_STRING_FIELD(context);
+		AST_STRING_FIELD(exten);
+		AST_STRING_FIELD(endpoint);
+		AST_STRING_FIELD(tech);
+	);
 	struct ao2_container *vars;
 };
 
-struct ast_msg_tech_holder {
-	const struct ast_msg_tech *tech;
-	/*!
-	 * \brief A rwlock for this object
-	 *
-	 * a read/write lock must be used to protect the wrapper instead
-	 * of the ao2 lock. A rdlock must be held to read tech_holder->tech.
-	 */
-	ast_rwlock_t tech_lock;
-};
-
-static struct ao2_container *msg_techs;
+/*! \brief Lock for \c msg_techs vector */
+static ast_rwlock_t msg_techs_lock;
+
+/*! \brief Vector of message technologies */
+AST_VECTOR(, const struct ast_msg_tech *) msg_techs;
+
+/*! \brief Lock for \c msg_handlers vector */
+static ast_rwlock_t msg_handlers_lock;
+
+/*! \brief Vector of received message handlers */
+AST_VECTOR(, const struct ast_msg_handler *) msg_handlers;
 
 static struct ast_taskprocessor *msg_q_tp;
 
@@ -387,21 +391,7 @@
 {
 	struct ast_msg *msg = obj;
 
-	ast_free(msg->to);
-	msg->to = NULL;
-
-	ast_free(msg->from);
-	msg->from = NULL;
-
-	ast_free(msg->body);
-	msg->body = NULL;
-
-	ast_free(msg->context);
-	msg->context = NULL;
-
-	ast_free(msg->exten);
-	msg->exten = NULL;
-
+	ast_string_field_free_memory(msg);
 	ao2_ref(msg->vars, -1);
 }
 
@@ -413,27 +403,7 @@
 		return NULL;
 	}
 
-	if (!(msg->to = ast_str_create(32))) {
-		ao2_ref(msg, -1);
-		return NULL;
-	}
-
-	if (!(msg->from = ast_str_create(32))) {
-		ao2_ref(msg, -1);
-		return NULL;
-	}
-
-	if (!(msg->body = ast_str_create(128))) {
-		ao2_ref(msg, -1);
-		return NULL;
-	}
-
-	if (!(msg->context = ast_str_create(16))) {
-		ao2_ref(msg, -1);
-		return NULL;
-	}
-
-	if (!(msg->exten = ast_str_create(16))) {
+	if (ast_string_field_init(msg, 128)) {
 		ao2_ref(msg, -1);
 		return NULL;
 	}
@@ -442,8 +412,7 @@
 		ao2_ref(msg, -1);
 		return NULL;
 	}
-
-	ast_str_set(&msg->context, 0, "default");
+	ast_string_field_set(msg, context, "default");
 
 	return msg;
 }
@@ -457,73 +426,109 @@
 struct ast_msg *ast_msg_destroy(struct ast_msg *msg)
 {
 	ao2_ref(msg, -1);
-
 	return NULL;
 }
 
 int ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...)
 {
 	va_list ap;
-	int res;
 
 	va_start(ap, fmt);
-	res = ast_str_set_va(&msg->to, 0, fmt, ap);
+	ast_string_field_build_va(msg, to, fmt, ap);
 	va_end(ap);
 
-	return res < 0 ? -1 : 0;
+	return 0;
 }
 
 int ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...)
 {
 	va_list ap;
-	int res;
 
 	va_start(ap, fmt);
-	res = ast_str_set_va(&msg->from, 0, fmt, ap);
+	ast_string_field_build_va(msg, from, fmt, ap);
 	va_end(ap);
 
-	return res < 0 ? -1 : 0;
+	return 0;
 }
 
 int ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...)
 {
 	va_list ap;
-	int res;
 
 	va_start(ap, fmt);
-	res = ast_str_set_va(&msg->body, 0, fmt, ap);
+	ast_string_field_build_va(msg, body, fmt, ap);
 	va_end(ap);
 
-	return res < 0 ? -1 : 0;
+	return 0;
 }
 

[... 3177 lines stripped ...]



More information about the svn-commits mailing list