[svn-commits] russell: branch russell/xcon_bfcp r47236 - in /team/russell/xcon_bfcp: apps/ ...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Mon Nov 6 11:31:14 MST 2006


Author: russell
Date: Mon Nov  6 12:31:13 2006
New Revision: 47236

URL: http://svn.digium.com/view/asterisk?rev=47236&view=rev
Log:
Add patch from issue #7838

Added:
    team/russell/xcon_bfcp/apps/xcon_bfcp/
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_floor_list.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_floor_list.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_link_list.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_link_list.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_messages.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_messages.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_messages_build.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_messages_parse.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_sdp.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_sdp.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_server.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_server.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_strings.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_user_list.c   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/bfcp_user_list.h   (with props)
    team/russell/xcon_bfcp/apps/xcon_bfcp/xcon_blueprints.h   (with props)
    team/russell/xcon_bfcp/channels/bfcp_sdp/
    team/russell/xcon_bfcp/channels/bfcp_sdp/bfcp_sdp.c   (with props)
    team/russell/xcon_bfcp/channels/bfcp_sdp/bfcp_sdp.h   (with props)
Modified:
    team/russell/xcon_bfcp/apps/Makefile
    team/russell/xcon_bfcp/apps/app_meetme.c
    team/russell/xcon_bfcp/channels/Makefile
    team/russell/xcon_bfcp/channels/chan_sip.c
    team/russell/xcon_bfcp/configs/extensions.ael.sample
    team/russell/xcon_bfcp/configs/extensions.conf.sample

Modified: team/russell/xcon_bfcp/apps/Makefile
URL: http://svn.digium.com/view/asterisk/team/russell/xcon_bfcp/apps/Makefile?rev=47236&r1=47235&r2=47236&view=diff
==============================================================================
--- team/russell/xcon_bfcp/apps/Makefile (original)
+++ team/russell/xcon_bfcp/apps/Makefile Mon Nov  6 12:31:13 2006
@@ -36,3 +36,5 @@
 all: _all
 
 include $(ASTTOPDIR)/Makefile.moddir_rules
+
+app_meetme.so : app_meetme.o xcon_bfcp/bfcp_server.o xcon_bfcp/bfcp_link_list.o xcon_bfcp/bfcp_user_list.o xcon_bfcp/bfcp_floor_list.o xcon_bfcp/bfcp_messages.o xcon_bfcp/bfcp_messages_build.o xcon_bfcp/bfcp_messages_parse.o xcon_bfcp/bfcp_sdp.o

Modified: team/russell/xcon_bfcp/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/russell/xcon_bfcp/apps/app_meetme.c?rev=47236&r1=47235&r2=47236&view=diff
==============================================================================
--- team/russell/xcon_bfcp/apps/app_meetme.c (original)
+++ team/russell/xcon_bfcp/apps/app_meetme.c Mon Nov  6 12:31:13 2006
@@ -61,10 +61,40 @@
 #include "asterisk/astobj.h"
 #include "asterisk/devicestate.h"
 
+#include "asterisk/term.h"	/* Needed for some "coloured" console notifications */
+#include "asterisk/sched.h"	/* Will be needed for the external VideoMixer (currently UNUSED!) */
+#include "asterisk/io.h"	/* Will be needed for the external VideoMixer (currently UNUSED!) */
+#include "asterisk/rtp.h"	/* Will be needed for the external VideoMixer (currently UNUSED!) */
+
+/*! The library managing the Floor Contrl Server behaviour */
+#include "xcon_bfcp/bfcp_server.h"
+/*! Useful user-friendly strings for BFCP definitions */
+#include "xcon_bfcp/bfcp_strings.h"
+/*! Definition of the structure to pass to chan_sip for BFCP+SDP reinvites */
+#include "xcon_bfcp/bfcp_sdp.h"
+/*! Static, embedded, definitions of some common conference blueprints
+	\todo: make it dynamic */
+#include "xcon_bfcp/xcon_blueprints.h"
+
 #include "enter.h"
 #include "leave.h"
 
 #define CONFIG_FILE_NAME "meetme.conf"
+
+#define DEFAULT_XCON_PREFIX	 867	/*!< Prefix wildcard for XCON conferences */
+#define DEFAULT_SCHEDULER_PORT 	2346	/*!< Default XconScheduler listening port */
+#define DEFAULT_BFCP_PORT 	2345	/*!< Default BFCP Server listening port */
+#define DEFAULT_BFCP_MAXCONF 	  10	/*!< Default BFCP Server max number of allowed concurrent conferences */
+
+/*! Static variable to store the prefix wildcard for XCON conferences as read from the configuration file */
+static int xcon_prefix;
+
+/*! New VideoMixer stuff: RTPs, scheduler's and IO's context
+	\note currently UNUSED! */
+static struct sockaddr_in bindaddr = { 0, };	/*!< The address we bind the Mixer's RTPs to */
+static struct sched_context *mixer_sched;	/*!< The VideoMixer's scheduling context */
+static struct io_context *mixer_io;		/*!< The VideoMixer's IO context */
+static void *mixer_listener(void *args);	/*!< The VideoMixer(s) listening thread(s) */
 
 /*! each buffer is 20ms, so this is 640ms total */
 #define DEFAULT_AUDIO_BUFFERS  32
@@ -155,7 +185,9 @@
 	/*! If set, the user has put us on hold */
 	CONFFLAG_HOLD = (1 << 27),
 	/*! If set, the user should continue in the dialplan if kicked out */
-	CONFFLAG_KICK_CONTINUE = (1 << 28)
+	CONFFLAG_KICK_CONTINUE = (1 << 28),
+	/*! If set, the MeetMe room will be treated as an XCON conference */
+	CONFFLAG_XCON = (1 << 29)
 };
 
 enum {
@@ -190,6 +222,7 @@
 	AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
 	AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
 	AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
+	AST_APP_OPTION('B', CONFFLAG_XCON ),
 });
 
 AST_APP_OPTIONS(sla_opts, {
@@ -198,12 +231,14 @@
 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 *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";
 
@@ -252,7 +287,8 @@
 "      'X' -- allow user to exit the conference by entering a valid single\n"
 "             digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
 "             if that variable is not defined.\n"
-"      '1' -- do not play message when first person enters\n";
+"      '1' -- do not play message when first person enters\n"
+"      'B' -- trigger XCON Conference mode, enabling BFCP for moderation.\n";
 
 static const char *descrip2 =
 "  MeetMeCount(confno[|var]): Plays back the number of users in the specified\n"
@@ -285,6 +321,10 @@
 "      'V' -- Raise entire conference listening volume\n"
 "";
 
+static const char *descripsched =
+"  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"
@@ -299,6 +339,7 @@
 
 #define CONFIG_FILE_NAME "meetme.conf"
 #define CONFIG_FILE_NAME_SLA "sla.conf"
+#define XCON_CONFIG_FILE_NAME "xcon.conf"
 
 /*! \brief The MeetMe Conference object */
 struct ast_conference {
@@ -325,6 +366,20 @@
 	struct ast_frame *transframe[32];
 	struct ast_frame *origframe;
 	struct ast_trans_pvt *transpath[32];
+
+	unsigned long int xconconferenceID;	/*!< XCON specific Conference ID */
+	char *subject;				/*!< XCON specific Conference Subject (Topic) */
+	unsigned long int xconpin;		/*!< XCON pin, needed for conferences with private access */
+	unsigned short int xconpassword;	/*!< XCON Conference Administrator's numeric password */
+	unsigned short int audiofloorID;	/*!< BFCP Floor ID for Audio, if enabled */
+	unsigned short int videofloorID;	/*!< BFCP Floor ID for Video, if enabled */
+
+	struct ast_rtp *mixer_in;		/*!< The Mixer's RTP channel to get the mixed video from (currently UNUSED!) */
+	struct hostent *mixer_vhp;		/*!< RTP host IP we bind to (currently UNUSED!) */
+	struct ast_hostent *mixer_videohp;
+	pthread_t mixer_listening_thread;	/*!< Listening thread for incoming Mixer's RTP (currently UNUSED!) */
+	pthread_attr_t mixer_listening_attr;	/*!< Listening thread attribute (currently UNUSED!) */
+
 	AST_LIST_HEAD_NOLOCK(, ast_conf_user) userlist;
 	AST_LIST_ENTRY(ast_conference) list;
 };
@@ -350,6 +405,20 @@
 	time_t jointime;                        /*!< Time the user joined the conference */
 	struct volume talk;
 	struct volume listen;
+
+	unsigned short int xconuserID;		/*!< XCON specific User ID */
+	char *xconuserdisplay;			/*!< XCON User's Display Name */
+	char *xconuseruri;			/*!< XCON User's URI */
+	unsigned short int audiofloorstatus;	/*!< BFCP Status for the Floor Audio (if present) */
+	unsigned short int videofloorstatus;	/*!< BFCP Status for the Floor Video (if present) */
+	int notify_audio_change;		/*!< Flag to notify an user if he has been muted/unmuted */
+	int notify_video_change;		/*!< Flag to notify an user if he can/can't send video */
+
+	struct ast_rtp *mixer_out;		/*!< The Mixer's RTP channel to send this user's video to (currently UNUSED!) */
+	struct hostent *mixer_vhp;		/*!< RTP video Mixer's host IP (currently UNUSED!) */
+	struct ast_hostent *mixer_videohp;
+	struct ast_frame *mixer_frame;		/*!< The latest frame received from the VideoMixer (currently UNUSED!) */
+
 	AST_LIST_ENTRY(ast_conf_user) list;
 };
 
@@ -378,6 +447,60 @@
 struct ast_sla_box {
 	ASTOBJ_CONTAINER_COMPONENTS(struct ast_sla);
 } slas;
+
+
+/*! XCON Binary Floor Control Protocol (BFCP) management */
+static bfcp bfcp_server_list;		/*! The object managing the BFCP server behaviour */
+static unsigned short int bfcp_port;	/*! The port the BFCP server will listen on (TCP only, TLS not supported yet) */
+static int bfcp_user_id;		/*! Static user counter to assign new BFCP User IDs */
+/*! Callback function called by the BFCP library to notify the application about incoming/outgoing messages */
+int bfcp_notifications(bfcp_arguments *arguments, int outgoing);
+
+/*! XCON Scheduler server management */
+static struct xcon_scheduler {
+	int socket;			/*! The file descriptor */
+	unsigned short int port;	/*! The listening port */
+	struct sockaddr_in *address;	/*! The listening address */
+	int fdmax;			/*! The highest file descriptor (needed for select) */
+	fd_set *readfds, *writefds;	/*! The file descriptor sets for select */
+	pthread_t thread;		/*! The XconScheduler listening thread */
+	char admin[15];			/*! The manager's username... (must be a valid user from manager.conf)  */
+	char password[15];		/*! 	... and password 						*/
+} xcon_scheduler;
+
+/*! XCON Registered Conferences management, to avoid always checking the configuration file */
+struct xcon_registered_conference {
+	char *subject;						/*! The conference subject (topic) */
+	unsigned long int conferenceID;				/*! The XCON Conference ID */
+	unsigned short int pin;					/*! The numeric PIN to access the conference, if private */
+	unsigned short int password;				/*! The numeric password for the Administrator */
+	unsigned short int maxfloors;				/*! The max number of floors this conference will support */
+	unsigned short int maxrequests;				/*! The max number of requests for the same floor this conference will allow from each user */
+	unsigned short int audiofloorID;			/*! The Audio Floor Identifier */
+	unsigned short int audiousers;				/*! How many users can have audio granted at the same time */
+	unsigned short int videofloorID;			/*! The Video Floor Identifier */
+	unsigned short int videousers;				/*! How many users can have audio granted at the same time */
+	unsigned short int autopolicy;				/*! AutoAccept policy for floors with no chair (0=accept, 1=deny) */
+	unsigned short int waitrequest;				/*! The time in seconds the server waits for a chair's decision */
+	int is_active;						/*! A flag to check if this is an active conference or not */
+	AST_LIST_ENTRY(xcon_registered_conference) list;	/*! To manage the linked list */
+};
+
+static AST_LIST_HEAD_STATIC(regxconfs, xcon_registered_conference);
+
+/*! Methods to manage the registered conferences list (add, remove, and free) */
+int xcon_register_conference(char *subject, unsigned long int conferenceID, unsigned short int pin, unsigned short int password, unsigned short int maxfloors, unsigned short int maxrequests, unsigned short int audiofloorID, unsigned short int audiousers, unsigned short int videofloorID, unsigned short int videousers, int autopolicy);
+int xcon_unregister_conference(unsigned long int conferenceID);
+int xcon_free_registered_conferences(void);
+
+/*! Wrapper functions to get pointers to a conference and/or an user */
+struct ast_conference *xcon_get_conference(unsigned long int conferenceID);
+struct ast_conf_user *xcon_get_user(struct ast_conference *cnf, unsigned short int userID);
+
+/*! Muting/Unmuting XCON wrappers */
+int xcon_mute_user(struct ast_conference *cnf, struct ast_conf_user *user);
+int xcon_unmute_user(struct ast_conference *cnf, struct ast_conf_user *user);
+
 
 static int audio_buffers;			/*!< The number of audio buffers to be allocated on pseudo channels
 						   when in a conference
@@ -584,7 +707,7 @@
 	free(sla);
 }
 
-static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount)
+static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount, int xcon)
 {
 	struct ast_conference *cnf;
 	struct zt_confinfo ztc;
@@ -652,10 +775,129 @@
 			cnf->start = time(NULL);
 			cnf->zapconf = ztc.confno;
 			cnf->isdynamic = dynamic ? 1 : 0;
-			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);
-			manager_event(EVENT_FLAG_CALL, "MeetmeStart", "Meetme: %s\r\n", cnf->confno);
+
+			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 {
+					/* 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*/
+								/* 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_initialize_conference_server(bfcp_server_list,
+												conferences->conferenceID,
+												conferences->maxfloors,
+												conferences->maxrequests,
+												conferences->autopolicy,
+												conferences->waitrequest) <0) {
+									fatal++;
+									if (option_verbose > 2)
+										ast_verbose(VERBOSE_PREFIX_3 "The new conference could not be added to the BFCP Server...\n");
+									break;
+								}
+								if (option_verbose > 2)
+									ast_verbose(VERBOSE_PREFIX_3 "The new 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_add_floor_server(bfcp_server_list, conferences->conferenceID, 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_add_floor_server(bfcp_server_list, conferences->conferenceID, 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 receive media from the video mixer too (currently UNUSED!) */
+									if(!cnf->mixer_in) {
+										struct sockaddr_in vsin;	/* Video socket address */
+										cnf->mixer_in = ast_rtp_new_with_bindaddr(NULL, NULL, 0, 0, bindaddr.sin_addr);
+/*										ast_rtp_set_callback(cnf->mixer_in, mixer_callback);*/
+										ast_rtp_settos(cnf->mixer_in, 0);
+										ast_rtp_setdtmf(cnf->mixer_in, 0);
+										ast_rtp_setdtmfcompensate(cnf->mixer_in, 0);
+/*										ast_rtp_set_m_type(cnf->mixer_in, 31);
+										ast_rtp_set_rtpmap_type(cnf->mixer_in, 31, "video", "H.261", 0);*/
+										ast_rtp_get_us(cnf->mixer_in, &vsin);
+										if (option_verbose > 2)
+											ast_verbose(VERBOSE_PREFIX_3 "\tIncoming VideoMixer RTP Channel waiting on port %d\n", ntohs(vsin.sin_port));
+										struct hostent *mixer_vhp;
+										struct ast_hostent *mixer_videohp;
+										mixer_videohp = calloc(sizeof(struct ast_hostent), sizeof(char));
+										mixer_vhp = ast_gethostbyname("127.0.0.1", mixer_videohp);
+										vsin.sin_family = AF_INET;
+										if (mixer_vhp)
+											memcpy(&vsin.sin_addr, mixer_vhp->h_addr, sizeof(vsin.sin_addr));
+										/* Setup video port number */
+										vsin.sin_port = htons(6668);
+										ast_rtp_set_peer(cnf->mixer_in, &vsin);
+										pthread_attr_init(&cnf->mixer_listening_attr);
+										pthread_attr_setdetachstate(&cnf->mixer_listening_attr, PTHREAD_CREATE_DETACHED);
+										ast_pthread_create(&cnf->mixer_listening_thread, &cnf->mixer_listening_attr, mixer_listener, cnf);
+									}
+								}
+								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:
@@ -690,6 +932,474 @@
 
 	return RESULT_SUCCESS;
 }
