[asterisk-commits] oej: branch oej/pine-instance-uuid-1.8 r400214 - in /team/oej/pine-instance-u...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Oct 1 02:43:47 CDT 2013


Author: oej
Date: Tue Oct  1 02:43:31 2013
New Revision: 400214

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=400214
Log:
Resolving issues that this branch was suffering from. Poor little branch.

Modified:
    team/oej/pine-instance-uuid-1.8/   (props changed)
    team/oej/pine-instance-uuid-1.8/CHANGES
    team/oej/pine-instance-uuid-1.8/UPGRADE.txt
    team/oej/pine-instance-uuid-1.8/addons/chan_ooh323.c
    team/oej/pine-instance-uuid-1.8/apps/app_meetme.c
    team/oej/pine-instance-uuid-1.8/apps/app_mixmonitor.c
    team/oej/pine-instance-uuid-1.8/apps/app_playback.c
    team/oej/pine-instance-uuid-1.8/apps/app_queue.c
    team/oej/pine-instance-uuid-1.8/apps/app_stack.c
    team/oej/pine-instance-uuid-1.8/build_tools/prep_tarball
    team/oej/pine-instance-uuid-1.8/cel/cel_custom.c
    team/oej/pine-instance-uuid-1.8/channels/chan_dahdi.c
    team/oej/pine-instance-uuid-1.8/channels/chan_iax2.c
    team/oej/pine-instance-uuid-1.8/channels/chan_misdn.c
    team/oej/pine-instance-uuid-1.8/channels/chan_sip.c
    team/oej/pine-instance-uuid-1.8/channels/iax2-parser.c
    team/oej/pine-instance-uuid-1.8/channels/misdn/isdn_msg_parser.c
    team/oej/pine-instance-uuid-1.8/channels/sig_pri.c
    team/oej/pine-instance-uuid-1.8/channels/sig_ss7.c
    team/oej/pine-instance-uuid-1.8/channels/sip/dialplan_functions.c
    team/oej/pine-instance-uuid-1.8/channels/sip/include/sip.h
    team/oej/pine-instance-uuid-1.8/channels/sip/reqresp_parser.c
    team/oej/pine-instance-uuid-1.8/configs/chan_dahdi.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/h323.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/iax.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/indications.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/queues.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/sip.conf.sample
    team/oej/pine-instance-uuid-1.8/configs/sla.conf.sample
    team/oej/pine-instance-uuid-1.8/configure.ac
    team/oej/pine-instance-uuid-1.8/contrib/realtime/postgresql/realtime.sql
    team/oej/pine-instance-uuid-1.8/default.exports
    team/oej/pine-instance-uuid-1.8/funcs/func_channel.c
    team/oej/pine-instance-uuid-1.8/funcs/func_dialgroup.c
    team/oej/pine-instance-uuid-1.8/funcs/func_global.c
    team/oej/pine-instance-uuid-1.8/funcs/func_strings.c
    team/oej/pine-instance-uuid-1.8/include/asterisk/astmm.h
    team/oej/pine-instance-uuid-1.8/include/asterisk/autoconfig.h.in
    team/oej/pine-instance-uuid-1.8/include/asterisk/frame.h
    team/oej/pine-instance-uuid-1.8/include/asterisk/lock.h
    team/oej/pine-instance-uuid-1.8/include/asterisk/logger.h
    team/oej/pine-instance-uuid-1.8/include/asterisk/utils.h
    team/oej/pine-instance-uuid-1.8/main/abstract_jb.c
    team/oej/pine-instance-uuid-1.8/main/asterisk.c
    team/oej/pine-instance-uuid-1.8/main/asterisk.exports.in
    team/oej/pine-instance-uuid-1.8/main/astfd.c
    team/oej/pine-instance-uuid-1.8/main/astmm.c
    team/oej/pine-instance-uuid-1.8/main/astobj2.c
    team/oej/pine-instance-uuid-1.8/main/cdr.c
    team/oej/pine-instance-uuid-1.8/main/cel.c
    team/oej/pine-instance-uuid-1.8/main/channel.c
    team/oej/pine-instance-uuid-1.8/main/cli.c
    team/oej/pine-instance-uuid-1.8/main/config.c
    team/oej/pine-instance-uuid-1.8/main/data.c
    team/oej/pine-instance-uuid-1.8/main/event.c
    team/oej/pine-instance-uuid-1.8/main/features.c
    team/oej/pine-instance-uuid-1.8/main/heap.c
    team/oej/pine-instance-uuid-1.8/main/http.c
    team/oej/pine-instance-uuid-1.8/main/indications.c
    team/oej/pine-instance-uuid-1.8/main/loader.c
    team/oej/pine-instance-uuid-1.8/main/lock.c
    team/oej/pine-instance-uuid-1.8/main/logger.c
    team/oej/pine-instance-uuid-1.8/main/manager.c
    team/oej/pine-instance-uuid-1.8/main/pbx.c
    team/oej/pine-instance-uuid-1.8/main/slinfactory.c
    team/oej/pine-instance-uuid-1.8/main/threadstorage.c
    team/oej/pine-instance-uuid-1.8/main/utils.c
    team/oej/pine-instance-uuid-1.8/main/xmldoc.c
    team/oej/pine-instance-uuid-1.8/pbx/pbx_dundi.c
    team/oej/pine-instance-uuid-1.8/pbx/pbx_loopback.c
    team/oej/pine-instance-uuid-1.8/res/res_agi.c
    team/oej/pine-instance-uuid-1.8/res/res_jabber.c
    team/oej/pine-instance-uuid-1.8/res/res_musiconhold.c
    team/oej/pine-instance-uuid-1.8/res/res_rtp_asterisk.c
    team/oej/pine-instance-uuid-1.8/res/res_security_log.c
    team/oej/pine-instance-uuid-1.8/res/res_srtp.c
    team/oej/pine-instance-uuid-1.8/sounds/Makefile
    team/oej/pine-instance-uuid-1.8/tests/test_hashtab_thrash.c
    team/oej/pine-instance-uuid-1.8/tests/test_substitution.c
    team/oej/pine-instance-uuid-1.8/utils/   (props changed)
    team/oej/pine-instance-uuid-1.8/utils/Makefile
    team/oej/pine-instance-uuid-1.8/utils/ael_main.c
    team/oej/pine-instance-uuid-1.8/utils/check_expr.c
    team/oej/pine-instance-uuid-1.8/utils/conf2ael.c
    team/oej/pine-instance-uuid-1.8/utils/extconf.c

