[asterisk-commits] qwell: branch qwell/pimp_my_dtmf r386302 - in /team/qwell/pimp_my_dtmf: ./ ap...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 22 12:34:53 CDT 2013


Author: qwell
Date: Mon Apr 22 12:34:46 2013
New Revision: 386302

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386302
Log:
Multiple revisions 386022,386056,386163,386192,386213,386238

........
  r386022 | root | 2013-04-18 13:17:43 -0500 (Thu, 18 Apr 2013) | 39 lines
  
  Multiple revisions 386019-386020
  
  ........
    r386019 | dlee | 2013-04-18 12:26:29 -0500 (Thu, 18 Apr 2013) | 17 lines
    
    Fix lock errors on startup.
    
    In messages.c, there are several places in the code where we create a
    tmp_tech_holder and pass that into an ao2_find call. Unfortunately, we
    weren't initializing the rwlock on the tmp_tech_holder, which the hash
    function was locking. It's apparently harmless, but still not the best
    code.
    
    This patch extracts all that copy/pasted code into two functions,
    msg_find_by_tech and msg_find_by_tech_name, which properly initialize
    and destroy the rwlock on the tmp_tech_holder.
    
    Review: https://reviewboard.asterisk.org/r/2454/
    ........
    
    Merged revisions 386006 from http://svn.asterisk.org/svn/asterisk/branches/11
  ........
    r386020 | dlee | 2013-04-18 12:30:28 -0500 (Thu, 18 Apr 2013) | 12 lines
    
    Allow WebSocket connections on more URL's
    
    This patch adds the concept of ast_websocket_server to
    res_http_websocket, allowing WebSocket connections on URL's more more
    than /ws.
    
    The existing funcitons for managing the WebSocket subprotocols on /ws
    still work, so this patch should be completely backward compatible.
    
    (closes issue ASTERISK-21279)
    Review: https://reviewboard.asterisk.org/r/2453/
  ........
  
  Merged revisions 386019-386020 from file:///srv/subversion/repos/asterisk/trunk
........
  r386056 | root | 2013-04-19 01:17:38 -0500 (Fri, 19 Apr 2013) | 13 lines
  
  cli.c: Properly initialize debug_modules and verbose_modules.
  
  This avoids some lock errors on the core set {debug,verbose} commands.
  ........
  
  Merged revisions 386049 from http://svn.asterisk.org/svn/asterisk/branches/1.8
  ........
  
  Merged revisions 386051 from http://svn.asterisk.org/svn/asterisk/branches/11
  ........
  
  Merged revisions 386054 from file:///srv/subversion/repos/asterisk/trunk
........
  r386163 | root | 2013-04-19 18:17:44 -0500 (Fri, 19 Apr 2013) | 58 lines
  
  Prevent res_timing_pthread from blocking callers
  
  There were several reports of deadlock when using
  res_timing_pthread. Backtraces indicated that one thread was blocked
  waiting for the write to the pipe to complete and this thread held
  the container lock for the timers.  Therefore any thread that wanted
  to create a new timer or read an existing timer would block waiting
  for either the timer lock or the container lock and deadlock ensued.
  
  This patch changes the way the pipe is used to eliminate this source
  of deadlocks:
  
  1) The pipe is placed in non-blocking mode so that it would never
  block even if the following changes someone fail...
  
  2) Instead of writing bytes into the pipe for each "tick" that's
  fired the pipe now has two states--signaled and unsignaled. If
  signaled, the pipe is hot and any pollers of the read side
  filedescriptor will be woken up. If unsigned the pipe is idle. This
  eliminates even the chance of filling up the pipe and reduces the
  potential overhead of calling unnecessary writes.
  
  3) Since we're tracking the signaled / unsignaled state, we can
  eliminate the exta poll system call for every firing because we know
  that there is data to be read.
  
  (closes issue ASTERISK-21389)
  Reported by: Matt Jordan
  Tested by: Shaun Ruffell, Matt Jordan, Tony Lewis
  patches:
    0001-res_timing_pthread-Reduce-probability-of-deadlocking.patch uploaded by sruffell (License 5417)
  
  (closes issue ASTERISK-19754)
  Reported by: Nikola Ciprich
  
  (closes issue ASTERISK-20577)
  Reported by: Kien Kennedy
  
  (closes issue ASTERISK-17436)
  Reported by: Henry Fernandes
  
  (closes issue ASTERISK-17467)
  Reported by: isrl
  
  (closes issue ASTERISK-17458)
  Reported by: isrl
  
  Review: https://reviewboard.asterisk.org/r/2441/
  ........
  
  Merged revisions 386109 from http://svn.asterisk.org/svn/asterisk/branches/1.8
  ........
  
  Merged revisions 386159 from http://svn.asterisk.org/svn/asterisk/branches/11
  ........
  
  Merged revisions 386160 from file:///srv/subversion/repos/asterisk/trunk
