[svn-commits] phsultan: branch phsultan/jabberreceive r164796 - in /team/phsultan/jabberrec...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Dec 16 13:20:16 CST 2008


Author: phsultan
Date: Tue Dec 16 13:20:16 2008
New Revision: 164796

URL: http://svn.digium.com/view/asterisk?view=rev&rev=164796
Log:
Several changes to the implentation of the new XMPP messages reception functionality. The new approach is the result of discussions on the -dev mailing list and the code review board.

1) Implement a function (JABBER_RECEIVE) rather than an application.
2) Store all messages in a list, and pull them when calling JABBER_RECEIVE.
   When an XMPP messages comes in, all messages stored longer than a 
   configured value (default : 2 seconds) are removed.
3) Document all functions and applications with XML.

Modified:
    team/phsultan/jabberreceive/channels/chan_gtalk.c
    team/phsultan/jabberreceive/channels/chan_jingle.c
    team/phsultan/jabberreceive/configs/jabber.conf.sample
    team/phsultan/jabberreceive/doc/jabber.txt
    team/phsultan/jabberreceive/res/res_jabber.c

Modified: team/phsultan/jabberreceive/channels/chan_gtalk.c
URL: http://svn.digium.com/view/asterisk/team/phsultan/jabberreceive/channels/chan_gtalk.c?view=diff&rev=164796&r1=164795&r2=164796
==============================================================================
--- team/phsultan/jabberreceive/channels/chan_gtalk.c (original)
+++ team/phsultan/jabberreceive/channels/chan_gtalk.c Tue Dec 16 13:20:16 2008
@@ -1468,7 +1468,6 @@
 	int res = 0;
 	struct aji_client *client = NULL;
 	struct gtalk_pvt *p = chan->tech_pvt;
-	
 
 	if (!p->parent) {
 		ast_log(LOG_ERROR, "Parent channel not found\n");

Modified: team/phsultan/jabberreceive/channels/chan_jingle.c
URL: http://svn.digium.com/view/asterisk/team/phsultan/jabberreceive/channels/chan_jingle.c?view=diff&rev=164796&r1=164795&r2=164796
==============================================================================
--- team/phsultan/jabberreceive/channels/chan_jingle.c (original)
+++ team/phsultan/jabberreceive/channels/chan_jingle.c Tue Dec 16 13:20:16 2008
@@ -1295,12 +1295,12 @@
 	}
 	if (!p->parent->connection) {
 		ast_log(LOG_ERROR, "XMPP client not found\n");
-		return -1; 
+		return -1;
 	}
 	client = p->parent->connection;
 	ast_aji_send_chat(client, p->them, text);
 	return res;
-}               
+}
 
 static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
 {

Modified: team/phsultan/jabberreceive/configs/jabber.conf.sample
URL: http://svn.digium.com/view/asterisk/team/phsultan/jabberreceive/configs/jabber.conf.sample?view=diff&rev=164796&r1=164795&r2=164796
==============================================================================
--- team/phsultan/jabberreceive/configs/jabber.conf.sample (original)
+++ team/phsultan/jabberreceive/configs/jabber.conf.sample Tue Dec 16 13:20:16 2008
@@ -20,4 +20,4 @@
 					;;	xaway, or dnd
 ;statusmessage="I am available"		;;Have custom status message for
 					;;Asterisk.
-;timeout=100				;;Timeout on the message stack.
+;timeout=2				;;Timeout (in seconds) on the message stack, defaults to 2.

Modified: team/phsultan/jabberreceive/doc/jabber.txt
URL: http://svn.digium.com/view/asterisk/team/phsultan/jabberreceive/doc/jabber.txt?view=diff&rev=164796&r1=164795&r2=164796
==============================================================================
--- team/phsultan/jabberreceive/doc/jabber.txt (original)
+++ team/phsultan/jabberreceive/doc/jabber.txt Tue Dec 16 13:20:16 2008
@@ -1,39 +1,20 @@
 XMPP (Jabber) is an xml based protocol primarily for presence and messaging.
 It is an open standard and there are several open server implementations,
-ejabberd, jabberd(2), wildfire, and many others, as well as several open source
+ejabberd, jabberd(2), openfire, and many others, as well as several open source
 clients, Psi, gajim, gaim etc. XMPP differs from other IM applications as it
-is immensly extendable.  This allows us to easily integrate Asterisk with 
+is immensly extendable.  This allows us to easily integrate Asterisk with
 XMPP. The Asterisk XMPP Interface is provided by res_jabber.so.
 
 res_jabber allows for Asterisk to connect to any XMPP (Jabber) server and
 is also used to provide the connection interface for chan_jingle and
 chan_gtalk.
 
-A function (JABBER_STATUS) and two applications (JabberSend and
-JabberReceive) are exposed to the dialplan.
+Functions (JABBER_STATUS, JABBER_RECEIVE) and applications (JabberSend) 
+are exposed to the dialplan.
 
-You'll find examples of how to use these function/applications
+You'll find examples of how to use these functions/applications
 hereafter. We assume that 'asterisk-xmpp' is properly configured in
 jabber.conf.
-
-**** JABBER_STATUS ****
-
-Note : as of version 1.6, the corresponding application JabberStatus is still
-available, but marked as deprecated in favor of this function.
-
-JABBER_STATUS stores the status of a buddy in a dialplan variable for
-further use. Here is an AEL example of how to use it :
-
-1234 => {
-         JabberStatus(asterisk-xmpp,buddy at gmail.com,STATUS);
-         if (${STATUS}=1) {
-                   NoOp(User is online and active, ring his Gtalk client.);
-                   Dial(Gtalk/asterisk-xmpp/buddy at gmail.com);
-         } else {
-                   NoOp(Prefer the SIP phone);
-                   Dial(SIP/1234);
-         }
-}
 
 **** JabberSend ****
 
@@ -47,19 +28,38 @@
 	}
 }
 
-**** JabberReceive ****
+**** JABBER_STATUS ****
 