+
+/*! \brief CLI commands for XCON related information */
+static int xcon_info(int fd, int argc, char *argv[]);
+static int xcon_show_registered(int fd, int argc, char *argv[]);
+static int xcon_show_conferences(int fd, int argc, char *argv[]);
+static int xcon_show_conference(int fd, int argc, char *argv[]);
+static int xcon_show_users(int fd, int argc, char *argv[]);
+static int xcon_show_user(int fd, int argc, char *argv[]);
+static int xcon_remove_conference(int fd, int argc, char *argv[]);
+static int xcon_remove_user(int fd, int argc, char *argv[]);
+
+static char xcon_info_usage[] = 
+"Usage: xcon info\n"
+"       Shows information on the XCON Servers.\n";
+
+static char xcon_show_registered_usage[] = 
+"Usage: xcon show registered\n"
+"       Shows the registered conferences in the XCON Server.\n";
+
+static char xcon_show_conferences_usage[] = 
+"Usage: xcon show conferences\n"
+"       Shows the active conferences on the XCON Server.\n";
+
+static char xcon_show_conference_usage[] = 
+"Usage: xcon show conference <ID>\n"
+"       Shows the conference number <ID> in the XCON Server.\n";
+
+static char xcon_show_users_usage[] = 
+"Usage: xcon show users <conferenceID>\n"
+"       Shows all the users in conference <conferenceID> on the XCON Server.\n";
+
+static char xcon_show_user_usage[] = 
+"Usage: xcon show user <conferenceID> <userID>\n"
+"       Shows the user number <userID> in conference <conferenceID> on the XCON Server.\n";
+
+static char xcon_remove_conference_usage[] = 
+"Usage: xcon remove conference <ID>\n"
+"       Removes the conference number <ID> and all its users from the XCON Server.\n";
+
+static char xcon_remove_user_usage[] = 
+"Usage: xcon remove user <conferenceID> <userID>\n"
+"       Removes the user <userID> from the conference <confID> in the XCON Server.\n";
+
+static struct ast_cli_entry xcon_cli[] = {
+	{ { "xcon", "info", NULL }, xcon_info, "Shows information on the XCON Server", xcon_info_usage },
+	{ { "xcon", "show", "registered", NULL }, xcon_show_registered, "Shows the registered conferences in the XCON Server", xcon_show_registered_usage },
+	{ { "xcon", "show", "conferences", NULL }, xcon_show_conferences, "Shows the active conferences on the XCON Server", xcon_show_conferences_usage },
+	{ { "xcon", "show", "conference", NULL }, xcon_show_conference, "Shows info about a conference in the XCON Server", xcon_show_conference_usage },
+	{ { "xcon", "show", "users", NULL }, xcon_show_users, "Shows all the users in an active conferences on the XCON Server", xcon_show_users_usage },
+	{ { "xcon", "show", "user", NULL }, xcon_show_user, "Shows info about an user in a conference in the XCON Server", xcon_show_user_usage },
+	{ { "xcon", "remove", "conference", NULL }, xcon_remove_conference, "Removes a conference from the XCON Server", xcon_remove_conference_usage },
+	{ { "xcon", "remove", "user", NULL }, xcon_remove_user, "Removes an user from a conference in the XCON Server", xcon_remove_user_usage },
+};
+
+/*! \brief Shows XCON Servers (XconScheduler and BFCP) Information */
+static int xcon_info(int fd, int argc, char *argv[])
+{
+	if (bfcp_server_list) {
+		ast_cli(fd,"  BFCP Server listening on port %d.\n",bfcp_port);
+		ast_cli(fd,"  BFCP Server List active with max %d conferences allowed (%d active).\n",bfcp_server_list->Max_number_conference + 1,bfcp_server_list->Actual_number_conference);
+	}
+	else
+		ast_cli(fd,"BFCP Server not up.\n");
+	if (xcon_scheduler.socket > -1)
+		ast_cli(fd,"  XconScheduler Server listening on port %d.\n",xcon_scheduler.port);
+	else
+		ast_cli(fd,"XconScheduler Server not up.\n");
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Shows XCON registered conferences */
+static int xcon_show_registered(int fd, int argc, char *argv[])
+{
+	int i = 0;
+	struct xcon_registered_conference *conferences = NULL;
+	AST_LIST_LOCK(&regxconfs);
+	if (AST_LIST_EMPTY(&regxconfs)) {
+		ast_cli(fd,"  There are no registered conferences.\n");
+		return RESULT_SUCCESS;
+	}
+	ast_cli(fd,"  Registered conferences:\n");
+	AST_LIST_TRAVERSE(&regxconfs, conferences, list) {
+		i++;
+		ast_cli(fd,"    %d: %li (password=%d), %s (PIN=%d), Audio %s, Video %s (Topic: %s)\n",i,conferences->conferenceID,conferences->password,conferences->pin ? "Private" : "Public",conferences->pin,conferences->audiofloorID ? "enabled" : "disabled",conferences->videofloorID ? "enabled" : "disabled", conferences->subject ? conferences->subject : "(none)");
+	}
+	AST_LIST_UNLOCK(&regxconfs);
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Shows all currently active (running) XCON conferences */
+static int xcon_show_conferences(int fd, int argc, char *argv[])
+{
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		bfcp_conference *lconferences = bfcp_server_list->list_conferences;
+		int i = 0;
+		if (lconferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_SUCCESS;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_SUCCESS;
+		}		
+		ast_cli(fd,"  Conferences:\n");
+		for(i=0; i < bfcp_server_list->Actual_number_conference; i++)
+			ast_cli(fd,"    %d: %li\n",i+1,bfcp_server_list->list_conferences[i].conferenceID);
+	}
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Shows info on a specific, currently active (running), XCON conference */
+static int xcon_show_conference(int fd, int argc, char *argv[])
+{
+	int j=0;
+	bfcp_list_floors *list_floor;
+	bfcp_list_users *list_user;
+	bfcp_queue *list_link;
+	bfcp_user *user;
+	bfcp_node *node;
+	bfcp_floor *FloorID;
+	floor_request_query *query_floorrequest;
+	floor_query *query;
+
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		unsigned long int ID = atoi(argv[3]);
+		if(!ID)
+			return RESULT_SHOWUSAGE;
+		int i = 0;
+		if (bfcp_server_list->list_conferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_FAILURE;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_FAILURE;
+		}		
+		for(i=0; i < bfcp_server_list->Actual_number_conference; i++) {
+			if (bfcp_server_list->list_conferences[i].conferenceID == ID) {
+				ast_cli(fd,"ConferenceID: %li\n\n", bfcp_server_list->list_conferences[i].conferenceID);
+				list_floor = bfcp_server_list->list_conferences[i].floor;
+				if (list_floor !=NULL) {
+					ast_cli(fd,"Maximum number of floors in the conference: %d\n", list_floor->number_floors + 1);
+					ast_cli(fd,"FLOORS\n");
+					for(j= 0;j<list_floor->actual_number_floors;j++) {
+						ast_cli(fd,"FloorID: %u, ", list_floor->floors[j].floorID);
+						ast_cli(fd,"ChairID: %u", list_floor->floors[j].chairID);
+						if (list_floor->floors[j].floorState==0)
+							ast_cli(fd," state: FREE\n");
+						else if (list_floor->floors[j].floorState==1)
+							ast_cli(fd," state: ACCEPTED\n");
+						else if (list_floor->floors[j].floorState>=2)
+							ast_cli(fd," state: GRANTED\n");
+						else
+							ast_cli(fd," state: error!\n");
+						ast_cli(fd,"Number of simultaneous granted users: %d\n", list_floor->floors[j].limit_granted_floor-1);
+						query= list_floor->floors[j].floorquery;
+						if (query!=NULL)
+							ast_cli(fd,"QUERY LIST\n");
+						while(query) {
+							ast_cli(fd,"User: %i\n",query->userID);
+							query=query->next;
+						}
+					}
+				}
+				list_user = bfcp_server_list->list_conferences[i].user;
+				if (list_user !=NULL) {
+					user=list_user->users;
+					ast_cli(fd,"Maximum number of request per floors in the conference: %d\n", list_user->max_number_floor_request);
+					ast_cli(fd,"USERS\n");
+					while(user){
+						ast_cli(fd,"userID: %u (Display Name: %s, URI: %s)\n",
+							user->userID,
+							user->user_display_name ? user->user_display_name : "none",
+							user->user_URI ? user->user_URI : "none");
+						ast_cli(fd,"\n");
+						user= user->next;
+					}
+				}
+				list_link = bfcp_server_list->list_conferences[i].pending;
+				if (list_link !=NULL) {
+					node=list_link->head;
+					if (node) ast_cli(fd,"PENDING LIST\n");
+					while(node!=NULL) {
+						ast_cli(fd,"FloorRequestID: %u userID: %u Priority: %u Queue_position: %u ", node->floorRequestID, node->userID, node->priority, node->queue_position); 
+						if (node->beneficiaryID!=0)
+							ast_cli(fd,"BeneficiaryID: %u", node->beneficiaryID);
+						ast_cli(fd,"\n");
+						FloorID=node->floorID;
+						while(FloorID) {
+							ast_cli(fd,"FloorID: %u ", FloorID->floorID);
+							if (FloorID->chair_info!=NULL)
+								ast_cli(fd,"chair_information: %s ", FloorID->chair_info);
+							if (FloorID->status==0)
+								ast_cli(fd," state: FREE\n");
+							else if (FloorID->status==1)
+								ast_cli(fd," state: ACCEPTED\n");
+							else if (FloorID->status>=2)
+								ast_cli(fd," state: GRANTED\n");                          
+							else
+								ast_cli(fd," state: error!\n");
+							FloorID= FloorID->next;
+						}
+						query_floorrequest=node->floorrequest;
+						while(query_floorrequest) {
+							ast_cli(fd,"Floor Request query: %u \n", query_floorrequest->userID);
+							query_floorrequest= query_floorrequest->next;
+						}
+						node= node->next;
+						ast_cli(fd,"-----------------\n");
+					}
+				}
+				list_link = bfcp_server_list->list_conferences[i].accepted;
+				if (list_link !=NULL) {
+					node=list_link->head;
+					if (node)
+						ast_cli(fd,"ACCEPTED LIST\n");
+					while(node!=NULL) {
+						ast_cli(fd,"FloorRequestID: %u userID: %u Priority: %u Queue_position: %u ", node->floorRequestID, node->userID, node->priority, node->queue_position);
+						if (node->beneficiaryID!=0)
+							ast_cli(fd,"BeneficiaryID: %u", node->beneficiaryID);
+						ast_cli(fd,"\n");
+						FloorID=node->floorID;
+						while(FloorID) {
+							ast_cli(fd,"FloorID: %u ", FloorID->floorID);
+							if (FloorID->chair_info!=NULL)
+								ast_cli(fd,"chair_information: %s ", FloorID->chair_info);
+							if (FloorID->status==0)
+								ast_cli(fd," state: FREE\n");
+							else if (FloorID->status==1)
+								ast_cli(fd," state: ACCEPTED\n");
+							else if (FloorID->status>=2)
+								ast_cli(fd," state: GRANTED\n");
+							else ast_cli(fd," state: error!\n");
+							FloorID= FloorID->next;
+						}
+					
+						query_floorrequest=node->floorrequest;
+						while(query_floorrequest) {
+							ast_cli(fd,"Floor Request query: %u \n", query_floorrequest->userID);
+							query_floorrequest= query_floorrequest->next;
+						}
+						node= node->next;
+						ast_cli(fd,"-----------------\n");
+					}
+				}
+				list_link = bfcp_server_list->list_conferences[i].granted;
+				if (list_link !=NULL) {
+					node=list_link->head;
+					if (node)
+						ast_cli(fd,"GRANTED LIST\n");
+					while(node!=NULL) {
+						ast_cli(fd,"FloorRequestID: %u userID: %u Priority: %u Queue_position: %u ", node->floorRequestID, node->userID, node->priority, node->queue_position);
+						if (node->beneficiaryID!=0)
+							ast_cli(fd,"BeneficiaryID: %u", node->beneficiaryID);
+						ast_cli(fd,"\n");
+						FloorID=node->floorID;
+						while(FloorID) {
+							ast_cli(fd,"FloorID: %u ", FloorID->floorID);
+							if (FloorID->chair_info!=NULL)
+								ast_cli(fd,"chair_information: %s ", FloorID->chair_info);
+							if (FloorID->status==0)
+								ast_cli(fd," state: FREE\n");
+							else if (FloorID->status==1)
+								ast_cli(fd," state: ACCEPTED\n");
+							else if (FloorID->status>=2)
+								ast_cli(fd," state: GRANTED\n");
+							else ast_cli(fd," state: error!\n"); 
+							FloorID= FloorID->next;
+						}
+						query_floorrequest=node->floorrequest;
+						while(query_floorrequest) {
+							ast_cli(fd,"Floor Request query: %u \n", query_floorrequest->userID);
+							query_floorrequest= query_floorrequest->next;
+						}
+						node= node->next;
+						ast_cli(fd,"-----------------\n");
+					}
+				}			
+			} else {
+				ast_cli(fd,"  There is no active conference with ID %ld in the BFCP Server.\n",ID);
+				return RESULT_FAILURE;
+			}		
+		}
+	}
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Shows all users in a currently active (running) XCON conferences */
+static int xcon_show_users(int fd, int argc, char *argv[])
+{
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		unsigned long int ID = atoi(argv[3]);
+		if(!ID)
+			return RESULT_SHOWUSAGE;
+		if (bfcp_server_list->list_conferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_FAILURE;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_FAILURE;
+		}	
+
+		struct ast_conference *cnf = xcon_get_conference(ID);
+		int user_count = 0;
+		if(cnf) {
+			AST_LIST_LOCK(&confs);
+			struct ast_conf_user *user;
+			ast_cli(fd,"  Users in Conference %lu:\n",ID);
+			AST_LIST_TRAVERSE(&cnf->userlist, user, list) {
+				if(!user)
+					break;
+				user_count++;
+				ast_cli(fd,"    %d: UserID %u (Display Name: %s, URI: %s)",
+					user_count,
+					user->xconuserID,
+					user->xconuserdisplay ? user->xconuserdisplay : "none",
+					user->xconuseruri ? user->xconuseruri : "none");
+				if(cnf->audiofloorID)
+					ast_cli(fd,", Audio %s", user->audiofloorstatus ? bfcp_status[user->audiofloorstatus-1].description : "NOT GRANTED");
+				if(cnf->videofloorID)
+					ast_cli(fd,", Video %s", user->videofloorstatus ? bfcp_status[user->videofloorstatus-1].description : "NOT GRANTED");
+				ast_cli(fd,"\n");
+			}
+			AST_LIST_UNLOCK(&confs);
+		} else {
+			ast_cli(fd,"  There is no active conference with ID %ld in the BFCP Server.\n",ID);
+			return RESULT_FAILURE;
+		}	
+	}
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Shows a specific user in a currently active (running) XCON conferences */
+static int xcon_show_user(int fd, int argc, char *argv[])
+{
+	if (argc != 5)
+		return RESULT_SHOWUSAGE;
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		unsigned long int confID = atoi(argv[3]);
+		if(!confID)
+			return RESULT_SHOWUSAGE;
+		unsigned short int userID = atoi(argv[4]);
+		if(!userID)
+			return RESULT_SHOWUSAGE;
+		if (bfcp_server_list->list_conferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_FAILURE;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_FAILURE;
+		}	
+
+		struct ast_conference *cnf = xcon_get_conference(confID);
+		if(cnf) {
+			AST_LIST_LOCK(&confs);
+			struct ast_conf_user *user = xcon_get_user(cnf, userID);
+			if(user) {
+				ast_cli(fd,"  UserID %u (Display Name: %s, URI: %s)",
+					user->xconuserID,
+					user->xconuserdisplay ? user->xconuserdisplay : "none",
+					user->xconuseruri ? user->xconuseruri : "none");
+				if(cnf->audiofloorID)
+					ast_cli(fd,", Audio %s", user->audiofloorstatus ? bfcp_status[user->audiofloorstatus-1].description : "NOT GRANTED");
+				if(cnf->videofloorID)
+					ast_cli(fd,", Video %s", user->videofloorstatus ? bfcp_status[user->videofloorstatus-1].description : "NOT GRANTED");
+				ast_cli(fd,"\n");
+			} else {
+				ast_cli(fd,"  There is no user %u in conference with ID %ld in the BFCP Server.\n",userID,confID);
+				AST_LIST_UNLOCK(&confs);
+				return RESULT_FAILURE;
+			}
+			AST_LIST_UNLOCK(&confs);
+		} else {
+			ast_cli(fd,"  There is no active conference with ID %ld in the BFCP Server.\n",confID);
+			return RESULT_FAILURE;
+		}	
+	}
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Removes a currently active (running) XCON conference, without unregistering it, by kicking its participants */
+static int xcon_remove_conference(int fd, int argc, char *argv[])
+{
+	if (argc != 4)
+		return RESULT_SHOWUSAGE;
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		unsigned long int ID = atoi(argv[3]);
+		if(!ID)
+			return RESULT_SHOWUSAGE;
+		if (bfcp_server_list->list_conferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_FAILURE;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_FAILURE;
+		}	
+
+		struct ast_conference *cnf = xcon_get_conference(ID);
+		if(cnf) {
+			AST_LIST_LOCK(&confs);
+			struct ast_conf_user *user;
+			AST_LIST_TRAVERSE(&cnf->userlist, user, list) {
+				user->adminflags |= ADMINFLAG_KICKME;
+			}
+			AST_LIST_UNLOCK(&confs);
+		} else {
+			ast_cli(fd,"  There is no active conference with ID %ld in the BFCP Server.\n",ID);
+			return RESULT_FAILURE;
+		}	
+	}
+	return RESULT_SUCCESS;
+}
+
+/*! \brief Removes a specific user from a currently active (running) XCON conference by kicking her/him */
+static int xcon_remove_user(int fd, int argc, char *argv[])
+{
+	if (argc != 5)
+		return RESULT_SHOWUSAGE;
+	if (bfcp_server_list == NULL)
+		ast_cli(fd,"  BFCP Server List has not been created yet.\n");
+	else {
+		unsigned long int confID = atoi(argv[3]);
+		if(!confID)
+			return RESULT_SHOWUSAGE;
+		unsigned short int userID = atoi(argv[4]);
+		if(!userID)
+			return RESULT_SHOWUSAGE;
+		if (bfcp_server_list->list_conferences == NULL) {
+			ast_cli(fd,"  The BFCP Server List is NULL.\n");
+			return RESULT_FAILURE;
+		}
+		if (bfcp_server_list->Actual_number_conference == 0) {
+			ast_cli(fd,"  There are no active conferences in the BFCP Server.\n");
+			return RESULT_FAILURE;
+		}
+
+		struct ast_conference *cnf = xcon_get_conference(confID);
+		if(!cnf) {
+			ast_cli(fd,"  There is no active conference with ID %ld in the BFCP Server.\n",confID);
+			return RESULT_FAILURE;
+		}
+		struct ast_conf_user *user = xcon_get_user(cnf, userID);
+		if(!user) {
+			ast_cli(fd,"  There's no user with ID %d in Conference %ld.\n",userID,confID);
+			return RESULT_FAILURE;
+		}
+		user->adminflags |= ADMINFLAG_KICKME;
+	}
+	return RESULT_SUCCESS;
+}
+
 
 static int meetme_cmd(int fd, int argc, char **argv) 
 {
@@ -982,6 +1692,39 @@
 	else
 		close(conf->fd);
 	
+	if(conf->xconconferenceID) {
+		AST_LIST_LOCK(&regxconfs);
+		/* Disable the is_active flag for the registered conference */
+		struct xcon_registered_conference *conferences = NULL;
+		if(!AST_LIST_EMPTY(&regxconfs)) {
+			AST_LIST_TRAVERSE(&regxconfs, conferences, list) {
+				if(conferences->conferenceID == conf->xconconferenceID)
+					conferences->is_active = 0;
+			}
+		}
+		AST_LIST_UNLOCK(&regxconfs);
+		/* Remove the Conference from the BFCP Server too */
+		if(bfcp_destroy_conference_server(bfcp_server_list,conf->xconconferenceID) <0 ) {
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "The Conference %lu could not be deleted from the BFCP Server...\n",conf->xconconferenceID);
+		} else {
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "The Conference %lu has been deleted from the BFCP Server.\n",conf->xconconferenceID);
+		}
+	
+		manager_event(EVENT_FLAG_CALL, "XconDeactivateEvent",
+			"ConferenceID: %lu\r\n",
+			conf->xconconferenceID);
+	
+		conf->xconconferenceID = 0;
+
+		/* Mixer currently UNUSED! */

[... 11413 lines stripped ...]


More information about the svn-commits mailing list