[asterisk-commits] jrose: branch jrose/bridge_projects r386039 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 18 15:49:08 CDT 2013


Author: jrose
Date: Thu Apr 18 15:49:06 2013
New Revision: 386039

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386039
Log:
fix automerge conflicts and get automerge back on.

Modified:
    team/jrose/bridge_projects/   (props changed)
    team/jrose/bridge_projects/include/asterisk/bridging.h
    team/jrose/bridge_projects/include/asterisk/http_websocket.h
    team/jrose/bridge_projects/main/bridging.c
    team/jrose/bridge_projects/main/features.c
    team/jrose/bridge_projects/main/message.c
    team/jrose/bridge_projects/res/res_http_websocket.c

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Thu Apr 18 15:49:06 2013
@@ -1,1 +1,1 @@
-/trunk:1-385939
+/trunk:1-386020

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_projects-integrated (original)
+++ bridge_projects-integrated Thu Apr 18 15:49:06 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-385942
+/team/group/bridge_construction:1-386038

Modified: team/jrose/bridge_projects/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/bridging.h?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/bridging.h (original)
+++ team/jrose/bridge_projects/include/asterisk/bridging.h Thu Apr 18 15:49:06 2013
@@ -130,7 +130,12 @@
 	struct ast_channel *chan;
 	/*! Asterisk channel we are swapping with (if swapping) */
 	struct ast_channel *swap;
-	/*! Bridge this channel is participating in */
+	/*!
+	 * \brief Bridge this channel is participating in
+	 *
+	 * \note The bridge pointer cannot change while the bridge or
+	 * bridge_channel is locked.
+	 */
 	struct ast_bridge *bridge;
 	/*!
 	 * \brief Bridge class private channel data.
@@ -150,6 +155,7 @@
 	void *tech_pvt;
 	/*! Thread handling the bridged channel (Needed by ast_bridge_depart) */
 	pthread_t thread;
+	/* v-- These flags change while the bridge is locked or before the channel is in the bridge. */
 	/*! TRUE if the channel is in a bridge. */
 	unsigned int in_bridge:1;
 	/*! TRUE if the channel just joined the bridge. */
@@ -158,6 +164,7 @@
 	unsigned int suspended:1;
 	/*! TRUE if the channel must wait for an ast_bridge_depart to reclaim the channel. */
 	unsigned int depart_wait:1;
+	/* ^-- These flags change while the bridge is locked or before the channel is in the bridge. */
 	/*! Features structure for features that are specific to this channel */
 	struct ast_bridge_features *features;
 	/*! Technology optimization parameters used by bridging technologies capable of
@@ -205,6 +212,8 @@
 
 	/*! Bridge reconfiguration deferred technology destruction. */
 	AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY = 1000,
+	/*! Bridge deferred dissolving. */
+	AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
 };
 
 enum ast_bridge_video_mode_type {
@@ -261,6 +270,8 @@
  * \details
  * The bridge is being dissolved.  Remove any external
  * references to the bridge so it can be destroyed.
+ *
+ * \note On entry, self must NOT be locked.
  *
  * \return Nothing
  */
@@ -626,7 +637,7 @@
  *
  * \note The features parameter must be NULL or obtained by
  * ast_bridge_features_new().  You must not dereference features
- * after calling.
+ * after calling even if the call fails.
  *
  * \retval 0 on success
  * \retval -1 on failure
@@ -716,8 +727,8 @@
 /*!
  * \brief Merge two bridges together
  *
- * \param bridge1 First bridge
- * \param bridge2 Second bridge
+ * \param dst_bridge Destination bridge of merge.
+ * \param src_bridge Source bridge of merge.
  *
  * \retval 0 on success
  * \retval -1 on failure
@@ -725,18 +736,18 @@
  * Example usage:
  *
  * \code
- * ast_bridge_merge(bridge1, bridge2);
- * \endcode
- *
- * This merges the bridge pointed to by bridge2 into the bridge
- * pointed to by bridge1.  In reality all of the channels in
- * bridge2 are moved to bridge1.
- *
- * \note The second bridge has no active channels in it when
- * this operation is completed.  The caller must explicitly call
- * ast_bridge_destroy().
- */
-int ast_bridge_merge(struct ast_bridge *bridge1, struct ast_bridge *bridge2);
+ * ast_bridge_merge(dst_bridge, src_bridge);
+ * \endcode
+ *
+ * This merges the bridge pointed to by src_bridge into the bridge
+ * pointed to by dst_bridge.  In reality all of the channels in
+ * src_bridge are moved to dst_bridge.
+ *
+ * \note The source bridge has no active channels in it when
+ * this operation is completed.  The caller should explicitly
+ * call ast_bridge_destroy().
+ */
+int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge);
 
 /*!
  * \brief XXX Hack function for moving a channel from one bridge to another

Modified: team/jrose/bridge_projects/include/asterisk/http_websocket.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/http_websocket.h?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/http_websocket.h (original)
+++ team/jrose/bridge_projects/include/asterisk/http_websocket.h Thu Apr 18 15:49:06 2013
@@ -19,6 +19,7 @@
 #ifndef _ASTERISK_HTTP_WEBSOCKET_H
 #define _ASTERISK_HTTP_WEBSOCKET_H
 
+#include "asterisk/http.h"
 #include "asterisk/optional_api.h"
 
 /*!
@@ -40,7 +41,13 @@
 };
 
 /*!
- * \brief Opaque structure for WebSocket sessions
+ * \brief Opaque structure for WebSocket server.
+ * \since 12
+ */
+struct ast_websocket_server;
+
+/*!
+ * \brief Opaque structure for WebSocket sessions.
  */
 struct ast_websocket;
 
