[svn-commits] russell: branch group/xcon_bfcp r54005 - in /team/group/xcon_bfcp: ./ apps/ c...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Mon Feb 12 09:21:33 MST 2007


Author: russell
Date: Mon Feb 12 10:21:32 2007
New Revision: 54005

URL: http://svn.digium.com/view/asterisk?view=rev&rev=54005
Log:
Merged revisions 53817,53819,53851,53882-53885,53914,53932-53933,53953,53980,54003-54004 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r53817 | russell | 2007-02-09 18:40:57 -0600 (Fri, 09 Feb 2007) | 32 lines

Merged revisions 53810 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r53810 | russell | 2007-02-09 18:35:09 -0600 (Fri, 09 Feb 2007) | 24 lines

Merge team/russell/sla_rewrite

This is a completely new implementation of the SLA functionality introduced in
Asterisk 1.4.  It is now functional and ready for testing.  However, I will be
adding some additional features over the next week, as well.

For information on how to set this up, see configs/sla.conf.sample 
and doc/sla.txt.

In addition to the changes in app_meetme.c for the SLA implementation itself,
this merge brings in various other changes:

chan_sip:
 - Add the ability to indicate HOLD state in NOTIFY messages.
 - Queue HOLD and UNHOLD control frames even if the channel is not bridged to
   another channel.

linkedlists.h:
 - Add support for rwlock based linked lists.

dial.c:
 - Add the ability to run ast_dial_start() without a reference channel to
   inherit information from.

........

................
r53819 | russell | 2007-02-09 18:42:19 -0600 (Fri, 09 Feb 2007) | 9 lines

Blocked revisions 53818 via svnmerge

........
r53818 | russell | 2007-02-09 18:41:57 -0600 (Fri, 09 Feb 2007) | 2 lines

Change some text to properly state "On Hold", which was already done in trunk.

........

................
r53851 | kpfleming | 2007-02-10 00:14:55 -0600 (Sat, 10 Feb 2007) | 11 lines

Merged revisions 53850 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r53850 | kpfleming | 2007-02-10 00:06:08 -0600 (Sat, 10 Feb 2007) | 3 lines

don't display the --with-imap message unless --with-imap was specified without a path
use '-n' instead of '! -z' for tests

........

................
r53882 | pcadach | 2007-02-10 03:19:58 -0600 (Sat, 10 Feb 2007) | 8 lines

Blocked revisions 53878 via svnmerge

........
r53878 | pcadach | 2007-02-10 01:04:47 -0800 (Сбт, 10 Фев 2007) | 1 line

Bring deprecated 'debug channel <x|all>' command back
........

................
r53883 | pcadach | 2007-02-10 03:21:22 -0600 (Sat, 10 Feb 2007) | 9 lines

Merged revisions 53879 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r53879 | pcadach | 2007-02-10 01:07:11 -0800 (Сбт, 10 Фев 2007) | 1 line

Provide correct DTMF duration
........

................
r53884 | pcadach | 2007-02-10 03:22:15 -0600 (Sat, 10 Feb 2007) | 9 lines

Merged revisions 53880 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r53880 | pcadach | 2007-02-10 01:08:55 -0800 (Сбт, 10 Фев 2007) | 1 line

Much simpler than previous one ;-)
........

................
r53885 | pcadach | 2007-02-10 03:23:09 -0600 (Sat, 10 Feb 2007) | 9 lines

Merged revisions 53881 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r53881 | pcadach | 2007-02-10 01:09:49 -0800 (Сбт, 10 Фев 2007) | 1 line

Fix VLDTMF reception
........

................
r53914 | oej | 2007-02-11 13:15:55 -0600 (Sun, 11 Feb 2007) | 2 lines

Fix debug handling in acl.c

................
r53932 | oej | 2007-02-11 13:42:55 -0600 (Sun, 11 Feb 2007) | 5 lines

Add support for outbound proxy for peers and [general]

This replaces the older, broken, implementation where a setting in
[general] did not do anything and the [peer] part was broken.

................
r53933 | oej | 2007-02-11 14:04:49 -0600 (Sun, 11 Feb 2007) | 2 lines

Small fix in outbound proxy support.

................
r53953 | oej | 2007-02-11 14:49:38 -0600 (Sun, 11 Feb 2007) | 2 lines

Be careful with debug messages in trunk, they tend to stay around for release....

................
r53980 | tilghman | 2007-02-11 20:44:33 -0600 (Sun, 11 Feb 2007) | 2 lines

Formatting fixes

................
r54003 | russell | 2007-02-12 09:40:23 -0600 (Mon, 12 Feb 2007) | 2 lines

Simplify a small bit of logic.

................
r54004 | russell | 2007-02-12 09:48:28 -0600 (Mon, 12 Feb 2007) | 10 lines

Merged revisions 54002 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r54002 | russell | 2007-02-12 10:38:39 -0500 (Mon, 12 Feb 2007) | 2 lines

Fix a typo where "vmpassword" should be "vmsecret"

........

................

Added:
    team/group/xcon_bfcp/doc/sla.txt
      - copied unchanged from r54004, trunk/doc/sla.txt
Modified:
    team/group/xcon_bfcp/   (props changed)
    team/group/xcon_bfcp/apps/app_echo.c
    team/group/xcon_bfcp/apps/app_meetme.c
    team/group/xcon_bfcp/channels/chan_h323.c
    team/group/xcon_bfcp/channels/chan_sip.c
    team/group/xcon_bfcp/configs/sip.conf.sample
    team/group/xcon_bfcp/configs/sla.conf.sample
    team/group/xcon_bfcp/configs/users.conf.sample
    team/group/xcon_bfcp/configure
    team/group/xcon_bfcp/configure.ac
    team/group/xcon_bfcp/funcs/func_realtime.c
    team/group/xcon_bfcp/include/asterisk/app.h
    team/group/xcon_bfcp/include/asterisk/dial.h
    team/group/xcon_bfcp/include/asterisk/utils.h
    team/group/xcon_bfcp/main/acl.c
    team/group/xcon_bfcp/main/channel.c
    team/group/xcon_bfcp/main/dial.c

Propchange: team/group/xcon_bfcp/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/group/xcon_bfcp/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/group/xcon_bfcp/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/xcon_bfcp/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Feb 12 10:21:32 2007
@@ -1,1 +1,1 @@
-/trunk:1-53794
+/trunk:1-54004

Modified: team/group/xcon_bfcp/apps/app_echo.c
URL: http://svn.digium.com/view/asterisk/team/group/xcon_bfcp/apps/app_echo.c?view=diff&rev=54005&r1=54004&r2=54005
==============================================================================
--- team/group/xcon_bfcp/apps/app_echo.c (original)
+++ team/group/xcon_bfcp/apps/app_echo.c Mon Feb 12 10:21:32 2007
@@ -69,21 +69,14 @@
 			break;
 		f->delivery.tv_sec = 0;
 		f->delivery.tv_usec = 0;
-		switch (f->frametype) {
-		case AST_FRAME_DTMF:
-			if (f->subclass == '#') {
-				res = 0;
-				if (ast_write(chan, f))
-					res = -1;
-				ast_frfree(f);
-				goto end;
-			}
-			/* fall through */
-		default:
-			if (ast_write(chan, f)) {
-				ast_frfree(f);
-				goto end;
-			}
+		if (ast_write(chan, f)) {
+			ast_frfree(f);
+			goto end;
+		}
+		if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
+			res = 0;
+			ast_frfree(f);
+			goto end;
 		}
 		ast_frfree(f);
 	}

Modified: team/group/xcon_bfcp/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/group/xcon_bfcp/apps/app_meetme.c?view=diff&rev=54005&r1=54004&r2=54005
==============================================================================
--- team/group/xcon_bfcp/apps/app_meetme.c (original)
+++ team/group/xcon_bfcp/apps/app_meetme.c Mon Feb 12 10:21:32 2007
@@ -60,6 +60,7 @@
 #include "asterisk/ulaw.h"
 #include "asterisk/astobj.h"
 #include "asterisk/devicestate.h"
+#include "asterisk/dial.h"
 
 #include "asterisk/term.h"	/* Needed for some "coloured" console notifications */
 #include "asterisk/rtp.h"	/* Needed for the cascaded conferences trunking and for the external VideoMixer */
@@ -83,6 +84,7 @@
 #define DEFAULT_GW_BFCP_PORT 		2354	/*!< Default Gatewayed BFCP Server listening port (if used) */
 #define DEFAULT_GW_BFCP_DISPATCHER 	3000	/*!< Default DCON Dispatcher listening port (if used) */
 #define DEFAULT_BFCP_MAXCONF 	  	10	/*!< Default BFCP Server max number of allowed concurrent conferences */
+#define SLA_CONFIG_FILE  "sla.conf"
 
 /*! Static variable to store the prefix wildcard for XCON conferences as read from the configuration file */
 static int xcon_prefix;
@@ -175,12 +177,10 @@
 	CONFFLAG_INTROUSERNOREVIEW = (1 << 23),
 	/*! If set, the user will be initially self-muted */
 	CONFFLAG_STARTMUTED = (1 << 24),
-	/*! If set, the user is a shared line appearance station */
-	CONFFLAG_SLA_STATION = (1 << 25),
-	/*! If set, the user is a shared line appearance trunk */
-	CONFFLAG_SLA_TRUNK = (1 << 26),
-	/*! If set, the user has put us on hold */
-	CONFFLAG_HOLD = (1 << 27),
+	/*! Pass DTMF through the conference */
+	CONFFLAG_PASS_DTMF = (1 << 25),
+	CONFFLAG_SLA_STATION = (1 << 26),
+	CONFFLAG_SLA_TRUNK = (1 << 27),
 	/*! If set, the user should continue in the dialplan if kicked out */
 	CONFFLAG_KICK_CONTINUE = (1 << 28),
 	/*! If set, the MeetMe room will be treated as a (primary) XCON conference */
@@ -194,7 +194,7 @@
 	OPT_ARG_ARRAY_SIZE = 1,
 };
 
-AST_APP_OPTIONS(meetme_opts, {
+AST_APP_OPTIONS(meetme_opts, BEGIN_OPTIONS
 	AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
 	AST_APP_OPTION('a', CONFFLAG_ADMIN ),
 	AST_APP_OPTION('b', CONFFLAG_AGI ),
@@ -204,6 +204,7 @@
 	AST_APP_OPTION('d', CONFFLAG_DYNAMIC ),
 	AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ),
 	AST_APP_OPTION('e', CONFFLAG_EMPTY ),
+	AST_APP_OPTION('F', CONFFLAG_PASS_DTMF ),
 	AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
 	AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ),
 	AST_APP_OPTION('M', CONFFLAG_MOH ),
@@ -223,24 +224,21 @@
 	AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
 	AST_APP_OPTION('B', CONFFLAG_XCON ),
 	AST_APP_OPTION('G', CONFFLAG_XCON_GW ),
-});
-
-AST_APP_OPTIONS(sla_opts, {
-	/* Just a placeholder for now */
-});
+END_OPTIONS );
+
 static const char *app = "MeetMe";
 static const char *app2 = "MeetMeCount";
 static const char *app3 = "MeetMeAdmin";
 static const char *appsched = "XconScheduler";
