Index: channels/chan_gtalk.c
===================================================================
--- channels/chan_gtalk.c	(revision 116556)
+++ channels/chan_gtalk.c	(working copy)
@@ -166,6 +166,7 @@
 /* Forward declarations */
 static struct ast_channel *gtalk_request(const char *type, int format, void *data, int *cause);
 static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);
+static int gtalk_sendtext(struct ast_channel *ast, const char *text);
 static int gtalk_digit_begin(struct ast_channel *ast, char digit);
 static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int gtalk_call(struct ast_channel *ast, char *dest, int timeout);
@@ -194,6 +195,7 @@
 	.description = "Gtalk Channel Driver",
 	.capabilities = AST_FORMAT_AUDIO_MASK,
 	.requester = gtalk_request,
+	.send_text = gtalk_sendtext,
 	.send_digit_begin = gtalk_digit_begin,
 	.send_digit_end = gtalk_digit_end,
 	.bridge = ast_rtp_bridge,
@@ -1456,6 +1458,14 @@
 	return res;
 }
 
+static int gtalk_sendtext(struct ast_channel *chan, const char *text)
+{
+	struct gtalk_pvt *p = chan->tech_pvt;
+	struct aji_client *client = p->parent->connection;
+	ast_aji_send_chat(client, p->them, text);
+	return 0;
+}
+
 static int gtalk_digit_begin(struct ast_channel *chan, char digit)
 {
 	return gtalk_digit(chan, digit, 0);
Index: res/res_jabber.c
===================================================================
--- res/res_jabber.c	(revision 116556)
+++ res/res_jabber.c	(working copy)
@@ -69,6 +69,7 @@
 static void aji_client_destroy(struct aji_client *obj);
 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);
 static int aji_start_tls(struct aji_client *client);
 static int aji_tls_handshake(struct aji_client *client);
@@ -128,23 +129,32 @@
 static char *ajisend_synopsis = "JabberSend(jabber,screenname,message)";
 
 static char *ajisend_descrip =
-"JabberSend(Jabber,ScreenName,Message)\n"
-"  Jabber - Client or transport Asterisk uses to connect to Jabber\n" 
-"  ScreenName - User Name to message.\n" 
+"JabberSend(Jabber,JID,Message)\n"
+"  Jabber  - Client or transport Asterisk uses to connect to Jabber\n" 
+"  JID     - Jabber ID of the buddy to send message to\n" 
 "  Message - Message to be sent to the buddy\n";
 
 static char *app_ajistatus = "JabberStatus";
 
-static char *ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)";
+static char *ajistatus_synopsis = "JabberStatus(Jabber,JID,Variable)";
 
 static char *ajistatus_descrip =
-"JabberStatus(Jabber,ScreenName,Variable)\n"
-"  Jabber - Client or transport Asterisk uses to connect to Jabber\n"
-"  ScreenName - User Name to retrieve status from.\n"
+"JabberStatus(Jabber,JID,Variable)\n"
+"  Jabber   - Client or transport Asterisk uses to connect to Jabber\n"
+"  JID      - Jabber ID of the buddy 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 char *app_ajirecv = "JabberReceive";
+
+static char *ajirecv_synopsis = "JabberReceive(Variable)";
+
+static char *ajirecv_descrip =
+"JabberReceive(JID,Variable)\n"
+"  JID      - Jabber ID of the buddy to receive message from\n" 
+"  Variable - Variable to store message in\n";
+
 struct aji_client_container clients;
 struct aji_capabilities *capabilities = NULL;
 
@@ -729,6 +739,46 @@
 	return IKS_OK;
 }
 
+ /*!
+ * \brief Dial plan function to receive a message.
+ * \param channel, and data, data is sender, variable.
+ * \return received text or NULL.
+ */
+static int aji_recv_exec(struct ast_channel *chan, void *data)
+{
+	char message[AST_MAX_EXTENSION];
+	int timeout = 10000;
+	char *buf, *parse, *variable = NULL;
+	AST_DECLARE_APP_ARGS(args,
+			     AST_APP_ARG(sender);
+			     AST_APP_ARG(variable);
+			     );
+
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_WARNING, "JabberReceive requires two arguments\n");
+		return -1;
+	}
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc != 2) {
+		ast_log(LOG_WARNING, "JabberReceive requires two arguments\n");
+		return -1;
+	}
+
+	ast_log(LOG_NOTICE, "Waiting for an XMPP message from %s\n", args.sender);
+	buf = ast_recvtext(chan, timeout);
+	/* 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 0;
+}
+
 /*!
  * \brief the debug loop.
  * \param data void
@@ -1435,17 +1485,63 @@
 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);
+			     );
+
+	ast_debug(3, "client %s received a message\n", client->name);
 	
 	if (!(insert = ast_calloc(1, sizeof(*insert))))
 		return;
 	time(&insert->arrived);
-	if (iks_find_cdata(pak->x, "body"))
+	if (iks_find_cdata(pak->x, "body")) {
 		insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
-	if (pak->id)
-		ast_copy_string(insert->id, pak->id, sizeof(insert->message));
-	if (pak->from)
-		insert->from = ast_strdup(pak->from->full);
+	}
+	if (pak->id) {
+		ast_copy_string(insert->id, pak->id, sizeof(insert->id));
+	}
+	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")) {
+		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 = (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);
+			ast_debug(3, "chan was %s \n", chan ? "FOUND" : "NOT FOUND");
+			if (chan) {
+				break;
+			}
+		}
+	}
+
 	AST_LIST_LOCK(&client->messages);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
 		if (flag) {
@@ -2985,6 +3081,7 @@
 			"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(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, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
 	ast_custom_function_register(&jabberstatus_function);
 