@@ -58,7 +65,24 @@
 typedef void (*ast_websocket_callback)(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers);
 
 /*!
- * \brief Add a sub-protocol handler to the server
+ * \brief Creates a \ref websocket_server
+ *
+ * \retval New \ref websocket_server instance
+ * \retval \c NULL on error
+ * \since 12
+ */
+struct ast_websocket_server *ast_websocket_server_create(void);
+
+/*!
+ * \brief Callback suitable for use with a \ref ast_http_uri.
+ *
+ * Set the data field of the ast_http_uri to \ref ast_websocket_server.
+ * \since 12
+ */
+int ast_websocket_uri_cb(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers);
+
+/*!
+ * \brief Add a sub-protocol handler to the default /ws server
  *
  * \param name Name of the sub-protocol to register
  * \param callback Callback called when a new connection requesting the sub-protocol is established
@@ -69,7 +93,7 @@
 AST_OPTIONAL_API(int, ast_websocket_add_protocol, (const char *name, ast_websocket_callback callback), {return -1;});
 
 /*!
- * \brief Remove a sub-protocol handler from the server
+ * \brief Remove a sub-protocol handler from the default /ws server.
  *
  * \param name Name of the sub-protocol to unregister
  * \param callback Callback that was previously registered with the sub-protocol
@@ -78,6 +102,30 @@
  * \retval -1 if sub-protocol was not found or if callback did not match
  */
 AST_OPTIONAL_API(int, ast_websocket_remove_protocol, (const char *name, ast_websocket_callback callback), {return -1;});
