From: Jason Parker Date: Tue, 8 Jan 2013 19:09:11 +0000 (+0000) Subject: Multiple revisions 377136,377166,377212,377227,377241,377258,377261,377354,377382... X-Git-Tag: 10.12.0-digiumphones-rc2~3^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e653779927deb22be5a5514e56cdfa6e2ed3b65;p=thirdparty%2Fasterisk.git Multiple revisions 377136,377166,377212,377227,377241,377258,377261,377354,377382,377399,377432,377504,377510,377558,377592,377624,377656,377705,377709,377741,377772 ........ r377136 | rmudgett | 2012-12-03 14:33:08 -0600 (Mon, 03 Dec 2012) | 17 lines Cleanup core main on exit. * Cleanup time zones on exit. * Make exit clean/unclean report consistent for AMI and CLI in really_quit(). (issue ASTERISK-20649) Reported by: Corey Farrell Patches: core-cleanup-1_8-10.patch (license #5909) patch uploaded by Corey Farrell core-cleanup-11-trunk.patch (license #5909) patch uploaded by Corey Farrell Modified ........ Merged revisions 377135 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377166 | rmudgett | 2012-12-03 16:53:58 -0600 (Mon, 03 Dec 2012) | 15 lines Cleanup ast_run_atexits() atexits list. * Convert atexits list to a mutex instead of a rd/wr lock. The lock is only write locked. * Move CLI verbose Asterisk ending message to where AMI message is output in really_quit() to avoid further surprises about using stuff already shutdown. (issue ASTERISK-20649) Reported by: Corey Farrell ........ Merged revisions 377165 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377212 | rmudgett | 2012-12-04 16:31:02 -0600 (Tue, 04 Dec 2012) | 1 line confbridge: Update online XML documentation. ........ r377227 | rmudgett | 2012-12-04 18:49:53 -0600 (Tue, 04 Dec 2012) | 29 lines confbridge: Fix several small issues. * Made func_confbridge_helper() allow an empty value when setting options. You previously could not Set(CONFBRIDGE(user,pin)=) and clear the configured pin from the dialplan. * Made func_confbridge_helper() handle its datastore better if multiple threads attempt to set the first CONFBRIDGE option value on the channel. * Made the func_confbridge_helper() only output one diagnostic message concerning the option. * Made the bridge video_mode able to repeatedly change in the config file and CONFBRIDGE dialplan function. The video_mode option values are an enum and not independent of each other. * Made handle_cli_confbridge_show_bridge_profile() better handle the video_mode option. * Simplified datastore handling code in conf_find_user_profile() and conf_find_bridge_profile(). * Made parse_bridge(), parse_user(), and parse_menu() use var->file instead of CONFBRIDGE_CONFIG because the var could have been from an include file. (closes issue ASTERISK-20655) Reported by: Birger "WIMPy" Harzenetter ........ r377241 | rmudgett | 2012-12-04 20:09:13 -0600 (Tue, 04 Dec 2012) | 4 lines * Fix registering core show codecs/codec CLI commands twice. * Fix registering atexit format_attr_shutdown() more than once. ........ r377258 | file | 2012-12-05 10:49:33 -0600 (Wed, 05 Dec 2012) | 19 lines Fix a SIP request memory leak with TLS connections. During the TLS re-work in chan_sip some TLS specific code was moved into a separate function. This function operates on a copy of the incoming SIP request. This copy was never deinitialized causing a memory leak for each request processed. This function is now given a SIP request structure which it can use to copy the incoming request into. This reduces the amount of memory allocations done since the internal allocated components are reused between packets and also ensures the SIP request structure is deinitialized when the TLS connection is torn down. (closes issue ASTERISK-20763) Reported by: deti ........ Merged revisions 377257 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377261 | jrose | 2012-12-05 10:57:26 -0600 (Wed, 05 Dec 2012) | 15 lines res_srtp: Fix a crash caused by srtp_dealloc on an already dealloced session When srtp_create fails, the session may be dealloced or just not alloced. At the same time though, the session pointer might not be set to NULL in this process and attempting to srtp_dealloc it again will cause a segfault. This patch checks for failure of srtp_create and sets the session pointer to NULL if it fails. (closes issue ASTERISK-20499) Reported by: tootai Review: https://reviewboard.asterisk.org/r/2228/ ........ Merged revisions 377256 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377354 | rmudgett | 2012-12-06 17:56:45 -0600 (Thu, 06 Dec 2012) | 24 lines confbridge: Fix some resource leaks on conference teardown. * Made destroy_conference_bridge() destroy a missed ast_mutex_t and ast_cond_t. * Made join_conference_bridge() init the ast_mutex_t's and ast_cond_t so destroy_conference_bridge() can destroy them unconditionally. * Made join_conference_bridge() abort if the new conference could not be added to the conferences container. * Made leave_conference() discard any post-join actions if join_conference_bridge() had to abort early. * Made the join_conference_bridge() diagnostic messages better describe what happened. * Renamed leave_conference_bridge() to leave_conference() and made it only take a conference user pointer. The conference pointer was redundant. * Made conf_bridge_profile_copy() use struct copy instead of memcpy(). * No need to lock the conference in start_conf_record_thread() since all of the callers already have it locked. ........ r377382 | kmoore | 2012-12-07 15:58:21 -0600 (Fri, 07 Dec 2012) | 17 lines codec_dahdi: Fix output of "transcoder show" CLI command. In r306010 "Asterisk media architecture conversion - no more format bitfields", the logic for incrementing encoders and decoders when opening transcoder channels was changed without making the corresponding change when decrementing encoder / decoder channels. The result being that when a channel was destroyed, codec_dahdi couldn't properly tell if it was an encoder or decoder, and the default case is to assume it was a decoder. This could result in negative numbers for decoders in use like in: VOIP6*CLI> transcoder show 2/-2 encoders/decoders of 92 channels are in use. (closes issue ASTERISK-19921) Patch-by: Shaun Ruffell ........ r377399 | rmudgett | 2012-12-07 17:42:03 -0600 (Fri, 07 Dec 2012) | 5 lines MALLOC_DEBUG: Only wait if we want atexit allocation dumps. ........ Merged revisions 377398 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377432 | rmudgett | 2012-12-07 18:29:23 -0600 (Fri, 07 Dec 2012) | 14 lines Fix order of SIP allow/disallow in MySQL contrib script. Using the contrib sippeers.sql script to create the sippeers MySQL table would result in being unable to place calls if you set the disallow value to all. (closes issue ASTERISK-20756) Reported by: Andre Luis Patches: sippeers.patch patch uploaded by Andre Luis ........ Merged revisions 377431 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377504 | tilghman | 2012-12-09 19:24:41 -0600 (Sun, 09 Dec 2012) | 5 lines Remove some dead code and additionally handle a case that wasn't handled. ........ Merged revisions 377487 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377510 | tilghman | 2012-12-09 19:39:58 -0600 (Sun, 09 Dec 2012) | 16 lines Improve documentation by making all of the colors used readable, no matter what the background color is. Dark blue on a black background is unreadable, as is yellow on a light background. This patch turns on the bright attribute for colors when on a dark background and turns *off* the bright attribute when the -W command line option is used (indicating a _light_ background). This ensures that text is readable in both cases. Patch by: tilghman Review: https://reviewboard.asterisk.org/r/2224 ........ Merged revisions 377509 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377558 | igorg | 2012-12-09 23:04:36 -0600 (Sun, 09 Dec 2012) | 8 lines Fix crash on transfer initiated from insreeen menu on Unistim phones. Removed CDR-related code that moved to do_masquarade before. (closes issue ASTERISK-20417) Reported by: Rudolf Migalin ........ Merged revisions 377557 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377592 | igorg | 2012-12-10 00:41:47 -0600 (Mon, 10 Dec 2012) | 9 lines Fix codec mismatch Fix code to send in both rx and tx open stream messages correct codecs. Found that on phase 0/1 phones wrong codecs cause to no audio in some situations. (issue ASTERISK-20183) ........ Merged revisions 377591 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377624 | kmoore | 2012-12-10 08:40:26 -0600 (Mon, 10 Dec 2012) | 14 lines Handle Session-Expires less than local Min-SE in 200 OK Ensure that a call is immediately torn down if a Session-Expires value received in a 200 OK is less than the local Min-SE. This also prevents Asterisk from allowing calls with Session-Expires below the RFC4028-mandated minimum (90s). (closes issue ASTERISK-20653) Review: https://reviewboard.asterisk.org/r/2237/ Patch-by: Kinsey Moore ........ Merged revisions 377623 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377656 | kmoore | 2012-12-10 10:53:16 -0600 (Mon, 10 Dec 2012) | 14 lines Ensure ReceiveFax provides a CED tone via T.38 When using res_fax_digium, the T.38 CED tone was not being provided properly which would cause some incoming faxes to fail. This was not an issue with res_fax_spandsp since it does not strictly honor the send_ced flag and sends the CED tone whenever receiving a T.38 fax. (closes issue FAX-343) Reported-by: Benjamin Tietz Patch-by: Kinsey Moore ........ Merged revisions 377655 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377705 | rmudgett | 2012-12-10 18:32:40 -0600 (Mon, 10 Dec 2012) | 14 lines Cleanup dnsmgr on exit. * Cleanup dnsmgr thread and CLI commands on exit. (issue ASTERISK-20649) Reported by: Corey Farrell Patches: dnsmgr-cleanup-1_8.patch (license #5909) patch uploaded by Corey Farrell dnsmgr-cleanup-10-11-trunk.patch (license #5909) patch uploaded by Corey Farrell Modified ........ Merged revisions 377704 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377709 | rmudgett | 2012-12-10 19:00:05 -0600 (Mon, 10 Dec 2012) | 15 lines Cleanup event on exit. * Cleanup CLI commands on exit. * v10 only: Merged v1.8 -r374177 change to event.c missed in v10 -r374178. (issue ASTERISK-20649) Reported by: Corey Farrell Patches: event_shutdown-10-only.patch (license #5909) patch uploaded by Corey Farrell event_shutdown-1_8-11-trunk.patch (license #5909) patch uploaded by Corey Farrell ........ Merged revisions 377708 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377741 | rmudgett | 2012-12-10 20:11:29 -0600 (Mon, 10 Dec 2012) | 19 lines Cleanup indications on exit. * Made ast_unregister_indication_country() unlink the found tone zone before selecting a new default_tone_zone to make it impossible to select the tone zone being unregistered again. * Ringcadence is no longer parsed twice in store_config_tone_zone(). * Cleanup CLI commands and destroy default_tone_zone on exit. (issue ASTERISK-20649) Reported by: Corey Farrell Patches: indications-cleanup-all.patch (license #5909) patch uploaded by Corey Farrell Modified ........ Merged revisions 377740 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ r377772 | rmudgett | 2012-12-10 20:42:34 -0600 (Mon, 10 Dec 2012) | 13 lines Cleanup logger on exit. * Cleanup CLI commands, destroy verbosers and logchannels lists on exit. (issue ASTERISK-20649) Reported by: Corey Farrell Patches: logger-cleanup-all.patch (license #5909) patch uploaded by Corey Farrell Modified ........ Merged revisions 377771 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 377136,377166,377212,377227,377241,377258,377261,377354,377382,377399,377432,377504,377510,377558,377592,377624,377656,377705,377709,377741,377772 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@378659 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/addons/cdr_mysql.c b/addons/cdr_mysql.c index 445f9e3d05..b87d8c6aa1 100644 --- a/addons/cdr_mysql.c +++ b/addons/cdr_mysql.c @@ -430,6 +430,9 @@ static int my_load_module(int reload) int res; struct ast_config *cfg; struct ast_variable *var; + /* CONFIG_STATUS_FILEUNCHANGED is impossible when config_flags is always 0, + * and it has to be zero, so a reload can be sent to tell the driver to + * rescan the table layout. */ struct ast_flags config_flags = { 0 }; struct column *entry; char *temp; @@ -445,11 +448,13 @@ static int my_load_module(int reload) * have changed, which is not detectable by config file change detection, * but should still cause the configuration to be re-parsed. */ cfg = ast_config_load(config, config_flags); - if (!cfg) { + if (cfg == CONFIG_STATUS_FILEMISSING) { ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config); return AST_MODULE_LOAD_SUCCESS; - } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) - return AST_MODULE_LOAD_SUCCESS; + } else if (cfg == CONFIG_STATUS_FILEINVALID) { + ast_log(LOG_ERROR, "Unable to load configuration file '%s'\n", config); + return AST_MODULE_LOAD_DECLINE; + } if (reload) { AST_RWLIST_WRLOCK(&columns); diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 22e1cd0e22..df72400809 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -60,34 +60,48 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/test.h" /*** DOCUMENTATION - - - Conference bridge application. - - - - The conference number - - - The bridge profile name from confbridge.conf. When left blank, a dynamically built bridge profile created by the CONFBRIDGE dialplan function is searched for on the channel and used. If no dynamic profile is present, the 'default_bridge' profile found in confbridge.conf is used. - It is important to note that while user profiles may be unique for each participant, mixing bridge profiles on a single conference is _NOT_ recommended and will produce undefined results. - - - The user profile name from confbridge.conf. When left blank, a dynamically built user profile created by the CONFBRIDGE dialplan function is searched for on the channel and used. If no dynamic profile is present, the 'default_user' profile found in confbridge.conf is used. - - - The name of the DTMF menu in confbridge.conf to be applied to this channel. No menu is applied by default if this option is left blank. - - - - Enters the user into a specified conference bridge. The user can exit the conference by hangup or DTMF menu option. - - - ConfBridge - CONFBRIDGE - CONFBRIDGE_INFO - - + + + Conference bridge application. + + + + Name of the conference bridge. You are not limited to just + numbers. + + + The bridge profile name from confbridge.conf. When left blank, + a dynamically built bridge profile created by the CONFBRIDGE dialplan + function is searched for on the channel and used. If no dynamic + profile is present, the 'default_bridge' profile found in + confbridge.conf is used. + It is important to note that while user profiles may be unique + for each participant, mixing bridge profiles on a single conference + is _NOT_ recommended and will produce undefined results. + + + The user profile name from confbridge.conf. When left blank, + a dynamically built user profile created by the CONFBRIDGE dialplan + function is searched for on the channel and used. If no dynamic + profile is present, the 'default_user' profile found in + confbridge.conf is used. + + + The name of the DTMF menu in confbridge.conf to be applied to + this channel. No menu is applied by default if this option is left + blank. + + + + Enters the user into a specified conference bridge. The user can + exit the conference by hangup or DTMF menu option. + + + ConfBridge + CONFBRIDGE + CONFBRIDGE_INFO + + Set a custom dynamic bridge and user profile on a channel for the ConfBridge application using the same options defined in confbridge.conf. @@ -96,7 +110,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Type refers to which type of profile the option belongs too. Type can be bridge or user. - + Option refers to confbridge.conf option that is being set dynamically on this channel. @@ -282,7 +296,7 @@ enum { /*! \brief Container to hold all conference bridges in progress */ static struct ao2_container *conference_bridges; -static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user); +static void leave_conference(struct conference_bridge_user *user); static int play_sound_number(struct conference_bridge *conference_bridge, int say_number); static int execute_menu_entry(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user, @@ -546,9 +560,7 @@ static int start_conf_record_thread(struct conference_bridge *conference_bridge) { ao2_ref(conference_bridge, +1); /* give the record thread a ref */ - ao2_lock(conference_bridge); conf_start_record(conference_bridge); - ao2_unlock(conference_bridge); if (ast_pthread_create_background(&conference_bridge->record_thread, NULL, record_thread, conference_bridge)) { ast_log(LOG_WARNING, "Failed to create recording channel for conference %s\n", conference_bridge->name); @@ -754,8 +766,6 @@ static void destroy_conference_bridge(void *obj) ast_debug(1, "Destroying conference bridge '%s'\n", conference_bridge->name); - ast_mutex_destroy(&conference_bridge->playback_lock); - if (conference_bridge->playback_chan) { struct ast_channel *underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL); if (underlying_channel) { @@ -770,7 +780,11 @@ static void destroy_conference_bridge(void *obj) ast_bridge_destroy(conference_bridge->bridge); conference_bridge->bridge = NULL; } + conf_bridge_profile_destroy(&conference_bridge->b_profile); + ast_cond_destroy(&conference_bridge->record_cond); + ast_mutex_destroy(&conference_bridge->record_lock); + ast_mutex_destroy(&conference_bridge->playback_lock); } /*! \brief Call the proper join event handler for the user for the conference bridge's current state @@ -947,7 +961,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct if (conference_bridge && (max_members_reached || conference_bridge->locked) && !ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN)) { ao2_unlock(conference_bridges); ao2_ref(conference_bridge, -1); - ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name); + ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", name); ast_stream_and_wait(conference_bridge_user->chan, conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds), ""); @@ -959,10 +973,17 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */ if (!(conference_bridge = ao2_alloc(sizeof(*conference_bridge), destroy_conference_bridge))) { ao2_unlock(conference_bridges); - ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name); + ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", name); return NULL; } + /* Setup lock for playback channel */ + ast_mutex_init(&conference_bridge->playback_lock); + + /* Setup lock for the record channel */ + ast_mutex_init(&conference_bridge->record_lock); + ast_cond_init(&conference_bridge->record_cond, NULL); + /* Setup conference bridge parameters */ conference_bridge->record_thread = AST_PTHREADT_NULL; ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name)); @@ -973,7 +994,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct ao2_ref(conference_bridge, -1); conference_bridge = NULL; ao2_unlock(conference_bridges); - ast_log(LOG_ERROR, "Conference bridge '%s' could not be created.\n", name); + ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", name); return NULL; } @@ -986,15 +1007,15 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct ast_bridge_set_talker_src_video_mode(conference_bridge->bridge); } - /* Setup lock for playback channel */ - ast_mutex_init(&conference_bridge->playback_lock); - - /* Setup lock for the record channel */ - ast_mutex_init(&conference_bridge->record_lock); - ast_cond_init(&conference_bridge->record_cond, NULL); - /* Link it into the conference bridges container */ - ao2_link(conference_bridges, conference_bridge); + if (!ao2_link(conference_bridges, conference_bridge)) { + ao2_ref(conference_bridge, -1); + conference_bridge = NULL; + ao2_unlock(conference_bridges); + ast_log(LOG_ERROR, + "Conference '%s' could not be added to the conferences list.\n", name); + return NULL; + } /* Set the initial state to EMPTY */ conference_bridge->state = CONF_STATE_EMPTY; @@ -1007,7 +1028,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct } send_conf_start_event(conference_bridge->name); - ast_debug(1, "Created conference bridge '%s' and linked to container '%p'\n", name, conference_bridges); + ast_debug(1, "Created conference '%s' and linked to container.\n", name); } ao2_unlock(conference_bridges); @@ -1026,7 +1047,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct if (ast_check_hangup(conference_bridge_user->chan)) { ao2_unlock(conference_bridge); - leave_conference_bridge(conference_bridge, conference_bridge_user); + leave_conference(conference_bridge_user); return NULL; } @@ -1035,7 +1056,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct /* Announce number of users if need be */ if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) { if (announce_user_count(conference_bridge, conference_bridge_user)) { - leave_conference_bridge(conference_bridge, conference_bridge_user); + leave_conference(conference_bridge_user); return NULL; } } @@ -1043,7 +1064,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) && (conference_bridge->activeusers > conference_bridge_user->u_profile.announce_user_count_all_after)) { if (announce_user_count(conference_bridge, NULL)) { - leave_conference_bridge(conference_bridge, conference_bridge_user); + leave_conference(conference_bridge_user); return NULL; } } @@ -1058,21 +1079,26 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct } /*! - * \brief Leave a conference bridge - * - * \param conference_bridge The conference bridge to leave - * \param conference_bridge_user The conference bridge user structure + * \brief Leave a conference * + * \param user The conference user */ -static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) +static void leave_conference(struct conference_bridge_user *user) { - ao2_lock(conference_bridge); + struct post_join_action *action; - handle_conf_user_leave(conference_bridge_user); + ao2_lock(user->conference_bridge); + handle_conf_user_leave(user); + ao2_unlock(user->conference_bridge); - /* Done mucking with the conference bridge, huzzah */ - ao2_unlock(conference_bridge); - ao2_ref(conference_bridge, -1); + /* Discard any post-join actions */ + while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) { + ast_free(action); + } + + /* Done mucking with the conference, huzzah */ + ao2_ref(user->conference_bridge, -1); + user->conference_bridge = NULL; } /*! @@ -1455,7 +1481,7 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) /* if we're shutting down, don't attempt to do further processing */ if (ast_shutting_down()) { - leave_conference_bridge(conference_bridge, &conference_bridge_user); + leave_conference(&conference_bridge_user); conference_bridge = NULL; goto confbridge_cleanup; } @@ -1481,7 +1507,7 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) } /* Easy as pie, depart this channel from the conference bridge */ - leave_conference_bridge(conference_bridge, &conference_bridge_user); + leave_conference(&conference_bridge_user); conference_bridge = NULL; /* If the user was kicked from the conference play back the audio prompt for it */ diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index 234b86a3dc..cb69ee6315 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -286,7 +286,6 @@ static int set_bridge_option(const char *name, const char *value, struct bridge_ case 80: break; default: - ast_log(LOG_WARNING, "invalid mixing interval %u\n", b_profile->mix_interval); b_profile->mix_interval = 0; return -1; } @@ -294,11 +293,30 @@ static int set_bridge_option(const char *name, const char *value, struct bridge_ ast_set2_flag(b_profile, ast_true(value), BRIDGE_OPT_RECORD_CONFERENCE); } else if (!strcasecmp(name, "video_mode")) { if (!strcasecmp(value, "first_marked")) { - ast_set_flag(b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED); + ast_set_flags_to(b_profile, + BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED + | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED + | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, + BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED); } else if (!strcasecmp(value, "last_marked")) { - ast_set_flag(b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED); + ast_set_flags_to(b_profile, + BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED + | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED + | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, + BRIDGE_OPT_VIDEO_SRC_LAST_MARKED); } else if (!strcasecmp(value, "follow_talker")) { - ast_set_flag(b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER); + ast_set_flags_to(b_profile, + BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED + | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED + | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, + BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER); + } else if (!strcasecmp(value, "none")) { + ast_clear_flag(b_profile, + BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED + | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED + | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER); + } else { + return -1; } } else if (!strcasecmp(name, "max_members")) { if (sscanf(value, "%30u", &b_profile->max_members) != 1) { @@ -346,7 +364,7 @@ static int set_bridge_option(const char *name, const char *value, struct bridge_ ast_string_field_set(sounds, leave, tmp->sounds->leave); ao2_ref(tmp->sounds, -1); /* sounds struct copied over to it from the template by reference only. */ - ao2_ref(oldsounds,-1); /* original sounds struct we don't need anymore */ + ao2_ref(oldsounds, -1); /* original sounds struct we don't need anymore */ tmp->sounds = sounds; /* the new sounds struct that is a deep copy of the one from the template. */ } else { return -1; @@ -374,17 +392,16 @@ static const struct ast_datastore_info confbridge_datastore = { }; int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value) { - struct ast_datastore *datastore = NULL; - struct func_confbridge_data *b_data = NULL; - char *parse = NULL; - int new = 0; + struct ast_datastore *datastore; + struct func_confbridge_data *b_data; + char *parse; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(type); AST_APP_ARG(option); ); /* parse all the required arguments and make sure they exist. */ - if (ast_strlen_zero(data) || ast_strlen_zero(value)) { + if (ast_strlen_zero(data)) { return -1; } parse = ast_strdupa(data); @@ -394,50 +411,51 @@ int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data } ast_channel_lock(chan); - if (!(datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) { - ast_channel_unlock(chan); - - if (!(datastore = ast_datastore_alloc(&confbridge_datastore, NULL))) { + datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL); + if (!datastore) { + datastore = ast_datastore_alloc(&confbridge_datastore, NULL); + if (!datastore) { + ast_channel_unlock(chan); return 0; } - if (!(b_data = ast_calloc(1, sizeof(*b_data)))) { + b_data = ast_calloc(1, sizeof(*b_data)); + if (!b_data) { + ast_channel_unlock(chan); ast_datastore_free(datastore); return 0; } - if (!(b_data->b_profile.sounds = bridge_profile_sounds_alloc())) { + b_data->b_profile.sounds = bridge_profile_sounds_alloc(); + if (!b_data->b_profile.sounds) { + ast_channel_unlock(chan); ast_datastore_free(datastore); ast_free(b_data); return 0; } datastore->data = b_data; - new = 1; + ast_channel_datastore_add(chan, datastore); } else { - ast_channel_unlock(chan); b_data = datastore->data; } + ast_channel_unlock(chan); /* SET(CONFBRIDGE(type,option)=value) */ - if (!strcasecmp(args.type, "bridge") && !set_bridge_option(args.option, value, &b_data->b_profile)) { - b_data->b_usable = 1; - } else if (!strcasecmp(args.type, "user") && !set_user_option(args.option, value, &b_data->u_profile)) { - b_data->u_usable = 1; - } else { - ast_log(LOG_WARNING, "Profile type \"%s\" can not be set in CONFBRIDGE function with option \"%s\" and value \"%s\"\n", - args.type, args.option, value); - goto cleanup_error; + if (!value) { + value = ""; } - if (new) { - ast_channel_lock(chan); - ast_channel_datastore_add(chan, datastore); - ast_channel_unlock(chan); + if (!strcasecmp(args.type, "bridge")) { + if (!set_bridge_option(args.option, value, &b_data->b_profile)) { + b_data->b_usable = 1; + return 0; + } + } else if (!strcasecmp(args.type, "user")) { + if (!set_user_option(args.option, value, &b_data->u_profile)) { + b_data->u_usable = 1; + return 0; + } } - return 0; -cleanup_error: - ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd); - if (new) { - ast_datastore_free(datastore); - } + ast_log(LOG_WARNING, "%s(%s,%s) cannot be set to '%s'. Invalid type, option, or value.\n", + cmd, args.type, args.option, value); return -1; } @@ -486,7 +504,7 @@ static int parse_bridge(const char *cat, struct ast_config *cfg) continue; } else if (set_bridge_option(var->name, var->value, b_profile)) { ast_log(LOG_WARNING, "Invalid: '%s' at line %d of %s is not supported.\n", - var->name, var->lineno, CONFBRIDGE_CONFIG); + var->name, var->lineno, var->file); } } ao2_unlock(b_profile); @@ -524,7 +542,7 @@ static int parse_user(const char *cat, struct ast_config *cfg) continue; } else if (set_user_option(var->name, var->value, u_profile)) { ast_log(LOG_WARNING, "Invalid option '%s' at line %d of %s is not supported.\n", - var->name, var->lineno, CONFBRIDGE_CONFIG); + var->name, var->lineno, var->file); } } ao2_unlock(u_profile); @@ -755,7 +773,7 @@ static int parse_menu(const char *cat, struct ast_config *cfg) continue; } else if (add_menu_entry(menu, var->name, var->value)) { ast_log(LOG_WARNING, "Unknown option '%s' at line %d of %s is not supported.\n", - var->name, var->lineno, CONFBRIDGE_CONFIG); + var->name, var->lineno, var->file); } } ao2_unlock(menu); @@ -1009,14 +1027,25 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e, ast_cli(a->fd,"Max Members: No Limit\n"); } - if (b_profile.flags & BRIDGE_OPT_VIDEO_SRC_LAST_MARKED) { + switch (b_profile.flags + & (BRIDGE_OPT_VIDEO_SRC_LAST_MARKED | BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED + | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) { + case BRIDGE_OPT_VIDEO_SRC_LAST_MARKED: ast_cli(a->fd, "Video Mode: last_marked\n"); - } else if (b_profile.flags & BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) { + break; + case BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED: ast_cli(a->fd, "Video Mode: first_marked\n"); - } else if (b_profile.flags & BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER) { + break; + case BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER: ast_cli(a->fd, "Video Mode: follow_talker\n"); - } else { + break; + case 0: ast_cli(a->fd, "Video Mode: no video\n"); + break; + default: + /* Opps. We have more than one video mode flag set. */ + ast_assert(0); + break; } ast_cli(a->fd,"sound_join: %s\n", conf_get_sound(CONF_SOUND_JOIN, b_profile.sounds)); @@ -1229,7 +1258,7 @@ static int conf_parse_init(void) return 0; } -void conf_destroy_config() +void conf_destroy_config(void) { if (user_profiles) { ao2_ref(user_profiles, -1); @@ -1316,15 +1345,14 @@ const struct user_profile *conf_find_user_profile(struct ast_channel *chan, cons if (chan) { ast_channel_lock(chan); - if ((datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) { - ast_channel_unlock(chan); + datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL); + ast_channel_unlock(chan); + if (datastore) { b_data = datastore->data; if (b_data->u_usable) { conf_user_profile_copy(result, &b_data->u_profile); return result; } - } else { - ast_channel_unlock(chan); } } @@ -1344,7 +1372,7 @@ const struct user_profile *conf_find_user_profile(struct ast_channel *chan, cons void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src) { - memcpy(dst, src, sizeof(*dst)); + *dst = *src; if (src->sounds) { ao2_ref(src->sounds, +1); } @@ -1367,15 +1395,14 @@ const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, if (chan) { ast_channel_lock(chan); - if ((datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) { - ast_channel_unlock(chan); + datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL); + ast_channel_unlock(chan); + if (datastore) { b_data = datastore->data; if (b_data->b_usable) { conf_bridge_profile_copy(result, &b_data->b_profile); return result; } - } else { - ast_channel_unlock(chan); } } if (ast_strlen_zero(bridge_profile_name)) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f449181599..9a101e349e 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2561,10 +2561,10 @@ static int sip_check_authtimeout(time_t start) * \retval -1 Failed to read data * \retval 0 Succeeded in reading data */ -static int sip_tls_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session, int authenticated, time_t start, struct sip_threadinfo *me) +static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, struct ast_tcptls_session_instance *tcptls_session, + int authenticated, time_t start, struct sip_threadinfo *me) { int res, content_length, after_poll = 1, need_poll = 1; - struct sip_request reqcpy = { 0, }; char buf[1024] = ""; int timeout = -1; @@ -2618,10 +2618,10 @@ static int sip_tls_read(struct sip_request *req, struct ast_tcptls_session_insta } ast_str_append(&req->data, 0, "%s", buf); } - copy_request(&reqcpy, req); - parse_request(&reqcpy); + copy_request(reqcpy, req); + parse_request(reqcpy); /* In order to know how much to read, we need the content-length header */ - if (sscanf(sip_get_header(&reqcpy, "Content-Length"), "%30d", &content_length)) { + if (sscanf(sip_get_header(reqcpy, "Content-Length"), "%30d", &content_length)) { while (content_length > 0) { size_t bytes_read; if (!tcptls_session->client && !authenticated) { @@ -3035,7 +3035,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s req.socket.fd = tcptls_session->fd; if (tcptls_session->ssl) { - res = sip_tls_read(&req, tcptls_session, authenticated, start, me); + res = sip_tls_read(&req, &reqcpy, tcptls_session, authenticated, start, me); } else { res = sip_tcp_read(&req, tcptls_session, authenticated, start); } @@ -21560,6 +21560,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &st_ref_param); if (rtn != 0) { ast_set_flag(&p->flags[0], SIP_PENDINGBYE); + } else if (tmp_st_interval < st_get_se(p, FALSE)) { + ast_log(LOG_WARNING, "Got Session-Expires less than local Min-SE in 200 OK, tearing down call\n"); + ast_set_flag(&p->flags[0], SIP_PENDINGBYE); } if (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UAC) { p->stimer->st_ref = SESSION_TIMER_REFRESHER_US; diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 4d9e2bbfad..d506eed0a4 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -1956,20 +1956,6 @@ static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subcha ast_quiet_chan(peerc); ast_quiet_chan(peerd); */ - if (peera->cdr && peerb->cdr) { - peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr); - } else if (peera->cdr) { - peerb->cdr = peera->cdr; - } - peera->cdr = NULL; - - if (peerb->cdr && peerc->cdr) { - peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr); - } else if (peerc->cdr) { - peerb->cdr = peerc->cdr; - } - peerc->cdr = NULL; - if (ast_channel_masquerade(peerb, peerc)) { ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); @@ -2197,9 +2183,9 @@ static void start_rtp(struct unistim_subchannel *sub) buffsend[16] = (htons(sin.sin_port) & 0x00ff); buffsend[20] = (us.sin_port & 0xff00) >> 8; buffsend[19] = (us.sin_port & 0x00ff); - buffsend[11] = codec; } - buffsend[12] = codec; + buffsend[11] = codec; /* rx */ + buffsend[12] = codec; /* tx */ send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, sub->parent->parent->session); @@ -2227,9 +2213,9 @@ static void start_rtp(struct unistim_subchannel *sub) buffsend[16] = (htons(sin.sin_port) & 0x00ff); buffsend[20] = (us.sin_port & 0xff00) >> 8; buffsend[19] = (us.sin_port & 0x00ff); - buffsend[12] = codec; } - buffsend[11] = codec; + buffsend[11] = codec; /* rx */ + buffsend[12] = codec; /* tx */ send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, sub->parent->parent->session); } else { diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c index ccd323ae68..5fedc25cb0 100644 --- a/codecs/codec_dahdi.c +++ b/codecs/codec_dahdi.c @@ -396,7 +396,7 @@ static void dahdi_destroy(struct ast_trans_pvt *pvt) { struct codec_dahdi_pvt *dahdip = pvt->pvt; - switch (dahdip->fmts.dstfmt) { + switch (ast_format_id_from_old_bitfield(dahdip->fmts.dstfmt)) { case AST_FORMAT_G729A: case AST_FORMAT_G723_1: ast_atomic_fetchadd_int(&channels.encoders, -1); diff --git a/contrib/realtime/mysql/sippeers.sql b/contrib/realtime/mysql/sippeers.sql index 6884ac6a9e..5c58df7ea1 100644 --- a/contrib/realtime/mysql/sippeers.sql +++ b/contrib/realtime/mysql/sippeers.sql @@ -28,8 +28,8 @@ CREATE TABLE IF NOT EXISTS `sippeers` ( `callgroup` varchar(40) DEFAULT NULL, `pickupgroup` varchar(40) DEFAULT NULL, `language` varchar(40) DEFAULT NULL, - `allow` varchar(40) DEFAULT NULL, `disallow` varchar(40) DEFAULT NULL, + `allow` varchar(40) DEFAULT NULL, `insecure` varchar(40) DEFAULT NULL, `trustrpid` enum('yes','no') DEFAULT NULL, `progressinband` enum('yes','no','never') DEFAULT NULL, diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h index e1f8c7246b..a7ed68136f 100644 --- a/include/asterisk/_private.h +++ b/include/asterisk/_private.h @@ -19,6 +19,7 @@ int load_modules(unsigned int); /*!< Provided by loader.c */ int load_pbx(void); /*!< Provided by pbx.c */ int init_logger(void); /*!< Provided by logger.c */ void close_logger(void); /*!< Provided by logger.c */ +void clean_time_zones(void); /*!< Provided by localtime.c */ int init_framer(void); /*!< Provided by frame.c */ int ast_term_init(void); /*!< Provided by term.c */ int astdb_init(void); /*!< Provided by db.c */ diff --git a/main/asterisk.c b/main/asterisk.c index de189b8590..44be5bb30e 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -213,10 +213,10 @@ struct console { struct ast_atexit { void (*func)(void); - AST_RWLIST_ENTRY(ast_atexit) list; + AST_LIST_ENTRY(ast_atexit) list; }; -static AST_RWLIST_HEAD_STATIC(atexits, ast_atexit); +static AST_LIST_HEAD_STATIC(atexits, ast_atexit); struct timeval ast_startuptime; struct timeval ast_lastreloadtime; @@ -953,39 +953,57 @@ static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct #endif /* ! LOW_MEMORY */ +static void ast_run_atexits(void) +{ + struct ast_atexit *ae; + + AST_LIST_LOCK(&atexits); + while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) { + if (ae->func) { + ae->func(); + } + ast_free(ae); + } + AST_LIST_UNLOCK(&atexits); +} + +static void __ast_unregister_atexit(void (*func)(void)) +{ + struct ast_atexit *ae; + + AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) { + if (ae->func == func) { + AST_LIST_REMOVE_CURRENT(list); + ast_free(ae); + break; + } + } + AST_LIST_TRAVERSE_SAFE_END; +} + int ast_register_atexit(void (*func)(void)) { struct ast_atexit *ae; - if (!(ae = ast_calloc(1, sizeof(*ae)))) + ae = ast_calloc(1, sizeof(*ae)); + if (!ae) { return -1; - + } ae->func = func; - ast_unregister_atexit(func); - - AST_RWLIST_WRLOCK(&atexits); - AST_RWLIST_INSERT_HEAD(&atexits, ae, list); - AST_RWLIST_UNLOCK(&atexits); + AST_LIST_LOCK(&atexits); + __ast_unregister_atexit(func); + AST_LIST_INSERT_HEAD(&atexits, ae, list); + AST_LIST_UNLOCK(&atexits); return 0; } void ast_unregister_atexit(void (*func)(void)) { - struct ast_atexit *ae = NULL; - - AST_RWLIST_WRLOCK(&atexits); - AST_RWLIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) { - if (ae->func == func) { - AST_RWLIST_REMOVE_CURRENT(list); - break; - } - } - AST_RWLIST_TRAVERSE_SAFE_END; - AST_RWLIST_UNLOCK(&atexits); - - free(ae); + AST_LIST_LOCK(&atexits); + __ast_unregister_atexit(func); + AST_LIST_UNLOCK(&atexits); } /* Sending commands from consoles back to the daemon requires a terminating NULL */ @@ -1657,17 +1675,6 @@ int ast_set_priority(int pri) return 0; } -static void ast_run_atexits(void) -{ - struct ast_atexit *ae; - AST_RWLIST_RDLOCK(&atexits); - AST_RWLIST_TRAVERSE(&atexits, ae, list) { - if (ae->func) - ae->func(); - } - AST_RWLIST_UNLOCK(&atexits); -} - static int can_safely_quit(shutdown_nice_t niceness, int restart); static void really_quit(int num, shutdown_nice_t niceness, int restart); @@ -1750,8 +1757,11 @@ static int can_safely_quit(shutdown_nice_t niceness, int restart) return 1; } +/*! Called when exiting is certain. */ static void really_quit(int num, shutdown_nice_t niceness, int restart) { + int active_channels; + if (niceness >= SHUTDOWN_NICE) { ast_module_shutdown(); } @@ -1778,21 +1788,24 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart) } } } + active_channels = ast_active_channels(); /* The manager event for shutdown must happen prior to ast_run_atexits, as * the manager interface will dispose of its sessions as part of its * shutdown. */ manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\n" "Restart: %s\r\n", - ast_active_channels() ? "Uncleanly" : "Cleanly", + active_channels ? "Uncleanly" : "Cleanly", restart ? "True" : "False"); + if (option_verbose && ast_opt_console) { + ast_verbose("Asterisk %s ending (%d).\n", + active_channels ? "uncleanly" : "cleanly", num); + } if (option_verbose) ast_verbose("Executing last minute cleanups\n"); ast_run_atexits(); - /* Called on exit */ - if (option_verbose && ast_opt_console) - ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num); + ast_debug(1, "Asterisk ending (%d).\n", num); if (ast_socket > -1) { pthread_cancel(lthread); @@ -1819,6 +1832,7 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart) /* close logger */ close_logger(); + clean_time_zones(); /* If there is a consolethread running send it a SIGHUP so it can execvp, otherwise we can do it ourselves */ @@ -1832,6 +1846,7 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart) } else { /* close logger */ close_logger(); + clean_time_zones(); } exit(0); @@ -2230,14 +2245,25 @@ static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args #define ASTERISK_PROMPT2 "%s*CLI> " -static struct ast_cli_entry cli_asterisk[] = { - AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"), +/*! + * \brief Shutdown Asterisk CLI commands. + * + * \note These CLI commands cannot be unregistered at shutdown + * because one of them is likely the reason for the shutdown. + * The CLI generates a warning if a command is in-use when it is + * unregistered. + */ +static struct ast_cli_entry cli_asterisk_shutdown[] = { AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"), AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"), AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"), AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"), AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"), AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"), +}; + +static struct ast_cli_entry cli_asterisk[] = { + AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"), AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"), AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"), AST_CLI_DEFINE(handle_version, "Display version info"), @@ -3357,6 +3383,11 @@ static void print_intro_message(const char *runuser, const char *rungroup) } } +static void main_atexit(void) +{ + ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk)); +} + int main(int argc, char *argv[]) { int c; @@ -4072,7 +4103,9 @@ int main(int argc, char *argv[]) #endif /* defined(__AST_DEBUG_MALLOC) */ ast_lastreloadtime = ast_startuptime = ast_tvnow(); + ast_cli_register_multiple(cli_asterisk_shutdown, ARRAY_LEN(cli_asterisk_shutdown)); ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk)); + ast_register_atexit(main_atexit); run_startup_commands(); diff --git a/main/astmm.c b/main/astmm.c index 1283de2dfe..9396d09873 100644 --- a/main/astmm.c +++ b/main/astmm.c @@ -1333,8 +1333,11 @@ static void mm_atexit_final(void) { FILE *log; - fprintf(stderr, "Waiting 10 seconds to let other threads die.\n"); - sleep(10); + /* Only wait if we want atexit allocation dumps. */ + if (atexit_list || atexit_summary) { + fprintf(stderr, "Waiting 10 seconds to let other threads die.\n"); + sleep(10); + } regions_check_all_fences(); diff --git a/main/dnsmgr.c b/main/dnsmgr.c index 7d4246f60f..fda7bd91d5 100644 --- a/main/dnsmgr.c +++ b/main/dnsmgr.c @@ -394,6 +394,26 @@ static struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Relo static struct ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh"); static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status"); +static void dnsmgr_shutdown(void) +{ + ast_cli_unregister(&cli_reload); + ast_cli_unregister(&cli_status); + ast_cli_unregister(&cli_refresh); + + /* Destroy refresh thread. */ + ast_mutex_lock(&refresh_lock); + if (refresh_thread != AST_PTHREADT_NULL) { + /* wake up the thread so it will exit */ + pthread_cancel(refresh_thread); + pthread_kill(refresh_thread, SIGURG); + pthread_join(refresh_thread, NULL); + refresh_thread = AST_PTHREADT_NULL; + } + ast_mutex_unlock(&refresh_lock); + + ast_sched_context_destroy(sched); +} + int dnsmgr_init(void) { if (!(sched = ast_sched_context_create())) { @@ -403,6 +423,9 @@ int dnsmgr_init(void) ast_cli_register(&cli_reload); ast_cli_register(&cli_status); ast_cli_register(&cli_refresh); + + ast_register_atexit(dnsmgr_shutdown); + return do_reload(1); } diff --git a/main/event.c b/main/event.c index 42d9e72c60..60535bbae6 100644 --- a/main/event.c +++ b/main/event.c @@ -1804,6 +1804,40 @@ static struct ast_cli_entry event_cli[] = { AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"), }; +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void event_shutdown(void) +{ + struct ast_event_sub *sub; + int i; + + ast_cli_unregister_multiple(event_cli, ARRAY_LEN(event_cli)); + + if (event_dispatcher) { + event_dispatcher = ast_taskprocessor_unreference(event_dispatcher); + } + + /* Remove any remaining subscriptions. Note that we can't just call + * unsubscribe, as it will attempt to lock the subscription list + * as well */ + for (i = 0; i < AST_EVENT_TOTAL; i++) { + AST_RWDLLIST_WRLOCK(&ast_event_subs[i]); + while ((sub = AST_RWDLLIST_REMOVE_HEAD(&ast_event_subs[i], entry))) { + ast_event_sub_destroy(sub); + } + AST_RWDLLIST_UNLOCK(&ast_event_subs[i]); + AST_RWDLLIST_HEAD_DESTROY(&ast_event_subs[i]); + } + + for (i = 0; i < AST_EVENT_TOTAL; i++) { + if (!ast_event_cache[i].hash_fn) { + continue; + } + if (ast_event_cache[i].container) { + ao2_ref(ast_event_cache[i].container, -1); + } + } +} + int ast_event_init(void) { int i; @@ -1820,17 +1854,23 @@ int ast_event_init(void) if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS, ast_event_hash, ast_event_cmp))) { - return -1; + goto event_init_cleanup; } } if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) { - return -1; + goto event_init_cleanup; } ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli)); + ast_register_atexit(event_shutdown); + return 0; + +event_init_cleanup: + event_shutdown(); + return -1; } size_t ast_event_minimum_length(void) diff --git a/main/format.c b/main/format.c index b739038b9c..cf72368d3b 100644 --- a/main/format.c +++ b/main/format.c @@ -881,7 +881,6 @@ static struct ast_cli_entry my_clis[] = { }; int init_framer(void) { - ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis)); return 0; } @@ -1083,30 +1082,27 @@ init_list_cleanup: /*! \internal \brief Clean up resources on Asterisk shutdown */ static void format_attr_shutdown(void) { + ast_cli_unregister_multiple(my_clis, ARRAY_LEN(my_clis)); if (interfaces) { ao2_ref(interfaces, -1); interfaces = NULL; } + ast_rwlock_destroy(&ilock); } int ast_format_attr_init(void) { - ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis)); if (ast_rwlock_init(&ilock)) { return -1; } - if (!(interfaces = ao2_container_alloc(283, interface_hash_cb, interface_cmp_cb))) { - goto init_cleanup; + ast_rwlock_destroy(&ilock); + return -1; } - return 0; -init_cleanup: - ast_rwlock_destroy(&ilock); - if (interfaces) { - ao2_ref(interfaces, -1); - } - return -1; + ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis)); + ast_register_atexit(format_attr_shutdown); + return 0; } static int custom_celt_format(struct ast_format_list *entry, unsigned int maxbitrate, unsigned int framesize) @@ -1200,7 +1196,6 @@ static int conf_process_format_name(const char *name, enum ast_format_id *id) *id = 0; return -1; } - ast_register_atexit(format_attr_shutdown); return 0; } diff --git a/main/indications.c b/main/indications.c index 152860d9ee..df50ec1468 100644 --- a/main/indications.c +++ b/main/indications.c @@ -560,11 +560,13 @@ static int ast_unregister_indication_country(const char *country) ast_copy_string(zone_arg.country, country, sizeof(zone_arg.country)); - if (!(tz = ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER))) { + ao2_lock(ast_tone_zones); + tz = ao2_find(ast_tone_zones, &zone_arg, OBJ_POINTER | OBJ_UNLINK); + if (!tz) { + ao2_unlock(ast_tone_zones); return -1; } - ao2_lock(ast_tone_zones); if (default_tone_zone == tz) { ast_tone_zone_unref(default_tone_zone); /* Get a new default, punt to the first one we find */ @@ -572,8 +574,6 @@ static int ast_unregister_indication_country(const char *country) } ao2_unlock(ast_tone_zones); - ao2_unlink(ast_tone_zones, tz); - tz = ast_tone_zone_unref(tz); return 0; @@ -939,7 +939,6 @@ static void store_config_tone_zone(struct ast_tone_zone *zone, const char *var, CV_STR("description", zone->description); CV_F("ringcadence", store_tone_zone_ring_cadence(zone, value)); - CV_F("ringcadance", store_tone_zone_ring_cadence(zone, value)); ast_register_indication(zone, var, value); @@ -1153,6 +1152,11 @@ int ast_tone_zone_data_add_structure(struct ast_data *tree, struct ast_tone_zone /*! \internal \brief Clean up resources on Asterisk shutdown */ static void indications_shutdown(void) { + ast_cli_unregister_multiple(cli_indications, ARRAY_LEN(cli_indications)); + if (default_tone_zone) { + ast_tone_zone_unref(default_tone_zone); + default_tone_zone = NULL; + } if (ast_tone_zones) { ao2_ref(ast_tone_zones, -1); ast_tone_zones = NULL; @@ -1168,6 +1172,7 @@ int ast_indications_init(void) } if (load_indications(0)) { + indications_shutdown(); return -1; } diff --git a/main/logger.c b/main/logger.c index 91102f040d..e46a81c1aa 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1155,6 +1155,9 @@ int init_logger(void) void close_logger(void) { struct logchannel *f = NULL; + struct verb *cur = NULL; + + ast_cli_unregister_multiple(cli_logger, ARRAY_LEN(cli_logger)); logger_initialized = 0; @@ -1167,6 +1170,12 @@ void close_logger(void) if (logthread != AST_PTHREADT_NULL) pthread_join(logthread, NULL); + AST_RWLIST_WRLOCK(&verbosers); + while ((cur = AST_LIST_REMOVE_HEAD(&verbosers, list))) { + ast_free(cur); + } + AST_RWLIST_UNLOCK(&verbosers); + AST_RWLIST_WRLOCK(&logchannels); if (qlog) { @@ -1174,11 +1183,12 @@ void close_logger(void) qlog = NULL; } - AST_RWLIST_TRAVERSE(&logchannels, f, list) { + while ((f = AST_LIST_REMOVE_HEAD(&logchannels, list))) { if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) { fclose(f->fileptr); f->fileptr = NULL; } + ast_free(f); } closelog(); /* syslog */ diff --git a/main/stdtime/localtime.c b/main/stdtime/localtime.c index de8306c4a0..bf60e3ab72 100644 --- a/main/stdtime/localtime.c +++ b/main/stdtime/localtime.c @@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "private.h" #include "tzfile.h" +#include "asterisk/_private.h" #include "asterisk/lock.h" #include "asterisk/localtime.h" #include "asterisk/strings.h" @@ -427,7 +428,7 @@ static void *kqueue_daemon(void *data) closedir(sp->dir); } #endif - free(sp); + ast_free(sp); /* Just in case the signal was sent late */ AST_LIST_LOCK(&zonelist); @@ -1417,6 +1418,17 @@ static int gmtload(struct state *sp) return -1; } +void clean_time_zones(void) +{ + struct state *sp; + + AST_LIST_LOCK(&zonelist); + while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) { + ast_free(sp); + } + AST_LIST_UNLOCK(&zonelist); +} + static const struct state *ast_tzset(const char *zone) { struct state *sp; diff --git a/main/xmldoc.c b/main/xmldoc.c index 125cd240b9..7e8eca4974 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -354,7 +354,13 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors) /* Setup color */ if (withcolors) { - ast_term_color_code(&colorized, colorized_tags[c].colorfg, 0); + if (ast_opt_light_background) { + /* Turn off *bright* colors */ + ast_term_color_code(&colorized, colorized_tags[c].colorfg & 0x7f, 0); + } else { + /* Turn on *bright* colors */ + ast_term_color_code(&colorized, colorized_tags[c].colorfg | 0x80, 0); + } if (!colorized) { return NULL; } diff --git a/res/res_fax.c b/res/res_fax.c index bf59eb1216..f0c6163757 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -1837,6 +1837,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data) ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename); details->caps = AST_FAX_TECH_RECEIVE; + details->option.send_ced = AST_FAX_OPTFLAG_TRUE; /* check for debug */ if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) { @@ -1901,8 +1902,6 @@ static int receivefax_exec(struct ast_channel *chan, const char *data) ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name); return -1; } - } else { - details->option.send_ced = 1; } if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) { diff --git a/res/res_srtp.c b/res/res_srtp.c index f651c40675..b9499f8f1c 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -383,6 +383,8 @@ tryagain: retry++; ao2_iterator_destroy(&it); goto tryagain; + } else { + srtp->session = NULL; } ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed"); } @@ -437,6 +439,8 @@ static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, /* Any failures after this point can use ast_srtp_destroy to destroy the instance */ if (srtp_create(&temp->session, &policy->sp) != err_status_ok) { + /* Session either wasn't created or was created and dealloced. */ + temp->session = NULL; ast_srtp_destroy(temp); return -1; }