Merge "app_queue.c: Extract some functions for simpler code."
authorMark Michelson <mmichelson@digium.com>
Wed, 19 Aug 2015 22:03:35 +0000 (17:03 -0500)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Wed, 19 Aug 2015 22:03:35 +0000 (17:03 -0500)
apps/app_queue.c
contrib/scripts/install_prereq
res/ari/ari_websockets.c
res/res_ari.c
res/res_http_websocket.c

index 9cc6efa..bb3ec17 100644 (file)
@@ -549,7 +549,7 @@ ASTERISK_REGISTER_FILE()
                        Count number of members answering a queue.
                </synopsis>
                <syntax>
-                       <parameter name="queuename" required="true" />
+                       <parameter name="queuename" required="false" />
                        <parameter name="option" required="true">
                                <enumlist>
                                        <enum name="logged">
@@ -565,13 +565,22 @@ ASTERISK_REGISTER_FILE()
                                                <para>Returns the total number of members for the specified queue.</para>
                                        </enum>
                                        <enum name="penalty">
-                                               <para>Gets or sets queue member penalty.</para>
+                                               <para>Gets or sets queue member penalty.  If
+                                               <replaceable>queuename</replaceable> is not specified
+                                               when setting the penalty then the penalty is set in all queues
+                                               the interface is a member.</para>
                                        </enum>
                                        <enum name="paused">
-                                               <para>Gets or sets queue member paused status.</para>
+                                               <para>Gets or sets queue member paused status.  If
+                                               <replaceable>queuename</replaceable> is not specified
+                                               when setting the paused status then the paused status is set
+                                               in all queues the interface is a member.</para>
                                        </enum>
                                        <enum name="ringinuse">
-                                               <para>Gets or sets queue member ringinuse.</para>
+                                               <para>Gets or sets queue member ringinuse.  If
+                                               <replaceable>queuename</replaceable> is not specified
+                                               when setting ringinuse then ringinuse is set
+                                               in all queues the interface is a member.</para>
                                        </enum>
                                </enumlist>
                        </parameter>
@@ -579,10 +588,8 @@ ASTERISK_REGISTER_FILE()
                </syntax>
                <description>
                        <para>Allows access to queue counts [R] and member information [R/W].</para>
-                       <para>
-                               <replaceable>queuename</replaceable> is required for all operations
-                               <replaceable>interface</replaceable> is required for all member operations.
-                       </para>
+                       <para><replaceable>queuename</replaceable> is required for all read operations.</para>
+                       <para><replaceable>interface</replaceable> is required for all member operations.</para>
                </description>
                <see-also>
                        <ref type="application">Queue</ref>
@@ -8058,12 +8065,29 @@ static int queue_function_exists(struct ast_channel *chan, const char *cmd, char
        return 0;
 }
 
+static struct member *get_interface_helper(struct call_queue *q, const char *interface)
+{
+       struct member *m;
+
+       if (ast_strlen_zero(interface)) {
+               ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
+               return NULL;
+       }
+
+       m = interface_exists(q, interface);
+       if (!m) {
+               ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
+                       interface, q->name);
+       }
+       return m;
+}
+
 /*!
  * \brief Get number either busy / free / ready or total members of a specific queue
  * \brief Get or set member properties penalty / paused / ringinuse
  * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ringinuse)
  * \retval -1 on error
-*/
+ */
 static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
        int count = 0;
@@ -8080,14 +8104,18 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
        buf[0] = '\0';
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
+               ast_log(LOG_ERROR,
+                       "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
+                       cmd);
                return -1;
        }
 
        AST_STANDARD_APP_ARGS(args, data);
 
-       if (args.argc < 2) {
-               ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
+       if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.option)) {
+               ast_log(LOG_ERROR,
+                       "Missing required argument. %s(<queuename>,<option>[,<interface>])\n",
+                       cmd);
                return -1;
        }
 
@@ -8126,27 +8154,29 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
                                ao2_ref(m, -1);
                        }
                        ao2_iterator_destroy(&mem_iter);