+
+/*!
+ * \brief Add a sub-protocol handler to the given server.
+ *
+ * \param name Name of the sub-protocol to register
+ * \param callback Callback called when a new connection requesting the sub-protocol is established
+ *
+ * \retval 0 success
+ * \retval -1 if sub-protocol handler could not be registered
+ * \since 12
+ */
+AST_OPTIONAL_API(int, ast_websocket_server_add_protocol, (struct ast_websocket_server *server, const char *name, ast_websocket_callback callback), {return -1;});
+
+/*!
+ * \brief Remove a sub-protocol handler from the given server.
+ *
+ * \param name Name of the sub-protocol to unregister
+ * \param callback Callback that was previously registered with the sub-protocol
+ *
+ * \retval 0 success
+ * \retval -1 if sub-protocol was not found or if callback did not match
+ * \since 12
+ */
+AST_OPTIONAL_API(int, ast_websocket_server_remove_protocol, (struct ast_websocket_server *server, const char *name, ast_websocket_callback callback), {return -1;});
 
 /*!
  * \brief Read a WebSocket frame and handle it

Modified: team/jrose/bridge_projects/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/bridging.c?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/main/bridging.c (original)
+++ team/jrose/bridge_projects/main/bridging.c Thu Apr 18 15:49:06 2013
@@ -209,10 +209,7 @@
 		ao2_ref(bridge, +1);
 		ast_bridge_channel_unlock(bridge_channel);
 
-		/*
-		 * The bridge pointer cannot change while the bridge or
-		 * bridge_channel is locked.
-		 */
+		/* Lock the bridge and see if it is still the bridge we need to lock. */
 		ast_bridge_lock(bridge);
 		if (bridge == bridge_channel->bridge) {
 			ao2_ref(bridge, -1);
@@ -418,6 +415,10 @@
 static void bridge_dissolve(struct ast_bridge *bridge)
 {
 	struct ast_bridge_channel *bridge_channel;
+	struct ast_frame action = {
+		.frametype = AST_FRAME_BRIDGE_ACTION,
+		.subclass.integer = AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
+	};
 
 	if (bridge->dissolved) {
 		return;
@@ -430,7 +431,9 @@
 	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
 		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 	}
-	bridge->v_table->dissolving(bridge);
+
+	/* Must defer dissolving bridge because it is already locked. */
+	ast_bridge_queue_action(bridge, &action);
 }
 
 /*!
@@ -689,6 +692,12 @@
 static void bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
 	ast_bridge_channel_lock_bridge(bridge_channel);
+/*
+ * BUGBUG need to implement a deferred write queue for when there is no peer channel in the bridge (yet or it was kicked).
+ *
+ * The tech decides if a frame needs to be pushed back for deferral.
+ * simple_bridge/native_bridge are likely the only techs that will do this.
+ */
 	bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame);
 	ast_bridge_unlock(bridge_channel->bridge);
 }
@@ -1114,6 +1123,11 @@
 	case AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY:
 		ast_bridge_unlock(bridge);
 		bridge_tech_deferred_destroy(bridge, action);
+		ast_bridge_lock(bridge);
+		break;
+	case AST_BRIDGE_ACTION_DEFERRED_DISSOLVING:
+		ast_bridge_unlock(bridge);
+		bridge->v_table->dissolving(bridge);
 		ast_bridge_lock(bridge);
 		break;
 	default:
@@ -2995,7 +3009,10 @@
 		return -1;
 	}
 
-	/* We are claiming the reference held by the depart thread. */
+	/*
+	 * We are claiming the reference held by the depart bridge
+	 * channel thread.
+	 */
 
 	ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 
@@ -3030,55 +3047,6 @@
 	ast_bridge_unlock(bridge);
 
 	return 0;
-}
-
-/*!
- * \internal
- * \brief Do the merge of two bridges.
- * \since 12.0.0
- *
- * \param bridge1 First bridge
- * \param bridge2 Second bridge
- *
- * \return Nothing
- *
- * \note The two bridges are assumed already locked.
- *
- * This merges the bridge pointed to by bridge2 into the bridge
- * pointed to by bridge1.  In reality all of the channels in
- * bridge2 are moved to bridge1.
- *
- * \note The second bridge has no active channels in it when
- * this operation is completed.  The caller must explicitly call
- * ast_bridge_destroy().
- */
-static void bridge_merge_do(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
-{
-	struct ast_bridge_channel *bridge_channel;
-
-	ast_debug(1, "Merging bridge %s into bridge %s\n",
-		bridge2->uniqueid, bridge1->uniqueid);
-
-	ast_bridge_publish_merge(bridge1, bridge2);
-
-	/* Move channels from bridge2 over to bridge1 */
-	while ((bridge_channel = AST_LIST_FIRST(&bridge2->channels))) {
-		bridge_channel_pull(bridge_channel);
-
-		/* Point to new bridge.*/
-		ao2_ref(bridge1, +1);
-		ast_bridge_channel_lock(bridge_channel);
-		bridge_channel->bridge = bridge1;
-		ast_bridge_channel_unlock(bridge_channel);
-		ao2_ref(bridge2, -1);
-
-		bridge_channel_push(bridge_channel);
-	}
-	bridge_reconfigured(bridge1);
-	bridge_reconfigured(bridge2);
-
-	ast_debug(1, "Merged bridge %s into bridge %s\n",
-		bridge2->uniqueid, bridge1->uniqueid);
 }
 
 static void ast_bridge_move_do(struct ast_bridge *bridge_src, struct ast_bridge *bridge_dst, struct ast_channel *chan)
@@ -3141,45 +3109,94 @@
 	return res;
 }
 
