diff options
Diffstat (limited to 'include/asterisk')
59 files changed, 3734 insertions, 1388 deletions
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h index b3c2b2002..e989b16fd 100644 --- a/include/asterisk/_private.h +++ b/include/asterisk/_private.h @@ -44,7 +44,6 @@ int ast_named_locks_init(void); /*!< Provided by named_locks.c */ int ast_file_init(void); /*!< Provided by file.c */ int ast_features_init(void); /*!< Provided by features.c */ void ast_autoservice_init(void); /*!< Provided by autoservice.c */ -int ast_data_init(void); /*!< Provided by data.c */ int ast_http_init(void); /*!< Provided by http.c */ int ast_http_reload(void); /*!< Provided by http.c */ int ast_tps_init(void); /*!< Provided by taskprocessor.c */ diff --git a/include/asterisk/alertpipe.h b/include/asterisk/alertpipe.h new file mode 100644 index 000000000..09c335829 --- /dev/null +++ b/include/asterisk/alertpipe.h @@ -0,0 +1,160 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2017, Sean Bright + * + * Sean Bright <sean.bright@gmail.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_ALERTPIPE_H +#define ASTERISK_ALERTPIPE_H + +#include "asterisk/utils.h" + +typedef enum { + AST_ALERT_READ_SUCCESS = 0, + AST_ALERT_NOT_READABLE, + AST_ALERT_READ_FAIL, + AST_ALERT_READ_FATAL, +} ast_alert_status_t; + +/*! + * \brief Initialize an alert pipe + * \since 13.16.0 + * + * \param p a two-element array to hold the alert pipe's file descriptors + * + * \return non-zero if a failure occurred, zero otherwise. + */ +int ast_alertpipe_init(int alert_pipe[2]); + +/*! + * \brief Close an alert pipe + * \since 13.16.0 + * + * \param p a two-element containing the alert pipe's file descriptors + */ +void ast_alertpipe_close(int alert_pipe[2]); + +/*! + * \brief Read an event from an alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \retval AST_ALERT_READ_SUCCESS on success + * \retval AST_ALERT_NOT_READABLE if the alert pipe is not readable + * \retval AST_ALERT_READ_FATAL if the alert pipe's file descriptors are in + * blocking mode, or a read error occurs. + */ +ast_alert_status_t ast_alertpipe_read(int alert_pipe[2]); + +/*! + * \brief Write an event to an alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \retval 0 Success + * \retval 1 Failure + */ +ssize_t ast_alertpipe_write(int alert_pipe[2]); + +/*! + * \brief Consume all alerts written to the alert pipe + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \retval AST_ALERT_READ_SUCCESS on success + * \retval AST_ALERT_NOT_READABLE if the alert pipe is not readable + * \retval AST_ALERT_READ_FATAL if the alert pipe's file descriptors are in + * blocking mode, or a read error occurs. + */ +ast_alert_status_t ast_alertpipe_flush(int alert_pipe[2]); + +/*! + * \brief Sets the alert pipe file descriptors to default values + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + */ +AST_INLINE_API( +void ast_alertpipe_clear(int alert_pipe[2]), +{ + alert_pipe[0] = alert_pipe[1] = -1; +} +) + +/*! + * \brief Determine if the alert pipe is readable + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return non-zero if the alert pipe is readable, zero otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_readable(int alert_pipe[2]), +{ + return alert_pipe[0] > -1; +} +) + +/*! + * \brief Determine if the alert pipe is writable + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return non-zero if the alert pipe is writable, zero otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_writable(int alert_pipe[2]), +{ + return alert_pipe[1] > -1; +} +) + +/*! + * \brief Get the alert pipe's read file descriptor + * \since 13.16.0 + * + * \param p a two-element array containing the alert pipe's file descriptors + * + * \return -1 if the file descriptor is not initialized, a non-negative value + * otherwise. + */ +AST_INLINE_API( +int attribute_pure ast_alertpipe_readfd(int alert_pipe[2]), +{ + return alert_pipe[0]; +} +) + +/*! + * \brief Swap the file descriptors from two alert pipes + * \since 13.16.0 + * + * \param p1 a two-element array containing an alert pipe's file descriptors + * \param p2 a two-element array containing an alert pipe's file descriptors + */ +AST_INLINE_API( +void ast_alertpipe_swap(int alert_pipe_1[2], int alert_pipe_2[2]), +{ + SWAP(alert_pipe_1[0], alert_pipe_2[0]); + SWAP(alert_pipe_1[1], alert_pipe_2[1]); +} +) + +#endif /* ASTERISK_ALERTPIPE_H */ diff --git a/include/asterisk/app.h b/include/asterisk/app.h index d86b63338..0505a6b98 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -871,9 +871,34 @@ int ast_vm_test_destroy_user(const char *context, const char *mailbox); int ast_vm_test_create_user(const char *context, const char *mailbox); #endif -/*! \brief Safely spawn an external program while closing file descriptors - \note This replaces the \b system call in all Asterisk modules -*/ +/*! + * \brief Safely spawn an external program while closing file descriptors + * + * \note This replaces the \b execvp call in all Asterisk modules + * + * \param dualfork Non-zero to simulate running the program in the + * background by forking twice. The option provides similar + * functionality to the '&' in the OS shell command "cmd &". The + * option allows Asterisk to run a reaper loop to watch the first fork + * which immediately exits after spaning the second fork. The actual + * program is run in the second fork. + * \param file execvp(file, argv) file parameter + * \param argv execvp(file, argv) argv parameter + */ +int ast_safe_execvp(int dualfork, const char *file, char *const argv[]); + +/*! + * \brief Safely spawn an OS shell command while closing file descriptors + * + * \note This replaces the \b system call in all Asterisk modules + * + * \param s - OS shell command string to execute. + * + * \warning Command injection can happen using this call if the passed + * in string is created using untrusted data from an external source. + * It is best not to use untrusted data. However, the caller could + * filter out dangerous characters to avoid command injection. + */ int ast_safe_system(const char *s); /*! diff --git a/include/asterisk/ari.h b/include/asterisk/ari.h index 865b4b00c..f83d5963f 100644 --- a/include/asterisk/ari.h +++ b/include/asterisk/ari.h @@ -268,4 +268,14 @@ void ast_ari_response_created(struct ast_ari_response *response, */ void ast_ari_response_alloc_failed(struct ast_ari_response *response); +/*! \brief Determines whether the res_ari module is loaded */ +#define CHECK_ARI_MODULE_LOADED() \ + do { \ + if (!ast_module_check("res_ari.so") \ + || !ast_ari_oom_json()) { \ + return AST_MODULE_LOAD_DECLINE; \ + } \ + } while(0) + + #endif /* _ASTERISK_ARI_H */ diff --git a/include/asterisk/astmm.h b/include/asterisk/astmm.h index e129dc034..06300c861 100644 --- a/include/asterisk/astmm.h +++ b/include/asterisk/astmm.h @@ -30,21 +30,10 @@ extern "C" { #ifndef _ASTERISK_ASTMM_H #define _ASTERISK_ASTMM_H -/* IWYU pragma: private, include "asterisk/utils.h" */ - -#ifndef STANDALONE +/* IWYU pragma: private, include "asterisk.h" */ #define __AST_DEBUG_MALLOC -#include "asterisk.h" - -/* Include these now to prevent them from being needed later */ -#include <sys/types.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> - void *ast_std_malloc(size_t size); void *ast_std_calloc(size_t nmemb, size_t size); void *ast_std_realloc(void *ptr, size_t size); @@ -179,8 +168,6 @@ void __ast_mm_init_phase_2(void); #define ast_free(a) \ __ast_free(a,__FILE__, __LINE__, __PRETTY_FUNCTION__) -#endif /* !STANDALONE */ - #else #error "NEVER INCLUDE astmm.h DIRECTLY!!" #endif /* _ASTERISK_ASTMM_H */ diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index 28ae73e87..a18f099c0 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -671,6 +671,10 @@ int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, v * of the cb / data pair. If it was subscribed multiple times it must be * unsubscribed as many times. The OBJ_MULTIPLE flag can be used to remove * matching subscriptions. + * + * \note When it's time to run callbacks they are copied to a temporary list so the + * weakproxy can be unlocked before running. That means it's possible for + * this function to find nothing before the callback is run in another thread. */ int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags); @@ -854,11 +858,9 @@ struct ao2_global_obj { * \return Nothing */ #define ao2_t_global_obj_release(holder, tag) \ - __ao2_global_obj_release(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) + __ao2_global_obj_replace_unref(&holder, NULL, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) #define ao2_global_obj_release(holder) \ - __ao2_global_obj_release(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) - -void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name); + __ao2_global_obj_replace_unref(&holder, NULL, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) /*! * \brief Replace an ao2 object in the global holder. @@ -1773,6 +1775,17 @@ void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func); +/*! + * \brief Perform an ao2_find on a container with ao2_weakproxy objects, returning the real object. + * + * \note Only OBJ_SEARCH_* and OBJ_NOLOCK flags are supported by this function. + * \see ao2_callback for description of arguments. + */ +#define ao2_weakproxy_find(c, arg, flags, tag) \ + __ao2_weakproxy_find(c, arg, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) +void *__ao2_weakproxy_find(struct ao2_container *c, const void *arg, enum search_flags flags, + const char *tag, const char *file, int line, const char *func); + /*! \brief * * diff --git a/include/asterisk/autochan.h b/include/asterisk/autochan.h index 319c203ab..128377b57 100644 --- a/include/asterisk/autochan.h +++ b/include/asterisk/autochan.h @@ -32,6 +32,7 @@ struct ast_autochan { struct ast_channel *chan; AST_LIST_ENTRY(ast_autochan) list; + ast_mutex_t lock; }; /*! @@ -61,19 +62,24 @@ struct ast_autochan { * ast_autochan_channel_lock and ast_autochan_channel_unlock. An attempt to lock * the autochan->chan directly may result in it being changed after you've * retrieved the value of chan, but before you've had a chance to lock it. - * First when chan is locked, the autochan structure is guaranteed to keep the + * While chan is locked, the autochan structure is guaranteed to keep the * same channel. */ +/*! + * \brief Lock the autochan's channel lock. + * + * \note We must do deadlock avoidance because the channel lock is + * superior to the autochan lock in locking order. + */ #define ast_autochan_channel_lock(autochan) \ do { \ - struct ast_channel *autochan_chan = autochan->chan; \ - ast_channel_lock(autochan_chan); \ - if (autochan->chan == autochan_chan) { \ - break; \ + ast_mutex_lock(&(autochan)->lock); \ + while (ast_channel_trylock((autochan)->chan)) { \ + DEADLOCK_AVOIDANCE(&(autochan)->lock); \ } \ - ast_channel_unlock(autochan_chan); \ - } while (1) + ast_mutex_unlock(&(autochan)->lock); \ + } while (0) #define ast_autochan_channel_unlock(autochan) \ ast_channel_unlock(autochan->chan) diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index c7a190892..4700d4092 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -9,6 +9,9 @@ /* Define to 1 if internal poll should be used. */ #undef AST_POLL_COMPAT +/* Define to enable XML documentation. */ +#undef AST_XML_DOCS + /* Define to 1 if your system's implementation of mutexes supports comparison of a mutex to its initializer. */ #undef CAN_COMPARE_MUTEX_TO_INIT_VALUE @@ -62,6 +65,9 @@ /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF +/* Define to 1 if you have the <assert.h> header file. */ +#undef HAVE_ASSERT_H + /* Define to 1 if you have the `atan' function. */ #undef HAVE_ATAN @@ -173,6 +179,9 @@ /* Define to 1 if you have the 'crypt_r' function. */ #undef HAVE_CRYPT_R +/* Define to 1 if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + /* Define to 1 if you have a functional curl library. */ #undef HAVE_CURL @@ -201,6 +210,9 @@ /* Define to 1 if your system has the dladdr() GNU extension */ #undef HAVE_DLADDR +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT @@ -213,9 +225,16 @@ /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT +/* Define to 1 if you have the <errno.h> header file. */ +#undef HAVE_ERRNO_H + /* Define to 1 if you have the `euidaccess' function. */ #undef HAVE_EUIDACCESS +/* Define to 1 if your system supports eventfd and the EFD_NONBLOCK and + EFD_SEMAPHORE flags. */ +#undef HAVE_EVENTFD + /* Define to 1 if you have the `exp' function. */ #undef HAVE_EXP @@ -246,6 +265,9 @@ /* Define to 1 if you have the LIBFFTW3 library. */ #undef HAVE_FFTW3 +/* Define to 1 if you have the <float.h> header file. */ +#undef HAVE_FLOAT_H + /* Define to 1 if you have the `floor' function. */ #undef HAVE_FLOOR @@ -315,6 +337,9 @@ /* Define if your system has the GMIME libraries. */ #undef HAVE_GMIME +/* Define to 1 if you have the <grp.h> header file. */ +#undef HAVE_GRP_H + /* Define to indicate the GSM library */ #undef HAVE_GSM @@ -464,6 +489,9 @@ /* Define to 1 if you have the <malloc.h> header file. */ #undef HAVE_MALLOC_H +/* Define to 1 if you have the <math.h> header file. */ +#undef HAVE_MATH_H + /* Define to 1 if you have the `memchr' function. */ #undef HAVE_MEMCHR @@ -563,6 +591,9 @@ /* Define to 1 if you have the Opus library. */ #undef HAVE_OPUS +/* Define to 1 if you have the Opusfile library. */ +#undef HAVE_OPUSFILE + /* Define this to indicate the ${OSPTK_DESCRIP} library */ #undef HAVE_OSPTK @@ -621,6 +652,10 @@ /* Define if your system has the PJSIP_TLS_TRANSPORT_PROTO headers. */ #undef HAVE_PJSIP_TLS_TRANSPORT_PROTO +/* Define to 1 if PJPROJECT has the pjsip_tsx_layer_find_tsx2 support feature. + */ +#undef HAVE_PJSIP_TSX_LAYER_FIND_TSX2 + /* Define to 1 if PJPROJECT has the pj_ssl_cert_load_from_files2 support feature. */ #undef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2 @@ -755,6 +790,9 @@ /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV +/* Define to 1 if you have the <pwd.h> header file. */ +#undef HAVE_PWD_H + /* Define if your system has the PWLib libraries. */ #undef HAVE_PWLIB @@ -767,6 +805,9 @@ /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP +/* Define to 1 if you have the <regex.h> header file. */ +#undef HAVE_REGEX_H + /* Define to 1 if you have the `remainder' function. */ #undef HAVE_REMAINDER @@ -776,6 +817,9 @@ /* Define to 1 if you have the LIBRESAMPLE library. */ #undef HAVE_RESAMPLE +/* Define to 1 if you have the <resolv.h> header file. */ +#undef HAVE_RESOLV_H + /* Define to 1 if your system has the close resolver function. */ #undef HAVE_RES_CLOSE @@ -812,6 +856,9 @@ /* Define to 1 if your system has /sbin/launchd. */ #undef HAVE_SBIN_LAUNCHD +/* Define to 1 if you have the <sched.h> header file. */ +#undef HAVE_SCHED_H + /* Define if your system has the SDL libraries. */ #undef HAVE_SDL @@ -879,6 +926,9 @@ /* Define to 1 if SRTP has the SRTP Library Shutdown Function feature. */ #undef HAVE_SRTP_SHUTDOWN +/* Define to the version of the srtp library. */ +#undef HAVE_SRTP_VERSION + /* Define to 1 if you have the ISDN SS7 library. */ #undef HAVE_SS7 @@ -892,6 +942,9 @@ zero-length file name argument. */ #undef HAVE_STAT_EMPTY_STRING_BUG +/* Define to 1 if you have the <stdarg.h> header file. */ +#undef HAVE_STDARG_H + /* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H @@ -901,6 +954,9 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -1069,9 +1125,6 @@ /* Define to 1 if you have the <sys/ioctl.h> header file. */ #undef HAVE_SYS_IOCTL_H -/* Define to 1 if you have the <sys/io.h> header file. */ -#undef HAVE_SYS_IO_H - /* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H @@ -1082,6 +1135,9 @@ /* Define to 1 if your system has working sys/poll.h */ #undef HAVE_SYS_POLL_H +/* Define to 1 if you have the <sys/resource.h> header file. */ +#undef HAVE_SYS_RESOURCE_H + /* Define to 1 if you have the <sys/select.h> header file. */ #undef HAVE_SYS_SELECT_H @@ -1100,6 +1156,9 @@ /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the <sys/un.h> header file. */ +#undef HAVE_SYS_UN_H + /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H @@ -1121,6 +1180,9 @@ /* Define to 1 if your system defines timersub. */ #undef HAVE_TIMERSUB +/* Define to 1 if you have the <time.h> header file. */ +#undef HAVE_TIME_H + /* Define to 1 if you have the Term Info library. */ #undef HAVE_TINFO diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index ffe08da13..8d5c50211 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -102,6 +102,10 @@ enum ast_bridge_video_mode_type { /*! A single user's video feed is distributed to all bridge channels, but * that feed is automatically picked based on who is talking the most. */ AST_BRIDGE_VIDEO_MODE_TALKER_SRC, + /*! Operate as a selective forwarding unit. Video from each participant is + * cloned to a dedicated stream on a subset of the remaining participants. + */ + AST_BRIDGE_VIDEO_MODE_SFU, }; /*! \brief This is used for both SINGLE_SRC mode to set what channel @@ -130,6 +134,7 @@ struct ast_bridge_video_mode { struct ast_bridge_video_single_src_data single_src_data; struct ast_bridge_video_talker_src_data talker_src_data; } mode_data; + unsigned int video_update_discard; }; /*! @@ -267,6 +272,8 @@ struct ast_bridge_softmix { unsigned int binaural_active; }; +AST_LIST_HEAD_NOLOCK(ast_bridge_channels_list, ast_bridge_channel); + /*! * \brief Structure that contains information about a bridge */ @@ -284,7 +291,7 @@ struct ast_bridge { /*! Call ID associated with the bridge */ ast_callid callid; /*! Linked list of channels participating in the bridge */ - AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) channels; + struct ast_bridge_channels_list channels; /*! Queue of actions to perform on the bridge. */ AST_LIST_HEAD_NOLOCK(, ast_frame) action_queue; /*! Softmix technology parameters. */ @@ -323,6 +330,9 @@ struct ast_bridge { /*! Immutable bridge UUID. */ AST_STRING_FIELD(uniqueid); ); + + /*! Type mapping used for media routing */ + struct ast_vector_int media_types; }; /*! \brief Bridge base class virtual method table. */ @@ -889,6 +899,19 @@ void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_ void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge); /*! + * \brief Set the bridge to be a selective forwarding unit + */ +void ast_bridge_set_sfu_video_mode(struct ast_bridge *bridge); + +/*! + * \brief Set the amount of time to discard subsequent video updates after a video update has been sent + * + * \param bridge Bridge to set the minimum video update wait time on + * \param video_update_discard Amount of time after sending a video update that others should be discarded + */ +void ast_bridge_set_video_update_discard(struct ast_bridge *bridge, unsigned int video_update_discard); + +/*! * \brief Update information about talker energy for talker src video mode. */ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyfame); diff --git a/include/asterisk/bridge_after.h b/include/asterisk/bridge_after.h index 53f30b9ad..045168571 100644 --- a/include/asterisk/bridge_after.h +++ b/include/asterisk/bridge_after.h @@ -45,6 +45,8 @@ enum ast_bridge_after_cb_reason { AST_BRIDGE_AFTER_CB_REASON_DEPART, /*! Was explicitly removed by external code. */ AST_BRIDGE_AFTER_CB_REASON_REMOVED, + /*! The channel failed to enter the bridge. */ + AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED, }; /*! diff --git a/include/asterisk/bridge_channel.h b/include/asterisk/bridge_channel.h index a7971df27..4504d6bcb 100644 --- a/include/asterisk/bridge_channel.h +++ b/include/asterisk/bridge_channel.h @@ -145,6 +145,8 @@ struct ast_bridge_channel { AST_LIST_ENTRY(ast_bridge_channel) entry; /*! Queue of outgoing frames to the channel. */ AST_LIST_HEAD_NOLOCK(, ast_frame) wr_queue; + /*! Queue of deferred frames, queued onto channel when other party joins. */ + AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_queue; /*! Pipe to alert thread when frames are put into the wr_queue. */ int alert_pipe[2]; /*! @@ -183,6 +185,12 @@ struct ast_bridge_channel { unsigned int padding:30; }; }; + struct { + /*! An index mapping of where a channel's media needs to be routed */ + struct ast_vector_int to_bridge; + /*! An index mapping of where a bridge's media needs to be routed */ + struct ast_vector_int to_channel; + } stream_map; }; /*! @@ -704,6 +712,32 @@ void ast_bridge_channel_feature_digit_add(struct ast_bridge_channel *bridge_chan */ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, int digit); +/*! + * \brief Maps a channel's stream topology to and from the bridge + * \since 15.0.0 + * + * \details + * When a channel joins a bridge or its associated stream topology is + * updated, each stream in the topology needs to be mapped according + * to its media type to the bridge. Calling this method creates a + * mapping of each stream on the channel indexed to the bridge's + * supported media types and vice versa (i.e. bridge's media types + * indexed to channel streams). + * + * The first channel to join the bridge creates the initial order for + * the bridge's media types (e.g. a one to one mapping is made). + * Subsequently added channels are mapped to that order adding more + * media types if/when the newly added channel has more streams and/or + * media types specified by the bridge. + * + * \param bridge_channel Channel to map + * + * \note The bridge_channel's bridge must be locked prior to calling this function. + * + * \return Nothing + */ +void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/include/asterisk/bridge_channel_internal.h b/include/asterisk/bridge_channel_internal.h index fb8e781e8..ba71e9fc4 100644 --- a/include/asterisk/bridge_channel_internal.h +++ b/include/asterisk/bridge_channel_internal.h @@ -98,6 +98,17 @@ void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct as /*! * \internal + * \brief Queue any deferred frames on the channel. + * \since 13.17.0 + * + * \param bridge_channel Channel that the deferred frames should be pulled from and queued to. + * + * \return Nothing + */ +void bridge_channel_queue_deferred_frames(struct ast_bridge_channel *bridge_channel); + +/*! + * \internal * \brief Push the bridge channel into its specified bridge. * \since 12.0.0 * diff --git a/include/asterisk/bridge_technology.h b/include/asterisk/bridge_technology.h index 8df19d9e9..eaea28de5 100644 --- a/include/asterisk/bridge_technology.h +++ b/include/asterisk/bridge_technology.h @@ -108,8 +108,13 @@ struct ast_bridge_technology { * * \note On entry, bridge is already locked. * - * \note The bridge technology must tollerate a failed to join channel + * \note The bridge technology must tolerate a failed to join channel * until it can be kicked from the bridge. + * + * \note A channel may be in a suspended state already when joining a bridge + * technology. The technology must handle this case. + * + * \note A channel may not be answered when joining a bridge technology. */ int (*join)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); /*! @@ -153,8 +158,40 @@ struct ast_bridge_technology { * \retval -1 Frame needs to be deferred. * * \note On entry, bridge is already locked. + * + * \note Deferred frames will be automatically queued onto the channel when another + * channel joins the bridge. */ int (*write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame); + /*! + * \brief Callback for when a request has been made to change a stream topology on a channel + * + * \details + * This is called when a bridge receives a request to change the + * topology on the channel. A bridge technology should define a + * handler for this callback if it needs to update internals or + * intercept the request and not pass it on to other channels. + * This can be done by returning a nonzero value. + * + * \retval 0 Frame can pass to the bridge technology. + * \retval non-zero Frame intercepted by the bridge technology. + * + * \note On entry, bridge is already locked. + */ + int (*stream_topology_request_change)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); + /*! + * \brief Callback for when a stream topology changes on the channel + * + * \details + * This is called when a bridge receives an indication that a + * topology has been changed on a channel and the new topology has + * been mapped to the bridge. A bridge technology should define a + * handler for this callback if it needs to update internals due + * to a channel's topology changing. + * + * \note On entry, bridge is already locked. + */ + void (*stream_topology_changed)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel); /*! TRUE if the bridge technology is currently suspended. */ unsigned int suspended:1; /*! Module this bridge technology belongs to. It is used for reference counting bridges using the technology. */ diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index f752f7f9f..e10da8223 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -217,19 +217,19 @@ /*! \brief CDR engine settings */ enum ast_cdr_settings { - CDR_ENABLED = 1 << 0, /*< Enable CDRs */ - CDR_BATCHMODE = 1 << 1, /*< Whether or not we should dispatch CDRs in batches */ - CDR_UNANSWERED = 1 << 2, /*< Log unanswered CDRs */ - CDR_CONGESTION = 1 << 3, /*< Treat congestion as if it were a failed call */ - CDR_END_BEFORE_H_EXTEN = 1 << 4, /*< End the CDR before the 'h' extension runs */ - CDR_INITIATED_SECONDS = 1 << 5, /*< Include microseconds into the billing time */ - CDR_DEBUG = 1 << 6, /*< Enables extra debug statements */ + CDR_ENABLED = 1 << 0, /*!< Enable CDRs */ + CDR_BATCHMODE = 1 << 1, /*!< Whether or not we should dispatch CDRs in batches */ + CDR_UNANSWERED = 1 << 2, /*!< Log unanswered CDRs */ + CDR_CONGESTION = 1 << 3, /*!< Treat congestion as if it were a failed call */ + CDR_END_BEFORE_H_EXTEN = 1 << 4, /*!< End the CDR before the 'h' extension runs */ + CDR_INITIATED_SECONDS = 1 << 5, /*!< Include microseconds into the billing time */ + CDR_DEBUG = 1 << 6, /*!< Enables extra debug statements */ }; /*! \brief CDR Batch Mode settings */ enum ast_cdr_batch_mode_settings { - BATCH_MODE_SCHEDULER_ONLY = 1 << 0, /*< Don't spawn a thread to handle the batches - do it on the scheduler */ - BATCH_MODE_SAFE_SHUTDOWN = 1 << 1, /*< During safe shutdown, submit the batched CDRs */ + BATCH_MODE_SCHEDULER_ONLY = 1 << 0, /*!< Don't spawn a thread to handle the batches - do it on the scheduler */ + BATCH_MODE_SAFE_SHUTDOWN = 1 << 1, /*!< During safe shutdown, submit the batched CDRs */ }; /*! @@ -237,14 +237,14 @@ enum ast_cdr_batch_mode_settings { * state of a CDR object based on these flags. */ enum ast_cdr_options { - AST_CDR_FLAG_KEEP_VARS = (1 << 0), /*< Copy variables during the operation */ - AST_CDR_FLAG_DISABLE = (1 << 1), /*< Disable the current CDR */ - AST_CDR_FLAG_DISABLE_ALL = (3 << 1), /*< Disable the CDR and all future CDRs */ - AST_CDR_FLAG_PARTY_A = (1 << 3), /*< Set the channel as party A */ - AST_CDR_FLAG_FINALIZE = (1 << 4), /*< Finalize the current CDRs */ - AST_CDR_FLAG_SET_ANSWER = (1 << 5), /*< If the channel is answered, set the answer time to now */ - AST_CDR_FLAG_RESET = (1 << 6), /*< If set, set the start and answer time to now */ - AST_CDR_LOCK_APP = (1 << 7), /*< Prevent any further changes to the application field/data field for this CDR */ + AST_CDR_FLAG_KEEP_VARS = (1 << 0), /*!< Copy variables during the operation */ + AST_CDR_FLAG_DISABLE = (1 << 1), /*!< Disable the current CDR */ + AST_CDR_FLAG_DISABLE_ALL = (3 << 1), /*!< Disable the CDR and all future CDRs */ + AST_CDR_FLAG_PARTY_A = (1 << 3), /*!< Set the channel as party A */ + AST_CDR_FLAG_FINALIZE = (1 << 4), /*!< Finalize the current CDRs */ + AST_CDR_FLAG_SET_ANSWER = (1 << 5), /*!< If the channel is answered, set the answer time to now */ + AST_CDR_FLAG_RESET = (1 << 6), /*!< If set, set the start and answer time to now */ + AST_CDR_LOCK_APP = (1 << 7), /*!< Prevent any further changes to the application field/data field for this CDR */ }; /*! @@ -262,11 +262,11 @@ enum ast_cdr_disposition { /*! \brief The global options available for CDRs */ struct ast_cdr_config { - struct ast_flags settings; /*< CDR settings */ + struct ast_flags settings; /*!< CDR settings */ struct batch_settings { - unsigned int time; /*< Time between batches */ - unsigned int size; /*< Size to trigger a batch */ - struct ast_flags settings; /*< Settings for batches */ + unsigned int time; /*!< Time between batches */ + unsigned int size; /*!< Size to trigger a batch */ + struct ast_flags settings; /*!< Settings for batches */ } batch_settings; }; @@ -312,7 +312,7 @@ struct ast_cdr { unsigned int flags; /*! Unique Channel Identifier */ char uniqueid[AST_MAX_UNIQUEID]; - /* Linked group Identifier */ + /*! Linked group Identifier */ char linkedid[AST_MAX_UNIQUEID]; /*! User field */ char userfield[AST_MAX_USER_FIELD]; diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h index 350b4bf9f..c77a3538c 100644 --- a/include/asterisk/cel.h +++ b/include/asterisk/cel.h @@ -87,29 +87,6 @@ enum ast_cel_event_type { */ unsigned int ast_cel_check_enabled(void); -/*! - * \brief Allocate a CEL record - * - * \since 1.8 - * - * \note The CEL record must be destroyed with ast_cel_destroy(). - * - * \retval non-NULL an allocated ast_cel structure - * \retval NULL error - */ -struct ast_cel *ast_cel_alloc(void); - -/*! - * \brief Destroy a CEL record. - * - * \param cel the record to destroy - * - * \since 1.8 - * - * \return nothing. - */ -void ast_cel_destroy(struct ast_cel *cel); - /*! * \brief Get the name of a CEL event type * diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 80476a4e0..3dfbe61d9 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -123,6 +123,7 @@ References: #ifndef _ASTERISK_CHANNEL_H #define _ASTERISK_CHANNEL_H +#include "asterisk/alertpipe.h" #include "asterisk/abstract_jb.h" #include "asterisk/astobj2.h" #include "asterisk/poll-compat.h" @@ -173,17 +174,17 @@ extern "C" { #include "asterisk/linkedlists.h" #include "asterisk/stringfields.h" #include "asterisk/datastore.h" -#include "asterisk/data.h" +#include "asterisk/format_cap.h" #include "asterisk/channelstate.h" #include "asterisk/ccss.h" #include "asterisk/framehook.h" #include "asterisk/stasis.h" -#include "asterisk/json.h" #include "asterisk/endpoints.h" #define DATASTORE_INHERIT_FOREVER INT_MAX -#define AST_MAX_FDS 11 +#define AST_MAX_FDS 11 /*!< original maximum number of file descriptors */ +#define AST_EXTENDED_FDS 12 /*!< the start of extended file descriptor positions */ /* * We have AST_MAX_FDS file descriptors in a channel. * Some of them have a fixed use: @@ -203,6 +204,8 @@ enum ast_bridge_result { typedef unsigned long long ast_group_t; +struct ast_stream_topology; + /*! \todo Add an explanation of an Asterisk generator */ struct ast_generator { @@ -630,6 +633,26 @@ struct ast_channel_tech { */ struct ast_channel *(* const requester)(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause); + /*! + * \brief Requester - to set up call data structures (pvt's) with stream topology + * + * \param type type of channel to request + * \param topology Stream topology for requested channel + * \param assignedid Unique ID string to assign to channel + * \param requestor channel asking for data + * \param addr destination of the call + * \param cause Cause of failure + * + * \details + * Request a channel of a given type, with addr as optional information used + * by the low level module + * + * \retval NULL failure + * \retval non-NULL channel on success + */ + struct ast_channel *(* const requester_with_stream_topology)(const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause); + + int (* const devicestate)(const char *device_number); /*!< Devicestate call back */ int (* const presencestate)(const char *presence_provider, char **subtype, char **message); /*!< Presencestate callback */ @@ -664,9 +687,33 @@ struct ast_channel_tech { /*! \brief Answer the channel */ int (* const answer)(struct ast_channel *chan); - /*! \brief Read a frame, in standard format (see frame.h) */ + /*! + * \brief Read a frame (or chain of frames from the same stream), in standard format (see frame.h) + * + * \param chan channel to read frames from + * + * \retval non-NULL on success + * \retval NULL on failure + * + * \note Each media frame from this callback will have the stream_num of it changed to the default + * stream num based on the type of media returned. As a result a multistream capable channel + * should not implement this callback. + */ struct ast_frame * (* const read)(struct ast_channel *chan); + /*! + * \brief Read a frame (or chain of frames from the same stream), in standard format (see frame.h), with stream num + * + * \param chan channel to read frames from + * + * \retval non-NULL on success + * \retval NULL on failure + * + * \note Each media frame from this callback should contain a stream_num value which is set to the + * stream that the media frame originated from. + */ + struct ast_frame * (* const read_stream)(struct ast_channel *chan); + /*! \brief Write a frame, in standard format (see frame.h) */ int (* const write)(struct ast_channel *chan, struct ast_frame *frame); @@ -887,10 +934,6 @@ enum { * world */ AST_CHAN_TP_INTERNAL = (1 << 2), - /*! - * \brief Channels with this particular technology support multiple simultaneous streams - */ - AST_CHAN_TP_MULTISTREAM = (1 << 3), }; /*! \brief ast_channel flags */ @@ -1373,6 +1416,25 @@ struct ast_channel *ast_channel_release(struct ast_channel *chan); */ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause); +/*! + * \brief Requests a channel (specifying stream topology) + * + * \param type type of channel to request + * \param topology Stream topology for requested channel + * \param assignedids Unique ID to create channel with + * \param requestor channel asking for data + * \param addr destination of the call + * \param cause Cause of failure + * + * \details + * Request a channel of a given type, with addr as optional information used + * by the low level module + * + * \retval NULL failure + * \retval non-NULL channel on success + */ +struct ast_channel *ast_request_with_stream_topology(const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause); + enum ast_channel_requestor_relationship { /*! The requestor is the future bridge peer of the channel. */ AST_CHANNEL_REQUESTOR_BRIDGE_PEER, @@ -1926,14 +1988,37 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception); /*! * \brief Reads a frame + * * \param chan channel to read a frame from + * * \return Returns a frame, or NULL on error. If it returns NULL, you * best just stop reading frames and assume the channel has been * disconnected. + * + * \note This function will filter frames received from the channel so + * that only frames from the default stream for each media type + * are returned. All other media frames from other streams will + * be absorbed internally and a NULL frame returned instead. */ struct ast_frame *ast_read(struct ast_channel *chan); /*! + * \brief Reads a frame, but does not filter to just the default streams + * + * \param chan channel to read a frame from + * + * \return Returns a frame, or NULL on error. If it returns NULL, you + * best just stop reading frames and assume the channel has been + * disconnected. + * + * \note This function will not perform any filtering and will return + * media frames from all streams on the channel. To determine which + * stream a frame originated from the stream_num on it can be + * examined. + */ +struct ast_frame *ast_read_stream(struct ast_channel *chan); + +/*! * \brief Reads a frame, returning AST_FRAME_NULL frame if audio. * \param chan channel to read a frame from * \return Returns a frame, or NULL on error. If it returns NULL, you @@ -1945,6 +2030,26 @@ struct ast_frame *ast_read(struct ast_channel *chan); struct ast_frame *ast_read_noaudio(struct ast_channel *chan); /*! + * \brief Reads a frame, but does not filter to just the default streams, + * returning AST_FRAME_NULL frame if audio. + * + * \param chan channel to read a frame from + * + * \return Returns a frame, or NULL on error. If it returns NULL, you + * best just stop reading frames and assume the channel has been + * disconnected. + * + * \note This function will not perform any filtering and will return + * media frames from all streams on the channel. To determine which + * stream a frame originated from the stream_num on it can be + * examined. + * + * \note Audio is replaced with AST_FRAME_NULL to avoid + * transcode when the resulting audio is not necessary. + */ +struct ast_frame *ast_read_stream_noaudio(struct ast_channel *chan); + +/*! * \brief Write a frame to a channel * This function writes the given frame to the indicated channel. * \param chan destination channel of the frame @@ -2134,11 +2239,12 @@ int ast_waitfordigit(struct ast_channel *c, int ms); * Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading. * \param c channel to wait for a digit on * \param ms how many milliseconds to wait (<0 for indefinite). + * \param breakon string of DTMF digits to break upon or NULL for any. * \param audiofd audio file descriptor to write to if audio frames are received * \param ctrlfd control file descriptor to monitor for reading * \return Returns 1 if ctrlfd becomes available */ -int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd); +int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd); /*! * \brief Reads multiple digits @@ -2359,12 +2465,6 @@ void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_par /*! Set the file descriptor on the channel */ void ast_channel_set_fd(struct ast_channel *chan, int which, int fd); -/*! Add a channel to an optimized waitfor */ -void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1); - -/*! Delete a channel from an optimized waitfor */ -void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1); - /*! Start a tone going */ int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol); /*! Stop a tone from playing */ @@ -3760,27 +3860,6 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame); /*! - * \brief Insert into an astdata tree, the channel structure. - * \param[in] tree The ast data tree. - * \param[in] chan The channel structure to add to tree. - * \param[in] add_bridged Add the bridged channel to the structure. - * \retval <0 on error. - * \retval 0 on success. - */ -int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan, int add_bridged); - -/*! - * \brief Compare to channel structures using the data api. - * \param[in] tree The search tree generated by the data api. - * \param[in] chan The channel to compare. - * \param[in] structure_name The name of the node of the channel structure. - * \retval 0 The structure matches. - * \retval 1 The structure doesn't matches. - */ -int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct ast_channel *chan, - const char *structure_name); - -/*! * \since 1.8 * \brief Run a redirecting interception macro and update a channel's redirecting information * \deprecated You should use the ast_channel_redirecting_sub() function instead. @@ -4230,12 +4309,6 @@ struct ast_namedgroups *ast_channel_named_pickupgroups(const struct ast_channel void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value); /* Alertpipe accessors--the "internal" functions for channel.c use only */ -typedef enum { - AST_ALERT_READ_SUCCESS = 0, - AST_ALERT_NOT_READABLE, - AST_ALERT_READ_FAIL, - AST_ALERT_READ_FATAL, -} ast_alert_status_t; int ast_channel_alert_write(struct ast_channel *chan); int ast_channel_alert_writable(struct ast_channel *chan); ast_alert_status_t ast_channel_internal_alert_flush(struct ast_channel *chan); @@ -4257,11 +4330,30 @@ void ast_channel_internal_fd_set(struct ast_channel *chan, int which, int value) int ast_channel_fd(const struct ast_channel *chan, int which); int ast_channel_fd_isset(const struct ast_channel *chan, int which); -/* epoll data internal accessors */ -#ifdef HAVE_EPOLL -struct ast_epoll_data *ast_channel_internal_epfd_data(const struct ast_channel *chan, int which); -void ast_channel_internal_epfd_data_set(struct ast_channel *chan, int which , struct ast_epoll_data *value); -#endif +/*! + * \since 15 + * \brief Retrieve the number of file decriptor positions present on the channel + * + * \param chan The channel to get the count of + * + * \pre chan is locked + * + * \return The number of file descriptor positions + */ +int ast_channel_fd_count(const struct ast_channel *chan); + +/*! + * \since 15 + * \brief Add a file descriptor to the channel without a fixed position + * + * \param chan The channel to add the file descriptor to + * \param value The file descriptor + * + * \pre chan is locked + * + * \return The position of the file descriptor + */ +int ast_channel_fd_add(struct ast_channel *chan, int value); pthread_t ast_channel_blocker(const struct ast_channel *chan); void ast_channel_blocker_set(struct ast_channel *chan, pthread_t value); @@ -4345,6 +4437,31 @@ void ast_channel_dialed_causes_clear(const struct ast_channel *chan); struct ast_flags *ast_channel_flags(struct ast_channel *chan); /*! + * \since 13.17.0 + * \brief Set a flag on a channel + * + * \param chan The channel to set the flag on + * \param flag The flag to set + * + * \note This will lock the channel internally. If the channel is already + * locked it is still safe to call. + */ + +void ast_channel_set_flag(struct ast_channel *chan, unsigned int flag); + +/*! + * \since 13.17.0 + * \param Clear a flag on a channel + * + * \param chan The channel to clear the flag from + * \param flag The flag to clear + * + * \note This will lock the channel internally. If the channel is already + * locked it is still safe to call. + */ +void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag); + +/*! * \since 12.4.0 * \brief Return whether or not any manager variables have been set * @@ -4548,6 +4665,9 @@ struct ast_bridge_channel *ast_channel_get_bridge_channel(struct ast_channel *ch * * \note absolutely _NO_ channel locks should be held before calling this function. * + * \note The dialplan location on the returned channel is where the channel + * should be started in the dialplan if it is returned to it. + * * \param yankee The channel to gain control of * \retval NULL Could not gain control of the channel * \retval non-NULL The channel @@ -4796,4 +4916,63 @@ struct ast_stream_topology *ast_channel_set_stream_topology( */ struct ast_stream *ast_channel_get_default_stream(struct ast_channel *chan, enum ast_media_type type); +/*! + * \brief Determine if a channel is multi-stream capable + * + * \param channel The channel to test + * + * \pre chan is locked + * + * \return Returns true if the channel is multi-stream capable. + */ +int ast_channel_is_multistream(struct ast_channel *chan); + +/*! + * \brief Request that the stream topology of a channel change + * + * \param chan The channel to change + * \param topology The new stream topology + * \param change_source The source that initiated the change + * + * \note Absolutely _NO_ channel locks should be held before calling this function. + * + * \retval 0 request has been accepted to be attempted + * \retval -1 request could not be attempted + * + * \note This function initiates an asynchronous request to change the stream topology. It is not + * guaranteed that the topology will change and until an AST_CONTROL_STREAM_TOPOLOGY_CHANGED + * frame is received from the channel the current handler of the channel must tolerate the + * stream topology as it currently exists. + * + * \note This interface is provided for applications and resources to request that the topology change. + * It is not for use by the channel driver itself. + */ +int ast_channel_request_stream_topology_change(struct ast_channel *chan, + struct ast_stream_topology *topology, void *change_source); + +/*! + * \brief Provide notice to a channel that the stream topology has changed + * + * \param chan The channel to provide notice to + * \param topology The new stream topology + * + * \pre chan is locked Absolutely _NO_ other channels can be locked. + * + * \retval 0 success + * \retval -1 failure + * + * \note This interface is provided for applications and resources to accept a topology change. + * It is not for use by the channel driver itself. + */ +int ast_channel_stream_topology_changed(struct ast_channel *chan, struct ast_stream_topology *topology); + +/*! + * \brief Retrieve the source that initiated the last stream topology change + * + * \param chan The channel + * + * \retval The channel's stream topology change source + */ +void *ast_channel_get_stream_topology_change_source(struct ast_channel *chan); + #endif /* _ASTERISK_CHANNEL_H */ diff --git a/include/asterisk/channel_internal.h b/include/asterisk/channel_internal.h index 3de2b14aa..dd791a416 100644 --- a/include/asterisk/channel_internal.h +++ b/include/asterisk/channel_internal.h @@ -29,5 +29,7 @@ void ast_channel_internal_errno_set(enum ast_channel_error error); enum ast_channel_error ast_channel_internal_errno(void); void ast_channel_internal_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology); +void ast_channel_internal_set_stream_topology_change_source( + struct ast_channel *chan, void *change_source); void ast_channel_internal_swap_stream_topology(struct ast_channel *chan1, struct ast_channel *chan2); diff --git a/include/asterisk/codec.h b/include/asterisk/codec.h index 2ae955181..79798acd0 100644 --- a/include/asterisk/codec.h +++ b/include/asterisk/codec.h @@ -76,6 +76,8 @@ struct ast_codec { int (*get_length)(unsigned int samples); /*! \brief Whether the media can be smoothed or not */ unsigned int smooth; + /*! \brief Flags to be passed to the smoother */ + unsigned int smoother_flags; /*! \brief The module that registered this codec */ struct ast_module *mod; }; @@ -166,6 +168,17 @@ int ast_codec_get_max(void); const char *ast_codec_media_type2str(enum ast_media_type type); /*! + * \brief Conversion function to take a media string and convert it to a media type + * + * \param media_type_str The media type string + * + * \retval The ast_media_type that corresponds to the string + * + * \since 15.0.0 + */ +enum ast_media_type ast_media_type_from_str(const char *media_type_str); + +/*! * \brief Get the number of samples contained within a frame * * \param frame The frame itself diff --git a/include/asterisk/compat.h b/include/asterisk/compat.h index 252ce914a..88f88cf8b 100644 --- a/include/asterisk/compat.h +++ b/include/asterisk/compat.h @@ -27,35 +27,18 @@ #define __STDC_VERSION__ 0 #endif -#ifdef HAVE_INTTYPES_H #include <inttypes.h> -#endif - -#ifdef HAVE_LIMITS_H #include <limits.h> -#endif - -#ifdef HAVE_UNISTD_H #include <unistd.h> -#endif #ifdef HAVE_STDDEF_H #include <stddef.h> #endif -#ifdef HAVE_STDINT_H #include <stdint.h> -#endif - -#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#endif - #include <stdarg.h> - -#ifdef HAVE_STDLIB_H #include <stdlib.h> -#endif #ifdef HAVE_ALLOCA_H #include <alloca.h> /* not necessarily present - could be in stdlib */ @@ -65,9 +48,7 @@ #include <stdio.h> /* this is always present */ -#ifdef HAVE_STRING_H #include <string.h> -#endif #ifndef AST_POLL_COMPAT #include <poll.h> @@ -158,7 +139,6 @@ void timersub(struct timeval *tvend, struct timeval *tvstart, struct timeval *tv #include <alloca.h> #include <strings.h> -#include <string.h> #include <pthread.h> #include <sys/stat.h> #include <signal.h> diff --git a/include/asterisk/config.h b/include/asterisk/config.h index f57966b0b..1addfa317 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -1086,6 +1086,11 @@ enum ast_parse_flags { PARSE_UINT16 = 0x0005, #endif + /* Returns an int processed by ast_app_parse_timelen. + * The first argument is an enum ast_timelen value (required). + */ + PARSE_TIMELEN = 0x0006, + /* Returns a struct ast_sockaddr, with optional default value * (passed by reference) and port handling (accept, ignore, * require, forbid). The format is 'ipaddress[:port]'. IPv6 address @@ -1152,6 +1157,12 @@ enum ast_parse_flags { * returns 1, b unchanged * ast_parse_arg("12", PARSE_UINT32|PARSE_IN_RANGE|PARSE_RANGE_DEFAULTS, &a, 1, 10); * returns 1, a = 10 + * ast_parse_arg("223", PARSE_TIMELEN|PARSE_IN_RANGE, &a, TIMELEN_SECONDS, -1000, 1000); + * returns 0, a = 1000 + * ast_parse_arg("223", PARSE_TIMELEN|PARSE_IN_RANGE, &a, TIMELEN_SECONDS, -1000, 250000); + * returns 0, a = 223000 + * ast_parse_arg("223", PARSE_TIMELEN|PARSE_IN_RANGE|PARSE_DEFAULT, &a, TIMELEN_SECONDS, 9999, -1000, 250000); + * returns 0, a = 9999 * ast_parse_arg("www.foo.biz:44", PARSE_INADDR, &sa); * returns 0, sa contains address and port * ast_parse_arg("www.foo.biz", PARSE_INADDR|PARSE_PORT_REQUIRE, &sa); diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h index f2a457eb5..f4c3db188 100644 --- a/include/asterisk/config_options.h +++ b/include/asterisk/config_options.h @@ -468,6 +468,30 @@ enum aco_option_type { */ OPT_YESNO_T, + /*! \brief Type for default option handler for time length signed integers + * + * \note aco_option_register flags: + * See flags available for use with the PARSE_TIMELEN type for the ast_parse_arg function + * aco_option_register varargs: + * FLDSET macro with the field of type int + * The remaining varargs for should be arguments compatible with the varargs for the + * ast_parse_arg function with the PARSE_TIMELEN type and the flags passed in the + * aco_option_register flags parameter. + * + * \note In most situations, it is preferable to not pass the PARSE_DEFAULT flag. If a config + * contains an invalid value, it is better to let the config loading fail with warnings so that + * the problem is fixed by the administrator. + * + * Example: + * struct test_item { + * int timelen; + * }; + * {code} + * aco_option_register(&cfg_info, "timelen", ACO_EXACT, my_types, "3", OPT_TIMELEN_T, PARSE_IN_RANGE, FLDSET(struct test_item, intopt), TIMELEN_MILLISECONDS, -10, 10); + * {endcode} + */ + OPT_TIMELEN_T, + }; /*! \brief A callback function for handling a particular option diff --git a/include/asterisk/conversions.h b/include/asterisk/conversions.h new file mode 100644 index 000000000..2997760a8 --- /dev/null +++ b/include/asterisk/conversions.h @@ -0,0 +1,62 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2017, Digium, Inc. + * + * Kevin Harwell <kharwell@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 Conversion utility functions + */ + +#ifndef _ASTERISK_CONVERSIONS_H +#define _ASTERISK_CONVERSIONS_H + +/*! + * \brief Convert the given string to an unsigned integer + * + * This function will return failure for the following reasons: + * + * The given string to convert is NULL + * The given string to convert is empty. + * The given string to convert is negative (starts with a '-') + * The given string to convert contains non numeric values + * Once converted the number is out of range (greater than UINT_MAX) + * + * \param str The string to convert + * \param res [out] The converted value + * + * \returns -1 if it fails to convert, 0 on success + */ +int ast_str_to_uint(const char *str, unsigned int *res); + +/*! + * \brief Convert the given string to an unsigned long + * + * This function will return failure for the following reasons: + * + * The given string to convert is NULL + * The given string to convert is empty. + * The given string to convert is negative (starts with a '-') + * The given string to convert contains non numeric values + * Once converted the number is out of range (greater than ULONG_MAX) + * + * \param str The string to convert + * \param res [out] The converted value + * + * \returns -1 if it fails to convert, 0 on success + */ +int ast_str_to_ulong(const char *str, unsigned long *res); + +#endif /* _ASTERISK_CONVERSIONS_H */ diff --git a/include/asterisk/core_local.h b/include/asterisk/core_local.h index 8557072c6..27e924477 100644 --- a/include/asterisk/core_local.h +++ b/include/asterisk/core_local.h @@ -42,36 +42,37 @@ struct stasis_message_type; /* ------------------------------------------------------------------- */ /*! - * \brief Lock the "chan" and "owner" channels (and return them) on the base - * private structure as well as the base private structure itself. + * \brief Add a reference to the local channel's private tech, lock the local channel's + * private base, and add references and lock both sides of the local channel. * - * \note This also adds references to each of the above mentioned elements and - * also the underlying private local structure. * \note None of these locks should be held prior to calling this function. - * \note To undo this process call ast_local_unlock_all. + * \note To undo this process call ast_local_unlock_all2. * - * \since 13.8.0 + * \since 13.17.0, 14.6.0 * * \param chan Must be a local channel - * \param outchan The local channel's "chan" channel - * \param outowner The local channel's "owner" channel + * \param tech_pvt [out] channel's private tech (ref and lock added) + * \param base_chan [out] One side of the local channel (ref and lock added) + * \param base_owner [out] Other side of the local channel (ref and lock added) */ -void ast_local_lock_all(struct ast_channel *chan, struct ast_channel **outchan, - struct ast_channel **outowner); +void ast_local_lock_all(struct ast_channel *chan, void **tech_pvt, + struct ast_channel **base_chan, struct ast_channel **base_owner); /*! - * \brief Unlock the "chan" and "owner" channels on the base private structure - * as well as the base private structure itself. + * \brief Remove a reference to the given local channel's private tech, unlock the given + * local channel's private base, and remove references and unlock both sides of + * given the local channel. * - * \note This also removes references to each of the above mentioned elements and - * also the underlying private local structure. - * \note This function should be used in conjunction with ast_local_lock_all. + * \note This function should be used in conjunction with ast_local_lock_all2. * - * \since 13.8.0 + * \since 13.17.0, 14.6.0 * - * \param chan Must be a local channel + * \param tech_pvt channel's private tech (ref and lock removed) + * \param base_chan One side of the local channel (ref and lock removed) + * \param base_owner Other side of the local channel (ref and lock removed) */ -void ast_local_unlock_all(struct ast_channel *chan); +void ast_local_unlock_all(void *tech_pvt, struct ast_channel *base_chan, + struct ast_channel *base_owner); /*! * \brief Get the other local channel in the pair. diff --git a/include/asterisk/data.h b/include/asterisk/data.h deleted file mode 100644 index d6da1f7d6..000000000 --- a/include/asterisk/data.h +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2009, Eliel C. Sardanons (LU1ALY) <eliels@gmail.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 Data retrieval API. - * \author Brett Bryant <brettbryant@gmail.com> - * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com> - * \arg \ref AstDataRetrieval - */ - -#ifndef ASTERISK_DATA_H -#define ASTERISK_DATA_H - -#include "asterisk/frame.h" -#include "asterisk/format_cap.h" - -/*! - * \page AstDataRetrieval The Asterisk DATA retrieval API. - * - * This module implements an abstraction for retrieving asterisk data and - * export it. - * - * \section USAGE - * - * \subsection Provider - * - * \b Register - * - * To register a callback use: - * - * \code - * static const struct ast_data_handler callback_handler = { - * .get = callback_handler_get_function, - * }; - * - * ast_data_register("/node/path", &callback_handler); - * \endcode - * - * If you instead want to register multiple nodes at once use: - * \code - * static const struct ast_data_handler handler_struct1 = { - * .get = handler_callback_read, - * }; - * ... other handlers ... - * - * static const struct ast_data_entry list_providers[] = { - * AST_DATA_ENTRY("/path1/node1", &handler_struct1), - * AST_DATA_ENTRY("/path2/node2", &handler_struct2), - * AST_DATA_ENTRY("/path3/node3", &handler_struct3), - * }; - * - * ... - * - * ast_data_register_multiple(list_providers, ARRAY_LEN(list_providers)); - * \endcode - * - * \b Unregister - * - * To unregister a callback function already registered you can just call: - * - * \code - * ast_data_unregister(NULL); - * \endcode - * And every node registered by the current module (file) will be unregistered. - * If you want to unregister a specific node use: - * - * \code - * ast_data_unregister("/node/path"); - * \endcode - * - * \b Implementation - * - * A simple callback function implementation: - * - * \code - * #include <data.h> - * - * struct test_structure { - * int a; - * double b; - * }; - * - * DATA_EXPORT_TEST_STRUCTURE(MEMBER) \ - * MEMBER(test_structure, a, AST_DATA_INTEGER) \ - * MEMBER(test_structure, b, AST_DATA_DOUBLE) - * - * AST_DATA_STRUCTURE(test_structure, DATA_EXPORT_TEST_STRUCTURE) - * - * static int my_callback_function(struct ast_data_search *search, - * struct ast_data *root_node) - * { - * struct ast_data *internal_node; - * struct test_structure ts = { - * .a = 10, - * .b = 20 - * }; - * - * internal_node = ast_data_add_node(root_node, "test_node"); - * if (!internal_node) { - * return -1; - * } - * - * ast_data_add_structure(test_structure, internal_node, ts); - * - * if (!ast_data_search_match(search, internal_node)) { - * ast_data_remove_node(root_node, internal_node); - * } - * - * return 0; - * } - * - * \endcode - * - * \subsection Get - * - * \b Getting \b the \b tree - * - * To get the tree you need to create a query, a query is based on three parameters - * a \b path to the provider, a \b search condition and a \b filter condition. - * \code - * struct ast_data *result; - * struct ast_data_query query = { - * .path = "/asterisk/application/app_queue/queues", - * .search = "/queues/queue/name=queue1", - * .filter = "/queues/queue/name|wrapuptime|members/member/interface" - * }; - * - * result = ast_data_get(&query); - * \endcode - * - * After using it you need to release the allocated memory of the returned tree: - * \code - * ast_data_free(result); - * \endcode - * - * \b Iterate - * - * To retrieve nodes from the tree, it is possible to iterate through the returned - * nodes of the tree using: - * \code - * struct ast_data_iterator *i; - * struct ast_data *internal_node; - * - * i = ast_data_iterator_init(result_tree, "path/node_name"); - * while ((internal_node = ast_data_iterator_next(i))) { - * ... do something with node ... - * } - * ast_data_iterator_end(i); - * \endcode - * node_name is the name of the nodes to retrieve and path is the path to the internal - * nodes to retrieve (if needed). - * - * \b Retrieving - * - * After getting the node you where searching for, you will need to retrieve its value, - * to do that you may use one of the ast_data_retrieve_##type functions: - * \code - * int a = ast_data_retrieve_int(tree, "path/to/the/node"); - * double b = ast_data_retrieve_dbl(tree, "path/to/the/node"); - * unsigned int c = ast_data_retrieve_bool(tree, "path/to/the/node"); - * char *d = ast_data_retrieve_string(tree, "path/to/the/node"); - * struct sockaddr_in e = ast_data_retrieve_ipaddr(tree, "path/to/the/node"); - * unsigned int f = ast_data_retrieve_uint(tree, "path/to/the/node"); - * void *g = ast_data_retrieve_ptr(tree, "path/to/the/node"); - * \endcode - * - */ - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -/*! \brief The data type of the data node. */ -enum ast_data_type { - AST_DATA_CONTAINER, - AST_DATA_INTEGER, - AST_DATA_UNSIGNED_INTEGER, - AST_DATA_DOUBLE, - AST_DATA_BOOLEAN, - AST_DATA_STRING, - AST_DATA_CHARACTER, - AST_DATA_PASSWORD, - AST_DATA_IPADDR, - AST_DATA_TIMESTAMP, - AST_DATA_SECONDS, - AST_DATA_MILLISECONDS, - AST_DATA_POINTER -}; - -/*! \brief The Data API structures version. */ -#define AST_DATA_HANDLER_VERSION 1 -#define AST_DATA_QUERY_VERSION 1 - -/*! \brief opaque definition of an ast_data handler, a tree node. */ -struct ast_data; - -/*! \brief opaque definition of an ast_data_iterator handler. */ -struct ast_data_iterator; - -/*! \brief opaque definition of an ast_data_search structure. */ -struct ast_data_search; - -/*! \brief structure retrieved from a node, with the nodes content. */ -struct ast_data_retrieve { - /*! \brief The type of the node retrieved. */ - enum ast_data_type type; - - union { - char AST_DATA_CHARACTER; - char *AST_DATA_STRING; - char *AST_DATA_PASSWORD; - int AST_DATA_INTEGER; - unsigned int AST_DATA_TIMESTAMP; - unsigned int AST_DATA_SECONDS; - unsigned int AST_DATA_MILLISECONDS; - double AST_DATA_DOUBLE; - unsigned int AST_DATA_UNSIGNED_INTEGER; - unsigned int AST_DATA_BOOLEAN; - void *AST_DATA_POINTER; - struct in_addr AST_DATA_IPADDR; - void *AST_DATA_CONTAINER; - } value; -}; - -/*! - * \brief The get callback definition. - */ -typedef int (*ast_data_get_cb)(const struct ast_data_search *search, - struct ast_data *root); - -/*! \brief The structure of the node handler. */ -struct ast_data_handler { - /*! \brief Structure version. */ - uint32_t version; - /*! \brief Data get callback implementation. */ - ast_data_get_cb get; -}; - -/*! \brief This entries are for multiple registers. */ -struct ast_data_entry { - /*! \brief Path of the node to register. */ - const char *path; - /*! \brief Data handler structure. */ - const struct ast_data_handler *handler; -}; - -#define AST_DATA_ENTRY(__path, __handler) { .path = __path, .handler = __handler } - -/*! \brief A query to the data API is specified in this structure. */ -struct ast_data_query { - /*! \brief Data query version. */ - uint32_t version; - /*! \brief Path to the node to retrieve. */ - char *path; - /*! \brief Filter string, return the internal nodes specified here. - * Setting it to NULL will return every internal node. */ - char *filter; - /*! \brief Search condition. */ - char *search; -}; - -/*! \brief Map the members of a structure. */ -struct ast_data_mapping_structure { - /*! \brief structure member name. */ - const char *name; - /*! \brief structure member type. */ - enum ast_data_type type; - /*! \brief member getter. */ - union { - char (*AST_DATA_CHARACTER)(void *ptr); - char *(*AST_DATA_STRING)(void *ptr); - char *(*AST_DATA_PASSWORD)(void *ptr); - int (*AST_DATA_INTEGER)(void *ptr); - int (*AST_DATA_TIMESTAMP)(void *ptr); - int (*AST_DATA_SECONDS)(void *ptr); - int (*AST_DATA_MILLISECONDS)(void *ptr); - double (*AST_DATA_DOUBLE)(void *ptr); - unsigned int (*AST_DATA_UNSIGNED_INTEGER)(void *ptr); - unsigned int (*AST_DATA_BOOLEAN)(void *ptr); - void *(*AST_DATA_POINTER)(void *ptr); - struct in_addr (*AST_DATA_IPADDR)(void *ptr); - void *(*AST_DATA_CONTAINER)(void *ptr); - } get; -}; - -/* Generate the structure and the functions to access the members of a structure. */ -#define AST_DATA_STRUCTURE(__struct, __name) \ - __name(__AST_DATA_MAPPING_FUNCTION); \ - static const struct ast_data_mapping_structure __data_mapping_structure_##__struct[] = { \ - __name(__AST_DATA_MAPPING_STRUCTURE) \ - } - -/* Generate the structure to access the members and setup the pointer of the getter. */ -#define __AST_DATA_MAPPING_STRUCTURE(__structure, __member, __type) \ - { .name = #__member, .get.__type = data_mapping_structure_get_##__structure##__member, \ - .type = __type }, - -/* based on the data type, specifify the type of return value for the getter function. */ -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_PASSWORD(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_PASSWORD, char *) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_STRING(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_STRING, char *) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_CHARACTER(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_CHARACTER, char) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_INTEGER(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_INTEGER, int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_TIMESTAMP(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_INTEGER, int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_SECONDS(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_INTEGER, int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_MILLISECONDS(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_INTEGER, int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_UNSIGNED_INTEGER(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_UNSIGNED_INTEGER, unsigned int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_BOOLEAN(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_BOOLEAN, unsigned int) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_POINTER(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_POINTER, void *) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_IPADDR(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_IPADDR, struct in_addr) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_DOUBLE(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_DBL, double) -#define __AST_DATA_MAPPING_FUNCTION_AST_DATA_CONTAINER(__structure, __member) \ - __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, AST_DATA_CONTAINER, void *) - -#define __AST_DATA_MAPPING_FUNCTION(__structure, __member, __type) \ - __AST_DATA_MAPPING_FUNCTION_##__type(__structure, __member) - -/* Create the function to retrieve a member of the structure. */ -#define __AST_DATA_MAPPING_FUNCTION_TYPE(__structure, __member, __type, __real_type) \ - static __real_type data_mapping_structure_get_##__structure##__member(void *ptr) { \ - struct __structure *struct_##__member = (struct __structure *) ptr; \ - return (__real_type) struct_##__member->__member; \ - } - -/*! - * \brief Register a data provider. - * \param[in] path The path of the node to register. - * \param[in] handler The structure defining this node handler. - * \param[in] registrar Who is registering this node. - * \param[in] mod The module registering this handler. - * \see ast_data_unregister - * \retval <0 on error. - * \retval 0 on success. - * \see __ast_data_unregister, __ast_data_register_multiple - */ -int __ast_data_register(const char *path, const struct ast_data_handler *handler, - const char *registrar, struct ast_module *mod); -#define ast_data_register(path, handler) __ast_data_register(path, handler, __FILE__, AST_MODULE_SELF) -#define ast_data_register_core(path, handler) __ast_data_register(path, handler, __FILE__, NULL) - -/*! - * \brief Register multiple data providers at once. - * \param[in] data_entries An array of data_entries structures. - * \param[in] entries The number of entries in the data_entries array. - * \param[in] registrar Who is registering this nodes. - * \param[in] mod The module registering this handlers. - * \retval <0 on error (none of the nodes are being registered on error). - * \retval 0 on success. - * \see __ast_data_register, __ast_data_unregister - */ -int __ast_data_register_multiple(const struct ast_data_entry *data_entries, - size_t entries, const char *registrar, struct ast_module *mod); -#define ast_data_register_multiple(data_entries, entries) \ - __ast_data_register_multiple(data_entries, entries, __FILE__, AST_MODULE_SELF) -#define ast_data_register_multiple_core(data_entries, entries) \ - __ast_data_register_multiple(data_entries, entries, __FILE__, NULL) - -/*! - * \brief Unregister a data provider. - * \param[in] path Which node to unregister, if path is NULL unregister every node - * registered by the passed 'registrar'. - * \param[in] registrar Who is trying to unregister this node, only the owner (the - * one who registered the node) will be able to unregister it. - * \see ast_data_register - * \retval <0 on error. - * \retval 0 on success. - * \see __ast_data_register, __ast_data_register_multiple - */ -int __ast_data_unregister(const char *path, const char *registrar); -#define ast_data_unregister(path) __ast_data_unregister(path, __FILE__) - -/*! - * \brief Check the current generated node to know if it matches the search - * condition. - * \param[in] search The search condition. - * \param[in] data The AstData node generated. - * \return 1 If the "data" node matches the search condition. - * \return 0 If the "data" node does not matches the search condition. - * \see ast_data_remove_node - */ -int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data); - -/*! - * \brief Based on a search tree, evaluate every member of a structure against it. - * \param[in] search The search tree. - * \param[in] mapping The structure mapping. - * \param[in] mapping_len The lenght of the structure mapping. - * \param[in] structure The structure pointer. - * \param[in] structure_name The name of the structure to compare. - * \retval 0 If the structure matches. - * \retval 1 If the structure doesn't match. - */ -int __ast_data_search_cmp_structure(const struct ast_data_search *search, - const struct ast_data_mapping_structure *mapping, size_t mapping_len, - void *structure, const char *structure_name); -#define ast_data_search_cmp_structure(search, structure_name, structure, structure_name_cmp) \ - __ast_data_search_cmp_structure(search, __data_mapping_structure_##structure_name, \ - ARRAY_LEN(__data_mapping_structure_##structure_name), structure, structure_name_cmp) - -/*! - * \brief Retrieve a subtree from the asterisk data API. - * \param[in] query The query structure specifying what nodes to retrieve. - * \retval NULL on error. - * \retval non-NULL The dynamically allocated requested sub-tree (it needs to be - * released using ast_data_free. - * \see ast_data_free, ast_data_get_xml - */ -struct ast_data *ast_data_get(const struct ast_data_query *query); - -#ifdef HAVE_LIBXML2 -/*! - * \brief Retrieve a subtree from the asterisk data API in XML format.. - * \param[in] query The query structure specifying what nodes to retrieve. - * \retval NULL on error. - * \retval non-NULL The dynamically allocated requested sub-tree (it needs to be - * released using ast_data_free. - * \see ast_data_free, ast_data_get - */ -struct ast_xml_doc *ast_data_get_xml(const struct ast_data_query *query); -#endif - -/*! - * \brief Release the allocated memory of a tree. - * \param[in] root The sub-tree pointer returned by a call to ast_data_get. - * \see ast_data_get - */ -void ast_data_free(struct ast_data *root); - -/*! - * \brief Get a node type. - * \param[in] res A pointer to the ast_data result set. - * \param[in] path A path to the node to get the type. - * \return The type of the requested node type. - */ -enum ast_data_type ast_data_retrieve_type(struct ast_data *res, const char *path); - -/*! - * \brief Get the node name. - * \param[in] node The node pointer. - * \returns The node name. - */ -char *ast_data_retrieve_name(struct ast_data *node); - -/*! - * \brief Add a container child. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_node(struct ast_data *root, const char *childname); - -/*! - * \brief Add an integer node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] value The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_int(struct ast_data *root, const char *childname, - int value); - -/*! - * \brief Add a char node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] value The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_char(struct ast_data *root, const char *childname, - char value); - -/*! - * \brief Add an unsigned integer node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] value The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_uint(struct ast_data *root, const char *childname, - unsigned int value); - -/*! - * \brief Add a floating point node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] dbl The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_dbl(struct ast_data *root, const char *childname, - double dbl); -/*! - * \brief Add a ipv4 address type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] addr The ipv4 address value. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_ipaddr(struct ast_data *root, const char *childname, - struct in_addr addr); - -/*! - * \brief Add a ptr node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] ptr The pointer value to add. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_ptr(struct ast_data *root, const char *childname, - void *ptr); - -/*! - * \brief Add a password node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] string The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_password(struct ast_data *root, const char *childname, - const char *string); - -/*! - * \brief Add a timestamp node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] timestamp The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_timestamp(struct ast_data *root, const char *childname, - unsigned int timestamp); - -/*! - * \brief Add a seconds node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] seconds The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_seconds(struct ast_data *root, const char *childname, - unsigned int seconds); - -/*! - * \brief Add a milliseconds node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] milliseconds The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_milliseconds(struct ast_data *root, const char *childname, - unsigned int milliseconds); - -/*! - * \brief Add a string node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] string The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_str(struct ast_data *root, const char *childname, - const char *string); - -/*! - * \brief Add a boolean node type. - * \param[in] root The root of the ast_data to insert into. - * \param[in] childname The name of the child element to be added. - * \param[in] boolean The value for the new node. - * \retval NULL on error (memory exhaustion only). - * \retval non-NULL a newly allocated node. - */ -struct ast_data *ast_data_add_bool(struct ast_data *root, const char *childname, - unsigned int boolean); - -/*! - * \brief Add a complete structure to a node. - * \param[in] root Where to add the structure. - * \param[in] mapping The structure mapping array. - * \param[in] mapping_len The lenght of the mapping array. - * \param[in] structure The structure pointer. - * \retval 0 on success. - * \retval 1 on error. - */ -int __ast_data_add_structure(struct ast_data *root, - const struct ast_data_mapping_structure *mapping, - size_t mapping_len, void *structure); -#define ast_data_add_structure(structure_name, root, structure) \ - __ast_data_add_structure(root, __data_mapping_structure_##structure_name, \ - ARRAY_LEN(__data_mapping_structure_##structure_name), structure) - -/*! - * \brief Remove a node that was added using ast_data_add_ - * \param[in] root The root node of the node to be removed. - * \param[in] child The node pointer to remove. - */ -void ast_data_remove_node(struct ast_data *root, struct ast_data *child); - -/*! - * \brief Initialize an iterator. - * \param[in] tree The returned tree by a call to ast_data_get. - * \param[in] elements Which elements to iterate through. - * \retval NULL on error. - * \retval non-NULL A dinamically allocated iterator structure. - */ -struct ast_data_iterator *ast_data_iterator_init(struct ast_data *tree, - const char *elements); - -/*! - * \brief Release (stop using) an iterator. - * \param[in] iterator The iterator created by ast_data_iterator_start. - * \see ast_data_iterator_start - */ -void ast_data_iterator_end(struct ast_data_iterator *iterator); - -/*! - * \brief Get the next node of the tree. - * \param[in] iterator The iterator structure returned by ast_data_iterator_start. - * \retval NULL when no more nodes to return. - * \retval non-NULL A node of the ast_data tree. - * \see ast_data_iterator_start, ast_data_iterator_stop - */ -struct ast_data *ast_data_iterator_next(struct ast_data_iterator *iterator); - -/*! - * \brief Retrieve a value from a node in the tree. - * \param[in] tree The structure returned by a call to ast_data_get. - * \param[in] path The path to the node. - * \param[out] content The node content. - * \retval 0 on success. - * \retval <0 on error. - */ -int ast_data_retrieve(struct ast_data *tree, const char *path, struct ast_data_retrieve *content); - -/*! - * \brief Retrieve the integer value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline int ast_data_retrieve_int(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_INTEGER; -} - -/*! - * \brief Retrieve the character value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline char ast_data_retrieve_char(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_CHARACTER; -} - -/*! - * \brief Retrieve the boolean value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline unsigned int ast_data_retrieve_bool(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_BOOLEAN; -} - -/*! - * \brief Retrieve the unsigned integer value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline unsigned int ast_data_retrieve_uint(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_UNSIGNED_INTEGER; -} - -/*! - * \brief Retrieve the password value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline const char *ast_data_retrieve_password(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_PASSWORD; -} - -/*! - * \brief Retrieve the string value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline const char *ast_data_retrieve_string(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_STRING; -} - -/*! - * \brief Retrieve the ptr value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline void *ast_data_retrieve_ptr(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_POINTER; -} - -/*! - * \brief Retrieve the double value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline double ast_data_retrieve_dbl(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_DOUBLE; -} - -/*! - * \brief Retrieve the ipv4 address value of a node. - * \param[in] tree The tree from where to get the value. - * \param[in] path The node name or path. - * \returns The value of the node. - */ -static inline struct in_addr ast_data_retrieve_ipaddr(struct ast_data *tree, const char *path) -{ - struct ast_data_retrieve ret; - - ast_data_retrieve(tree, path, &ret); - - return ret.value.AST_DATA_IPADDR; -} - -/*! - * \brief Add the codec in the root node based on the format parameter. - * \param[in] root The astdata root node where to add the codec node. - * \param[in] node_name The name of the node where we are going to add the codec. - * \param[in] format The codec allowed. - * \return < 0 on error. - * \return 0 on success. - */ -int ast_data_add_codec(struct ast_data *root, const char *node_name, struct ast_format *format); - -/*! - * \brief Add the list of codecs in the root node based on the capability parameter. - * \param[in] root The astdata root node where to add the codecs node. - * \param[in] node_name The name of the node where we are going to add the list of - * codecs. - * \param[in] capability The codecs allowed. - * \return < 0 on error. - * \return 0 on success. - */ -int ast_data_add_codecs(struct ast_data *root, const char *node_name, struct ast_format_cap *capability); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* ASTERISK_DATA_H */ diff --git a/include/asterisk/features_config.h b/include/asterisk/features_config.h index baaff183b..1bce50bba 100644 --- a/include/asterisk/features_config.h +++ b/include/asterisk/features_config.h @@ -117,6 +117,21 @@ struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_ch char *ast_get_chan_features_xferfailsound(struct ast_channel *chan); /*! + * \brief Get the transfer configuration option atxferabort + * + * \note The channel should be locked before calling this function. + * \note The returned value has to be freed. + * + * If no channel is provided, then option is pulled from the global + * transfer configuration. + * + * \param chan The channel to get configuration options for + * \retval NULL Failed to get configuration + * \retval non-NULL The atxferabort + */ +char *ast_get_chan_features_atxferabort(struct ast_channel *chan); + +/*! * \brief Configuration relating to call pickup */ struct ast_features_pickup_config { diff --git a/include/asterisk/format.h b/include/asterisk/format.h index b01592d16..946c03d98 100644 --- a/include/asterisk/format.h +++ b/include/asterisk/format.h @@ -32,7 +32,7 @@ struct ast_format; /*! \brief Format comparison results */ enum ast_format_cmp_res { - /*! Both formats are equivalent to eachother */ + /*! Both formats are equivalent to each other */ AST_FORMAT_CMP_EQUAL = 0, /*! Both formats are completely different and not the same in any way */ AST_FORMAT_CMP_NOT_EQUAL, @@ -110,7 +110,7 @@ struct ast_format_interface { struct ast_format *(* const format_parse_sdp_fmtp)(const struct ast_format *format, const char *attributes); /*! - * \brief Generate SDP attribute information from an ast_format_attr structure. + * \brief Generate SDP attribute information from an ast_format structure. * * \param format The format containing attributes * \param payload The payload number to place into the fmtp line @@ -356,6 +356,17 @@ const char *ast_format_get_codec_name(const struct ast_format *format); int ast_format_can_be_smoothed(const struct ast_format *format); /*! + * \since 13.17.0 + * + * \brief Get smoother flags for this format + * + * \param format The media format + * + * \return smoother flags for the provided format + */ +int ast_format_get_smoother_flags(const struct ast_format *format); + +/*! * \brief Get the media type of a format * * \param format The media format diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h index 6099c59ea..067546310 100644 --- a/include/asterisk/format_cache.h +++ b/include/asterisk/format_cache.h @@ -184,6 +184,11 @@ extern struct ast_format *ast_format_mp4; extern struct ast_format *ast_format_vp8; /*! + * \brief Built-in cached vp9 format. + */ +extern struct ast_format *ast_format_vp9; + +/*! * \brief Built-in cached jpeg format. */ extern struct ast_format *ast_format_jpeg; @@ -224,6 +229,11 @@ extern struct ast_format *ast_format_t140; extern struct ast_format *ast_format_t140_red; /*! + * \brief Built-in cached T.38 format. + */ +extern struct ast_format *ast_format_t38; + +/*! * \brief Built-in "null" format. */ extern struct ast_format *ast_format_none; diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 90f8aa086..eb6a6479a 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -137,6 +137,8 @@ enum { AST_FRFLAG_HAS_TIMING_INFO = (1 << 0), /*! This frame has been requeued */ AST_FRFLAG_REQUEUED = (1 << 1), + /*! This frame contains a valid sequence number */ + AST_FRFLAG_HAS_SEQUENCE_NUMBER = (1 << 2), }; struct ast_frame_subclass { @@ -181,6 +183,8 @@ struct ast_frame { long len; /*! Sequence number */ int seqno; + /*! Stream number the frame originated from */ + int stream_num; }; /*! @@ -295,6 +299,9 @@ enum ast_control_frame_type { AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */ AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */ AST_CONTROL_MASQUERADE_NOTIFY = 34, /*!< A masquerade is about to begin/end. (Never sent as a frame but directly with ast_indicate_data().) */ + AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE = 35, /*!< Channel indication that a stream topology change has been requested */ + AST_CONTROL_STREAM_TOPOLOGY_CHANGED = 36, /*!< Channel indication that a stream topology change has occurred */ + AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED = 37, /*!< Channel indication that one of the source streams has changed its source */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING diff --git a/include/asterisk/indications.h b/include/asterisk/indications.h index b02be1fdf..309954b05 100644 --- a/include/asterisk/indications.h +++ b/include/asterisk/indications.h @@ -28,7 +28,6 @@ #include "asterisk/astobj2.h" #include "asterisk/utils.h" -#include "asterisk/data.h" /*! * \brief Description of a tone @@ -242,12 +241,4 @@ static inline struct ast_tone_zone_sound *ast_tone_zone_sound_ref(struct ast_ton return ts; } -/*! - * \brief Add a tone_zone structure to the data tree specified. - * - * \retval <0 on error. - * \retval 0 on success. - */ -int ast_tone_zone_data_add_structure(struct ast_data *tree, struct ast_tone_zone *zone); - #endif /* _ASTERISK_INDICATIONS_H */ diff --git a/include/asterisk/io.h b/include/asterisk/io.h index 6ee8450bd..f103cf556 100644 --- a/include/asterisk/io.h +++ b/include/asterisk/io.h @@ -24,6 +24,7 @@ #define _ASTERISK_IO_H #include "asterisk/poll-compat.h" +#include "asterisk/netsock2.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -148,6 +149,29 @@ int ast_get_termcols(int fd); */ int ast_sd_notify(const char *state); +/*! + * \brief Find a listening file descriptor provided by socket activation. + * \param type SOCK_STREAM or SOCK_DGRAM + * \param addr The socket address of the bound listener. + * \retval <0 No match. + * \retval >0 File Descriptor matching sockaddr. + * + * \note This function returns -1 if systemd's development headers were not + * detected on the system. + */ +int ast_sd_get_fd(int type, const struct ast_sockaddr *addr); + +/*! + * \brief Find a listening AF_LOCAL file descriptor provided by socket activation. + * \param type SOCK_STREAM or SOCK_DGRAM + * \param path The path of the listener. + * \retval <0 No match. + * \retval >0 File Descriptor matching path. + * + * \note This function returns -1 if systemd's development headers were not + * detected on the system. + */ +int ast_sd_get_fd_un(int type, const char *path); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index 5b6817f6b..58c9a8383 100644 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -240,13 +240,8 @@ enum ast_lock_type { * lock info struct. The lock is marked as pending as the thread is waiting * on the lock. ast_mark_lock_acquired() will mark it as held by this thread. */ -#ifdef HAVE_BKTR void ast_store_lock_info(enum ast_lock_type type, const char *filename, int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt); -#else -void ast_store_lock_info(enum ast_lock_type type, const char *filename, - int line_num, const char *func, const char *lock_name, void *lock_addr); -#endif /* HAVE_BKTR */ /*! * \brief Mark the last lock as acquired @@ -264,11 +259,7 @@ void ast_mark_lock_failed(void *lock_addr); * this gets called by ast_mutex_unlock so that information on the lock can * be removed from the current thread's lock info struct. */ -#ifdef HAVE_BKTR void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt); -#else -void ast_remove_lock_info(void *lock_addr); -#endif /* HAVE_BKTR */ void ast_suspend_lock_info(void *lock_addr); void ast_restore_lock_info(void *lock_addr); diff --git a/include/asterisk/logger.h b/include/asterisk/logger.h index 9f9f671c0..8b1e5fe01 100644 --- a/include/asterisk/logger.h +++ b/include/asterisk/logger.h @@ -429,7 +429,9 @@ void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid); #define DEBUG_ATLEAST(level) \ (option_debug >= (level) \ - || (ast_opt_dbg_module && (int)ast_debug_get_by_module(AST_MODULE) >= (level))) + || (ast_opt_dbg_module \ + && ((int)ast_debug_get_by_module(AST_MODULE) >= (level) \ + || (int)ast_debug_get_by_module(__FILE__) >= (level)))) /*! * \brief Log a DEBUG message @@ -500,6 +502,29 @@ int ast_verb_console_get(void); */ void ast_verb_console_set(int verb_level); +/*! + * \brief Test if logger is initialized + * + * \retval true if the logger is initialized + */ +int ast_is_logger_initialized(void); + +/*! + * \brief Set the maximum number of messages allowed in the processing queue + * + * \param queue_limit + * + * \return Nothing + */ +void ast_logger_set_queue_limit(int queue_limit); + +/*! + * \brief Get the maximum number of messages allowed in the processing queue + * + * \return Queue limit + */ +int ast_logger_get_queue_limit(void); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index 60c51de85..67dcead47 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -54,7 +54,7 @@ - \ref manager.c Main manager code file */ -#define AMI_VERSION "3.1.0" +#define AMI_VERSION "4.0.0" #define DEFAULT_MANAGER_PORT 5038 /* Default port for Asterisk management via TCP */ #define DEFAULT_MANAGER_TLS_PORT 5039 /* Default port for Asterisk management via TCP */ diff --git a/include/asterisk/module.h b/include/asterisk/module.h index a80c7f843..69ebb2640 100644 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -94,6 +94,20 @@ enum ast_module_support_level { AST_MODULE_SUPPORT_DEPRECATED, }; +/*! Used to specify which modules should be returned by ast_module_helper. */ +enum ast_module_helper_type { + /*! Modules that are loaded by dlopen. */ + AST_MODULE_HELPER_LOADED = 0, + /*! Running modules that include a reload callback. */ + AST_MODULE_HELPER_RELOAD = 1, + /*! Modules that can be loaded or started. */ + AST_MODULE_HELPER_LOAD, + /*! Modules that can be unloaded. */ + AST_MODULE_HELPER_UNLOAD, + /*! Running modules */ + AST_MODULE_HELPER_RUNNING, +}; + /*! * \brief Load a module. * \param resource_name The name of the module to load. @@ -237,14 +251,12 @@ int ast_loader_unregister(int (*updater)(void)); * \param state The possible match to return. * \param rpos The position we should be matching. This should be the same as * pos. - * \param needsreload This should be 1 if we need to reload this module and 0 - * otherwise. This function will only return modules that are reloadble - * if this is 1. + * \param type The type of action that will be performed by CLI. * * \retval A possible completion of the partial match. * \retval NULL if no matches were found. */ -char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload); +char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type); /* Opaque type for module handles generated by the loader */ @@ -303,8 +315,6 @@ struct ast_module_info { enum ast_module_load_result (*load)(void); /*!< register stuff etc. Optional. */ int (*reload)(void); /*!< config etc. Optional. */ int (*unload)(void); /*!< unload. called with the module locked */ - int (*backup_globals)(void); /*!< for embedded modules, backup global data */ - void (*restore_globals)(void); /*!< for embedded modules, restore global data */ const char *name; /*!< name of the module for loader reference and CLI commands */ const char *description; /*!< user friendly description of the module. */ @@ -379,8 +389,6 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons load_func, \ reload_func, \ unload_func, \ - NULL, \ - NULL, \ AST_MODULE, \ desc, \ keystr, \ @@ -440,70 +448,9 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons static const __attribute__((unused)) struct ast_module_info *ast_module_info; #endif -#if !defined(EMBEDDED_MODULE) -#define __MODULE_INFO_SECTION -#define __MODULE_INFO_GLOBALS -#else -/* - * For embedded modules we need additional information to backup and - * restore the global variables in the module itself, so we can unload - * reload the module. - * EMBEDDED_MODULE is defined as the module name, so the calls to make_var() - * below will actually define different symbols for each module. - */ -#define __MODULE_INFO_SECTION __attribute__((section(".embed_module"))) -#define __MODULE_INFO_GLOBALS .backup_globals = __backup_globals, .restore_globals = __restore_globals, - -#define make_var_sub(mod, type) __ ## mod ## _ ## type -#define make_var(mod, type) make_var_sub(mod, type) - -extern void make_var(EMBEDDED_MODULE, bss_start); -extern void make_var(EMBEDDED_MODULE, bss_end); -extern void make_var(EMBEDDED_MODULE, data_start); -extern void make_var(EMBEDDED_MODULE, data_end); - -static void * __attribute__((section(".embed_module"))) __global_backup; - -static int __backup_globals(void) -{ - size_t data_size = & make_var(EMBEDDED_MODULE, data_end) - & make_var(EMBEDDED_MODULE, data_start); - - if (__global_backup) - return 0; - - if (!data_size) - return 0; - - if (!(__global_backup = ast_malloc(data_size))) - return -1; - - memcpy(__global_backup, & make_var(EMBEDDED_MODULE, data_start), data_size); - - return 0; -} - -static void __restore_globals(void) -{ - size_t data_size = & make_var(EMBEDDED_MODULE, data_end) - & make_var(EMBEDDED_MODULE, data_start); - size_t bss_size = & make_var(EMBEDDED_MODULE, bss_end) - & make_var(EMBEDDED_MODULE, bss_start); - - if (bss_size) - memset(& make_var(EMBEDDED_MODULE, bss_start), 0, bss_size); - - if (!data_size || !__global_backup) - return; - - memcpy(& make_var(EMBEDDED_MODULE, data_start), __global_backup, data_size); -} -#undef make_var -#undef make_var_sub -#endif /* EMBEDDED_MODULE */ - #define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...) \ static struct ast_module_info \ - __MODULE_INFO_SECTION \ __mod_info = { \ - __MODULE_INFO_GLOBALS \ .name = AST_MODULE, \ .flags = flags_to_set, \ .description = desc, \ diff --git a/include/asterisk/netsock2.h b/include/asterisk/netsock2.h index 3ede99087..6c0dd633b 100644 --- a/include/asterisk/netsock2.h +++ b/include/asterisk/netsock2.h @@ -129,6 +129,22 @@ static inline void ast_sockaddr_setnull(struct ast_sockaddr *addr) } /*! + * \brief + * Copies the data from a sockaddr to an ast_sockaddr + * + * \param dst The destination ast_sockaddr + * \param src The source sockaddr + * \param len Length of the value stored in sockaddr + * \retval void + */ +static inline void ast_sockaddr_copy_sockaddr(struct ast_sockaddr *dst, + struct sockaddr *src, socklen_t len) +{ + memcpy(dst, src, len); + dst->len = len; +} + +/*! * \since 1.8 * * \brief diff --git a/include/asterisk/network.h b/include/asterisk/network.h index 3371e5895..5216f4c61 100644 --- a/include/asterisk/network.h +++ b/include/asterisk/network.h @@ -86,6 +86,11 @@ const char *ast_inet_ntoa(struct in_addr ia); #endif #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__ +#ifdef getprotobyname +#undef getprotobyname +#endif +#define getprotobyname __getprotobyname_is_not_threadsafe__do_not_use__ + /*! \brief Compares the source address and port of two sockaddr_in */ static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2) { diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 05ad6c560..878748d16 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -66,6 +66,8 @@ enum ast_option_flags { AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13), /*! Display timestamp in CLI verbose output */ AST_OPT_FLAG_TIMESTAMP = (1 << 14), + /*! Cache media frames for performance */ + AST_OPT_FLAG_CACHE_MEDIA_FRAMES = (1 << 15), /*! Reconnect */ AST_OPT_FLAG_RECONNECT = (1 << 16), /*! Transmit Silence during Record() and DTMF Generation */ @@ -99,7 +101,7 @@ enum ast_option_flags { }; /*! These are the options that set by default when Asterisk starts */ -#define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN +#define AST_DEFAULT_OPTIONS (AST_OPT_FLAG_TRANSCODE_VIA_SLIN | AST_OPT_FLAG_CACHE_MEDIA_FRAMES) #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK) @@ -116,6 +118,7 @@ enum ast_option_flags { #define ast_opt_stdexten_macro ast_test_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO) #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE) #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES) +#define ast_opt_cache_media_frames ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_MEDIA_FRAMES) #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP) #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT) #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) @@ -196,6 +199,7 @@ extern int dahdi_chan_name_len; extern int ast_language_is_prefix; +extern int ast_option_rtpusedynamic; extern unsigned int ast_option_rtpptdynamic; #if defined(__cplusplus) || defined(c_plusplus) diff --git a/include/asterisk/res_hep.h b/include/asterisk/res_hep.h index cfd213ad7..dba86e88b 100644 --- a/include/asterisk/res_hep.h +++ b/include/asterisk/res_hep.h @@ -72,6 +72,8 @@ struct hepv3_capture_info { size_t len; /*! If non-zero, the payload accompanying this capture info will be compressed */ unsigned int zipped:1; + /*! The IPPROTO_* protocol where we captured the packet */ + int protocol_id; }; /*! diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 09ace0775..e71eb98d7 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -98,22 +98,41 @@ struct ast_sip_transport_state { */ pj_ssl_cipher ciphers[SIP_TLS_MAX_CIPHERS]; /*! - * Optional local network information, used for NAT purposes + * Optional local network information, used for NAT purposes. + * "deny" (set) means that it's in the local network. Use the + * ast_sip_transport_is_nonlocal and ast_sip_transport_is_local + * macro's. * \since 13.8.0 */ struct ast_ha *localnet; /*! - * DNS manager for refreshing the external address + * DNS manager for refreshing the external signaling address * \since 13.8.0 */ - struct ast_dnsmgr_entry *external_address_refresher; + struct ast_dnsmgr_entry *external_signaling_address_refresher; /*! - * Optional external address information + * Optional external signaling address information * \since 13.8.0 */ - struct ast_sockaddr external_address; + struct ast_sockaddr external_signaling_address; + /*! + * DNS manager for refreshing the external media address + * \since 13.18.0 + */ + struct ast_dnsmgr_entry *external_media_address_refresher; + /*! + * Optional external signaling address information + * \since 13.18.0 + */ + struct ast_sockaddr external_media_address; }; +#define ast_sip_transport_is_nonlocal(transport_state, addr) \ + (!transport_state->localnet || ast_apply_ha(transport_state->localnet, addr) == AST_SENSE_ALLOW) + +#define ast_sip_transport_is_local(transport_state, addr) \ + (transport_state->localnet && ast_apply_ha(transport_state->localnet, addr) != AST_SENSE_ALLOW) + /* * \brief Transport to bind to */ @@ -194,6 +213,8 @@ struct ast_sip_transport { int write_timeout; /*! Allow reload */ int allow_reload; + /*! Automatically send requests out the same transport requests have come in on */ + int symmetric_transport; }; #define SIP_SORCERY_DOMAIN_ALIAS_TYPE "domain_alias" @@ -258,6 +279,8 @@ struct ast_sip_contact { AST_STRING_FIELD_EXTENDED(call_id); /*! The name of the endpoint that added the contact */ AST_STRING_FIELD_EXTENDED(endpoint_name); + /*! If true delete the contact on Asterisk restart/boot */ + int prune_on_boot; }; #define CONTACT_STATUS "contact_status" @@ -363,6 +386,8 @@ enum ast_sip_dtmf_mode { AST_SIP_DTMF_INFO, /*! Use SIP 4733 if supported by the other side or INBAND if not */ AST_SIP_DTMF_AUTO, + /*! Use SIP 4733 if supported by the other side or INFO DTMF (blech) if not */ + AST_SIP_DTMF_AUTO_INFO, }; /*! @@ -412,6 +437,8 @@ enum ast_sip_endpoint_identifier_type { AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME = (1 << 0), /*! Identify based on user name in Auth header first, then From header */ AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME = (1 << 1), + /*! Identify based on source IP address */ + AST_SIP_ENDPOINT_IDENTIFY_BY_IP = (1 << 2), }; AST_VECTOR(ast_sip_identify_by_vector, enum ast_sip_endpoint_identifier_type); @@ -664,6 +691,8 @@ struct ast_sip_endpoint_media_configuration { struct ast_sip_t38_configuration t38; /*! Configured codecs */ struct ast_format_cap *codecs; + /*! Capabilities in topology form */ + struct ast_stream_topology *topology; /*! DSCP TOS bits for audio streams */ unsigned int tos_audio; /*! Priority for audio streams */ @@ -676,6 +705,16 @@ struct ast_sip_endpoint_media_configuration { unsigned int g726_non_standard; /*! Bind the RTP instance to the media_address */ unsigned int bind_rtp_to_media_address; + /*! Use RTCP-MUX */ + unsigned int rtcp_mux; + /*! Maximum number of audio streams to offer/accept */ + unsigned int max_audio_streams; + /*! Maximum number of video streams to offer/accept */ + unsigned int max_video_streams; + /*! Use BUNDLE */ + unsigned int bundle; + /*! Enable webrtc settings and defaults */ + unsigned int webrtc; }; /*! @@ -761,8 +800,20 @@ struct ast_sip_endpoint { unsigned int preferred_codec_only; /*! Do we allow an asymmetric RTP codec? */ unsigned int asymmetric_rtp_codec; + /*! Do we allow overlap dialling? */ + unsigned int allow_overlap; + /*! Whether to notifies all the progress details on blind transfer */ + unsigned int refer_blind_progress; + /*! Whether to notifies dialog-info 'early' on INUSE && RINGING state */ + unsigned int notify_early_inuse_ringing; + /*! If set, we'll push incoming MWI NOTIFYs to stasis using this mailbox */ + AST_STRING_FIELD_EXTENDED(incoming_mwi_mailbox); }; +/*! URI parameter for symmetric transport */ +#define AST_SIP_X_AST_TXP "x-ast-txp" +#define AST_SIP_X_AST_TXP_LEN 9 + /*! * \brief Initialize an auth vector with the configured values. * @@ -853,6 +904,17 @@ struct ast_sip_endpoint_identifier { }; /*! + * \brief Contact retrieval filtering flags + */ +enum ast_sip_contact_filter { + /*! \brief Default filter flags */ + AST_SIP_CONTACT_FILTER_DEFAULT = 0, + + /*! \brief Return only reachable or unknown contacts */ + AST_SIP_CONTACT_FILTER_REACHABLE = (1 << 0), +}; + +/*! * \brief Register a SIP service in Asterisk. * * This is more-or-less a wrapper around pjsip_endpt_register_module(). @@ -865,7 +927,9 @@ struct ast_sip_endpoint_identifier { * \retval 0 Success * \retval -1 Failure */ -int ast_sip_register_service(pjsip_module *module); +#define ast_sip_register_service(module) \ + __ast_sip_register_service(module, __FILE__, __LINE__, __PRETTY_FUNCTION__) +int __ast_sip_register_service(pjsip_module *module, const char *file, int line, const char *func); /*! * This is the opposite of ast_sip_register_service(). Unregistering a @@ -874,7 +938,9 @@ int ast_sip_register_service(pjsip_module *module); * * \param module The PJSIP module to unregister */ -void ast_sip_unregister_service(pjsip_module *module); +#define ast_sip_unregister_service(module) \ + __ast_sip_unregister_service(module, __FILE__, __LINE__, __PRETTY_FUNCTION__) +void __ast_sip_unregister_service(pjsip_module *module, const char *file, int line, const char *func); /*! * \brief Register a SIP authenticator @@ -1038,6 +1104,18 @@ struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name); struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor); /*! + * \brief Retrieve the first bound contact for an AOR and filter based on flags + * \since 13.16.0 + * + * \param aor Pointer to the AOR + * \param flags Filtering flags + * \retval NULL if no contacts available + * \retval non-NULL if contacts available + */ +struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor, + unsigned int flags); + +/*! * \brief Retrieve all contacts currently available for an AOR * * \param aor Pointer to the AOR @@ -1052,6 +1130,23 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor); /*! + * \brief Retrieve all contacts currently available for an AOR and filter based on flags + * \since 13.16.0 + * + * \param aor Pointer to the AOR + * \param flags Filtering flags + * + * \retval NULL if no contacts available + * \retval non-NULL if contacts available + * + * \warning + * Since this function prunes expired contacts before returning, it holds a named write + * lock on the aor. If you already hold the lock, call ast_sip_location_retrieve_aor_contacts_nolock instead. + */ +struct ao2_container *ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor, + unsigned int flags); + +/*! * \brief Retrieve all contacts currently available for an AOR without locking the AOR * \since 13.9.0 * @@ -1066,6 +1161,22 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_si struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor); /*! + * \brief Retrieve all contacts currently available for an AOR without locking the AOR and filter based on flags + * \since 13.16.0 + * + * \param aor Pointer to the AOR + * \param flags Filtering flags + * + * \retval NULL if no contacts available + * \retval non-NULL if contacts available + * + * \warning + * This function should only be called if you already hold a named write lock on the aor. + */ +struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor, + unsigned int flags); + +/*! * \brief Retrieve the first bound contact from a list of AORs * * \param aor_list A comma-separated list of AOR names @@ -1094,6 +1205,18 @@ struct ao2_container *ast_sip_location_retrieve_contacts_from_aor_list(const cha struct ast_sip_contact **contact); /*! + * \brief Retrieve the first bound contact AND the AOR chosen from a list of AORs and filter based on flags + * \since 13.16.0 + * + * \param aor_list A comma-separated list of AOR names + * \param flags Filtering flags + * \param aor The chosen AOR + * \param contact The chosen contact + */ +void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags, + struct ast_sip_aor **aor, struct ast_sip_contact **contact); + +/*! * \brief Retrieve a named contact * * \param contact_name Name of the contact @@ -1111,6 +1234,9 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na * \param expiration_time Optional expiration time of the contact * \param path_info Path information * \param user_agent User-Agent header from REGISTER request + * \param via_addr + * \param via_port + * \param call_id * \param endpoint The endpoint that resulted in the contact being added * * \retval -1 failure @@ -1134,6 +1260,9 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, * \param expiration_time Optional expiration time of the contact * \param path_info Path information * \param user_agent User-Agent header from REGISTER request + * \param via_addr + * \param via_port + * \param call_id * \param endpoint The endpoint that resulted in the contact being added * * \retval -1 failure @@ -1148,6 +1277,31 @@ int ast_sip_location_add_contact_nolock(struct ast_sip_aor *aor, const char *uri struct ast_sip_endpoint *endpoint); /*! + * \brief Create a new contact for an AOR without locking the AOR + * \since 13.18.0 + * + * \param aor Pointer to the AOR + * \param uri Full contact URI + * \param expiration_time Optional expiration time of the contact + * \param path_info Path information + * \param user_agent User-Agent header from REGISTER request + * \param via_addr + * \param via_port + * \param call_id + * \param prune_on_boot Non-zero if the contact cannot survive a restart/boot. + * \param endpoint The endpoint that resulted in the contact being added + * + * \return The created contact or NULL on failure. + * + * \warning + * This function should only be called if you already hold a named write lock on the aor. + */ +struct ast_sip_contact *ast_sip_location_create_contact(struct ast_sip_aor *aor, + const char *uri, struct timeval expiration_time, const char *path_info, + const char *user_agent, const char *via_addr, int via_port, const char *call_id, + int prune_on_boot, struct ast_sip_endpoint *endpoint); + +/*! * \brief Update a contact * * \param contact New contact object with details @@ -1168,6 +1322,12 @@ int ast_sip_location_update_contact(struct ast_sip_contact *contact); int ast_sip_location_delete_contact(struct ast_sip_contact *contact); /*! + * \brief Prune the prune_on_boot contacts + * \since 13.18.0 + */ +void ast_sip_location_prune_boot_contacts(void); + +/*! * \brief Callback called when an outbound request with authentication credentials is to be sent in dialog * * This callback will have the created request on it. The callback's purpose is to do any extra @@ -1657,6 +1817,26 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, /*! * \brief General purpose method for creating an rdata structure using specific information + * \since 13.15.0 + * + * \param rdata[out] The rdata structure that will be populated + * \param packet A SIP message + * \param src_name The source IP address of the message + * \param src_port The source port of the message + * \param transport_type The type of transport the message was received on + * \param local_name The local IP address the message was received on + * \param local_port The local port the message was received on + * \param contact_uri The contact URI of the message + * + * \retval 0 success + * \retval -1 failure + */ +int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, + const char *src_name, int src_port, char *transport_type, const char *local_name, + int local_port, const char *contact_uri); + +/*! + * \brief General purpose method for creating an rdata structure using specific information * * \param rdata[out] The rdata structure that will be populated * \param packet A SIP message @@ -1669,8 +1849,8 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, * \retval 0 success * \retval -1 failure */ -int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, - const char *local_name, int local_port); +int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, + int src_port, char *transport_type, const char *local_name, int local_port); /*! * \brief General purpose method for creating a SIP request @@ -1949,6 +2129,24 @@ int ast_sip_append_body(pjsip_tx_data *tdata, const char *body_text); void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size); /*! + * \brief Create and copy a pj_str_t into a standard character buffer. + * + * pj_str_t is not NULL-terminated. Any place that expects a NULL- + * terminated string needs to have the pj_str_t copied into a separate + * buffer. + * + * Copies the pj_str_t contents into a newly allocated buffer pointed to + * by dest. NULL-terminates the buffer. + * + * \note Caller is responsible for freeing the allocated memory. + * + * \param dest [out] The destination buffer + * \param src The pj_str_t to copy + * \retval Number of characters copied or negative value on error + */ +int ast_copy_pj_str2(char **dest, const pj_str_t *src); + +/*! * \brief Get the looked-up endpoint on an out-of dialog request or response * * The function may ONLY be called on out-of-dialog requests or responses. For @@ -2423,14 +2621,20 @@ struct ast_sip_supplement { * \retval 0 Success * \retval -1 Failure */ -int ast_sip_register_supplement(struct ast_sip_supplement *supplement); +#define ast_sip_register_supplement(supplement) \ + __ast_sip_register_supplement(supplement, __FILE__, __LINE__, __PRETTY_FUNCTION__) +int __ast_sip_register_supplement(struct ast_sip_supplement *supplement, + const char *file, int line, const char *func); /*! * \brief Unregister a an supplement to SIP out of dialog processing * * \param supplement The supplement to unregister */ -void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement); +#define ast_sip_unregister_supplement(supplement) \ + __ast_sip_unregister_supplement(supplement, __FILE__, __LINE__, __PRETTY_FUNCTION__) +void __ast_sip_unregister_supplement(struct ast_sip_supplement *supplement, + const char *file, int line, const char *func); /*! * \brief Retrieve the global MWI taskprocessor high water alert trigger level. @@ -2707,4 +2911,168 @@ void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, void ast_sip_get_unidentified_request_thresholds(unsigned int *count, unsigned int *period, unsigned int *prune_interval); +/*! + * \brief Get the transport name from an endpoint or request uri + * \since 13.15.0 + * + * \param endpoint + * \param sip_uri + * \param buf Buffer to receive transport name + * \param buf_len Buffer length + * + * \retval 0 Success + * \retval -1 Failure + * + * \note + * If endpoint->transport is not NULL, it is returned in buf. + * Otherwise if sip_uri has an 'x-ast-txp' parameter AND the sip_uri host is + * an ip4 or ip6 address, its value is returned, + */ +int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint, + pjsip_sip_uri *sip_uri, char *buf, size_t buf_len); + +/*! + * \brief Sets pjsip_tpselector from an endpoint or uri + * \since 13.15.0 + * + * \param endpoint If endpoint->transport is set, it's used + * \param sip_uri If sip_uri contains a x-ast-txp parameter, it's used + * \param selector The selector to be populated + * + * \retval 0 success + * \retval -1 failure + */ +int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, + pjsip_sip_uri *sip_uri, pjsip_tpselector *selector); + +/*! + * \brief Set the transport on a dialog + * \since 13.15.0 + * + * \param endpoint + * \param dlg + * \param selector (optional) + * + * \note + * This API calls ast_sip_get_transport_name(endpoint, dlg->target) and if the result is + * non-NULL, calls pjsip_dlg_set_transport. If 'selector' is non-NULL, it is updated with + * the selector used. + */ +int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, + pjsip_tpselector *selector); + +/*! + * \brief Convert the DTMF mode enum value into a string + * \since 13.18.0 + * + * \param dtmf the dtmf mode + * \param buf Buffer to receive dtmf mode string + * \param buf_len Buffer length + * + * \retval 0 Success + * \retval -1 Failure + * + */ +int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, + char *buf, size_t buf_len); + +/*! + * \brief Convert the DTMF mode name into an enum + * \since 13.18.0 + * + * \param dtmf_mode dtmf mode as a string + * + * \retval >= 0 The enum value + * \retval -1 Failure + * + */ +int ast_sip_str_to_dtmf(const char *dtmf_mode); + +/*! + * \brief Transport shutdown monitor callback. + * \since 13.18.0 + * + * \param data User data to know what to do when transport shuts down. + * + * \note The callback does not need to care that data is an ao2 object. + * + * \return Nothing + */ +typedef void (*ast_transport_monitor_shutdown_cb)(void *data); + +enum ast_transport_monitor_reg { + /*! \brief Successfully registered the transport monitor */ + AST_TRANSPORT_MONITOR_REG_SUCCESS, + /*! \brief Replaced the already existing transport monitor with new one. */ + AST_TRANSPORT_MONITOR_REG_REPLACED, + /*! + * \brief Transport not found to monitor. + * \note Transport is either already shutdown or is not reliable. + */ + AST_TRANSPORT_MONITOR_REG_NOT_FOUND, + /*! \brief Error while registering transport monitor. */ + AST_TRANSPORT_MONITOR_REG_FAILED, +}; + +/*! + * \brief Register a reliable transport shutdown monitor callback. + * \since 13.18.0 + * + * \param transport Transport to monitor for shutdown. + * \param cb Who to call when transport is shutdown. + * \param ao2_data Data to pass with the callback. + * + * \return enum ast_transport_monitor_reg + */ +enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport, + ast_transport_monitor_shutdown_cb cb, void *ao2_data); + +/*! + * \brief Unregister a reliable transport shutdown monitor callback. + * \since 13.18.0 + * + * \param transport Transport to monitor for shutdown. + * \param cb Who to call when transport is shutdown. + * + * \return Nothing + */ +void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb); + +/*! + * \brief Unregister monitor callback from all reliable transports. + * \since 13.18.0 + * + * \param cb Who to call when a transport is shutdown. + * + * \return Nothing + */ +void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb); + +/*! Transport state notification registration element. */ +struct ast_sip_tpmgr_state_callback { + /*! PJPROJECT transport state notification callback */ + pjsip_tp_state_callback cb; + AST_LIST_ENTRY(ast_sip_tpmgr_state_callback) node; +}; + +/*! + * \brief Register a transport state notification callback element. + * \since 13.18.0 + * + * \param element What we are registering. + * + * \return Nothing + */ +void ast_sip_transport_state_register(struct ast_sip_tpmgr_state_callback *element); + +/*! + * \brief Unregister a transport state notification callback element. + * \since 13.18.0 + * + * \param element What we are unregistering. + * + * \return Nothing + */ +void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element); + #endif /* _RES_PJSIP_H */ diff --git a/include/asterisk/res_pjsip_presence_xml.h b/include/asterisk/res_pjsip_presence_xml.h index deed0901e..55b79ad6e 100644 --- a/include/asterisk/res_pjsip_presence_xml.h +++ b/include/asterisk/res_pjsip_presence_xml.h @@ -69,7 +69,8 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len); * \param[out] local_state */ void ast_sip_presence_exten_state_to_str(int state, char **statestring, - char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state); + char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state, + unsigned int notify_early_inuse_ringing); /*! * \brief Create XML attribute diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index 26dd451a7..a0fc9650e 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -28,6 +28,8 @@ #include "asterisk/netsock2.h" /* Needed for ast_sdp_srtp struct */ #include "asterisk/sdp_srtp.h" +/* Needed for ast_media_type */ +#include "asterisk/codec.h" /* Forward declarations */ struct ast_sip_endpoint; @@ -56,17 +58,21 @@ enum ast_sip_session_t38state { }; struct ast_sip_session_sdp_handler; +struct ast_sip_session; +struct ast_sip_session_media; + +typedef struct ast_frame *(*ast_sip_session_media_read_cb)(struct ast_sip_session *session, struct ast_sip_session_media *session_media); +typedef int (*ast_sip_session_media_write_cb)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, + struct ast_frame *frame); /*! * \brief A structure containing SIP session media information */ struct ast_sip_session_media { - union { - /*! \brief RTP instance itself */ - struct ast_rtp_instance *rtp; - /*! \brief UDPTL instance itself */ - struct ast_udptl *udptl; - }; + /*! \brief RTP instance itself */ + struct ast_rtp_instance *rtp; + /*! \brief UDPTL instance itself */ + struct ast_udptl *udptl; /*! \brief Direct media address */ struct ast_sockaddr direct_media_addr; /*! \brief SDP handler that setup the RTP */ @@ -85,8 +91,54 @@ struct ast_sip_session_media { unsigned int remotely_held:1; /*! \brief Stream is on hold by local side */ unsigned int locally_held:1; - /*! \brief Stream type this session media handles */ - char stream_type[1]; + /*! \brief Does remote support rtcp_mux */ + unsigned int remote_rtcp_mux:1; + /*! \brief Media type of this session media */ + enum ast_media_type type; + /*! \brief The write callback when writing frames */ + ast_sip_session_media_write_cb write_callback; + /*! \brief The stream number to place into any resulting frames */ + int stream_num; + /*! \brief Media identifier for this stream (may be shared across multiple streams) */ + char *mid; + /*! \brief The bundle group the stream belongs to */ + int bundle_group; + /*! \brief Whether this stream is currently bundled or not */ + unsigned int bundled; + /*! \brief Media stream label */ + char mslabel[AST_UUID_STR_LEN]; + /*! \brief Track label */ + char label[AST_UUID_STR_LEN]; + /*! \brief The underlying session has been changed in some fashion */ + unsigned int changed; + /*! \brief Remote media stream label */ + char *remote_mslabel; +}; + +/*! + * \brief Structure which contains read callback information + */ +struct ast_sip_session_media_read_callback_state { + /*! \brief The file descriptor itself */ + int fd; + /*! \brief The callback to invoke */ + ast_sip_session_media_read_cb read_callback; + /*! \brief The media session */ + struct ast_sip_session_media *session; +}; + +/*! + * \brief Structure which contains media state information (streams, sessions) + */ +struct ast_sip_session_media_state { + /*! \brief Mapping of stream to media sessions */ + AST_VECTOR(, struct ast_sip_session_media *) sessions; + /*! \brief Added read callbacks - these are whole structs and not pointers */ + AST_VECTOR(, struct ast_sip_session_media_read_callback_state) read_callbacks; + /*! \brief Default media sessions for each type */ + struct ast_sip_session_media *default_session[AST_MEDIA_TYPE_END]; + /*! \brief The media stream topology */ + struct ast_stream_topology *topology; }; /*! @@ -121,8 +173,6 @@ struct ast_sip_session { AST_LIST_HEAD(, ast_sip_session_supplement) supplements; /*! Datastores added to the session by supplements to the session */ struct ao2_container *datastores; - /*! Media streams */ - struct ao2_container *media; /*! Serializer for tasks relating to this SIP session */ struct ast_taskprocessor *serializer; /*! Non-null if the session serializer is suspended or being suspended. */ @@ -137,8 +187,10 @@ struct ast_sip_session { pj_timer_entry scheduled_termination; /*! Identity of endpoint this session deals with */ struct ast_party_id id; - /*! Requested capabilities */ - struct ast_format_cap *req_caps; + /*! Active media state (sessions + streams) - contents are guaranteed not to change */ + struct ast_sip_session_media_state *active_media_state; + /*! Pending media state (sessions + streams) */ + struct ast_sip_session_media_state *pending_media_state; /*! Optional DSP, used only for inband DTMF/Fax-CNG detection if configured */ struct ast_dsp *dsp; /*! Whether the termination of the session should be deferred */ @@ -153,6 +205,12 @@ struct ast_sip_session { struct ast_sip_aor *aor; /*! From header saved at invite creation */ pjsip_fromto_hdr *saved_from_hdr; + /*! Whether the end of the session should be deferred */ + unsigned int defer_end:1; + /*! Session end (remote hangup) requested while termination deferred */ + unsigned int ended_while_deferred:1; + /*! DTMF mode to use with this session, from endpoint but can change */ + enum ast_sip_dtmf_mode dtmf; }; typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata); @@ -309,34 +367,29 @@ struct ast_sip_session_sdp_handler { /*! * \brief Set session details based on a stream in an incoming SDP offer or answer * \param session The session for which the media is being negotiated - * \param session_media The media to be setup for this session + * \param session_media The media session * \param sdp The entire SDP. Useful for getting "global" information, such as connections or attributes - * \param stream The stream on which to operate - * \retval 0 The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called. - * \retval <0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned. - * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called. - */ - int (*negotiate_incoming_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream); - /*! - * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer - * \param session The session for which media is being added - * \param session_media The media to be setup for this session - * \param stream The stream on which to operate + * \param index The index for the session media, Asterisk stream, and PJMEDIA stream being negotiated + * \param asterisk_stream The Asterisk stream representation * \retval 0 The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called. * \retval <0 There was an error encountered. No further operation will take place and the current negotiation will be abandoned. * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called. */ - int (*handle_incoming_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, struct pjmedia_sdp_media *stream); + int (*negotiate_incoming_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, + const struct pjmedia_sdp_session *sdp, int index, struct ast_stream *asterisk_stream); /*! * \brief Create an SDP media stream and add it to the outgoing SDP offer or answer * \param session The session for which media is being added * \param session_media The media to be setup for this session * \param sdp The entire SDP as currently built + * \param remote Optional remote SDP if this is an answer + * \param stream The stream that is to be added to the outgoing SDP * \retval 0 This handler has no stream to add. If there are other registered handlers for this stream type, they will be called. * \retval <0 There was an error encountered. No further operation will take place and the current SDP negotiation will be abandoned. * \retval >0 The handler has a stream to be added to the SDP. No further handler of this stream type will be called. */ - int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp); + int (*create_outgoing_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp, + const struct pjmedia_sdp_session *remote, struct ast_stream *stream); /*! * \brief Update media stream with external address if applicable * \param tdata The outgoing message itself @@ -347,17 +400,18 @@ struct ast_sip_session_sdp_handler { /*! * \brief Apply a negotiated SDP media stream * \param session The session for which media is being applied - * \param session_media The media to be setup for this session + * \param session_media The media session * \param local The entire local negotiated SDP - * \param local_stream The local stream which to apply * \param remote The entire remote negotiated SDP - * \param remote_stream The remote stream which to apply + * \param index The index of the session media, SDP streams, and Asterisk streams + * \param asterisk_stream The Asterisk stream representation * \retval 0 The stream was not applied by this handler. If there are other registered handlers for this stream type, they will be called. * \retval <0 There was an error encountered. No further operation will take place and the current application will be abandoned. * \retval >0 The stream was handled by this handler. No further handler of this stream type will be called. */ - int (*apply_negotiated_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream, - const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream); + int (*apply_negotiated_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, + const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_session *remote, int index, + struct ast_stream *asterisk_stream); /*! * \brief Stop a session_media created by this handler but do not destroy resources * \param session The session for which media is being stopped @@ -387,7 +441,7 @@ struct ast_sip_channel_pvt { /*! * \brief Allocate a new SIP channel pvt structure * - * \param pvt Pointer to channel specific implementation + * \param pvt Pointer to channel specific information * \param session Pointer to SIP session * * \retval non-NULL success @@ -446,17 +500,21 @@ void ast_sip_session_unsuspend(struct ast_sip_session *session); * \param contact The contact that this session will communicate with * \param location Name of the location to call, be it named location or explicit URI. Overrides contact if present. * \param request_user Optional request user to place in the request URI if permitted - * \param req_caps The requested capabilities + * \param req_topology The requested capabilities */ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, const char *location, const char *request_user, - struct ast_format_cap *req_caps); + struct ast_stream_topology *req_topology); /*! * \brief Terminate a session and, if possible, send the provided response code * * \param session The session to terminate * \param response The response code to use for termination if possible + * + * \warning Calling this function MAY cause the last session reference to be + * released and the session destructor to be called. If you need to do something + * with session after this call, be sure to bump the ref count before calling terminate. */ void ast_sip_session_terminate(struct ast_sip_session *session, int response); @@ -478,6 +536,13 @@ int ast_sip_session_defer_termination(struct ast_sip_session *session); void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session); /*! + * \brief End the session if it had been previously deferred + * + * \param session The session to end if it had been deferred + */ +void ast_sip_session_end_if_deferred(struct ast_sip_session *session); + +/*! * \brief Register an SDP handler * * An SDP handler is responsible for parsing incoming SDP streams and ensuring that @@ -515,14 +580,27 @@ void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler * * \retval 0 Success * \retval -1 Failure */ -int ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement); +#define ast_sip_session_register_supplement(supplement) \ + __ast_sip_session_register_supplement(supplement, __FILE__, __LINE__, __PRETTY_FUNCTION__) +int __ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement, + const char *file, int line, const char *func); /*! * \brief Unregister a an supplement to SIP session processing * * \param supplement The supplement to unregister */ -void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement); +#define ast_sip_session_unregister_supplement(supplement) \ + __ast_sip_session_unregister_supplement(supplement, __FILE__, __LINE__, __PRETTY_FUNCTION__) +void __ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement, + const char *file, int line, const char *func); + +/*! + * \brief Add supplements to a SIP session + * + * \param session The session to initialize + */ +int ast_sip_session_add_supplements(struct ast_sip_session *session); /*! * \brief Alternative for ast_datastore_alloc() @@ -596,15 +674,37 @@ void ast_sip_session_remove_datastore(struct ast_sip_session *session, const cha * \param on_response Callback called when response for request is received * \param method The method that should be used when constructing the session refresh * \param generate_new_sdp Boolean to indicate if a new SDP should be created + * \param media_state Optional requested media state for the SDP + * * \retval 0 Successfully sent refresh * \retval -1 Failure to send refresh + * + * \note If a media_state is passed in ownership will be taken in all cases */ int ast_sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, - int generate_new_sdp); + int generate_new_sdp, + struct ast_sip_session_media_state *media_state); + +/*! + * \brief Regenerate SDP Answer + * + * This method is used when an SDP offer has been received but an SDP answer + * has not been sent yet. It requests that a new local SDP be created and + * set as the SDP answer. As with any outgoing request in res_pjsip_session, + * this will call into registered supplements in case they wish to add anything. + * + * \param session The session on which the answer will be updated + * \param on_sdp_creation Callback called when SDP is created + * \param generate_new_sdp Boolean to indicate if a new SDP should be created + * \retval 0 Successfully updated the SDP answer + * \retval -1 Failure to updated the SDP answer + */ +int ast_sip_session_regenerate_answer(struct ast_sip_session *session, + ast_sip_session_sdp_creation_cb on_sdp_creation); /*! * \brief Send a SIP response @@ -675,6 +775,123 @@ struct ast_sip_session *ast_sip_dialog_get_session(pjsip_dialog *dlg); */ void ast_sip_session_resume_reinvite(struct ast_sip_session *session); +/*! + * \brief Determines if a provided pending stream will be the default stream or not + * \since 15.0.0 + * + * \param session The session to check against + * \param stream The pending stream + * + * \retval 1 if stream will be default + * \retval 0 if stream will NOT be the default + */ +int ast_sip_session_is_pending_stream_default(const struct ast_sip_session *session, const struct ast_stream *stream); + +/*! + * \brief Allocate a session media state structure + * \since 15.0.0 + * + * \retval non-NULL success + * \retval NULL failure + */ +struct ast_sip_session_media_state *ast_sip_session_media_state_alloc(void); + +/*! + * \brief Allocate an ast_session_media and add it to the media state's vector. + * \since 15.0.0 + * + * This allocates a session media of the specified type. The position argument + * determines where in the vector that the new session media will be inserted. + * + * \note The returned ast_session_media is the reference held by the vector. Callers + * of this function must NOT decrement the refcount of the session media. + * + * \param session Session on which to query active media state for + * \param media_state Media state to place the session media into + * \param type The type of the session media + * \param position Position at which to insert the new session media. + * + * \note The active media state will be queried and if a media session already + * exists at the given position for the same type it will be reused instead of + * allocating a new one. + * + * \retval non-NULL success + * \retval NULL failure + */ +struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session, + struct ast_sip_session_media_state *media_state, enum ast_media_type type, int position); + +/*! + * \brief Reset a media state to a clean state + * \since 15.0.0 + * + * \param media_state The media state to reset + */ +void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state); + +/*! + * \brief Clone a media state + * \since 15.0.0 + * + * \param media_state The media state to clone + * + * \retval non-NULL success + * \retval NULL failure + */ +struct ast_sip_session_media_state *ast_sip_session_media_state_clone(const struct ast_sip_session_media_state *media_state); + +/*! + * \brief Free a session media state structure + * \since 15.0.0 + */ +void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state); + +/*! + * \brief Set a read callback for a media session with a specific file descriptor + * \since 15.0.0 + * + * \param session The session + * \param session_media The media session + * \param fd The file descriptor + * \param callback The read callback + * + * \retval 0 the read callback was successfully added + * \retval -1 the read callback could not be added + * + * \note This operations on the pending media state + */ +int ast_sip_session_media_add_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, + int fd, ast_sip_session_media_read_cb callback); + +/*! + * \brief Set a write callback for a media session + * \since 15.0.0 + * + * \param session The session + * \param session_media The media session + * \param callback The write callback + * + * \retval 0 the write callback was successfully add + * \retval -1 the write callback is already set to something different + * + * \note This operates on the pending media state + */ +int ast_sip_session_media_set_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, + ast_sip_session_media_write_cb callback); + +/*! + * \brief Retrieve the underlying media session that is acting as transport for a media session + * \since 15.0.0 + * + * \param session The session + * \param session_media The media session to retrieve the transport for + * + * \note This operates on the pending media state + * + * \note This function is guaranteed to return non-NULL + */ +struct ast_sip_session_media *ast_sip_session_media_get_transport(struct ast_sip_session *session, struct ast_sip_session_media *session_media); + /*! \brief Determines whether the res_pjsip_session module is loaded */ #define CHECK_PJSIP_SESSION_MODULE_LOADED() \ do { \ diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index c0ae33155..f9d686aca 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -81,6 +81,12 @@ extern "C" { /*! Maximum number of payload types RTP can support. */ #define AST_RTP_MAX_PT 128 +/*! + * Last RTP payload type statically assigned, see + * http://www.iana.org/assignments/rtp-parameters + */ +#define AST_RTP_PT_LAST_STATIC 34 + /*! First dynamic RTP payload type */ #define AST_RTP_PT_FIRST_DYNAMIC 96 @@ -114,6 +120,8 @@ enum ast_rtp_property { AST_RTP_PROPERTY_STUN, /*! Enable RTCP support */ AST_RTP_PROPERTY_RTCP, + /*! Enable Asymmetric RTP Codecs */ + AST_RTP_PROPERTY_ASYMMETRIC_CODEC, /*! * \brief Maximum number of RTP properties supported @@ -237,6 +245,15 @@ enum ast_rtp_instance_stat { AST_RTP_INSTANCE_STAT_RXOCTETCOUNT, }; +enum ast_rtp_instance_rtcp { + /*! RTCP should not be sent/received */ + AST_RTP_INSTANCE_RTCP_DISABLED = 0, + /*! RTCP should be sent/received based on standard port rules */ + AST_RTP_INSTANCE_RTCP_STANDARD, + /*! RTCP should be sent/received on the same port as RTP */ + AST_RTP_INSTANCE_RTCP_MUX, +}; + /* Codes for RTP-specific data - not defined by our AST_FORMAT codes */ /*! DTMF (RFC2833) */ #define AST_RTP_DTMF (1 << 0) @@ -447,6 +464,8 @@ struct ast_rtp_engine_ice { void (*turn_request)(struct ast_rtp_instance *instance, enum ast_rtp_ice_component_type component, enum ast_transport transport, const char *server, unsigned int port, const char *username, const char *password); + /*! Callback to alter the number of ICE components on a session */ + void (*change_components)(struct ast_rtp_instance *instance, int num_components); }; /*! \brief DTLS setup types */ @@ -489,6 +508,7 @@ struct ast_rtp_dtls_cfg { char *cipher; /*!< Cipher to use */ char *cafile; /*!< Certificate authority file */ char *capath; /*!< Path to certificate authority */ + unsigned int ephemeral_cert:1; /*!< Whether to not to generate an ephemeral certificate - defaults to 0 (off) */ }; /*! \brief Structure that represents the optional DTLS SRTP support within an RTP engine */ @@ -582,6 +602,16 @@ struct ast_rtp_engine { void (*available_formats)(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result); /*! Callback to send CNG */ int (*sendcng)(struct ast_rtp_instance *instance, int level); + /*! Callback to retrieve local SSRC */ + unsigned int (*ssrc_get)(struct ast_rtp_instance *instance); + /*! Callback to retrieve RTCP SDES CNAME */ + const char *(*cname_get)(struct ast_rtp_instance *instance); + /*! Callback to bundle an RTP instance to another */ + int (*bundle)(struct ast_rtp_instance *child, struct ast_rtp_instance *parent); + /*! Callback to set remote SSRC information */ + void (*set_remote_ssrc)(struct ast_rtp_instance *instance, unsigned int ssrc); + /*! Callback to set the stream identifier */ + void (*set_stream_num)(struct ast_rtp_instance *instance, int stream_num); /*! Callback to pointer for optional ICE support */ struct ast_rtp_engine_ice *ice; /*! Callback to pointer for optional DTLS SRTP support */ @@ -619,12 +649,13 @@ struct ast_rtp_glue { /*! * \brief Used to prevent two channels from remotely bridging audio rtp if the channel tech has a * reason for prohibiting it based on qualities that need to be compared from both channels. - * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, function this is not used. + * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used. */ int (*allow_rtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance); /*! * \brief Callback for retrieving the RTP instance carrying video * \note This function increases the reference count on the returned RTP instance. + * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used. */ enum ast_rtp_glue_result (*get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance); /*! @@ -637,11 +668,15 @@ struct ast_rtp_glue { /*! * \brief Callback for retrieving the RTP instance carrying text * \note This function increases the reference count on the returned RTP instance. + * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used. */ enum ast_rtp_glue_result (*get_trtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance); /*! Callback for updating the destination that the remote side should send RTP to */ int (*update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active); - /*! Callback for retrieving codecs that the channel can do. Result returned in result_cap. */ + /*! + * \brief Callback for retrieving codecs that the channel can do. Result returned in result_cap. + * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used. + */ void (*get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap); /*! Linked list information */ AST_RWLIST_ENTRY(ast_rtp_glue) entry; @@ -1432,7 +1467,8 @@ unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs); * * \since 1.8 */ -unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format *format, int code); +unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, + const struct ast_format *format, int code); /*! * \brief Retrieve all formats that were found @@ -1485,6 +1521,20 @@ void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_fo int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code); /*! + * \brief Set a payload code for use with a specific Asterisk format + * + * \param codecs Codecs structure to manipulate + * \param code The payload code + * \param format Asterisk format + * + * \retval 0 Payload was set to the given format + * \retval -1 Payload was in use or could not be set + * + * \since 15.0.0 + */ +int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format); + +/*! * \brief Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code * \since 14.0.0 * @@ -1537,7 +1587,8 @@ int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload) * * \since 1.8 */ -const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options); +const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, + const struct ast_format *format, int code, enum ast_rtp_options options); /*! * \brief Convert formats into a string and put them into a buffer @@ -2243,6 +2294,8 @@ int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level); * * \retval 0 Success * \retval non-zero Failure + * + * \note If no remote policy is provided any existing SRTP policies are left and the new local policy is added */ int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy* remote_policy, struct ast_srtp_policy *local_policy, int rtcp); @@ -2298,6 +2351,16 @@ struct ast_rtp_engine_dtls *ast_rtp_instance_get_dtls(struct ast_rtp_instance *i int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name, const char *value); /*! + * \brief Validates DTLS related configuration options + * + * \param dtls_cfg a DTLS configuration structure + * + * \retval 0 if valid + * \retval -1 if invalid + */ +int ast_rtp_dtls_cfg_validate(struct ast_rtp_dtls_cfg *dtls_cfg); + +/*! * \brief Copy contents of a DTLS configuration structure * * \param src_cfg source DTLS configuration structure @@ -2370,6 +2433,54 @@ time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp); */ void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time); +/*! + * \brief Retrieve the local SSRC value that we will be using + * + * \param rtp The RTP instance + * \return The SSRC value + */ +unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp); + +/*! + * \brief Retrieve the CNAME used in RTCP SDES items + * + * This is a pointer directly into the RTP struct, not a copy. + * + * \param rtp The RTP instance + * \return the CNAME + */ +const char *ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp); + +/*! + * \brief Request that an RTP instance be bundled with another + * \since 15.0.0 + * + * \param child The child RTP instance + * \param parent The parent RTP instance the child should be bundled with + * + * \retval 0 success + * \retval -1 failure + */ +int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent); + +/*! + * \brief Set the remote SSRC for an RTP instance + * \since 15.0.0 + * + * \param rtp The RTP instance + * \param ssrc The remote SSRC + */ +void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc); + +/*! + * \brief Set the stream number for an RTP instance + * \since 15.0.0 + * + * \param rtp The RTP instance + * \param stream_num The stream identifier number + */ +void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *instance, int stream_num); + /*! \addtogroup StasisTopicsAndMessages * @{ */ diff --git a/include/asterisk/sdp.h b/include/asterisk/sdp.h new file mode 100644 index 000000000..768469544 --- /dev/null +++ b/include/asterisk/sdp.h @@ -0,0 +1,703 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2017, Digium, Inc. + * + * Mark Michelson <mmichelson@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. + */ + +/* NOTE: It is unlikely that you need to include this file. You probably will only need + * this if you are an SDP translator, or if you are an inner part of the SDP API + */ + +#ifndef _SDP_PRIV_H +#define _SDP_PRIV_H + +#include "asterisk/vector.h" +#include "asterisk/format.h" +#include "asterisk/sdp_state.h" +#include "asterisk/stream.h" + +/*! + * \brief Structure representing an SDP Attribute + */ +struct ast_sdp_a_line { + /*! Attribute name */ + char *name; + /*! Attribute value. For attributes that have no value, this will be an empty string */ + char *value; +}; + +/*! + * \brief A collection of SDP Attributes + */ +AST_VECTOR(ast_sdp_a_lines, struct ast_sdp_a_line *); + +/*! + * \brief Structure representing an SDP Connection + */ +struct ast_sdp_c_line { + /* IP family string (e.g. IP4 or IP6) */ + char *address_type; + /* Connection address. Can be an IP address or FQDN */ + char *address; +}; + +/*! + * \brief Structre representing SDP Media Payloads + */ +struct ast_sdp_payload { + /* Media format description */ + char *fmt; +}; + +/*! + * \brief A collection of SDP Media Payloads + */ +AST_VECTOR(ast_sdp_payloads, struct ast_sdp_payload *); + +/*! + * \brief Structure representing an SDP Media Stream + * + * This contains both the m line, as well as its + * constituent a lines. + */ +struct ast_sdp_m_line { + /*! Media type (e.g. "audio" or "video") */ + char *type; + /*! RTP profile string (e.g. "RTP/AVP") */ + char *proto; + /*! Port number in m line */ + uint16_t port; + /*! Number of ports specified in m line */ + uint16_t port_count; + /*! RTP payloads */ + struct ast_sdp_payloads *payloads; + /*! Connection information for this media stream */ + struct ast_sdp_c_line *c_line; + /*! The attributes for this media stream */ + struct ast_sdp_a_lines *a_lines; +}; + +/*! + * \brief A collection of SDP Media Streams + */ +AST_VECTOR(ast_sdp_m_lines, struct ast_sdp_m_line *); + +/*! + * \brief Structure representing an SDP Origin + */ +struct ast_sdp_o_line { + /*! Origin user name */ + char *username; + /*! Origin id */ + uint64_t session_id; + /*! Origin version */ + uint64_t session_version; + /*! Origin IP address type (e.g. "IP4" or "IP6") */ + char *address_type; + /*! Origin address. Can be an IP address or FQDN */ + char *address; +}; + +/*! + * \brief Structure representing an SDP Session Name + */ +struct ast_sdp_s_line { + /* Session Name */ + char *session_name; +}; + +/*! + * \brief Structure representing SDP Timing + */ +struct ast_sdp_t_line { + /*! Session start time */ + uint64_t start_time; + /*! Session end time */ + uint64_t stop_time; +}; + +/*! + * \brief An SDP + */ +struct ast_sdp { + /*! SDP Origin line */ + struct ast_sdp_o_line *o_line; + /*! SDP Session name */ + struct ast_sdp_s_line *s_line; + /*! SDP top-level connection information */ + struct ast_sdp_c_line *c_line; + /*! SDP timing information */ + struct ast_sdp_t_line *t_line; + /*! SDP top-level attributes */ + struct ast_sdp_a_lines *a_lines; + /*! SDP media streams */ + struct ast_sdp_m_lines *m_lines; +}; + +/*! + * \brief A structure representing an SDP rtpmap attribute + */ +struct ast_sdp_rtpmap { + /*! The RTP payload number for the rtpmap */ + int payload; + /*! The Name of the codec */ + char *encoding_name; + /*! The clock rate of the codec */ + int clock_rate; + /*! Optional encoding parameters */ + char *encoding_parameters; + /*! Area where strings are stored */ + char buf[0]; +}; + +/*! + * \brief Free an SDP Attribute + * + * \param a_line The attribute to free + * + * \since 15 + */ +void ast_sdp_a_free(struct ast_sdp_a_line *a_line); + +/*! + * \brief Free an SDP Attribute collection + * + * \param a_lines The attribute collection to free + * + * \since 15 + */ +void ast_sdp_a_lines_free(struct ast_sdp_a_lines *a_lines); + +/*! + * \brief Free SDP Connection Data + * + * \param c_line The connection data to free + * + * \since 15 + */ +void ast_sdp_c_free(struct ast_sdp_c_line *c_line); + +/*! + * \brief Free an SDP Media Description Payload + * + * \param payload The payload to free + * + * \since 15 + */ +void ast_sdp_payload_free(struct ast_sdp_payload *payload); + +/*! + * \brief Free an SDP Media Description Payload collection + * + * \param payloads collection to free + * + * \since 15 + */ +void ast_sdp_payloads_free(struct ast_sdp_payloads *payloads); + +/*! + * \brief Free an SDP Media Description + * Frees the media description and all resources it contains + * + * \param m_line The media description to free + * + * \since 15 + */ +void ast_sdp_m_free(struct ast_sdp_m_line *m_line); + +/*! + * \brief Free an SDP Media Description collection + * + * \param m_lines The collection description to free + * + * \since 15 + */ +void ast_sdp_m_lines_free(struct ast_sdp_m_lines *m_lines); + +/*! + * \brief Free an SDP Origin + * + * \param o_line The origin description to free + * + * \since 15 + */ +void ast_sdp_o_free(struct ast_sdp_o_line *o_line); + +/*! + * \brief Free an SDP Session + * + * \param s_line The session to free + * + * \since 15 + */ +void ast_sdp_s_free(struct ast_sdp_s_line *s_line); + +/*! + * \brief Free SDP Timing + * + * \param t_line The timing description to free + * + * \since 15 + */ +void ast_sdp_t_free(struct ast_sdp_t_line *t_line); + +/*! + * \brief Allocate an SDP Attribute + * + * \param name Attribute Name + * \param value Attribute Name + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_a_line *ast_sdp_a_alloc(const char *name, const char *value); + +/*! + * \brief Allocate an SDP Connection + * + * \param family Family ("IN", etc) + * \param addr Address + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_c_line *ast_sdp_c_alloc(const char *family, const char *addr); + +/*! + * \brief Allocate an SDP Media Description Payload + * + * \param fmt The media format description + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_payload *ast_sdp_payload_alloc(const char *fmt); + +/*! + * \brief Allocate an SDP Media Description + * + * \param type ("audio", "video", etc) + * \param port Starting port + * \param port_count Port pairs to allocate + * \param proto ("RTP/AVP", "RTP/SAVP", "udp") + * \param c_line Connection to add. May be NULL + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_m_line *ast_sdp_m_alloc(const char *type, uint16_t port, + uint16_t port_count, const char *proto, struct ast_sdp_c_line *c_line); + +/*! + * \brief Allocate an SDP Session + * + * \param session_name The session name + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_s_line *ast_sdp_s_alloc(const char *session_name); + +/*! + * \brief Allocate SDP Timing + * + * \param start_time (Seconds since 1900) + * \param end_time (Seconds since 1900) + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_t_line *ast_sdp_t_alloc(uint64_t start_time, uint64_t stop_time); + +/*! + * \brief Allocate an SDP Origin + * + * \param username User name + * \param sesison_id Session ID + * \param sesison_version Session Version + * \param address_type Address type ("IN4", "IN6", etc) + * \param address Unicast address + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_o_line *ast_sdp_o_alloc(const char *username, uint64_t session_id, + uint64_t session_version, const char *address_type, const char *address); + +/*! + * \brief Add an SDP Attribute to an SDP + * + * \param sdp SDP + * \param a_line Attribute + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_add_a(struct ast_sdp *sdp, struct ast_sdp_a_line *a_line); + +/*! + * \brief Get the count of Attributes on an SDP + * + * \param sdp SDP + * + * \returns Number of Attributes + * + * \since 15 + */ +int ast_sdp_get_a_count(const struct ast_sdp *sdp); + +/*! + * \brief Get an Attribute from an SDP + * + * \param sdp SDP + * \param index Attribute index + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_a_line *ast_sdp_get_a(const struct ast_sdp *sdp, int index); + +/*! + * \brief Add a Media Description to an SDP + * + * \param sdp SDP + * \param m_line Media Description + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_add_m(struct ast_sdp *sdp, struct ast_sdp_m_line *m_line); + +/*! + * \brief Add an RTP Media Description to an SDP + * + * \param sdp SDP + * \param sdp_state SDP state information + * \param options SDP Options + * \param stream_index stream + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_add_m_from_rtp_stream(struct ast_sdp *sdp, const struct ast_sdp_state *sdp_state, + const struct ast_sdp_options *options, int stream_index); + +/*! + * \brief Get the count of Media Descriptions on an SDP + * + * \param sdp SDP + * + * \returns The number of Media Descriptions + * + * \since 15 + */ +int ast_sdp_get_m_count(const struct ast_sdp *sdp); + +/*! + * \brief Get a Media Descriptions from an SDP + * + * \param sdp SDP + * \param index Media Description index + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_m_line *ast_sdp_get_m(const struct ast_sdp *sdp, int index); + +/*! + * \brief Add an SDP Attribute to a Media Description + * + * \param m_line Media Description + * \param a_line Attribute + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_m_add_a(struct ast_sdp_m_line *m_line, struct ast_sdp_a_line *a_line); + +/*! + * \brief Get the count of Attributes on a Media Description + * + * \param m_line Media Description + * + * \returns Number of Attributes + * + * \since 15 + */ +int ast_sdp_m_get_a_count(const struct ast_sdp_m_line *m_line); + +/*! + * \brief Get an Attribute from a Media Description + * + * \param m_line Media Description + * \param index Attribute index + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_a_line *ast_sdp_m_get_a(const struct ast_sdp_m_line *m_line, int index); + +/*! + * \brief Add a Payload to a Media Description + * + * \param m_line Media Description + * \param payload Payload + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_m_add_payload(struct ast_sdp_m_line *m_line, + struct ast_sdp_payload *payload); + +/*! + * \brief Get the count of Payloads on a Media Description + * + * \param m_line Media Description + * + * \returns Number of Attributes + * + * \since 15 + */ +int ast_sdp_m_get_payload_count(const struct ast_sdp_m_line *m_line); + +/*! + * \brief Get a Payload from a Media Description + * + * \param m_line Media Description + * \param index Payload index + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp_payload *ast_sdp_m_get_payload(const struct ast_sdp_m_line *m_line, int index); + +/*! + * \brief Add a Format to a Media Description + * + * \param m_line Media Description + * \param options SDP Options + * \param rtp_code rtp_code from ast_rtp_codecs_payload_code + * \param asterisk_format True if the value in format is to be used. + * \param format Format + * \param code from AST_RTP list + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_m_add_format(struct ast_sdp_m_line *m_line, const struct ast_sdp_options *options, + int rtp_code, int asterisk_format, const struct ast_format *format, int code); + +/*! + * \brief Create an SDP ao2 object + * + * \param o_line Origin + * \param c_line Connection + * \param s_line Session + * \param t_line Timing + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \since 15 + */ +struct ast_sdp *ast_sdp_alloc(struct ast_sdp_o_line *o_line, + struct ast_sdp_c_line *c_line, struct ast_sdp_s_line *s_line, + struct ast_sdp_t_line *t_line); + +/*! + * \brief Find the first attribute match index in the top-level SDP + * + * \note This will not search within streams for the given attribute. + * + * \param sdp The SDP in which to search + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval index of attribute line on success. + * \retval -1 on failure or not found. + * + * \since 15.0.0 + */ +int ast_sdp_find_a_first(const struct ast_sdp *sdp, const char *attr_name, int payload); + +/*! + * \brief Find the next attribute match index in the top-level SDP + * + * \note This will not search within streams for the given attribute. + * + * \param sdp The SDP in which to search + * \param last The last matching index found + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval index of attribute line on success. + * \retval -1 on failure or not found. + * + * \since 15.0.0 + */ +int ast_sdp_find_a_next(const struct ast_sdp *sdp, int last, const char *attr_name, int payload); + +/*! + * \brief Find an attribute in the top-level SDP + * + * \note This will not search within streams for the given attribute. + * + * \param sdp The SDP in which to search + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval NULL Could not find the given attribute + * \retval Non-NULL The attribute to find + * + * \since 15.0.0 + */ +struct ast_sdp_a_line *ast_sdp_find_attribute(const struct ast_sdp *sdp, + const char *attr_name, int payload); + +/*! + * \brief Find the first attribute match index in an SDP stream (m-line) + * + * \param m_line The SDP m-line in which to search + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval index of attribute line on success. + * \retval -1 on failure or not found. + * + * \since 15.0.0 + */ +int ast_sdp_m_find_a_first(const struct ast_sdp_m_line *m_line, const char *attr_name, + int payload); + +/*! + * \brief Find the next attribute match index in an SDP stream (m-line) + * + * \param m_line The SDP m-line in which to search + * \param last The last matching index found + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval index of attribute line on success. + * \retval -1 on failure or not found. + * + * \since 15.0.0 + */ +int ast_sdp_m_find_a_next(const struct ast_sdp_m_line *m_line, int last, + const char *attr_name, int payload); + +/*! + * \brief Find an attribute in an SDP stream (m-line) + * + * \param m_line The SDP m-line in which to search + * \param attr_name The name of the attribute to search for + * \param payload Optional payload number to search for. If irrelevant, set to -1 + * + * \retval NULL Could not find the given attribute + * \retval Non-NULL The attribute to find + * + * \since 15.0.0 + */ +struct ast_sdp_a_line *ast_sdp_m_find_attribute(const struct ast_sdp_m_line *m_line, + const char *attr_name, int payload); + +/*! + * \brief Convert an SDP a_line into an rtpmap + * + * The returned value is heap-allocated and must be freed with + * ast_sdp_rtpmap_free() + * + * \param a_line The SDP a_line to convert + * + * \retval NULL Fail + * \retval non-NULL Success + * + * \since 15.0.0 + */ +struct ast_sdp_rtpmap *ast_sdp_a_get_rtpmap(const struct ast_sdp_a_line *a_line); + + +/*! + * \brief Allocate a new SDP rtpmap + * + * \param payload The RTP payload number + * \param encoding_name The human-readable name for the codec + * \param clock_rate The rate of the codec, in cycles per second + * \param encoding_parameters Optional codec-specific parameters (such as number of channels) + * + * \retval NULL Fail + * \retval non-NULL Success + * + * \since 15.0.0 + */ +struct ast_sdp_rtpmap *ast_sdp_rtpmap_alloc(int payload, const char *encoding_name, + int clock_rate, const char *encoding_parameters); + +/*! + * \brief Free an SDP rtpmap + * + * \since 15.0.0 + */ +void ast_sdp_rtpmap_free(struct ast_sdp_rtpmap *rtpmap); + +/*! + * \brief Turn an SDP into a stream topology + * + * This traverses the m-lines of the SDP and creates a stream topology, with + * each m-line corresponding to a stream in the created topology. + * + * \param sdp The SDP to convert + * \param g726_non_standard Non-zero if G.726 is non-standard + * + * \retval NULL An error occurred when converting + * \retval non-NULL The generated stream topology + * + * \since 15.0.0 + */ +struct ast_stream_topology *ast_get_topology_from_sdp(const struct ast_sdp *sdp, int g726_non_standard); +#endif /* _SDP_PRIV_H */ diff --git a/include/asterisk/sdp_options.h b/include/asterisk/sdp_options.h index a5c2d084e..e45ae8cb1 100644 --- a/include/asterisk/sdp_options.h +++ b/include/asterisk/sdp_options.h @@ -19,9 +19,211 @@ #ifndef _ASTERISK_SDP_OPTIONS_H #define _ASTERISK_SDP_OPTIONS_H +#include "asterisk/udptl.h" +#include "asterisk/format_cap.h" + struct ast_sdp_options; /*! + * \brief SDP DTMF mode options + */ +enum ast_sdp_options_dtmf { + /*! No DTMF to be used */ + AST_SDP_DTMF_NONE, + /*! Use RFC 4733 events for DTMF */ + AST_SDP_DTMF_RFC_4733, + /*! Use DTMF in the audio stream */ + AST_SDP_DTMF_INBAND, + /*! Use SIP 4733 if supported by the other side or INBAND if not */ + AST_SDP_DTMF_AUTO, +}; + +/*! + * \brief ICE options + * + * This is an enum because it will support a TRICKLE-ICE option + * in the future. + */ +enum ast_sdp_options_ice { + /*! ICE is not enabled on this session */ + AST_SDP_ICE_DISABLED, + /*! Standard ICE is enabled on this session */ + AST_SDP_ICE_ENABLED_STANDARD, +}; + +/*! + * \brief Implementation of the SDP + * + * Users of the SDP API set the implementation based on what they + * natively handle. This indicates the type of SDP that the API expects + * when being given an SDP, and it indicates the type of SDP that the API + * returns when asked for one. + */ +enum ast_sdp_options_impl { + /*! SDP is represented as a string */ + AST_SDP_IMPL_STRING, + /*! SDP is represented as a pjmedia_sdp_session */ + AST_SDP_IMPL_PJMEDIA, + /*! End of the list */ + AST_SDP_IMPL_END, +}; + +/*! + * \brief SDP encryption options + */ +enum ast_sdp_options_encryption { + /*! No encryption */ + AST_SDP_ENCRYPTION_DISABLED, + /*! SRTP SDES encryption */ + AST_SDP_ENCRYPTION_SRTP_SDES, + /*! DTLS encryption */ + AST_SDP_ENCRYPTION_DTLS, +}; + +/*! + * \brief Callback when processing an offer SDP for our answer SDP. + * \since 15.0.0 + * + * \details + * This callback is called after merging our last negotiated topology + * with the remote's offer topology and before we have sent our answer + * SDP. At this point you can alter new_topology streams. You can + * decline, remove formats, or rename streams. Changing anything else + * on the streams is likely to not end well. + * + * * To decline a stream simply set the stream state to + * AST_STREAM_STATE_REMOVED. You could implement a maximum number + * of active streams of a given type policy. + * + * * To remove formats use the format API to remove any formats from a + * stream. The streams have the current joint negotiated formats. + * Most likely you would want to remove all but the first format. + * + * * To rename a stream you need to clone the stream and give it a + * new name and then set it in new_topology using + * ast_stream_topology_set_stream(). + * + * \note Removing all formats is an error. You should decline the + * stream instead. + * + * \param context User supplied context data pointer for the SDP + * state. + * \param old_topology Active negotiated topology. NULL if this is + * the first SDP negotiation. The old topology is available so you + * can tell if any streams are new or changing type. + * \param new_topology New negotiated topology that we intend to + * generate the answer SDP. + * + * \return Nothing + */ +typedef void (*ast_sdp_answerer_modify_cb)(void *context, + const struct ast_stream_topology *old_topology, + struct ast_stream_topology *new_topology); + +/*! + * \internal + * \brief Callback when generating a topology for our SDP offer. + * \since 15.0.0 + * + * \details + * This callback is called after merging any topology updates from the + * system by ast_sdp_state_update_local_topology() and before we have + * sent our offer SDP. At this point you can alter new_topology + * streams. You can decline, add/remove/update formats, or rename + * streams. Changing anything else on the streams is likely to not + * end well. + * + * * To decline a stream simply set the stream state to + * AST_STREAM_STATE_REMOVED. You could implement a maximum number + * of active streams of a given type policy. + * + * * To update formats use the format API to change formats of the + * streams. The streams have the current proposed formats. You + * could do whatever you want for formats but you should stay within + * the configured formats for the stream type's endpoint. However, + * you should use ast_sdp_state_update_local_topology() instead of + * this backdoor method. + * + * * To rename a stream you need to clone the stream and give it a + * new name and then set it in new_topology using + * ast_stream_topology_set_stream(). + * + * \note Removing all formats is an error. You should decline the + * stream instead. + * + * \note Declined new streams that are in slots higher than present in + * old_topology are removed so the SDP can be smaller. The remote has + * never seen those slots so we shouldn't bother keeping them. + * + * \param context User supplied context data pointer for the SDP + * state. + * \param old_topology Active negotiated topology. NULL if this is + * the first SDP negotiation. The old topology is available so you + * can tell if any streams are new or changing type. + * \param new_topology Merged topology that we intend to generate the + * offer SDP. + * + * \return Nothing + */ +typedef void (*ast_sdp_offerer_modify_cb)(void *context, + const struct ast_stream_topology *old_topology, + struct ast_stream_topology *new_topology); + +/*! + * \brief Callback when generating an offer SDP to configure extra stream data. + * \since 15.0.0 + * + * \details + * This callback is called after any ast_sdp_offerer_modify_cb + * callback and before we have sent our offer SDP. The callback can + * call several SDP API calls to configure the proposed capabilities + * of streams before we create the SDP offer. For example, the + * callback could configure a stream specific connection address, T.38 + * parameters, RTP instance, or UDPTL instance parameters. + * + * \param context User supplied context data pointer for the SDP + * state. + * \param topology Topology ready to configure extra stream options. + * + * \return Nothing + */ +typedef void (*ast_sdp_offerer_config_cb)(void *context, const struct ast_stream_topology *topology); + +/*! + * \brief Callback before applying a topology. + * \since 15.0.0 + * + * \details + * This callback is called before the topology is applied so the + * using module can do what is necessary before the topology becomes + * active. + * + * \param context User supplied context data pointer for the SDP + * state. + * \param topology Topology ready to be applied. + * + * \return Nothing + */ +typedef void (*ast_sdp_preapply_cb)(void *context, const struct ast_stream_topology *topology); + +/*! + * \brief Callback after applying a topology. + * \since 15.0.0 + * + * \details + * This callback is called after the topology is applied so the + * using module can do what is necessary after the topology becomes + * active. + * + * \param context User supplied context data pointer for the SDP + * state. + * \param topology Topology already applied. + * + * \return Nothing + */ +typedef void (*ast_sdp_postapply_cb)(void *context, const struct ast_stream_topology *topology); + +/*! * \since 15.0.0 * \brief Allocate a new SDP options structure. * @@ -47,111 +249,526 @@ struct ast_sdp_options *ast_sdp_options_alloc(void); void ast_sdp_options_free(struct ast_sdp_options *options); /*! - * \brief ICE options + * \since 15.0.0 + * \brief Set SDP Options media_address * - * This is an enum because it is predicted that this eventually - * support a TRICKLE-ICE option. + * \param options SDP Options + * \param media_address */ -enum ast_sdp_options_ice { - /*! ICE is not enabled on this session */ - AST_SDP_ICE_DISABLED, - /*! Standard ICE is enabled on this session */ - AST_SDP_ICE_ENABLED_STANDARD, -}; +void ast_sdp_options_set_media_address(struct ast_sdp_options *options, + const char *media_address); /*! * \since 15.0.0 - * \brief Set ICE options + * \brief Get SDP Options media_address * - * The default is AST_SDP_ICE_DISABLED + * \param options SDP Options + * + * \returns media_address */ -int ast_sdp_options_set_ice(struct ast_sdp_options *options, - enum ast_sdp_options_ice ice_setting); +const char *ast_sdp_options_get_media_address(const struct ast_sdp_options *options); /*! * \since 15.0.0 - * \brief Retrieve ICE options + * \brief Set SDP Options interface_address + * + * \param options SDP Options + * \param interface_address */ -enum ast_sdp_options_ice ast_sdp_options_get_ice(const struct ast_sdp_options *options); +void ast_sdp_options_set_interface_address(struct ast_sdp_options *options, + const char *interface_address); /*! * \since 15.0.0 - * \brief Enable or disable telephone events. + * \brief Get SDP Options interface_address * - * A non-zero value indicates telephone events are enabled. - * A zero value indicates telephone events are disabled. + * \param options SDP Options * - * The default is 0 + * \returns interface_address */ -int ast_sdp_options_set_telephone_event(struct ast_sdp_options *options, - int telephone_event_enabled); +const char *ast_sdp_options_get_interface_address(const struct ast_sdp_options *options); /*! * \since 15.0.0 - * \brief Retrieve telephone event setting. + * \brief Set SDP Options sdpowner * - * \retval 0 Telephone events are currently disabled. - * \retval non-zero Telephone events are currently enabled. + * \param options SDP Options + * \param sdpowner */ -int ast_sdp_options_get_telephone_event(const struct ast_sdp_options *options); +void ast_sdp_options_set_sdpowner(struct ast_sdp_options *options, + const char *sdpowner); /*! - * \brief Representation of the SDP + * \since 15.0.0 + * \brief Get SDP Options sdpowner * - * Users of the SDP API set the representation based on what they - * natively handle. This indicates the type of SDP that the API expects - * when being given an SDP, and it indicates the type of SDP that the API - * returns when asked for one. + * \param options SDP Options + * + * \returns sdpowner */ -enum ast_sdp_options_repr { - /*! SDP is represented as a string */ - AST_SDP_REPR_STRING, - /*! SDP is represented as a pjmedia_sdp_session */ - AST_SDP_REPR_PJMEDIA, - /*! End of the list */ - AST_SDP_REPR_END, -}; +const char *ast_sdp_options_get_sdpowner(const struct ast_sdp_options *options); /*! * \since 15.0.0 - * \brief Set the SDP representation + * \brief Set SDP Options sdpsession * - * The default is AST_SDP_REPR_STRING + * \param options SDP Options + * \param sdpsession */ -int ast_sdp_options_set_repr(struct ast_sdp_options *options, - enum ast_sdp_options_repr repr); +void ast_sdp_options_set_sdpsession(struct ast_sdp_options *options, + const char *sdpsession); /*! * \since 15.0.0 - * \brief Get the SDP representation + * \brief Get SDP Options sdpsession + * + * \param options SDP Options + * + * \returns sdpsession */ -enum ast_sdp_options_repr ast_sdp_options_get_repr(const struct ast_sdp_options *options); +const char *ast_sdp_options_get_sdpsession(const struct ast_sdp_options *options); /*! - * \brief SDP encryption options + * \since 15.0.0 + * \brief Set SDP Options rtp_engine + * + * \param options SDP Options + * \param rtp_engine */ -enum ast_sdp_options_encryption { - /*! No encryption */ - AST_SDP_ENCRYPTION_DISABLED, - /*! SRTP SDES encryption */ - AST_SDP_ENCRYPTION_SRTP_SDES, - /*! DTLS encryption */ - AST_SDP_ENCRYPTION_DTLS, -}; +void ast_sdp_options_set_rtp_engine(struct ast_sdp_options *options, + const char *rtp_engine); + +/*! + * \since 15.0.0 + * \brief Get SDP Options rtp_engine + * + * \param options SDP Options + * + * \returns rtp_engine + */ +const char *ast_sdp_options_get_rtp_engine(const struct ast_sdp_options *options); + +void ast_sdp_options_set_state_context(struct ast_sdp_options *options, void *state_context); +void *ast_sdp_options_get_state_context(const struct ast_sdp_options *options); + +void ast_sdp_options_set_answerer_modify_cb(struct ast_sdp_options *options, ast_sdp_answerer_modify_cb answerer_modify_cb); +ast_sdp_answerer_modify_cb ast_sdp_options_get_answerer_modify_cb(const struct ast_sdp_options *options); + +void ast_sdp_options_set_offerer_modify_cb(struct ast_sdp_options *options, ast_sdp_offerer_modify_cb offerer_modify_cb); +ast_sdp_offerer_modify_cb ast_sdp_options_get_offerer_modify_cb(const struct ast_sdp_options *options); + +void ast_sdp_options_set_offerer_config_cb(struct ast_sdp_options *options, ast_sdp_offerer_config_cb offerer_config_cb); +ast_sdp_offerer_config_cb ast_sdp_options_get_offerer_config_cb(const struct ast_sdp_options *options); + +void ast_sdp_options_set_preapply_cb(struct ast_sdp_options *options, ast_sdp_preapply_cb preapply_cb); +ast_sdp_preapply_cb ast_sdp_options_get_preapply_cb(const struct ast_sdp_options *options); + +void ast_sdp_options_set_postapply_cb(struct ast_sdp_options *options, ast_sdp_postapply_cb postapply_cb); +ast_sdp_postapply_cb ast_sdp_options_get_postapply_cb(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options rtp_symmetric + * + * \param options SDP Options + * \param rtp_symmetric + */ +void ast_sdp_options_set_rtp_symmetric(struct ast_sdp_options *options, + unsigned int rtp_symmetric); + +/*! + * \since 15.0.0 + * \brief Get SDP Options rtp_symmetric + * + * \param options SDP Options + * + * \returns rtp_symmetric + */ +unsigned int ast_sdp_options_get_rtp_symmetric(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options rtp_ipv6 + * + * \param options SDP Options + * \param rtp_ipv6 + */ +void ast_sdp_options_set_rtp_ipv6(struct ast_sdp_options *options, + unsigned int rtp_ipv6); + +/*! + * \since 15.0.0 + * \brief Get SDP Options rtp_ipv6 + * + * \param options SDP Options + * + * \returns rtp_ipv6 + */ +unsigned int ast_sdp_options_get_rtp_ipv6(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options g726_non_standard + * + * \param options SDP Options + * \param g726_non_standard + */ +void ast_sdp_options_set_g726_non_standard(struct ast_sdp_options *options, + unsigned int g726_non_standard); + +/*! + * \since 15.0.0 + * \brief Get SDP Options g726_non_standard + * + * \param options SDP Options + * + * \returns g726_non_standard + */ +unsigned int ast_sdp_options_get_g726_non_standard(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options tos_audio + * + * \param options SDP Options + * \param tos_audio + */ +void ast_sdp_options_set_tos_audio(struct ast_sdp_options *options, + unsigned int tos_audio); + +/*! + * \since 15.0.0 + * \brief Get SDP Options tos_audio + * + * \param options SDP Options + * + * \returns tos_audio + */ +unsigned int ast_sdp_options_get_tos_audio(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options cos_audio + * + * \param options SDP Options + * \param cos_audio + */ +void ast_sdp_options_set_cos_audio(struct ast_sdp_options *options, + unsigned int cos_audio); + +/*! + * \since 15.0.0 + * \brief Get SDP Options cos_audio + * + * \param options SDP Options + * + * \returns cos_audio + */ +unsigned int ast_sdp_options_get_cos_audio(const struct ast_sdp_options *options); /*! * \since 15.0.0 - * \brief Set the SDP encryption + * \brief Set SDP Options tos_video * - * The default is AST_SDP_ENCRYPTION_DISABLED + * \param options SDP Options + * \param tos_video */ -int ast_sdp_options_set_encryption(struct ast_sdp_options *options, +void ast_sdp_options_set_tos_video(struct ast_sdp_options *options, + unsigned int tos_video); + +/*! + * \since 15.0.0 + * \brief Get SDP Options tos_video + * + * \param options SDP Options + * + * \returns tos_video + */ +unsigned int ast_sdp_options_get_tos_video(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options cos_video + * + * \param options SDP Options + * \param cos_video + */ +void ast_sdp_options_set_cos_video(struct ast_sdp_options *options, + unsigned int cos_video); + +/*! + * \since 15.0.0 + * \brief Get SDP Options cos_video + * + * \param options SDP Options + * + * \returns cos_video + */ +unsigned int ast_sdp_options_get_cos_video(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options dtmf + * + * \param options SDP Options + * \param dtmf + */ +void ast_sdp_options_set_dtmf(struct ast_sdp_options *options, + enum ast_sdp_options_dtmf dtmf); + +/*! + * \since 15.0.0 + * \brief Get SDP Options dtmf + * + * \param options SDP Options + * + * \returns dtmf + */ +enum ast_sdp_options_dtmf ast_sdp_options_get_dtmf(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options ice + * + * \param options SDP Options + * \param ice + */ +void ast_sdp_options_set_ice(struct ast_sdp_options *options, + enum ast_sdp_options_ice ice); + +/*! + * \since 15.0.0 + * \brief Get SDP Options ice + * + * \param options SDP Options + * + * \returns ice + */ +enum ast_sdp_options_ice ast_sdp_options_get_ice(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options impl + * + * \param options SDP Options + * \param impl + */ +void ast_sdp_options_set_impl(struct ast_sdp_options *options, + enum ast_sdp_options_impl impl); + +/*! + * \since 15.0.0 + * \brief Get SDP Options impl + * + * \param options SDP Options + * + * \returns impl + */ +enum ast_sdp_options_impl ast_sdp_options_get_impl(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options encryption + * + * \param options SDP Options + * \param encryption + */ +void ast_sdp_options_set_encryption(struct ast_sdp_options *options, enum ast_sdp_options_encryption encryption); /*! * \since 15.0.0 - * \brief Get the SDP encryption + * \brief Get SDP Options encryption + * + * \param options SDP Options + * + * \returns encryption */ enum ast_sdp_options_encryption ast_sdp_options_get_encryption(const struct ast_sdp_options *options); +/*! + * \since 15.0.0 + * \brief Get SDP Options RTCP MUX + * + * \param options SDP Options + * + * \returns Boolean indicating if RTCP MUX is enabled. + */ +unsigned int ast_sdp_options_get_rtcp_mux(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options RTCP MUX + * + * \param options SDP Options + * \param value Boolean that indicates if RTCP MUX should be enabled. + */ +void ast_sdp_options_set_rtcp_mux(struct ast_sdp_options *options, unsigned int value); + +/*! + * \since 15.0.0 + * \brief Set SDP Options udptl_symmetric + * + * \param options SDP Options + * \param udptl_symmetric + */ +void ast_sdp_options_set_udptl_symmetric(struct ast_sdp_options *options, + unsigned int udptl_symmetric); + +/*! + * \since 15.0.0 + * \brief Get SDP Options udptl_symmetric + * + * \param options SDP Options + * + * \returns udptl_symmetric + */ +unsigned int ast_sdp_options_get_udptl_symmetric(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options udptl_error_correction + * + * \param options SDP Options + * \param error_correction + */ +void ast_sdp_options_set_udptl_error_correction(struct ast_sdp_options *options, + enum ast_t38_ec_modes error_correction); + +/*! + * \since 15.0.0 + * \brief Get SDP Options udptl_error_correction + * + * \param options SDP Options + * + * \returns udptl_error_correction + */ +enum ast_t38_ec_modes ast_sdp_options_get_udptl_error_correction(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options udptl_far_max_datagram + * + * \param options SDP Options + * \param far_max_datagram + */ +void ast_sdp_options_set_udptl_far_max_datagram(struct ast_sdp_options *options, + unsigned int far_max_datagram); + +/*! + * \since 15.0.0 + * \brief Get SDP Options udptl_far_max_datagram + * + * \param options SDP Options + * + * \returns udptl_far_max_datagram + */ +unsigned int ast_sdp_options_get_udptl_far_max_datagram(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Set SDP Options max_streams + * + * \param options SDP Options + * \param max_streams + */ +void ast_sdp_options_set_max_streams(struct ast_sdp_options *options, + unsigned int max_streams); + +/*! + * \since 15.0.0 + * \brief Get SDP Options max_streams + * + * \param options SDP Options + * + * \returns max_streams + */ +unsigned int ast_sdp_options_get_max_streams(const struct ast_sdp_options *options); + +/*! + * \since 15.0.0 + * \brief Enable setting SSRC level attributes on SDPs + * + * \param options SDP Options + * \param ssrc Boolean indicating if SSRC attributes should be included in generated SDPs + */ +void ast_sdp_options_set_ssrc(struct ast_sdp_options *options, unsigned int ssrc); + +/*! + * \since 15.0.0 + * \brief Get SDP Options ssrc + * + * \param options SDP Options + * + * \returns Whether SSRC-level attributes will be added to our SDP. + */ +unsigned int ast_sdp_options_get_ssrc(const struct ast_sdp_options *options); + +/*! + * \brief Set the SDP options scheduler context used to create new streams of the type. + * \since 15.0.0 + * + * \param options SDP Options + * \param type Media type the scheduler context is for. + * \param sched Scheduler context to use for the specified media type. + * + * \return Nothing + */ +void ast_sdp_options_set_sched_type(struct ast_sdp_options *options, + enum ast_media_type type, struct ast_sched_context *sched); + +/*! + * \brief Get the SDP options scheduler context used to create new streams of the type. + * \since 15.0.0 + * + * \param options SDP Options + * \param type Media type the format cap represents. + * + * \return The stored scheduler context to create new streams of the type. + */ +struct ast_sched_context *ast_sdp_options_get_sched_type(const struct ast_sdp_options *options, + enum ast_media_type type); + +/*! + * \brief Set all allowed stream types to create new streams. + * \since 15.0.0 + * + * \param options SDP Options + * \param cap Format capabilities to set all allowed stream types at once. + * Could be NULL to disable creating any new streams. + * + * \return Nothing + */ +void ast_sdp_options_set_format_caps(struct ast_sdp_options *options, + struct ast_format_cap *cap); + +/*! + * \brief Set the SDP options format cap used to create new streams of the type. + * \since 15.0.0 + * + * \param options SDP Options + * \param type Media type the format cap represents. + * \param cap Format capabilities to use for the specified media type. + * Could be NULL to disable creating new streams of type. + * + * \return Nothing + */ +void ast_sdp_options_set_format_cap_type(struct ast_sdp_options *options, + enum ast_media_type type, struct ast_format_cap *cap); + +/*! + * \brief Get the SDP options format cap used to create new streams of the type. + * \since 15.0.0 + * + * \param options SDP Options + * \param type Media type the format cap represents. + * + * \retval NULL if stream not allowed to be created. + * \retval cap to use in negotiating the new stream. + * + * \note The returned cap does not have its own ao2 ref. + */ +struct ast_format_cap *ast_sdp_options_get_format_cap_type(const struct ast_sdp_options *options, + enum ast_media_type type); + #endif /* _ASTERISK_SDP_OPTIONS_H */ diff --git a/include/asterisk/sdp_priv.h b/include/asterisk/sdp_priv.h deleted file mode 100644 index 000d11143..000000000 --- a/include/asterisk/sdp_priv.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2017, Digium, Inc. - * - * Mark Michelson <mmichelson@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. - */ - -/* NOTE: It is unlikely that you need to include this file. You probably will only need - * this if you are an SDP translator, or if you are an inner part of the SDP API - */ - -#ifndef _SDP_PRIV_H -#define _SDP_PRIV_H - -#include "asterisk/vector.h" - -/*! - * \brief Structure representing an SDP attribute - */ -struct ast_sdp_a_line { - /*! Attribute name */ - char *name; - /*! Attribute value. For attributes that have no value, this will be an empty string */ - char *value; -}; - -/*! - * \brief Structure representing an SDP connection - */ -struct ast_sdp_c_line { - /* IP family string (e.g. IP4 or IP6) */ - char *family; - /* Connection address. Can be an IP address or FQDN */ - char *addr; -}; - -/*! - * \brief A collection of SDP attributes - */ -AST_VECTOR(ast_sdp_a_line_vector, struct ast_sdp_a_line); - -/*! - * \brief An SDP media stream - * - * This contains both the m line, as well as its - * constituent a lines. - */ -struct ast_sdp_m_line { - /*! Media type (e.g. "audio" or "video") */ - char *type; - /*! Port number in m line */ - uint16_t port; - /*! Number of ports specified in m line */ - uint16_t port_count; - /*! RTP profile string (e.g. "RTP/AVP") */ - char *profile; - /*! RTP payloads */ - AST_VECTOR(, char *) payloads; - /*! Connection information for this media stream */ - struct ast_sdp_c_line c_line; - /*! The attributes for this media stream */ - struct ast_sdp_a_line_vector a_lines; -}; - -/*! - * \brief SDP time information - */ -struct ast_sdp_t_line { - /*! Session start time */ - uint32_t start; - /*! Session end time */ - uint32_t end; -}; - -/*! - * \brief An SDP - */ -struct ast_sdp { - /*! SDP Origin line */ - struct { - /*! Origin user name */ - char *user; - /*! Origin id */ - uint32_t id; - /*! Origin version */ - uint32_t version; - /*! Origin IP address family (e.g. "IP4" or "IP6") */ - char *family; - /*! Origin address. Can be an IP address or FQDN */ - char *addr; - } o_line; - /*! SDP Session name */ - char *s_line; - /*! SDP top-level connection information */ - struct ast_sdp_c_line c_line; - /*! SDP timing information */ - struct ast_sdp_t_line t_line; - /*! SDP top-level attributes */ - struct ast_sdp_a_line_vector a_lines; - /*! SDP media streams */ - AST_VECTOR(, struct ast_sdp_m_line) m_lines; -}; - -/*! - * \brief Allocate a new SDP. - * - * \note This does not perform any initialization. - * - * \retval NULL FAIL - * \retval non-NULL New SDP - */ -struct ast_sdp *ast_sdp_alloc(void); - -/*! - * \brief Free an SDP and all its constituent parts - */ -void ast_sdp_free(struct ast_sdp *dead); - -#endif /* _SDP_PRIV_H */ diff --git a/include/asterisk/sdp_state.h b/include/asterisk/sdp_state.h index b5e44179e..ec9d502e2 100644 --- a/include/asterisk/sdp_state.h +++ b/include/asterisk/sdp_state.h @@ -19,19 +19,34 @@ #ifndef _ASTERISK_SDP_STATE_H #define _ASTERISK_SDP_STATE_H +#include "asterisk/stream.h" +#include "asterisk/sdp_options.h" + struct ast_sdp_state; -struct ast_sdp_options; -struct ast_stream_topology; +struct ast_sockaddr; +struct ast_udptl; +struct ast_control_t38_parameters; /*! * \brief Allocate a new SDP state * + * \details * SDP state keeps tabs on everything SDP-related for a media session. * Most SDP operations will require the state to be provided. * Ownership of the SDP options is taken on by the SDP state. * A good strategy is to call this during session creation. + * + * \param topology Initial stream topology to offer. + * NULL if we are going to be the answerer. We can always + * update the local topology later if it turns out we need + * to be the offerer. + * \param options SDP options for the duration of the session. + * + * \retval SDP state struct + * \retval NULL on failure */ -struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *streams, struct ast_sdp_options *options); +struct ast_sdp_state *ast_sdp_state_alloc(struct ast_stream_topology *topology, + struct ast_sdp_options *options); /*! * \brief Free the SDP state. @@ -45,14 +60,286 @@ void ast_sdp_state_free(struct ast_sdp_state *sdp_state); * * Stream numbers correspond to the streams in the topology of the associated channel */ -struct ast_rtp_instance *ast_sdp_state_get_rtp_instance(struct ast_sdp_state *sdp_state, int stream_index); +struct ast_rtp_instance *ast_sdp_state_get_rtp_instance(const struct ast_sdp_state *sdp_state, + int stream_index); + +/*! + * \brief Get the associated UDPTL instance for a particular stream on the SDP state. + * + * Stream numbers correspond to the streams in the topology of the associated channel + */ +struct ast_udptl *ast_sdp_state_get_udptl_instance(const struct ast_sdp_state *sdp_state, + int stream_index); + +/*! + * \brief Get the global connection address on the SDP state. + */ +const struct ast_sockaddr *ast_sdp_state_get_connection_address(const struct ast_sdp_state *sdp_state); + +/*! + * \brief Get the connection address for a particular stream. + * + * \param sdp_state + * \param stream_index The particular stream to get the connection address of + * \param address[out] A place to store the address in + * + * \retval 0 Success + * + * \note + * Stream numbers correspond to the streams in the topology of the associated channel + */ +int ast_sdp_state_get_stream_connection_address(const struct ast_sdp_state *sdp_state, + int stream_index, struct ast_sockaddr *address); /*! * \brief Get the joint negotiated streams based on local and remote capabilities. * * If this is called prior to receiving a remote SDP, then this will just mirror * the local configured endpoint capabilities. + * + * \note Cannot return NULL. It is a BUG if it does. + */ +const struct ast_stream_topology *ast_sdp_state_get_joint_topology( + const struct ast_sdp_state *sdp_state); + +/*! + * \brief Get the local topology + * + * \note Cannot return NULL. It is a BUG if it does. + */ +const struct ast_stream_topology *ast_sdp_state_get_local_topology( + const struct ast_sdp_state *sdp_state); + +/*! + * \brief Get the sdp_state options + * + */ +const struct ast_sdp_options *ast_sdp_state_get_options( + const struct ast_sdp_state *sdp_state); + + +/*! + * \brief Get the local SDP. + * + * \param sdp_state + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \note + * This function will return the last local SDP created if one were + * previously requested for the current negotiation. Otherwise it + * creates our SDP offer/answer depending on what role we are playing + * in the current negotiation. + */ +const struct ast_sdp *ast_sdp_state_get_local_sdp(struct ast_sdp_state *sdp_state); + +/*! + * \brief Get the local SDP Implementation. + * + * \param sdp_state + * + * \retval non-NULL Success + * \retval NULL Failure + * + * \note + * This function calls ast_sdp_state_get_local_sdp then translates it into + * the defined implementation. + * + * The return here is const. The use case for this is so that a channel can add + * the SDP to an outgoing message. The API user should not attempt to modify the SDP. + * SDP modification should only be done through the API. + * + * \since 15 + */ +const void *ast_sdp_state_get_local_sdp_impl(struct ast_sdp_state *sdp_state); + +/*! + * \brief Set the remote SDP + * + * \param sdp_state + * \param sdp + * + * \note It is assumed that the passed in SDP has been checked for sanity + * already. e.g., There are no syntax errors, a c= line is reachable for + * each m= line, etc... + * + * \retval 0 Success + * \retval non-0 Failure + * Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected. + * + * \since 15 + */ +int ast_sdp_state_set_remote_sdp(struct ast_sdp_state *sdp_state, const struct ast_sdp *sdp); + +/*! + * \brief Set the remote SDP from an Implementation + * + * \param sdp_state + * \param remote The implementation's representation of an SDP. + * + * \retval 0 Success + * \retval non-0 Failure + * Use ast_sdp_state_is_offer_rejected() to see if the SDP offer was rejected. + * + * \since 15 + */ +int ast_sdp_state_set_remote_sdp_from_impl(struct ast_sdp_state *sdp_state, const void *remote); + +/*! + * \brief Was the set remote offer rejected. + * \since 15.0.0 + * + * \param sdp_state + * + * \retval 0 if not rejected. + * \retval non-zero if rejected. + */ +int ast_sdp_state_is_offer_rejected(struct ast_sdp_state *sdp_state); + +/*! + * \brief Are we the SDP offerer. + * \since 15.0.0 + * + * \param sdp_state + * + * \retval 0 if we are not the offerer. + * \retval non-zero we are the offerer. + */ +int ast_sdp_state_is_offerer(struct ast_sdp_state *sdp_state); + +/*! + * \brief Are we the SDP answerer. + * \since 15.0.0 + * + * \param sdp_state + * + * \retval 0 if we are not the answerer. + * \retval non-zero we are the answerer. + */ +int ast_sdp_state_is_answerer(struct ast_sdp_state *sdp_state); + +/*! + * \brief Restart the SDP offer/answer negotiations. + * + * \param sdp_state + * + * \retval 0 Success + * \retval non-0 Failure + */ +int ast_sdp_state_restart_negotiations(struct ast_sdp_state *sdp_state); + +/*! + * \brief Update the local stream topology on the SDP state. + * + * \details + * Basically we are saving off any topology updates until we create the + * next SDP offer. Repeated updates merge with the previous updated + * topology. + * + * \param sdp_state + * \param topology The new stream topology. + * + * \retval 0 Success + * \retval non-0 Failure + * + * \since 15 + */ +int ast_sdp_state_update_local_topology(struct ast_sdp_state *sdp_state, struct ast_stream_topology *topology); + +/*! + * \brief Set the local address (IP address) to use for connection addresses + * + * \param sdp_state + * \param address The local address + * + * \note + * Passing NULL as an address will unset the explicit local connection address. + * + * \since 15 + */ +void ast_sdp_state_set_local_address(struct ast_sdp_state *sdp_state, struct ast_sockaddr *address); + +/*! + * \brief Set the connection address (IP address and port) to use for a specific stream + * + * \param sdp_state + * \param stream_index The stream to set the connection address for + * \param address The connection address + * + * \retval 0 Success + * + * \note + * Passing NULL as an address will unset the explicit local connection address. + * + * \since 15 + */ +int ast_sdp_state_set_connection_address(struct ast_sdp_state *sdp_state, int stream_index, + struct ast_sockaddr *address); + +/*! + * \since 15.0.0 + * \brief Set the global locally held state. + * + * \param sdp_state + * \param locally_held + */ +void ast_sdp_state_set_global_locally_held(struct ast_sdp_state *sdp_state, unsigned int locally_held); + +/*! + * \since 15.0.0 + * \brief Get the global locally held state. + * + * \param sdp_state + * + * \returns locally_held + */ +unsigned int ast_sdp_state_get_global_locally_held(const struct ast_sdp_state *sdp_state); + +/*! + * \since 15.0.0 + * \brief Set a stream to be held or unheld locally + * + * \param sdp_state + * \param stream_index The stream to set the held value for + * \param locally_held + */ +void ast_sdp_state_set_locally_held(struct ast_sdp_state *sdp_state, + int stream_index, unsigned int locally_held); + +/*! + * \since 15.0.0 + * \brief Get whether a stream is locally held or not + * + * \param sdp_state + * \param stream_index The stream to get the held state for + * + * \returns locally_held + */ +unsigned int ast_sdp_state_get_locally_held(const struct ast_sdp_state *sdp_state, + int stream_index); + +/*! + * \since 15.0.0 + * \brief Get whether a stream is remotely held or not + * + * \param sdp_state + * \param stream_index The stream to get the held state for + * + * \returns remotely_held + */ +unsigned int ast_sdp_state_get_remotely_held(const struct ast_sdp_state *sdp_state, + int stream_index); + +/*! + * \since 15.0.0 + * \brief Set the UDPTL session parameters + * + * \param sdp_state + * \param stream_index The stream to set the UDPTL session parameters for + * \param params */ -struct ast_stream_topology *ast_sdp_state_get_joint_topology(struct ast_sdp_state *sdp_state); +void ast_sdp_state_set_t38_parameters(struct ast_sdp_state *sdp_state, + int stream_index, struct ast_control_t38_parameters *params); #endif /* _ASTERISK_SDP_STATE_H */ diff --git a/include/asterisk/sdp_translator.h b/include/asterisk/sdp_translator.h index 62a875e0a..e1d51f0be 100644 --- a/include/asterisk/sdp_translator.h +++ b/include/asterisk/sdp_translator.h @@ -28,15 +28,15 @@ struct sdp; */ struct ast_sdp_translator_ops { /*! The SDP representation on which this translator operates */ - enum ast_sdp_options_repr repr; + enum ast_sdp_options_impl repr; /*! Allocate new translator private data for a translator */ void *(*translator_new)(void); /*! Free translator private data */ void (*translator_free)(void *translator_priv); /*! Convert the channel-native SDP into an internal Asterisk SDP */ - struct ast_sdp *(*to_sdp)(void *repr_sdp, void *translator_priv); + struct ast_sdp *(*to_sdp)(const void *repr_sdp, void *translator_priv); /*! Convert an internal Asterisk SDP into a channel-native SDP */ - void *(*from_sdp)(struct ast_sdp *sdp, void *translator_priv); + const void *(*from_sdp)(const struct ast_sdp *sdp, void *translator_priv); }; /*! @@ -72,7 +72,7 @@ void ast_sdp_unregister_translator(struct ast_sdp_translator_ops *ops); * \retval NULL FAIL * \retval non-NULL New SDP translator */ -struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_repr repr); +struct ast_sdp_translator *ast_sdp_translator_new(enum ast_sdp_options_impl repr); /*! * \brief Free an SDP translator @@ -87,7 +87,7 @@ void ast_sdp_translator_free(struct ast_sdp_translator *translator); * \retval NULL FAIL * \retval Non-NULL The translated SDP */ -struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator, void *native_sdp); +struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator, const void *native_sdp); /*! * \brief Translate an internal Asterisk SDP to a native SDP @@ -97,6 +97,7 @@ struct ast_sdp *ast_sdp_translator_to_sdp(struct ast_sdp_translator *translator, * \retval NULL FAIL * \retval non-NULL The translated SDP */ -void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator, struct ast_sdp *ast_sdp); +const void *ast_sdp_translator_from_sdp(struct ast_sdp_translator *translator, + const struct ast_sdp *ast_sdp); #endif /* _ASTERISK_SDP_TRANSLATOR_H */ diff --git a/include/asterisk/smoother.h b/include/asterisk/smoother.h index e63aa77bd..65ac88921 100644 --- a/include/asterisk/smoother.h +++ b/include/asterisk/smoother.h @@ -33,6 +33,7 @@ extern "C" { #define AST_SMOOTHER_FLAG_G729 (1 << 0) #define AST_SMOOTHER_FLAG_BE (1 << 1) +#define AST_SMOOTHER_FLAG_FORCED (1 << 2) /*! \name AST_Smoother */ diff --git a/include/asterisk/sorcery.h b/include/asterisk/sorcery.h index 896633816..bfb2c39ad 100644 --- a/include/asterisk/sorcery.h +++ b/include/asterisk/sorcery.h @@ -392,9 +392,9 @@ int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface); * \retval non-NULL success * \retval NULL if allocation failed */ -struct ast_sorcery *__ast_sorcery_open(const char *module); +struct ast_sorcery *__ast_sorcery_open(const char *module, const char *file, int line, const char *func); -#define ast_sorcery_open() __ast_sorcery_open(AST_MODULE) +#define ast_sorcery_open() __ast_sorcery_open(AST_MODULE, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Retrieves an existing sorcery instance by module name @@ -1280,8 +1280,13 @@ int ast_sorcery_is_stale(const struct ast_sorcery *sorcery, void *object); * \brief Decrease the reference count of a sorcery structure * * \param sorcery Pointer to a sorcery structure + * + * \note Prior to 16.0.0 this was a function which had to be used. + * Now you can use any variant of ao2_cleanup or ao2_ref to + * release a reference. */ -void ast_sorcery_unref(struct ast_sorcery *sorcery); +#define ast_sorcery_unref(sorcery) \ + ao2_cleanup(sorcery) /*! * \brief Get the unique identifier of a sorcery object diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h index e131833a9..8ef2bda1c 100644 --- a/include/asterisk/stasis_app.h +++ b/include/asterisk/stasis_app.h @@ -51,7 +51,6 @@ */ #include "asterisk/channel.h" -#include "asterisk/json.h" /*! @{ */ @@ -794,6 +793,38 @@ int stasis_app_control_remove_channel_from_bridge( struct stasis_app_control *control, struct ast_bridge *bridge); /*! + * \brief Initialize bridge features into a channel control + * + * \note Bridge features on a control are destroyed after each bridge session, + * so new features need to be initialized before each bridge add. + * + * \param control Control in which to store the features + * + * \return non-zero on failure + * \return zero on success + */ +int stasis_app_control_bridge_features_init( + struct stasis_app_control *control); + +/*! + * \brief Set whether DTMF from the channel is absorbed instead of passing through to the bridge + * + * \param control Control whose channel should have its DTMF absorbed when bridged + * \param absorb Whether DTMF should be absorbed (1) instead of passed through (0). + */ +void stasis_app_control_absorb_dtmf_in_bridge( + struct stasis_app_control *control, int absorb); + +/*! + * \brief Set whether audio from the channel is muted instead of passing through to the bridge + * + * \param control Control whose channel should have its audio muted when bridged + * \param mute Whether audio should be muted (1) instead of passed through (0). + */ +void stasis_app_control_mute_in_bridge( + struct stasis_app_control *control, int mute); + +/*! * \since 12 * \brief Gets the bridge currently associated with a control object. * diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index deb79b0d0..4843617db 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -22,7 +22,6 @@ #include "asterisk/stringfields.h" #include "asterisk/stasis.h" -#include "asterisk/json.h" #include "asterisk/channel.h" /*! \addtogroup StasisTopicsAndMessages diff --git a/include/asterisk/stasis_endpoints.h b/include/asterisk/stasis_endpoints.h index 539f270cf..2fbe5f4b7 100644 --- a/include/asterisk/stasis_endpoints.h +++ b/include/asterisk/stasis_endpoints.h @@ -28,7 +28,6 @@ */ #include "asterisk/endpoints.h" -#include "asterisk/json.h" #include "asterisk/stasis.h" #include "asterisk/stasis_cache_pattern.h" #include "asterisk/stringfields.h" diff --git a/include/asterisk/stasis_system.h b/include/asterisk/stasis_system.h index 274c02e49..55959063c 100644 --- a/include/asterisk/stasis_system.h +++ b/include/asterisk/stasis_system.h @@ -19,7 +19,6 @@ #ifndef _ASTERISK_STASIS_SYSTEM_H #define _ASTERISK_STASIS_SYSTEM_H -#include "asterisk/json.h" #include "asterisk/stasis.h" /*! diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h index 48ee88322..c2d5a8877 100644 --- a/include/asterisk/stream.h +++ b/include/asterisk/stream.h @@ -27,6 +27,7 @@ #define _AST_STREAM_H_ #include "asterisk/codec.h" +#include "asterisk/vector.h" /*! * \brief Forward declaration for a stream, as it is opaque @@ -44,29 +45,50 @@ struct ast_format_cap; struct ast_stream_topology; /*! + * \brief A mapping of two topologies. + */ +struct ast_stream_topology_map; + +typedef void (*ast_stream_data_free_fn)(void *); + +/*! * \brief States that a stream may be in */ enum ast_stream_state { - /*! - * \brief Set when the stream has been removed - */ - AST_STREAM_STATE_REMOVED = 0, - /*! - * \brief Set when the stream is sending and receiving media - */ - AST_STREAM_STATE_SENDRECV, - /*! - * \brief Set when the stream is sending media only - */ - AST_STREAM_STATE_SENDONLY, - /*! - * \brief Set when the stream is receiving media only - */ - AST_STREAM_STATE_RECVONLY, - /*! - * \brief Set when the stream is not sending OR receiving media - */ - AST_STREAM_STATE_INACTIVE, + /*! + * \brief Set when the stream has been removed/declined + */ + AST_STREAM_STATE_REMOVED = 0, + /*! + * \brief Set when the stream is sending and receiving media + */ + AST_STREAM_STATE_SENDRECV, + /*! + * \brief Set when the stream is sending media only + */ + AST_STREAM_STATE_SENDONLY, + /*! + * \brief Set when the stream is receiving media only + */ + AST_STREAM_STATE_RECVONLY, + /*! + * \brief Set when the stream is not sending OR receiving media + */ + AST_STREAM_STATE_INACTIVE, +}; + +/*! + * \brief Stream data slots + */ +enum ast_stream_data_slot { + /*! + * \brief Data slot for RTP instance + */ + AST_STREAM_DATA_RTP_CODECS = 0, + /*! + * \brief Controls the size of the data pointer array + */ + AST_STREAM_DATA_SLOT_MAX }; /*! @@ -99,13 +121,17 @@ void ast_stream_free(struct ast_stream *stream); * \brief Create a deep clone of an existing stream * * \param stream The existing stream + * \param Optional name for cloned stream. If NULL, then existing stream's name is copied. * * \retval non-NULL success * \retval NULL failure * + * \note Opaque data pointers set with ast_stream_set_data() are not part + * of the deep clone. We have no way to clone the data. + * * \since 15 */ -struct ast_stream *ast_stream_clone(const struct ast_stream *stream); +struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char *name); /*! * \brief Get the name of a stream @@ -202,6 +228,45 @@ void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state const char *ast_stream_state2str(enum ast_stream_state state); /*! + * \brief Convert a string to a stream state + * + * \param str The string to convert + * + * \return The stream state + * + * \since 15.0.0 + */ +enum ast_stream_state ast_stream_str2state(const char *str); + +/*! + * \brief Get the opaque stream data + * + * \param stream The media stream + * \param slot The data slot to retrieve + * + * \retval non-NULL success + * \retval NULL failure + * + * \since 15 + */ +void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot); + +/*! + * \brief Set the opaque stream data + * + * \param stream The media stream + * \param slot The data slot to set + * \param data Opaque data + * \param data_free_fn Callback to free data when stream is freed. May be NULL for no action. + * + * \return data + * + * \since 15 + */ +void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot, + void *data, ast_stream_data_free_fn data_free_fn); + +/*! * \brief Get the position of the stream in the topology * * \param stream The media stream @@ -236,6 +301,20 @@ struct ast_stream_topology *ast_stream_topology_clone( const struct ast_stream_topology *topology); /*! + * \brief Compare two stream topologies to see if they are equal + * + * \param left The left topology + * \param right The right topology + * + * \retval 1 topologies are equivalent + * \retval 0 topologies differ + * + * \since 15 + */ +int ast_stream_topology_equal(const struct ast_stream_topology *left, + const struct ast_stream_topology *right); + +/*! * \brief Destroy a stream topology * * \param topology The topology of streams @@ -305,11 +384,30 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology, unsigned int position, struct ast_stream *stream); /*! + * \brief Delete a specified stream from the given topology. + * \since 15.0.0 + * + * \param topology The topology of streams. + * \param position The topology position to delete. + * + * \note Deleting a stream will completely remove it from the topology + * as if it never existed in it. i.e., Any following stream positions + * will shift down so there is no gap. + * + * \retval 0 on success. + * \retval -1 on failure. + * + * \return Nothing + */ +int ast_stream_topology_del_stream(struct ast_stream_topology *topology, + unsigned int position); + +/*! * \brief A helper function that, given a format capabilities structure, * creates a topology and separates the media types in format_cap into * separate streams. * - * \param caps The format capabilities structure + * \param caps The format capabilities structure (NULL creates an empty topology) * * \retval non-NULL success * \retval NULL failure @@ -318,7 +416,7 @@ int ast_stream_topology_set_stream(struct ast_stream_topology *topology, * since a new format capabilities structure is created for each media type. * * \note Each stream will have its name set to the corresponding media type. - * For example: "AST_MEDIA_TYPE_AUDIO". + * For example: "audio". * * \note Each stream will be set to the sendrecv state. * @@ -328,7 +426,26 @@ struct ast_stream_topology *ast_stream_topology_create_from_format_cap( struct ast_format_cap *cap); /*! - * \brief Gets the first stream of a specific type from the topology + * \brief Create a format capabilities structure representing the topology. + * + * \details + * A helper function that, given a stream topology, creates a format + * capabilities structure containing all formats from all active streams. + * + * \param topology The topology of streams + * + * \retval non-NULL success + * \retval NULL failure + * + * \note The stream topology is NOT altered by this function. + * + * \since 15 + */ +struct ast_format_cap *ast_format_cap_from_stream_topology( + struct ast_stream_topology *topology); + +/*! + * \brief Gets the first active stream of a specific type from the topology * * \param topology The topology of streams * \param type The media type @@ -342,4 +459,42 @@ struct ast_stream *ast_stream_topology_get_first_stream_by_type( const struct ast_stream_topology *topology, enum ast_media_type type); +/*! + * \brief Map a given topology's streams to the given types. + * + * \note The given vectors in which mapping values are placed are reset by + * this function. This means if those vectors already contain mapping + * values they will be lost. + * + * \param topology The topology to map + * \param types The media types to be mapped + * \param v0 Index mapping of topology to types + * \param v1 Index mapping of types to topology + * + * \since 15 + */ +void ast_stream_topology_map(const struct ast_stream_topology *topology, + struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1); + +/*! + * \brief Get the stream group that a stream is part of + * + * \param stream The stream + * + * \return the numerical stream group (-1 if not in a group) + * + * \since 15.2.0 + */ +int ast_stream_get_group(const struct ast_stream *stream); + +/*! + * \brief Set the stream group for a stream + * + * \param stream The stream + * \param group The group the stream is part of + * + * \since 15.2.0 + */ +void ast_stream_set_group(struct ast_stream *stream, int group); + #endif /* _AST_STREAM_H */ diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h index eb5b4e43c..963519dc7 100644 --- a/include/asterisk/strings.h +++ b/include/asterisk/strings.h @@ -26,6 +26,7 @@ /* #define DEBUG_OPAQUE */ #include <ctype.h> +#include <limits.h> #include "asterisk/utils.h" #include "asterisk/threadstorage.h" @@ -1174,6 +1175,19 @@ char *ast_tech_to_upper(char *dev_str), ) /*! + * \brief Restrict hash value range + * + * \details + * Hash values used all over asterisk are expected to be non-negative + * (signed) int values. This function restricts an unsigned int hash + * value to the positive half of the (signed) int values. + */ +static force_inline int attribute_pure ast_str_hash_restrict(unsigned int hash) +{ + return (int) (hash & (unsigned int) INT_MAX); +} + +/*! * \brief Compute a hash value on a string * * This famous hash algorithm was written by Dan Bernstein and is @@ -1183,20 +1197,21 @@ char *ast_tech_to_upper(char *dev_str), */ static force_inline int attribute_pure ast_str_hash(const char *str) { - int hash = 5381; + unsigned int hash = 5381; - while (*str) - hash = hash * 33 ^ *str++; + while (*str) { + hash = hash * 33 ^ (unsigned char) *str++; + } - return abs(hash); + return ast_str_hash_restrict(hash); } /*! * \brief Compute a hash value on a string * * \param[in] str The string to add to the hash - * \param[in] hash The hash value to add to - * + * \param[in] seed The hash value to start with + * * \details * This version of the function is for when you need to compute a * string hash of more than one string. @@ -1206,12 +1221,15 @@ static force_inline int attribute_pure ast_str_hash(const char *str) * * \sa http://www.cse.yorku.ca/~oz/hash.html */ -static force_inline int ast_str_hash_add(const char *str, int hash) +static force_inline int ast_str_hash_add(const char *str, int seed) { - while (*str) - hash = hash * 33 ^ *str++; + unsigned int hash = (unsigned int) seed; + + while (*str) { + hash = hash * 33 ^ (unsigned char) *str++; + } - return abs(hash); + return ast_str_hash_restrict(hash); } /*! @@ -1223,13 +1241,13 @@ static force_inline int ast_str_hash_add(const char *str, int hash) */ static force_inline int attribute_pure ast_str_case_hash(const char *str) { - int hash = 5381; + unsigned int hash = 5381; while (*str) { - hash = hash * 33 ^ tolower(*str++); + hash = hash * 33 ^ (unsigned char) tolower(*str++); } - return abs(hash); + return ast_str_hash_restrict(hash); } /*! @@ -1365,4 +1383,24 @@ char *ast_generate_random_string(char *buf, size_t size); */ int ast_strings_match(const char *left, const char *op, const char *right); +/*! + * \brief Read lines from a string buffer + * \since 13.18.0 + * + * \param buffer [IN/OUT] A pointer to a char * string with either Unix or Windows line endings + * + * \return The "next" line + * + * \warning The original string and *buffer will be modified. + * + * \details + * Both '\n' and '\r\n' are treated as single delimiters but consecutive occurrances of + * the delimiters are NOT considered to be a single delimiter. This preserves blank + * lines in the input. + * + * MacOS line endings ('\r') are not supported at this time. + * + */ +char *ast_read_line_from_buffer(char **buffer); + #endif /* _ASTERISK_STRINGS_H */ diff --git a/include/asterisk/test.h b/include/asterisk/test.h index 49731feb6..90e772cbc 100644 --- a/include/asterisk/test.h +++ b/include/asterisk/test.h @@ -241,6 +241,14 @@ struct ast_test_info { * \note The description must not end with a newline. */ const char *description; + /*! + * \brief Only run if explicitly named + * + * \details + * Run this test only if it's explicitly named on the command line. + * Do NOT run it as part of an execute category or execute all command. + */ + unsigned int explicit_only; }; #ifdef TEST_FRAMEWORK diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index 423d73b26..0a12b1d8a 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -622,7 +622,13 @@ int __ast_vasprintf(char **ret, const char *fmt, va_list ap, const char *file, i DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1); - if ((res = vasprintf(ret, fmt, ap)) == -1) { + res = vasprintf(ret, fmt, ap); + if (res < 0) { + /* + * *ret is undefined so set to NULL to ensure it is + * initialized to something useful. + */ + *ret = NULL; MALLOC_FAILURE_MSG; } diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h index 83732e7c8..8bd1cefef 100644 --- a/include/asterisk/vector.h +++ b/include/asterisk/vector.h @@ -48,6 +48,12 @@ size_t current; \ } +/*! \brief Integer vector definition */ +AST_VECTOR(ast_vector_int, int); + +/*! \brief String vector definition */ +AST_VECTOR(ast_vector_string, char *); + /*! * \brief Define a vector structure with a read/write lock * @@ -88,6 +94,26 @@ }) /*! + * \brief Steal the elements from a vector and reinitialize. + * + * \param vec Vector to operate on. + * + * This allows you to use vector.h to construct a list and use the + * data as a bare array. + * + * \note The stolen array must eventually be released using ast_free. + * + * \warning AST_VECTOR_SIZE and AST_VECTOR_MAX_SIZE are both reset + * to 0. If either are needed they must be saved to a local + * variable before stealing the elements. + */ +#define AST_VECTOR_STEAL_ELEMENTS(vec) ({ \ + typeof((vec)->elems) __elems = (vec)->elems; \ + AST_VECTOR_INIT((vec), 0); \ + (__elems); \ +}) + +/*! * \brief Initialize a vector with a read/write lock * * If \a size is 0, then no space will be allocated until the vector is @@ -241,6 +267,29 @@ }) /*! + * \brief Default a vector up to size with the given value. + * + * \note If a size of 0 is given then all elements in the given vector are set. + * \note The vector will grow to the given size if needed. + * + * \param vec Vector to default. + * \param size The number of elements to default + * \param value The default value to set each element to + */ +#define AST_VECTOR_DEFAULT(vec, size, value) ({ \ + int res = 0; \ + typeof((size)) __size = (size) ? (size) : AST_VECTOR_SIZE(vec); \ + size_t idx; \ + for (idx = 0; idx < __size; ++idx) { \ + res = AST_VECTOR_REPLACE(vec, idx, value); \ + if (res == -1) { \ + break; \ + } \ + } \ + res; \ +}) + +/*! * \brief Insert an element at a specific position in a vector, growing the vector if needed. * * \param vec Vector to insert into. @@ -278,27 +327,31 @@ * \brief Add an element into a sorted vector * * \param vec Sorted vector to add to. - * \param elem Element to insert. + * \param elem Element to insert. Must not be an array type. * \param cmp A strcmp compatible compare function. * * \return 0 on success. * \return Non-zero on failure. * * \warning Use of this macro on an unsorted vector will produce unpredictable results + * \warning 'elem' must not be an array type so passing 'x' where 'x' is defined as + * 'char x[4]' will fail to compile. However casting 'x' as 'char *' does + * result in a value that CAN be used. */ #define AST_VECTOR_ADD_SORTED(vec, elem, cmp) ({ \ int res = 0; \ size_t __idx = (vec)->current; \ + typeof(elem) __elem = (elem); \ do { \ if (__make_room((vec)->current, vec) != 0) { \ res = -1; \ break; \ } \ - while (__idx > 0 && (cmp((vec)->elems[__idx - 1], elem) > 0)) { \ + while (__idx > 0 && (cmp((vec)->elems[__idx - 1], __elem) > 0)) { \ (vec)->elems[__idx] = (vec)->elems[__idx - 1]; \ __idx--; \ } \ - (vec)->elems[__idx] = elem; \ + (vec)->elems[__idx] = __elem; \ (vec)->current++; \ } while (0); \ res; \ @@ -518,6 +571,14 @@ #define AST_VECTOR_SIZE(vec) (vec)->current /*! + * \brief Get the maximum number of elements the vector can currently hold. + * + * \param vec Vector to query. + * \return Maximum number of elements the vector can currently hold. + */ +#define AST_VECTOR_MAX_SIZE(vec) (vec)->max + +/*! * \brief Reset vector. * * \param vec Vector to reset. @@ -553,6 +614,42 @@ }) /*! + * \brief Get the nth index from a vector that matches the given comparison + * + * \param vec Vector to get from. + * \param nth The nth index to find + * \param value Value to pass into comparator. + * \param cmp Comparator function/macros (called as \c cmp(elem, value)) + * + * \return a pointer to the element that was found or NULL + */ +#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp) ({ \ + int res = -1; \ + size_t idx; \ + typeof(nth) __nth = (nth); \ + typeof(value) __value = (value); \ + for (idx = 0; idx < (vec)->current; ++idx) { \ + if (cmp((vec)->elems[idx], __value) && !(--__nth)) { \ + res = (int)idx; \ + break; \ + } \ + } \ + res; \ +}) + +/*! + * \brief Get the 1st index from a vector that matches the given comparison + * + * \param vec Vector to get from. + * \param value Value to pass into comparator. + * \param cmp Comparator function/macros (called as \c cmp(elem, value)) + * + * \return a pointer to the element that was found or NULL + */ +#define AST_VECTOR_GET_INDEX(vec, value, cmp) \ + AST_VECTOR_GET_INDEX_NTH(vec, 1, value, cmp) + +/*! * \brief Get an element from a vector that matches the given comparison * * \param vec Vector to get from. diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h index 063e8c0b3..ab7b630a2 100644 --- a/include/asterisk/xml.h +++ b/include/asterisk/xml.h @@ -246,10 +246,5 @@ struct ast_xml_node *ast_xml_xpath_get_first_result(struct ast_xml_xpath_results */ struct ast_xml_xpath_results *ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str); -/* Features using ast_xml_ */ -#ifdef HAVE_LIBXML2 -#define AST_XML_DOCS -#endif - #endif /* _ASTERISK_XML_H */ |