-static const char *appslas = "SLAStation";
-static const char *appslat = "SLATrunk";
+static const char *slastation_app = "SLAStation";
+static const char *slatrunk_app = "SLATrunk";
 
 static const char *synopsis = "MeetMe conference bridge";
 static const char *synopsis2 = "MeetMe participant count";
 static const char *synopsis3 = "MeetMe conference Administration";
 static const char *synopsched = "XCON Conference IVR Scheduler";
-static const char *synopslas = "Shared Line Appearance - Station";
-static const char *synopslat = "Shared Line Appearance - Trunk";
+static const char *slastation_synopsis = "Shared Line Appearance Station";
+static const char *slatrunk_synopsis = "Shared Line Appearance Trunk";
 
 static const char *descrip =
 "  MeetMe([confno][,[options][,pin]]): Enters the user into a specified MeetMe\n"
@@ -262,6 +260,8 @@
 "      'D' -- dynamically add conference, prompting for a PIN\n"
 "      'e' -- select an empty conference\n"
 "      'E' -- select an empty pinless conference\n"
+"      'F' -- Pass DTMF through the conference.  DTMF used to activate any\n"
+"             conference features will not be passed through.\n"
 "      'i' -- announce user join/leave with review\n"
 "      'I' -- announce user join/leave without review\n"
 "      'l' -- set listen only mode (Listen only, no talking)\n"
@@ -325,17 +325,14 @@
 "  XconScheduler(): Register a new XCON conference with default settings\n"
 "";
 
-static const char *descripslas =
-"  SLAStation(sla[,options]): Run Shared Line Appearance for station\n"
-"Runs the share line appearance for a station calling in.  If there are no\n"
-"other participants in the conference, the trunk is called and is dumped into\n"
-"the bridge.\n";
-
-static const char *descripslat =
-"  SLATrunk(sla[,options]): Run Shared Line Appearance for trunk\n"
-"Runs the share line appearance for a trunk calling in.  If there are no\n"
-"other participants in the conference, all member stations are invited into\n"
-"the bridge.\n";
+static const char *slastation_desc =
+"  SLAStation():\n";
+
+static const char *slatrunk_desc =
+"  SLATrunk():\n";
+
+#define MAX_CONFNUM 80
+#define MAX_PIN     80
 
 #define CONFIG_FILE_NAME "meetme.conf"
 #define CONFIG_FILE_NAME_SLA "sla.conf"
@@ -346,7 +343,7 @@
 struct ast_conference {
 	ast_mutex_t playlock;                   /*!< Conference specific lock (players) */
 	ast_mutex_t listenlock;                 /*!< Conference specific lock (listeners) */
-	char confno[AST_MAX_EXTENSION];         /*!< Conference */
+	char confno[MAX_CONFNUM];               /*!< Conference */
 	struct ast_channel *chan;               /*!< Announcements channel */
 	struct ast_channel *lchan;              /*!< Listen/Record channel */
 	int fd;                                 /*!< Announcements fd */
@@ -362,8 +359,8 @@
 	pthread_attr_t attr;                    /*!< thread attribute */
 	const char *recordingfilename;          /*!< Filename to record the Conference into */
 	const char *recordingformat;            /*!< Format to record the Conference in */
-	char pin[AST_MAX_EXTENSION];            /*!< If protected by a PIN */
-	char pinadmin[AST_MAX_EXTENSION];       /*!< If protected by a admin PIN */
+	char pin[MAX_PIN];                      /*!< If protected by a PIN */
+	char pinadmin[MAX_PIN];                 /*!< If protected by a admin PIN */
 	struct ast_frame *transframe[32];
 	struct ast_frame *origframe;
 	struct ast_trans_pvt *transpath[32];
@@ -400,8 +397,6 @@
 	int zapchannel;                         /*!< Is a Zaptel channel */
 	char usrvalue[50];                      /*!< Custom User Value */
 	char namerecloc[PATH_MAX];				/*!< Name Recorded file Location */
-	int control;							/*! Queue Control for transmission */
-	int dtmf;								/*! Queue DTMF for transmission */
 	time_t jointime;                        /*!< Time the user joined the conference */
 	struct volume talk;
 	struct volume listen;
@@ -419,6 +414,7 @@
 	AST_LIST_HEAD_NOLOCK(, xcon_videoframe) videoframes;
 	ast_mutex_t videoframe_lock;		/*!< Lock to update/retrieve frames */
 
+	AST_LIST_HEAD_NOLOCK(, ast_frame) frame_q;
 	AST_LIST_ENTRY(ast_conf_user) list;
 };
 
@@ -474,31 +470,48 @@
 struct xcon_cascaded_conference *xcon_setup_new_cascaded_conference(struct ast_conference *cnf);
 static void *cascaded_listener(void *args);	/*!< The Cascaded audio frames listening thread(s) */
 