-int ast_bridge_merge(struct ast_bridge *bridge1, struct ast_bridge *bridge2)
+/*!
+ * \internal
+ * \brief Do the merge of two bridges.
+ * \since 12.0.0
+ *
+ * \param dst_bridge Destination bridge of merge.
+ * \param src_bridge Source bridge of merge.
+ *
+ * \return Nothing
+ *
+ * \note The two bridges are assumed already locked.
+ *
+ * This merges the bridge pointed to by src_bridge into the bridge
+ * pointed to by dst_bridge.  In reality all of the channels in
+ * src_bridge are moved to dst_bridge.
+ *
+ * \note The source bridge has no active channels in it when
+ * this operation is completed.  The caller should explicitly
+ * call ast_bridge_destroy().
+ */
+static void bridge_merge_do(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge)
+{
+	struct ast_bridge_channel *bridge_channel;
+
+	ast_debug(1, "Merging bridge %s into bridge %s\n",
+		src_bridge->uniqueid, dst_bridge->uniqueid);
+
+	ast_bridge_publish_merge(dst_bridge, src_bridge);
+
+	/* Move channels from src_bridge over to dst_bridge */
+	while ((bridge_channel = AST_LIST_FIRST(&src_bridge->channels))) {
+		bridge_channel_pull(bridge_channel);
+
+		/* Point to new bridge.*/
+		ao2_ref(dst_bridge, +1);
+		ast_bridge_channel_lock(bridge_channel);
+		bridge_channel->bridge = dst_bridge;
+		ast_bridge_channel_unlock(bridge_channel);
+		ao2_ref(src_bridge, -1);
+
+		bridge_channel_push(bridge_channel);
+	}
+	bridge_reconfigured(dst_bridge);
+	bridge_reconfigured(src_bridge);
+
+	ast_debug(1, "Merged bridge %s into bridge %s\n",
+		src_bridge->uniqueid, dst_bridge->uniqueid);
+}
+
+int ast_bridge_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge)
 {
 	int res = -1;
 
 	/* Deadlock avoidance. */
 	for (;;) {
-		ast_bridge_lock(bridge1);
-		if (!ast_bridge_trylock(bridge2)) {
+		ast_bridge_lock(dst_bridge);
+		if (!ast_bridge_trylock(src_bridge)) {
 			break;
 		}
-		ast_bridge_unlock(bridge1);
+		ast_bridge_unlock(dst_bridge);
 		sched_yield();
 	}
 
-	if (bridge1->dissolved || bridge2->dissolved) {
+	if (dst_bridge->dissolved || src_bridge->dissolved) {
 		ast_debug(1, "Can't merge bridge %s into bridge %s, one or both bridges are dissolved.\n",
-			bridge2->uniqueid, bridge1->uniqueid);
-	} else if (bridge1->inhibit_merge || bridge2->inhibit_merge
-		|| ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
-		|| ast_test_flag(&bridge2->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
+			src_bridge->uniqueid, dst_bridge->uniqueid);
+	} else if (dst_bridge->inhibit_merge || src_bridge->inhibit_merge
+		|| ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_MERGE_INHIBIT_TO)
+		|| ast_test_flag(&src_bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM)) {
 		/* Merging is inhibited by either bridge. */
 		ast_debug(1, "Can't merge bridge %s into bridge %s, merging inhibited.\n",
-			bridge2->uniqueid, bridge1->uniqueid);
-	} else if (2 < bridge1->num_channels + bridge2->num_channels
-		&& !(bridge1->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
-		&& !ast_test_flag(&bridge1->feature_flags, AST_BRIDGE_FLAG_SMART)) {
+			src_bridge->uniqueid, dst_bridge->uniqueid);
+	} else if (2 < dst_bridge->num_channels + src_bridge->num_channels
+		&& !(dst_bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)
+		&& !ast_test_flag(&dst_bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
 		ast_debug(1, "Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired.\n",
-			bridge2->uniqueid, bridge1->uniqueid);
+			src_bridge->uniqueid, dst_bridge->uniqueid);
 	} else {
-		++bridge1->inhibit_merge;
-		++bridge2->inhibit_merge;
-		bridge_merge_do(bridge1, bridge2);
-		--bridge2->inhibit_merge;
-		--bridge1->inhibit_merge;
+		++dst_bridge->inhibit_merge;
+		++src_bridge->inhibit_merge;
+		bridge_merge_do(dst_bridge, src_bridge);
+		--src_bridge->inhibit_merge;
+		--dst_bridge->inhibit_merge;
 		res = 0;
 	}
 
-	ast_bridge_unlock(bridge2);
-	ast_bridge_unlock(bridge1);
+	ast_bridge_unlock(src_bridge);
+	ast_bridge_unlock(dst_bridge);
 	return res;
 }
 

Modified: team/jrose/bridge_projects/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/features.c?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/main/features.c (original)
+++ team/jrose/bridge_projects/main/features.c Thu Apr 18 15:49:06 2013
@@ -4443,7 +4443,6 @@
 	/* Put peer into the bridge */
 	if (ast_bridge_impart(bridge, peer, NULL, peer_features, 1)) {
 		ast_bridge_destroy(bridge);
-		ast_bridge_features_destroy(peer_features);
 		ast_bridge_features_cleanup(&chan_features);
 		bridge_failed_peer_goto(chan, peer);
 		return -1;

Modified: team/jrose/bridge_projects/main/message.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/message.c?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/main/message.c (original)
+++ team/jrose/bridge_projects/main/message.c Thu Apr 18 15:49:06 2013
@@ -1041,6 +1041,27 @@
 	return res;
 }
 
+static struct ast_msg_tech_holder *msg_find_by_tech(const struct ast_msg_tech *msg_tech, int ao2_flags)
+{
+	struct ast_msg_tech_holder *tech_holder;
+	struct ast_msg_tech_holder tmp_tech_holder = {
+		.tech = msg_tech,
+	};
+
+	ast_rwlock_init(&tmp_tech_holder.tech_lock);
+	tech_holder = ao2_find(msg_techs, &tmp_tech_holder, ao2_flags);
+	ast_rwlock_destroy(&tmp_tech_holder.tech_lock);
+	return tech_holder;
+}
+
+static struct ast_msg_tech_holder *msg_find_by_tech_name(const char *tech_name, int ao2_flags)
+{
+	struct ast_msg_tech tmp_msg_tech = {
+		.name = tech_name,
+	};
+	return msg_find_by_tech(&tmp_msg_tech, ao2_flags);
+}
+
 /*!
  * \internal
  * \brief MessageSend() application
@@ -1089,16 +1110,7 @@
 	tech_name = ast_strdupa(args.to);
 	tech_name = strsep(&tech_name, ":");
 
-	{
-		struct ast_msg_tech tmp_msg_tech = {
-			.name = tech_name,
-		};
-		struct ast_msg_tech_holder tmp_tech_holder = {
-			.tech = &tmp_msg_tech,
-		};
-
-		tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
-	}
+	tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
 
 	if (!tech_holder) {
 		ast_log(LOG_WARNING, "No message technology '%s' found.\n", tech_name);
@@ -1159,16 +1171,8 @@
 
 	tech_name = ast_strdupa(to);
 	tech_name = strsep(&tech_name, ":");
-	{
-		struct ast_msg_tech tmp_msg_tech = {
-			.name = tech_name,
-		};
-		struct ast_msg_tech_holder tmp_tech_holder = {
-			.tech = &tmp_msg_tech,
-		};
-
-		tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
-	}
+
+	tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
 
 	if (!tech_holder) {
 		astman_send_error(s, m, "Message technology not found.");
@@ -1219,16 +1223,8 @@
 
 	tech_name = ast_strdupa(to);
 	tech_name = strsep(&tech_name, ":");
-	{
-		struct ast_msg_tech tmp_msg_tech = {
-			.name = tech_name,
-		};
-		struct ast_msg_tech_holder tmp_tech_holder = {
-			.tech = &tmp_msg_tech,
-		};
-
-		tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
-	}
+
+	tech_holder = msg_find_by_tech_name(tech_name, OBJ_POINTER);
 
 	if (!tech_holder) {
 		ao2_ref(msg, -1);
@@ -1249,12 +1245,9 @@
 
 int ast_msg_tech_register(const struct ast_msg_tech *tech)
 {
-	struct ast_msg_tech_holder tmp_tech_holder = {
-		.tech = tech,
-	};
 	struct ast_msg_tech_holder *tech_holder;
 
-	if ((tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER))) {
+	if ((tech_holder = msg_find_by_tech(tech, OBJ_POINTER))) {
 		ao2_ref(tech_holder, -1);
 		ast_log(LOG_ERROR, "Message technology already registered for '%s'\n",
 				tech->name);
@@ -1280,12 +1273,9 @@
 
 int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
 {
-	struct ast_msg_tech_holder tmp_tech_holder = {
-		.tech = tech,
-	};
 	struct ast_msg_tech_holder *tech_holder;
 
-	tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER | OBJ_UNLINK);
+	tech_holder = msg_find_by_tech(tech, OBJ_POINTER | OBJ_UNLINK);
 
 	if (!tech_holder) {
 		ast_log(LOG_ERROR, "No '%s' message technology found.\n", tech->name);

Modified: team/jrose/bridge_projects/res/res_http_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/res_http_websocket.c?view=diff&rev=386039&r1=386038&r2=386039
==============================================================================
--- team/jrose/bridge_projects/res/res_http_websocket.c (original)
+++ team/jrose/bridge_projects/res/res_http_websocket.c Thu Apr 18 15:49:06 2013
@@ -77,9 +77,6 @@
 	ast_websocket_callback callback; /*!< Callback called when a new session is established */
 };
 