Propchange: team/oej/pine-instance-uuid-1.8/
------------------------------------------------------------------------------
    automerge = Is-there-life-off-net?

Propchange: team/oej/pine-instance-uuid-1.8/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Oct  1 02:43:31 2013
@@ -24,3 +24,4 @@
 makeopts.embed_rules
 aclocal.m4
 update.log
+doxygen.log

Propchange: team/oej/pine-instance-uuid-1.8/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Oct  1 02:43:31 2013
@@ -1,1 +1,1 @@
-/branches/1.8:1-386606
+/branches/1.8:1-400213

Modified: team/oej/pine-instance-uuid-1.8/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-instance-uuid-1.8/CHANGES?view=diff&rev=400214&r1=400213&r2=400214
==============================================================================
--- team/oej/pine-instance-uuid-1.8/CHANGES (original)
+++ team/oej/pine-instance-uuid-1.8/CHANGES Tue Oct  1 02:43:31 2013
@@ -7,6 +7,15 @@
 === and the other UPGRADE files for older releases.
 ===
 ======================================================================
+
+------------------------------------------------------------------------------
+--- Functionality changes since Asterisk 1.8.19.1 ----------------------------
+------------------------------------------------------------------------------
+
+App_queue
+---------
+ * App_queue will now play periodic announcements for the caller that
+   holds the first position in the queue while waiting for answer.
 
 ------------------------------------------------------------------------------
 --- Functionality changes since Asterisk 1.8.12.0 ----------------------------

Modified: team/oej/pine-instance-uuid-1.8/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-instance-uuid-1.8/UPGRADE.txt?view=diff&rev=400214&r1=400213&r2=400214
==============================================================================
--- team/oej/pine-instance-uuid-1.8/UPGRADE.txt (original)
+++ team/oej/pine-instance-uuid-1.8/UPGRADE.txt Tue Oct  1 02:43:31 2013
@@ -17,10 +17,25 @@
 === UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6
 ===
 ===========================================================
+from 1.8.23.0 to 1.8.24.0:
+* res_agi will now properly indicate if there was an error in streaming an
+  audio file.  The result code will be -1 and the result returned from the
+  the function will be RESULT_FAILURE instead of the prior behavior of always
+  returning RESULT_SUCCESS even if there was an error. 
+
+* The option "register_retry_403" has been added to chan_sip to work around
+  servers that are known to erroneously send 403 in response to valid
+  REGISTER requests and allows Asterisk to continue attepmting to connect.
 
 from 1.8.22.0 to 1.8.23.0:
 * The default settings for chan_sip are now overriden properly by the general
   settings in sip.conf.  Please look over your settings upon upgrading.
+
+* It is now possible to play the Queue prompts to the first user waiting in a call queue.
+  Note that this may impact the ability for agents to talk with users, as a prompt may
+  still be playing when an agent connects to the user. This ability is disabled by
+  default but can be enabled on an individual queue using the 'announce-to-first-user'
+  option.
 
 from 1.8.21.0 to 1.8.22.0:
 * Added the 'n' option to MeetMe to prevent application of the DENOISE function

Modified: team/oej/pine-instance-uuid-1.8/addons/chan_ooh323.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-instance-uuid-1.8/addons/chan_ooh323.c?view=diff&rev=400214&r1=400213&r2=400214
==============================================================================
--- team/oej/pine-instance-uuid-1.8/addons/chan_ooh323.c (original)
+++ team/oej/pine-instance-uuid-1.8/addons/chan_ooh323.c Tue Oct  1 02:43:31 2013
@@ -286,6 +286,8 @@
 int onCallCleared(ooCallData *call);
 void onModeChanged(ooCallData *call, int t38mode);
 
+extern OOH323EndPoint gH323ep;
+
 static char gLogFile[256] = DEFAULT_LOGFILE;
 static int  gPort = 1720;
 static char gIP[20];
@@ -629,6 +631,7 @@
 		ooh323_destroy(p);
 		ast_mutex_unlock(&iflock);
 		ast_log(LOG_ERROR, "Destination format is not supported\n");
+		*cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
 		return NULL;
 	}
 
@@ -671,6 +674,10 @@
 			ast_mutex_unlock(&p->lock);
 			ooh323_destroy(p);
 			ast_mutex_unlock(&iflock);
+			return NULL;
+		} else if (gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered) {
+			ast_log(LOG_ERROR, "Gatekeeper client is configured but not registered\n");
+			*cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
 			return NULL;
 		}
 		p->g729onlyA = g729onlyA;

Modified: team/oej/pine-instance-uuid-1.8/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pine-instance-uuid-1.8/apps/app_meetme.c?view=diff&rev=400214&r1=400213&r2=400214
==============================================================================
--- team/oej/pine-instance-uuid-1.8/apps/app_meetme.c (original)
+++ team/oej/pine-instance-uuid-1.8/apps/app_meetme.c Tue Oct  1 02:43:31 2013
@@ -832,17 +832,26 @@
 	/*! This option uses the values in the sla_hold_access enum and sets the
 	 * access control type for hold on this station. */
 	unsigned int hold_access:1;
