]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Multiple revisions 377136,377166,377212,377227,377241,377258,377261,377354,377382...
authorJason Parker <jparker@digium.com>
Tue, 8 Jan 2013 19:09:11 +0000 (19:09 +0000)
committerJason Parker <jparker@digium.com>
Tue, 8 Jan 2013 19:09:11 +0000 (19:09 +0000)
........
  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

19 files changed:
addons/cdr_mysql.c
apps/app_confbridge.c
apps/confbridge/conf_config_parser.c
channels/chan_sip.c
channels/chan_unistim.c
codecs/codec_dahdi.c
contrib/realtime/mysql/sippeers.sql
include/asterisk/_private.h
main/asterisk.c
main/astmm.c
main/dnsmgr.c
main/event.c
main/format.c
main/indications.c
main/logger.c
main/stdtime/localtime.c
main/xmldoc.c
res/res_fax.c
res/res_srtp.c

index 445f9e3d0553daca76e22ff84d64885f65174645..b87d8c6aa14d59a4bfbcccacdf3469c023e36e7f 100644 (file)
@@ -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);
index 22e1cd0e22a91be0904991898d39e4d2a32b21f0..df72400809b2c1072b96cc12fbff96a2491152cc 100644 (file)
@@ -60,34 +60,48 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #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.
@@ -96,7 +110,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        <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>
@@ -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 */
index 234b86a3dcd4a60ad62b0517a3a85685ec83b7ea..cb69ee6315b33f3bf12c7a9a24f487d834e3e290 100644 (file)
@@ -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)) {
index f4491815990ce2359a4ac85612cbdf653c101efe..9a101e349e72615d4ce734e84b85e462b3e5d33b 100644 (file)
@@ -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;
index 4d9e2bbfada1bd4a022ce78630a235b5384b810c..d506eed0a40a46fd1e03c5042c70e04a8a311afd 100644 (file)
@@ -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 {
index ccd323ae6866f8cc6e8bbfaf689de7b30cf44c60..5fedc25cb0672046b570e7c066812fc6ec902039 100644 (file)
@@ -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);
index 6884ac6a9e1d298d1d80caeaf6dbd50ca3a64f01..5c58df7ea1e67487417b25cd57f85d4e8c55e145 100644 (file)
@@ -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,
index e1f8c7246baea9f8748e4fcdf790791ce902865b..a7ed68136f3212ae6b155f88c1c3df611dc1cc05 100644 (file)
@@ -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 */
index de189b85909b174b9705deb3183d59e10c5945c3..44be5bb30ef5b9ef188a94f9b2331d8fcd74a1a4 100644 (file)
@@ -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();
 
index 1283de2dfea3d869eacb0e3b12684f9cf141cc3e..9396d09873e8a06b4f2f8d85d41365d74c44af72 100644 (file)
@@ -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();
 
index 7d4246f60f63df49ef35314a8a33194efa324943..fda7bd91d5207790cdea482a2ca6a37c3555b6b2 100644 (file)
@@ -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);
 }
 
index 42d9e72c609d44d6478f6c61cc322ae5ae9f180a..60535bbae6b8f939b5b59ffb2122aa5c27a2885b 100644 (file)
@@ -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)
index b739038b9c8aba29c7e24257b97a5879d65bcc8b..cf72368d3be91828c48deb51c5b3796f8b699399 100644 (file)
@@ -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;
 }
 
index 152860d9ee1ac6e4ac8c07f7f55366290c6a2c2c..df50ec146830624e5064b236f380ddd38611a3fe 100644 (file)
@@ -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;
        }
 
index 91102f040d0c43a7624d857106b3677fdfff48d4..e46a81c1aa084cb0be8abfa80a70c89b0618b0ec 100644 (file)
@@ -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 */
index de8306c4a067cf0350da511b33921fdcc84b01e5..bf60e3ab729b2d9a35e0d0b352081bf4cdc119d4 100644 (file)
@@ -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;
index 125cd240b9ef7966eddbc75d685cc31508ae68c4..7e8eca4974384d7b9debcdce16c099c449541893 100644 (file)
@@ -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;
                                }
index bf59eb12168d51deafc09c731ba833e58d53ab8e..f0c6163757df972e785d0924e646aced20f10541 100644 (file)
@@ -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) {
index f651c406751c71372a9c31ea902931f62e1c64df..b9499f8f1c7da54b5ece833833d5e71b8267838f 100644 (file)
@@ -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;
        }