rtp_engine: rtcp_report_to_json can overflow the ssrc integer value
[asterisk/asterisk.git] / include / asterisk / json.h
index d8cf98e..227afbb 100644 (file)
 #ifndef _ASTERISK_JSON_H
 #define _ASTERISK_JSON_H
 
+#include "asterisk/netsock2.h"
+
 /*! \file
  *
  * \brief Asterisk JSON abstraction layer.
  * \since 12.0.0
  *
- * This is a very thin wrapper around the Jansson API. For more details on it, see its
- * docs at http://www.digip.org/jansson/doc/2.4/apiref.html.
-
+ * This is a very thin wrapper around the Jansson API. For more details on it,
+ * see its docs at http://www.digip.org/jansson/doc/2.11/apiref.html.
+ *
+ * Rather than provide the multiple ways of doing things that the Jansson API
+ * does, the Asterisk wrapper is always reference-stealing, and always NULL
+ * safe.
+ *
+ * And by always, I mean that the reference is stolen even if the function
+ * fails. This avoids lots of conditional logic, and also avoids having to track
+ * zillions of local variables when building complex JSON objects. You can
+ * instead chain \c ast_json_* calls together safely and only worry about
+ * cleaning up the root object.
+ *
+ * In the cases where you have a need to introduce intermediate objects, just
+ * wrap them with json_ref() when passing them to other \c ast_json_*()
+ * functions.
+ *
+ * \par Example code
+ *
+ * \code
+ *     // Example of how to use the Asterisk JSON API
+ *     static struct ast_json *foo(void) {
+ *             RAII_VAR(struct ast_json *, array, NULL, ast_json_unref);
+ *             RAII_VAR(struct ast_json *, obj, NULL, ast_json_unref);
+ *             int i, res;
+ *
+ *             array = ast_json_array_create();
+ *             if (!array) { return NULL; }
+ *
+ *             for (i = 0; i < 10; ++i) {
+ *                     // NULL safety and object stealing means calls can
+ *                     // be chained together directly.
+ *                     res = ast_json_array_append(array,
+ *                             ast_json_integer_create(i));
+ *                     if (res != 0) { return NULL; }
+ *             }
+ *
+ *             obj = ast_json_object_create();
+ *             if (!obj) { return NULL; }
+ *
+ *             // If you already have an object reference, ast_json_ref()
+ *             // can be used inline to bump the ref before passing it along
+ *             // to a ref-stealing call
+ *             res = ast_json_object_set(obj, "foo", ast_json_ref(array));
+ *             if (!res) { return NULL; }
+ *
+ *             return obj;
+ *     }
+ * \endcode
+ *
  * \author David M. Lee, II <dlee@digium.com>
  */
 
 /*!@{*/
 
 /*!
+ * \brief Primarily used to cast when packing to an "I" type.
+ */
+typedef AST_JSON_INT_T ast_json_int_t;
+
+/*!
  * \brief Initialize the JSON library.
  */
 void ast_json_init(void);