........
  r386192 | root | 2013-04-21 20:18:32 -0500 (Sun, 21 Apr 2013) | 9 lines
  
  sla: remove redundant locking.
  
  sla.lock was already locked in the only place that sla_check_reload() was called.
  Remove the redundant locking of sla.lock done in this function.  Less recursive
  locking is A Good Thing.
  ........
  
  Merged revisions 386190 from file:///srv/subversion/repos/asterisk/trunk
........
  r386213 | root | 2013-04-22 08:18:13 -0500 (Mon, 22 Apr 2013) | 7 lines
  
  Fix mistake in Doxygen. 
  
  Doxygen is only *ONE* comment that applies to the NEXT piece of code.
  ........
  
  Merged revisions 386211 from file:///srv/subversion/repos/asterisk/trunk
........
  r386238 | root | 2013-04-22 10:17:48 -0500 (Mon, 22 Apr 2013) | 1 line
  
  automerge cancel
........

Merged revisions 386022,386056,386163,386192,386213,386238 from http://svn.asterisk.org/svn/asterisk/team/group/pimp_my_sip

Modified:
    team/qwell/pimp_my_dtmf/   (props changed)
    team/qwell/pimp_my_dtmf/apps/app_meetme.c
    team/qwell/pimp_my_dtmf/include/asterisk/http_websocket.h
    team/qwell/pimp_my_dtmf/include/asterisk/srv.h
    team/qwell/pimp_my_dtmf/main/cli.c
    team/qwell/pimp_my_dtmf/main/message.c
    team/qwell/pimp_my_dtmf/res/res_http_websocket.c
    team/qwell/pimp_my_dtmf/res/res_timing_pthread.c

Propchange: team/qwell/pimp_my_dtmf/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/qwell/pimp_my_dtmf/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Apr 22 12:34:46 2013
@@ -1,1 +1,1 @@
-/team/group/pimp_my_sip:1-385983 /trunk:1-385317
+/team/group/pimp_my_sip:1-386301 /trunk:1-385317

Modified: team/qwell/pimp_my_dtmf/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/apps/app_meetme.c?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/apps/app_meetme.c (original)
+++ team/qwell/pimp_my_dtmf/apps/app_meetme.c Mon Apr 22 12:34:46 2013
@@ -6437,17 +6437,18 @@
 
 static int sla_load_config(int reload);
 
-/*! \brief Check if we can do a reload of SLA, and do it if we can */
+/*!
+ * \internal
+ * \brief Check if we can do a reload of SLA, and do it if we can
+ * \pre sla.lock is locked.
+ */
 static void sla_check_reload(void)
 {
 	struct sla_station *station;
 	struct sla_trunk *trunk;
 
-	ast_mutex_lock(&sla.lock);
-
 	if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 
 		|| !AST_LIST_EMPTY(&sla.ringing_stations)) {
-		ast_mutex_unlock(&sla.lock);
 		return;
 	}
 
@@ -6458,7 +6459,6 @@
 	}
 	AST_RWLIST_UNLOCK(&sla_stations);
 	if (station) {
-		ast_mutex_unlock(&sla.lock);
 		return;
 	}
 
@@ -6469,15 +6469,12 @@
 	}
 	AST_RWLIST_UNLOCK(&sla_trunks);
 	if (trunk) {
-		ast_mutex_unlock(&sla.lock);
 		return;
 	}
 
 	/* yay */
 	sla_load_config(1);
 	sla.reload = 0;
-
-	ast_mutex_unlock(&sla.lock);
 }
 
 static void *sla_thread(void *data)