-/*! \brief Container for registered protocols */
-static struct ao2_container *protocols;
-
 /*! \brief Hashing function for protocols */
 static int protocol_hash_fn(const void *obj, const int flags)
 {
@@ -103,6 +100,36 @@
 {
 	struct websocket_protocol *protocol = obj;
 	ast_free(protocol->name);
+}
+
+/*! \brief Structure for a WebSocket server */
+struct ast_websocket_server {
+	struct ao2_container *protocols; /*!< Container for registered protocols */
+};
+
+static void websocket_server_dtor(void *obj)
+{
+	struct ast_websocket_server *server = obj;
+	ao2_cleanup(server->protocols);
+	server->protocols = NULL;
+}
+
+struct ast_websocket_server *ast_websocket_server_create(void)
+{
+	RAII_VAR(struct ast_websocket_server *, server, NULL, ao2_cleanup);
+
+	server = ao2_alloc(sizeof(*server), websocket_server_dtor);
+	if (!server) {
+		return NULL;
+	}
+
+	server->protocols = ao2_container_alloc(MAX_PROTOCOL_BUCKETS, protocol_hash_fn, protocol_cmp_fn);
+	if (!server->protocols) {
+		return NULL;
+	}
+
+	ao2_ref(server, +1);
+	return server;
 }
 
 /*! \brief Destructor function for sessions */
@@ -118,38 +145,38 @@
 	ast_free(session->payload);
 }
 