@@ -60,6 +114,20 @@ void ast_json_set_alloc_funcs(void *(*malloc_fn)(size_t), void (*free_fn)(void*)
 void ast_json_reset_alloc_funcs(void);
 
 /*!
+ * \brief Asterisk's custom JSON allocator. Exposed for use by unit tests.
+ * \since 12.0.0
+ * \internal
+ */
+void *ast_json_malloc(size_t size);
+
+/*!
+ * \brief Asterisk's custom JSON allocator. Exposed for use by unit tests.
+ * \since 12.0.0
+ * \internal
+ */
+void ast_json_free(void *p);
+
+/*!
  * \struct ast_json
  * \brief Abstract JSON element (object, array, string, int, ...).
  * \since 12.0.0
@@ -78,6 +146,8 @@ struct ast_json *ast_json_ref(struct ast_json *value);
 /*!
  * \brief Decrease refcount on \a value. If refcount reaches zero, \a value is freed.
  * \since 12.0.0
+ *
+ * \note It is safe to pass \c NULL to this function.
  */
 void ast_json_unref(struct ast_json *value);
 
@@ -109,6 +179,50 @@ enum ast_json_type
  */
 enum ast_json_type ast_json_typeof(const struct ast_json *value);
 
+/*!
+ * \brief Get the string name for the given type.
+ * \since 12.0.0
+ * \param type Type to convert to string.
+ * \return Simple string for the type name (object, array, string, etc.)
+ * \return \c "?" for invalid types.
+ */
+const char *ast_json_typename(enum ast_json_type type);
+
+/*!@}*/
+
+/*!@{*/
+
+/*!
+ * \brief Check the string of the given length for UTF-8 format.
+ * \since 13.12.0
+ *
+ * \param str String to check.
+ * \param len Length of string to check.
+ *
+ * \retval 0 if not UTF-8 encoded or str is NULL.
+ * \retval 1 if UTF-8 encoded.
+ */
+int ast_json_utf8_check_len(const char *str, size_t len);
+
+/*!
+ * \brief Check the nul terminated string for UTF-8 format.
+ * \since 13.12.0
+ *
+ * \param str String to check.
+ *
+ * \retval 0 if not UTF-8 encoded or str is NULL.
+ * \retval 1 if UTF-8 encoded.
+ */
+int ast_json_utf8_check(const char *str);
+
+/*!
+ * \brief Check str for UTF-8 and replace with an empty string if fails the check.
+ *
+ * \note The convenience macro is normally used with ast_json_pack()
+ * or a function wrapper that calls ast_json_vpack().
+ */
+#define AST_JSON_UTF8_VALIDATE(str) (ast_json_utf8_check(str) ? (str) : "")
+
 /*!@}*/
 
 /*!@{*/
@@ -272,6 +386,34 @@ intmax_t ast_json_integer_get(const struct ast_json *integer);
  */
 int ast_json_integer_set(struct ast_json *integer, intmax_t value);
 
+/*!
+ * \brief Create a JSON real number.
+ * \since 12.0.0
+ * \param value Value of the new JSON real number.
+ * \return Newly allocated real number.
+ * \return \c NULL on error.
+ */
+struct ast_json *ast_json_real_create(double value);
+
+/*!
+ * \brief Get the value from a JSON real number.
+ * \since 12.0.0
+ * \param real JSON real number.
+ * \return Value of a JSON real number.
+ * \return 0 if \a real is not a JSON real number.
+ */
+double ast_json_real_get(const struct ast_json *real);
+
+/*!
+ * \brief Set the value of a JSON real number.
+ * \since 12.0.0
+ * \param integer JSON real number to modify.
+ * \param value New value for \a real.
+ * \return 0 on success.
+ * \return -1 on error.
+ */
+int ast_json_real_set(struct ast_json *real, double value);
+
 /*!@}*/
 
 /*!@{*/
@@ -312,8 +454,8 @@ struct ast_json *ast_json_array_get(const struct ast_json *array, size_t index);
  * \brief Change an element in an array.
  * \since 12.0.0
  *
- * The \a array steals the \a value reference; use ast_json_ref() to safely keep a pointer
- * to it.
+ * \note The \a array steals the \a value reference even if it returns error;
+ * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param array JSON array to modify.
  * \param index Zero-based index into array.
@@ -327,8 +469,8 @@ int ast_json_array_set(struct ast_json *array, size_t index, struct ast_json *va
  * \brief Append to an array.
  * \since 12.0.0
  *
- * The array steals the \a value reference; use ast_json_ref() to safely keep a pointer
- * to it.
+ * \note The \a array steals the \a value reference even if it returns error;
+ * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param array JSON array to modify.
  * \param value New JSON value to store at the end of \a array.
@@ -341,8 +483,8 @@ int ast_json_array_append(struct ast_json *array, struct ast_json *value);
  * \brief Insert into an array.
  * \since 12.0.0
  *
- * The array steals the \a value reference; use ast_json_ref() to safely keep a pointer
- * to it.
+ * \note The \a array steals the \a value reference even if it returns error;
+ * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param array JSON array to modify.
  * \param index Zero-based index into array.
@@ -423,8 +565,8 @@ struct ast_json *ast_json_object_get(struct ast_json *object, const char *key);
  * \brief Set a field in a JSON object.
  * \since 12.0.0
  *
- * The object steals the \a value reference; use ast_json_ref() to safely keep a pointer
- * to it.
+ * \note The object steals the \a value reference even if it returns error;
+ * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param object JSON object to modify.
  * \param key Key of field to set.
@@ -570,8 +712,8 @@ struct ast_json *ast_json_object_iter_value(struct ast_json_iter *iter);
  * \brief Set the value of the field pointed to by an iterator.
  * \since 12.0.0
  *
- * The array steals the value reference; use ast_json_ref() to safely keep a
- * pointer to it.
+ * \note The object steals the \a value reference even if it returns error;
+ * use ast_json_ref() to safely keep a pointer to it.
  *
  * \param object JSON object \a iter was obtained from.
  * \param iter JSON object iterator.
@@ -586,16 +728,43 @@ int ast_json_object_iter_set(struct ast_json *object, struct ast_json_iter *iter
 /*!@{*/
 
 /*!
+ * \brief Encoding format type.
+ * \since 12.0.0
+ */
+enum ast_json_encoding_format
+{
+       /*! Compact format, low human readability */
+       AST_JSON_COMPACT,
+       /*! Formatted for human readability */
+       AST_JSON_PRETTY,
+};
+
+/*!
+ * \brief Encode a JSON value to a compact string.
+ * \since 12.0.0
+ *
+ * Returned string must be freed by calling ast_json_free().
+ *
+ * \param root JSON value.
+ * \return String encoding of \a root.
+ * \return \c NULL on error.
+ */
+#define ast_json_dump_string(root) ast_json_dump_string_format(root, AST_JSON_COMPACT)
+
+/*!
  * \brief Encode a JSON value to a string.
  * \since 12.0.0
  *
- * Returned string must be freed by calling ast_free().
+ * Returned string must be freed by calling ast_json_free().
  *
- * \param JSON value.
+ * \param root JSON value.
+ * \param format encoding format type.
  * \return String encoding of \a root.
  * \return \c NULL on error.
  */
-char *ast_json_dump_string(struct ast_json *root);
+char *ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format);
+
+#define ast_json_dump_str(root, dst) ast_json_dump_str_format(root, dst, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to an \ref ast_str.
@@ -605,10 +774,13 @@ char *ast_json_dump_string(struct ast_json *root);
  *
  * \param root JSON value.
  * \param dst \ref ast_str to store JSON encoding.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a dst are undefined.
  */
-int ast_json_dump_str(struct ast_json *root, struct ast_str **dst);
+int ast_json_dump_str_format(struct ast_json *root, struct ast_str **dst, enum ast_json_encoding_format format);
+
+#define ast_json_dump_file(root, output) ast_json_dump_file_format(root, output, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to a \c FILE.
@@ -616,10 +788,13 @@ int ast_json_dump_str(struct ast_json *root, struct ast_str **dst);
  *
  * \param root JSON value.
  * \param output File to write JSON encoding to.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a output are undefined.
  */
-int ast_json_dump_file(struct ast_json *root, FILE *output);
+int ast_json_dump_file_format(struct ast_json *root, FILE *output, enum ast_json_encoding_format format);
+
+#define ast_json_dump_new_file(root, path) ast_json_dump_new_file_format(root, path, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to a file at the given location.
@@ -627,10 +802,11 @@ int ast_json_dump_file(struct ast_json *root, FILE *output);
  *
  * \param root JSON value.
  * \param path Path to file to write JSON encoding to.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a output are undefined.
  */
-int ast_json_dump_new_file(struct ast_json *root, const char *path);
+int ast_json_dump_new_file_format(struct ast_json *root, const char *path, enum ast_json_encoding_format format);
 
 #define AST_JSON_ERROR_TEXT_LENGTH    160
 #define AST_JSON_ERROR_SOURCE_LENGTH   80
@@ -707,7 +883,7 @@ struct ast_json *ast_json_load_new_file(const char *path, struct ast_json_error
  * \brief Helper for creating complex JSON values.
  * \since 12.0.0
  *
- * See original Jansson docs at http://www.digip.org/jansson/doc/2.4/apiref.html#apiref-pack
+ * See original Jansson docs at http://www.digip.org/jansson/doc/2.11/apiref.html#apiref-pack
  * for more details.
  */
 struct ast_json *ast_json_pack(char const *format, ...);
@@ -716,7 +892,7 @@ struct ast_json *ast_json_pack(char const *format, ...);
  * \brief Helper for creating complex JSON values simply.
  * \since 12.0.0
  *
- * See original Jansson docs at http://www.digip.org/jansson/doc/2.4/apiref.html#apiref-pack
+ * See original Jansson docs at http://www.digip.org/jansson/doc/2.11/apiref.html#apiref-pack
  * for more details.
  */
 struct ast_json *ast_json_vpack(char const *format, va_list ap);
@@ -764,4 +940,130 @@ struct ast_json *ast_json_deep_copy(const struct ast_json *value);
 
 /*!@}*/
 
+/*!@{*/
+
+/*!
+ * \brief Common JSON rendering functions for common 'objects'.
+ */
+
+/*!
+ * \brief Simple name/number pair.
+ * \param name Name
+ * \param number Number
+ * \return NULL if error (non-UTF8 characters, NULL inputs, etc.)
+ * \return JSON object with name and number fields
+ */
+struct ast_json *ast_json_name_number(const char *name, const char *number);
+
+/*!
+ * \brief Construct a timeval as JSON.
+ *
+ * JSON does not define a standard date format (boo), but the de facto standard
+ * is to use ISO 8601 formatted string. We build a millisecond resolution string
+ * from the \c timeval
+ *
+ * \param tv \c timeval to encode.
+ * \param zone Text string of a standard system zoneinfo file.  If NULL, the system localtime will be used.
+ * \return JSON string with ISO 8601 formatted date/time.
+ * \return \c NULL on error.
+ */
+struct ast_json *ast_json_timeval(const struct timeval tv, const char *zone);
+
+/*!
+ * \brief Construct an IP address as JSON
+ *
+ * XXX some comments describing the need for this here
+ *
+ * \param addr ast_sockaddr to encode
+ * \param transport_type ast_transport to include in the address string if any. Should just be one.
+ * \return JSON string containing the IP address with optional transport information
+ * \return \c NULL on error.
+ */
+struct ast_json *ast_json_ipaddr(const struct ast_sockaddr *addr, enum ast_transport transport_type);
+
+/*!
+ * \brief Construct a context/exten/priority as JSON.
+ *
+ * If a \c NULL is passed for \c context or \c exten, or -1 for \c priority,
+ * the fields is set to ast_json_null().
+ *
+ * \param context Context name.
+ * \param exten Extension.
+ * \param priority Dialplan priority.
+ * \return JSON object with \c context, \c exten and \c priority fields
+ */
+struct ast_json *ast_json_dialplan_cep(const char *context, const char *exten, int priority);
+
+struct ast_json_payload {
+       struct ast_json *json;
+};
+
+/*!
+ * \brief Create an ao2 object to pass json blobs as data payloads for stasis
+ * \since 12.0.0
+ *
+ * \param json the ast_json blob we are loading
+ *
+ * \retval NULL if we fail to alloc it
+ * \retval pointer to the ast_json_payload created
+ */
+struct ast_json_payload *ast_json_payload_create(struct ast_json *json);
+
+struct ast_party_id;
+/*!
+ * \brief Construct an ast_party_id as JSON.
+ * \since 12.0.0
+ *
+ * \param party The party ID to represent as JSON.
+ *
+ * \return JSON object with \c name, \c number and \c subaddress objects
+ * for those that are valid in the party ID
+ */
+struct ast_json *ast_json_party_id(struct ast_party_id *party);
+
+enum ast_json_to_ast_vars_code {
+       /*! \brief Conversion successful */
+       AST_JSON_TO_AST_VARS_CODE_SUCCESS,
+       /*!
+        * \brief Conversion failed because invalid value type supplied.
+        * \note Only string values allowed.
+        */
+       AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE,
+       /*! \brief Conversion failed because of allocation failure. (Out Of Memory) */
+       AST_JSON_TO_AST_VARS_CODE_OOM,
+};
+
+/*!
+ * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
+ * \since 12.5.0
+ *
+ * \param json_variables The JSON blob containing the variable
+ * \param variables An out reference to the variables to populate.
+ *
+ * \code
+ * struct ast_json *json_variables = ast_json_pack("[ { s: s } ]", "foo", "bar");
+ * struct ast_variable *variables = NULL;
+ * int res;
+ *
+ * res = ast_json_to_ast_variables(json_variables, &variables);
+ * \endcode
+ *
+ * \return Conversion enum ast_json_to_ast_vars_code status
+ */
+enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
+
+struct varshead;
+
+/*!
+ * \brief Construct a JSON object from a \c ast_var_t list
+ * \since 14.2.0
+ *
+ * \param channelvars The list of \c ast_var_t to represent as JSON
+ *
+ * \return JSON object with variable names as keys and variable values as values
+ */
+struct ast_json *ast_json_channel_vars(struct varshead *channelvars);
+
+/*!@}*/
+
 #endif /* _ASTERISK_JSON_H */