-	/*! Use count for inside sla_station_exec */
-	unsigned int ref_count;
+	/*! Mark used during reload processing */
+	unsigned int mark:1;
 };
 
+/*!
+ * \brief A reference to a station
+ *
+ * This struct looks near useless at first glance.  However, its existence
+ * in the list of stations in sla_trunk means that this station references
+ * that trunk.  We use the mark to keep track of whether it needs to be
+ * removed from the sla_trunk's list of stations during a reload.
+ */
 struct sla_station_ref {
 	AST_LIST_ENTRY(sla_station_ref) entry;
 	struct sla_station *station;
+	/*! Mark used during reload processing */
+	unsigned int mark:1;
 };
 
 struct sla_trunk {
-	AST_RWLIST_ENTRY(sla_trunk) entry;
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(name);
 		AST_STRING_FIELD(device);
@@ -866,10 +875,16 @@
 	/*! Whether this trunk is currently on hold, meaning that once a station
 	 *  connects to it, the trunk channel needs to have UNHOLD indicated to it. */
 	unsigned int on_hold:1;
-	/*! Use count for inside sla_trunk_exec */
-	unsigned int ref_count;
+	/*! Mark used during reload processing */
+	unsigned int mark:1;
 };
 
+/*!
+ * \brief A station's reference to a trunk
+ *
+ * An sla_station keeps a list of trunk_refs.  This holds metadata about the
+ * stations usage of the trunk.
+ */
 struct sla_trunk_ref {
 	AST_LIST_ENTRY(sla_trunk_ref) entry;
 	struct sla_trunk *trunk;
@@ -883,10 +898,12 @@
 	 *  station.  This takes higher priority than a ring delay set at
 	 *  the station level. */
 	unsigned int ring_delay;
+	/*! Mark used during reload processing */
+	unsigned int mark:1;
 };
 
-static AST_RWLIST_HEAD_STATIC(sla_stations, sla_station);
-static AST_RWLIST_HEAD_STATIC(sla_trunks, sla_trunk);
+static struct ao2_container *sla_stations;
+static struct ao2_container *sla_trunks;
 
 static const char sla_registrar[] = "SLA";
 
@@ -898,10 +915,6 @@
 	SLA_EVENT_DIAL_STATE,
 	/*! The state of a ringing trunk has changed */
 	SLA_EVENT_RINGING_TRUNK,
-	/*! A reload of configuration has been requested */
-	SLA_EVENT_RELOAD,
-	/*! Poke the SLA thread so it can check if it can perform a reload */
-	SLA_EVENT_CHECK_RELOAD,
 };
 
 struct sla_event {
@@ -957,8 +970,6 @@
 	/*! Attempt to handle CallerID, even though it is known not to work
 	 *  properly in some situations. */
 	unsigned int attempt_callerid:1;
-	/*! A reload has been requested */
-	unsigned int reload:1;
 } sla = {
 	.thread = AST_PTHREADT_NULL,
 };
@@ -1719,7 +1730,8 @@
 
 static char *sla_show_trunks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	const struct sla_trunk *trunk;
+	struct ao2_iterator i;
+	struct sla_trunk *trunk;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -1737,12 +1749,17 @@
 	            "=== Configured SLA Trunks ===================================\n"
 	            "=============================================================\n"
 	            "===\n");
-	AST_RWLIST_RDLOCK(&sla_trunks);
-	AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) {
+	i = ao2_iterator_init(sla_trunks, 0);
+	for (; (trunk = ao2_iterator_next(&i)); ao2_ref(trunk, -1)) {
 		struct sla_station_ref *station_ref;
 		char ring_timeout[16] = "(none)";
-		if (trunk->ring_timeout)
+
+		ao2_lock(trunk);
+
+		if (trunk->ring_timeout) {
 			snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout);
+		}
+
 		ast_cli(a->fd, "=== ---------------------------------------------------------\n"
 		            "=== Trunk Name:       %s\n"
 		            "=== ==> Device:       %s\n"
@@ -1756,13 +1773,16 @@
 		            ring_timeout,
 		            trunk->barge_disabled ? "No" : "Yes",
 		            sla_hold_str(trunk->hold_access));
-		AST_RWLIST_RDLOCK(&sla_stations);
-		AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry)
+
+		AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
 			ast_cli(a->fd, "===    ==> Station name: %s\n", station_ref->station->name);
-		AST_RWLIST_UNLOCK(&sla_stations);
+		}
+
 		ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
-	}
-	AST_RWLIST_UNLOCK(&sla_trunks);
+
+		ao2_unlock(trunk);
+	}
+	ao2_iterator_destroy(&i);
 	ast_cli(a->fd, "=============================================================\n\n");
 
 	return CLI_SUCCESS;
@@ -1784,7 +1804,8 @@
 
 static char *sla_show_stations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	const struct sla_station *station;
+	struct ao2_iterator i;
+	struct sla_station *station;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -1802,11 +1823,14 @@
 	            "=== Configured SLA Stations =================================\n"
 	            "=============================================================\n"
 	            "===\n");
-	AST_RWLIST_RDLOCK(&sla_stations);
-	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
+	i = ao2_iterator_init(sla_stations, 0);
+	for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
 		struct sla_trunk_ref *trunk_ref;
 		char ring_timeout[16] = "(none)";
 		char ring_delay[16] = "(none)";
+
+		ao2_lock(station);
+
 		if (station->ring_timeout) {
 			snprintf(ring_timeout, sizeof(ring_timeout), 
 				"%u", station->ring_timeout);
@@ -1827,7 +1851,6 @@
 		            S_OR(station->autocontext, "(none)"), 
 		            ring_timeout, ring_delay,
 		            sla_hold_str(station->hold_access));
-		AST_RWLIST_RDLOCK(&sla_trunks);
 		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
 			if (trunk_ref->ring_timeout) {
 				snprintf(ring_timeout, sizeof(ring_timeout),
@@ -1847,11 +1870,12 @@
 			            trunkstate2str(trunk_ref->state),
 			            ring_timeout, ring_delay);
 		}
-		AST_RWLIST_UNLOCK(&sla_trunks);
 		ast_cli(a->fd, "=== ---------------------------------------------------------\n"
 		            "===\n");
-	}
-	AST_RWLIST_UNLOCK(&sla_stations);
+
+		ao2_unlock(station);
+	}
+	ao2_iterator_destroy(&i);
 	ast_cli(a->fd, "============================================================\n"
 	            "\n");
 
@@ -1991,11 +2015,16 @@
 	struct sla_event *event;
 
 	if (sla.thread == AST_PTHREADT_NULL) {
+		ao2_ref(station, -1);
+		ao2_ref(trunk_ref, -1);
 		return;
 	}
 
-	if (!(event = ast_calloc(1, sizeof(*event))))
+	if (!(event = ast_calloc(1, sizeof(*event)))) {
+		ao2_ref(station, -1);
+		ao2_ref(trunk_ref, -1);
 		return;
+	}
 
 	event->type = type;
 	event->trunk_ref = trunk_ref;
@@ -2029,6 +2058,7 @@
 	struct sla_station *station;
 	struct sla_trunk_ref *trunk_ref = NULL;
 	char *trunk_name;
+	struct ao2_iterator i;
 
 	trunk_name = ast_strdupa(conf->confno);
 	strsep(&trunk_name, "_");
@@ -2037,16 +2067,23 @@
 		return;
 	}
 
-	AST_RWLIST_RDLOCK(&sla_stations);
-	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
+	i = ao2_iterator_init(sla_stations, 0);
+	while ((station = ao2_iterator_next(&i))) {
+		ao2_lock(station);
 		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
-			if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name))
+			if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) {
+				ao2_ref(trunk_ref, 1);
 				break;
-		}
-		if (trunk_ref)
+			}
+		}
+		ao2_unlock(station);
+		if (trunk_ref) {
+			/* station reference given to sla_queue_event_full() */
 			break;
-	}
-	AST_RWLIST_UNLOCK(&sla_stations);
+		}
+		ao2_ref(station, -1);
+	}
+	ao2_iterator_destroy(&i);
 
 	if (!trunk_ref) {
 		ast_debug(1, "Trunk not found for event!\n");
@@ -4801,6 +4838,23 @@
 			res = -2;
 			goto usernotfound;
 		}
+	} else {
+		/* fail for commands that require a user */
+		switch (*args.command) {
+		case 'm': /* Unmute */
+		case 'M': /* Mute */
+		case 't': /* Lower user's talk volume */
+		case 'T': /* Raise user's talk volume */
+		case 'u': /* Lower user's listen volume */
+		case 'U': /* Raise user's listen volume */
+		case 'r': /* Reset user's volume level */
+		case 'k': /* Kick user */
+			res = -2;
+			ast_log(LOG_NOTICE, "No user specified!\n");
+			goto usernotfound;
+		default:
+			break;
+		}
 	}
 
 	switch (*args.command) {
@@ -4816,21 +4870,24 @@
 	case 101: /* e: Eject last user*/
 	{
 		int max_no = 0;
-
-		/* If they passed in a user, disregard it */
-		if (user) {
-			ao2_ref(user, -1);
-		}
+		struct ast_conf_user *eject_user;
 
 		ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no);
-		user = ao2_find(cnf->usercontainer, &max_no, 0);
-		if (!ast_test_flag64(&user->userflags, CONFFLAG_ADMIN))
-			user->adminflags |= ADMINFLAG_KICKME;
-		else {
+		eject_user = ao2_find(cnf->usercontainer, &max_no, 0);
+		if (!eject_user) {
+			res = -1;
+			ast_log(LOG_NOTICE, "No last user to kick!\n");
+			break;
+		}
+
+		if (!ast_test_flag64(&eject_user->userflags, CONFFLAG_ADMIN)) {
+			eject_user->adminflags |= ADMINFLAG_KICKME;
+		} else {
 			res = -1;
 			ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n");
 		}
-		ao2_ref(user, -1);
+
+		ao2_ref(eject_user, -1);
 		break;
 	}
 	case 77: /* M: Mute */ 
@@ -5292,34 +5349,41 @@
 	ast_config_destroy(cfg);
 }
 
-/*! \brief Find an SLA trunk by name
- * \note This must be called with the sla_trunks container locked
+/*!
+ * \private
+ * \brief helper for RAII_VAR
+ */
+static void unref_obj(void *obj)
+{
+	if (obj) {
+		ao2_ref(obj, -1);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Find an SLA trunk by name
  */
 static struct sla_trunk *sla_find_trunk(const char *name)
 {
-	struct sla_trunk *trunk = NULL;
-
-	AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) {
-		if (!strcasecmp(trunk->name, name))
-			break;
-	}
-
-	return trunk;
-}
-
-/*! \brief Find an SLA station by name
- * \note This must be called with the sla_stations container locked
+	struct sla_trunk tmp_trunk = {
+		.name = name,
+	};
+
+	return ao2_find(sla_trunks, &tmp_trunk, OBJ_POINTER);
+}
+
+/*!
+ * \internal
+ * \brief Find an SLA station by name
  */
 static struct sla_station *sla_find_station(const char *name)
 {
-	struct sla_station *station = NULL;
-
-	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
-		if (!strcasecmp(station->name, name))
-			break;
-	}
-
-	return station;
+	struct sla_station tmp_station = {
+		.name = name,
+	};
+
+	return ao2_find(sla_stations, &tmp_station, OBJ_POINTER);
 }
 
 static int sla_check_station_hold_access(const struct sla_trunk *trunk,
@@ -5343,9 +5407,11 @@
 	return 0;
 }
 
-/*! \brief Find a trunk reference on a station by name
+/*!
+ * \brief Find a trunk reference on a station by name
  * \param station the station
  * \param name the trunk's name
+ * \pre sla_station is locked
  * \return a pointer to the station's trunk reference.  If the trunk
  *         is not found, it is not idle and barge is disabled, or if
  *         it is on hold and private hold is set, then NULL will be returned.
@@ -5372,16 +5438,32 @@
 		break;
 	}
 
+	if (trunk_ref) {
+		ao2_ref(trunk_ref, 1);
+	}
+
 	return trunk_ref;
 }
 
+static void sla_station_ref_destructor(void *obj)
+{
+	struct sla_station_ref *station_ref = obj;
+
+	if (station_ref->station) {
+		ao2_ref(station_ref->station, -1);
+		station_ref->station = NULL;
+	}
+}
+
 static struct sla_station_ref *sla_create_station_ref(struct sla_station *station)
 {
 	struct sla_station_ref *station_ref;
 
-	if (!(station_ref = ast_calloc(1, sizeof(*station_ref))))
+	if (!(station_ref = ao2_alloc(sizeof(*station_ref), sla_station_ref_destructor))) {
 		return NULL;
-
+	}
+
+	ao2_ref(station, 1);
 	station_ref->station = station;
 
 	return station_ref;
@@ -5394,10 +5476,46 @@
 	if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station))))
 		return NULL;
 
+	ao2_ref(station, 1);
 	ringing_station->station = station;
 	ringing_station->ring_begin = ast_tvnow();
 
 	return ringing_station;
+}
+
+static void sla_ringing_station_destroy(struct sla_ringing_station *ringing_station)
+{
+	if (ringing_station->station) {
+		ao2_ref(ringing_station->station, -1);
+		ringing_station->station = NULL;
+	}
+
+	ast_free(ringing_station);
+}
+
+static struct sla_failed_station *sla_create_failed_station(struct sla_station *station)
+{
+	struct sla_failed_station *failed_station;
+
+	if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) {
+		return NULL;
+	}
+
+	ao2_ref(station, 1);
+	failed_station->station = station;
+	failed_station->last_try = ast_tvnow();
+
+	return failed_station;
+}
+
+static void sla_failed_station_destroy(struct sla_failed_station *failed_station)
+{
+	if (failed_station->station) {
+		ao2_ref(failed_station->station, -1);
+		failed_station->station = NULL;
+	}
+
+	ast_free(failed_station);
 }
 
 static enum ast_device_state sla_state_to_devstate(enum sla_trunk_state state)
@@ -5422,18 +5540,25 @@
 {
 	struct sla_station *station;
 	struct sla_trunk_ref *trunk_ref;
-
-	AST_LIST_TRAVERSE(&sla_stations, station, entry) {
+	struct ao2_iterator i;
+
+	i = ao2_iterator_init(sla_stations, 0);
+	while ((station = ao2_iterator_next(&i))) {
+		ao2_lock(station);
 		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
 			if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0)
-				|| trunk_ref == exclude)
+					|| trunk_ref == exclude) {
 				continue;
+			}
 			trunk_ref->state = state;
 			ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE,
 					     "SLA:%s_%s", station->name, trunk->name);
 			break;
 		}
-	}
+		ao2_unlock(station);
+		ao2_ref(station, -1);
+	}
+	ao2_iterator_destroy(&i);
 }
 
 struct run_station_args {
@@ -5451,8 +5576,8 @@
 
 static void *run_station(void *data)
 {
-	struct sla_station *station;
-	struct sla_trunk_ref *trunk_ref;
+	RAII_VAR(struct sla_station *, station, NULL, unref_obj);
+	RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj);
 	struct ast_str *conf_name = ast_str_create(16);
 	struct ast_flags64 conf_flags = { 0 };
 	struct ast_conference *conf;
@@ -5495,6 +5620,8 @@
 	return NULL;
 }
 
+static void sla_ringing_trunk_destroy(struct sla_ringing_trunk *ringing_trunk);
+
 static void sla_stop_ringing_trunk(struct sla_ringing_trunk *ringing_trunk)
 {
 	char buf[80];
@@ -5504,10 +5631,11 @@
 	admin_exec(NULL, buf);
 	sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
 
-	while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry)))
-		ast_free(station_ref);
-
-	ast_free(ringing_trunk);
+	while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) {
+		ao2_ref(station_ref, -1);
+	}
+
+	sla_ringing_trunk_destroy(ringing_trunk);
 }
 
 static void sla_stop_ringing_station(struct sla_ringing_station *ringing_station,
@@ -5542,7 +5670,7 @@
 	}
 
 done:
-	ast_free(ringing_station);
+	sla_ringing_station_destroy(ringing_station);
 }
 
 static void sla_dial_state_callback(struct ast_dial *dial)
@@ -5594,8 +5722,10 @@
 			if (rm)
 				AST_LIST_REMOVE_CURRENT(entry);
 
-			if (trunk_ref)
+			if (trunk_ref) {
+				ao2_ref(s_trunk_ref, 1);
 				*trunk_ref = s_trunk_ref;
+			}
 
 			break;
 		}
@@ -5613,7 +5743,7 @@
 	struct sla_ringing_station *ringing_station;
 
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
-		struct sla_trunk_ref *s_trunk_ref = NULL;
+		RAII_VAR(struct sla_trunk_ref *, s_trunk_ref, NULL, unref_obj);
 		struct sla_ringing_trunk *ringing_trunk = NULL;
 		struct run_station_args args;
 		enum ast_dial_result dial_res;
@@ -5646,7 +5776,7 @@
 				ast_dial_join(ringing_station->station->dial);
 				ast_dial_destroy(ringing_station->station->dial);
 				ringing_station->station->dial = NULL;
-				ast_free(ringing_station);
+				sla_ringing_station_destroy(ringing_station);
 				break;
 			}
 			/* Track the channel that answered this trunk */
@@ -5657,12 +5787,14 @@
 			/* Now, start a thread that will connect this station to the trunk.  The rest of
 			 * the code here sets up the thread and ensures that it is able to save the arguments
 			 * before they are no longer valid since they are allocated on the stack. */
+			ao2_ref(s_trunk_ref, 1);
 			args.trunk_ref = s_trunk_ref;
+			ao2_ref(ringing_station->station, 1);
 			args.station = ringing_station->station;
 			args.cond = &cond;
 			args.cond_lock = &cond_lock;
-			ast_free(ringing_trunk);
-			ast_free(ringing_station);
+			sla_ringing_trunk_destroy(ringing_trunk);
+			sla_ringing_station_destroy(ringing_station);
 			ast_mutex_init(&cond_lock);
 			ast_cond_init(&cond, NULL);
 			ast_mutex_lock(&cond_lock);
@@ -5716,7 +5848,7 @@
 			continue;
 		if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) {
 			AST_LIST_REMOVE_CURRENT(entry);
-			ast_free(failed_station);
+			sla_failed_station_destroy(failed_station);
 			break;
 		}
 		res = 1;
@@ -5769,11 +5901,9 @@
 	if (res != AST_DIAL_RESULT_TRYING) {
 		struct sla_failed_station *failed_station;
 		ast_dial_destroy(dial);
-		if (!(failed_station = ast_calloc(1, sizeof(*failed_station))))
-			return -1;
-		failed_station->station = station;
-		failed_station->last_try = ast_tvnow();
-		AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry);
+		if ((failed_station = sla_create_failed_station(station))) {
+			AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry);
+		}
 		return -1;
 	}
 	if (!(ringing_station = sla_create_ringing_station(station))) {
@@ -5812,6 +5942,8 @@
 		if (trunk_ref->trunk == trunk)
 			break;
 	}
+
+	ao2_ref(trunk_ref, 1);
 
 	return trunk_ref;
 }
@@ -5824,7 +5956,7 @@
 static int sla_check_station_delay(struct sla_station *station, 
 	struct sla_ringing_trunk *ringing_trunk)
 {
-	struct sla_trunk_ref *trunk_ref;
+	RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj);
 	unsigned int delay = UINT_MAX;
 	int time_left, time_elapsed;
 
@@ -5917,7 +6049,7 @@
 			ast_dial_join(ringing_station->station->dial);
 			ast_dial_destroy(ringing_station->station->dial);
 			ringing_station->station->dial = NULL;
-			ast_free(ringing_station);
+			sla_ringing_station_destroy(ringing_station);
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END
@@ -6074,8 +6206,10 @@
 {
 	struct sla_station *station;
 	int res = 0;
-
-	AST_LIST_TRAVERSE(&sla_stations, station, entry) {
+	struct ao2_iterator i;
+
+	i = ao2_iterator_init(sla_stations, 0);
+	for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
 		struct sla_ringing_trunk *ringing_trunk;
 		int time_left;
 
@@ -6105,6 +6239,7 @@
 		if (time_left < *timeout)
 			*timeout = time_left;
 	}
+	ao2_iterator_destroy(&i);
 
 	return res;
 }
@@ -6146,49 +6281,19 @@
 	return 1;
 }
 
-static int sla_load_config(int reload);
-
-/*! \brief Check if we can do a reload of SLA, and do it if we can */
-static void sla_check_reload(void)
-{
-	struct sla_station *station;
-	struct sla_trunk *trunk;
-
-	ast_mutex_lock(&sla.lock);
-
-	if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 
-		|| !AST_LIST_EMPTY(&sla.ringing_stations)) {
-		ast_mutex_unlock(&sla.lock);
-		return;
-	}
-
-	AST_RWLIST_RDLOCK(&sla_stations);
-	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
-		if (station->ref_count)
-			break;
-	}
-	AST_RWLIST_UNLOCK(&sla_stations);
-	if (station) {
-		ast_mutex_unlock(&sla.lock);
-		return;
-	}
-
-	AST_RWLIST_RDLOCK(&sla_trunks);
-	AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) {
-		if (trunk->ref_count)
-			break;
-	}
-	AST_RWLIST_UNLOCK(&sla_trunks);
-	if (trunk) {
-		ast_mutex_unlock(&sla.lock);
-		return;
-	}
-
-	/* yay */
-	sla_load_config(1);
-	sla.reload = 0;
-
-	ast_mutex_unlock(&sla.lock);
+static void sla_event_destroy(struct sla_event *event)
+{
+	if (event->trunk_ref) {
+		ao2_ref(event->trunk_ref, -1);
+		event->trunk_ref = NULL;
+	}
+
+	if (event->station) {
+		ao2_ref(event->station, -1);
+		event->station = NULL;
+	}
+
+	ast_free(event);
 }
 
 static void *sla_thread(void *data)
