Add JABBER_RECEIVE as a dialplan function, implement SendText in Jingle channels
JABBER_RECEIVE (along with JabberSend) makes Asterisk interact with users over XMPP to process calls. SendText can be used instead of JabberSend in the context of XMPP based voice channels (chan_gtalk and chan_jingle). (closes issue #12569) Reported by: eech55 Tested by: phsultan, asannucci, lmadsen, jtodd, maxgo Review: https://reviewboard.asterisk.org/r/88/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@220457 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
d170b913b9
commit
5bec5836a0
9
CHANGES
9
CHANGES
|
@ -117,6 +117,8 @@ Dialplan Functions
|
||||||
mode=multirow. If rowlimit is set, then additional rows may be retrieved
|
mode=multirow. If rowlimit is set, then additional rows may be retrieved
|
||||||
from the same query by using the name of the function which retrieved the
|
from the same query by using the name of the function which retrieved the
|
||||||
first row as an argument to ODBC_FETCH().
|
first row as an argument to ODBC_FETCH().
|
||||||
|
* Added JABBER_RECEIVE, which permits receiving XMPP messages from the
|
||||||
|
dialplan. This function returns the content of the received message.
|
||||||
|
|
||||||
Dialplan Variables
|
Dialplan Variables
|
||||||
------------------
|
------------------
|
||||||
|
@ -265,6 +267,11 @@ Security Events Framework
|
||||||
coming soon. For more information on the security events framework, see the
|
coming soon. For more information on the security events framework, see the
|
||||||
"Security Events" chapter of the included documentation - doc/tex/asterisk.pdf.
|
"Security Events" chapter of the included documentation - doc/tex/asterisk.pdf.
|
||||||
|
|
||||||
|
Miscellaneous
|
||||||
|
-------------
|
||||||
|
* SendText is now implemented in chan_gtalk and chan_jingle. It will simply send
|
||||||
|
XMPP text messages to the remote JID.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 -------------
|
--- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 -------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@ -414,7 +421,7 @@ Miscellaneous
|
||||||
can connect calls in passthrough mode, as well as record and play back files.
|
can connect calls in passthrough mode, as well as record and play back files.
|
||||||
* Successful and unsuccessful call pickup can now be alerted through sounds, by
|
* Successful and unsuccessful call pickup can now be alerted through sounds, by
|
||||||
using pickupsound and pickupfailsound in features.conf.
|
using pickupsound and pickupfailsound in features.conf.
|
||||||
* ASTVARRUNDIR is now set to $(localstatedir)/run/asterisk by default.
|
* ASTVARRUNDIR is now set to $(localstatedir)/run/asterisk by default.
|
||||||
This means the asterisk pid file will now be in /var/run/asterisk/asterisk.pid on LINUX
|
This means the asterisk pid file will now be in /var/run/asterisk/asterisk.pid on LINUX
|
||||||
instead of the /var/run/asterisk.pid where it used to be. This will make
|
instead of the /var/run/asterisk.pid where it used to be. This will make
|
||||||
installs as non-root easier to manage.
|
installs as non-root easier to manage.
|
||||||
|
|
|
@ -168,6 +168,7 @@ AST_MUTEX_DEFINE_STATIC(gtalklock); /*!< Protect the interface list (of gtalk_pv
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static struct ast_channel *gtalk_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
|
static struct ast_channel *gtalk_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
|
||||||
static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);
|
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_begin(struct ast_channel *ast, char digit);
|
||||||
static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
|
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);
|
static int gtalk_call(struct ast_channel *ast, char *dest, int timeout);
|
||||||
|
@ -191,6 +192,7 @@ static const struct ast_channel_tech gtalk_tech = {
|
||||||
.description = "Gtalk Channel Driver",
|
.description = "Gtalk Channel Driver",
|
||||||
.capabilities = AST_FORMAT_AUDIO_MASK,
|
.capabilities = AST_FORMAT_AUDIO_MASK,
|
||||||
.requester = gtalk_request,
|
.requester = gtalk_request,
|
||||||
|
.send_text = gtalk_sendtext,
|
||||||
.send_digit_begin = gtalk_digit_begin,
|
.send_digit_begin = gtalk_digit_begin,
|
||||||
.send_digit_end = gtalk_digit_end,
|
.send_digit_end = gtalk_digit_end,
|
||||||
.bridge = ast_rtp_instance_bridge,
|
.bridge = ast_rtp_instance_bridge,
|
||||||
|
@ -1499,6 +1501,25 @@ static int gtalk_indicate(struct ast_channel *ast, int condition, const void *da
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gtalk_sendtext(struct ast_channel *chan, const char *text)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!p->parent->connection) {
|
||||||
|
ast_log(LOG_ERROR, "XMPP client not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client = p->parent->connection;
|
||||||
|
res = ast_aji_send_chat(client, p->them, text);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int gtalk_digit_begin(struct ast_channel *chan, char digit)
|
static int gtalk_digit_begin(struct ast_channel *chan, char digit)
|
||||||
{
|
{
|
||||||
return gtalk_digit(chan, digit, 0);
|
return gtalk_digit(chan, digit, 0);
|
||||||
|
|
|
@ -169,6 +169,7 @@ AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static struct ast_channel *jingle_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
|
static struct ast_channel *jingle_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
|
||||||
|
static int jingle_sendtext(struct ast_channel *ast, const char *text);
|
||||||
static int jingle_digit_begin(struct ast_channel *ast, char digit);
|
static int jingle_digit_begin(struct ast_channel *ast, char digit);
|
||||||
static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
|
static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
|
||||||
static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
|
static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
|
||||||
|
@ -190,6 +191,7 @@ static const struct ast_channel_tech jingle_tech = {
|
||||||
.description = "Jingle Channel Driver",
|
.description = "Jingle Channel Driver",
|
||||||
.capabilities = AST_FORMAT_AUDIO_MASK,
|
.capabilities = AST_FORMAT_AUDIO_MASK,
|
||||||
.requester = jingle_request,
|
.requester = jingle_request,
|
||||||
|
.send_text = jingle_sendtext,
|
||||||
.send_digit_begin = jingle_digit_begin,
|
.send_digit_begin = jingle_digit_begin,
|
||||||
.send_digit_end = jingle_digit_end,
|
.send_digit_end = jingle_digit_end,
|
||||||
.bridge = ast_rtp_instance_bridge,
|
.bridge = ast_rtp_instance_bridge,
|
||||||
|
@ -1273,6 +1275,26 @@ static int jingle_indicate(struct ast_channel *ast, int condition, const void *d
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int jingle_sendtext(struct ast_channel *chan, const char *text)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
struct aji_client *client = NULL;
|
||||||
|
struct jingle_pvt *p = chan->tech_pvt;
|
||||||
|
|
||||||
|
|
||||||
|
if (!p->parent) {
|
||||||
|
ast_log(LOG_ERROR, "Parent channel not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!p->parent->connection) {
|
||||||
|
ast_log(LOG_ERROR, "XMPP client not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
client = p->parent->connection;
|
||||||
|
res = ast_aji_send_chat(client, p->them, text);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
|
static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
|
||||||
{
|
{
|
||||||
struct jingle_pvt *p = ast->tech_pvt;
|
struct jingle_pvt *p = ast->tech_pvt;
|
||||||
|
|
|
@ -20,4 +20,7 @@
|
||||||
;; xaway, or dnd
|
;; xaway, or dnd
|
||||||
;statusmessage="I am available" ;;Have custom status message for
|
;statusmessage="I am available" ;;Have custom status message for
|
||||||
;;Asterisk.
|
;;Asterisk.
|
||||||
;timeout=100 ;;Timeout on the message stack.
|
;timeout=5 ;;Timeout (in seconds) on the message stack, defaults to 5.
|
||||||
|
;;Messages stored longer than this value will be deleted by Asterisk.
|
||||||
|
;;This option applies to incoming messages only, which are intended to
|
||||||
|
;;be processed by the JABBER_RECEIVE dialplan function.
|
||||||
|
|
118
doc/jabber.txt
118
doc/jabber.txt
|
@ -1,15 +1,107 @@
|
||||||
(res_jabber is very experimental!)
|
XMPP (Jabber) is an xml based protocol primarily for presence and messaging.
|
||||||
|
|
||||||
Jabber(xmpp) is an xml based protocol primarily for presence and messaging.
|
|
||||||
It is an open standard and there are several open server implementations,
|
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. Jabber differs from other IM applications as it
|
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
|
||||||
jabber. The Asterisk Jabber Interface is provided by res_jabber.so. res_jabber
|
XMPP. The Asterisk XMPP Interface is provided by res_jabber.so.
|
||||||
allows for Asterisk to connect to any jabber server via the standard client
|
|
||||||
protocol or also as a simple client. Several simple functions are exposed to
|
|
||||||
the dial plan, jabberstatus, jabbersend, and soon jabberrecv. res_jabber is also used
|
|
||||||
to provide the connection interface for chan_jingle.
|
|
||||||
|
|
||||||
The maintainer of res_jabber is Matthew O'Gorman <mogorman@digium.com> or
|
res_jabber allows for Asterisk to connect to any XMPP (Jabber) server and
|
||||||
mog_work on irc or (preferred) mogorman@astjab.org over jabber.
|
is also used to provide the connection interface for chan_jingle and
|
||||||
|
chan_gtalk.
|
||||||
|
|
||||||
|
Functions (JABBER_STATUS, JABBER_RECEIVE) and applications (JabberSend)
|
||||||
|
are exposed to the dialplan.
|
||||||
|
|
||||||
|
You'll find examples of how to use these functions/applications
|
||||||
|
hereafter. We assume that 'asterisk-xmpp' is properly configured in
|
||||||
|
jabber.conf.
|
||||||
|
|
||||||
|
**** JabberSend ****
|
||||||
|
|
||||||
|
JabberSend sends an XMPP message to a buddy. Example :
|
||||||
|
|
||||||
|
context default {
|
||||||
|
_XXXX => {
|
||||||
|
JabberSend(asterisk-xmpp,buddy@gmail.com,${CALLERID(name)} is calling ${EXTEN});
|
||||||
|
Dial(SIP/${EXTEN}, 30);
|
||||||
|
Hangup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
**** 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 => {
|
||||||
|
Set(STATUS=${JABBER_STATUS(asterisk-xmpp,buddy@gmail.com)});
|
||||||
|
if (${STATUS}=1) {
|
||||||
|
NoOp(User is online and active, ring his Gtalk client.);
|
||||||
|
Dial(Gtalk/asterisk-xmpp/buddy@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),
|
||||||
|
JABBER_RECEIVE helps Asterisk interact with users while calls flow
|
||||||
|
through the dialplan.
|
||||||
|
|
||||||
|
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
|
||||||
|
accessed from SIP, DAHDI or whatever channel type) are controlled by
|
||||||
|
user bob@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 {
|
||||||
|
1234 => {
|
||||||
|
Answer();
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,Call from $CALLERID(num) - choose an option to process the call);
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,1 : forward to cellphone);
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,2 : forward to work phone);
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,Default action : forward to your voicemail);
|
||||||
|
Set(OPTION=${JABBER_RECEIVE(asterisk-xmpp,bob@jabber.org,20)});
|
||||||
|
switch (${OPTION}) {
|
||||||
|
case 1:
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,(Calling cellphone...);
|
||||||
|
Dial(SIP/987654321);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
JabberSend(asterisk-xmpp,bob@jabber.org,(Calling workphone...);
|
||||||
|
Dial(SIP/${EXTEN});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Voicemail(${EXTEN}|u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
s => {
|
||||||
|
NoOp(Caller id : ${CALLERID(all)});
|
||||||
|
Answer();
|
||||||
|
SendText(Please enter the number you wish to call);
|
||||||
|
Set(NEWEXTEN=${JABBER_RECEIVE(asterisk-xmpp,${CALLERID(name)})});
|
||||||
|
SendText(Calling ${NEWEXTEN} ...);
|
||||||
|
Dial(SIP/${NEWEXTEN);
|
||||||
|
Hangup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The maintainer of res_jabber is Philippe Sultan <philippe.sultan@gmail.com>.
|
||||||
|
|
|
@ -117,7 +117,7 @@ struct aji_message {
|
||||||
char *from;
|
char *from;
|
||||||
char *message;
|
char *message;
|
||||||
char id[25];
|
char id[25];
|
||||||
time_t arrived;
|
struct timeval arrived;
|
||||||
AST_LIST_ENTRY(aji_message) list;
|
AST_LIST_ENTRY(aji_message) list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
679
res/res_jabber.c
679
res/res_jabber.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue