Merge "PJPROJECT logging: Fix detection of max supported log level."
authorzuul <zuul@gerrit.asterisk.org>
Fri, 27 Jan 2017 00:46:22 +0000 (18:46 -0600)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Fri, 27 Jan 2017 00:46:22 +0000 (18:46 -0600)
46 files changed:
CHANGES
UPGRADE.txt
apps/app_queue.c
channels/chan_oss.c
include/asterisk/ari.h
include/asterisk/mod_format.h
include/asterisk/stasis_app.h
include/asterisk/translate.h
main/app.c
main/astobj2.c
main/channel.c
main/format_compatibility.c
main/frame.c
main/strings.c
res/ari/ari_websockets.c
res/ari/cli.c
res/ari/resource_events.c
res/res_ari.c
res/res_ari_applications.c
res/res_ari_asterisk.c
res/res_ari_bridges.c
res/res_ari_channels.c
res/res_ari_device_states.c
res/res_ari_endpoints.c
res/res_ari_events.c
res/res_ari_mailboxes.c
res/res_ari_playbacks.c
res/res_ari_recordings.c
res/res_ari_sounds.c
res/res_musiconhold.c
res/res_pjsip/pjsip_configuration.c
res/res_pjsip_endpoint_identifier_ip.c
res/res_pjsip_pubsub.c
res/res_rtp_asterisk.c
res/res_stasis.c
res/stasis/app.c
res/stasis/app.h
res/stasis/cli.c [deleted file]
res/stasis/cli.h [deleted file]
res/stasis/stasis_bridge.c
rest-api-templates/param_parsing.mustache
rest-api-templates/res_ari_resource.c.mustache
tests/test_ari.c
tests/test_voicemail_api.c
third-party/pjproject/Makefile
third-party/pjproject/patches/0000-set_apps_initial_log_level.patch [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 5921e9b..1671d36 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -121,6 +121,14 @@ res_pjsip_endpoint_identifier_ip
    source IP addresses for requests. This is configurable using the
    "srv_lookups" option on the identify and defaults to "yes".
 
+ARI
+------------------
+ * The 'ari set debug' command has been enhanced to accept 'all' as an
+   application name.  This allows dumping of all apps even if an app
+   hasn't registered yet.
+
+ * 'ari set debug' now displays requests and responses as well as events.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ------------
 ------------------------------------------------------------------------------
index 6cb6148..569cc92 100644 (file)
@@ -33,6 +33,10 @@ Queue:
    their ringinuse value updated to the value of the queue. Previously, the
    ringinuse value for dynamic members was not updated on reload.
 
+Queue log:
+ - New RINGCANCELED event is logged when the caller hangs up while ringing.
+   The data1 field contains number of miliseconds since start of ringing.
+
 Channel Drivers:
 
 chan_dahdi:
index 68ee616..da24c51 100644 (file)
@@ -4791,6 +4791,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 #endif
        char *inchan_name;
        struct timeval start_time_tv = ast_tvnow();
+       int canceled_by_caller = 0; /* 1 when caller hangs up or press digit or press * */
 
        ast_channel_lock(qe->chan);
        inchan_name = ast_strdupa(ast_channel_name(qe->chan));
@@ -5229,29 +5230,33 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                        if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
                                /* Got hung up */
                                *to = -1;
-                               publish_dial_end_event(in, outgoing, NULL, "CANCEL");
                                if (f) {
                                        if (f->data.uint32) {
                                                ast_channel_hangupcause_set(in, f->data.uint32);
                                        }
                                        ast_frfree(f);
                                }
-                               return NULL;
-                       }
-
-                       if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
+                               canceled_by_caller = 1;
+                       } else if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
                                ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
                                *to = 0;
-                               publish_dial_end_event(in, outgoing, NULL, "CANCEL");
                                ast_frfree(f);
-                               return NULL;
-                       }
-                       if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
+                               canceled_by_caller = 1;
+                       } else if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
                                ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
                                *to = 0;
-                               publish_dial_end_event(in, outgoing, NULL, "CANCEL");
                                *digit = f->subclass.integer;
                                ast_frfree(f);
+                               canceled_by_caller = 1;
+                       }
+                       /* When caller hung up or pressed * or digit. */
+                       if (canceled_by_caller) {
+                               publish_dial_end_event(in, outgoing, NULL, "CANCEL");
+                               for (o = start; o; o = o->call_next) {
+                                       if (o->chan) {
+                                               ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), o->member->membername, "RINGCANCELED", "%d", (int) ast_tvdiff_ms(ast_tvnow(), start_time_tv));
+                                       }
+                               }
                                return NULL;
                        }
 
index 0d1e24a..3e1e38d 100644 (file)
@@ -725,7 +725,7 @@ static struct ast_frame *oss_read(struct ast_channel *c)
                return f;
        /* ok we can build and deliver the frame to the caller */
        f->frametype = AST_FRAME_VOICE;
-       f->subclass.format = ao2_bump(ast_format_slin);
+       f->subclass.format = ast_format_slin;
        f->samples = FRAME_SIZE;
        f->datalen = FRAME_SIZE * 2;
        f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET;
index 4019e94..865b4b0 100644 (file)
@@ -59,7 +59,8 @@ struct ast_ari_response;
 typedef void (*stasis_rest_callback)(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response);
+       struct ast_variable *headers, struct ast_json *body,
+       struct ast_ari_response *response);
 
 /*!
  * \brief Handler for a single RESTful path segment.
@@ -136,7 +137,7 @@ int ast_ari_remove_handler(struct stasis_rest_handlers *handler);
 void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
        const char *uri, enum ast_http_method method,
        struct ast_variable *get_params, struct ast_variable *headers,
-       struct ast_ari_response *response);
+       struct ast_json *body, struct ast_ari_response *response);
 
 /*!
  * \internal
@@ -201,6 +202,15 @@ const char *ast_ari_websocket_session_id(
        const struct ast_ari_websocket_session *session);
 
 /*!
+ * \brief Get the remote address from an ARI WebSocket.
+ *
+ * \param session Session to write to.
+ * \return ast_sockaddr (does not have to be freed)
+ */
+struct ast_sockaddr *ast_ari_websocket_session_get_remote_addr(
+       struct ast_ari_websocket_session *session);
+
+/*!
  * \brief The stock message to return when out of memory.
  *
  * The refcount is NOT bumped on this object, so ast_json_ref() if you want to
index bcd31de..7e05a28 100644 (file)
@@ -114,7 +114,11 @@ struct ast_filestream {
        int lasttimeout;
        struct ast_channel *owner;
        FILE *f;
-       struct ast_frame fr;    /*!< frame produced by read, typically */
+       /*!
+        * \brief frame produced by read, typically
+        * \note This frame holds a fr.subclass.format ref.
+        */
+       struct ast_frame fr;
        char *buf;              /*!< buffer pointed to by ast_frame; */
        void *_private; /*!< pointer to private buffer */
        const char *orig_chan_name;
index 137cbb9..e131833 100644 (file)
@@ -903,6 +903,56 @@ int stasis_app_control_dial(struct stasis_app_control *control,
  * allocated during the time that res_stasis was loaded.
  */
 void stasis_app_control_shutdown(void);
+
+/*!
+ * \brief Enable/disable request/response and event logging on an application
+ *
+ * \param app The app to debug
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_debug(struct stasis_app *app, int debug);
+
+/*!
+ * \brief Enable/disable request/response and event logging on an application
+ *
+ * \param app_name The app name to debug
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_debug_by_name(const char *app_name, int debug);
+
+/*!
+ * \brief Get debug status of an application
+ *
+ * \param app The app to check
+ * \return The debug flag for the app || the global debug flag
+ */
+int stasis_app_get_debug(struct stasis_app *app);
+
+/*!
+ * \brief Get debug status of an application
+ *
+ * \param app_name The app_name to check
+ * \return The debug flag for the app || the global debug flag
+ */
+int stasis_app_get_debug_by_name(const char *app_name);
+
+/*!
+ * \brief Enable/disable request/response and event logging on all applications
+ *
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_global_debug(int debug);
+
+struct ast_cli_args;
+
+/*!
+ * \brief Dump properties of a \c stasis_app to the CLI
+ *
+ * \param app The application
+ * \param a The CLI arguments
+ */
+void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a);
+
 /*! @} */
 
 #endif /* _ASTERISK_STASIS_APP_H */
index 8188eb8..5c79909 100644 (file)
@@ -208,7 +208,7 @@ struct ast_translator {
  */
 struct ast_trans_pvt {
        struct ast_translator *t;
-       struct ast_frame f;         /*!< used in frameout */
+       struct ast_frame f;         /*!< used in frameout.  This frame holds a f.subclass.format ref. */
        int samples;                /*!< samples available in outbuf */
        /*! \brief actual space used in outbuf */
        int datalen;
index f2e3a0f..1eb0741 100644 (file)
@@ -1422,22 +1422,20 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
        size_t size;
        size_t datalen;
        size_t samples = 0;
-       struct ast_frame *next;
 
        if (!orig) {
                return NULL;
        }
+       do {
+               if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+                       ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
+                       return NULL;
+               }
 
-       if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
-               ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
-               return NULL;
-       }
-
-       for (next = AST_LIST_NEXT(orig, frame_list);
-                orig;
-                orig = next, next = orig ? AST_LIST_NEXT(orig, frame_list) : NULL) {
                samples += orig->samples;
-       }
+
+               orig = AST_LIST_NEXT(orig, frame_list);
+       } while (orig);
 
        ast_verb(4, "Silencing %zu samples\n", samples);
 
@@ -1455,7 +1453,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
        silence->samples = samples;
        silence->datalen = datalen;
 
-       silence->subclass.format = ast_format_slin;
+       silence->subclass.format = ao2_bump(ast_format_slin);
 
        return silence;
 }
@@ -1661,14 +1659,13 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
                                        /* It's all good */
                                        res = 0;
                                } else {
-                                       RAII_VAR(struct ast_frame *, silence, NULL, ast_frame_dtor);
+                                       struct ast_frame *silence = NULL;
                                        struct ast_frame *orig = f;
 
                                        if (muted) {
                                                silence = make_silence(orig);
                                                if (!silence) {
-                                                       ast_log(LOG_WARNING,
-                                                               "Error creating silence\n");
+                                                       ast_log(LOG_WARNING, "Error creating silence\n");
                                                        break;
                                                }
                                                f = silence;
@@ -1679,6 +1676,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
                                                }
                                                res = ast_writestream(others[x], f);
                                        }
+                                       ast_frame_dtor(silence);
                                        f = orig;
                                }
 
index c8e48bb..1529e91 100644 (file)
@@ -524,6 +524,20 @@ int __ao2_ref(void *user_data, int delta,
 
        if (0 < current_value) {
                /* The object still lives. */
+#define EXCESSIVE_REF_COUNT            100000
+
+               if (EXCESSIVE_REF_COUNT <= current_value && ret < EXCESSIVE_REF_COUNT) {
+                       char excessive_ref_buf[100];
+
+                       /* We just reached or went over the excessive ref count trigger */
+                       snprintf(excessive_ref_buf, sizeof(excessive_ref_buf),
+                               "Excessive refcount %d reached on ao2 object %p",
+                               current_value, user_data);
+                       ast_log(__LOG_ERROR, file, line, func, "%s\n", excessive_ref_buf);
+
+                       __ast_assert_failed(0, excessive_ref_buf, file, line, func);
+               }
+
                if (ref_log && tag) {
                        fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
                                (delta < 0 ? "" : "+"), delta, ast_get_tid(),
index 4f84717..d916b7c 100644 (file)
@@ -4887,16 +4887,18 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
        if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_TEXT))) {
                struct ast_frame f;
 
+               memset(&f, 0, sizeof(f));
                f.frametype = AST_FRAME_TEXT;
                f.src = "DIALPLAN";
                f.mallocd = AST_MALLOCD_DATA;
                f.datalen = strlen(text);
                f.data.ptr = ast_strdup(text);
-               f.offset = 0;
-               f.seqno = 0;
-
                f.subclass.format = ast_format_t140;
-               res = ast_channel_tech(chan)->write_text(chan, &f);
+
+               if (f.data.ptr) {
+                       res = ast_channel_tech(chan)->write_text(chan, &f);
+                       ast_frfree(&f);
+               }
        } else if (ast_channel_tech(chan)->send_text) {
                res = ast_channel_tech(chan)->send_text(chan, text);
        }
index 84514ac..256d3a5 100644 (file)
@@ -262,10 +262,10 @@ struct ast_format *ast_format_compatibility_bitfield2format(uint64_t bitfield)
 
        /*! T.140 RED Text format RFC 4103 */
        case AST_FORMAT_T140_RED:
-               return ast_format_t140;
+               return ast_format_t140_red;
        /*! T.140 Text format - ITU T.140, RFC 4103 */
        case AST_FORMAT_T140:
-               return ast_format_t140_red;
+               return ast_format_t140;
        }
        return NULL;
 }
index 0175c72..133928b 100644 (file)
@@ -82,9 +82,9 @@ static struct ast_frame *ast_frame_header_new(void)
        if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
                if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
                        size_t mallocd_len = f->mallocd_hdr_len;
+
                        memset(f, 0, sizeof(*f));
                        f->mallocd_hdr_len = mallocd_len;
-                       f->mallocd = AST_MALLOCD_HDR;
                        frames->size--;
                        return f;
                }
@@ -139,12 +139,12 @@ static void __frame_free(struct ast_frame *fr, int cache)
 #endif
 
        if (fr->mallocd & AST_MALLOCD_DATA) {
-               if (fr->data.ptr)
+               if (fr->data.ptr) {
                        ast_free(fr->data.ptr - fr->offset);
+               }
        }
        if (fr->mallocd & AST_MALLOCD_SRC) {
-               if (fr->src)
-                       ast_free((void *) fr->src);
+               ast_free((void *) fr->src);
        }
        if (fr->mallocd & AST_MALLOCD_HDR) {
                if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
@@ -206,14 +206,14 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
                        return NULL;
                }
                out->frametype = fr->frametype;
+               out->subclass = fr->subclass;
                if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
                        (fr->frametype == AST_FRAME_IMAGE)) {
-                       out->subclass.format = ao2_bump(fr->subclass.format);
-               } else {
-                       memcpy(&out->subclass, &fr->subclass, sizeof(out->subclass));
+                       ao2_bump(out->subclass.format);
                }
                out->datalen = fr->datalen;
                out->samples = fr->samples;
+               out->mallocd = AST_MALLOCD_HDR;
                out->offset = fr->offset;
                /* Copy the timing data */
                ast_copy_flags(out, fr, AST_FLAGS_ALL);
@@ -226,47 +226,64 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
                out = fr;
        }
 
-       if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
-               if (!(out->src = ast_strdup(fr->src))) {
-                       if (out != fr) {
-                               ast_free(out);
+       if (fr->src) {
+               /* The original frame has a source string */
+               if (!(fr->mallocd & AST_MALLOCD_SRC)) {
+                       /*
+                        * The original frame has a non-malloced source string.
+                        *
+                        * Duplicate the string and put it into the isolated frame
+                        * which may also be the original frame.
+                        */
+                       newdata = ast_strdup(fr->src);
+                       if (!newdata) {
+                               if (out != fr) {
+                                       ast_frame_free(out, 0);
+                               }
+                               return NULL;
                        }
-                       return NULL;
+                       out->src = newdata;
+                       out->mallocd |= AST_MALLOCD_SRC;
+               } else if (out != fr) {
+                       /* Steal the source string from the original frame. */
+                       out->src = fr->src;
+                       fr->src = NULL;
+                       fr->mallocd &= ~AST_MALLOCD_SRC;
+                       out->mallocd |= AST_MALLOCD_SRC;
                }
-       } else {
-               out->src = fr->src;
-               fr->src = NULL;
-               fr->mallocd &= ~AST_MALLOCD_SRC;
        }
 
        if (!(fr->mallocd & AST_MALLOCD_DATA))  {
+               /* The original frame has a non-malloced data buffer. */
                if (!fr->datalen) {
+                       /* Actually it's just an int so we can simply copy it. */
                        out->data.uint32 = fr->data.uint32;
-                       out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC;
                        return out;
                }
-               if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
-                       if (out->src != fr->src) {
-                               ast_free((void *) out->src);
-                       }
+               /*
+                * Duplicate the data buffer and put it into the isolated frame
+                * which may also be the original frame.
+                */
+               newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET);
+               if (!newdata) {
                        if (out != fr) {
-                               ast_free(out);
+                               ast_frame_free(out, 0);
                        }
                        return NULL;
                }
                newdata += AST_FRIENDLY_OFFSET;
                out->offset = AST_FRIENDLY_OFFSET;
-               out->datalen = fr->datalen;
                memcpy(newdata, fr->data.ptr, fr->datalen);
                out->data.ptr = newdata;
-       } else {
+               out->mallocd |= AST_MALLOCD_DATA;
+       } else if (out != fr) {
+               /* Steal the data buffer from the original frame. */
                out->data = fr->data;
                memset(&fr->data, 0, sizeof(fr->data));
                fr->mallocd &= ~AST_MALLOCD_DATA;
+               out->mallocd |= AST_MALLOCD_DATA;
        }
 
-       out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
-
        return out;
 }
 
index b8f1ccb..d29da67 100644 (file)
@@ -184,15 +184,32 @@ static int str_hash(const void *obj, const int flags)
        return ast_str_hash(obj);
 }
 
+static int str_sort(const void *lhs, const void *rhs, int flags)
+{
+       if ((flags & OBJ_SEARCH_MASK) == OBJ_SEARCH_PARTIAL_KEY) {
+               return strncmp(lhs, rhs, strlen(rhs));
+       } else {
+               return strcmp(lhs, rhs);
+       }
+}
+
 static int str_cmp(void *lhs, void *rhs, int flags)
 {
-       return strcmp(lhs, rhs) ? 0 : CMP_MATCH;
+       int cmp = 0;
+
+       if ((flags & OBJ_SEARCH_MASK) == OBJ_SEARCH_PARTIAL_KEY) {
+               cmp = strncmp(lhs, rhs, strlen(rhs));
+       } else {
+               cmp = strcmp(lhs, rhs);
+       }
+
+       return cmp ? 0 : CMP_MATCH;
 }
 
 //struct ao2_container *ast_str_container_alloc_options(enum ao2_container_opts opts, int buckets)
 struct ao2_container *ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
 {
-       return ao2_container_alloc_options(opts, buckets, str_hash, str_cmp);
+       return ao2_container_alloc_hash(opts, 0, buckets, str_hash, str_sort, str_cmp);
 }
 
 int ast_str_container_add(struct ao2_container *str_container, const char *add)
index f1e63d3..4f8d6df 100644 (file)
@@ -21,6 +21,7 @@
 #include "asterisk/ari.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/http_websocket.h"
+#include "asterisk/stasis_app.h"
 #include "internal.h"
 
 /*! \file
@@ -137,6 +138,7 @@ struct ast_json *ast_ari_websocket_session_read(
                                ast_log(LOG_WARNING,
                                        "WebSocket input failed to parse\n");
                        }
+
                        break;
                default:
                        /* Ignore all other message types */
@@ -172,16 +174,20 @@ int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
                return -1;
        }
 
-#ifdef AST_DEVMODE
-       ast_debug(3, "Examining ARI event (length %u): \n%s\n", (unsigned int) strlen(str), str);
-#endif
        if (ast_websocket_write_string(session->ws_session, str)) {
-               ast_log(LOG_NOTICE, "Problem occurred during websocket write, websocket closed\n");
+               ast_log(LOG_NOTICE, "Problem occurred during websocket write to %s, websocket closed\n",
+                       ast_sockaddr_stringify(ast_ari_websocket_session_get_remote_addr(session)));
                return -1;
        }
        return 0;
 }
 
+struct ast_sockaddr *ast_ari_websocket_session_get_remote_addr(
+       struct ast_ari_websocket_session *session)
+{
+       return ast_websocket_remote_address(session->ws_session);
+}
+
 void ari_handle_websocket(struct ast_websocket_server *ws_server,
        struct ast_tcptls_session_instance *ser, const char *uri,
        enum ast_http_method method, struct ast_variable *get_params,
index 9d156f2..9d0eb30 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "asterisk/astobj2.h"
 #include "asterisk/cli.h"
+#include "asterisk/stasis_app.h"
 #include "internal.h"
 
 static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -249,11 +250,185 @@ static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args
        return CLI_SUCCESS;
 }
 
+static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       struct ao2_container *apps;
+       struct ao2_iterator it_apps;
+       char *app;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ari show apps";
+               e->usage =
+                       "Usage: ari show apps\n"
+                       "       Lists all registered applications.\n"
+                       ;
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       default:
+               break;
+       }
+
+       if (a->argc != 3) {
+               return CLI_SHOWUSAGE;
+       }
+
+       apps = stasis_app_get_all();
+       if (!apps) {
+               ast_cli(a->fd, "Unable to retrieve registered applications!\n");
+               return CLI_FAILURE;
+       }
+
+       ast_cli(a->fd, "Application Name         \n");
+       ast_cli(a->fd, "=========================\n");
+       it_apps = ao2_iterator_init(apps, 0);
+       while ((app = ao2_iterator_next(&it_apps))) {
+               ast_cli(a->fd, "%-25.25s\n", app);
+               ao2_ref(app, -1);
+       }
+
+       ao2_iterator_destroy(&it_apps);
+       ao2_ref(apps, -1);
+
+       return CLI_SUCCESS;
+}
+
+struct app_complete {
+       /*! Nth app to search for */
+       int state;
+       /*! Which app currently on */
+       int which;
+};
+
+static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
+{
+       struct app_complete *search = data;
+
+       if (++search->which > search->state) {
+               return CMP_MATCH;
+       }
+       return 0;
+}
+
+static char *complete_ari_app(struct ast_cli_args *a, int include_all)
+{
+       RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
+       RAII_VAR(char *, app, NULL, ao2_cleanup);
+
+       struct app_complete search = {
+               .state = a->n,
+       };
+
+       if (a->pos != 3) {
+               return NULL;
+       }
+
+       if (!apps) {
+               ast_cli(a->fd, "Error getting ARI applications\n");
+               return CLI_FAILURE;
+       }
+
+       if (include_all && ast_strlen_zero(a->word)) {
+               ast_str_container_add(apps, " all");
+       }
+
+       app = ao2_callback_data(apps,
+               ast_strlen_zero(a->word) ? 0 : OBJ_SEARCH_PARTIAL_KEY,
+               complete_ari_app_search, (char*)a->word, &search);
+
+       return app ? ast_strdup(app) : NULL;
+}
+
+static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       void *app;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ari show app";
+               e->usage =
+                       "Usage: ari show app <application>\n"
+                       "       Provide detailed information about a registered application.\n"
+                       ;
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ari_app(a, 0);
+       default:
+               break;
+       }
+
+       if (a->argc != 4) {
+               return CLI_SHOWUSAGE;
+       }
+
+       app = stasis_app_get_by_name(a->argv[3]);
+       if (!app) {
+               return CLI_FAILURE;
+       }
+
+       stasis_app_to_cli(app, a);
+
+       ao2_ref(app, -1);
+
+       return CLI_SUCCESS;
+}
+
+static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       void *app;
+       int debug;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ari set debug";
+               e->usage =
+                       "Usage: ari set debug <application|all> <on|off>\n"
+                       "       Enable or disable debugging on a specific application.\n"
+                       ;
+               return NULL;
+       case CLI_GENERATE:
+               return complete_ari_app(a, 1);
+       default:
+               break;
+       }
+
+       if (a->argc != 5) {
+               return CLI_SHOWUSAGE;
+       }
+
+       debug = !strcmp(a->argv[4], "on");
+
+       if (!strcmp(a->argv[3], "all")) {
+               stasis_app_set_global_debug(debug);
+               ast_cli(a->fd, "Debugging on all applications %s\n",
+                       debug ? "enabled" : "disabled");
+               return CLI_SUCCESS;
+       }
+
+       app = stasis_app_get_by_name(a->argv[3]);
+       if (!app) {
+               return CLI_FAILURE;
+       }
+
+       stasis_app_set_debug(app, debug);
+       ast_cli(a->fd, "Debugging on '%s' %s\n",
+               stasis_app_name(app),
+               debug ? "enabled" : "disabled");
+
+       ao2_ref(app, -1);
+
+       return CLI_SUCCESS;
+}
+
 static struct ast_cli_entry cli_ari[] = {
        AST_CLI_DEFINE(ari_show, "Show ARI settings"),
        AST_CLI_DEFINE(ari_show_users, "List ARI users"),
        AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
        AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
+       AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
+       AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
+       AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
 };
 
 int ast_ari_cli_register(void) {
index 597f4df..ed936f7 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "resource_events.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/http_websocket.h"
 #include "asterisk/stasis_app.h"
 #include "asterisk/vector.h"
 
@@ -108,6 +109,15 @@ static void stasis_app_message_handler(
                                msg_type,
                                msg_application);
        } else {
+               if (stasis_app_get_debug_by_name(app_name)) {
+                       char *str = ast_json_dump_string_format(message, ast_ari_json_format());
+
+                       ast_verbose("<--- Sending ARI event to %s --->\n%s\n",
+                               ast_sockaddr_stringify(ast_ari_websocket_session_get_remote_addr(session->ws_session)),
+                               str);
+                       ast_json_free(str);
+               }
+
                /* We are ready to publish the message */
                ast_ari_websocket_session_write(session->ws_session, message);
        }
index e362a58..549d783 100644 (file)
 #include "asterisk/astobj2.h"
 #include "asterisk/module.h"
 #include "asterisk/paths.h"
+#include "asterisk/stasis_app.h"
 
 #include <string.h>
 #include <sys/stat.h>
@@ -491,7 +492,7 @@ static void handle_options(struct stasis_rest_handlers *handler,
 void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
        const char *uri, enum ast_http_method method,
        struct ast_variable *get_params, struct ast_variable *headers,
-       struct ast_ari_response *response)
+       struct ast_json *body, struct ast_ari_response *response)
 {
        RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup);
        struct stasis_rest_handlers *handler;
@@ -506,8 +507,10 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
        while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
                struct stasis_rest_handlers *found_handler = NULL;
                int i;
+
                ast_uri_decode(path_segment, ast_uri_http_legacy);
                ast_debug(3, "Finding handler for %s\n", path_segment);
+
                for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
                        struct stasis_rest_handlers *child = handler->children[i];
 
@@ -569,7 +572,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
                return;
        }
 
-       callback(ser, get_params, path_vars, headers, response);
+       callback(ser, get_params, path_vars, headers, body, response);
        if (response->message == NULL && response->response_code == 0) {
                /* Really should not happen */
                ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
@@ -879,6 +882,10 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
        RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
        struct ast_ari_response response = { .fd = -1, 0 };
        RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy);
+       struct ast_variable *var;
+       const char *app_name = NULL;
+       RAII_VAR(struct ast_json *, body, ast_json_null(), ast_json_free);
+       int debug_app = 0;
 
        if (!response_body) {
                ast_http_request_close_on_completion(ser);
@@ -926,6 +933,25 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
                                "Bad Request", "Error parsing request body");
                        goto request_failed;
                }
+
+               /* Look for a JSON request entity only if there were no post_vars.
+                * If there were post_vars, then the request body would already have
+                * been consumed and can not be read again.
+                */
+               body = ast_http_get_json(ser, headers);
+               if (!body) {
+                       switch (errno) {
+                       case EFBIG:
+                               ast_ari_response_error(&response, 413, "Request Entity Too Large", "Request body too large");
+                               goto request_failed;
+                       case ENOMEM:
+                               ast_ari_response_error(&response, 500, "Internal Server Error", "Error processing request");
+                               goto request_failed;
+                       case EIO:
+                               ast_ari_response_error(&response, 400, "Bad Request", "Error parsing request body");
+                               goto request_failed;
+                       }
+               }
        }
        if (get_params == NULL) {
                get_params = post_vars;
@@ -942,6 +968,41 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
                get_params = post_vars;
        }
 
+       /* At this point, get_params will contain post_vars (if any) */
+       app_name = ast_variable_find_in_list(get_params, "app");
+       if (!app_name) {
+               struct ast_json *app = ast_json_object_get(body, "app");
+
+               app_name = (app ? ast_json_string_get(app) : NULL);
+       }
+
+       /* stasis_app_get_debug_by_name returns an "||" of the app's debug flag
+        * and the global debug flag.
+        */
+       debug_app = stasis_app_get_debug_by_name(app_name);
+       if (debug_app) {
+               struct ast_str *buf = ast_str_create(512);
+               char *str = ast_json_dump_string_format(body, ast_ari_json_format());
+
+               if (!buf) {
+                       ast_http_request_close_on_completion(ser);
+                       ast_http_error(ser, 500, "Server Error", "Out of memory");
+                       goto request_failed;
+               }
+
+               ast_str_append(&buf, 0, "<--- ARI request received from: %s --->\n",
+                       ast_sockaddr_stringify(&ser->remote_address));
+               for (var = headers; var; var = var->next) {
+                       ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
+               }
+               for (var = get_params; var; var = var->next) {
+                       ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
+               }
+               ast_verbose("%sbody:\n%s\n\n", ast_str_buffer(buf), str);
+               ast_json_free(str);
+               ast_free(buf);
+       }
+
        user = authenticate_user(get_params, headers);
        if (response.response_code > 0) {
                /* POST parameter processing error. Do nothing. */
@@ -980,7 +1041,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
                }
        } else {
                /* Other RESTful resources */
-               ast_ari_invoke(ser, uri, method, get_params, headers,
+               ast_ari_invoke(ser, uri, method, get_params, headers, body,
                        &response);
        }
 
@@ -992,6 +1053,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
        }
 
 request_failed:
+
        /* If you explicitly want to have no content, set message to
         * ast_json_null().
         */
@@ -1014,8 +1076,13 @@ request_failed:
                }
        }
 
-       ast_debug(3, "Examining ARI response:\n%d %s\n%s\n%s\n", response.response_code,
-               response.response_text, ast_str_buffer(response.headers), ast_str_buffer(response_body));
+       if (debug_app) {
+               ast_verbose("<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n",
+                       ast_sockaddr_stringify(&ser->remote_address), response.response_code,
+                       response.response_text, ast_str_buffer(response.headers),
+                       ast_str_buffer(response_body));
+       }
+
        ast_http_send(ser, method, response.response_code,
                      response.response_text, response.headers, response_body,
                      response.fd != -1 ? response.fd : 0, 0);
index 006d30c..951ee85 100644 (file)
 static void ast_ari_applications_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_applications_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -111,11 +110,10 @@ fin: __attribute__((unused))
 static void ast_ari_applications_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_applications_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -208,11 +206,10 @@ int ast_ari_applications_subscribe_parse_body(
 static void ast_ari_applications_subscribe_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_applications_subscribe_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -270,21 +267,6 @@ static void ast_ari_applications_subscribe_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_applications_subscribe_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -374,11 +356,10 @@ int ast_ari_applications_unsubscribe_parse_body(
 static void ast_ari_applications_unsubscribe_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_applications_unsubscribe_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -436,21 +417,6 @@ static void ast_ari_applications_unsubscribe_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_applications_unsubscribe_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
index 5dbf341..1dbd850 100644 (file)
 static void ast_ari_asterisk_get_object_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_get_object_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -133,11 +132,10 @@ int ast_ari_asterisk_update_object_parse_body(
 static void ast_ari_asterisk_update_object_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_update_object_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -155,21 +153,6 @@ static void ast_ari_asterisk_update_object_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.fields = body;
        ast_ari_asterisk_update_object(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -216,11 +199,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_delete_object_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_delete_object_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -320,11 +302,10 @@ int ast_ari_asterisk_get_info_parse_body(
 static void ast_ari_asterisk_get_info_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_get_info_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -376,21 +357,6 @@ static void ast_ari_asterisk_get_info_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_asterisk_get_info_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -439,10 +405,9 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_list_modules_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_list_modules_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -490,11 +455,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_get_module_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_get_module_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -550,11 +514,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_load_module_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_load_module_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -609,11 +572,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_unload_module_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_unload_module_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -669,11 +631,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_reload_module_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_reload_module_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -729,10 +690,9 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_list_log_channels_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_list_log_channels_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -793,11 +753,10 @@ int ast_ari_asterisk_add_log_parse_body(
 static void ast_ari_asterisk_add_log_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_add_log_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -815,21 +774,6 @@ static void ast_ari_asterisk_add_log_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_asterisk_add_log_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -878,11 +822,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_delete_log_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_delete_log_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -937,11 +880,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_rotate_log_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_rotate_log_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1009,11 +951,10 @@ int ast_ari_asterisk_get_global_var_parse_body(
 static void ast_ari_asterisk_get_global_var_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_get_global_var_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1025,21 +966,6 @@ static void ast_ari_asterisk_get_global_var_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_asterisk_get_global_var_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1104,11 +1030,10 @@ int ast_ari_asterisk_set_global_var_parse_body(
 static void ast_ari_asterisk_set_global_var_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_asterisk_set_global_var_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1123,21 +1048,6 @@ static void ast_ari_asterisk_set_global_var_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_asterisk_set_global_var_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
index 0b370c2..e61865e 100644 (file)
 static void ast_ari_bridges_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -132,11 +131,10 @@ int ast_ari_bridges_create_parse_body(
 static void ast_ari_bridges_create_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_create_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -154,21 +152,6 @@ static void ast_ari_bridges_create_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_create_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -232,11 +215,10 @@ int ast_ari_bridges_create_with_id_parse_body(
 static void ast_ari_bridges_create_with_id_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_create_with_id_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -257,21 +239,6 @@ static void ast_ari_bridges_create_with_id_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_create_with_id_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -318,11 +285,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -377,11 +343,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_destroy_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_destroy_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -478,11 +443,10 @@ int ast_ari_bridges_add_channel_parse_body(
 static void ast_ari_bridges_add_channel_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_add_channel_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -543,21 +507,6 @@ static void ast_ari_bridges_add_channel_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_add_channel_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -648,11 +597,10 @@ int ast_ari_bridges_remove_channel_parse_body(
 static void ast_ari_bridges_remove_channel_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_remove_channel_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -710,21 +658,6 @@ static void ast_ari_bridges_remove_channel_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -777,11 +710,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_set_video_source_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_set_video_source_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -841,11 +773,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_clear_video_source_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_clear_video_source_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -913,11 +844,10 @@ int ast_ari_bridges_start_moh_parse_body(
 static void ast_ari_bridges_start_moh_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_start_moh_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -935,21 +865,6 @@ static void ast_ari_bridges_start_moh_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_start_moh_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -998,11 +913,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_stop_moh_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_stop_moh_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1112,11 +1026,10 @@ int ast_ari_bridges_play_parse_body(
 static void ast_ari_bridges_play_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_play_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1186,21 +1099,6 @@ static void ast_ari_bridges_play_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_play_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1301,11 +1199,10 @@ int ast_ari_bridges_play_with_id_parse_body(
 static void ast_ari_bridges_play_with_id_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_play_with_id_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1375,21 +1272,6 @@ static void ast_ari_bridges_play_with_id_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_play_with_id_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1477,11 +1359,10 @@ int ast_ari_bridges_record_parse_body(
 static void ast_ari_bridges_record_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_bridges_record_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1517,21 +1398,6 @@ static void ast_ari_bridges_record_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_bridges_record_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
index 252bc4f..739eb01 100644 (file)
 static void ast_ari_channels_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -172,11 +171,10 @@ int ast_ari_channels_originate_parse_body(
 static void ast_ari_channels_originate_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_originate_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -224,21 +222,6 @@ static void ast_ari_channels_originate_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.variables = body;
        ast_ari_channels_originate(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -321,11 +304,10 @@ int ast_ari_channels_create_parse_body(
 static void ast_ari_channels_create_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_create_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -355,21 +337,6 @@ static void ast_ari_channels_create_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_create_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -417,11 +384,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -533,11 +499,10 @@ int ast_ari_channels_originate_with_id_parse_body(
 static void ast_ari_channels_originate_with_id_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_originate_with_id_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -588,21 +553,6 @@ static void ast_ari_channels_originate_with_id_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.variables = body;
        ast_ari_channels_originate_with_id(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -661,11 +611,10 @@ int ast_ari_channels_hangup_parse_body(
 static void ast_ari_channels_hangup_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_hangup_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -683,21 +632,6 @@ static void ast_ari_channels_hangup_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_hangup_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -771,11 +705,10 @@ int ast_ari_channels_continue_in_dialplan_parse_body(
 static void ast_ari_channels_continue_in_dialplan_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_continue_in_dialplan_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -802,21 +735,6 @@ static void ast_ari_channels_continue_in_dialplan_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_continue_in_dialplan_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -879,11 +797,10 @@ int ast_ari_channels_redirect_parse_body(
 static void ast_ari_channels_redirect_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_redirect_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -901,21 +818,6 @@ static void ast_ari_channels_redirect_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_redirect_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -967,11 +869,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_answer_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_answer_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1028,11 +929,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_ring_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_ring_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1089,11 +989,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_ring_stop_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_ring_stop_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1179,11 +1078,10 @@ int ast_ari_channels_send_dtmf_parse_body(
 static void ast_ari_channels_send_dtmf_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_send_dtmf_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1213,21 +1111,6 @@ static void ast_ari_channels_send_dtmf_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_send_dtmf_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1291,11 +1174,10 @@ int ast_ari_channels_mute_parse_body(
 static void ast_ari_channels_mute_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_mute_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1313,21 +1195,6 @@ static void ast_ari_channels_mute_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_mute_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1390,11 +1257,10 @@ int ast_ari_channels_unmute_parse_body(
 static void ast_ari_channels_unmute_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_unmute_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1412,21 +1278,6 @@ static void ast_ari_channels_unmute_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_unmute_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1476,11 +1327,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_hold_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_hold_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1537,11 +1387,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_unhold_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_unhold_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1611,11 +1460,10 @@ int ast_ari_channels_start_moh_parse_body(
 static void ast_ari_channels_start_moh_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_start_moh_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1633,21 +1481,6 @@ static void ast_ari_channels_start_moh_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_start_moh_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -1697,11 +1530,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_stop_moh_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_stop_moh_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1758,11 +1590,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_start_silence_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_start_silence_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1819,11 +1650,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_stop_silence_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_stop_silence_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -1934,11 +1764,10 @@ int ast_ari_channels_play_parse_body(
 static void ast_ari_channels_play_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_play_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2008,21 +1837,6 @@ static void ast_ari_channels_play_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_play_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2124,11 +1938,10 @@ int ast_ari_channels_play_with_id_parse_body(
 static void ast_ari_channels_play_with_id_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_play_with_id_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2198,21 +2011,6 @@ static void ast_ari_channels_play_with_id_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_play_with_id_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2301,11 +2099,10 @@ int ast_ari_channels_record_parse_body(
 static void ast_ari_channels_record_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_record_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2341,21 +2138,6 @@ static void ast_ari_channels_record_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_record_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2419,11 +2201,10 @@ int ast_ari_channels_get_channel_var_parse_body(
 static void ast_ari_channels_get_channel_var_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_get_channel_var_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2441,21 +2222,6 @@ static void ast_ari_channels_get_channel_var_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_get_channel_var_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2522,11 +2288,10 @@ int ast_ari_channels_set_channel_var_parse_body(
 static void ast_ari_channels_set_channel_var_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_set_channel_var_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2547,21 +2312,6 @@ static void ast_ari_channels_set_channel_var_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_set_channel_var_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2640,11 +2390,10 @@ int ast_ari_channels_snoop_channel_parse_body(
 static void ast_ari_channels_snoop_channel_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_snoop_channel_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2674,21 +2423,6 @@ static void ast_ari_channels_snoop_channel_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_snoop_channel_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2762,11 +2496,10 @@ int ast_ari_channels_snoop_channel_with_id_parse_body(
 static void ast_ari_channels_snoop_channel_with_id_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_snoop_channel_with_id_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2796,21 +2529,6 @@ static void ast_ari_channels_snoop_channel_with_id_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_snoop_channel_with_id_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -2876,11 +2594,10 @@ int ast_ari_channels_dial_parse_body(
 static void ast_ari_channels_dial_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_channels_dial_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -2901,21 +2618,6 @@ static void ast_ari_channels_dial_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_channels_dial_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
index 39e678f..b2aea52 100644 (file)
 static void ast_ari_device_states_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_device_states_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -111,11 +110,10 @@ fin: __attribute__((unused))
 static void ast_ari_device_states_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_device_states_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -182,11 +180,10 @@ int ast_ari_device_states_update_parse_body(
 static void ast_ari_device_states_update_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_device_states_update_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -204,21 +201,6 @@ static void ast_ari_device_states_update_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_device_states_update_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -267,11 +249,10 @@ fin: __attribute__((unused))
 static void ast_ari_device_states_delete_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_device_states_delete_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
index 5307cd1..944146f 100644 (file)
 static void ast_ari_endpoints_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_endpoints_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -132,11 +131,10 @@ int ast_ari_endpoints_send_message_parse_body(
 static void ast_ari_endpoints_send_message_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_endpoints_send_message_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -154,21 +152,6 @@ static void ast_ari_endpoints_send_message_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.variables = body;
        ast_ari_endpoints_send_message(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -214,11 +197,10 @@ fin: __attribute__((unused))
 static void ast_ari_endpoints_list_by_tech_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_endpoints_list_by_tech_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -273,11 +255,10 @@ fin: __attribute__((unused))
 static void ast_ari_endpoints_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_endpoints_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -353,11 +334,10 @@ int ast_ari_endpoints_send_message_to_endpoint_parse_body(
 static void ast_ari_endpoints_send_message_to_endpoint_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_endpoints_send_message_to_endpoint_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -381,21 +361,6 @@ static void ast_ari_endpoints_send_message_to_endpoint_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.variables = body;
        ast_ari_endpoints_send_message_to_endpoint(headers, &args, response);
 #if defined(AST_DEVMODE)
index 36c9b06..8ccb887 100644 (file)
@@ -287,11 +287,10 @@ int ast_ari_events_user_event_parse_body(
 static void ast_ari_events_user_event_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_events_user_event_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -352,21 +351,6 @@ static void ast_ari_events_user_event_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        args.variables = body;
        ast_ari_events_user_event(headers, &args, response);
 #if defined(AST_DEVMODE)
index 4d418fe..2eac609 100644 (file)
 static void ast_ari_mailboxes_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_mailboxes_list_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -111,11 +110,10 @@ fin: __attribute__((unused))
 static void ast_ari_mailboxes_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_mailboxes_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -187,11 +185,10 @@ int ast_ari_mailboxes_update_parse_body(
 static void ast_ari_mailboxes_update_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_mailboxes_update_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -212,21 +209,6 @@ static void ast_ari_mailboxes_update_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_mailboxes_update_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -274,11 +256,10 @@ fin: __attribute__((unused))
 static void ast_ari_mailboxes_delete_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_mailboxes_delete_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
index 9678830..8267a91 100644 (file)
 static void ast_ari_playbacks_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_playbacks_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -119,11 +118,10 @@ fin: __attribute__((unused))
 static void ast_ari_playbacks_stop_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_playbacks_stop_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -191,11 +189,10 @@ int ast_ari_playbacks_control_parse_body(
 static void ast_ari_playbacks_control_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_playbacks_control_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -213,21 +210,6 @@ static void ast_ari_playbacks_control_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_playbacks_control_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
index a43bbdd..e82605c 100644 (file)
 static void ast_ari_recordings_list_stored_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_list_stored_args args = {};
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -111,11 +110,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_get_stored_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_get_stored_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -170,11 +168,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_delete_stored_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_delete_stored_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -229,11 +226,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_get_stored_file_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_get_stored_file_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -302,11 +298,10 @@ int ast_ari_recordings_copy_stored_parse_body(
 static void ast_ari_recordings_copy_stored_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_copy_stored_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -324,21 +319,6 @@ static void ast_ari_recordings_copy_stored_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_recordings_copy_stored_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -387,11 +367,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_get_live_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_get_live_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -446,11 +425,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_cancel_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_cancel_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -505,11 +483,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_stop_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_stop_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -564,11 +541,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_pause_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_pause_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -624,11 +600,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_unpause_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_unpause_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -684,11 +659,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_mute_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_mute_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -744,11 +718,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_unmute_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_recordings_unmute_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
index eb4bbb3..fe0692f 100644 (file)
@@ -77,11 +77,10 @@ int ast_ari_sounds_list_parse_body(
 static void ast_ari_sounds_list_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_sounds_list_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
@@ -96,21 +95,6 @@ static void ast_ari_sounds_list_cb(
                } else
                {}
        }
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
        if (ast_ari_sounds_list_parse_body(body, &args)) {
                ast_ari_response_alloc_failed(response);
                goto fin;
@@ -157,11 +141,10 @@ fin: __attribute__((unused))
 static void ast_ari_sounds_get_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_sounds_get_args args = {};
        struct ast_variable *i;
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
index 3a751ec..70bb040 100644 (file)
@@ -1058,13 +1058,14 @@ static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclas
                                ast_set_flag(mohclass, MOH_RANDSTART);
                        }
                } else if (!strcasecmp(var->name, "format")) {
+                       ao2_cleanup(mohclass->format);
                        mohclass->format = ast_format_cache_get(var->value);
                        if (!mohclass->format) {
                                ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
                                mohclass->format = ao2_bump(ast_format_slin);
                        }
-               }
-       }
+               }
+       }
 }
 
 static int moh_add_file(struct mohclass *class, const char *filepath)
index 6a15946..1111664 100644 (file)
@@ -2069,6 +2069,8 @@ static void endpoint_destructor(void* obj)
        ast_variables_destroy(endpoint->channel_vars);
        AST_VECTOR_FREE(&endpoint->ident_method_order);
        ast_free(endpoint->contact_user);
+       ast_free_acl_list(endpoint->contact_acl);
+       ast_free_acl_list(endpoint->acl);
 }
 
 static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
index 63b254d..116e2d8 100644 (file)
@@ -247,7 +247,7 @@ static int ip_identify_match_handler(const struct aco_option *opt, struct ast_va
 
        while ((current_string = ast_strip(strsep(&input_string, ",")))) {
                char *mask = strrchr(current_string, '/');
-               int error;
+               int error = 0;
 
                if (ast_strlen_zero(current_string)) {
                        continue;
index 5799379..42f0dc1 100644 (file)
@@ -42,6 +42,7 @@
 #include "asterisk/res_pjsip.h"
 #include "asterisk/callerid.h"
 #include "asterisk/manager.h"
+#include "asterisk/cli.h"
 #include "asterisk/test.h"
 #include "res_pjsip/include/res_pjsip_private.h"
 #include "asterisk/res_pjsip_presence_xml.h"
@@ -3694,6 +3695,541 @@ static int ami_show_resource_lists(struct mansession *s, const struct message *m
 #define AMI_SHOW_SUBSCRIPTIONS_INBOUND "PJSIPShowSubscriptionsInbound"
 #define AMI_SHOW_SUBSCRIPTIONS_OUTBOUND "PJSIPShowSubscriptionsOutbound"
 
+#define MAX_REGEX_ERROR_LEN 128
+
+struct cli_sub_parms {
+       /*! CLI handler entry e parameter */
+       struct ast_cli_entry *e;
+       /*! CLI handler entry a parameter */
+       struct ast_cli_args *a;
+       /*! CLI subscription entry output line(s) */
+       struct ast_str *buf;
+       /*! Compiled regular expression to select if buf is written to CLI when not NULL. */
+       regex_t *like;
+       int count;
+};
+
+struct cli_sub_complete_parms {
+       struct ast_cli_args *a;
+       /*! Found callid for search position */
+       char *callid;
+       int wordlen;
+       int which;
+};
+
+static int cli_complete_subscription_common(struct sip_subscription_tree *sub_tree, struct cli_sub_complete_parms *cli)
+{
+       pj_str_t *callid;
+
+       if (!sub_tree->dlg) {
+               return 0;
+       }
+
+       callid = &sub_tree->dlg->call_id->id;
+       if (cli->wordlen <= pj_strlen(callid)
+               && !strncasecmp(cli->a->word, pj_strbuf(callid), cli->wordlen)
+               && (++cli->which > cli->a->n)) {
+               cli->callid = ast_malloc(pj_strlen(callid) + 1);
+               if (cli->callid) {
+                       ast_copy_pj_str(cli->callid, callid, pj_strlen(callid) + 1);
+               }
+               return -1;
+       }
+       return 0;
+}
+
+static int cli_complete_subscription_inbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_NOTIFIER
+               ? cli_complete_subscription_common(sub_tree, arg) : 0;
+}
+
+static int cli_complete_subscription_outbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_SUBSCRIBER
+               ? cli_complete_subscription_common(sub_tree, arg) : 0;
+}
+
+static char *cli_complete_subscription_callid(struct ast_cli_args *a)
+{
+       struct cli_sub_complete_parms cli;
+       on_subscription_t on_subscription;
+
+       if (a->pos != 4) {
+               return NULL;
+       }
+
+       if (!strcasecmp(a->argv[3], "inbound")) {
+               on_subscription = cli_complete_subscription_inbound;
+       } else if (!strcasecmp(a->argv[3], "outbound")) {
+               on_subscription = cli_complete_subscription_outbound;
+       } else {
+               /* Should never get here */
+               ast_assert(0);
+               return NULL;
+       }
+
+       cli.a = a;
+       cli.callid = NULL;
+       cli.wordlen = strlen(a->word);
+       cli.which = 0;
+       for_each_subscription(on_subscription, &cli);
+
+       return cli.callid;
+}
+
+static int cli_subscription_expiry(struct sip_subscription_tree *sub_tree)
+{
+       int expiry;
+
+       expiry = sub_tree->persistence
+               ? ast_tvdiff_ms(sub_tree->persistence->expires, ast_tvnow()) / 1000
+               : 0;
+       if (expiry < 0) {
+               /* Subscription expired */
+               expiry = 0;
+       }
+       return expiry;
+}
+
+static int cli_show_subscription_common(struct sip_subscription_tree *sub_tree, struct cli_sub_parms *cli)
+{
+       const char *callid = (const char *) cli->buf;/* Member repurposed to pass in callid */
+       pj_str_t *sub_callid;
+       struct ast_str *buf;
+       char *src;
+       char *dest;
+       char *key;
+       char *value;
+       char *value_end;
+       int key_len;
+       int key_filler_width;
+       int value_len;
+
+       if (!sub_tree->dlg) {
+               return 0;
+       }
+       sub_callid = &sub_tree->dlg->call_id->id;
+       if (pj_strcmp2(sub_callid, callid)) {
+               return 0;
+       }
+
+       buf = ast_str_create(512);
+       if (!buf) {
+               return -1;
+       }
+
+       ast_cli(cli->a->fd,
+               "%-20s: %s\n"
+               "===========================================================================\n",
+               "ParameterName", "ParameterValue");
+
+       ast_str_append(&buf, 0, "Resource: %s\n", sub_tree->root->resource);
+       ast_str_append(&buf, 0, "Event: %s\n", sub_tree->root->handler->event_name);
+       ast_str_append(&buf, 0, "Expiry: %d\n", cli_subscription_expiry(sub_tree));
+
+       sip_subscription_to_ami(sub_tree, &buf);
+
+       /* Convert AMI \r\n to \n line terminators. */
+       src = strchr(ast_str_buffer(buf), '\r');
+       if (src) {
+               dest = src;
+               ++src;
+               while (*src) {
+                       if (*src == '\r') {
+                               ++src;
+                               continue;
+                       }
+                       *dest++ = *src++;
+               }
+               *dest = '\0';
+               ast_str_update(buf);
+       }
+
+       /* Reformat AMI key value pairs to pretty columns */
+       key = ast_str_buffer(buf);
+       do {
+               value = strchr(key, ':');
+               if (!value) {
+                       break;
+               }
+               value_end = strchr(value, '\n');
+               if (!value_end) {
+                       break;
+               }
+
+               /* Calculate field lengths */
+               key_len = value - key;
+               key_filler_width = 20 - key_len;
+               if (key_filler_width < 0) {
+                       key_filler_width = 0;
+               }
+               value_len = value_end - value;
+
+               ast_cli(cli->a->fd, "%.*s%*s%.*s\n",
+                       key_len, key, key_filler_width, "",
+                       value_len, value);
+
+               key = value_end + 1;
+       } while (*key);
+       ast_cli(cli->a->fd, "\n");
+
+       ast_free(buf);
+
+       return -1;
+}
+
+static int cli_show_subscription_inbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_NOTIFIER
+               ? cli_show_subscription_common(sub_tree, arg) : 0;
+}
+
+static int cli_show_subscription_outbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_SUBSCRIBER
+               ? cli_show_subscription_common(sub_tree, arg) : 0;
+}
+
+static char *cli_show_subscription_inout(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       on_subscription_t on_subscription;
+       struct cli_sub_parms cli;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pjsip show subscription {inbound|outbound}";
+               e->usage = "Usage:\n"
+                                  "   pjsip show subscription inbound <call-id>\n"
+                                  "   pjsip show subscription outbound <call-id>\n"
+                                  "      Show active subscription with the dialog call-id\n";
+               return NULL;
+       case CLI_GENERATE:
+               return cli_complete_subscription_callid(a);
+       }
+
+       if (a->argc != 5) {
+               return CLI_SHOWUSAGE;
+       }
+
+       if (!strcasecmp(a->argv[3], "inbound")) {
+               on_subscription = cli_show_subscription_inbound;
+       } else if (!strcasecmp(a->argv[3], "outbound")) {
+               on_subscription = cli_show_subscription_outbound;
+       } else {
+               /* Should never get here */
+               ast_assert(0);
+               return NULL;
+       }
+
+       /* Find the subscription with the specified call-id */
+       cli.a = a;
+       cli.e = e;
+       cli.buf = (void *) a->argv[4];/* Repurpose the buf member to pass in callid */
+       for_each_subscription(on_subscription, &cli);
+
+       return CLI_SUCCESS;
+}
+
+#define CLI_SHOW_SUB_FORMAT_HEADER \
+       "Endpoint: <Endpoint/Caller-ID.............................................>\n" \
+       "Resource: <Resource/Event.................................................>\n" \
+       "  Expiry: <Expiry>  <Call-id..............................................>\n" \
+       "===========================================================================\n\n"
+#define CLI_SHOW_SUB_FORMAT_ENTRY  \
+       "Endpoint: %s/%s\n" \
+       "Resource: %s/%s\n" \
+       "  Expiry: %8d  %s\n\n"
+
+static int cli_show_subscriptions_detail(struct sip_subscription_tree *sub_tree, struct cli_sub_parms *cli)
+{
+       char caller_id[256];
+       char callid[256];
+
+       ast_callerid_merge(caller_id, sizeof(caller_id),
+               S_COR(sub_tree->endpoint->id.self.name.valid,
+                       sub_tree->endpoint->id.self.name.str, NULL),
+               S_COR(sub_tree->endpoint->id.self.number.valid,
+                       sub_tree->endpoint->id.self.number.str, NULL),
+               "<none>");
+
+       /* Call-id */
+       if (sub_tree->dlg) {
+               ast_copy_pj_str(callid, &sub_tree->dlg->call_id->id, sizeof(callid));
+       } else {
+               ast_copy_string(callid, "<unknown>", sizeof(callid));
+       }
+
+       ast_str_set(&cli->buf, 0, CLI_SHOW_SUB_FORMAT_ENTRY,
+               ast_sorcery_object_get_id(sub_tree->endpoint), caller_id,
+               sub_tree->root->resource, sub_tree->root->handler->event_name,
+               cli_subscription_expiry(sub_tree), callid);
+
+       if (cli->like) {
+               if (regexec(cli->like, ast_str_buffer(cli->buf), 0, NULL, 0)) {
+                       /* Output line did not match the regex */
+                       return 0;
+               }
+       }
+
+       ast_cli(cli->a->fd, "%s", ast_str_buffer(cli->buf));
+       ++cli->count;
+
+       return 0;
+}
+
+static int cli_show_subscriptions_inbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_NOTIFIER
+               ? cli_show_subscriptions_detail(sub_tree, arg) : 0;
+}
+
+static int cli_show_subscriptions_outbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_SUBSCRIBER
+               ? cli_show_subscriptions_detail(sub_tree, arg) : 0;
+}
+
+static char *cli_show_subscriptions_inout(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       on_subscription_t on_subscription;
+       struct cli_sub_parms cli;
+       regex_t like;
+       const char *regex;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pjsip show subscriptions {inbound|outbound} [like]";
+               e->usage = "Usage:\n"
+                                  "   pjsip show subscriptions inbound [like <regex>]\n"
+                                  "      Show active inbound subscriptions\n"
+                                  "   pjsip show subscriptions outbound [like <regex>]\n"
+                                  "      Show active outbound subscriptions\n"
+                                  "\n"
+                                  "   The regex selects a subscriptions output that matches.\n"
+                                  "   i.e.,  All output lines for a subscription are checked\n"
+                                  "   as a block by the regex.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 4 && a->argc != 6) {
+               return CLI_SHOWUSAGE;
+       }
+       if (!strcasecmp(a->argv[3], "inbound")) {
+               on_subscription = cli_show_subscriptions_inbound;
+       } else if (!strcasecmp(a->argv[3], "outbound")) {
+               on_subscription = cli_show_subscriptions_outbound;
+       } else {
+               /* Should never get here */
+               ast_assert(0);
+               return CLI_SHOWUSAGE;
+       }
+       if (a->argc == 6) {
+               int rc;
+
+               if (strcasecmp(a->argv[4], "like")) {
+                       return CLI_SHOWUSAGE;
+               }
+
+               /* Setup regular expression */
+               memset(&like, 0, sizeof(like));
+               cli.like = &like;
+               regex = a->argv[5];
+               rc = regcomp(cli.like, regex, REG_EXTENDED | REG_NOSUB);
+               if (rc) {
+                       char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
+
+                       regerror(rc, cli.like, regerr, MAX_REGEX_ERROR_LEN);
+                       ast_cli(a->fd, "Regular expression '%s' failed to compile: %s\n",
+                               regex, regerr);
+                       return CLI_FAILURE;
+               }
+       } else {
+               cli.like = NULL;
+               regex = NULL;
+       }
+
+       cli.a = a;
+       cli.e = e;
+       cli.count = 0;
+       cli.buf = ast_str_create(256);
+       if (!cli.buf) {
+               if (cli.like) {
+                       regfree(cli.like);
+               }
+               return CLI_FAILURE;
+       }
+
+       ast_cli(a->fd, CLI_SHOW_SUB_FORMAT_HEADER);
+       for_each_subscription(on_subscription, &cli);
+       ast_cli(a->fd, "%d active subscriptions%s%s%s\n",
+               cli.count,
+               regex ? " matched \"" : "",
+               regex ?: "",
+               regex ? "\"" : "");
+
+       ast_free(cli.buf);
+       if (cli.like) {
+               regfree(cli.like);
+       }
+
+       return CLI_SUCCESS;
+}
+
+#define CLI_LIST_SUB_FORMAT_HEADER "%-30.30s %-30.30s %6.6s %s\n"
+#define CLI_LIST_SUB_FORMAT_ENTRY  "%-30.30s %-30.30s %6d %s\n"
+
+static int cli_list_subscriptions_detail(struct sip_subscription_tree *sub_tree, struct cli_sub_parms *cli)
+{
+       char ep_cid_buf[50];
+       char res_evt_buf[50];
+       char callid[256];
+
+       /* Endpoint/CID column */
+       snprintf(ep_cid_buf, sizeof(ep_cid_buf), "%s/%s",
+               ast_sorcery_object_get_id(sub_tree->endpoint),
+               S_COR(sub_tree->endpoint->id.self.name.valid, sub_tree->endpoint->id.self.name.str,
+                       S_COR(sub_tree->endpoint->id.self.number.valid,
+                               sub_tree->endpoint->id.self.number.str, "<none>")));
+
+       /* Resource/Event column */
+       snprintf(res_evt_buf, sizeof(res_evt_buf), "%s/%s",
+               sub_tree->root->resource,
+               sub_tree->root->handler->event_name);
+
+       /* Call-id column */
+       if (sub_tree->dlg) {
+               ast_copy_pj_str(callid, &sub_tree->dlg->call_id->id, sizeof(callid));
+       } else {
+               ast_copy_string(callid, "<unknown>", sizeof(callid));
+       }
+
+       ast_str_set(&cli->buf, 0, CLI_LIST_SUB_FORMAT_ENTRY,
+               ep_cid_buf,
+               res_evt_buf,
+               cli_subscription_expiry(sub_tree),
+               callid);
+
+       if (cli->like) {
+               if (regexec(cli->like, ast_str_buffer(cli->buf), 0, NULL, 0)) {
+                       /* Output line did not match the regex */
+                       return 0;
+               }
+       }
+
+       ast_cli(cli->a->fd, "%s", ast_str_buffer(cli->buf));
+       ++cli->count;
+
+       return 0;
+}
+
+static int cli_list_subscriptions_inbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_NOTIFIER
+               ? cli_list_subscriptions_detail(sub_tree, arg) : 0;
+}
+
+static int cli_list_subscriptions_outbound(struct sip_subscription_tree *sub_tree, void *arg)
+{
+       return sub_tree->role == AST_SIP_SUBSCRIBER
+               ? cli_list_subscriptions_detail(sub_tree, arg) : 0;
+}
+
+static char *cli_list_subscriptions_inout(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       on_subscription_t on_subscription;
+       struct cli_sub_parms cli;
+       regex_t like;
+       const char *regex;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pjsip list subscriptions {inbound|outbound} [like]";
+               e->usage = "Usage:\n"
+                                  "   pjsip list subscriptions inbound [like <regex>]\n"
+                                  "      List active inbound subscriptions\n"
+                                  "   pjsip list subscriptions outbound [like <regex>]\n"
+                                  "      List active outbound subscriptions\n"
+                                  "\n"
+                                  "   The regex selects output lines that match.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 4 && a->argc != 6) {
+               return CLI_SHOWUSAGE;
+       }
+       if (!strcasecmp(a->argv[3], "inbound")) {
+               on_subscription = cli_list_subscriptions_inbound;
+       } else if (!strcasecmp(a->argv[3], "outbound")) {
+               on_subscription = cli_list_subscriptions_outbound;
+       } else {
+               /* Should never get here */
+               ast_assert(0);
+               return CLI_SHOWUSAGE;
+       }
+       if (a->argc == 6) {
+               int rc;
+
+               if (strcasecmp(a->argv[4], "like")) {
+                       return CLI_SHOWUSAGE;
+               }
+
+               /* Setup regular expression */
+               memset(&like, 0, sizeof(like));
+               cli.like = &like;
+               regex = a->argv[5];
+               rc = regcomp(cli.like, regex, REG_EXTENDED | REG_NOSUB);
+               if (rc) {
+                       char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
+
+                       regerror(rc, cli.like, regerr, MAX_REGEX_ERROR_LEN);
+                       ast_cli(a->fd, "Regular expression '%s' failed to compile: %s\n",
+                               regex, regerr);
+                       return CLI_FAILURE;
+               }
+       } else {
+               cli.like = NULL;
+               regex = NULL;
+       }
+
+       cli.a = a;
+       cli.e = e;
+       cli.count = 0;
+       cli.buf = ast_str_create(256);
+       if (!cli.buf) {
+               if (cli.like) {
+                       regfree(cli.like);
+               }
+               return CLI_FAILURE;
+       }
+
+       ast_cli(a->fd, CLI_LIST_SUB_FORMAT_HEADER,
+               "Endpoint/CLI", "Resource/Event", "Expiry", "Call-id");
+       for_each_subscription(on_subscription, &cli);
+       ast_cli(a->fd, "\n%d active subscriptions%s%s%s\n",
+               cli.count,
+               regex ? " matched \"" : "",
+               regex ?: "",
+               regex ? "\"" : "");
+
+       ast_free(cli.buf);
+       if (cli.like) {
+               regfree(cli.like);
+       }
+
+       return CLI_SUCCESS;
+}
+
+static struct ast_cli_entry cli_commands[] = {
+       AST_CLI_DEFINE(cli_list_subscriptions_inout, "List active inbound/outbound subscriptions"),
+       AST_CLI_DEFINE(cli_show_subscription_inout, "Show active subscription details"),
+       AST_CLI_DEFINE(cli_show_subscriptions_inout, "Show active inbound/outbound subscriptions"),
+};
+
 static int persistence_endpoint_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
 {
        struct subscription_persistence *persistence = obj;
@@ -4635,6 +5171,8 @@ static int load_module(void)
        ast_manager_register_xml("PJSIPShowResourceLists", EVENT_FLAG_SYSTEM,
                        ami_show_resource_lists);
 
+       ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
+
        AST_TEST_REGISTER(resource_tree);
        AST_TEST_REGISTER(complex_resource_tree);
        AST_TEST_REGISTER(bad_resource);
@@ -4648,6 +5186,16 @@ static int load_module(void)
 
 static int unload_module(void)
 {
+       AST_TEST_UNREGISTER(resource_tree);
+       AST_TEST_UNREGISTER(complex_resource_tree);
+       AST_TEST_UNREGISTER(bad_resource);
+       AST_TEST_UNREGISTER(bad_branch);
+       AST_TEST_UNREGISTER(duplicate_resource);
+       AST_TEST_UNREGISTER(loop);
+       AST_TEST_UNREGISTER(bad_event);
+
+       ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
+
        ast_manager_unregister(AMI_SHOW_SUBSCRIPTIONS_OUTBOUND);
        ast_manager_unregister(AMI_SHOW_SUBSCRIPTIONS_INBOUND);
        ast_manager_unregister("PJSIPShowResourceLists");
@@ -4657,14 +5205,6 @@ static int unload_module(void)
                ast_sched_context_destroy(sched);
        }
 
-       AST_TEST_UNREGISTER(resource_tree);
-       AST_TEST_UNREGISTER(complex_resource_tree);
-       AST_TEST_UNREGISTER(bad_resource);
-       AST_TEST_UNREGISTER(bad_branch);
-       AST_TEST_UNREGISTER(duplicate_resource);
-       AST_TEST_UNREGISTER(loop);
-       AST_TEST_UNREGISTER(bad_event);
-
        return 0;
 }
 
index b86463e..750e1ef 100644 (file)
@@ -230,6 +230,7 @@ struct dtls_details {
 /*! \brief RTP session description */
 struct ast_rtp {
        int s;
+       /*! \note The f.subclass.format holds a ref. */
        struct ast_frame f;
        unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
        unsigned int ssrc;              /*!< Synchronization source, RFC 3550, page 10. */
@@ -2765,6 +2766,7 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
        if (rtp->red) {
                AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
                ast_free(rtp->red);
+               rtp->red = NULL;
        }
 
 #ifdef HAVE_PJPROJECT
@@ -3485,7 +3487,8 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
        return 0;
 }
 
-static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
+static struct ast_frame *red_t140_to_red(struct rtp_red *red)
+{
        unsigned char *data = red->t140red.data.ptr;
        int len = 0;
        int i;
@@ -5059,22 +5062,21 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        int x;
 
-       if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
+       rtp->red = ast_calloc(1, sizeof(*rtp->red));
+       if (!rtp->red) {
                return -1;
        }
 
        rtp->red->t140.frametype = AST_FRAME_TEXT;
-       ao2_replace(rtp->red->t140.subclass.format, ast_format_t140_red);
+       rtp->red->t140.subclass.format = ast_format_t140_red;
        rtp->red->t140.data.ptr = &rtp->red->buf_data;
 
-       rtp->red->t140.ts = 0;
        rtp->red->t140red = rtp->red->t140;
        rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
-       rtp->red->t140red.datalen = 0;
+
        rtp->red->ti = buffer_time;
        rtp->red->num_gen = generations;
        rtp->red->hdrlen = generations * 4 + 1;
-       rtp->red->prev_ts = 0;
 
        for (x = 0; x < generations; x++) {
                rtp->red->pt[x] = payloads[x];
@@ -5084,8 +5086,6 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
        rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
        rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
 
-       rtp->red->t140.datalen = 0;
-
        return 0;
 }
 
index 24c2b65..1967209 100644 (file)
@@ -65,7 +65,6 @@
 #include "stasis/app.h"
 #include "stasis/control.h"
 #include "stasis/messaging.h"
-#include "stasis/cli.h"
 #include "stasis/stasis_bridge.h"
 #include "asterisk/core_unreal.h"
 #include "asterisk/musiconhold.h"
@@ -176,11 +175,6 @@ static struct ast_json *stasis_start_to_json(struct stasis_message *message,
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(start_message_type,
        .to_json = stasis_start_to_json);
 
-const char *stasis_app_name(const struct stasis_app *app)
-{
-       return app_name(app);
-}
-
 /*! AO2 hash function for \ref app */
 static int app_hash(const void *obj, const int flags)
 {
@@ -956,7 +950,7 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
 
        if (app_subscribe_channel(app, chan)) {
                ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
-                       app_name(app), ast_channel_name(chan));
+                       stasis_app_name(app), ast_channel_name(chan));
                return -1;
        }
 
@@ -970,7 +964,7 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
        payload->replace_channel = ao2_bump(replace_channel_snapshot);
 
        json_blob = ast_json_pack("{s: s, s: o, s: []}",
-               "app", app_name(app),
+               "app", stasis_app_name(app),
                "timestamp", ast_json_timeval(ast_tvnow(), NULL),
                "args");
        if (!json_blob) {
@@ -1040,7 +1034,7 @@ int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
                return 0;
        }
 
-       blob = ast_json_pack("{s: s}", "app", app_name(app));
+       blob = ast_json_pack("{s: s}", "app", stasis_app_name(app));
        if (!blob) {
                ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
                return -1;
@@ -1486,10 +1480,6 @@ static struct stasis_app *find_app_by_name(const char *app_name)
                res = ao2_find(apps_registry, app_name, OBJ_SEARCH_KEY);
        }
 
-       if (!res) {
-               ast_log(LOG_WARNING, "Could not find app '%s'\n",
-                       app_name ? : "(null)");
-       }
        return res;
 }
 
@@ -1970,8 +1960,6 @@ static int unload_module(void)
 {
        stasis_app_unregister_event_sources();
 
-       cli_cleanup();
-
        messaging_cleanup();
 
        cleanup();
@@ -2131,11 +2119,6 @@ static int load_module(void)
                return AST_MODULE_LOAD_FAILURE;
        }
 
-       if (cli_init()) {
-               unload_module();
-               return AST_MODULE_LOAD_FAILURE;
-       }
-
        bridge_stasis_init();
 
        stasis_app_register_event_sources();
index 0b75ed5..b0bcf3c 100644 (file)
@@ -41,6 +41,9 @@
 #define CHANNEL_ALL "__AST_CHANNEL_ALL_TOPIC"
 #define ENDPOINT_ALL "__AST_ENDPOINT_ALL_TOPIC"
 
+/*! Global debug flag.  No need for locking */
+int global_debug;
+
 static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate);
 
 struct stasis_app {
@@ -840,15 +843,64 @@ static void bridge_default_handler(void *data, struct stasis_subscription *sub,
        }
 }
 
-void app_set_debug(struct stasis_app *app, int debug)
+void stasis_app_set_debug(struct stasis_app *app, int debug)
 {
        if (!app) {
                return;
        }
 
-       {
-               SCOPED_AO2LOCK(lock, app);
-               app->debug = debug;
+       app->debug = debug;
+}
+
+void stasis_app_set_debug_by_name(const char *app_name, int debug)
+{
+       struct stasis_app *app = stasis_app_get_by_name(app_name);
+
+       if (!app) {
+               return;
+       }
+
+       app->debug = debug;
+       ao2_cleanup(app);
+}
+
+int stasis_app_get_debug(struct stasis_app *app)
+{
+       return (app ? app->debug : 0) || global_debug;
+}
+
+int stasis_app_get_debug_by_name(const char *app_name)
+{
+       RAII_VAR(struct stasis_app *, app, stasis_app_get_by_name(app_name), ao2_cleanup);
+
+       return (app ? app->debug : 0) || global_debug;
+}
+
+void stasis_app_set_global_debug(int debug)
+{
+       global_debug = debug;
+       if (!global_debug) {
+               struct ao2_container *app_names = stasis_app_get_all();
+               struct ao2_iterator it_app_names;
+               char *app_name;
+               struct stasis_app *app;
+
+               if (!app_names || !ao2_container_count(app_names)) {
+                       ao2_cleanup(app_names);
+                       return;
+               }
+
+               it_app_names = ao2_iterator_init(app_names, 0);
+               while ((app_name = ao2_iterator_next(&it_app_names))) {
+                       if ((app = stasis_app_get_by_name(app_name))) {
+                               stasis_app_set_debug(app, 0);
+                       }
+
+                       ao2_cleanup(app_name);
+                       ao2_cleanup(app);
+               }
+               ao2_iterator_cleanup(&it_app_names);
+               ao2_cleanup(app_names);
        }
 }
 
@@ -949,7 +1001,6 @@ struct stasis_topic *ast_app_get_topic(struct stasis_app *app)
 void app_send(struct stasis_app *app, struct ast_json *message)
 {
        stasis_app_cb handler;
-       int debug;
        char eid[20];
        RAII_VAR(void *, data, NULL, ao2_cleanup);
 
@@ -962,7 +1013,6 @@ void app_send(struct stasis_app *app, struct ast_json *message)
        /* Copy off mutable state with lock held */
        {
                SCOPED_AO2LOCK(lock, app);
-               debug = app->debug;
                handler = app->handler;
                if (app->data) {
                        ao2_ref(app->data, +1);
@@ -971,13 +1021,6 @@ void app_send(struct stasis_app *app, struct ast_json *message)
                /* Name is immutable; no need to copy */
        }
 
-       if (debug) {
-               char *dump = ast_json_dump_string_format(message, AST_JSON_PRETTY);
-               ast_verb(0, "Dispatching message to Stasis app '%s':\n%s\n",
-                       app->name, dump);
-               ast_json_free(dump);
-       }
-
        if (!handler) {
                ast_verb(3,
                        "Inactive Stasis app '%s' missed message\n", app->name);
@@ -1050,7 +1093,7 @@ void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
        app->data = data;
 }
 
-const char *app_name(const struct stasis_app *app)
+const char *stasis_app_name(const struct stasis_app *app)
 {
        return app->name;
 }
@@ -1067,7 +1110,7 @@ static int forwards_filter_by_type(void *obj, void *arg, int flags)
        return 0;
 }
 
-void app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
+void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
 {
        struct ao2_iterator *channels;
        struct ao2_iterator *endpoints;
index 6ed6a29..ac4ac59 100644 (file)
@@ -109,15 +109,6 @@ int app_is_finished(struct stasis_app *app);
 void app_update(struct stasis_app *app, stasis_app_cb handler, void *data);
 
 /*!
- * \brief Return an application's name.
- *
- * \param app Application.
- * \return Name of the application.
- * \return \c NULL is \a app is \c NULL.
- */
-const char *app_name(const struct stasis_app *app);
-
-/*!
  * \brief Send a message to an application.
  *
  * \param app Application.
@@ -137,16 +128,6 @@ struct app_forwards;
  */
 struct ast_json *app_to_json(const struct stasis_app *app);
 
-struct ast_cli_args;
-
-/*!
- * \brief Dump properties of a \c stasis_app to the CLI
- *
- * \param app The application
- * \param a The CLI arguments
- */
-void app_to_cli(const struct stasis_app *app, struct ast_cli_args *a);
-
 /*!
  * \brief Subscribes an application to a channel.
  *
@@ -300,12 +281,4 @@ char *app_get_replace_channel_app(struct ast_channel *chan);
  */
 int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan);
 
-/*!
- * \brief Enable/disable debugging on an application
- *
- * \param app The app to debug
- * \param debug If non-zero, enable debugging. If zero, disable.
- */
-void app_set_debug(struct stasis_app *app, int debug);
-
 #endif /* _ASTERISK_RES_STASIS_APP_H */
diff --git a/res/stasis/cli.c b/res/stasis/cli.c
deleted file mode 100644 (file)
index e6065b0..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2016, Digium, Inc.
- *
- * Matt Jordan <mjordan@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Stasis CLI commands.
- *
- * \author Matt Jordan <mjordan@digium.com>
- */
-
-#include "asterisk.h"
-
-#include "asterisk/cli.h"
-#include "asterisk/astobj2.h"
-
-#include "cli.h"
-#include "app.h"
-
-
-static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       struct ao2_container *apps;
-       struct ao2_iterator it_apps;
-       char *app;
-
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "ari show apps";
-               e->usage =
-                       "Usage: ari show apps\n"
-                       "       Lists all registered applications.\n"
-                       ;
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       default:
-               break;
-       }
-
-       if (a->argc != 3) {
-               return CLI_SHOWUSAGE;
-       }
-
-       apps = stasis_app_get_all();
-       if (!apps) {
-               ast_cli(a->fd, "Unable to retrieve registered applications!\n");
-               return CLI_FAILURE;
-       }
-
-       ast_cli(a->fd, "Application Name         \n");
-       ast_cli(a->fd, "=========================\n");
-       it_apps = ao2_iterator_init(apps, 0);
-       while ((app = ao2_iterator_next(&it_apps))) {
-               ast_cli(a->fd, "%-25.25s\n", app);
-               ao2_ref(app, -1);
-       }
-
-       ao2_iterator_destroy(&it_apps);
-       ao2_ref(apps, -1);
-
-       return CLI_SUCCESS;
-}
-
-struct app_complete {
-       /*! Nth app to search for */
-       int state;
-       /*! Which app currently on */
-       int which;
-};
-
-static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
-{
-       struct app_complete *search = data;
-
-       if (++search->which > search->state) {
-               return CMP_MATCH;
-       }
-       return 0;
-}
-
-static char *complete_ari_app(struct ast_cli_args *a)
-{
-       RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
-       RAII_VAR(char *, app, NULL, ao2_cleanup);
-
-       struct app_complete search = {
-               .state = a->n,
-       };
-
-       if (!apps) {
-               ast_cli(a->fd, "Error getting ARI applications\n");
-               return CLI_FAILURE;
-       }
-
-       app = ao2_callback_data(apps,
-               ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
-               complete_ari_app_search, (char*)a->word, &search);
-
-       return app ? ast_strdup(app) : NULL;
-}
-
-static char *complete_ari_show_app(struct ast_cli_args *a)
-{
-       if (a->pos == 3) {
-               return complete_ari_app(a);
-       }
-
-       return NULL;
-}
-
-static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       void *app;
-
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "ari show app";
-               e->usage =
-                       "Usage: ari show app <application>\n"
-                       "       Provide detailed information about a registered application.\n"
-                       ;
-               return NULL;
-       case CLI_GENERATE:
-               return complete_ari_show_app(a);
-       default:
-               break;
-       }
-
-       if (a->argc != 4) {
-               return CLI_SHOWUSAGE;
-       }
-
-       app = stasis_app_get_by_name(a->argv[3]);
-       if (!app) {
-               return CLI_FAILURE;
-       }
-
-       app_to_cli(app, a);
-
-       ao2_ref(app, -1);
-
-       return CLI_SUCCESS;
-}
-
-static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       void *app;
-       int debug;
-
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "ari set debug";
-               e->usage =
-                       "Usage: ari set debug <application> <on|off>\n"
-                       "       Enable or disable debugging on a specific application.\n"
-                       ;
-               return NULL;
-       case CLI_GENERATE:
-               return complete_ari_show_app(a);
-       default:
-               break;
-       }
-
-       if (a->argc != 5) {
-               return CLI_SHOWUSAGE;
-       }
-
-       app = stasis_app_get_by_name(a->argv[3]);
-       if (!app) {
-               return CLI_FAILURE;
-       }
-
-       debug = !strcmp(a->argv[4], "on");
-       app_set_debug(app, debug);
-       ast_cli(a->fd, "Debugging on '%s' %s\n",
-               app_name(app),
-               debug ? "enabled" : "disabled");
-
-       ao2_ref(app, -1);
-
-       return CLI_SUCCESS;
-}
-
-static struct ast_cli_entry cli_ari[] = {
-       AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
-       AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
-       AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
-};
-
-
-int cli_init(void)
-{
-       return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
-}
-
-void cli_cleanup(void)
-{
-       ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
-}
diff --git a/res/stasis/cli.h b/res/stasis/cli.h
deleted file mode 100644 (file)
index 49235c7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2016, Digium, Inc.
- *
- * Matt Jordan <mjordan@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-#ifndef _ASTERISK_RES_STASIS_CLI_H
-#define _ASTERISK_RES_STASIS_CLI_H
-
-/*! \file
- *
- * \brief Internal API for Stasis application CLI commands
- *
- * \author Matt Jordan <mjordan@digium.com>
- * \since 13.13.0
- */
-
-/*!
- * \brief Initialize the CLI commands
- *
- * \retval 0 on success
- * \retval non-zero on error
- */
-int cli_init(void);
-
-/*!
- * \brief Cleanup the CLI commands
- */
-void cli_cleanup(void);
-
-#endif /* _ASTERISK_RES_STASIS_CLI_H */
index 95e549a..7ce675c 100644 (file)
@@ -155,13 +155,13 @@ static int bridge_stasis_push_peek(struct ast_bridge *self, struct ast_bridge_ch
        }
        to_be_replaced = ast_channel_snapshot_get_latest(ast_channel_uniqueid(swap->chan));
 
-       ast_debug(3, "Copying stasis app name %s from %s to %s\n", app_name(control_app(swap_control)),
+       ast_debug(3, "Copying stasis app name %s from %s to %s\n", stasis_app_name(control_app(swap_control)),
                ast_channel_name(swap->chan), ast_channel_name(bridge_channel->chan));
 
        ast_channel_lock(bridge_channel->chan);
 
        /* copy the app name from the swap channel */
-       app_set_replace_channel_app(bridge_channel->chan, app_name(control_app(swap_control)));
+       app_set_replace_channel_app(bridge_channel->chan, stasis_app_name(control_app(swap_control)));
 
        /* set the replace channel snapshot */
        app_set_replace_channel_snapshot(bridge_channel->chan, to_be_replaced);
@@ -215,6 +215,7 @@ static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel
                 */
                return -1;
        }
+       ao2_cleanup(control);
 
        /*
         * If going into a holding bridge, default the role to participant, if
@@ -234,7 +235,6 @@ static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel
                }
        }
 
-       ao2_cleanup(control);
        if (self->allowed_capabilities & STASIS_BRIDGE_MIXING_CAPABILITIES) {
                ast_bridge_channel_update_linkedids(bridge_channel, swap);
                if (ast_test_flag(&self->feature_flags, AST_BRIDGE_FLAG_SMART)) {
index 247c121..d156ab7 100644 (file)
 {{/has_path_parameters}}
 {{^is_websocket}}
 {{#parse_body}}
-       /* Look for a JSON request entity */
-       body = ast_http_get_json(ser, headers);
-       if (!body) {
-               switch (errno) {
-               case EFBIG:
-                       ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-                       goto fin;
-               case ENOMEM:
-                       ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-                       goto fin;
-               case EIO:
-                       ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-                       goto fin;
-               }
-       }
 {{#body_parameter}}
        args.{{c_name}} = body;
 {{/body_parameter}}
index d5c8615..c28a62c 100644 (file)
 static void ast_ari_{{c_name}}_{{c_nickname}}_cb(
        struct ast_tcptls_session_instance *ser,
        struct ast_variable *get_params, struct ast_variable *path_vars,
-       struct ast_variable *headers, struct ast_ari_response *response)
+       struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
        struct ast_ari_{{c_name}}_{{c_nickname}}_args args = {};
 {{#has_parameters}}
        struct ast_variable *i;
 {{/has_parameters}}
-       RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
        int is_valid;
        int code;
index 1bd7749..bce5f95 100644 (file)
@@ -61,6 +61,7 @@ static void handler(const char *name,
                    struct ast_variable *get_params,
                    struct ast_variable *path_vars,
                    struct ast_variable *headers,
+                   struct ast_json *body,
                    struct ast_ari_response *response)
 {
        struct ast_json *message = ast_json_pack("{s: s, s: {}, s: {}, s: {}}",
@@ -98,9 +99,10 @@ static void handler(const char *name,
                struct ast_variable *get_params,                        \
                struct ast_variable *path_vars,                         \
                struct ast_variable *headers,                           \
+               struct ast_json *body,                                          \
                struct ast_ari_response *response)                      \
        {                                                               \
-               handler(#name, response_code, get_params, path_vars, headers, response); \
+               handler(#name, response_code, get_params, path_vars, headers, body, response); \
        }
 
 HANDLER(bang_get, 200)
@@ -343,7 +345,8 @@ AST_TEST_DEFINE(invoke_get)
                                 "head2", "head-two",
                                 "path_vars");
 
-       ast_ari_invoke(NULL, "foo", AST_HTTP_GET, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo", AST_HTTP_GET, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 1 == invocation_count);
        ast_test_validate(test, 200 == response->response_code);
@@ -380,7 +383,8 @@ AST_TEST_DEFINE(invoke_wildcard)
                                 "path_vars",
                                 "bam", "foshizzle");
 
-       ast_ari_invoke(NULL, "foo/foshizzle", AST_HTTP_GET, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo/foshizzle", AST_HTTP_GET, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 1 == invocation_count);
        ast_test_validate(test, 200 == response->response_code);
@@ -417,7 +421,8 @@ AST_TEST_DEFINE(invoke_delete)
                                 "path_vars",
                                 "bam", "foshizzle");
 
-       ast_ari_invoke(NULL, "foo/foshizzle/bang", AST_HTTP_DELETE, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo/foshizzle/bang", AST_HTTP_DELETE, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 1 == invocation_count);
        ast_test_validate(test, 204 == response->response_code);
@@ -467,7 +472,8 @@ AST_TEST_DEFINE(invoke_post)
                                 "head2", "head-two",
                                 "path_vars");
 
-       ast_ari_invoke(NULL, "foo/bar", AST_HTTP_POST, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo/bar", AST_HTTP_POST, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 1 == invocation_count);
        ast_test_validate(test, 200 == response->response_code);
@@ -496,7 +502,8 @@ AST_TEST_DEFINE(invoke_bad_post)
 
        fixture = setup_invocation_test();
        response = response_alloc();
-       ast_ari_invoke(NULL, "foo", AST_HTTP_POST, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo", AST_HTTP_POST, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 0 == invocation_count);
        ast_test_validate(test, 405 == response->response_code);
@@ -524,7 +531,8 @@ AST_TEST_DEFINE(invoke_not_found)
 
        fixture = setup_invocation_test();
        response = response_alloc();
-       ast_ari_invoke(NULL, "foo/fizzle/i-am-not-a-resource", AST_HTTP_GET, get_params, headers, response);
+       ast_ari_invoke(NULL, "foo/fizzle/i-am-not-a-resource", AST_HTTP_GET, get_params, headers,
+               ast_json_null(), response);
 
        ast_test_validate(test, 0 == invocation_count);
        ast_test_validate(test, 404 == response->response_code);
index 9cadf23..848c6bf 100644 (file)
                return AST_TEST_FAIL; \
        } \
        VM_API_SNAPSHOT_CREATE((mailbox), (context), (folder), 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0); \
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 0); \
+       VM_API_INT_VERIFY(0, test_mbox_snapshot->total_msg_num); \
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot); \
 } while (0)
 
@@ -1002,10 +1002,10 @@ AST_TEST_DEFINE(voicemail_api_nominal_move)
        test_vm_api_update_test_snapshots(test_mbox_snapshot);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[0]->folder_name, "Family");
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[1]->folder_name, "Family");
-       VM_API_INT_VERIFY(test_snapshots[1]->msg_number, 0);
-       VM_API_INT_VERIFY(test_snapshots[0]->msg_number, 1);
+       VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[0]->folder_name);
+       VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[1]->folder_name);
+       VM_API_INT_VERIFY(0, test_snapshots[1]->msg_number);
+       VM_API_INT_VERIFY(1, test_snapshots[0]->msg_number);
 
        /* Move both of the 2345 messages to Family */
        ast_test_status_update(test, "Test move of test_vm_api_2345 messages from Inbox to Family\n");
@@ -1016,8 +1016,8 @@ AST_TEST_DEFINE(voicemail_api_nominal_move)
        test_vm_api_update_test_snapshots(test_mbox_snapshot);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[2]->folder_name, "Family");
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[3]->folder_name, "Family");
+       VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[2]->folder_name);
+       VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[3]->folder_name);
 
        ast_test_status_update(test, "Test move of test_vm_api_2345 message from Family to INBOX\n");
        VM_API_MOVE_MESSAGE("test_vm_api_2345", "default", 2, "Family", multi_msg_ids, "INBOX");
@@ -1026,8 +1026,8 @@ AST_TEST_DEFINE(voicemail_api_nominal_move)
        test_vm_api_update_test_snapshots(test_mbox_snapshot);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[2]->folder_name, "INBOX");
-       VM_API_STRING_FIELD_VERIFY(test_snapshots[3]->folder_name, "INBOX");
+       VM_API_STRING_FIELD_VERIFY("INBOX", test_snapshots[2]->folder_name);
+       VM_API_STRING_FIELD_VERIFY("INBOX", test_snapshots[3]->folder_name);
 
        VM_API_TEST_CLEANUP;
 
@@ -1248,12 +1248,12 @@ AST_TEST_DEFINE(voicemail_api_nominal_forward)
 
        /* Make sure we didn't delete the message */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 1);
+       VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 3 messages in test_vm_api_2345 INBOX */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 3);
+       VM_API_INT_VERIFY(3, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX with default context to test_vm_api_2345 INBOX\n");
@@ -1261,12 +1261,12 @@ AST_TEST_DEFINE(voicemail_api_nominal_forward)
 
        /* Make sure we didn't delete the message */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 1);
+       VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 4 messages in test_vm_api_2345 INBOX */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 4);
+       VM_API_INT_VERIFY(4, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX to test_vm_api_2345 INBOX with default context\n");
@@ -1274,12 +1274,12 @@ AST_TEST_DEFINE(voicemail_api_nominal_forward)
 
        /* Make sure we didn't delete the message */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 1);
+       VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 5 messages in test_vm_api_2345 INBOX */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 5);
+       VM_API_INT_VERIFY(5, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX to test_vm_api_2345 INBOX, deleting original\n");
@@ -1287,12 +1287,12 @@ AST_TEST_DEFINE(voicemail_api_nominal_forward)
 
        /* Make sure we deleted the message */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 0);
+       VM_API_INT_VERIFY(0, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 6 messages in test_vm_api_2345 INBOX */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 6);
+       VM_API_INT_VERIFY(6, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_test_status_update(test, "Test forwarding 2 messages from test_vm_api_2345 INBOX to test_vm_api_1234 INBOX");
@@ -1300,24 +1300,24 @@ AST_TEST_DEFINE(voicemail_api_nominal_forward)
 
        /* Make sure we didn't delete the messages */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 6);
+       VM_API_INT_VERIFY(6, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 2 messages in test_vm_api_1234 INBOX */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 2);
+       VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_test_status_update(test, "Test forwarding 2 messages from test_vm_api_2345 INBOX to test_vm_api_1234 Family, deleting original\n");
        VM_API_FORWARD_MESSAGE("test_vm_api_2345", "default", "INBOX", "test_vm_api_1234", "default", "Family", 2, multi_msg_ids, 1);
        /* Make sure we deleted the messages */
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 4);
+       VM_API_INT_VERIFY(4, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        /* We should now have a total of 2 messages in test_vm_api_1234 Family */
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Family", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 2);
+       VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        VM_API_TEST_CLEANUP;
@@ -1447,20 +1447,20 @@ AST_TEST_DEFINE(voicemail_api_nominal_msg_playback)
 
        ast_test_status_update(test, "Playing back message from test_vm_api_2345 to callback function\n");
        VM_API_PLAYBACK_MESSAGE(test_channel, "test_vm_api_2345", "default", "INBOX", message_id_2345[0], &message_playback_callback_fn);
-       VM_API_INT_VERIFY(global_entered_playback_callback, 1);
+       VM_API_INT_VERIFY(1, global_entered_playback_callback);
        global_entered_playback_callback = 0;
 
        ast_test_status_update(test, "Playing back message from test_vm_api_2345 to callback function with default context\n");
        VM_API_PLAYBACK_MESSAGE(test_channel, "test_vm_api_2345", NULL, "INBOX", message_id_2345[1], &message_playback_callback_fn);
-       VM_API_INT_VERIFY(global_entered_playback_callback, 1);
+       VM_API_INT_VERIFY(1, global_entered_playback_callback);
        global_entered_playback_callback = 0;
 
        VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Old", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 2);
+       VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "Old", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
-       VM_API_INT_VERIFY(test_mbox_snapshot->total_msg_num, 2);
+       VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
        test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
 
        ast_hangup(test_channel);
index 2398ec4..bfd1c27 100644 (file)
@@ -187,13 +187,11 @@ source/pjsip-apps/lib/libasterisk_malloc_debug.a: source/pjsip-apps/lib/asterisk
        $(CMD_PREFIX) ar qs $@ $< >/dev/null 2>&1
 
 $(apps): APP = $(filter pj%,$(subst -, ,$(notdir $@)))
-$(apps): CFLAGS += -DPJ_LOG_MAX_LEVEL=2
 $(apps): LDFLAGS += $(MALLOC_DEBUG_LDFLAGS)
 $(apps): $(MALLOC_DEBUG_LIBS) pjproject.symbols $(APP_THIRD_PARTY_LIB_FILES)
        $(ECHO_PREFIX) Compiling $(APP)
        $(CMD_PREFIX) +$(MAKE) -C source/pjsip-apps/build $(filter pj%,$(subst -, ,$(notdir $@))) $(REALLY_QUIET)
 
-source/pjsip-apps/src/python/_pjsua.o: CFLAGS += -DPJ_LOG_MAX_LEVEL=2
 source/pjsip-apps/src/python/_pjsua.o: source/pjsip-apps/src/python/_pjsua.c $(apps)
        $(ECHO_PREFIX) Compiling python bindings
        $(CMD_PREFIX) $(CC) -o $@ -c $< $(PYTHONDEV_INCLUDE) $(CFLAGS) $(PJ_CFLAGS)
diff --git a/third-party/pjproject/patches/0000-set_apps_initial_log_level.patch b/third-party/pjproject/patches/0000-set_apps_initial_log_level.patch
new file mode 100644 (file)
index 0000000..fc0f570
--- /dev/null
@@ -0,0 +1,39 @@
+diff --git a/pjsip-apps/src/pjsua/main.c b/pjsip-apps/src/pjsua/main.c
+index 2baaf82..11831f2 100644
+--- a/pjsip-apps/src/pjsua/main.c
++++ b/pjsip-apps/src/pjsua/main.c
+@@ -126,5 +126,7 @@ int main_func(int argc, char *argv[])
+ int main(int argc, char *argv[])
+ {
++    pj_log_set_level(1);
++
+     return pj_run_app(&main_func, argc, argv, 0);
+ }
+diff --git a/pjsip-apps/src/pjsystest/main_console.c b/pjsip-apps/src/pjsystest/main_console.c
+index 122cdc7..dc79eab 100644
+--- a/pjsip-apps/src/pjsystest/main_console.c
++++ b/pjsip-apps/src/pjsystest/main_console.c
+@@ -133,6 +133,8 @@ void gui_sleep(unsigned sec)
+ int main()
+ {
++    pj_log_set_level(1);
++
+     if (systest_init() != PJ_SUCCESS)
+       return 1;
+diff --git a/pjsip-apps/src/python/_pjsua.c b/pjsip-apps/src/python/_pjsua.c
+index fb80e23..c9b21d8 100644
+--- a/pjsip-apps/src/python/_pjsua.c
++++ b/pjsip-apps/src/python/_pjsua.c
+@@ -4437,7 +4437,8 @@ init_pjsua(void)
+     PyObject* m = NULL;
+ #define ADD_CONSTANT(mod,name)        PyModule_AddIntConstant(mod,#name,name)
+-    
++    pj_log_set_level(1);
++
+     PyEval_InitThreads();
+     if (PyType_Ready(&PyTyp_pjsua_callback) < 0)