[asterisk-commits] branch mogorman/asterisk-xmpp - r7334 in /team/mogorman/asterisk-xmpp: ./ cha...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sun Dec 4 17:33:05 CST 2005


Author: mogorman
Date: Sun Dec  4 17:33:00 2005
New Revision: 7334

URL: http://svn.digium.com/view/asterisk?rev=7334&view=rev
Log:
This is my initial commit of all asterisk jabber stuff.
chan_agent: added support for asterisk to log agents in and out based on presence.
app: added wrapper functions so things wont break if res_xmpp is not loaded.
res_xmpp: the core.  IT allows asterisk to connect to jabber servers as clients or components.

Added:
    team/mogorman/asterisk-xmpp/configs/xmpp.conf.sample
    team/mogorman/asterisk-xmpp/include/asterisk/xmpp.h
    team/mogorman/asterisk-xmpp/res/res_xmpp.c
Modified:
    team/mogorman/asterisk-xmpp/app.c
    team/mogorman/asterisk-xmpp/channels/chan_agent.c
    team/mogorman/asterisk-xmpp/configs/agents.conf.sample
    team/mogorman/asterisk-xmpp/include/asterisk/app.h
    team/mogorman/asterisk-xmpp/include/asterisk/astobj.h
    team/mogorman/asterisk-xmpp/res/Makefile

Modified: team/mogorman/asterisk-xmpp/app.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/app.c?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/app.c (original)
+++ team/mogorman/asterisk-xmpp/app.c Sun Dec  4 17:33:00 2005
@@ -48,6 +48,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/lock.h"
 #include "asterisk/indications.h"
+#include "asterisk/xmpp.h"
 
 #define MAX_OTHER_FORMATS 10
 
@@ -232,6 +233,62 @@
 
 static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
 static int (*ast_messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
+
+static int (*astjab_register_func)(const char *action,  int (*func)(struct axi_master *asterisk, char *user, char *m,int type), const char *synopsis, const char *description)=NULL;
+static int (*astjab_send)(struct axi_master *asterisk, char *address, char *message) =NULL;
+static int (*astjab_check_roster)(void)=NULL;
+
+void ast_install_xmpp_functions(int (*axi_check_roster)(void), int (*axi_send)(struct axi_master *asterisk, char *address, char *message), int (*axi_register)(const char *action,  int (*func)(struct axi_master *asterisk,char *user, char *m, int type), const char *synopsis, const char *description))
+{
+	astjab_send = axi_send;
+	astjab_register_func=axi_register;
+	astjab_check_roster=axi_check_roster;
+}
+
+void ast_uninstall_xmpp_functions(void)
+{
+	astjab_send=NULL;
+	astjab_register_func=NULL;
+	astjab_check_roster=NULL;
+}
+
+int ast_xmpp_check_roster(void)
+{
+	static int warned = 0;
+	if (astjab_check_roster)
+		return astjab_check_roster();
+
+	if (option_verbose > 2) {
+		warned++;
+		ast_verbose(VERBOSE_PREFIX_3 "XMPP check_roster was not used because res_xmpp.so is not loaded.\nyou have been warned %itimes.\n",warned);
+	}
+	return 0;
+}
+int ast_xmpp_send(struct axi_master *asterisk,char *address, char *message)
+{
+	static int warned = 0;
+	if (astjab_send)
+		return astjab_send(asterisk,address,message);
+
+	if (option_verbose > 2 ) {
+		warned++;
+		ast_verbose(VERBOSE_PREFIX_3 "XMPP %s was not sent because res_xmpp.so is not loaded.\nyou have been warned %itimes.\n",message,warned);
+	}
+	return 0;
+}
+
+int ast_xmpp_register(const char *action,  int (*func)(struct axi_master *asterisk, char *user, char *m, int type), const char *synopsis, const char *description)
+{
+	static int warned = 0;
+	if (astjab_register_func)
+		return astjab_register_func(action,func,synopsis,description);
+
+	if (option_verbose > 2) {
+		warned++;
+		ast_verbose(VERBOSE_PREFIX_3 "XMPP function%s was not loaded because  res_xmpp.so is not loaded.\nyou have been warned %itimes.\n",action,warned);
+	}
+	return 0;
+}
 
 void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
 			      int (*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs))

Modified: team/mogorman/asterisk-xmpp/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/channels/chan_agent.c?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/channels/chan_agent.c (original)
+++ team/mogorman/asterisk-xmpp/channels/chan_agent.c Sun Dec  4 17:33:00 2005
@@ -68,6 +68,7 @@
 #include "asterisk/astdb.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/monitor.h"
+#include "asterisk/xmpp.h"
 
 static const char desc[] = "Agent Proxy Channel";
 static const char channeltype[] = "Agent";
@@ -155,6 +156,7 @@
 static int wrapuptime;
 static int ackcall;
 
+static int xmpplogon=1,xmpplogoff=6;
 static int maxlogintries = 3;
 static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye";
 
@@ -201,6 +203,9 @@
 	struct ast_channel *owner;     /**< Agent */
 	char loginchan[80];            /**< channel they logged in from */
 	char logincallerid[80];        /**< Caller ID they had when they logged in */
+	int xmpplogoff;		       /**< Logout agent based on xmpp presence */
+	int xmpplogon;		       /**< Logon agent based on xmpp presence */
+	char xuser[AST_MAX_AGENT];     /**< Username for xmpp presence */
 	struct ast_channel *chan;      /**< Channel we use */
 	struct agent_pvt *next;        /**< Next Agent in the linked list. */
 };
@@ -252,6 +257,8 @@
 static int agent_indicate(struct ast_channel *ast, int condition);
 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
