Support routing text messages outside of a call.
Asterisk now has protocol independent support for processing text messages outside of a call. Messages are routed through the Asterisk dialplan. SIP MESSAGE and XMPP are currently supported. There are options in sip.conf and jabber.conf that enable these features. There is a new application, MessageSend(). There are two new functions, MESSAGE() and MESSAGE_DATA(). Documentation will be available on the project wiki, wiki.asterisk.org. Thanks to Terry Wilson for the assistance with development and to David Vossel for helping with some additional testing. Review: https://reviewboard.asterisk.org/r/1042/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@321546 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
8bacd68ba0
commit
c321368c48
13
CHANGES
13
CHANGES
|
@ -12,6 +12,19 @@
|
|||
--- Functionality changes from Asterisk 1.8 to Asterisk 1.10 -----------------
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Text Messaging
|
||||
--------------
|
||||
* Asterisk now has protocol independent support for processing text messages
|
||||
outside of a call. Messages are routed through the Asterisk dialplan.
|
||||
SIP MESSAGE and XMPP are currently supported. There are options in
|
||||
jabber.conf and sip.conf to allow enabling these features.
|
||||
-> jabber.conf: see the "sendtodialplan" and "context" options.
|
||||
-> sip.conf: see the "accept_outofcall_message" and "auth_message_requests"
|
||||
options.
|
||||
The MESSAGE() dialplan function and MessageSend() application have been
|
||||
added to go along with this functionality. More detailed usage information
|
||||
can be found on the Asterisk wiki (http://wiki.asterisk.org/).
|
||||
|
||||
Parking
|
||||
-------
|
||||
* parkedmusicclass can now be set for non-default parking lots.
|
||||
|
|
|
@ -263,6 +263,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/cel.h"
|
||||
#include "asterisk/data.h"
|
||||
#include "asterisk/aoc.h"
|
||||
#include "asterisk/message.h"
|
||||
#include "sip/include/sip.h"
|
||||
#include "sip/include/globals.h"
|
||||
#include "sip/include/config_parser.h"
|
||||
|
@ -1252,7 +1253,8 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
|
|||
static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded);
|
||||
static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);
|
||||
static int transmit_info_with_vidupdate(struct sip_pvt *p);
|
||||
static int transmit_message_with_text(struct sip_pvt *p, const char *text);
|
||||
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth);
|
||||
static int transmit_message_with_msg(struct sip_pvt *p, const struct ast_msg *msg);
|
||||
static int transmit_refer(struct sip_pvt *p, const char *dest);
|
||||
static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten);
|
||||
static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);
|
||||
|
@ -1261,7 +1263,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
|
|||
static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
|
||||
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
|
||||
static void copy_request(struct sip_request *dst, const struct sip_request *src);
|
||||
static void receive_message(struct sip_pvt *p, struct sip_request *req);
|
||||
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
|
||||
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
|
||||
static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
|
||||
|
||||
|
@ -1532,7 +1534,7 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
|
|||
static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
|
||||
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
|
||||
static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
|
||||
static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
|
||||
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
|
||||
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
|
||||
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
|
||||
static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
|
||||
|
@ -1547,6 +1549,7 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest
|
|||
static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
|
||||
static void handle_response_subscribe(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
|
||||
static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
|
||||
static void handle_response_message(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
|
||||
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
|
||||
|
||||
/*------ SRTP Support -------- */
|
||||
|
@ -4444,7 +4447,7 @@ static int sip_sendtext(struct ast_channel *ast, const char *text)
|
|||
}
|
||||
if (debug)
|
||||
ast_verbose("Sending text %s on %s\n", text, ast->name);
|
||||
transmit_message_with_text(dialog, text);
|
||||
transmit_message_with_text(dialog, text, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13117,16 +13120,49 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
|
|||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Transmit text with SIP MESSAGE method */
|
||||
static int transmit_message_with_text(struct sip_pvt *p, const char *text)
|
||||
/*! \brief Transmit text with SIP MESSAGE method based on an ast_msg */
|
||||
static int transmit_message_with_msg(struct sip_pvt *p, const struct ast_msg *msg)
|
||||
{
|
||||
struct sip_request req;
|
||||
|
||||
reqprep(&req, p, SIP_MESSAGE, 0, 1);
|
||||
add_text(&req, text);
|
||||
struct ast_msg_var_iterator *i;
|
||||
const char *var, *val;
|
||||
|
||||
initreqprep(&req, p, SIP_MESSAGE, NULL);
|
||||
ast_string_field_set(p, msg_body, ast_msg_get_body(msg));
|
||||
initialize_initreq(p, &req);
|
||||
|
||||
i = ast_msg_var_iterator_init(msg);
|
||||
while (ast_msg_var_iterator_next(msg, i, &var, &val)) {
|
||||
add_header(&req, var, val);
|
||||
ast_msg_var_unref_current(i);
|
||||
}
|
||||
ast_msg_var_iterator_destroy(i);
|
||||
|
||||
add_text(&req, ast_msg_get_body(msg));
|
||||
|
||||
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
|
||||
}
|
||||
|
||||
/*! \brief Transmit text with SIP MESSAGE method */
|
||||
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth)
|
||||
{
|
||||
struct sip_request req;
|
||||
|
||||
if (init) {
|
||||
initreqprep(&req, p, SIP_MESSAGE, NULL);
|
||||
ast_string_field_set(p, msg_body, text);
|
||||
initialize_initreq(p, &req);
|
||||
} else {
|
||||
reqprep(&req, p, SIP_MESSAGE, 0, 1);
|
||||
}
|
||||
if (auth) {
|
||||
return transmit_request_with_auth(p, SIP_MESSAGE, p->ocseq, XMIT_RELIABLE, 0);
|
||||
} else {
|
||||
add_text(&req, text);
|
||||
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Allocate SIP refer structure */
|
||||
static int sip_refer_allocate(struct sip_pvt *p)
|
||||
{
|
||||
|
@ -13357,6 +13393,10 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqn
|
|||
add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
|
||||
}
|
||||
|
||||
if (sipmethod == SIP_MESSAGE) {
|
||||
add_text(&resp, p->msg_body);
|
||||
}
|
||||
|
||||
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
|
||||
}
|
||||
|
||||
|
@ -15912,15 +15952,52 @@ static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewl
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int get_msg_text2(struct ast_str **buf, struct sip_request *req, int addnewline)
|
||||
{
|
||||
int i, res = 0;
|
||||
|
||||
ast_str_reset(*buf);
|
||||
|
||||
for (i = 0; res >= 0 && i < req->lines; i++) {
|
||||
const char *line = REQ_OFFSET_TO_STR(req, line[i]);
|
||||
|
||||
res = ast_str_append(buf, 0, "%s%s", line, addnewline ? "\n" : "");
|
||||
}
|
||||
|
||||
return res < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
static void set_message_vars_from_req(struct ast_msg *msg, struct sip_request *req)
|
||||
{
|
||||
size_t x;
|
||||
char name_buf[1024] = "";
|
||||
char val_buf[1024] = "";
|
||||
char *c;
|
||||
|
||||
for (x = 0; x < req->headers; x++) {
|
||||
const char *header = REQ_OFFSET_TO_STR(req, header[x]);
|
||||
if ((c = strchr(header, ':'))) {
|
||||
ast_copy_string(name_buf, header, MIN((c - header + 1), sizeof(name_buf)));
|
||||
ast_copy_string(val_buf, ast_skip_blanks(c + 1), sizeof(val_buf));
|
||||
ast_trim_blanks(name_buf);
|
||||
ast_msg_set_var(msg, name_buf, val_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AST_THREADSTORAGE(sip_msg_buf);
|
||||
|
||||
/*! \brief Receive SIP MESSAGE method messages
|
||||
\note We only handle messages within current calls currently
|
||||
Reference: RFC 3428 */
|
||||
static void receive_message(struct sip_pvt *p, struct sip_request *req)
|
||||
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
|
||||
{
|
||||
char buf[1400];
|
||||
struct ast_str *buf;
|
||||
struct ast_frame f;
|
||||
const char *content_type = get_header(req, "Content-Type");
|
||||
struct ast_msg *msg;
|
||||
int res;
|
||||
char *from, *to;
|
||||
|
||||
if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
|
||||
transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
|
||||
|
@ -15929,7 +16006,15 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req)
|
|||
return;
|
||||
}
|
||||
|
||||
if (get_msg_text(buf, sizeof(buf), req, FALSE)) {
|
||||
if (!(buf = ast_str_thread_get(&sip_msg_buf, 128))) {
|
||||
transmit_response(p, "500 Internal Server Error", req);
|
||||
if (!p->owner) {
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_msg_text2(&buf, req, FALSE)) {
|
||||
ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
|
||||
transmit_response(p, "202 Accepted", req);
|
||||
if (!p->owner)
|
||||
|
@ -15939,23 +16024,93 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req)
|
|||
|
||||
if (p->owner) {
|
||||
if (sip_debug_test_pvt(p))
|
||||
ast_verbose("SIP Text message received: '%s'\n", buf);
|
||||
ast_verbose("SIP Text message received: '%s'\n", ast_str_buffer(buf));
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_TEXT;
|
||||
f.subclass.integer = 0;
|
||||
f.offset = 0;
|
||||
f.data.ptr = buf;
|
||||
f.datalen = strlen(buf) + 1;
|
||||
f.data.ptr = ast_str_buffer(buf);
|
||||
f.datalen = ast_str_strlen(buf) + 1;
|
||||
ast_queue_frame(p->owner, &f);
|
||||
transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Message outside of a call, we do not support that */
|
||||
ast_log(LOG_WARNING, "Received message to %s from %s, dropped it...\n Content-Type:%s\n Message: %s\n", get_header(req, "To"), get_header(req, "From"), content_type, buf);
|
||||
transmit_response(p, "405 Method Not Allowed", req);
|
||||
if (!sip_cfg.accept_outofcall_message) {
|
||||
/* Message outside of a call, we do not support that */
|
||||
ast_debug(1, "MESSAGE outside of a call administratively disabled.\n");
|
||||
transmit_response(p, "405 Method Not Allowed", req);
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sip_cfg.auth_message_requests) {
|
||||
int res;
|
||||
|
||||
copy_request(&p->initreq, req);
|
||||
set_pvt_allowed_methods(p, req);
|
||||
res = check_user(p, req, SIP_MESSAGE, e, XMIT_UNRELIABLE, addr);
|
||||
if (res == AUTH_CHALLENGE_SENT) {
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
if (res < 0) { /* Something failed in authentication */
|
||||
if (res == AUTH_FAKE_AUTH) {
|
||||
ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
|
||||
transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE);
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From"));
|
||||
transmit_response(p, "403 Forbidden", req);
|
||||
}
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
/* Auth was successful. Proceed. */
|
||||
} else {
|
||||
struct sip_peer *peer;
|
||||
|
||||
/*
|
||||
* MESSAGE outside of a call, not authenticating it.
|
||||
* Check to see if we match a peer anyway so that we can direct
|
||||
* it to the right context.
|
||||
*/
|
||||
|
||||
peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, 0, p->socket.type);
|
||||
if (peer) {
|
||||
/* Only if no auth is required. */
|
||||
if (ast_strlen_zero(peer->secret) && ast_strlen_zero(peer->md5secret)) {
|
||||
ast_string_field_set(p, context, peer->context);
|
||||
}
|
||||
peer = unref_peer(peer, "from find_peer() in receive_message");
|
||||
}
|
||||
}
|
||||
|
||||
if (!(msg = ast_msg_alloc())) {
|
||||
transmit_response(p, "500 Internal Server Error", req);
|
||||
if (!p->owner) {
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
to = ast_strdupa(REQ_OFFSET_TO_STR(req, rlPart2));
|
||||
from = ast_strdupa(get_header(req, "From"));
|
||||
|
||||
res = ast_msg_set_to(msg, "%s", to);
|
||||
res |= ast_msg_set_from(msg, "%s", get_in_brackets(from));
|
||||
res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf));
|
||||
res |= ast_msg_set_context(msg, "%s", p->context);
|
||||
res |= ast_msg_set_exten(msg, "%s", p->exten);
|
||||
|
||||
if (res) {
|
||||
ast_msg_destroy(msg);
|
||||
} else {
|
||||
set_message_vars_from_req(msg, req);
|
||||
ast_msg_queue(msg);
|
||||
}
|
||||
|
||||
transmit_response(p, "202 Accepted", req);
|
||||
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*! \brief CLI Command to show calls within limits set by call_limit */
|
||||
|
@ -20549,6 +20704,8 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
|
|||
handle_response_register(p, resp, rest, req, seqno);
|
||||
else if (sipmethod == SIP_UPDATE) {
|
||||
handle_response_update(p, resp, rest, req, seqno);
|
||||
} else if (sipmethod == SIP_MESSAGE) {
|
||||
handle_response_message(p, resp, rest, req, seqno);
|
||||
} else if (sipmethod == SIP_BYE) {
|
||||
if (p->options)
|
||||
p->options->auth_type = resp;
|
||||
|
@ -20894,11 +21051,11 @@ static void *sip_park_thread(void *stuff)
|
|||
|
||||
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
|
||||
if (!res) {
|
||||
transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n");
|
||||
transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0, 0);
|
||||
} else {
|
||||
/* Then tell the transferer what happened */
|
||||
sprintf(buf, "Call parked on extension '%d'", ext);
|
||||
transmit_message_with_text(transferer->tech_pvt, buf);
|
||||
transmit_message_with_text(transferer->tech_pvt, buf, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -23378,18 +23535,129 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Handle auth requests to a MESSAGE request
|
||||
*/
|
||||
static void handle_response_message(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
|
||||
{
|
||||
char *header, *respheader;
|
||||
char digest[1024];
|
||||
|
||||
if (p->options) {
|
||||
p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);
|
||||
}
|
||||
|
||||
if ((p->authtries == MAX_AUTHTRIES)) {
|
||||
ast_log(LOG_NOTICE, "Failed to authenticate on MESSAGE to '%s'\n", get_header(&p->initreq, "From"));
|
||||
pvt_set_needdestroy(p, "MESSAGE authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
p->authtries++;
|
||||
auth_headers((resp == 401 ? WWW_AUTH : PROXY_AUTH), &header, &respheader);
|
||||
memset(digest, 0, sizeof(digest));
|
||||
if (reply_digest(p, req, header, SIP_MESSAGE, digest, sizeof(digest))) {
|
||||
/* There's nothing to use for authentication */
|
||||
ast_debug(1, "Nothing to use for MESSAGE authentication\n");
|
||||
pvt_set_needdestroy(p, "MESSAGE authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->do_history) {
|
||||
append_history(p, "MessageAuth", "Try: %d", p->authtries);
|
||||
}
|
||||
|
||||
transmit_message_with_text(p, p->msg_body, 0, 1);
|
||||
}
|
||||
|
||||
/*! \brief Handle incoming MESSAGE request */
|
||||
static int handle_request_message(struct sip_pvt *p, struct sip_request *req)
|
||||
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
|
||||
{
|
||||
if (!req->ignore) {
|
||||
if (req->debug)
|
||||
ast_verbose("Receiving message!\n");
|
||||
receive_message(p, req);
|
||||
receive_message(p, req, addr, e);
|
||||
} else
|
||||
transmit_response(p, "202 Accepted", req);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from);
|
||||
|
||||
static const struct ast_msg_tech sip_msg_tech = {
|
||||
.name = "sip",
|
||||
.msg_send = sip_msg_send,
|
||||
};
|
||||
|
||||
static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from)
|
||||
{
|
||||
struct sip_pvt *pvt;
|
||||
int res;
|
||||
char *peer;
|
||||
struct sip_peer *peer_ptr;
|
||||
|
||||
if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
peer = ast_strdupa(to);
|
||||
if (strchr(peer, '@')) {
|
||||
strsep(&peer, "@");
|
||||
} else {
|
||||
strsep(&peer, ":");
|
||||
}
|
||||
if (ast_strlen_zero(peer)) {
|
||||
ast_log(LOG_WARNING, "MESSAGE(to) is invalid for SIP - '%s'\n", to);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(from)) {
|
||||
if ((peer_ptr = find_peer(from, NULL, 0, 1, 0, 0))) {
|
||||
ast_string_field_set(pvt, fromname, S_OR(peer_ptr->cid_name, peer_ptr->name));
|
||||
ast_string_field_set(pvt, fromuser, S_OR(peer_ptr->cid_num, peer_ptr->name));
|
||||
unref_peer(peer_ptr, "unref_peer, from sip_msg_send, find_peer");
|
||||
} else if (strchr(from, '<')) { /* from is callerid-style */
|
||||
char *sender;
|
||||
char *name = NULL, *location = NULL, *user = NULL, *domain = NULL;
|
||||
|
||||
sender = ast_strdupa(from);
|
||||
ast_callerid_parse(sender, &name, &location);
|
||||
ast_string_field_set(pvt, fromname, name);
|
||||
if (strchr(location, ':')) { /* Must be a URI */
|
||||
parse_uri(location, "sip:,sips:", &user, NULL, &domain, NULL);
|
||||
ast_string_field_set(pvt, fromuser, user);
|
||||
ast_string_field_set(pvt, fromdomain, domain);
|
||||
} else { /* Treat it as an exten/user */
|
||||
ast_string_field_set(pvt, fromuser, location);
|
||||
}
|
||||
} else { /* assume we just have the name, use defaults for the rest */
|
||||
ast_string_field_set(pvt, fromname, from);
|
||||
}
|
||||
}
|
||||
|
||||
sip_pvt_lock(pvt);
|
||||
|
||||
if (create_addr(pvt, peer, NULL, TRUE, NULL)) {
|
||||
sip_pvt_unlock(pvt);
|
||||
dialog_unlink_all(pvt, TRUE, TRUE);
|
||||
dialog_unref(pvt, "create_addr failed sending a MESSAGE");
|
||||
return -1;
|
||||
}
|
||||
ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);
|
||||
ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
|
||||
|
||||
/* XXX Does pvt->expiry need to be set? */
|
||||
|
||||
res = transmit_message_with_msg(pvt, msg);
|
||||
|
||||
sip_pvt_unlock(pvt);
|
||||
sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);
|
||||
dialog_unref(pvt, "sent a MESSAGE");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum sip_publish_type determine_sip_publish_type(struct sip_request *req, const char * const event, const char * const etag, const char * const expires, int *expires_int)
|
||||
{
|
||||
int etag_present = !ast_strlen_zero(etag);
|
||||
|
@ -24589,7 +24857,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as
|
|||
res = handle_request_bye(p, req);
|
||||
break;
|
||||
case SIP_MESSAGE:
|
||||
res = handle_request_message(p, req);
|
||||
res = handle_request_message(p, req, addr, e);
|
||||
break;
|
||||
case SIP_PUBLISH:
|
||||
res = handle_request_publish(p, req, addr, seqno, e);
|
||||
|
@ -27368,6 +27636,8 @@ static int reload_config(enum channelreloadreason reason)
|
|||
sip_cfg.directrtpsetup = FALSE; /* Experimental feature, disabled by default */
|
||||
sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
|
||||
sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
|
||||
sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE;
|
||||
sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE;
|
||||
sip_cfg.allowsubscribe = FALSE;
|
||||
sip_cfg.disallowed_methods = SIP_UNKNOWN;
|
||||
sip_cfg.contact_ha = NULL; /* Reset the contact ACL */
|
||||
|
@ -27616,6 +27886,10 @@ static int reload_config(enum channelreloadreason reason)
|
|||
if (ast_true(v->value)) {
|
||||
sip_cfg.auth_options_requests = 1;
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "auth_message_requests")) {
|
||||
sip_cfg.auth_message_requests = ast_true(v->value) ? 1 : 0;
|
||||
} else if (!strcasecmp(v->name, "accept_outofcall_message")) {
|
||||
sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0;
|
||||
} else if (!strcasecmp(v->name, "mohinterpret")) {
|
||||
ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
|
||||
} else if (!strcasecmp(v->name, "mohsuggest")) {
|
||||
|
@ -29586,6 +29860,11 @@ static int load_module(void)
|
|||
memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
|
||||
memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
|
||||
|
||||
if (ast_msg_tech_register(&sip_msg_tech)) {
|
||||
/* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */
|
||||
return AST_MODULE_LOAD_FAILURE;
|
||||
}
|
||||
|
||||
/* Make sure we can register our sip channel type */
|
||||
if (ast_channel_register(&sip_tech)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
|
||||
|
@ -29694,6 +29973,8 @@ static int unload_module(void)
|
|||
/* First, take us out of the channel type list */
|
||||
ast_channel_unregister(&sip_tech);
|
||||
|
||||
ast_msg_tech_unregister(&sip_msg_tech);
|
||||
|
||||
/* Unregister dial plan functions */
|
||||
ast_custom_function_unregister(&sipchaninfo_function);
|
||||
ast_custom_function_unregister(&sippeer_function);
|
||||
|
|
|
@ -211,6 +211,8 @@
|
|||
#define DEFAULT_CALLEVENTS FALSE /*!< Extra manager SIP call events */
|
||||
#define DEFAULT_ALWAYSAUTHREJECT TRUE /*!< Don't reject authentication requests always */
|
||||
#define DEFAULT_AUTH_OPTIONS FALSE
|
||||
#define DEFAULT_AUTH_MESSAGE TRUE
|
||||
#define DEFAULT_ACCEPT_OUTOFCALL_MESSAGE TRUE
|
||||
#define DEFAULT_REGEXTENONQUALIFY FALSE
|
||||
#define DEFAULT_LEGACY_USEROPTION_PARSING FALSE
|
||||
#define DEFAULT_T1MIN 100 /*!< 100 MS for minimal roundtrip time */
|
||||
|
@ -680,6 +682,8 @@ struct sip_settings {
|
|||
int allowguest; /*!< allow unauthenticated peers to connect? */
|
||||
int alwaysauthreject; /*!< Send 401 Unauthorized for all failing requests */
|
||||
int auth_options_requests; /*!< Authenticate OPTIONS requests */
|
||||
int auth_message_requests; /*!< Authenticate MESSAGE requests */
|
||||
int accept_outofcall_message; /*!< Accept MESSAGE outside of a call */
|
||||
int compactheaders; /*!< send compact sip headers */
|
||||
int allow_external_domains; /*!< Accept calls to external SIP domains? */
|
||||
int callevents; /*!< Whether we send manager events or not */
|
||||
|
@ -966,6 +970,7 @@ struct sip_pvt {
|
|||
AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
|
||||
AST_STRING_FIELD(engine); /*!< RTP engine to use */
|
||||
AST_STRING_FIELD(dialstring); /*!< The dialstring used to call this SIP endpoint */
|
||||
AST_STRING_FIELD(msg_body); /*!< Text for a MESSAGE body */
|
||||
);
|
||||
char via[128]; /*!< Via: header */
|
||||
int maxforwards; /*!< SIP Loop prevention */
|
||||
|
|
|
@ -34,3 +34,6 @@
|
|||
; 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.
|
||||
;sendtodialplan=yes ; Send incoming messages into the dialplan. Off by default.
|
||||
;context=messages ; Dialplan context to send incoming messages to. If not set,
|
||||
; "default" will be used.
|
||||
|
|
|
@ -385,6 +385,16 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
|
|||
;auth_options_requests = yes ; Enabling this option will authenticate OPTIONS requests just like
|
||||
; INVITE requests are. By default this option is disabled.
|
||||
|
||||
;accept_outofcall_message = no ; Disable this option to reject all MESSAGE requests outside of a
|
||||
; call. By default, this option is enabled. When enabled, MESSAGE
|
||||
; requests are passed in to the dialplan.
|
||||
|
||||
;auth_message_requests = yes ; Enabling this option will authenticate MESSAGE requests.
|
||||
; By default this option is enabled. However, it can be disabled
|
||||
; should an application desire to not load the Asterisk server with
|
||||
; doing authentication and implement end to end security in the
|
||||
; message body.
|
||||
|
||||
;g726nonstandard = yes ; If the peer negotiates G726-32 audio, use AAL2 packing
|
||||
; order instead of RFC3551 packing order (this is required
|
||||
; for Sipura and Grandstream ATAs, among others). This is
|
||||
|
|
|
@ -47,6 +47,7 @@ int ast_cel_engine_init(void); /*!< Provided by cel.c */
|
|||
int ast_cel_engine_reload(void); /*!< Provided by cel.c */
|
||||
int ast_ssl_init(void); /*!< Provided by ssl.c */
|
||||
int ast_test_init(void); /*!< Provided by test.c */
|
||||
int ast_msg_init(void); /*!< Provided by message.c */
|
||||
|
||||
/*!
|
||||
* \brief Reload asterisk modules.
|
||||
|
|
|
@ -3496,4 +3496,14 @@ int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, si
|
|||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Remove a channel from the global channels container
|
||||
*
|
||||
* \param chan channel to remove
|
||||
*
|
||||
* In a case where it is desired that a channel not be available in any lookups
|
||||
* in the global channels conatiner, use this function.
|
||||
*/
|
||||
void ast_channel_unlink(struct ast_channel *chan);
|
||||
|
||||
#endif /* _ASTERISK_CHANNEL_H */
|
||||
|
|
|
@ -157,6 +157,7 @@ struct aji_client {
|
|||
char name_space[256];
|
||||
char sid[10]; /* Session ID */
|
||||
char mid[6]; /* Message ID */
|
||||
char context[AST_MAX_CONTEXT];
|
||||
iksid *jid;
|
||||
iksparser *p;
|
||||
iksfilter *f;
|
||||
|
@ -179,6 +180,7 @@ struct aji_client {
|
|||
int message_timeout;
|
||||
int authorized;
|
||||
int distribute_events;
|
||||
int send_to_dialplan;
|
||||
struct ast_flags flags;
|
||||
int component; /* 0 client, 1 component */
|
||||
struct aji_buddy_container buddies;
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2010, Digium, Inc.
|
||||
*
|
||||
* Russell Bryant <russell@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Out-of-call text message support
|
||||
*
|
||||
* \author Russell Bryant <russell@digium.com>
|
||||
*
|
||||
* The purpose of this API is to provide support for text messages that
|
||||
* are not session based. The messages are passed into the Asterisk core
|
||||
* to be routed through the dialplan and potentially sent back out through
|
||||
* a message technology that has been registered through this API.
|
||||
*/
|
||||
|
||||
#ifndef __AST_MESSAGE_H__
|
||||
#define __AST_MESSAGE_H__
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief A text message.
|
||||
*
|
||||
* This is an opaque type that represents a text message.
|
||||
*/
|
||||
struct ast_msg;
|
||||
|
||||
/*!
|
||||
* \brief A message technology
|
||||
*
|
||||
* A message technology is capable of transmitting text messages.
|
||||
*/
|
||||
struct ast_msg_tech {
|
||||
/*!
|
||||
* \brief Name of this message technology
|
||||
*
|
||||
* This is the name that comes at the beginning of a URI for messages
|
||||
* that should be sent to this message technology implementation.
|
||||
* For example, messages sent to "xmpp:rbryant@digium.com" would be
|
||||
* passed to the ast_msg_tech with a name of "xmpp".
|
||||
*/
|
||||
const char * const name;
|
||||
/*!
|
||||
* \brief Send a message.
|
||||
*
|
||||
* \param msg the message to send
|
||||
* \param to the URI of where the message is being sent
|
||||
* \param from the URI of where the message was sent from
|
||||
*
|
||||
* The fields of the ast_msg are guaranteed not to change during the
|
||||
* duration of this function call.
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval non-zero failure
|
||||
*/
|
||||
int (* const msg_send)(const struct ast_msg *msg, const char *to, const char *from);
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Register a message technology
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval non-zero failure
|
||||
*/
|
||||
int ast_msg_tech_register(const struct ast_msg_tech *tech);
|
||||
|
||||
/*!
|
||||
* \brief Unregister a message technology.
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval non-zero failure
|
||||
*/
|
||||
int ast_msg_tech_unregister(const struct ast_msg_tech *tech);
|
||||
|
||||
/*!
|
||||
* \brief Allocate a message.
|
||||
*
|
||||
* Allocate a message for the purposes of passing it into the Asterisk core
|
||||
* to be routed through the dialplan. If ast_msg_queue() is not called, this
|
||||
* message must be destroyed using ast_msg_destroy(). Otherwise, the message
|
||||
* core code will take care of it.
|
||||
*
|
||||
* \return A message object. This function will return NULL if an allocation
|
||||
* error occurs.
|
||||
*/
|
||||
struct ast_msg *ast_msg_alloc(void);
|
||||
|
||||
/*!
|
||||
* \brief Destroy an ast_msg
|
||||
*
|
||||
* This should only be called on a message if it was not
|
||||
* passed on to ast_msg_queue().
|
||||
*
|
||||
* \return NULL, always.
|
||||
*/
|
||||
struct ast_msg *ast_msg_destroy(struct ast_msg *msg);
|
||||
|
||||
/*!
|
||||
* \brief Set the 'to' URI of a message
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int __attribute__((format(printf, 2, 3)))
|
||||
ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...);
|
||||
|
||||
/*!
|
||||
* \brief Set the 'from' URI of a message
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int __attribute__((format(printf, 2, 3)))
|
||||
ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...);
|
||||
|
||||
/*!
|
||||
* \brief Set the 'body' text of a message (in UTF-8)
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int __attribute__((format(printf, 2, 3)))
|
||||
ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...);
|
||||
|
||||
/*!
|
||||
* \brief Set the dialplan context for this message
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int __attribute__((format(printf, 2, 3)))
|
||||
ast_msg_set_context(struct ast_msg *msg, const char *fmt, ...);
|
||||
|
||||
/*!
|
||||
* \brief Set the dialplan extension for this message
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int __attribute__((format(printf, 2, 3)))
|
||||
ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...);
|
||||
|
||||
/*!
|
||||
* \brief Set a variable on the message
|
||||
* \note Setting a variable that already exists overwrites the existing variable value
|
||||
*
|
||||
* \param name Name of variable to set
|
||||
* \param value Value of variable to set
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value);
|
||||
|
||||
/*!
|
||||
* \brief Get the specified variable on the message
|
||||
* \note The return value is valid only as long as the ast_message is valid. Hold a reference
|
||||
* to the message if you plan on storing the return value.
|
||||
*
|
||||
* \return The value associated with variable "name". NULL if variable not found.
|
||||
*/
|
||||
const char *ast_msg_get_var(struct ast_msg *msg, const char *name);
|
||||
|
||||
/*!
|
||||
* \brief Get the body of a message.
|
||||
* \note The return value is valid only as long as the ast_message is valid. Hold a reference
|
||||
* to the message if you plan on storing the return value.
|
||||
*
|
||||
* \return The body of the messsage, encoded in UTF-8.
|
||||
*/
|
||||
const char *ast_msg_get_body(const struct ast_msg *msg);
|
||||
|
||||
/*!
|
||||
* \brief Queue a message for routing through the dialplan.
|
||||
*
|
||||
* Regardless of the return value of this function, this funciton will take
|
||||
* care of ensuring that the message object is properly destroyed when needed.
|
||||
*
|
||||
* \retval 0 message successfully queued
|
||||
* \retval non-zero failure, message not sent to dialplan
|
||||
*/
|
||||
int ast_msg_queue(struct ast_msg *msg);
|
||||
|
||||
/*!
|
||||
* \brief Opaque iterator for msg variables
|
||||
*/
|
||||
struct ast_msg_var_iterator;
|
||||
|
||||
/*!
|
||||
* \brief Create a new message variable iterator
|
||||
* \param msg A message whose variables are to be iterated over
|
||||
*
|
||||
* \return An opaque pointer to the new iterator
|
||||
*/
|
||||
struct ast_msg_var_iterator *ast_msg_var_iterator_init(const struct ast_msg *msg);
|
||||
|
||||
/*!
|
||||
* \brief Get the next variable name and value that is set for sending outbound
|
||||
* \param msg The message with the variables
|
||||
* \param i An iterator created with ast_msg_var_iterator_init
|
||||
* \param name A pointer to the name result pointer
|
||||
* \param value A pointer to the value result pointer
|
||||
*
|
||||
* \retval 0 No more entries
|
||||
* \retval 1 Valid entry
|
||||
*/
|
||||
int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *i, const char **name, const char **value);
|
||||
|
||||
/*!
|
||||
* \brief Destroy a message variable iterator
|
||||
* \param i Iterator to be destroyed
|
||||
*/
|
||||
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *i);
|
||||
|
||||
/*!
|
||||
* \brief Unref a message var from inside an iterator loop
|
||||
*/
|
||||
void ast_msg_var_unref_current(struct ast_msg_var_iterator *i);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __AST_MESSAGE_H__ */
|
|
@ -3750,6 +3750,11 @@ int main(int argc, char *argv[])
|
|||
ast_xmldoc_load_documentation();
|
||||
#endif
|
||||
|
||||
if (ast_msg_init()) {
|
||||
printf("%s", term_quit());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize the data retrieval API */
|
||||
if (ast_data_init()) {
|
||||
printf ("%s", term_quit());
|
||||
|
|
|
@ -9593,3 +9593,8 @@ struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ast_channel_unlink(struct ast_channel *chan)
|
||||
{
|
||||
ao2_unlink(channels, chan);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/manager.h"
|
||||
#include "asterisk/event.h"
|
||||
#include "asterisk/devicestate.h"
|
||||
#include "asterisk/message.h"
|
||||
|
||||
/*** DOCUMENTATION
|
||||
<application name="JabberSend" language="en_US">
|
||||
|
@ -373,6 +374,13 @@ static int aji_register_transport(void *data, ikspak *pak);
|
|||
static int aji_register_transport2(void *data, ikspak *pak);
|
||||
*/
|
||||
|
||||
static int msg_send_cb(const struct ast_msg *msg, const char *to, const char *from);
|
||||
|
||||
static const struct ast_msg_tech msg_tech = {
|
||||
.name = "xmpp",
|
||||
.msg_send = msg_send_cb,
|
||||
};
|
||||
|
||||
static struct ast_cli_entry aji_cli[] = {
|
||||
AST_CLI_DEFINE(aji_do_set_debug, "Enable/Disable Jabber debug"),
|
||||
AST_CLI_DEFINE(aji_do_reload, "Reload Jabber configuration"),
|
||||
|
@ -1136,6 +1144,44 @@ static int aji_send_exec(struct ast_channel *chan, const char *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msg_send_cb(const struct ast_msg *msg, const char *to, const char *from)
|
||||
{
|
||||
struct aji_client *client;
|
||||
char *sender;
|
||||
char *dest;
|
||||
int res;
|
||||
|
||||
sender = ast_strdupa(from);
|
||||
strsep(&sender, ":");
|
||||
dest = ast_strdupa(to);
|
||||
strsep(&dest, ":");
|
||||
|
||||
if (ast_strlen_zero(sender)) {
|
||||
ast_log(LOG_ERROR, "MESSAGE(from) of '%s' invalid for xmpp\n", from);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(client = ast_aji_get_client(sender))) {
|
||||
ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ast_debug(1, "Sending message to '%s' from '%s'\n", dest, client->name);
|
||||
|
||||
res = ast_aji_send_chat(client, dest, ast_msg_get_body(msg));
|
||||
if (res != IKS_OK) {
|
||||
ast_log(LOG_WARNING, "Failed to send xmpp message (%d).\n", res);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Reference leak here. See note with ast_aji_get_client() about the problems
|
||||
* with that function.
|
||||
*/
|
||||
|
||||
return res == IKS_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Application to send a message to a groupchat.
|
||||
* \param chan ast_channel
|
||||
|
@ -2218,6 +2264,7 @@ static void aji_handle_message(struct aji_client *client, ikspak *pak)
|
|||
{
|
||||
struct aji_message *insert;
|
||||
int deleted = 0;
|
||||
struct ast_msg *msg;
|
||||
|
||||
ast_debug(3, "client %s received a message\n", client->name);
|
||||
|
||||
|
@ -2248,6 +2295,23 @@ static void aji_handle_message(struct aji_client *client, ikspak *pak)
|
|||
ast_debug(3, "message comes from %s\n", insert->from);
|
||||
}
|
||||
|
||||
if ((msg = ast_msg_alloc())) {
|
||||
int res;
|
||||
|
||||
res = ast_msg_set_to(msg, "xmpp:%s", client->user);
|
||||
res |= ast_msg_set_from(msg, "xmpp:%s", insert->from);
|
||||
res |= ast_msg_set_body(msg, "%s", insert->message);
|
||||
res |= ast_msg_set_context(msg, "%s", client->context);
|
||||
|
||||
if (res) {
|
||||
ast_msg_destroy(msg);
|
||||
} else {
|
||||
ast_msg_queue(msg);
|
||||
}
|
||||
|
||||
msg = NULL;
|
||||
}
|
||||
|
||||
/* remove old messages received from this JID
|
||||
* and insert received message */
|
||||
deleted = delete_old_messages(client, pak->from->partial);
|
||||
|
@ -4248,6 +4312,7 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
|
|||
ASTOBJ_CONTAINER_MARKALL(&client->buddies);
|
||||
ast_copy_string(client->name, label, sizeof(client->name));
|
||||
ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
|
||||
ast_copy_string(client->context, "default", sizeof(client->context));
|
||||
|
||||
/* Set default values for the client object */
|
||||
client->debug = debug;
|
||||
|
@ -4265,6 +4330,7 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
|
|||
ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
|
||||
client->priority = 0;
|
||||
client->status = IKS_SHOW_AVAILABLE;
|
||||
client->send_to_dialplan = 0;
|
||||
|
||||
if (flag) {
|
||||
client->authorized = 0;
|
||||
|
@ -4356,6 +4422,10 @@ static int aji_create_client(char *label, struct ast_variable *var, int debug)
|
|||
} else {
|
||||
ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value);
|
||||
}
|
||||
} else if (!strcasecmp(var->name, "context")) {
|
||||
ast_copy_string(client->context, var->value, sizeof(client->context));
|
||||
} else if (!strcasecmp(var->name, "sendtodialplan")) {
|
||||
client->send_to_dialplan = ast_true(var->value) ? 1 : 0;
|
||||
}
|
||||
/* no transport support in this version */
|
||||
/* else if (!strcasecmp(var->name, "transport"))
|
||||
|
@ -4553,6 +4623,13 @@ static int aji_load_config(int reload)
|
|||
* (without the resource string)
|
||||
* \param name label or JID
|
||||
* \return aji_client.
|
||||
*
|
||||
* XXX \bug This function leads to reference leaks all over the place.
|
||||
* ASTOBJ_CONTAINER_FIND() returns a reference, but if the
|
||||
* client is found via the traversal, no reference is returned.
|
||||
* None of the calling code releases references. This code needs
|
||||
* to be changed to always return a reference, and all of the users
|
||||
* need to be fixed to release them.
|
||||
*/
|
||||
struct aji_client *ast_aji_get_client(const char *name)
|
||||
{
|
||||
|
@ -4668,7 +4745,7 @@ static int aji_reload(int reload)
|
|||
*/
|
||||
static int unload_module(void)
|
||||
{
|
||||
|
||||
ast_msg_tech_unregister(&msg_tech);
|
||||
ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli));
|
||||
ast_unregister_application(app_ajisend);
|
||||
ast_unregister_application(app_ajisendgroup);
|
||||
|
@ -4721,6 +4798,7 @@ static int load_module(void)
|
|||
ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli));
|
||||
ast_custom_function_register(&jabberstatus_function);
|
||||
ast_custom_function_register(&jabberreceive_function);
|
||||
ast_msg_tech_register(&msg_tech);
|
||||
|
||||
ast_mutex_init(&messagelock);
|
||||
ast_cond_init(&message_received_condition, NULL);
|
||||
|
|
Reference in New Issue