diff options
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | apps/app_confbridge.c | 18 | ||||
-rw-r--r-- | apps/app_queue.c | 1 | ||||
-rw-r--r-- | apps/confbridge/conf_config_parser.c | 4 | ||||
-rw-r--r-- | apps/confbridge/include/confbridge.h | 2 | ||||
-rw-r--r-- | configs/samples/confbridge.conf.sample | 6 | ||||
-rw-r--r-- | main/format.c | 22 | ||||
-rw-r--r-- | main/hashtab.c | 2 | ||||
-rw-r--r-- | res/res_pjsip.c | 6 |
9 files changed, 63 insertions, 5 deletions
@@ -12,6 +12,13 @@ --- Functionality changes from Asterisk 13.6.0 to Asterisk 13.7.0 ------------ ------------------------------------------------------------------------------ +ConfBridge +------------------ + * A new "timeout" user profile option has been added. This configures the number + of seconds that a participant may stay in the ConfBridge after joining. When + the time expires, the user is ejected from the conference and CONFBRIDGE_RESULT + is set to "TIMEOUT" on the channel. + chan_sip ------------------ * The websockets_enabled option has been added to the general section of diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 8045680e4..5976d39db 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -118,6 +118,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <value name="KICKED">The channel was kicked from the conference.</value> <value name="ENDMARKED">The channel left the conference as a result of the last marked user leaving.</value> <value name="DTMF">The channel pressed a DTMF sequence to exit the conference.</value> + <value name="TIMEOUT">The channel reached its configured timeout.</value> </variable> </variablelist> </description> @@ -1542,6 +1543,13 @@ static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user) return -1; } +static int user_timeout(struct ast_bridge_channel *bridge_channel, void *ignore) +{ + ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0); + pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "TIMEOUT"); + return -1; +} + static int conf_rec_name(struct confbridge_user *user, const char *conf_name) { char destdir[PATH_MAX]; @@ -1776,6 +1784,16 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) ast_autoservice_stop(chan); } + if (user.u_profile.timeout) { + ast_bridge_interval_hook(&user.features, + 0, + user.u_profile.timeout * 1000, + user_timeout, + NULL, + NULL, + AST_BRIDGE_HOOK_REMOVE_ON_PULL); + } + /* See if we need to automatically set this user as a video source or not */ handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER)); diff --git a/apps/app_queue.c b/apps/app_queue.c index 6dfb14356..5a8dcd246 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -6500,7 +6500,6 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, ringing); - ast_channel_unlock(qe->chan); ao2_lock(qe->parent); if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) { store_next_rr(qe, outgoing); diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index 6d6f7ab34..b8b1e2a9c 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -227,6 +227,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <configOption name="template"> <synopsis>When using the CONFBRIDGE dialplan function, use a user profile as a template for creating a new temporary profile</synopsis> </configOption> + <configOption name="timeout"> + <synopsis>Kick the user out of the conference after this many seconds. 0 means there is no timeout for the user.</synopsis> + </configOption> </configObject> <configObject name="bridge_profile"> <synopsis>A named profile to apply to specific bridges.</synopsis> @@ -2109,6 +2112,7 @@ int conf_load_config(void) aco_option_register(&cfg_info, "dsp_silence_threshold", ACO_EXACT, user_types, __stringify(DEFAULT_SILENCE_THRESHOLD), OPT_UINT_T, 0, FLDSET(struct user_profile, silence_threshold)); aco_option_register(&cfg_info, "dsp_talking_threshold", ACO_EXACT, user_types, __stringify(DEFAULT_TALKING_THRESHOLD), OPT_UINT_T, 0, FLDSET(struct user_profile, talking_threshold)); aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_JITTERBUFFER); + aco_option_register(&cfg_info, "timeout", ACO_EXACT, user_types, "0", OPT_UINT_T, 0, FLDSET(struct user_profile, timeout)); /* This option should only be used with the CONFBRIDGE dialplan function */ aco_option_register_custom(&cfg_info, "template", ACO_EXACT, user_types, NULL, user_template_handler, 0); diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h index 6f8439a9c..8d2dffb1c 100644 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -140,6 +140,8 @@ struct user_profile { unsigned int talking_threshold; /*! The time in ms of silence before a user is considered to be silent by the dsp. */ unsigned int silence_threshold; + /*! The time in ms the user may stay in the confbridge */ + unsigned int timeout; }; enum conf_sounds { diff --git a/configs/samples/confbridge.conf.sample b/configs/samples/confbridge.conf.sample index 860f1cb87..0419001eb 100644 --- a/configs/samples/confbridge.conf.sample +++ b/configs/samples/confbridge.conf.sample @@ -137,6 +137,12 @@ type=user ; This option is off by default. ;announcement=</path/to/file> ; Play a sound file to the user when they join the conference. +;timeout=3600 ; When set non-zero, this specifies the number of seconds that the participant + ; may stay in the conference before being automatically ejected. When the user + ; is ejected from the conference, the user's channel will have the CONFBRIDGE_RESULT + ; variable set to "TIMEOUT". A value of 0 indicates that there is no timeout. + ; Default: 0 + ; --- ConfBridge Bridge Profile Options --- [default_bridge] type=bridge diff --git a/main/format.c b/main/format.c index 8ac82f0ed..5bf38dfb2 100644 --- a/main/format.c +++ b/main/format.c @@ -302,6 +302,14 @@ const void *ast_format_attribute_get(const struct ast_format *format, const char { const struct ast_format_interface *interface = format->interface; + if (!interface) { + struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY); + if (format_interface) { + interface = format_interface->interface; + ao2_ref(format_interface, -1); + } + } + if (!interface || !interface->format_attribute_get) { return NULL; } @@ -330,11 +338,21 @@ struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, co void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str) { - if (!format->interface || !format->interface->format_generate_sdp_fmtp) { + const struct ast_format_interface *interface = format->interface; + + if (!interface) { + struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY); + if (format_interface) { + interface = format_interface->interface; + ao2_ref(format_interface, -1); + } + } + + if (!interface || !interface->format_generate_sdp_fmtp) { return; } - format->interface->format_generate_sdp_fmtp(format, payload, str); + interface->format_generate_sdp_fmtp(format, payload, str); } struct ast_codec *ast_format_get_codec(const struct ast_format *format) diff --git a/main/hashtab.c b/main/hashtab.c index 4b765979f..9b334d4a5 100644 --- a/main/hashtab.c +++ b/main/hashtab.c @@ -745,6 +745,8 @@ struct ast_hashtab_iter *ast_hashtab_start_write_traversal(struct ast_hashtab *t void ast_hashtab_end_traversal(struct ast_hashtab_iter *it) { + if (!it) + return; if (it->tab->do_locking) ast_rwlock_unlock(&it->tab->lock); free(it); diff --git a/res/res_pjsip.c b/res/res_pjsip.c index babbe7aaa..8e99c55d4 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -3155,9 +3155,11 @@ static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint, char errmsg[PJ_ERR_MSG_SIZE]; if (timeout > 0) { - pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(endpt), + int timers_cancelled = pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(endpt), req_wrapper->timeout_timer, TIMER_INACTIVE); - ao2_ref(req_wrapper, -1); + if (timers_cancelled > 0) { + ao2_ref(req_wrapper, -1); + } } /* Complain of failure to send the request. */ |