@@ -6227,27 +6332,21 @@
 			case SLA_EVENT_RINGING_TRUNK:
 				sla_handle_ringing_trunk_event();
 				break;
-			case SLA_EVENT_RELOAD:
-				sla.reload = 1;
-			case SLA_EVENT_CHECK_RELOAD:
-				break;
-			}
-			ast_free(event);
+			}
+			sla_event_destroy(event);
 			ast_mutex_lock(&sla.lock);
 		}
-
-		if (sla.reload) {
-			sla_check_reload();
-		}
 	}
 
 	ast_mutex_unlock(&sla.lock);
 
-	while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry)))
-		ast_free(ringing_station);
-
-	while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry)))
-		ast_free(failed_station);
+	while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) {
+		sla_ringing_station_destroy(ringing_station);
+	}
+
+	while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) {
+		sla_failed_station_destroy(failed_station);
+	}
 
 	return NULL;
 }
@@ -6268,7 +6367,8 @@
 	char conf_name[MAX_CONFNUM];
 	struct ast_conference *conf;
 	struct ast_flags64 conf_flags = { 0 };
-	struct sla_trunk_ref *trunk_ref = args->trunk_ref;
+	RAII_VAR(struct sla_trunk_ref *, trunk_ref, args->trunk_ref, unref_obj);
+	RAII_VAR(struct sla_station *, station, args->station, unref_obj);
 	int caller_is_saved;
 	struct ast_party_caller caller;
 	int last_state = 0;
@@ -6340,8 +6440,8 @@
 			break;
 
 		/* check that SLA station that originated trunk call is still alive */
-		if (args->station && ast_device_state(args->station->device) == AST_DEVICE_NOT_INUSE) {
-			ast_debug(3, "Originating station device %s no longer active\n", args->station->device);
+		if (station && ast_device_state(station->device) == AST_DEVICE_NOT_INUSE) {
+			ast_debug(3, "Originating station device %s no longer active\n", station->device);
 			trunk_ref->trunk->chan = NULL;
 			break;
 		}
@@ -6394,15 +6494,19 @@
 	return NULL;
 }
 
-/*! \brief For a given station, choose the highest priority idle trunk
+/*!
+ * \brief For a given station, choose the highest priority idle trunk
+ * \pre sla_station is locked
  */
 static struct sla_trunk_ref *sla_choose_idle_trunk(const struct sla_station *station)
 {
 	struct sla_trunk_ref *trunk_ref = NULL;
 
 	AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
-		if (trunk_ref->state == SLA_TRUNK_STATE_IDLE)
+		if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) {
+			ao2_ref(trunk_ref, 1);
 			break;
+		}
 	}
 
 	return trunk_ref;
@@ -6411,8 +6515,8 @@
 static int sla_station_exec(struct ast_channel *chan, const char *data)
 {
 	char *station_name, *trunk_name;
-	struct sla_station *station;
-	struct sla_trunk_ref *trunk_ref = NULL;
+	RAII_VAR(struct sla_station *, station, NULL, unref_obj);
+	RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj);
 	char conf_name[MAX_CONFNUM];
 	struct ast_flags64 conf_flags = { 0 };
 	struct ast_conference *conf;
@@ -6432,25 +6536,21 @@
 		return 0;
 	}
 
-	AST_RWLIST_RDLOCK(&sla_stations);
 	station = sla_find_station(station_name);
-	if (station)
-		ast_atomic_fetchadd_int((int *) &station->ref_count, 1);
-	AST_RWLIST_UNLOCK(&sla_stations);
 
 	if (!station) {
 		ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name);
 		pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);
 		return 0;
 	}
 
-	AST_RWLIST_RDLOCK(&sla_trunks);
+	ao2_lock(station);
 	if (!ast_strlen_zero(trunk_name)) {
 		trunk_ref = sla_find_trunk_ref_byname(station, trunk_name);
-	} else
+	} else {
 		trunk_ref = sla_choose_idle_trunk(station);
-	AST_RWLIST_UNLOCK(&sla_trunks);
+	}
+	ao2_unlock(station);
 
 	if (!trunk_ref) {
 		if (ast_strlen_zero(trunk_name))
@@ -6460,8 +6560,6 @@
 				"'%s' due to access controls.\n", trunk_name);
 		}
 		pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
-		ast_atomic_fetchadd_int((int *) &station->ref_count, -1);
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);
 		return 0;
 	}
 
@@ -6490,7 +6588,7 @@
 			answer_trunk_chan(ringing_trunk->trunk->chan);
 			sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
 
-			free(ringing_trunk);
+			sla_ringing_trunk_destroy(ringing_trunk);
 
 			/* Queue up reprocessing ringing trunks, and then ringing stations again */
 			sla_queue_event(SLA_EVENT_RINGING_TRUNK);
@@ -6510,6 +6608,8 @@
 			.cond_lock = &cond_lock,
 			.cond = &cond,
 		};
+		ao2_ref(trunk_ref, 1);
+		ao2_ref(station, 1);
 		sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
 		/* Create a thread to dial the trunk and dump it into the conference.
 		 * However, we want to wait until the trunk has been dialed and the
@@ -6529,8 +6629,6 @@
 			pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
 			sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
 			trunk_ref->chan = NULL;
-			ast_atomic_fetchadd_int((int *) &station->ref_count, -1);
-			sla_queue_event(SLA_EVENT_CHECK_RELOAD);
 			return 0;
 		}
 	}
@@ -6563,19 +6661,28 @@
 	
 	pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS");
 
-	ast_atomic_fetchadd_int((int *) &station->ref_count, -1);
-	sla_queue_event(SLA_EVENT_CHECK_RELOAD);
-
 	return 0;
 }
 
+static void sla_trunk_ref_destructor(void *obj)
+{
+	struct sla_trunk_ref *trunk_ref = obj;
+
+	if (trunk_ref->trunk) {
+		ao2_ref(trunk_ref->trunk, -1);
+		trunk_ref->trunk = NULL;
+	}
+}
+
 static struct sla_trunk_ref *create_trunk_ref(struct sla_trunk *trunk)
 {
 	struct sla_trunk_ref *trunk_ref;
 
-	if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref))))
+	if (!(trunk_ref = ao2_alloc(sizeof(*trunk_ref), sla_trunk_ref_destructor))) {
 		return NULL;
-
+	}
+
+	ao2_ref(trunk, 1);
 	trunk_ref->trunk = trunk;
 
 	return trunk_ref;
@@ -6585,9 +6692,11 @@
 {
 	struct sla_ringing_trunk *ringing_trunk;
 
-	if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk))))
+	if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) {
 		return NULL;
-	
+	}
+
+	ao2_ref(trunk, 1);
 	ringing_trunk->trunk = trunk;
 	ringing_trunk->ring_begin = ast_tvnow();
 
@@ -6600,6 +6709,16 @@
 	sla_queue_event(SLA_EVENT_RINGING_TRUNK);
 
 	return ringing_trunk;
+}
+
+static void sla_ringing_trunk_destroy(struct sla_ringing_trunk *ringing_trunk)
+{
+	if (ringing_trunk->trunk) {
+		ao2_ref(ringing_trunk->trunk, -1);
+		ringing_trunk->trunk = NULL;
+	}
+
+	ast_free(ringing_trunk);
 }
 
 enum {
@@ -6620,7 +6739,7 @@
 	char conf_name[MAX_CONFNUM];
 	struct ast_conference *conf;
 	struct ast_flags64 conf_flags = { 0 };
-	struct sla_trunk *trunk;
+	RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj);
 	struct sla_ringing_trunk *ringing_trunk;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(trunk_name);
@@ -6644,16 +6763,11 @@
 		}
 	}
 
-	AST_RWLIST_RDLOCK(&sla_trunks);
 	trunk = sla_find_trunk(args.trunk_name);
-	if (trunk)
-		ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1);
-	AST_RWLIST_UNLOCK(&sla_trunks);
 
 	if (!trunk) {
 		ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name);
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);	
 		return 0;
 	}
 
@@ -6661,8 +6775,6 @@
 		ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n",
 			args.trunk_name);
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
-		ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1);
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);	
 		return 0;
 	}
 
@@ -6670,8 +6782,6 @@
 
 	if (!(ringing_trunk = queue_ringing_trunk(trunk))) {
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
-		ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1);
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);	
 		return 0;
 	}
 
@@ -6679,8 +6789,6 @@
 	conf = build_conf(conf_name, "", "", 1, 1, 1, chan, NULL);
 	if (!conf) {
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
-		ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1);
-		sla_queue_event(SLA_EVENT_CHECK_RELOAD);	
 		return 0;
 	}
 	ast_set_flag64(&conf_flags, 
@@ -6714,46 +6822,37 @@
 	AST_LIST_TRAVERSE_SAFE_END;
 	ast_mutex_unlock(&sla.lock);
 	if (ringing_trunk) {
-		ast_free(ringing_trunk);
+		sla_ringing_trunk_destroy(ringing_trunk);
 		pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED");
 		/* Queue reprocessing of ringing trunks to make stations stop ringing
 		 * that shouldn't be ringing after this trunk stopped. */
 		sla_queue_event(SLA_EVENT_RINGING_TRUNK);
 	}
 
-	ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1);
-	sla_queue_event(SLA_EVENT_CHECK_RELOAD);	
-
 	return 0;
 }
 
 static enum ast_device_state sla_state(const char *data)
 {
 	char *buf, *station_name, *trunk_name;
-	struct sla_station *station;
+	RAII_VAR(struct sla_station *, station, NULL, unref_obj);
 	struct sla_trunk_ref *trunk_ref;
 	enum ast_device_state res = AST_DEVICE_INVALID;
 
 	trunk_name = buf = ast_strdupa(data);
 	station_name = strsep(&trunk_name, "_");
 
-	AST_RWLIST_RDLOCK(&sla_stations);
-	AST_LIST_TRAVERSE(&sla_stations, station, entry) {
-		if (strcasecmp(station_name, station->name))
-			continue;
-		AST_RWLIST_RDLOCK(&sla_trunks);
+	station = sla_find_station(station_name);
+	if (station) {
+		ao2_lock(station);
 		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
-			if (!strcasecmp(trunk_name, trunk_ref->trunk->name))
+			if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) {
+				res = sla_state_to_devstate(trunk_ref->state);
 				break;
-		}
-		if (!trunk_ref) {
-			AST_RWLIST_UNLOCK(&sla_trunks);
-			break;
-		}
-		res = sla_state_to_devstate(trunk_ref->state);
-		AST_RWLIST_UNLOCK(&sla_trunks);
-	}
-	AST_RWLIST_UNLOCK(&sla_stations);
+			}
+		}
+		ao2_unlock(station);
+	}
 
 	if (res == AST_DEVICE_INVALID) {
 		ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n",
@@ -6763,26 +6862,39 @@
 	return res;
 }
 
-static void destroy_trunk(struct sla_trunk *trunk)
-{
+static int sla_trunk_release_refs(void *obj, void *arg, int flags)
+{
+	struct sla_trunk *trunk = obj;

[... 6103 lines stripped ...]



More information about the asterisk-commits mailing list