+static int xmpp_agent_status(struct axi_master *asterisk,char *user,char *message, int type);
+static int xmpp_login(char *agent,char *exten, char *context);
 
 static const struct ast_channel_tech agent_tech = {
 	.type = channeltype,
@@ -312,11 +319,16 @@
 static struct agent_pvt *add_agent(char *agent, int pending)
 {
 	int argc;
-	char *argv[3];
+	char *argv[5];
 	char *args;
 	char *password = NULL;
 	char *name = NULL;
 	char *agt = NULL;
+	char *xuser = NULL;
+	int xlogon=0,xlogoff=0;
+	xlogon=xmpplogon;
+	xlogoff=xmpplogoff;
+	char status[100];
 	struct agent_pvt *p, *prev;
 
 	args = ast_strdupa(agent);
@@ -331,6 +343,38 @@
 		if (argc > 2) {
 			name = argv[2];
 			while (*name && *name < 33) name++;
+		}
+		if (argc > 3) {
+			xuser = argv[3];
+			while(*xuser && *xuser < 33)xuser++;
+		}
+		if (argc > 4) {
+			if(!strcasecmp(argv[4],"online"))
+				xlogon=1;
+			if(!strcasecmp(argv[4],"chatty"))
+				xlogon=2;
+			if(!strcasecmp(argv[4],"away"))
+				xlogon=3;
+			if(!strcasecmp(argv[4],"xaway"))
+				xlogon=4;
+			if(!strcasecmp(argv[4],"dnd"))
+				xlogon=5;
+			if(!strcasecmp(argv[4],"offline"))
+				xlogon=6;
+		}
+		if (argc > 5) {
+			if(!strcasecmp(argv[4],"online"))
+				xlogoff=1;
+			if(!strcasecmp(argv[4],"chatty"))
+				xlogoff=2;
+			if(!strcasecmp(argv[4],"away"))
+				xlogoff=3;
+			if(!strcasecmp(argv[4],"xaway"))
+				xlogoff=4;
+			if(!strcasecmp(argv[4],"dnd"))
+				xlogoff=5;
+			if(!strcasecmp(argv[4],"offline"))
+				xlogoff=6;
 		}
 	} else {
 		ast_log(LOG_WARNING, "A blank agent line!\n");
@@ -371,9 +415,18 @@
 	ast_copy_string(p->password, password ? password : "", sizeof(p->password));
 	ast_copy_string(p->name, name ? name : "", sizeof(p->name));
 	ast_copy_string(p->moh, moh, sizeof(p->moh));
+	ast_copy_string(p->xuser,xuser ? xuser :"",sizeof(p->xuser));
+	p->xmpplogon=xlogon;
+	p->xmpplogoff=xlogoff;
 	p->ackcall = ackcall;
 	p->autologoff = autologoff;
 
+	if(p->xuser)
+	{
+		sprintf(status,"axi_agent%s",p->xuser);
+		ast_xmpp_register(status,xmpp_agent_status,"Handles Agent status.\n",mandescr_agent_logoff);
+	}
+	
 	/* If someone reduces the wrapuptime and reloads, we want it
 	 * to change the wrapuptime immediately on all calls */
 	if (p->wrapuptime > wrapuptime) {
@@ -1064,6 +1117,32 @@
 			autologoff = atoi(v->value);
 			if (autologoff < 0)
 				autologoff = 0;
+		} else if (!strcasecmp(v->name, "xmpplogon")) {
+			if(!strcasecmp(v->value,"online"))
+				xmpplogon=1;
+			if(!strcasecmp(v->value,"chatty"))
+				xmpplogon=2;
+			if(!strcasecmp(v->value,"away"))
+				xmpplogon=3;
+			if(!strcasecmp(v->value,"xaway"))
+				xmpplogon=4;
+			if(!strcasecmp(v->value,"dnd"))
+				xmpplogon=5;
+			if(!strcasecmp(v->value,"offline"))
+				xmpplogon=6;
+		} else if (!strcasecmp(v->name, "xmpplogoff")) {
+			if(!strcasecmp(v->value,"online"))
+				xmpplogoff=1;
+			if(!strcasecmp(v->value,"chatty"))
+				xmpplogoff=2;
+			if(!strcasecmp(v->value,"away"))
+				xmpplogoff=3;
+			if(!strcasecmp(v->value,"xaway"))
+				xmpplogoff=4;
+			if(!strcasecmp(v->value,"dnd"))
+				xmpplogoff=5;
+			if(!strcasecmp(v->value,"offline"))
+				xmpplogoff=6;
 		} else if (!strcasecmp(v->name, "ackcall")) {
 			if (!strcasecmp(v->value, "always"))
 				ackcall = 2;
@@ -1549,6 +1628,45 @@
 		astman_send_error(s, m, "No such agent");
 
 	return 0;
+}
+
+static int xmpp_agent_status(struct axi_master *asterisk,char *user,char *message, int type)
+{
+	char *m=NULL;
+	m=(char*)malloc(strlen(message));
+	//ast_copy_string(m, message, sizeof(m));
+	strcpy(m,message);
+	char *context=NULL;
+	char *extension=NULL;
+	struct agent_pvt *tmp = agents;
+
+	if(m){
+		context=strchr(m,'@');
+		*context='\0';
+		context++;
+		extension=m;
+	}
+
+	ast_mutex_lock(&agentlock);
+	while(tmp)
+	{
+		if(!strncasecmp(tmp->xuser,user,strlen(tmp->xuser)))
+		{
+			if(tmp->xmpplogon >= type){
+				xmpp_login(tmp->agent,extension,context);
+				ast_xmpp_send(asterisk,user,"Agent is logged in.");
+			}
+			if(tmp->xmpplogoff <= type){
+				agent_logoff(tmp->agent, 1);
+				ast_xmpp_send(asterisk,user,"Agent is logged out.");
+			}
+
+		}
+		tmp=tmp->next;
+	}
+	ast_mutex_unlock(&agentlock);
+	free(m);
+	return 1;
 }
 
 static char *complete_agent_logoff_cmd(char *line, char *word, int pos, int state)
@@ -2134,6 +2252,63 @@
 	return __login_exec(chan, data, 1);
 }
 
+static int xmpp_login(char *agent,char *exten, char *context)
+{
+	char *wrapuptime_s=NULL;
+	char *ackcall_s=NULL;
+	struct agent_pvt *p;
+	int login_state = 0;
+
+	p = agents;
+	while(p) {
+		if (strncmp(p->agent, agent,strlen(p->agent)) || p->pending) {
+			p = p->next;
+			continue;
+		}
+		if (p->chan) {
+			login_state = 2; /* already logged in (and on the phone)*/
+			break;
+		}
+		ast_mutex_lock(&p->lock);
+		login_state = 1; /* Successful Login */
+		ast_copy_string(p->loginchan, exten, sizeof(p->loginchan));
+		
+		if (ast_strlen_zero(context))
+			snprintf(p->loginchan, sizeof(p->loginchan), "%s", exten);
+		else
+			snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context);
+
+		if (wrapuptime_s && !ast_strlen_zero(wrapuptime_s)) {
+			p->wrapuptime = atoi(wrapuptime_s);
+			if (p->wrapuptime < 0)
+				p->wrapuptime = 0;
+		}
+
+		if (ast_true(ackcall_s))
+			p->ackcall = 1;
+		else
+			p->ackcall = 0;
+
+		if (p->loginstart == 0)
+			time(&p->loginstart);
+		ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan);
+		if (option_verbose > 1)
+			ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan);
+		ast_device_state_changed("Agent/%s", p->agent);
+		ast_mutex_unlock(&p->lock);
+		p = p->next;
+	}
+
+	if (login_state == 1)
+		ast_verbose("Agent logged in\n");
+	else if (login_state == 0)
+		ast_verbose("No such agent\n");
+	else if (login_state == 2)
+		ast_verbose("Agent already logged in\n");
+
+	return 0;
+}
+
 /**
  * Sets an agent as logged in by callback in the Manager API.
  * It is registered on load_module() and it gets called by the manager backend.
@@ -2441,6 +2616,7 @@
 	read_agent_config();
 	if (persistent_agents)
 		reload_agents();
+	ast_xmpp_check_roster();
 	return 0;
 }
 
@@ -2449,6 +2625,7 @@
 	read_agent_config();
 	if (persistent_agents)
 		reload_agents();
+	ast_xmpp_check_roster();
 	return 0;
 }
 

Modified: team/mogorman/asterisk-xmpp/configs/agents.conf.sample
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/configs/agents.conf.sample?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/configs/agents.conf.sample (original)
+++ team/mogorman/asterisk-xmpp/configs/agents.conf.sample Sun Dec  4 17:33:00 2005
@@ -56,6 +56,10 @@
 ; By default its "wav".
 ;recordformat=gsm
 ;
+; Log the agent out based on status online,chatty,away,xawa,dnd,offline
+;xlogon=online
+;xlogoff=away
+;
 ; Insert into CDR userfield a name of the the created recording 
 ; By default it's turned off. 
 ;createlink=yes
@@ -74,7 +78,7 @@
 ;
 ; This section contains the agent definitions, in the form:
 ;
-; agent => agentid,agentpassword,name
+; agent => agentid,agentpassword,name,user at jabber.com,xlogon,xlogoff
 ;
 ;agent => 1001,4321,Mark Spencer
 ;agent => 1002,4321,Will Meadows

Added: team/mogorman/asterisk-xmpp/configs/xmpp.conf.sample
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/configs/xmpp.conf.sample?rev=7334&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/configs/xmpp.conf.sample (added)
+++ team/mogorman/asterisk-xmpp/configs/xmpp.conf.sample Sun Dec  4 17:33:00 2005
@@ -1,0 +1,42 @@
+[general]
+debug=1
+
+[asterisk-c]
+type=component
+host=test.asterisk.org
+username=test.asterisk.org
+password=asterisk
+port=42791
+component=test
+
+[asterisk]
+type=client
+host= astjab.org
+username= asterisk at asterisk.org/asterisk
+password= asterisk
+security=1
+port= 5222
+
+[AOL]
+type=transport
+host=aim.astjab.org
+username=myaolsn
+password=secret
+
+[meonaim]
+type=user
+username=mcslaveog at aim.astjab.org
+host=aim.astjab.org
+channel=1234 at local
+
+[testuser]
+type=user
+username=mogorman at astjab.org
+channel=1000 at local
+channel=Work,1001 at local
+channel=Home,1002 at local
+
+[testuser2]
+type=user
+username=cherry at astjab.org
+channel=2000 at local

Modified: team/mogorman/asterisk-xmpp/include/asterisk/app.h
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/include/asterisk/app.h?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/include/asterisk/app.h (original)
+++ team/mogorman/asterisk-xmpp/include/asterisk/app.h Sun Dec  4 17:33:00 2005
@@ -27,6 +27,7 @@
 extern "C" {
 #endif
 
+#include "asterisk/xmpp.h"
 /* IVR stuff */
 
 /*! \brief Callback function for IVR
@@ -102,6 +103,16 @@
 /*! Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#' */
 int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec);
 