-int AST_OPTIONAL_API_NAME(ast_websocket_add_protocol)(const char *name, ast_websocket_callback callback)
+int AST_OPTIONAL_API_NAME(ast_websocket_server_add_protocol)(struct ast_websocket_server *server, const char *name, ast_websocket_callback callback)
 {
 	struct websocket_protocol *protocol;
 
-	if (!protocols) {
-		return -1;
-	}
-
-	ao2_lock(protocols);
+	if (!server->protocols) {
+		return -1;
+	}
+
+	ao2_lock(server->protocols);
 
 	/* Ensure a second protocol handler is not registered for the same protocol */
-	if ((protocol = ao2_find(protocols, name, OBJ_KEY | OBJ_NOLOCK))) {
+	if ((protocol = ao2_find(server->protocols, name, OBJ_KEY | OBJ_NOLOCK))) {
 		ao2_ref(protocol, -1);
-		ao2_unlock(protocols);
+		ao2_unlock(server->protocols);
 		return -1;
 	}
 
 	if (!(protocol = ao2_alloc(sizeof(*protocol), protocol_destroy_fn))) {
-		ao2_unlock(protocols);
+		ao2_unlock(server->protocols);
 		return -1;
 	}
 
 	if (!(protocol->name = ast_strdup(name))) {
 		ao2_ref(protocol, -1);
-		ao2_unlock(protocols);
+		ao2_unlock(server->protocols);
 		return -1;
 	}
 
 	protocol->callback = callback;
 
-	ao2_link_flags(protocols, protocol, OBJ_NOLOCK);
-	ao2_unlock(protocols);
+	ao2_link_flags(server->protocols, protocol, OBJ_NOLOCK);
+	ao2_unlock(server->protocols);
 	ao2_ref(protocol, -1);
 
 	ast_verb(2, "WebSocket registered sub-protocol '%s'\n", name);
@@ -157,15 +184,11 @@
 	return 0;
 }
 
-int AST_OPTIONAL_API_NAME(ast_websocket_remove_protocol)(const char *name, ast_websocket_callback callback)
+int AST_OPTIONAL_API_NAME(ast_websocket_server_remove_protocol)(struct ast_websocket_server *server, const char *name, ast_websocket_callback callback)
 {
 	struct websocket_protocol *protocol;
 
-	if (!protocols) {
-		return -1;
-	}
-
-	if (!(protocol = ao2_find(protocols, name, OBJ_KEY))) {
+	if (!(protocol = ao2_find(server->protocols, name, OBJ_KEY))) {
 		return -1;
 	}
 
@@ -174,7 +197,7 @@
 		return -1;
 	}
 
-	ao2_unlink(protocols, protocol);
+	ao2_unlink(server->protocols, protocol);
 	ao2_ref(protocol, -1);
 
 	ast_verb(2, "WebSocket unregistered sub-protocol '%s'\n", name);
@@ -474,20 +497,22 @@
 	return 0;
 }
 
-/*! \brief Callback that is executed everytime an HTTP request is received by this module */
-static int websocket_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
+int ast_websocket_uri_cb(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
 {
 	struct ast_variable *v;
 	char *upgrade = NULL, *key = NULL, *key1 = NULL, *key2 = NULL, *protos = NULL, *requested_protocols = NULL, *protocol = NULL;
 	int version = 0, flags = 1;
 	struct websocket_protocol *protocol_handler = NULL;
 	struct ast_websocket *session;
+	struct ast_websocket_server *server;
 
 	/* Upgrade requests are only permitted on GET methods */
 	if (method != AST_HTTP_GET) {
 		ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
 		return -1;
 	}
+
+	server = urih->data;
 
 	/* Get the minimum headers required to satisfy our needs */
 	for (v = headers; v; v = v->next) {
@@ -533,7 +558,7 @@
 
 	/* Iterate through the requested protocols trying to find one that we have a handler for */
 	while ((protocol = strsep(&requested_protocols, ","))) {
-		if ((protocol_handler = ao2_find(protocols, ast_strip(protocol), OBJ_KEY))) {
+		if ((protocol_handler = ao2_find(server->protocols, ast_strip(protocol), OBJ_KEY))) {
 			break;
 		}
 	}
@@ -619,7 +644,7 @@
 }
 
 static struct ast_http_uri websocketuri = {
-	.callback = websocket_callback,
+	.callback = ast_websocket_uri_cb,
 	.description = "Asterisk HTTP WebSocket",
 	.uri = "ws",
 	.has_subtree = 0,
@@ -664,9 +689,30 @@
 	ast_websocket_unref(session);
 }
 
+int AST_OPTIONAL_API_NAME(ast_websocket_add_protocol)(const char *name, ast_websocket_callback callback)
+{
+	struct ast_websocket_server *ws_server = websocketuri.data;
+	if (!ws_server) {
+		return -1;
+	}
+	return ast_websocket_server_add_protocol(ws_server, name, callback);
+}
+
+int AST_OPTIONAL_API_NAME(ast_websocket_remove_protocol)(const char *name, ast_websocket_callback callback)
+{
+	struct ast_websocket_server *ws_server = websocketuri.data;
+	if (!ws_server) {
+		return -1;
+	}
+	return ast_websocket_server_remove_protocol(ws_server, name, callback);
+}
+
 static int load_module(void)
 {
-	protocols = ao2_container_alloc(MAX_PROTOCOL_BUCKETS, protocol_hash_fn, protocol_cmp_fn);
+	websocketuri.data = ast_websocket_server_create();
+	if (!websocketuri.data) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
 	ast_http_uri_link(&websocketuri);
 	ast_websocket_add_protocol("echo", websocket_echo_callback);
 
@@ -677,8 +723,8 @@
 {
 	ast_websocket_remove_protocol("echo", websocket_echo_callback);
 	ast_http_uri_unlink(&websocketuri);
-	ao2_ref(protocols, -1);
-	protocols = NULL;
+	ao2_ref(websocketuri.data, -1);
+	websocketuri.data = NULL;
 
 	return 0;
 }




More information about the asterisk-commits mailing list