[svn-commits] branch mogorman/asterisk-xmpp - r7334 in
/team/mogorman/asterisk-xmpp: ./ cha...
svn-commits at lists.digium.com
svn-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 svn-commits
mailing list