-JabberReceive waits (up to X seconds) for a message from buddy and stores
-it to a dialplan variable. Used along with JabberSend (or SendText, 
+Note : as of version 1.6, the corresponding application JabberStatus is still
+available, but marked as deprecated in favor of this function.
+
+JABBER_STATUS stores the status of a buddy in a dialplan variable for
+further use. Here is an AEL example of how to use it :
+
+1234 => {
+	Set(STATUS=${JABBER_STATUS(asterisk-xmpp,buddy at gmail.com)});
+	if (${STATUS}=1) {
+		NoOp(User is online and active, ring his Gtalk client.);
+		Dial(Gtalk/asterisk-xmpp/buddy at gmail.com);
+	} else {
+		NoOp(Prefer the SIP phone);
+		Dial(SIP/1234);
+	}
+}
+
+**** JABBER_RECEIVE ****
+
+JABBER_RECEIVE waits (up to X seconds) for a XMPP message and returns
+its content. Used along with JabberSend (or SendText,
 provided it's implemented in the corresponding channel type),
-JabberReceive helps Asterisk interact with users while calls flow
+JABBER_RECEIVE helps Asterisk interact with users while calls flow
 through the dialplan.
 
-JabberReceive/JabberSend are not tied to the XMPP media modules
+JABBER_RECEIVE/JabberSend are not tied to the XMPP media modules
 chan_gtalk and chan_jingle, and can be used anywhere in the dialplan.
-In the following example, calls targeted to extension 1234 (be it 
+In the following example, calls targeted to extension 1234 (be it
 accessed from SIP, DAHDI or whatever channel type) are controlled by
-user bob at jabber.org. Asterisk notifies him that a call is coming, and
+user bob at domain.com. Asterisk notifies him that a call is coming, and
 asks him to take an action. This dialog takes place over an XMPP chat.
 
 context from-ext {
@@ -69,10 +69,10 @@
 		JabberSend(asterisk-xmpp,bob at jabber.org,1 : forward to cellphone);
 		JabberSend(asterisk-xmpp,bob at jabber.org,2 : forward to work phone);
 		JabberSend(asterisk-xmpp,bob at jabber.org,Default action : forward to your voicemail);
-		JabberReceive(bob at jabber.org,OPTION,20);
+		Set(OPTION=${JABBER_RECEIVE(asterisk-xmpp,bob at jabber.org,20)});
 		switch (${OPTION}) {
 			case 1:
-	  			JabberSend(asterisk-xmpp,bob at jabber.org,(Calling cellphone...);
+				JabberSend(asterisk-xmpp,bob at jabber.org,(Calling cellphone...);
 				Dial(SIP/987654321);
 				break;
 			case 2:
@@ -85,11 +85,11 @@
 	}
 }
 
-When calling from a GoogleTalk or Jingle client, the CALLERID(name) 
-is set to the XMPP id of the caller (i.e. his JID). In the 
-following example, Asterisk chats back with the caller identified by the 
-caller id. We also take advantage of the SendText implementation in 
-chan_gtalk (available in chan_jingle, and chan_sip as well), to 
+When calling from a GoogleTalk or Jingle client, the CALLERID(name)
+is set to the XMPP id of the caller (i.e. his JID). In the
+following example, Asterisk chats back with the caller identified by the
+caller id. We also take advantage of the SendText implementation in
+chan_gtalk (available in chan_jingle, and chan_sip as well), to
 allow the caller to establish SIP calls from his GoogleTalk client :
 
 context gtalk-in {
@@ -97,10 +97,10 @@
 	  NoOp(Caller id : ${CALLERID(all)});
 	  Answer();
 	  SendText(Please enter the number you wish to call);
-	  JabberReceive(${CALLERID(name)},NEWEXTEN);
+	  Set(NEWEXTEN=${JABBER_RECEIVE(asterisk-xmpp,${CALLERID(name)})});
 	  SendText(Calling ${NEWEXTEN} ...);
 	  Dial(SIP/${NEWEXTEN);
-	  Hangup(); 
+	  Hangup();
 	}
 }
 

Modified: team/phsultan/jabberreceive/res/res_jabber.c
URL: http://svn.digium.com/view/asterisk/team/phsultan/jabberreceive/res/res_jabber.c?view=diff&rev=164796&r1=164795&r2=164796
==============================================================================
--- team/phsultan/jabberreceive/res/res_jabber.c (original)
+++ team/phsultan/jabberreceive/res/res_jabber.c Tue Dec 16 13:20:16 2008
@@ -34,6 +34,97 @@
 	<depend>iksemel</depend>
 	<use>openssl</use>
  ***/
+/*** DOCUMENTATION
+	<application name="JabberSend" language="en_US">
+		<synopsis>
+			Sends an XMPP message to a buddy.
+		</synopsis>
+		<syntax>
+			<parameter name="account" required="true">
+				<para>The local named account to listen on (specified in 
+				jabber.conf)</para>
+			</parameter>
+			<parameter name="jid" required="true">
+				<para>Jabber ID of the buddy to send the message to. It can be a 
+				bare JID (username at domain) or a full JID (username at domain/resource).</para>
+			</parameter>
+			<parameter name="message" required="true">
+				<para>The message to send.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Sends the content of <replaceable>message</replaceable> as text message 
+			from the given <replaceable>account</replaceable> to the buddy identified by 
+			<replaceable>jid</replaceable></para>
+			<para>Example: JabberSend(asterisk,bob at domain.com,Hello world) sends "Hello world"
+			to <replaceable>bob at domain.com</replaceable> as an XMPP message from the account
+			<replaceable>asterisk</replaceable>, configured in jabber.conf.</para>
+		</description>
+		<see-also>
+			<ref type="function">JABBER_STATUS</ref>
+			<ref type="function">JABBER_RECEIVE</ref>
+		</see-also>
+	</application>
+	<function name="JABBER_RECEIVE" language="en_US">
+		<synopsis>
+			Reads XMPP messages.	
+		</synopsis>
+		<syntax>
+			<parameter name="account" required="true">
+				<para>The local named account to listen on (specified in
+				jabber.conf)</para>
+			</parameter>
+			<parameter name="jid" required="true">
+				<para>Jabber ID of the buddy to receive message from. It can be a 
+				bare JID (username at domain) or a full JID (username at domain/resource).</para>
+			</parameter>
+			<parameter name="timeout">
+				<para>In seconds, defaults to <literal>20</literal>.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Receives a text message on the given <replaceable>account</replaceable>
+			from the buddy identified by <replaceable>jid</replaceable> and returns the contents.</para>
+			<para>Example: ${JABBER_RECEIVE(asterisk,bob at domain.com)} returns an XMPP message
+			sent from <replaceable>bob at domain.com</replaceable> (or nothing in case of a time out), to 
+			the <replaceable>asterisk</replaceable> XMPP account configured in jabber.conf.</para>
+		</description>
+		<see-also>
+			<ref type="function">JABBER_STATUS</ref>
+			<ref type="application">JabberSend</ref>
+		</see-also>
+	</function>
+	<function name="JABBER_STATUS" language="en_US">
+		<synopsis>
+			Retrieves a buddy's status.	
+		</synopsis>
+		<syntax>
+			<parameter name="account" required="true">
+				<para>The local named account to listen on (specified in
+				jabber.conf)</para>
+			</parameter>
+			<parameter name="jid" required="true">
+				<para>Jabber ID of the buddy to receive message from. It can be a 
+				bare JID (username at domain) or a full JID (username at domain/resource).</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Retrieves the numeric status associated with the buddy identified 
+			by <replaceable>jid</replaceable>.
+			If the buddy does not exist in the buddylist, returns 7.</para>
+			<para>Status will be 1-7.</para>
+	   		<para>1=Online, 2=Chatty, 3=Away, 4=XAway, 5=DND, 6=Offline</para>
+			<para>If not in roster variable will be set to 7.</para>
+			<para>Example: ${JABBER_STATUS(asterisk,bob at domain.com)} returns 1 if 
+			<replaceable>bob at domain.com</replaceable> is online. <replaceable>asterisk</replaceable> is 
+			the associated XMPP account configured in jabber.conf.</para>
+		</description>
+		<see-also>
+			<ref type="function">JABBER_RECEIVE</ref>
+			<ref type="application">JabberSend</ref>
+		</see-also>
+	</function>
+ ***/
 
 #include "asterisk.h"
 
@@ -74,9 +165,9 @@
 /*-- Forward declarations */
 static void aji_buddy_destroy(struct aji_buddy *obj);
 static void aji_client_destroy(struct aji_client *obj);
+static int delete_old_messages(struct aji_client *client);
 static int aji_send_exec(struct ast_channel *chan, void *data);
 static int aji_status_exec(struct ast_channel *chan, void *data);
-static int aji_recv_exec(struct ast_channel *chan, void *data);
 static int aji_is_secure(struct aji_client *client);
 #ifdef HAVE_OPENSSL
 static int aji_start_tls(struct aji_client *client);
@@ -133,14 +224,6 @@
 
 static char *app_ajisend = "JabberSend";
 
-static char *ajisend_synopsis = "JabberSend(Jabber,JID,Message)";
-
-static char *ajisend_descrip =
-"JabberSend(Jabber,JID,Message)\n"
-"  Jabber   - Client or transport Asterisk uses to connect to Jabber\n" 
-"  JID      - XMPP/Jabber JID (Name) of recipient\n" 
-"  Message  - Message to be sent to the buddy\n";
-
 static char *app_ajistatus = "JabberStatus";
 
 static char *ajistatus_synopsis = "JabberStatus(Jabber,JID,Variable)";
@@ -153,16 +236,6 @@
 "             In order, 1=Online, 2=Chatty, 3=Away, 4=XAway, 5=DND, 6=Offline\n" 
 "             If not in roster variable will be set to 7\n\n"
 "Note: This application is deprecated. Please use the JABBER_STATUS() function instead.\n";
-
-static char *app_ajirecv = "JabberReceive";
-
-static char *ajirecv_synopsis = "JabberReceive(Variable)";
-
-static char *ajirecv_descrip =
-"JabberReceive(JID,Variable[,timeout])\n"
-"  JID      - Jabber ID of the buddy to receive message from\n" 
-"  Variable - Variable to store message in\n"
-"  timeout  - Defaults to 20s\n" ;
 
 struct aji_client_container clients;
 struct aji_capabilities *capabilities = NULL;
@@ -457,16 +530,164 @@
 
 static struct ast_custom_function jabberstatus_function = {
 	.name = "JABBER_STATUS",
-	.synopsis = "Retrieve buddy status",
-	.syntax = "JABBER_STATUS(<sender>,<buddy>[/<resource>])",
 	.read = acf_jabberstatus_read,
-	.desc =
-"Retrieves the numeric status associated with the specified buddy (jid). If the\n"
-"buddy does not exist in the buddylist, returns 7.\n"
-"Status will be 1-7.\n" 
-"             1=Online, 2=Chatty, 3=Away, 4=XAway, 5=DND, 6=Offline\n" 
-"             If not in roster variable will be set to 7\n\n",
 };
+
+ /*!
+ * \brief Dial plan function to receive a message.
+ * \param channel, and data, data is account, JID and optional
+ * timeout.
+ * \return 0 on success, -1 on failure.
+ */
+static int acf_jabberreceive_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
+{
+	char *aux = NULL, *parse = NULL;
+	int timeout;
+	time_t triggered;
+	struct aji_client *client = NULL;
+	int found = 0;
+	struct aji_message *tmp = NULL;
+	iksid *id = NULL;
+	AST_DECLARE_APP_ARGS(args,
+			AST_APP_ARG(account);
+			AST_APP_ARG(jid);
+			AST_APP_ARG(timeout);
+			);
+
+	time(&triggered);
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
+		return -1;
+	}
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc < 2 || args.argc > 3) {
+                ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
+		return -1;
+	}
+
+	client = ast_aji_get_client(args.account);
+	if (!client) {
+		ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account);
+		return -1;
+	}
+
+	id = iks_id_new(client->stack, args.jid);	
+	if (!id) {
+		ast_log(LOG_WARNING, "Could not build a valid Jabber Identifier from %s, exiting\n", args.jid);
+		return -1;
+	}
+
+	if (ast_strlen_zero(args.timeout)) {
+		timeout = 20;
+	} else {
+		timeout = atoi(args.timeout);
+		if (timeout <= 0) {
+			ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
+			return -1;
+		}
+	}
+
+	ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid);
+
+	/* search the messages list, grab the first message that matches with 
+	 * the from JID we're expecting, remove it from the messages list */
+	while (difftime(time(NULL), triggered) < timeout) {
+		AST_LIST_LOCK(&client->messages);
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
+			iksid *from = iks_id_new(client->stack, tmp->from);
+			if (!from) {
+				ast_log(LOG_WARNING, "Could not build a valid Jabber Identifier from %s, exiting\n", tmp->from);
+				return -1;
+			}
+			if (strchr(args.jid, '/')) {
+				if (iks_id_cmp(from, id, IKS_ID_RESOURCE | IKS_ID_USER | IKS_ID_SERVER)) {
+					continue;
+				}
+			} else {
+				if (iks_id_cmp(from, id, IKS_ID_USER | IKS_ID_SERVER)) {
+					continue;
+				}
+			}
+			found = 1;
+			aux = ast_strdupa(tmp->message);
+			AST_LIST_REMOVE_CURRENT(list);
+			if (tmp->from) {
+				ast_free(tmp->from);
+			}
+			if (tmp->message) {
+				ast_free(tmp->message);
+			}
+			break;
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+		AST_LIST_UNLOCK(&client->messages);
+		if (found) {
+			break;
+		}
+		ast_safe_sleep(chan, 500);
+	}
+	/* return if we timed out */
+	if (!found) {
+		ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
+		return -1;
+	}
+	ast_copy_string(buf, aux, buflen);
+	return 0;
+}
+
+static struct ast_custom_function jabberreceive_function = {
+	.name = "JABBER_RECEIVE",
+	.read = acf_jabberreceive_read,
+};
+
+/*!
+ * \brief Delete old messages
+ * Messages stored during more than client->message_timeout are deleted
+ * \param client Asterisk's XMPP client
+ * \return the number of deleted messages, or -1 in case of failure
+ */
+static int delete_old_messages(struct aji_client *client) {
+	int deleted = 0;
+	int flag = 0;
+	struct aji_message *tmp = NULL;
+	if (!client) {
+		ast_log(LOG_ERROR, "Cannot find our XMPP client\n");
+		return -1;
+	}
+	
+	/* remove old messages */	
+	AST_LIST_LOCK(&client->messages);
+	if (AST_LIST_EMPTY(&client->messages)) {
+		AST_LIST_UNLOCK(&client->messages);
+		return 0;
+	}
+
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
+		if (flag) {
+			AST_LIST_REMOVE_CURRENT(list);
+			if (tmp->from)
+				ast_free(tmp->from);
+			if (tmp->message)
+				ast_free(tmp->message);
+			deleted ++;
+		} else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
+			flag = 1;
+			AST_LIST_REMOVE_CURRENT(list);
+			if (tmp->from)
+				ast_free(tmp->from);
+			if (tmp->message)
+				ast_free(tmp->message);
+			deleted ++;
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END;
+	AST_LIST_UNLOCK(&client->messages);
+
+	return deleted;
+}
 
 /*!
  * \brief Dial plan function to send a message.
@@ -485,14 +706,14 @@
 	);
 
 	if (!data) {
-		ast_log(LOG_ERROR, "Usage:  JabberSend(<sender>,<recipient>,<message>)\n");
-		return 0;
+		ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
+		return -1;
 	}
 	s = ast_strdupa(data);
 
 	AST_STANDARD_APP_ARGS(args, s);
 	if (args.argc < 3) {
-		ast_log(LOG_ERROR, "JabberSend requires 3 arguments: '%s'\n", (char *) data);
+		ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
 		return -1;
 	}
 
@@ -500,8 +721,9 @@
 		ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
 		return -1;
 	}
-	if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message))
+	if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) {
 		ast_aji_send_chat(client, args.recipient, args.message);
+	}
 	return 0;
 }
 
@@ -774,61 +996,6 @@
 		return ret;	
 
 	return IKS_OK;
-}
-
- /*!
- * \brief Dial plan function to receive a message.
- * \param channel, and data, data is sender, variable.
- * \return 1 on success, -1 on failure.
- */
-static int aji_recv_exec(struct ast_channel *chan, void *data)
-{
-	char message[AST_MAX_EXTENSION];
-	char *buf, *parse, *variable = NULL;
-	int to; /* timeout */
-	
-	AST_DECLARE_APP_ARGS(args,
-			     AST_APP_ARG(sender);
-			     AST_APP_ARG(variable);
-			     AST_APP_ARG(timeout);
-			     );
-
-	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "%s requires arguments (sender,variable[,timeout])\n", app_ajirecv);
-		return -1;
-	}
-
-	parse = ast_strdupa(data);
-	AST_STANDARD_APP_ARGS(args, parse);
-
-	if (args.argc < 2 || args.argc > 3) {
-		ast_log(LOG_WARNING, "%s requires arguments (sender,variable[,timeout])\n", app_ajirecv);
-		return -1;
-	}
-
-	if (ast_strlen_zero(args.timeout)) {
-		to = 20000;
-	} else {
-		to = atoi(args.timeout);
-		if (to > 0) {
-			to *= 1000;
-		} else {
-			ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
-			return -1;
-		}
-	}
-
-	ast_debug(3, "Waiting for an XMPP message from %s\n", args.sender);
-	buf = ast_recvtext(chan, to);
-	/* return if we timed out */
-	if (!buf) {
-		return -1;
-	}
-	ast_copy_string(message, buf, sizeof(message));
-	variable = ast_skip_blanks(args.variable);
-	ast_trim_blanks(variable);
-	pbx_builtin_setvar_helper(chan, variable, message);
-	return 1;
 }
 
 /*!
@@ -1536,25 +1703,22 @@
 
 /*!
  * \brief Handles presence packets.
+ * Adds the incoming message to the client's message list.
  * \param client the configured XMPP client we use to connect to a XMPP server
  * \param pak ikspak the node
  */
 static void aji_handle_message(struct aji_client *client, ikspak *pak)
 {
-	struct aji_message *insert, *tmp;
-	struct ast_channel *chan = NULL;
-	char *parse = NULL;
-	struct ast_frame f = { AST_FRAME_TEXT, };
-	int flag = 0;
-	AST_DECLARE_APP_ARGS(args,
-			     AST_APP_ARG(sender);
-			     AST_APP_ARG(variable);
-			     );
+	struct aji_message *insert;
+	int deleted = 0;
 
 	ast_debug(3, "client %s received a message\n", client->name);
-	
-	if (!(insert = ast_calloc(1, sizeof(*insert))))
+
+	if (!(insert = ast_calloc(1, sizeof(*insert)))) {
+		ast_log(LOG_ERROR, "Out of memory.\n");
 		return;
+	}
+
 	time(&insert->arrived);
 	if (iks_find_cdata(pak->x, "body")) {
 		insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
@@ -1564,58 +1728,14 @@
 	}
 	if (pak->from){
 		/* insert will furtherly be added to message list */
- 		insert->from = ast_strdup(pak->from->full);
-	}
-	/* if we receive a message from a buddy, try to pass it to 
-	   a channel waiting for JabberReceive to return */
-	if (pak->from && iks_find_cdata(pak->x, "body")) {
+		insert->from = ast_strdup(pak->from->full);
 		ast_debug(3, "message comes from %s\n", insert->from);
-		
-		/* build the text frame from received message */
-		if (insert->message) {
-			f.datalen = strlen(insert->message);
-			f.data.ptr = (void *) insert->message;
-		}
-
-		while ((chan = ast_channel_walk_locked(chan))) {
-			if (!chan->data) {
-				continue;
-			}
-			parse = ast_strdupa(chan->data);
-			AST_STANDARD_APP_ARGS(args, parse);
-		
-			/* now queue the text frame only if the channel is 
-			   under control of the JabberReceive app *and* the 
-			   XMPP message comes from the configured JID */
-			if (!strcasecmp(chan->appl, "JabberReceive") && !strncmp(args.sender, pak->from->partial, strlen(pak->from->partial))) {
-				ast_debug(3, "Queuing text frame to %s\n", chan->name);				
-				ast_queue_frame(chan, &f);
-			}
-			ast_channel_unlock(chan);
-			if (chan) {
-				break;
-			}
-		}
-	}
-
+	}
+
+	/* remove old messages, and insert received message */	
+	deleted = delete_old_messages(client);
+	ast_debug(3, "Deleted %d messages for client %s\n", deleted, client->name);
 	AST_LIST_LOCK(&client->messages);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