Modified: team/qwell/pimp_my_dtmf/include/asterisk/http_websocket.h
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/include/asterisk/http_websocket.h?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/include/asterisk/http_websocket.h (original)
+++ team/qwell/pimp_my_dtmf/include/asterisk/http_websocket.h Mon Apr 22 12:34:46 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/qwell/pimp_my_dtmf/include/asterisk/srv.h
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/include/asterisk/srv.h?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/include/asterisk/srv.h (original)
+++ team/qwell/pimp_my_dtmf/include/asterisk/srv.h Mon Apr 22 12:34:46 2013
@@ -52,8 +52,7 @@
 
 /*! Lookup entry in SRV records Returns 1 if found, 0 if not found, -1 on hangup 
 	Only do SRV record lookup if you get a domain without a port. If you get a port #, it's a DNS host name.
-*/
-/*!	\param	chan Ast channel
+!	\param	chan Ast channel
 	\param	host host name (return value)
 	\param	hostlen Length of string "host"
 	\param	port Port number (return value)

Modified: team/qwell/pimp_my_dtmf/main/cli.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/main/cli.c?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/main/cli.c (original)
+++ team/qwell/pimp_my_dtmf/main/cli.c Mon Apr 22 12:34:46 2013
@@ -102,9 +102,9 @@
 AST_RWLIST_HEAD(module_level_list, module_level);
 
 /*! list of module names and their debug levels */
-static struct module_level_list debug_modules;
+static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE;
 /*! list of module names and their verbose levels */
-static struct module_level_list verbose_modules;
+static struct module_level_list verbose_modules = AST_RWLIST_HEAD_INIT_VALUE;
 
 AST_THREADSTORAGE(ast_cli_buf);
 

Modified: team/qwell/pimp_my_dtmf/main/message.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/main/message.c?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/main/message.c (original)
+++ team/qwell/pimp_my_dtmf/main/message.c Mon Apr 22 12:34:46 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/qwell/pimp_my_dtmf/res/res_http_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/res/res_http_websocket.c?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/res/res_http_websocket.c (original)
+++ team/qwell/pimp_my_dtmf/res/res_http_websocket.c Mon Apr 22 12:34:46 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;
 }

Modified: team/qwell/pimp_my_dtmf/res/res_timing_pthread.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/pimp_my_dtmf/res/res_timing_pthread.c?view=diff&rev=386302&r1=386301&r2=386302
==============================================================================
--- team/qwell/pimp_my_dtmf/res/res_timing_pthread.c (original)
+++ team/qwell/pimp_my_dtmf/res/res_timing_pthread.c Mon Apr 22 12:34:46 2013
@@ -31,8 +31,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
 
+#include <stdbool.h>
 #include <math.h>
-#include <sys/select.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include "asterisk/module.h"
 #include "asterisk/timing.h"
@@ -40,7 +42,6 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/time.h"
 #include "asterisk/lock.h"
-#include "asterisk/poll-compat.h"
 
 static void *timing_funcs_handle;
 
@@ -91,13 +92,15 @@
 	unsigned int tick_count;
 	unsigned int pending_ticks;
 	struct timeval start;
-	unsigned int continuous:1;
+	bool continuous:1;
+	bool pipe_signaled:1;
 };
 
 static void pthread_timer_destructor(void *obj);
 static struct pthread_timer *find_timer(int handle, int unlinkobj);
-static void write_byte(struct pthread_timer *timer);
-static int read_pipe(struct pthread_timer *timer, unsigned int num);
+static void signal_pipe(struct pthread_timer *timer);
+static void unsignal_pipe(struct pthread_timer *timer);
+static void ack_ticks(struct pthread_timer *timer, unsigned int num);
 
 /*!
  * \brief Data for the timing thread
@@ -113,6 +116,7 @@
 {
 	struct pthread_timer *timer;
 	int fd;
+	int i;
 
 	if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
 		errno = ENOMEM;
@@ -127,6 +131,12 @@
 		return -1;
 	}
 
+	for (i = 0; i < ARRAY_LEN(timer->pipe); ++i) {
+		int flags = fcntl(timer->pipe[i], F_GETFL);
+		flags |= O_NONBLOCK;
+		fcntl(timer->pipe[i], F_SETFL, flags);
+	}
+	
 	ao2_lock(pthread_timers);
 	if (!ao2_container_count(pthread_timers)) {
 		ast_mutex_lock(&timing_thread.lock);
@@ -193,7 +203,6 @@
 static int pthread_timer_ack(int handle, unsigned int quantity)
 {
 	struct pthread_timer *timer;
-	int res;
 
 	ast_assert(quantity > 0);
 
@@ -202,12 +211,12 @@
 	}
 
 	ao2_lock(timer);
-	res = read_pipe(timer, quantity);
+	ack_ticks(timer, quantity);
 	ao2_unlock(timer);
 
 	ao2_ref(timer, -1);
 
-	return res;
+	return 0;
 }
 
 static int pthread_timer_enable_continuous(int handle)
@@ -221,8 +230,8 @@
 
 	ao2_lock(timer);
 	if (!timer->continuous) {
-		timer->continuous = 1;
-		write_byte(timer);
+		timer->continuous = true;
+		signal_pipe(timer);
 	}
 	ao2_unlock(timer);
 
@@ -242,13 +251,8 @@
 
 	ao2_lock(timer);
 	if (timer->continuous) {
-		timer->continuous = 0;
-		if (read_pipe(timer, 1) != 0) {
-			/* Let the errno from read_pipe propagate up */
-			ao2_unlock(timer);
-			ao2_ref(timer, -1);
-			return -1;
-		}
+		timer->continuous = false;
+		unsignal_pipe(timer);
 	}
 	ao2_unlock(timer);
 