-               } else if (!strcasecmp(args.option, "count") || ast_strlen_zero(args.option)) {
+               } else if (!strcasecmp(args.option, "count")) {
                        count = ao2_container_count(q->members);
-               } else if (!strcasecmp(args.option, "penalty") && !ast_strlen_zero(args.interface) &&
-                          ((m = interface_exists(q, args.interface)))) {
-                       count = m->penalty;
-                       ao2_ref(m, -1);
-               } else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
-                          ((m = interface_exists(q, args.interface)))) {
-                       count = m->paused;
-                       ao2_ref(m, -1);
-               } else if ( (!strcasecmp(args.option, "ignorebusy") || !strcasecmp(args.option, "ringinuse")) &&
-                          !ast_strlen_zero(args.interface) &&
-                          ((m = interface_exists(q, args.interface)))) {
-                       count = m->ringinuse;
-                       ao2_ref(m, -1);
-               } else if (!ast_strlen_zero(args.interface)) {
-                       ast_log(LOG_ERROR, "Queue member interface %s not in queue %s\n",
-                               args.interface, args.queuename);
+               } else if (!strcasecmp(args.option, "penalty")) {
+                       m = get_interface_helper(q, args.interface);
+                       if (m) {
+                               count = m->penalty;
+                               ao2_ref(m, -1);
+                       }
+               } else if (!strcasecmp(args.option, "paused")) {
+                       m = get_interface_helper(q, args.interface);
+                       if (m) {
+                               count = m->paused;
+                               ao2_ref(m, -1);
+                       }
+               } else if ((!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
+                       || !strcasecmp(args.option, "ringinuse"))) {
+                       m = get_interface_helper(q, args.interface);
+                       if (m) {
+                               count = m->ringinuse;
+                               ao2_ref(m, -1);
+                       }
                } else {
-                       ast_log(LOG_ERROR, "Unknown option %s provided to %s, valid values are: "
-                               "logged, free, ready, count, penalty, paused, ringinuse\n", args.option, cmd);
+                       ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
                }
                ao2_unlock(q);
                queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
@@ -8163,9 +8193,6 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
 static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
 {
        int memvalue;
-       struct call_queue *q;
-       struct member *m;
-       char rtvalue[80];
 
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(queuename);
@@ -8174,65 +8201,48 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
        );
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER(<queuename>,<option>,<interface>)\n");
+               ast_log(LOG_ERROR,
+                       "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
+                       cmd);
                return -1;
        }
 
        AST_STANDARD_APP_ARGS(args, data);
 
-       if (args.argc < 3) {
-               ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
+       if (ast_strlen_zero(args.option)
+               || ast_strlen_zero(args.interface)) {
+               ast_log(LOG_ERROR,
+                       "Missing required argument. %s([<queuename>],<option>,<interface>)\n",
+                       cmd);
                return -1;
        }
 
-       if (ast_strlen_zero(args.interface) && ast_strlen_zero(args.option)) {
-               ast_log (LOG_ERROR, "<interface> and <option> parameter's can't be null\n");
-               return -1;
-       }
+       /*
+        * If queuename is empty then the option will be
+        * set for the interface in all queues.
+        */
 
        memvalue = atoi(value);
        if (!strcasecmp(args.option, "penalty")) {
-               /* if queuename = NULL then penalty will be set for interface in all the queues.*/
                if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, memvalue)) {
-                       ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
+                       ast_log(LOG_ERROR, "Invalid interface, queue, or penalty\n");
                        return -1;
                }
-       } else if ((q = find_load_queue_rt_friendly(args.queuename))) {
-               ao2_lock(q);
-               if ((m = interface_exists(q, args.interface))) {
-                       sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
-                       if (!strcasecmp(args.option, "paused")) {
-                               if (m->realtime) {
-                                       update_realtime_member_field(m, q->name, args.option, rtvalue);
-                               }
-                               m->paused = (memvalue <= 0) ? 0 : 1;
-                               ast_devstate_changed(m->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
-                                       AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, args.interface);
-
-                       } else if ((!strcasecmp(args.option, "ignorebusy")) || (!strcasecmp(args.option, "ringinuse"))) {
-                               if (m->realtime) {
-                                       update_realtime_member_field(m, q->name, args.option, rtvalue);
-                               }
-
-                               m->ringinuse = (memvalue <= 0) ? 0 : 1;
-                       } else {
-                               ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ringinuse/ignorebusy are valid\n");
-                               ao2_ref(m, -1);
-                               ao2_unlock(q);
-                               ao2_ref(q, -1);
-                               return -1;
-                       }
-                       ao2_ref(m, -1);
-               } else {
-                       ao2_unlock(q);
-                       ao2_ref(q, -1);
-                       ast_log(LOG_ERROR, "Invalid interface for queue\n");
+       } else if (!strcasecmp(args.option, "paused")) {
+               memvalue = (memvalue <= 0) ? 0 : 1;
+               if (set_member_paused(args.queuename, args.interface, NULL, memvalue)) {
+                       ast_log(LOG_ERROR, "Invalid interface or queue\n");
                        return -1;
                }
-               ao2_unlock(q);
-               ao2_ref(q, -1);
-        } else {
-               ast_log(LOG_ERROR, "Invalid queue\n");
+       } else if (!strcasecmp(args.option, "ignorebusy") /* ignorebusy is legacy */
+               || !strcasecmp(args.option, "ringinuse")) {
+               memvalue = (memvalue <= 0) ? 0 : 1;
+               if (set_member_value(args.queuename, args.interface, MEMBER_RINGINUSE, memvalue)) {
+                       ast_log(LOG_ERROR, "Invalid interface or queue\n");
+                       return -1;
+               }
+       } else {
+               ast_log(LOG_ERROR, "%s: Invalid option '%s' provided.\n", cmd, args.option);
                return -1;
        }
        return 0;
index b0caab8..17cbf03 100755 (executable)
@@ -31,7 +31,7 @@ PACKAGES_DEBIAN="$PACKAGES_DEBIAN libresample-dev libc-client-dev binutils-dev l
 PACKAGES_DEBIAN="$PACKAGES_DEBIAN subversion git libxslt1-dev"
 PACKAGES_RH="automake gcc gcc-c++ ncurses-devel openssl-devel libxml2-devel unixODBC-devel libcurl-devel libogg-devel libvorbis-devel speex-devel"
 PACKAGES_RH="$PACKAGES_RH spandsp-devel freetds-devel net-snmp-devel iksemel-devel corosynclib-devel newt-devel popt-devel libtool-ltdl-devel lua-devel"
-PACKAGES_RH="$PACKAGES_RH libsqlite3x-devel radiusclient-ng-devel portaudio-devel postgresql-devel libresample-devel neon-devel libical-devel"
+PACKAGES_RH="$PACKAGES_RH sqlite-devel libsqlite3x-devel radiusclient-ng-devel portaudio-devel postgresql-devel libresample-devel neon-devel libical-devel"
 PACKAGES_RH="$PACKAGES_RH openldap-devel gmime22-devel sqlite2-devel mysql-devel bluez-libs-devel jack-audio-connection-kit-devel gsm-devel libedit-devel libuuid-devel"
 PACKAGES_RH="$PACKAGES_RH jansson-devel libsrtp-devel pjproject-devel subversion git libxslt-devel"
 
index 528e7f8..ed02437 100644 (file)
@@ -174,7 +174,7 @@ int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
                return -1;
        }
 
-       ast_debug(3, "Examining ARI event (length %zu): \n%s\n", strlen(str), str);
+       ast_debug(3, "Examining ARI event (length %u): \n%s\n", (unsigned int) strlen(str), str);
        if (ast_websocket_write_string(session->ws_session, str)) {
                ast_log(LOG_NOTICE, "Problem occurred during websocket write, websocket closed\n");
                return -1;
index 0575fde..62083bf 100644 (file)
@@ -180,8 +180,7 @@ int ast_ari_add_handler(struct stasis_rest_handlers *handler)
 
        SCOPED_MUTEX(lock, &root_handler_lock);
 
-       old_size = sizeof(*new_handler) +
-               root_handler->num_children * sizeof(handler);
+       old_size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
        new_size = old_size + sizeof(handler);
 
        new_handler = ao2_alloc(new_size, NULL);
@@ -200,21 +199,24 @@ int ast_ari_add_handler(struct stasis_rest_handlers *handler)
 
 int ast_ari_remove_handler(struct stasis_rest_handlers *handler)
 {
-       RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
-       size_t size, i, j;
+       struct stasis_rest_handlers *new_handler;
+       size_t size;
+       size_t i;
+       size_t j;
 
        ast_assert(root_handler != NULL);
 
        ast_mutex_lock(&root_handler_lock);
-       size = sizeof(*new_handler) +
-               root_handler->num_children * sizeof(handler);
+       size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
 
        new_handler = ao2_alloc(size, NULL);
        if (!new_handler) {
+               ast_mutex_unlock(&root_handler_lock);
                return -1;
        }
-       memcpy(new_handler, root_handler, sizeof(*new_handler));
 
+       /* Create replacement root_handler less the handler to remove. */
+       memcpy(new_handler, root_handler, sizeof(*new_handler));
        for (i = 0, j = 0; i < root_handler->num_children; ++i) {
                if (root_handler->children[i] == handler) {
                        ast_module_unref(ast_module_info->self);
@@ -224,9 +226,10 @@ int ast_ari_remove_handler(struct stasis_rest_handlers *handler)
        }
        new_handler->num_children = j;
 
+       /* Replace the old root_handler with the new. */
        ao2_cleanup(root_handler);
-       ao2_ref(new_handler, +1);
        root_handler = new_handler;
+
        ast_mutex_unlock(&root_handler_lock);
        return 0;
 }
index a29daa8..c40aae6 100644 (file)
@@ -209,7 +209,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_server_add_protocol)(struct ast_websocke
 
        protocol = ast_websocket_sub_protocol_alloc(name);
        if (!protocol) {
-               ao2_unlock(server->protocols);
                return -1;
        }
        protocol->session_established = callback;
@@ -833,6 +832,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
                        ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to generate a session id\n",
                                ast_sockaddr_stringify(&ser->remote_address));
                        ast_http_error(ser, 500, "Internal Server Error", "Allocation failed");
+                       ao2_ref(protocol_handler, -1);
                        return 0;
                }
 
@@ -840,6 +840,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
                    && protocol_handler->session_attempted(ser, get_vars, headers, session->session_id)) {
                        ast_debug(3, "WebSocket connection from '%s' rejected by protocol handler '%s'\n",
                                ast_sockaddr_stringify(&ser->remote_address), protocol_handler->name);
+                       websocket_bad_request(ser);
                        ao2_ref(protocol_handler, -1);
                        return 0;
                }