-		if (flag) {
-			AST_LIST_REMOVE_CURRENT(list);
-			if (tmp->from)
-				ast_free(tmp->from);
-			if (tmp->message)
-				ast_free(tmp->message);
-		} else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
-			flag = 1;
-			AST_LIST_REMOVE_CURRENT(list);
-			if (tmp->from)
-				ast_free(tmp->from);
-			if (tmp->message)
-				ast_free(tmp->message);
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
 	AST_LIST_INSERT_HEAD(&client->messages, insert, list);
 	AST_LIST_UNLOCK(&client->messages);
 }
@@ -2714,7 +2834,7 @@
 	client->forcessl = 0;
 	client->keepalive = 1;
 	client->timeout = 50;
-	client->message_timeout = 100;
+	client->message_timeout = 2;
 	AST_LIST_HEAD_INIT(&client->messages);
 	client->component = 0;
 	ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
@@ -3087,9 +3207,9 @@
 	ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli));
 	ast_unregister_application(app_ajisend);
 	ast_unregister_application(app_ajistatus);
-	ast_unregister_application(app_ajirecv);
 	ast_manager_unregister("JabberSend");
 	ast_custom_function_unregister(&jabberstatus_function);
+	ast_custom_function_unregister(&jabberreceive_function);
 	
 	ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
 		ASTOBJ_RDLOCK(iterator);
@@ -3113,11 +3233,11 @@
 		return AST_MODULE_LOAD_DECLINE;
 	ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
 			"Sends a message to a Jabber Client", mandescr_jabber_send);
-	ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);
+	ast_register_application_xml(app_ajisend, aji_send_exec);
 	ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip);
-	ast_register_application(app_ajirecv, aji_recv_exec, ajirecv_synopsis, ajirecv_descrip);
 	ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli));
 	ast_custom_function_register(&jabberstatus_function);
+	ast_custom_function_register(&jabberreceive_function);
 
 	return 0;
 }




More information about the svn-commits mailing list