-/*! SLA station - one device in an SLA configuration */
-struct ast_sla_station {
-	ASTOBJ_COMPONENTS(struct ast_sla_station);
-	char *dest;
-	char tech[0];
+enum sla_trunk_state {
+	SLA_TRUNK_STATE_IDLE,
+	SLA_TRUNK_STATE_RINGING,
+	SLA_TRUNK_STATE_UP,
+	SLA_TRUNK_STATE_ONHOLD,
 };
 
-struct ast_sla_station_box {
-	ASTOBJ_CONTAINER_COMPONENTS(struct ast_sla_station);
+struct sla_trunk_ref;
+
+struct sla_station {
+	AST_RWLIST_ENTRY(sla_station) entry;
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);	
+		AST_STRING_FIELD(device);	
+		AST_STRING_FIELD(autocontext);	
+	);
+	AST_LIST_HEAD_NOLOCK(, sla_trunk_ref) trunks;
+	struct ast_dial *dial;
 };
 
-/*! SLA - Shared Line Appearance object. These consist of one trunk (outbound line)
-	and stations that receive incoming calls and place outbound calls over the trunk 
-*/
-struct ast_sla {
-	ASTOBJ_COMPONENTS (struct ast_sla);
-	struct ast_sla_station_box stations;	/*!< Stations connected to this SLA */
-	char confname[80];	/*!< Name for this SLA bridge */
-	char trunkdest[256];	/*!< Device (channel) identifier for the trunk line */
-	char trunktech[20];	/*!< Technology used for the trunk (channel driver) */
+struct sla_station_ref {
+	AST_LIST_ENTRY(sla_station_ref) entry;
+	struct sla_station *station;
 };
 
-struct ast_sla_box {
-	ASTOBJ_CONTAINER_COMPONENTS(struct ast_sla);
-} slas;
+struct sla_trunk {
+	AST_RWLIST_ENTRY(sla_trunk) entry;
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(device);
+		AST_STRING_FIELD(autocontext);	
+	);
+	AST_LIST_HEAD_NOLOCK(, sla_station_ref) stations;
+	/*! Number of stations that use this trunk */
+	unsigned int num_stations;
+	/*! Number of stations currently on a call with this trunk */
+	unsigned int active_stations;
+	/*! Number of stations that have this trunk on hold. */
+	unsigned int hold_stations;
+	struct ast_channel *chan;
+	pthread_t station_thread;
+};
 
 /*! XCON Scheduler protocol management */
 static int scheduler_exists;			/*! A static variable to check whether the Scheduler is up or not */
@@ -559,6 +572,45 @@
 int dcon_remove_remote_user(struct ast_conference *cnf, unsigned short int userID);
 int dcon_free_remote_users(struct ast_conference *cnf);
  
+struct sla_trunk_ref {
+	AST_LIST_ENTRY(sla_trunk_ref) entry;
+	struct sla_trunk *trunk;
+	enum sla_trunk_state state;
+	struct ast_channel *chan;
+};
+
+static AST_RWLIST_HEAD_STATIC(sla_stations, sla_station);
+static AST_RWLIST_HEAD_STATIC(sla_trunks, sla_trunk);
+
+static const char sla_registrar[] = "SLA";
+
+enum sla_event_type {
+	SLA_EVENT_HOLD,
+	SLA_EVENT_UNHOLD
+};
+
+struct sla_event {
+	enum sla_event_type type;
+	struct sla_station *station;
+	struct sla_trunk_ref *trunk_ref;
+	AST_LIST_ENTRY(sla_event) entry;
+};
+
+/*!
+ * \brief A structure for data used by the sla thread
+ */
+static struct sla {
+	/*! The SLA thread ID */
+	pthread_t thread;
+	ast_cond_t cond;
+	ast_mutex_t lock;
+	AST_LIST_HEAD_NOLOCK(, sla_trunk_ref) ringing_trunks;
+	AST_LIST_HEAD_NOLOCK(, sla_event) event_q;
+	unsigned int stop:1;
+} sla = {
+	.thread = AST_PTHREADT_NULL,
+};
+
 /*! The number of audio buffers to be allocated on pseudo channels
  *  when in a conference */
 static int audio_buffers;
@@ -569,7 +621,7 @@
  *  conversion... the numbers have been modified
  *  to give the user a better level of adjustability
  */