+void ast_install_xmpp_functions(int (*axi_check_roster)(void), int (*axi_send)(struct axi_master *asterisk, char *address, char *message), int (*axi_register)(const char *action, int (*func)(struct axi_master *asterisk,char *user, char *m, int type), const char *synopsis, const char *description) );
+
+void ast_uninstall_xmpp_functions(void);
+
+int ast_xmpp_send(struct axi_master *asterisk,char *address, char *message);
+
+int ast_xmpp_check_roster(void);
+
+int ast_xmpp_register(const char *action, int (*func)(struct axi_master *asterisk,char *user, char *m, int type), const char *synopsis, const char *description);
+
 void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
 			      int (*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs));
   

Modified: team/mogorman/asterisk-xmpp/include/asterisk/astobj.h
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/include/asterisk/astobj.h?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/include/asterisk/astobj.h (original)
+++ team/mogorman/asterisk-xmpp/include/asterisk/astobj.h Sun Dec  4 17:33:00 2005
@@ -382,6 +382,19 @@
 		next = (container)->head; \
 		while((continue) && (iterator = next)) { \
 			next = iterator->next[0]; \
+			eval; \
+		} \
+		ASTOBJ_CONTAINER_UNLOCK(container); \
+	} while(0)
+
+#define ASTOBJ_CONTAINER_TRAVERSE2(container,iteratorname,continue,eval) \
+	do { \
+		typeof((container)->head) iterator##iteratorname; \
+		typeof((container)->head) next; \
+		ASTOBJ_CONTAINER_RDLOCK(container); \
+		next = (container)->head; \
+		while((continue) && (iterator##iteratorname = next)) { \
+			next = iterator##iteratorname->next[0]; \
 			eval; \
 		} \
 		ASTOBJ_CONTAINER_UNLOCK(container); \

Added: team/mogorman/asterisk-xmpp/include/asterisk/xmpp.h
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/include/asterisk/xmpp.h?rev=7334&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/include/asterisk/xmpp.h (added)
+++ team/mogorman/asterisk-xmpp/include/asterisk/xmpp.h Sun Dec  4 17:33:00 2005
@@ -1,0 +1,131 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * AXI - Asterisk XMPP Interface
+ * Asterisk to XMPP bridge. 
+ * 
+ * Copyright (C) 1999-2005, Digium, Inc.
+ *
+ * Mathew O'Gorman <mogorman at digium.com>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ *
+ * $Revision: 1.16 $
+ */
+
+#ifndef _ASTERISK_XMPP_H
+#define _ASTERISK_XMPP_H
+
+#include <iksemel.h>
+#include "asterisk/astobj.h"
+
+enum axi_state {
+	AXI_DISCONNECTED=0,
+	AXI_CONNECTING,
+	AXI_ALMOST,
+	AXI_CONNECTED
+};
+
+enum axi_prune_register{
+	AXI_DONOTHING=0,
+	AXI_PRUNE=1,
+	AXI_REGISTER=2
+};
+
+enum axi_utype{
+	AXI_USER=0,
+	AXI_TRANS=1,
+	AXI_UTRANS=2
+};
+
+struct axi_location{
+	ASTOBJ_COMPONENTS( struct axi_location);
+	int status;
+	char channel[80];
+	int priority;
+};
+
+struct axi_location_container{
+	ASTOBJ_CONTAINER_COMPONENTS(struct axi_location);
+};
+
+struct axi_user {
+	ASTOBJ_COMPONENTS(struct axi_user);
+	char user[80];
+	char host[80];
+	char pass[80]; /*For Transports*/
+	//char type[5]; // Not sure what I did it for. 
+	char defchannel[80];
+	enum axi_utype utype;	
+	int defstatus;
+	struct axi_location_container resource;
+	enum axi_prune_register on_roster;
+};
+
+struct axi_user_container {
+	ASTOBJ_CONTAINER_COMPONENTS(struct axi_user);
+};
+
+struct axi_transport_container {
+	ASTOBJ_CONTAINER_COMPONENTS(struct axi_transport);
+};
+
+struct axi_master {
+	ASTOBJ_COMPONENTS(struct axi_master);
+	char password[80];
+	char user[80];
+	char server[80];
+	char sid[10]; /* Session ID */
+	char component[80];
+	char mid[6]; /* Message ID */
+	iksid *jid;
+	iksparser *p;
+	iksfilter *f;
+	ikstack *stack;
+	enum axi_state state;
+	int port;
+	int debug;
+	int security;
+	int version;
+	struct axi_user_container users;
+	pthread_t thread;
+	int pruneregister;
+};
+
+struct axi_master_container{
+	ASTOBJ_CONTAINER_COMPONENTS(struct axi_master);
+};
+struct axi_action {
+	/*! Name of the action */
+	char action[100];
+	/*! Short description of the action */
+	const char *synopsis;
+	/*! Detailed description of the action */
+	const char *description;
+	/*! Permission required for action.  EVENT_FLAG_* */
+
+	/*! Function to be called */
+	int (*func)(struct axi_master *asterisk,char *user, char *message, int type);
+	/*! For easy linking */
+	struct axi_action *next;
+};
+
+#define axi_register(a, b, c, d) axi_register2(a, b, c, d, NULL)
+/* Use axi_register2 to register with help text for new xmpp commands */
+
+/*! Register a xmpp command with the xmpp interface */
+/*! 	\param action Name of the requested Action:
+	\param authority Required authority for this command
+	\param func Function to call for this command
+	\param synopsis Help text (one line, up to 30 chars) for CLI xmpp show commands
+	\param description Help text, several lines
+*/
+int ast_axi_register2(const char *action, int (*func)(struct axi_master *asterisk,char *user, char *m,int type), const char *synopsis, const char *description);
+int ast_axi_send(struct axi_master *asterisk,char *address, char *message);
+int ast_axi_disconnect(struct axi_master *asterisk);
+int ast_axi_check_roster(void);
+int ast_axi_create_chat(struct axi_master *asterisk,char *room, char *server, char *topic);
+int ast_axi_invite_chat(struct axi_master *asterisk, char *user, char *room, char *message);
+int ast_axi_join_chat(struct axi_master *asterisk,char *room);
+#endif

Modified: team/mogorman/asterisk-xmpp/res/Makefile
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/Makefile?rev=7334&r1=7333&r2=7334&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/res/Makefile (original)
+++ team/mogorman/asterisk-xmpp/res/Makefile Sun Dec  4 17:33:00 2005
@@ -52,6 +52,18 @@
 
 CRYPTO_LIBS=-lssl -lcrypto
 
+XMPP_LIB=-liksemel
+
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/iksemel.h),)
+  MODS+=res_xmpp.so
+  OSPLIB=$(CROSS_COMPILE_TARGET)/usr/local/lib/libiksemel.a
+  else
+     ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/iksemel.h),)
+       MODS+=res_xmpp.so
+       OSPLIB=$(CROSS_COMPILE_TARGET)/usr/lib/libiksemel.a
+     endif
+  endif
+
 CFLAGS+=
 
 ifndef WITHOUT_ZAPTEL
