diff --git a/include/librist/receiver.h b/include/librist/receiver.h index dd75d93853fdf9b1d9d04cd8eb6de06c040b13da..4315bf390fc641ab03cc5d43bbacaab6c74e3742 100644 --- a/include/librist/receiver.h +++ b/include/librist/receiver.h @@ -102,6 +102,29 @@ typedef int (*receiver_data_callback2_t)(void *arg, struct rist_data_block *data RIST_DEPRECATED RIST_API int rist_receiver_data_callback_set(struct rist_ctx *ctx, receiver_data_callback_t, void *arg); RIST_API int rist_receiver_data_callback_set2(struct rist_ctx *ctx, receiver_data_callback2_t, void *arg); +/** + * @brief Session Timeout callback function + * + * This function will notify the app that a session timeout has occured + * + * @param arg optional user data set via rist_session_timeout_callback_set + * @param flow_id id of the flow that is timing out + * @return int, ignored. + */ +typedef int (*receiver_session_timeout_callback_t)(void *arg, uint32_t flow_id); + +/** + * @brief Enable Session Timeout callback channel + * + * Call to enable session timeout callback channel. + * + * @param ctx RIST receiver context + * @param session_timeout_callback The function that will be called when a session times out + * @param arg the extra argument passed to the `session_timeout_callback` + * @return 0 on success, -1 on error + */ +RIST_API int rist_receiver_session_timeout_callback_set(struct rist_ctx *ctx, receiver_session_timeout_callback_t, void *arg); + /** * @brief Free rist data block * diff --git a/meson.build b/meson.build index 05d00b32da70a86d3bb15936f8d06f6ceea62fac..d4077dfda6f22f9e3400e3fb28ada405ad1863af 100755 --- a/meson.build +++ b/meson.build @@ -4,7 +4,7 @@ # SPDX-License-Identifier: BSD-2-Clause project('libRIST', 'c', - version: '0.2.11', + version: '0.2.12', default_options: ['c_std=c99', 'warning_level=3', 'libdir=lib'], meson_version: '>= 0.51.0') @@ -17,9 +17,9 @@ cdata = configuration_data() #If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0. #If any interfaces have been added since the last public release, then increment age. #If any interfaces have been removed or changed since the last public release, then set age to 0. -librist_abi_current = 8 +librist_abi_current = 9 librist_abi_revision = 0 -librist_abi_age = 4 +librist_abi_age = 5 librist_soversion = librist_abi_current - librist_abi_age librist_version = '@0@.@1@.@2@'.format(librist_abi_current - librist_abi_age, librist_abi_age, librist_abi_revision) @@ -30,7 +30,7 @@ librist_version = '@0@.@1@.@2@'.format(librist_abi_current - librist_abi_age, li #PATCH not used (doesn't make sense for API version, remains here for backwards compat) librist_api_version_major = 4 -librist_api_version_minor = 5 +librist_api_version_minor = 6 librist_api_version_patch = 0 librist_src_root = meson.current_source_dir() diff --git a/src/rist-common.c b/src/rist-common.c index 2695bbeed6b759dee9665de2ab6a29b2786ea0f1..61af9711a3a4dde16af2d9e43e0be0c2f049eaf6 100755 --- a/src/rist-common.c +++ b/src/rist-common.c @@ -3951,6 +3951,9 @@ PTHREAD_START_FUNC(receiver_pthread_protocol, arg) rist_log_priv(&ctx->common, RIST_LOG_INFO, "\t************** Session Timeout after %" PRIu64 "s of no data, deleting flow with id %"PRIu32" ***************\n", flow_age / RIST_CLOCK / 1000, f->flow_id); + if (ctx->receiver_session_timeout_callback) { + ctx->receiver_session_timeout_callback(ctx->receiver_session_timeout_callback_argument, f->flow_id); + } pthread_mutex_unlock(&f->mutex); pthread_mutex_lock(&ctx->common.peerlist_lock); for (size_t i = 0; i < f->peer_lst_len; i++) { diff --git a/src/rist-private.h b/src/rist-private.h index 58fb36c3291618e7d03b3be43bcfbbacc079476e..e8f109bfd35768289a6a87b99c1cdc064aecb22e 100755 --- a/src/rist-private.h +++ b/src/rist-private.h @@ -366,6 +366,10 @@ struct rist_receiver { void *receiver_data_callback_argument; int receiver_data_ready_notify_fd; + /* Receiver session timeout callback */ + receiver_session_timeout_callback_t receiver_session_timeout_callback; + void *receiver_session_timeout_callback_argument; + /* Receiver thread variables */ bool protocol_running; pthread_t receiver_thread; diff --git a/src/rist.c b/src/rist.c index f79c5dc2a711c64f1e66bd3d6a93d1bb85f54fad..0cf7729a21ed65cfdfced004436e13fd9bbc5b13 100644 --- a/src/rist.c +++ b/src/rist.c @@ -296,6 +296,26 @@ int rist_receiver_data_callback_set2(struct rist_ctx *rist_ctx, return 0; } +int rist_receiver_session_timeout_callback_set(struct rist_ctx *rist_ctx, + receiver_session_timeout_callback_t session_timeout_callback, + void *arg) { + if (RIST_UNLIKELY(!rist_ctx)) { + rist_log_priv3(RIST_LOG_ERROR, + "ctx is null on rist_session_timeout_callback_set call!\n"); + return -1; + } + if (RIST_UNLIKELY(rist_ctx->mode != RIST_RECEIVER_MODE || + !rist_ctx->receiver_ctx)) { + rist_log_priv3(RIST_LOG_ERROR, "rist_receiver_session_timeout_callback_set call with " + "CTX not set up for receiving\n"); + return -1; + } + struct rist_receiver *ctx = rist_ctx->receiver_ctx; + ctx->receiver_session_timeout_callback = session_timeout_callback; + ctx->receiver_session_timeout_callback_argument = arg; + return 0; +} + /* Sender functions */ int rist_sender_create(struct rist_ctx **_ctx, enum rist_profile profile, uint32_t flow_id, struct rist_logging_settings *logging_settings) diff --git a/tools/ristreceiver.c b/tools/ristreceiver.c index ecbfbfc42e21a4e2ab6f6bbc76548b6e7170db1b..916eaa48e83c4d19dd204122cfb8fc31e30647b8 100644 --- a/tools/ristreceiver.c +++ b/tools/ristreceiver.c @@ -40,7 +40,7 @@ # define strtok_r strtok_s #endif -#define RISTRECEIVER_VERSION "2" +#define RISTRECEIVER_VERSION "3" #define MAX_INPUT_COUNT 20 #define MAX_OUTPUT_COUNT 20 @@ -86,6 +86,7 @@ static struct option long_options[] = { { "srpfile", required_argument, NULL, 'F' }, #endif { "config", required_argument, NULL, 'c' }, +{ "session-timeout-exit", no_argument, NULL, 'x' }, { "help", no_argument, NULL, 'h' }, { "help-url", no_argument, NULL, 'u' }, #if HAVE_PROMETHEUS_SUPPORT @@ -147,6 +148,7 @@ const char help_str[] = "Usage: %s [OPTIONS] \nWhere OPTIONS are:\n" " | --metrics-unix | Unix socket to expose metrics on |\n" #endif //HAVE_SOCK_UN_H #endif //HAVE_PROMETHEUS_SUPPORT +" -x | --session-timeout-exit | Exit on Session Timeout |\n" " -h | --help | Show this help |\n" " -u | --help-url | Show all the possible url options |\n" " * == mandatory value \n" @@ -170,6 +172,7 @@ struct rist_callback_object { int tun; int tun_mode; #endif + int session_timeout_exit; }; static inline void risttools_rtp_set_hdr(uint8_t *p_rtp, uint8_t i_type, uint16_t i_seqnum, uint32_t i_timestamp, uint32_t i_ssrc) @@ -421,6 +424,14 @@ struct ristreceiver_flow_cumulative_stats { struct ristreceiver_flow_cumulative_stats *stats_list; +static int session_timeout_callback(void *arg, uint32_t flow_id) { + struct rist_callback_object *callback_object = (void *) arg; + rist_log(&logging_settings, RIST_LOG_INFO, "Flow with id %"PRIu32" has timed out\n", flow_id); + if (callback_object->session_timeout_exit) + exit(1); + return 0; +} + static int cb_stats(void *arg, const struct rist_stats *stats_container) { rist_log(&logging_settings, RIST_LOG_INFO, "%s\n", stats_container->stats_json); if (stats_container->stats_type == RIST_STATS_RECEIVER_FLOW) @@ -559,7 +570,7 @@ int main(int argc, char *argv[]) rist_log(&logging_settings, RIST_LOG_INFO, "Starting ristreceiver version: %s libRIST library: %s API version: %s\n", LIBRIST_VERSION, librist_version(), librist_api_version()); - while ((c = getopt_long(argc, argv, "r:i:o:b:s:e:t:m:p:S:v:F:c:h:uM", long_options, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "r:i:o:b:s:e:t:m:p:S:v:F:c:h:uMx", long_options, &option_index)) != -1) { switch (c) { case 'i': inputurl = strdup(optarg); @@ -689,6 +700,9 @@ int main(int argc, char *argv[]) #endif cleanup_tools_config(yaml_config); break; + case 'x': + callback_object.session_timeout_exit = 1; + break; case 'h': /* Fall through */ default: @@ -758,6 +772,15 @@ int main(int argc, char *argv[]) exit(1); } + double api_version = strtod(librist_api_version(), NULL); + if (api_version > 4.5) + { + if (rist_receiver_session_timeout_callback_set(ctx, session_timeout_callback, (void *)&callback_object) == -1) { + rist_log(&logging_settings, RIST_LOG_ERROR, "Could not enable session timeout callback\n"); + exit(1); + } + } + #ifdef USE_TUN // Setup tun device if (oobtun) {