-static signed char gain_map[] = {
+static const char const gain_map[] = {
 	-15,
 	-13,
 	-10,
@@ -625,7 +677,7 @@
 
 static int set_talk_volume(struct ast_conf_user *user, int volume)
 {
-	signed char gain_adjust;
+	char gain_adjust;
 
 	/* attempt to make the adjustment in the channel driver;
 	   if successful, don't adjust in the frame reading routine
@@ -637,7 +689,7 @@
 
 static int set_listen_volume(struct ast_conf_user *user, int volume)
 {
-	signed char gain_adjust;
+	char gain_adjust;
 
 	/* attempt to make the adjustment in the channel driver;
 	   if successful, don't adjust in the frame reading routine
@@ -651,7 +703,7 @@
 {
 	switch (action) {
 	case VOL_UP:
-		switch (vol->desired) {
+		switch (vol->desired) { 
 		case 5:
 			break;
 		case 0:
@@ -748,18 +800,19 @@
 		ast_autoservice_stop(chan);
 }
 
-static void station_destroy(struct ast_sla_station *station)
-{
-	free(station);
-}
-
-static void sla_destroy(struct ast_sla *sla)
-{
-	ASTOBJ_CONTAINER_DESTROYALL(&sla->stations, station_destroy);
-	ASTOBJ_CONTAINER_DESTROY(&sla->stations);
-	free(sla);
-}
-
+/*!
+ * \brief Find or create a conference
+ *
+ * \param confno The conference name/number
+ * \param pin The regular user pin
+ * \param pinadmin The admin pin
+ * \param make Make the conf if it doesn't exist
+ * \param dynamic Mark the newly created conference as dynamic
+ * \param refcount How many references to mark on the conference
+ *
+ * \return A pointer to the conference struct, or NULL if it wasn't found and
+ *         make or dynamic were not set.
+ */
 static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount, int xcon)
 {
 	struct ast_conference *cnf;
@@ -772,215 +825,194 @@
 			break;
 	}
 
-	if (!cnf && (make || dynamic)) {
-		/* Make a new one */
-		if ((cnf = ast_calloc(1, sizeof(*cnf)))) {
-			ast_mutex_init(&cnf->playlock);
-			ast_mutex_init(&cnf->listenlock);
-			ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
-			ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
-			ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
-			cnf->refcount = 0;
-			cnf->markedusers = 0;
-			cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
-			if (cnf->chan) {
-				ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR);
-				ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR);
-				cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
-			} else {
-				ast_log(LOG_WARNING, "Unable to open pseudo channel - trying device\n");
-				cnf->fd = open("/dev/zap/pseudo", O_RDWR);
-				if (cnf->fd < 0) {
-					ast_log(LOG_WARNING, "Unable to open pseudo device\n");
-					free(cnf);
-					cnf = NULL;
-					goto cnfout;
-				}
-			}
-			memset(&ztc, 0, sizeof(ztc));
-			/* Setup a new zap conference */
-			ztc.chan = 0;
-			ztc.confno = -1;
-			ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON;
-			if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
-				ast_log(LOG_WARNING, "Error setting conference\n");
-				if (cnf->chan)
-					ast_hangup(cnf->chan);
-				else
-					close(cnf->fd);
-				free(cnf);
-				cnf = NULL;
-				goto cnfout;
-			}
-			cnf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
-			if (cnf->lchan) {
-				ast_set_read_format(cnf->lchan, AST_FORMAT_SLINEAR);
-				ast_set_write_format(cnf->lchan, AST_FORMAT_SLINEAR);
-				ztc.chan = 0;
-				ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON;
-				if (ioctl(cnf->lchan->fds[0], ZT_SETCONF, &ztc)) {
-					ast_log(LOG_WARNING, "Error setting conference\n");
-					ast_hangup(cnf->lchan);
-					cnf->lchan = NULL;
-				}
-			}
-			/* Fill the conference struct */
-			cnf->start = time(NULL);
-			cnf->zapconf = ztc.confno;
-			cnf->isdynamic = dynamic ? 1 : 0;
-
-			if(xcon) {
-				/* If requested, we add the XCON related stuff: */
-				/*     we get the conferenceID and all the other settings */
-				/*     and we create a new conference in the BFCP list */
-				int fatal = 0;
-				cnf->xconconferenceID = atoi(cnf->confno);
-				if(!cnf->xconconferenceID) {
+	if (cnf || (!make && !dynamic))
+		goto cnfout;
+
+	/* Make a new one */
+	if (!(cnf = ast_calloc(1, sizeof(*cnf))))
+		goto cnfout;
+
+	ast_mutex_init(&cnf->playlock);
+	ast_mutex_init(&cnf->listenlock);
+	ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
+	ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
+	ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
+	cnf->refcount = 0;
+	cnf->markedusers = 0;
+	cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
+	if (cnf->chan) {
+		ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR);
+		ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR);
+		cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
+	} else {
+		ast_log(LOG_WARNING, "Unable to open pseudo channel - trying device\n");
+		cnf->fd = open("/dev/zap/pseudo", O_RDWR);
+		if (cnf->fd < 0) {
+			ast_log(LOG_WARNING, "Unable to open pseudo device\n");
+			free(cnf);
+			cnf = NULL;
+			goto cnfout;
+		}
+	}
+	memset(&ztc, 0, sizeof(ztc));
+	/* Setup a new zap conference */
+	ztc.chan = 0;
+	ztc.confno = -1;
+	ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON;
+	if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
+		ast_log(LOG_WARNING, "Error setting conference\n");
+		if (cnf->chan)
+			ast_hangup(cnf->chan);
+		else
+			close(cnf->fd);
+		free(cnf);
+		cnf = NULL;
+		goto cnfout;
+	}
+	cnf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
+	if (cnf->lchan) {
+		ast_set_read_format(cnf->lchan, AST_FORMAT_SLINEAR);
+		ast_set_write_format(cnf->lchan, AST_FORMAT_SLINEAR);
+		ztc.chan = 0;
+		ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON;
+		if (ioctl(cnf->lchan->fds[0], ZT_SETCONF, &ztc)) {
+			ast_log(LOG_WARNING, "Error setting conference\n");
+			ast_hangup(cnf->lchan);
+			cnf->lchan = NULL;
+		}
+	}
+	/* Fill the conference struct */
+	cnf->start = time(NULL);
+	cnf->zapconf = ztc.confno;
+	cnf->isdynamic = dynamic ? 1 : 0;
+
+	if(xcon) {
+		/* If requested, we add the XCON related stuff: */
+		/*     we get the conferenceID and all the other settings */
+		/*     and we create a new conference in the BFCP list */
+		int fatal = 0;
+		cnf->xconconferenceID = atoi(cnf->confno);
+		if(!cnf->xconconferenceID) {
+			fatal++;
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "The XCON ConferenceID is invalid...\n");
+		} else {
+			if(xcon == XCON_REMOTE_CONFERENCE) {
+				cnf->xcondcontype = XCON_REMOTE_CONFERENCE;
+				if(bfcp_gw_initialize_conference_server(XCON_REMOTE_CONFERENCE, cnf->xconconferenceID, 0, 0, 0, 0 < 0)) {
 					fatal++;
 					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "The XCON ConferenceID is invalid...\n");
+						ast_verbose(VERBOSE_PREFIX_3 "The new remote conference could not be added to the BFCP Server...\n");
+				}
+				/* NOTE: we create an RTP channel to send/receive audio to/from the main XCON focus */
+				if(!xcon_setup_new_cascaded_conference(cnf)) {
+					fatal++;
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Could not create the Cascaded Conference RTP channel...\n");
+				}
+				if (!fatal && (option_verbose > 2))
+					ast_verbose(VERBOSE_PREFIX_3 "The new remote conference (ConferenceID: %lu) has been added to the BFCP Server:\n", cnf->xconconferenceID);
+			} else {
+				/* We don't read the file for that: we use the locally registered conferences */
+				AST_LIST_LOCK(&regxconfs);
+				struct xcon_registered_conference *conferences;
+				if(AST_LIST_EMPTY(&regxconfs)) {
+					fatal++;
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "  There are no registered conferences?? That should NEVER happen here!\n");
 				} else {
-					if(xcon == XCON_REMOTE_CONFERENCE) {
-						cnf->xcondcontype = XCON_REMOTE_CONFERENCE;
-						if(bfcp_gw_initialize_conference_server(XCON_REMOTE_CONFERENCE, cnf->xconconferenceID, 0, 0, 0, 0 < 0)) {
-							fatal++;
+					AST_LIST_TRAVERSE(&regxconfs, conferences, list) {	/* We look for the right conference */
+						if(conferences->conferenceID == cnf->xconconferenceID) {	/* Found, read it*/
+							/* Set up the conference type (remote or local) */
+							cnf->xcondcontype = XCON_LOCAL_CONFERENCE;
+							/* First of all we get the Administrator's numeric password... */
+							cnf->xconpassword = conferences->password;
+							/* ...and the numeric PIN to enter the conference, if private... */
+							cnf->xconpin = conferences->pin;
+							/* ...then we add the conference to the BFCP server... */
+							if(bfcp_gw_initialize_conference_server(XCON_LOCAL_CONFERENCE,
+											conferences->conferenceID,
+											conferences->maxfloors,
+											conferences->maxrequests,
+											conferences->autopolicy,
+											conferences->waitrequest) < 0) {
+								fatal++;
+								if (option_verbose > 2)
+									ast_verbose(VERBOSE_PREFIX_3 "The new local conference could not be added to the BFCP Server...\n");
+								break;
+							}
 							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "The new remote conference could not be added to the BFCP Server...\n");
-						}
-						/* NOTE: we create an RTP channel to send/receive audio to/from the main XCON focus */
-						if(!xcon_setup_new_cascaded_conference(cnf)) {
-							fatal++;
-							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "Could not create the Cascaded Conference RTP channel...\n");
-						}
-						if (!fatal && (option_verbose > 2))
-							ast_verbose(VERBOSE_PREFIX_3 "The new remote conference (ConferenceID: %lu) has been added to the BFCP Server:\n", cnf->xconconferenceID);
-					} else {
-						/* We don't read the file for that: we use the locally registered conferences */
-						AST_LIST_LOCK(&regxconfs);
-						struct xcon_registered_conference *conferences;
-						if(AST_LIST_EMPTY(&regxconfs)) {
-							fatal++;
-							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "  There are no registered conferences?? That should NEVER happen here!\n");
-						} else {
-							AST_LIST_TRAVERSE(&regxconfs, conferences, list) {	/* We look for the right conference */
-								if(conferences->conferenceID == cnf->xconconferenceID) {	/* Found, read it*/
-									/* Set up the conference type (remote or local) */
-									cnf->xcondcontype = XCON_LOCAL_CONFERENCE;
-									/* First of all we get the Administrator's numeric password... */
-									cnf->xconpassword = conferences->password;
-									/* ...and the numeric PIN to enter the conference, if private... */
-									cnf->xconpin = conferences->pin;
-									/* ...then we add the conference to the BFCP server... */
-									if(bfcp_gw_initialize_conference_server(XCON_LOCAL_CONFERENCE,
-													conferences->conferenceID,
-													conferences->maxfloors,
-													conferences->maxrequests,
-													conferences->autopolicy,
-													conferences->waitrequest) < 0) {
+								ast_verbose(VERBOSE_PREFIX_3 "The new local conference (ConferenceID: %lu) has been added to the BFCP Server:\n", cnf->xconconferenceID);
+							/* ...and finally we add the required floors to the BFCP conference */
+							if(conferences->audiofloorID) { /* Add a Floor for Audio */
+								cnf->audiofloorID = conferences->audiofloorID;
+								if(bfcp_gw_add_floor_server(conferences->conferenceID, AUDIO_FLOOR, conferences->audiofloorID, 0, conferences->audiousers) <0 ) {
+									fatal++;
+									if (option_verbose > 2)
+										ast_verbose(VERBOSE_PREFIX_3 "Couldn't add the new Audio Floor to the Conference...\n");
+									break;
+								}
+								if (option_verbose > 2)
+									ast_verbose(VERBOSE_PREFIX_3 "    Floor: Audio, ID %d (%s)\n", cnf->audiofloorID, conferences->audiousers ? "limited users" : "unlimited users");
+							}
+							if(conferences->videofloorID) { /* Add a Floor for Video */
+								cnf->videofloorID = conferences->videofloorID;
+								/* Only add to the list if Audio and Video floors are different (they could be managed together in the same floor) */
+/*								if(cnf->videofloorID != cnf->audiofloorID) {*/
+									if(bfcp_gw_add_floor_server(conferences->conferenceID, VIDEO_FLOOR, conferences->videofloorID, 0, conferences->videousers) <0 ) {
 										fatal++;
 										if (option_verbose > 2)
-											ast_verbose(VERBOSE_PREFIX_3 "The new local conference could not be added to the BFCP Server...\n");
+											ast_verbose(VERBOSE_PREFIX_3 "Couldn't add the new Video Floor to the Conference...\n");
 										break;
 									}
+/*								}*/
+								if (option_verbose > 2)
+									ast_verbose(VERBOSE_PREFIX_3 "    Floor: Video, ID %d (%s)\n", cnf->videofloorID, conferences->videousers ? "limited users" : "unlimited users");
+								/* NOTE: we create an RTP channel to latterly receive mixed frames from the video mixer as well
+								if(xcon_setup_new_videomixer(1, cnf) < 0) {
+									fatal++;
 									if (option_verbose > 2)
-										ast_verbose(VERBOSE_PREFIX_3 "The new local conference (ConferenceID: %lu) has been added to the BFCP Server:\n", cnf->xconconferenceID);
-									/* ...and finally we add the required floors to the BFCP conference */
-									if(conferences->audiofloorID) { /* Add a Floor for Audio */
-										cnf->audiofloorID = conferences->audiofloorID;
-										if(bfcp_gw_add_floor_server(conferences->conferenceID, AUDIO_FLOOR, conferences->audiofloorID, 0, conferences->audiousers) <0 ) {
-											fatal++;
-											if (option_verbose > 2)
-												ast_verbose(VERBOSE_PREFIX_3 "Couldn't add the new Audio Floor to the Conference...\n");
-											break;
-										}
-										if (option_verbose > 2)
-											ast_verbose(VERBOSE_PREFIX_3 "    Floor: Audio, ID %d (%s)\n", cnf->audiofloorID, conferences->audiousers ? "limited users" : "unlimited users");
-									}
-									if(conferences->videofloorID) { /* Add a Floor for Video */
-										cnf->videofloorID = conferences->videofloorID;
-										/* Only add to the list if Audio and Video floors are different (they could be managed together in the same floor) */
-/*										if(cnf->videofloorID != cnf->audiofloorID) {*/
-											if(bfcp_gw_add_floor_server(conferences->conferenceID, VIDEO_FLOOR, conferences->videofloorID, 0, conferences->videousers) <0 ) {
-												fatal++;
-												if (option_verbose > 2)
-													ast_verbose(VERBOSE_PREFIX_3 "Couldn't add the new Video Floor to the Conference...\n");
-												break;
-											}
-/*										}*/
-										if (option_verbose > 2)
-											ast_verbose(VERBOSE_PREFIX_3 "    Floor: Video, ID %d (%s)\n", cnf->videofloorID, conferences->videousers ? "limited users" : "unlimited users");
-										/* NOTE: we create an RTP channel to latterly receive mixed frames from the video mixer as well
-										if(xcon_setup_new_videomixer(1, cnf) < 0) {
-											fatal++;
-											if (option_verbose > 2)
-												ast_verbose(VERBOSE_PREFIX_3 "Could not create the VideoMixer RTP channel...\n");
-										}	*/
-									}
-									cnf->subject = conferences->subject;
-									conferences->is_active = 1;
-									break;
-								}
+										ast_verbose(VERBOSE_PREFIX_3 "Could not create the VideoMixer RTP channel...\n");
+								}	*/
 							}
+							cnf->subject = conferences->subject;
+							conferences->is_active = 1;
+							break;
 						}
-						AST_LIST_UNLOCK(&regxconfs);
 					}
-					/* Show the results */
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "    Adding conference to the BFCP Server: %s\n", fatal ? "FAILED" : "DONE");
 				}