@@ -91,6 +103,9 @@
 res_crypto.so: res_crypto.o
 	$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CRYPTO_LIBS)
 
+res_xmpp.so: res_xmpp.o
+	$(CC) $(SOLINK) -o $@ $< $(XMPP_LIB)
+
 clean:
 	rm -f *.so *.o .depend
 

Added: team/mogorman/asterisk-xmpp/res/res_xmpp.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/res_xmpp.c?rev=7334&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/res_xmpp.c (added)
+++ team/mogorman/asterisk-xmpp/res/res_xmpp.c Sun Dec  4 17:33:00 2005
@@ -1,0 +1,1453 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * The Asterisk XMPP Interface - AXI
+ *
+ * Yes I finally sat down and wrote something.
+ * and didnt just talk flack.
+ * 
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Matt O'Gorman <mogorman at digium.com>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iksemel.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.43 $")
+#include "asterisk/channel.h"
+#include "asterisk/xmpp.h"
+#include "asterisk/file.h"
+#include "asterisk/config.h"
+#include "asterisk/callerid.h"
+#include "asterisk/lock.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/cli.h"
+#include "asterisk/app.h"
+#include "asterisk/pbx.h"
+#include "asterisk/md5.h"
+#include "asterisk/acl.h"
+#include "asterisk/utils.h"
+#include "asterisk/module.h"
+#include "asterisk/astobj.h"
+
+#define JABBER_CONFIG "xmpp.conf"
+
+AST_MUTEX_DEFINE_STATIC(actionlock);
+
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static void axi_user_destroy(struct axi_user *obj);
+static void axi_master_destroy(struct axi_master *obj);
+static void axi_location_destroy(struct axi_location *obj);
+static int axi_send_exec(struct ast_channel *chan, void *data);
+static int axi_status_exec(struct ast_channel *chan, void *data);
+static void axi_log_hook(void *udata, const char *data, size_t size,int is_incoming);
+static int axi_execute(struct axi_master *asterisk,char *action, char *user, char *message, int type);
+static int axi_act_hook(void *udata, int type, iks * node);
+static void axi_handle_iq(struct axi_master *asterisk, ikspak *pak);
+static void axi_handle_presence(struct axi_master *asterisk, ikspak *pak);
+static void axi_handle_subscribe(struct axi_master *asterisk, ikspak *pak);
+static int axi_recv(struct axi_master *asterisk,int timeout);
+static void *axi_recv_loop(void *data);
+static int axi_client_initialize(struct axi_master *asterisk);
+static int axi_component_initialize(struct axi_master *asterisk);
+static int axi_client_connect(void *udata, ikspak *pak);
+static int axi_component_connect(void *udata,ikspak *pak);
+static void axi_set_presence(struct axi_master *asterisk,char *user, int level, char *desc);
+static int axi_do_debug(int fd, int argc, char *argv[]);
+static int axi_no_debug(int fd, int argc, char *argv[]);
+static int axi_do_debug_component(int fd, int argc, char *argv[]);
+static int axi_no_debug_component(int fd, int argc, char *argv[]);
+static int axi_test(int fd, int argc, char *argv[]);
+static int axi_show_clients(int fd, int argc, char *argv[]);
+static int axi_register_struct(struct axi_action *act);
+static struct axi_master *axi_create_master(char *label,struct ast_variable *var,int debug,int pruneregister);
+static struct axi_user *axi_create_user(char *label,struct ast_variable *var,enum axi_utype utype);
+static int axi_load_config(void);
+static void axi_handle_message(struct axi_master *asterisk, ikspak *pak);
+static void axi_pruneregister(struct axi_master *asterisk);
+static int axi_register_transport(void *udata,ikspak *pak);
+static int axi_register_transport2(void *udata,ikspak *pak);
+static void axi_increment_mid(char *mid);
+
+static char debug_usage[] =
+"Usage: XMPP debug\n"
+"	Enables dumping of XMPP packets for debugging purposes\n";
+
+static char test_usage[] =
+"Usage: XMPP no debug\n"
+"	Disables dumping of XMPP packets for debugging purposes\n";
+
+static char no_debug_usage[] =
+"Usage: XMPP test\n"
+"	Sends test massage for debugging purposes\n";
+
+static struct ast_cli_entry axi_cli[] = {
+	{{"xmpp", "debug", NULL}, axi_do_debug,"Enable XMPP debugging", debug_usage},
+	{{"xmpp", "debug", "component", NULL}, axi_do_debug_component,"Enable XMPP debugging for a component",debug_usage},
+	{{"xmpp", "debug", "client", NULL}, axi_do_debug_component,"Enable XMPP debugging for a client",debug_usage},
+	{{"xmpp", "show","connected", NULL}, axi_show_clients,"Show state of clients and components",debug_usage},
+	{{"xmpp", "no", "debug", NULL}, axi_no_debug,"Disable XMPP debug", no_debug_usage},
+	{{"xmpp", "no","debug", "component", NULL}, axi_no_debug_component,"Disable XMPP debugging for a component",no_debug_usage},
+	{{"xmpp", "no", "debug", "client", NULL}, axi_no_debug_component,"Disable XMPP debugging for a client",no_debug_usage},
+
+	{{"xmpp", "test", NULL}, axi_test, "Shows roster, but is genearlly used for mog's debugging.", test_usage},
+};
+static char *tdesc = "AXI - Asterisk XMPP Interface";
+
+static struct axi_action *first_action = NULL;
+
+struct axi_master_container masters;
+
+static void axi_master_destroy(struct axi_master *obj){
+	ASTOBJ_CONTAINER_DESTROYALL(&obj->users,axi_user_destroy);
+	ASTOBJ_CONTAINER_DESTROY(&obj->users);
+
+	free(obj);
+	obj = NULL;
+}
+
+static void axi_user_destroy(struct axi_user *obj)
+{
+	ASTOBJ_CONTAINER_DESTROYALL(&obj->resource,axi_location_destroy);
+	ASTOBJ_CONTAINER_DESTROY(&obj->resource);
+	free(obj);
+	obj =NULL;
+}
+
+static void axi_location_destroy(struct axi_location *obj)
+{
+	free(obj);
+	obj = NULL;
+}
+
+static char *app_axisend = "XMPPSend";
+
+static char *axisend_synopsis = "XMPPSend(XMPP,ScreenName,Message)";
+
+static char *axisend_descrip =
+"XMPPSend(XMPP,ScreenName,Message)\n"
+"  XMPP - Client or transport Asterisk uses to connect to XMPP\n"
+"  ScreenName - User Name to message.\n"
+"  Message - Message to be sent to the user\n";
+
+static char *app_axistatus = "XMPPStatus";
+
+static char *axistatus_synopsis = "XMPPStatus(XMPP,ScreenName,Variable)";
+
+static char *axistatus_descrip =
+"XMPPStatus(XMPP,ScreenName,Variable)\n"
+"  XMPP - Client or transport Asterisk uses to connect to XMPP\n"
+"  ScreenName - User Name to retrieve status from.\n"
+"  Variable - Variable to store presence in will be 1-6.\n"
+"	      In order, Online, Chatty, Away, XAway, DND, Offline\n"
+"	      If not in roster variable will = 7\n";
+
+static int axi_status_exec(struct ast_channel *chan, void *data)
+{
+	struct axi_master *asterisk=NULL;
+	struct axi_user *user=NULL;
+	char *s=NULL,*sender=NULL,*screenname=NULL,*variable=NULL;
+	int stat=7;
+	char status[2];
+	char *tmp;
+	if (data) {
+		s = ast_strdupa((char *)data);
+		if (s) {
+			sender = strsep(&s,"|");
+			asterisk = ASTOBJ_CONTAINER_FIND(&masters,sender);
+			if(sender && (sender[0]!='\0')){
+				screenname = strsep(&s, "|");
+				if (screenname && (screenname[0] != '\0')) {
+					variable = s;
+				} else {
+					ast_log(LOG_ERROR, "Bad arguments\n");
+					return -1;
+				}	
+			}
+		}
+	}else{
+		ast_log(LOG_ERROR, "Out of memory\n");
+		return -1;
+	}
+	if(strchr(screenname,'@')) /*real xmpp id */
+	{
+		if(strchr(screenname,'/')) /* has specific resource */
+		{
+			tmp=strchr(screenname,'/');
+			tmp++;
+			ASTOBJ_CONTAINER_TRAVERSE2(&asterisk->users,1,1,{
+			ASTOBJ_RDLOCK(iterator1);
+			{
+				if(strncasecmp(iterator1->user,screenname,strlen(iterator1->user))==0)
+				{
+					ASTOBJ_CONTAINER_TRAVERSE2(&iterator1->resource,2,1,{
+					ASTOBJ_RDLOCK(iterator2);
+					if(!strcasecmp(iterator2->name,tmp))
+						stat=iterator2->status;
+					ASTOBJ_UNLOCK(iterator2);
+					});
+				}
+			}
+			ASTOBJ_UNLOCK(iterator1);
+			});
+		}
+		else{
+			ASTOBJ_CONTAINER_TRAVERSE2(&asterisk->users,1,1,{
+			ASTOBJ_RDLOCK(iterator1);
+			{
+				if(!strcasecmp(iterator1->user,screenname))
+				{
+					stat=iterator1->defstatus;
+				}
+			}
+			ASTOBJ_UNLOCK(iterator1);
+			});
+		}
+	}
+	else{			/* just a label*/
+		user=ASTOBJ_CONTAINER_FIND(&asterisk->users,screenname);
+		stat=user->defstatus;
+	}
+	sprintf(status,"%d",stat);
+	pbx_builtin_setvar_helper(chan, variable,status);
+	return 0;
+}
+
+static int axi_send_exec(struct ast_channel *chan, void *data)
+{
+	struct axi_master *asterisk=NULL;
+
+	char *s=NULL,*sender=NULL,*recipiant=NULL,*message=NULL;
+	if (data) {
+		s = ast_strdupa((char *)data);
+		if (s) {
+			sender = strsep(&s,"|");
+			asterisk = ASTOBJ_CONTAINER_FIND(&masters,sender);
+			if(sender && (sender[0]!='\0')){
+				recipiant = strsep(&s, "|");
+				if (recipiant && (recipiant[0] != '\0')) {
+					message = s;
+				} else {
+					ast_log(LOG_ERROR, "Bad arguments \n");
+					return -1;
+				}	
+			}
+		}
+	}else{
+		ast_log(LOG_ERROR, "Out of memory\n");
+		return -1;
+	}
+		if(asterisk)
+			ast_axi_send(asterisk,recipiant,message);
+	return 0;
+}
+
+static void axi_log_hook(void *udata, const char *data, size_t size,int is_incoming)
+{
+	struct axi_master *asterisk = ASTOBJ_REF((struct axi_master *) udata);
+	char *buf = (char *) malloc(size + 1);
+	memcpy(buf, data, size);
+	buf[size] = 0;
+	if (asterisk->debug == 1) {
+		if (is_incoming)
+			ast_verbose("\nXMPP: %s INCOMING: %s\n",asterisk->name, buf);
+		else
+			ast_verbose("\nXMPP: %s OUTGOING: %s\n",asterisk->name, buf);
+
+	}
+	if(asterisk)
+		ASTOBJ_UNREF(asterisk, axi_master_destroy);
+}
+
+static int axi_execute(struct axi_master *asterisk, char *action, char *user, char *message, int type)
+{	
+	struct axi_action *tmp = first_action;
+
+	while( tmp ) {
+			if (!strcasecmp(action, tmp->action)) {
+					if (tmp->func(asterisk,user, message, type))
+					{
+						return -1;
+					}
+			}
+			else{
+				tmp = tmp->next;
+			}
+	}
+	return 0;
+	
+}
+
+static int axi_act_hook(void *udata, int type, iks * node)
+{
+	struct axi_master *asterisk = ASTOBJ_REF((struct axi_master *) udata);
+	ikspak *pak;
+	if(strlen(asterisk->sid)==0){
+		ast_copy_string(asterisk->sid,iks_find_attrib(node, "id"),sizeof(asterisk->sid));
+	}
+
+	pak=iks_packet(node);
+
+	iks_filter_packet (asterisk->f,pak);
+		
+		if (type == IKS_NODE_START) {
+		}
+	
+		if (type == IKS_NODE_NORMAL) {
+			switch(pak->type){
+				case IKS_PAK_NONE:
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Don't know what to do with you NONE\n");
+					break;
+				case IKS_PAK_MESSAGE:
+					axi_handle_message(asterisk,pak);
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Don't know what to do with you MESSAGE\n");
+					break;
+				case IKS_PAK_PRESENCE:
+					axi_handle_presence(asterisk,pak);
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Do know how to handle presence!!\n");
+					break;
+				case IKS_PAK_S10N:
+					axi_handle_subscribe(asterisk,pak);
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Dont know S10N subscribe!!\n");
+					break;
+				case IKS_PAK_IQ:
+					axi_handle_iq(asterisk,pak);
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Dont have an IQ!!!\n");
+					break;
+				default:
+					ast_verbose(VERBOSE_PREFIX_3 "XMPP: I Dont know %i\n",pak->type );
+			}
+		}
+		if (type == IKS_NODE_ERROR) {
+		}
+		if (type == IKS_NODE_STOP) {
+		}
+	
+	if (node){
+	 	iks_delete(node);
+	}
+	if(asterisk)
+		ASTOBJ_UNREF(asterisk, axi_master_destroy);
+	return IKS_OK;
+}
+
+static void axi_handle_message(struct axi_master *asterisk, ikspak *pak)
+{
+/*	ast_verbose("%s\n",pak->id);
+	if(pak->subtype == IKS_TYPE_CHAT)
+	{
+	}
+	*/
+}
+static void axi_handle_iq(struct axi_master *asterisk, ikspak *pak)
+{
+}
+
+int ast_axi_check_roster(void)
+{
+	char action[100];
+	char fullname[100];
+	ASTOBJ_CONTAINER_TRAVERSE2(&masters,1,1, {
+		ASTOBJ_RDLOCK(iterator1);
+		ASTOBJ_CONTAINER_TRAVERSE2(&iterator1->users,2,1, {
+			ASTOBJ_RDLOCK(iterator2);
+			ASTOBJ_CONTAINER_TRAVERSE2(&iterator2->resource,3,1, {
+				ASTOBJ_RDLOCK(iterator3);
+				if(iterator3->status){
+				sprintf(action,"axi_agent%s",iterator2->user);
+				sprintf(fullname,"%s/%s",iterator2->user,iterator3->name);
+				axi_execute(iterator1,action,fullname,iterator3->channel,iterator3->status);
+				}
+				ASTOBJ_UNLOCK(iterator3);
+			});
+			ASTOBJ_UNLOCK(iterator2);
+		});
+		ASTOBJ_UNLOCK(iterator1);
+	});
+	return 1;
+}
+static void axi_handle_presence(struct axi_master *asterisk, ikspak *pak)
+{
+	char action[100];
+	char *agent=NULL;
+	char *channel=NULL;
+	struct axi_user *user=NULL;
+	char *tmp;
+	int status=6;
+	int repeatflag=0; /* dont send event if status is same. */
+	struct axi_location *resource=NULL;
+
+	status=(pak->show)?pak->show:6;
+	ASTOBJ_CONTAINER_TRAVERSE(&asterisk->users,1, {
+			ASTOBJ_RDLOCK(iterator);
+			if(!strncasecmp(iks_find_attrib(pak->x,"from"),iterator->user,strlen(iterator->user)))
+				user=iterator;
+			ASTOBJ_UNLOCK(iterator);
+		});
+
+	if(user){
+		tmp=(strchr(iks_find_attrib(pak->x,"from"),'/'))?strchr(iks_find_attrib(pak->x,"from"),'/'):"/noresource";
+		tmp++;
+		agent=user->user;
+		channel=user->defchannel;
+		user->defstatus=(pak->show==0?6:pak->show);
+		if((resource=ASTOBJ_CONTAINER_FIND(&user->resource,tmp)))
+		{
+			if(status==resource->status)
+					repeatflag=0;
+				else
+					repeatflag=1;
+				resource->status=status;
+			resource->priority=atoi((iks_find_cdata(pak->x,"priority"))?iks_find_cdata(pak->x,"priority"):"0");
+			ASTOBJ_UNREF(resource,axi_location_destroy);
+		}
+		else
+		{
+			resource = malloc(sizeof(struct axi_location));
+			ASTOBJ_INIT(resource);
+			ASTOBJ_WRLOCK(resource);
+			ast_copy_string(resource->name, tmp, sizeof(resource->name));
+			ast_copy_string(resource->channel,channel,sizeof(resource->channel));
+			resource->status=status;
+			repeatflag=1;
+			resource->priority=atoi((iks_find_cdata(pak->x,"priority"))?iks_find_cdata(pak->x,"priority"):"0");
+			ASTOBJ_UNLOCK(resource);
+			ASTOBJ_CONTAINER_LINK(&user->resource, resource);
+			
+		}
+	}
+	if(agent && user)
+	{
+		sprintf(action,"axi_agent%s",agent);
+		if(repeatflag){
+			axi_execute(asterisk,action,iks_find_attrib(pak->x,"from"),channel,status);
+		}
+		ASTOBJ_CONTAINER_TRAVERSE(&user->resource,1,{
+			ASTOBJ_RDLOCK(iterator);
+			if((!strcasecmp(iterator->name,tmp)) && (iterator->status==6) && (!strcasecmp(iterator->channel,user->defchannel)))
+			{
+				ASTOBJ_CONTAINER_UNLINK(&user->resource,iterator);
+			}
+		ASTOBJ_UNLOCK(iterator);
+		});
+
+		switch(pak->subtype) {
+			case IKS_TYPE_AVAILABLE:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: I am available ^_* %i\n",pak->subtype );
+				break;
+			case IKS_TYPE_UNAVAILABLE:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: I am available ^_* %i\n",pak->subtype );
+				break;
+			default:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: Ohh sexy and the wrong type%i\n",pak->subtype );
+		}
+		switch(pak->show)
+		{
+			case IKS_SHOW_UNAVAILABLE:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type: %i subtype %i\n",pak->subtype,pak->show);
+				break;
+			case IKS_SHOW_AVAILABLE:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type is available\n");
+				break;
+			case IKS_SHOW_CHAT:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type: %i subtype %i\n",pak->subtype,pak->show);
+				break;
+			case IKS_SHOW_AWAY:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type is away\n");
+	
+				break;
+			case IKS_SHOW_XA:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type: %i subtype %i\n",pak->subtype,pak->show);
+				break;
+			case IKS_SHOW_DND:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: type: %i subtype %i\n",pak->subtype,pak->show);
+				break;
+			default:
+				ast_verbose(VERBOSE_PREFIX_3 "XMPP: Kinky! how did that happen %i\n",pak->show);
+		}
+
+	}
+}
+
+static void axi_handle_subscribe(struct axi_master *asterisk, ikspak *pak)
+{
+	int res=0;
+	switch(pak->subtype)
+	{
+		case IKS_TYPE_SUBSCRIBE:
+			res =iks_send(asterisk->p,iks_make_s10n(IKS_TYPE_SUBSCRIBED,iks_find_attrib(pak->x, "from"),"Asterisk has approved subscription"));
+			ast_verbose(VERBOSE_PREFIX_3 "XMPP: This is a subcription of type %i\n",pak->subtype );
+			break;
+		case IKS_TYPE_SUBSCRIBED:
+			ast_verbose(VERBOSE_PREFIX_3 "XMPP: This is a subcription of type %i\n",pak->subtype );
+			break;
+		case IKS_TYPE_UNSUBSCRIBE:
+			ast_verbose(VERBOSE_PREFIX_3 "XMPP: This is a subcription of type %i\n",pak->subtype );
+			break;
+		case IKS_TYPE_UNSUBSCRIBED:
+			ast_verbose(VERBOSE_PREFIX_3 "XMPP: This is a subcription of type %i\n",pak->subtype );
+			break;
+		default: /*IKS_TYPE_ERROR:*/
+			ast_verbose(VERBOSE_PREFIX_3 "XMPP: This is a subcription of type %i\n",pak->subtype );
+			break;
+	}
+}
+
+int ast_axi_send(struct axi_master *asterisk, char *address, char *message)
+{
+	int res=0;
+	iks *message_packet;
+	if(asterisk->state==AXI_CONNECTED){
+		message_packet=iks_make_msg(IKS_TYPE_CHAT, address, message);
+		iks_insert_attrib(message_packet,"from",asterisk->user);
+		res =iks_send(asterisk->p,message_packet);
+	 	iks_delete(message_packet);
+	}
+	else
+		ast_verbose("We arent connected dont send\n");
+	return 1;
+}
+
+int ast_axi_create_chat(struct axi_master *asterisk,char *room, char *server, char *topic)
+{
+	int res=0;
+	iks *iq, *query;
+	iq = iks_new("iq");
+	iks_insert_attrib(iq,"type","get");
+	iks_insert_attrib(iq,"to",server);
+	iks_insert_attrib(iq,"id",asterisk->mid);
+	axi_increment_mid(asterisk->mid);
+	
+	return res; 
+}
+
+int ast_axi_join_chat(struct axi_master *asterisk,char *room)
+{
+	int res=0;
+	iks *p1,*priority, *priority2, *p2;
+	p1 = iks_new("presence");
+	priority = iks_new("priority");
+	iks_insert_cdata(priority,"0",strlen("0"));
+	iks_insert_attrib(p1,"to",room);
+	iks_insert_node(p1,priority);
+	res =iks_send(asterisk->p,p1);
+	iks_delete(p1);
+	iks_delete(priority);
+
+	p2 = iks_new("presence");
+	priority2= iks_new("priority");
+	iks_insert_cdata(priority2,"5",strlen("5"));
+	iks_insert_attrib(p2,"to",room);
+	iks_insert_node(p2,priority2);
+	res =iks_send(asterisk->p,p2);
+	iks_delete(p2);
+	iks_delete(priority2);
+	return 1;
+}
+int ast_axi_invite_chat(struct axi_master *asterisk, char *user, char *room, char *message)
+{
+	int res=0;
+	iks *invite,*body,*namespace;
+	invite = iks_new("message");
+	body = iks_new("body");
+	namespace = iks_new("x");
+	iks_insert_attrib(invite,"to",user);
+	iks_insert_attrib(invite,"id",asterisk->mid);
+	axi_increment_mid(asterisk->mid);
+	iks_insert_cdata(body,message,strlen(message));
+	iks_insert_attrib(namespace,"xmlns","jabber:x:conference");
+	iks_insert_attrib(namespace,"jid",room);
+	iks_insert_node(invite,body);
+	iks_insert_node(invite,namespace);
+	res =iks_send(asterisk->p,invite);
+	iks_delete(body);
+	iks_delete(namespace);
+	iks_delete(invite);
+	return 1;
+}
+

[... 874 lines stripped ...]


More information about the asterisk-commits mailing list