........
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
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;
* 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);
#include "asterisk/test.h"
/*** DOCUMENTATION
- <application name="ConfBridge" language="en_US">
- <synopsis>
- Conference bridge application.
- </synopsis>
- <syntax>
- <parameter name="confno">
- <para>The conference number</para>
- </parameter>
- <parameter name="bridge_profile">
- <para>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. </para>
- <para>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.</para>
- </parameter>
- <parameter name="user_profile">
- <para>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.</para>
- </parameter>
- <parameter name="menu">
- <para>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.</para>
- </parameter>
- </syntax>
- <description>
- <para>Enters the user into a specified conference bridge. The user can exit the conference by hangup or DTMF menu option.</para>
- </description>
- <see-also>
- <ref type="application">ConfBridge</ref>
- <ref type="function">CONFBRIDGE</ref>
- <ref type="function">CONFBRIDGE_INFO</ref>
- </see-also>
- </application>
+ <application name="ConfBridge" language="en_US">
+ <synopsis>
+ Conference bridge application.
+ </synopsis>
+ <syntax>
+ <parameter name="conference" required="true">
+ <para>Name of the conference bridge. You are not limited to just
+ numbers.</para>
+ </parameter>
+ <parameter name="bridge_profile">
+ <para>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. </para>
+ <para>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.</para>
+ </parameter>
+ <parameter name="user_profile">
+ <para>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.</para>
+ </parameter>
+ <parameter name="menu">
+ <para>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.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Enters the user into a specified conference bridge. The user can
+ exit the conference by hangup or DTMF menu option.</para>
+ </description>
+ <see-also>
+ <ref type="application">ConfBridge</ref>
+ <ref type="function">CONFBRIDGE</ref>
+ <ref type="function">CONFBRIDGE_INFO</ref>
+ </see-also>
+ </application>
<function name="CONFBRIDGE" language="en_US">
<synopsis>
Set a custom dynamic bridge and user profile on a channel for the ConfBridge application using the same options defined in confbridge.conf.
<parameter name="type" required="true">
<para>Type refers to which type of profile the option belongs too. Type can be <literal>bridge</literal> or <literal>user</literal>.</para>
</parameter>
- <parameter name="option" required="true">
+ <parameter name="option" required="true">
<para>Option refers to <filename>confbridge.conf</filename> option that is being set dynamically on this channel.</para>
</parameter>
</syntax>
/*! \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,
{
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);
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) {
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
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),
"");
/* 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));
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;
}
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;
}
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);
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;
}
/* 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;
}
}
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;
}
}
}
/*!
- * \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;
}
/*!
/* 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;
}
}
/* 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 */
case 80:
break;
default:
- ast_log(LOG_WARNING, "invalid mixing interval %u\n", b_profile->mix_interval);
b_profile->mix_interval = 0;
return -1;
}
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) {
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;
};
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);
}
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;
}
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);
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);
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);
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));
return 0;
}
-void conf_destroy_config()
+void conf_destroy_config(void)
{
if (user_profiles) {
ao2_ref(user_profiles, -1);
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);
}
}
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);
}
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)) {
* \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;
}
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) {
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);
}
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;
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);
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);
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 {
{
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);
`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,
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 */
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;
#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 */
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);
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();
}
}
}
}
+ 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);
/* 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 */
} else {
/* close logger */
close_logger();
+ clean_time_zones();
}
exit(0);
#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"),
}
}
+static void main_atexit(void)
+{
+ ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
+}
+
int main(int argc, char *argv[])
{
int c;
#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();
{
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();
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())) {
ast_cli_register(&cli_reload);
ast_cli_register(&cli_status);
ast_cli_register(&cli_refresh);
+
+ ast_register_atexit(dnsmgr_shutdown);
+
return do_reload(1);
}
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;
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)
};
int init_framer(void)
{
- ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
return 0;
}
/*! \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)
*id = 0;
return -1;
}
- ast_register_atexit(format_attr_shutdown);
return 0;
}
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 */
}
ao2_unlock(ast_tone_zones);
- ao2_unlink(ast_tone_zones, tz);
-
tz = ast_tone_zone_unref(tz);
return 0;
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);
/*! \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;
}
if (load_indications(0)) {
+ indications_shutdown();
return -1;
}
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;
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) {
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 */
#include "private.h"
#include "tzfile.h"
+#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
closedir(sp->dir);
}
#endif
- free(sp);
+ ast_free(sp);
/* Just in case the signal was sent late */
AST_LIST_LOCK(&zonelist);
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;
/* 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;
}
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) {
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) {
retry++;
ao2_iterator_destroy(&it);
goto tryagain;
+ } else {
+ srtp->session = NULL;
}
ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed");
}
/* 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;
}