-				if(!fatal) {
-					/* The new XCON conference has been created */
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "Created XCON conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
-					AST_LIST_INSERT_HEAD(&confs, cnf, list);
-				} else {
-					/* Something wrong happened, a fatal error, destroy the conference */
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "The XCON conference %d for conference '%s' could not be created\n", cnf->zapconf, cnf->confno);
-					free(cnf);
-					cnf = NULL;
-					goto cnfout;
-				}
-			} else {
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
-				AST_LIST_INSERT_HEAD(&confs, cnf, list);
-			}
-		} 
-	}
- cnfout:
-	if (cnf){ 
+				AST_LIST_UNLOCK(&regxconfs);
+			}
+			/* Show the results */
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "    Adding conference to the BFCP Server: %s\n", fatal ? "FAILED" : "DONE");
+		}
+		if(!fatal) {
+			/* The new XCON conference has been created */
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "Created XCON conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
+			AST_LIST_INSERT_HEAD(&confs, cnf, list);
+		} else {
+			/* Something wrong happened, a fatal error, destroy the conference */
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "The XCON conference %d for conference '%s' could not be created\n", cnf->zapconf, cnf->confno);
+			free(cnf);
+			cnf = NULL;
+			goto cnfout;
+		}
+	} else {
+		if (option_verbose > 2)
+			ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
+		AST_LIST_INSERT_HEAD(&confs, cnf, list);
+	}
+
+cnfout:
+	if (cnf)
 		cnf->refcount += refcount;