@@ -267,7 +271,7 @@
 	}
 
 	ao2_lock(timer);
-	if (timer->continuous && timer->pending_ticks == 1) {
+	if (timer->continuous) {
 		res = AST_TIMING_EVENT_CONTINUOUS;
 	}
 	ao2_unlock(timer);
@@ -366,79 +370,69 @@
 /*!
  * \internal
  * \pre timer is locked
- * \retval 0 if nothing to read or read success
- * \retval -1 on error
- */
-static int read_pipe(struct pthread_timer *timer, unsigned int quantity)
-{
-	int rd_fd = timer->pipe[PIPE_READ];
+ */
+static void ack_ticks(struct pthread_timer *timer, unsigned int quantity)
+{
 	int pending_ticks = timer->pending_ticks;
 
 	ast_assert(quantity);
-
-	if (timer->continuous && pending_ticks) {
-		pending_ticks--;
-	}
 
 	if (quantity > pending_ticks) {
 		quantity = pending_ticks;
 	}
 
 	if (!quantity) {
-		return 0;
-	}
-
-	do {
-		unsigned char buf[1024];
-		ssize_t res;
-		struct pollfd pfd = {
-			.fd = rd_fd,
-			.events = POLLIN,
-		};
-
-		if (ast_poll(&pfd, 1, 0) != 1) {
-			ast_debug(1, "Reading not available on timing pipe, "
-					"quantity: %u\n", quantity);
-			return -1;
-		}
-
-		res = read(rd_fd, buf,
-			(quantity < sizeof(buf)) ? quantity : sizeof(buf));
-
-		if (res == -1) {
-			if (errno == EAGAIN) {
-				continue;
-			}
-			ast_log(LOG_ERROR, "read failed on timing pipe: %s\n",
-					strerror(errno));
-			return -1;
-		}
-
-		quantity -= res;
-		timer->pending_ticks -= res;
-	} while (quantity);
-
-	return 0;
+		return;
+	}
+
+	timer->pending_ticks -= quantity;
+
+	if ((0 == timer->pending_ticks) && !timer->continuous) {
+		unsignal_pipe(timer);
+	}
 }
 
 /*!
  * \internal
  * \pre timer is locked
  */
-static void write_byte(struct pthread_timer *timer)
+static void signal_pipe(struct pthread_timer *timer)
 {
 	ssize_t res;
 	unsigned char x = 42;
 
-	do {
-		res = write(timer->pipe[PIPE_WRITE], &x, 1);
-	} while (res == -1 && errno == EAGAIN);
-
-	if (res == -1) {
+	if (timer->pipe_signaled) {
+		return;
+	}
+
+	res = write(timer->pipe[PIPE_WRITE], &x, 1);
+	if (-1 == res) {
 		ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n",
 				strerror(errno));
 	} else {
-		timer->pending_ticks++;
+		timer->pipe_signaled = true;
+	}
+}
+
+/*!
+ * \internal
+ * \pre timer is locked
+ */
+static void unsignal_pipe(struct pthread_timer *timer)
+{
+	ssize_t res;
+	unsigned long buffer;
+
+	if (!timer->pipe_signaled) {
+		return;
+	}
+
+	res = read(timer->pipe[PIPE_READ], &buffer, sizeof(buffer));
+	if (-1 == res) {
+		ast_log(LOG_ERROR, "Error reading from pipe: %s\n",
+				strerror(errno));
+	} else {
+		timer->pipe_signaled = false;
 	}
 }
 
@@ -452,7 +446,8 @@
 
 	ao2_lock(timer);
 	if (check_timer(timer)) {
-		write_byte(timer);
+		timer->pending_ticks++;
+		signal_pipe(timer);
 	}
 	ao2_unlock(timer);
 




More information about the asterisk-commits mailing list