-	}
+
 	AST_LIST_UNLOCK(&confs);
+
 	return cnf;
-}
-
-/*! \brief CLI command for showing SLAs */
-static int sla_show(int fd, int argc, char *argv[]) 
-{
-	struct ast_sla *sla;
-	if (argc != 2)
-		return RESULT_SHOWUSAGE;
-
-	ast_cli(fd, "Shared line appearances:\n");
-	ASTOBJ_CONTAINER_TRAVERSE(&slas, 1, {
-		ASTOBJ_RDLOCK(iterator);
-		ast_cli(fd, "SLA %s\n", iterator->name);
-		if (ast_strlen_zero(iterator->trunkdest) || ast_strlen_zero(iterator->trunktech))
-			ast_cli(fd, "   Trunk => <unspecified>\n");
-		else
-			ast_cli(fd, "   Trunk => %s/%s\n", iterator->trunktech, iterator->trunkdest);
-		sla = iterator;
-		ASTOBJ_CONTAINER_TRAVERSE(&sla->stations, 1, {
-			ast_cli(fd, "   Station: %s/%s\n", iterator->tech, iterator->dest);
-		});
-		ASTOBJ_UNLOCK(iterator);
-	});
-
-	return RESULT_SUCCESS;
 }
 
 /*! \brief CLI commands for XCON related information */
@@ -1692,7 +1724,7 @@
 			min = ((now - user->jointime) % 3600) / 60;
 			sec = (now - user->jointime) % 60;
 			if ( !concise )
-				ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n",
+				ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %02d:%02d:%02d\n",
 					user->user_no,
 					S_OR(user->chan->cid.cid_num, "<unknown>"),
 					S_OR(user->chan->cid.cid_name, "<no name>"),
@@ -1700,8 +1732,7 @@
 					user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "",
 					user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "",
 					user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "",
-					istalking(user->talking), 
-					user->userflags & CONFFLAG_HOLD ? " (On Hold) " : "", hr, min, sec);
+					istalking(user->talking), hr, min, sec); 
 			else 
 				ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n",
 					user->user_no,
@@ -1795,18 +1826,94 @@
 "Usage: meetme (un)lock|(un)mute|kick|list [concise] <confno> <usernumber>\n"
 "       Executes a command for the conference or on a conferee\n";
 
-static const char sla_show_usage[] =
-"Usage: sla show\n"
-"       Lists status of all shared line appearances\n";
+static int sla_show_trunks(int fd, int argc, char **argv)
+{
+	const struct sla_trunk *trunk;
+
+	ast_cli(fd, "--- Configured SLA Trunks -----------------------------------\n"
+	            "-------------------------------------------------------------\n\n");
+	AST_RWLIST_RDLOCK(&sla_trunks);
+	AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) {
+		struct sla_station_ref *station_ref;
+		ast_cli(fd, "--- Trunk Name:      %s\n"
+		            "--- ==> Device:      %s\n"
+					"--- ==> AutoContext: %s\n"
+					"--- ==> Stations ...\n",
+					trunk->name, trunk->device, 
+					S_OR(trunk->autocontext, "(none)"));
+		AST_RWLIST_RDLOCK(&sla_stations);
+		AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry)
+			ast_cli(fd, "--- =====> Station name: %s\n", station_ref->station->name);
+		AST_RWLIST_UNLOCK(&sla_stations);
+		ast_cli(fd, "\n");
+	}
+	AST_RWLIST_UNLOCK(&sla_trunks);
+	ast_cli(fd, "-------------------------------------------------------------\n");
+
+	return RESULT_SUCCESS;
+}
+
+static const char *trunkstate2str(enum sla_trunk_state state)
+{
+#define S(e) case e: return # e;
+	switch (state) {
+	S(SLA_TRUNK_STATE_IDLE)
+	S(SLA_TRUNK_STATE_RINGING)
+	S(SLA_TRUNK_STATE_UP)
+	S(SLA_TRUNK_STATE_ONHOLD)
+	}
+	return "Uknown State";
+#undef S
+}
+
+static const char sla_show_trunks_usage[] =
+"Usage: sla show trunks\n"
+"       This will list all trunks defined in sla.conf\n";
+
+static int sla_show_stations(int fd, int argc, char **argv)
+{
+	const struct sla_station *station;
+
+	ast_cli(fd, "--- Configured SLA Stations ---------------------------------\n"
+	            "-------------------------------------------------------------\n\n");
+	AST_RWLIST_RDLOCK(&sla_stations);
+	AST_RWLIST_TRAVERSE(&sla_stations, station, entry) {
+		struct sla_trunk_ref *trunk_ref;
+		ast_cli(fd, "--- Station Name:    %s\n"
+		            "--- ==> Device:      %s\n"
+					"--- ==> AutoContext: %s\n"
+					"--- ==> Trunks ...\n",
+					station->name, station->device, 
+					S_OR(station->autocontext, "(none)"));
+		AST_RWLIST_RDLOCK(&sla_trunks);
+		AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry)
+			ast_cli(fd, "--- =====> Trunk Name: %s State: %s\n", 
+				trunk_ref->trunk->name, trunkstate2str(trunk_ref->state));
+		AST_RWLIST_UNLOCK(&sla_trunks);
+		ast_cli(fd, "\n");
+	}
+	AST_RWLIST_UNLOCK(&sla_stations);
+	ast_cli(fd, "-------------------------------------------------------------\n");
+
+	return RESULT_SUCCESS;
+}
+
+static const char sla_show_stations_usage[] =
+"Usage: sla show stations\n"

[... 2697 lines stripped ...]


More information about the svn-commits mailing list