Review Board 1.7.16


Support text messages outside of a call

Review Request #1042 - Created Dec. 1, 2010 and submitted

Russell Bryant
trunk
Reviewers
asterisk-dev
Asterisk
This branch contains a proposal for adding protocol independent support for processing text messages into and out of the dialplan, outside of a call.  The file doc/asterisk-messaging.txt contains more details on the proposal.  The introduction of the document is quoted here:

"    Asterisk has some limited support today for messaging.  The support that
exists primarily includes passing text messages in the context of a call.  The
SIP and IAX2 protocols have support for this, but that's it.

    There are a couple of other messaging protocols that are supported: Skype
and XMPP (Jabber).  The support of these is very minimal and not very integrated
into the architecture of Asterisk since these messages are not in the context of
a phone call.  They provide a combination of dialplan and manager interface
interfaces that are specific to each protocol.  There just is no current
architectural concept of dealing with text messages.

    The purpose of this proposal is to introduce text messaging into the
architecture of Asterisk.  For messaging support to exist in the true spirit of
Asterisk architecture, the design needs to achieve the following two goals:

    a) Protocol Independence
    b) Scriptable message routing

    The rest of this document goes through some details about how these goals
will be achieved in a way that is both architecturally compatible with Asterisk
as well as practical to implement."

----------

In addition to the documented proposal, I have made some good progress on implementation.  While the document includes some ideas for future enhancements, what is there so far should be usable.

 - core modifications to allow sending incoming messages through the dialplan
 - core modifications to allow outbound messages from the dialplan
 - modifications to res_jabber to allow inbound and outbound messages in the new architecture
 - changes to chan_sip to support inbound and outbound MESSAGE outside of a call
svn/testsuite/asterisk/team/russell/messaging:
  - This branch of the testsuite contains my tests for this branch, which include:
    - tests/sip/message_disabled
      - Ensure MESSAGE outside of a call is rejected when disabled.
    - tests/sip/message_unauth
      - When enabled, test sending a MESSAGE to Asterisk and send another back out from the dialplan.
    - tests/sip/message_auth
      - Same as the last test, but authenticate MESSAGE both inbound and outbound.
    - tests/sip/message_from_call
      - Set up a normal SIP call and send an out of call MESSAGE from the dialplan processing the call

I have also written some simple apps using the pjsua Python module from pjsip that can send and receive messages sent through Asterisk.

Lastly, I have done some manual testing of XMPP messages in and out of Asterisk using this code.
/trunk/channels/chan_sip.c
Revision 299249 New Change
[20] 260 lines
[+20] [+] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
261
#include "asterisk/ast_version.h"
261
#include "asterisk/ast_version.h"
262
#include "asterisk/event.h"
262
#include "asterisk/event.h"
263
#include "asterisk/cel.h"
263
#include "asterisk/cel.h"
264
#include "asterisk/data.h"
264
#include "asterisk/data.h"
265
#include "asterisk/aoc.h"
265
#include "asterisk/aoc.h"

    
   
266
#include "asterisk/message.h"
266
#include "sip/include/sip.h"
267
#include "sip/include/sip.h"
267
#include "sip/include/globals.h"
268
#include "sip/include/globals.h"
268
#include "sip/include/config_parser.h"
269
#include "sip/include/config_parser.h"
269
#include "sip/include/reqresp_parser.h"
270
#include "sip/include/reqresp_parser.h"
270
#include "sip/include/sip_utils.h"
271
#include "sip/include/sip_utils.h"
[+20] [20] 974 lines
[+20] [+] static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
1245
static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init, const char * const explicit_uri);
1246
static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init, const char * const explicit_uri);
1246
static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int oldsdp);
1247
static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int oldsdp);
1247
static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded);
1248
static int transmit_info_with_aoc(struct sip_pvt *p, struct ast_aoc_decoded *decoded);
1248
static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);
1249
static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);
1249
static int transmit_info_with_vidupdate(struct sip_pvt *p);
1250
static int transmit_info_with_vidupdate(struct sip_pvt *p);
1250
static int transmit_message_with_text(struct sip_pvt *p, const char *text);
1251
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth);
1251
static int transmit_refer(struct sip_pvt *p, const char *dest);
1252
static int transmit_refer(struct sip_pvt *p, const char *dest);
1252
static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten);
1253
static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten);
1253
static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);
1254
static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);
1254
static int transmit_cc_notify(struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state);
1255
static int transmit_cc_notify(struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state);
1255
static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader);
1256
static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader);
1256
static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
1257
static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
1257
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
1258
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
1258
static void copy_request(struct sip_request *dst, const struct sip_request *src);
1259
static void copy_request(struct sip_request *dst, const struct sip_request *src);
1259
static void receive_message(struct sip_pvt *p, struct sip_request *req);
1260
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
1260
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
1261
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
1261
static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
1262
static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
1262

    
   
1263

   
1263
/* Misc dialog routines */
1264
/* Misc dialog routines */
1264
static int __sip_autodestruct(const void *data);
1265
static int __sip_autodestruct(const void *data);
[+20] [20] 256 lines
[+20] [+] static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock);
1521
static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *recount, const char *e, int *nounlock);
1522
static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *recount, const char *e, int *nounlock);
1522
static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock);
1523
static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock);
1523
static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
1524
static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
1524
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
1525
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
1525
static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
1526
static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
1526
static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
1527
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
1527
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
1528
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
1528
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
1529
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
1529
static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
1530
static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
1530
static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
1531
static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
1531
static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
1532
static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
[+20] [20] 4 lines
[+20] [+] static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno, int *nounlock);
1536
static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1537
static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1537
static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1538
static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1538
static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1539
static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1539
static void handle_response_subscribe(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1540
static void handle_response_subscribe(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1540
static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1541
static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);

    
   
1542
static void handle_response_message(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1541
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1543
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
1542

    
   
1544

   
1543
/*------ SRTP Support -------- */
1545
/*------ SRTP Support -------- */
1544
static int setup_srtp(struct sip_srtp **srtp);
1546
static int setup_srtp(struct sip_srtp **srtp);
1545
static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struct sip_srtp **srtp, const char *a);
1547
static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struct sip_srtp **srtp, const char *a);
[+20] [20] 91 lines
[+20] [+] static struct ast_cc_agent_callbacks sip_cc_agent_callbacks = {
1637
{
1639
{
1638
	struct ast_cc_agent *agent = obj;
1640
	struct ast_cc_agent *agent = obj;
1639
	struct sip_cc_agent_pvt *agent_pvt = agent->private_data;
1641
	struct sip_cc_agent_pvt *agent_pvt = agent->private_data;
1640
	const char *uri = arg;
1642
	const char *uri = arg;
1641

    
   
1643

   
1642
	return !sip_uri_cmp(agent_pvt->notify_uri, uri) ? CMP_MATCH | CMP_STOP : 0;
1644
	return !strcmp(agent_pvt->notify_uri, uri) ? CMP_MATCH | CMP_STOP : 0;
1643
}
1645
}
1644

    
   
1646

   
1645
static struct ast_cc_agent *find_sip_cc_agent_by_notify_uri(const char * const uri)
1647
static struct ast_cc_agent *find_sip_cc_agent_by_notify_uri(const char * const uri)
1646
{
1648
{
1647
	struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_notify_uri_helper, (char *)uri, "SIP");
1649
	struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_notify_uri_helper, (char *)uri, "SIP");
[+20] [20] 4 lines
[+20] static struct ast_cc_agent *find_sip_cc_agent_by_notify_uri(const char * const uri)
1652
{
1654
{
1653
	struct ast_cc_agent *agent = obj;
1655
	struct ast_cc_agent *agent = obj;
1654
	struct sip_cc_agent_pvt *agent_pvt = agent->private_data;
1656
	struct sip_cc_agent_pvt *agent_pvt = agent->private_data;
1655
	const char *uri = arg;
1657
	const char *uri = arg;
1656

    
   
1658

   
1657
	return !sip_uri_cmp(agent_pvt->subscribe_uri, uri) ? CMP_MATCH | CMP_STOP : 0;
1659
	return !strcmp(agent_pvt->subscribe_uri, uri) ? CMP_MATCH | CMP_STOP : 0;
1658
}
1660
}
1659

    
   
1661

   
1660
static struct ast_cc_agent *find_sip_cc_agent_by_subscribe_uri(const char * const uri)
1662
static struct ast_cc_agent *find_sip_cc_agent_by_subscribe_uri(const char * const uri)
1661
{
1663
{
1662
	struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_subscribe_uri_helper, (char *)uri, "SIP");
1664
	struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_subscribe_uri_helper, (char *)uri, "SIP");
[+20] [20] 2552 lines
[+20] [+] static int sip_sendtext(struct ast_channel *ast, const char *text)
4215
		ast_debug(2, "Trying to send MESSAGE to device that does not support it.\n");
4217
		ast_debug(2, "Trying to send MESSAGE to device that does not support it.\n");
4216
		return(0);
4218
		return(0);
4217
	}
4219
	}
4218
	if (debug)
4220
	if (debug)
4219
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4221
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4220
	transmit_message_with_text(dialog, text);
4222
	transmit_message_with_text(dialog, text, 0, 0);
4221
	return 0;	
4223
	return 0;	
4222
}
4224
}
4223

    
   
4225

   
4224
/*! \brief Update peer object in realtime storage
4226
/*! \brief Update peer object in realtime storage
4225
	If the Asterisk system name is set in asterisk.conf, we will use
4227
	If the Asterisk system name is set in asterisk.conf, we will use
[+20] [20] 8384 lines
[+20] [+] static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader)
12610
	dialog_unref(p, "p is finished here at the end of transmit_register");
12612
	dialog_unref(p, "p is finished here at the end of transmit_register");
12611
	return res;
12613
	return res;
12612
}
12614
}
12613

    
   
12615

   
12614
/*! \brief Transmit text with SIP MESSAGE method */
12616
/*! \brief Transmit text with SIP MESSAGE method */
12615
static int transmit_message_with_text(struct sip_pvt *p, const char *text)
12617
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth)
12616
{
12618
{
12617
	struct sip_request req;
12619
	struct sip_request req;
12618
	
12620

   

    
   
12621
	if (init) {

    
   
12622
		initreqprep(&req, p, SIP_MESSAGE, NULL);

    
   
12623
		ast_string_field_set(p, msg_body, text);

    
   
12624
		initialize_initreq(p, &req);

    
   
12625
	} else {
12619
	reqprep(&req, p, SIP_MESSAGE, 0, 1);
12626
		reqprep(&req, p, SIP_MESSAGE, 0, 1);

    
   
12627
	}

    
   
12628
	if (auth) {

    
   
12629
		return transmit_request_with_auth(p, SIP_MESSAGE, p->ocseq, XMIT_RELIABLE, 0);

    
   
12630
	} else {
12620
	add_text(&req, text);
12631
		add_text(&req, text);
12621
	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12632
		return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12622
}
12633
	}

    
   
12634
}
12623

    
   
12635

   
12624
/*! \brief Allocate SIP refer structure */
12636
/*! \brief Allocate SIP refer structure */
12625
static int sip_refer_allocate(struct sip_pvt *p)
12637
static int sip_refer_allocate(struct sip_pvt *p)
12626
{
12638
{
12627
	p->refer = ast_calloc(1, sizeof(struct sip_refer));
12639
	p->refer = ast_calloc(1, sizeof(struct sip_refer));
[+20] [20] 227 lines
[+20] [+] static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
12855
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12867
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12856
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12868
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12857
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12869
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12858
	}
12870
	}
12859

    
   
12871

   

    
   
12872
	if (sipmethod == SIP_MESSAGE) {

    
   
12873
		add_text(&resp, p->msg_body);

    
   
12874
	}

    
   
12875

   
12860
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12876
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12861
}
12877
}
12862

    
   
12878

   
12863
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12879
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12864
static void destroy_association(struct sip_peer *peer)
12880
static void destroy_association(struct sip_peer *peer)
[+20] [20] 2507 lines
[+20] [+] static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline)
15372
			strcat(buf, "\n"); /* safe */
15388
			strcat(buf, "\n"); /* safe */
15373
	}
15389
	}
15374
	return 0;
15390
	return 0;
15375
}
15391
}
15376

    
   
15392

   

    
   
15393
static int get_msg_text2(struct ast_str **buf, struct sip_request *req, int addnewline)

    
   
15394
{

    
   
15395
	int i, res = 0;

    
   
15396

   

    
   
15397
	ast_str_reset(*buf);

    
   
15398

   

    
   
15399
	for (i = 0; res >= 0 && i < req->lines; i++) {

    
   
15400
		const char *line = REQ_OFFSET_TO_STR(req, line[i]);

    
   
15401
		int res;

    
   
15402

   

    
   
15403
		res = ast_str_append(buf, 0, "%s%s", line, addnewline ? "\n" : "");

    
   
15404
	}

    
   
15405

   

    
   
15406
	return res < 0 ? -1 : 0;

    
   
15407
}

    
   
15408

   

    
   
15409
AST_THREADSTORAGE(sip_msg_buf);
15377

    
   
15410

   
15378
/*! \brief  Receive SIP MESSAGE method messages
15411
/*! \brief  Receive SIP MESSAGE method messages
15379
\note	We only handle messages within current calls currently
15412
\note	We only handle messages within current calls currently
15380
	Reference: RFC 3428 */
15413
	Reference: RFC 3428 */
15381
static void receive_message(struct sip_pvt *p, struct sip_request *req)
15414
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
15382
{
15415
{
15383
	char buf[1400];	
15416
	struct ast_str *buf;
15384
	struct ast_frame f;
15417
	struct ast_frame f;
15385
	const char *content_type = get_header(req, "Content-Type");
15418
	const char *content_type = get_header(req, "Content-Type");

    
   
15419
	struct ast_msg *msg;

    
   
15420
	int res;

    
   
15421
	char *from, *to;
15386

    
   
15422

   
15387
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15423
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15388
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15424
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15389
		if (!p->owner)
15425
		if (!p->owner)
15390
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15426
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15391
		return;
15427
		return;
15392
	}
15428
	}
15393

    
   
15429

   
15394
	if (get_msg_text(buf, sizeof(buf), req, FALSE)) {
15430
	if (!(buf = ast_str_thread_get(&sip_msg_buf, 128))) {

    
   
15431
		transmit_response(p, "500 Internal Server Error", req);

    
   
15432
		if (!p->owner) {

    
   
15433
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15434
		}

    
   
15435
		return;

    
   
15436
	}

    
   
15437

   

    
   
15438
	if (get_msg_text2(&buf, req, FALSE)) {
15395
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15439
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15396
		transmit_response(p, "202 Accepted", req);
15440
		transmit_response(p, "202 Accepted", req);
15397
		if (!p->owner)
15441
		if (!p->owner)
15398
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15442
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15399
		return;
15443
		return;
15400
	}
15444
	}
15401

    
   
15445

   
15402
	if (p->owner) {
15446
	if (p->owner) {
15403
		if (sip_debug_test_pvt(p))
15447
		if (sip_debug_test_pvt(p))
15404
			ast_verbose("SIP Text message received: '%s'\n", buf);
15448
			ast_verbose("SIP Text message received: '%s'\n", ast_str_buffer(buf));
15405
		memset(&f, 0, sizeof(f));
15449
		memset(&f, 0, sizeof(f));
15406
		f.frametype = AST_FRAME_TEXT;
15450
		f.frametype = AST_FRAME_TEXT;
15407
		f.subclass.integer = 0;
15451
		f.subclass.integer = 0;
15408
		f.offset = 0;
15452
		f.offset = 0;
15409
		f.data.ptr = buf;
15453
		f.data.ptr = ast_str_buffer(buf);
15410
		f.datalen = strlen(buf);
15454
		f.datalen = ast_str_strlen(buf);
15411
		ast_queue_frame(p->owner, &f);
15455
		ast_queue_frame(p->owner, &f);
15412
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15456
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15413
		return;
15457
		return;
15414
	}
15458
	}
15415

    
   
15459

   

    
   
15460
	if (!sip_cfg.accept_outofcall_message) {
15416
	/* Message outside of a call, we do not support that */
15461
		/* Message outside of a call, we do not support that */
15417
	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);
15462
		ast_debug(1, "MESSAGE outside of a call administratively disabled.\n");
15418
	transmit_response(p, "405 Method Not Allowed", req);
15463
		transmit_response(p, "405 Method Not Allowed", req);
15419
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15464
		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15420
	return;
15465
		return;
15421
}
15466
	}
15422

    
   
15467

   

    
   
15468
	if (sip_cfg.auth_message_requests) {

    
   
15469
		int res;

    
   
15470

   

    
   
15471
		copy_request(&p->initreq, req);

    
   
15472
		set_pvt_allowed_methods(p, req);

    
   
15473
		res = check_user(p, req, SIP_MESSAGE, e, XMIT_UNRELIABLE, addr);

    
   
15474
		if (res == AUTH_CHALLENGE_SENT) {

    
   
15475
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15476
			return;

    
   
15477
		}

    
   
15478
		if (res < 0) { /* Something failed in authentication */

    
   
15479
			if (res == AUTH_FAKE_AUTH) {

    
   
15480
				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));

    
   
15481
				transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE);

    
   
15482
			} else {

    
   
15483
				ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From"));

    
   
15484
				transmit_response(p, "403 Forbidden", req);

    
   
15485
			}

    
   
15486
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15487
			return;

    
   
15488
		}

    
   
15489
		/* Auth was successful.  Proceed. */

    
   
15490
	} else {

    
   
15491
		struct sip_peer *peer;

    
   
15492

   

    
   
15493
		/*

    
   
15494
		 * MESSAGE outside of a call, not authenticating it.

    
   
15495
		 * Check to see if we match a peer anyway so that we can direct

    
   
15496
		 * it to the right context.

    
   
15497
		 */

    
   
15498

   

    
   
15499
		peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, 0, p->socket.type);

    
   
15500
		if (peer) {

    
   
15501
			/* Only if no auth is required. */

    
   
15502
			if (ast_strlen_zero(peer->secret) && ast_strlen_zero(peer->md5secret)) {

    
   
15503
				ast_string_field_set(p, context, peer->context);

    
   
15504
			}

    
   
15505
			peer = unref_peer(peer, "from find_peer() in receive_message");

    
   
15506
		}

    
   
15507
	}

    
   
15508

   

    
   
15509
	if (!(msg = ast_msg_alloc())) {

    
   
15510
		transmit_response(p, "500 Internal Server Error", req);

    
   
15511
		if (!p->owner) {

    
   
15512
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15513
		}

    
   
15514
		return;

    
   
15515
	}

    
   
15516

   

    
   
15517
	to = ast_strdupa(REQ_OFFSET_TO_STR(req, rlPart2));

    
   
15518
	from = ast_strdupa(get_header(req, "From"));

    
   
15519

   

    
   
15520
	res = ast_msg_set_to(msg, "%s", to);

    
   
15521
	res |= ast_msg_set_from(msg, "%s", get_in_brackets(from));

    
   
15522
	res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf));

    
   
15523
	res |= ast_msg_set_context(msg, "%s", p->context);

    
   
15524

   

    
   
15525
	if (res) {

    
   
15526
		ast_msg_destroy(msg);

    
   
15527
	} else {

    
   
15528
		ast_msg_queue(msg);

    
   
15529
	}

    
   
15530

   

    
   
15531
	transmit_response(p, "202 Accepted", req);

    
   
15532
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15533
}

    
   
15534

   
15423
/*! \brief  CLI Command to show calls within limits set by call_limit */
15535
/*! \brief  CLI Command to show calls within limits set by call_limit */
15424
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15536
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15425
{
15537
{
15426
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15538
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15427
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
15539
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
[+20] [20] 4525 lines
[+20] [+] static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
19953
				handle_response_subscribe(p, resp, rest, req, seqno);
20065
				handle_response_subscribe(p, resp, rest, req, seqno);
19954
			else if (p->registry && sipmethod == SIP_REGISTER)
20066
			else if (p->registry && sipmethod == SIP_REGISTER)
19955
				res = handle_response_register(p, resp, rest, req, seqno);
20067
				res = handle_response_register(p, resp, rest, req, seqno);
19956
			else if (sipmethod == SIP_UPDATE) {
20068
			else if (sipmethod == SIP_UPDATE) {
19957
				handle_response_update(p, resp, rest, req, seqno);
20069
				handle_response_update(p, resp, rest, req, seqno);

    
   
20070
			} else if (sipmethod == SIP_MESSAGE) {

    
   
20071
				handle_response_message(p, resp, rest, req, seqno);
19958
			} else if (sipmethod == SIP_BYE) {
20072
			} else if (sipmethod == SIP_BYE) {
19959
				if (p->options)
20073
				if (p->options)
19960
					p->options->auth_type = resp;
20074
					p->options->auth_type = resp;
19961
				if (ast_strlen_zero(p->authname)) {
20075
				if (ast_strlen_zero(p->authname)) {
19962
					ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
20076
					ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
[+20] [20] 346 lines
[+20] [+] static void *sip_park_thread(void *stuff)
20309
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20423
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20310
	
20424
	
20311

    
   
20425

   
20312
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20426
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20313
	if (!res) {
20427
	if (!res) {
20314
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n");
20428
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0, 0);
20315
	} else {
20429
	} else {
20316
		/* Then tell the transferer what happened */
20430
		/* Then tell the transferer what happened */
20317
		sprintf(buf, "Call parked on extension '%d'", ext);
20431
		sprintf(buf, "Call parked on extension '%d'", ext);
20318
		transmit_message_with_text(transferer->tech_pvt, buf);
20432
		transmit_message_with_text(transferer->tech_pvt, buf, 0, 0);
20319
	}
20433
	}
20320
#endif
20434
#endif
20321

    
   
20435

   
20322
	/* Any way back to the current call??? */
20436
	/* Any way back to the current call??? */
20323
	/* Transmit response to the REFER request */
20437
	/* Transmit response to the REFER request */
[+20] [20] 2400 lines
[+20] [+] static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
22724
	}
22838
	}
22725

    
   
22839

   
22726
	return 1;
22840
	return 1;
22727
}
22841
}
22728

    
   
22842

   

    
   
22843
/*!

    
   
22844
 * \internal

    
   
22845
 * \brief Handle auth requests to a MESSAGE request

    
   
22846
 */

    
   
22847
static void handle_response_message(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)

    
   
22848
{

    
   
22849
	char *header, *respheader;

    
   
22850
	char digest[1024];

    
   
22851

   

    
   
22852
	if (p->options) {

    
   
22853
		p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);

    
   
22854
	}

    
   
22855

   

    
   
22856
	if ((p->authtries == MAX_AUTHTRIES)) {

    
   
22857
		ast_log(LOG_NOTICE, "Failed to authenticate on MESSAGE to '%s'\n", get_header(&p->initreq, "From"));

    
   
22858
		pvt_set_needdestroy(p, "MESSAGE authentication failed");

    
   
22859
		return;

    
   
22860
	}

    
   
22861

   

    
   
22862
	p->authtries++;

    
   
22863
	auth_headers((resp == 401 ? WWW_AUTH : PROXY_AUTH), &header, &respheader);

    
   
22864
	memset(digest, 0, sizeof(digest));

    
   
22865
	if (reply_digest(p, req, header, SIP_MESSAGE, digest, sizeof(digest))) {

    
   
22866
		/* There's nothing to use for authentication */

    
   
22867
		ast_debug(1, "Nothing to use for MESSAGE authentication\n");

    
   
22868
		pvt_set_needdestroy(p, "MESSAGE authentication failed");

    
   
22869
		return;

    
   
22870
	}

    
   
22871

   

    
   
22872
	if (p->do_history) {

    
   
22873
		append_history(p, "MessageAuth", "Try: %d", p->authtries);

    
   
22874
	}

    
   
22875

   

    
   
22876
	transmit_message_with_text(p, p->msg_body, 0, 1);

    
   
22877
}

    
   
22878

   
22729
/*! \brief Handle incoming MESSAGE request */
22879
/*! \brief Handle incoming MESSAGE request */
22730
static int handle_request_message(struct sip_pvt *p, struct sip_request *req)
22880
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
22731
{
22881
{
22732
	if (!req->ignore) {
22882
	if (!req->ignore) {
22733
		if (req->debug)
22883
		if (req->debug)
22734
			ast_verbose("Receiving message!\n");
22884
			ast_verbose("Receiving message!\n");
22735
		receive_message(p, req);
22885
		receive_message(p, req, addr, e);
22736
	} else
22886
	} else
22737
		transmit_response(p, "202 Accepted", req);
22887
		transmit_response(p, "202 Accepted", req);
22738
	return 1;
22888
	return 1;
22739
}
22889
}
22740

    
   
22890

   

    
   
22891
static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from);

    
   
22892

   

    
   
22893
static const struct ast_msg_tech sip_msg_tech = {

    
   
22894
	.name = "sip",

    
   
22895
	.msg_send = sip_msg_send,

    
   
22896
};

    
   
22897

   

    
   
22898
static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from)

    
   
22899
{

    
   
22900
	struct sip_pvt *pvt;

    
   
22901
	int res;

    
   
22902
	char *peer;

    
   
22903

   

    
   
22904
	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL))) {

    
   
22905
		return -1;

    
   
22906
	}

    
   
22907

   

    
   
22908
	peer = ast_strdupa(to);

    
   
22909
	if (strchr(peer, '@')) {

    
   
22910
		strsep(&peer, "@");

    
   
22911
	} else {

    
   
22912
		strsep(&peer, ":");

    
   
22913
	}

    
   
22914
	if (ast_strlen_zero(peer)) {

    
   
22915
		ast_log(LOG_WARNING, "MESSAGE(to) is invalid for SIP - '%s'\n", to);

    
   
22916
		return -1;

    
   
22917
	}

    
   
22918

   

    
   
22919
	sip_pvt_lock(pvt);

    
   
22920

   

    
   
22921
	if (create_addr(pvt, peer, NULL, TRUE, NULL)) {

    
   
22922
		sip_pvt_unlock(pvt);

    
   
22923
		dialog_unlink_all(pvt, TRUE, TRUE);

    
   
22924
		dialog_unref(pvt, "create_addr failed sending a MESSAGE");

    
   
22925
		return -1;

    
   
22926
	}

    
   
22927
	ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);

    
   
22928
	ast_set_flag(&pvt->flags[0], SIP_OUTGOING);

    
   
22929

   

    
   
22930
	/* XXX Does pvt->expiry need to be set? */

    
   
22931

   

    
   
22932
	res = transmit_message_with_text(pvt, ast_msg_get_body(msg), 1, 0);

    
   
22933

   

    
   
22934
	sip_pvt_unlock(pvt);

    
   
22935
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);

    
   
22936
	dialog_unref(pvt, "sent a MESSAGE");

    
   
22937

   

    
   
22938
	return res;

    
   
22939
}

    
   
22940

   
22741
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)
22941
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)
22742
{
22942
{
22743
	int etag_present = !ast_strlen_zero(etag);
22943
	int etag_present = !ast_strlen_zero(etag);
22744
	int body_present = req->lines > 0;
22944
	int body_present = req->lines > 0;
22745

    
   
22945

   
[+20] [20] 1176 lines
[+20] [+] static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock)
23922
		break;
24122
		break;
23923
	case SIP_BYE:
24123
	case SIP_BYE:
23924
		res = handle_request_bye(p, req);
24124
		res = handle_request_bye(p, req);
23925
		break;
24125
		break;
23926
	case SIP_MESSAGE:
24126
	case SIP_MESSAGE:
23927
		res = handle_request_message(p, req);
24127
		res = handle_request_message(p, req, addr, e);
23928
		break;
24128
		break;
23929
	case SIP_PUBLISH:
24129
	case SIP_PUBLISH:
23930
		res = handle_request_publish(p, req, addr, seqno, e);
24130
		res = handle_request_publish(p, req, addr, seqno, e);
23931
		break;
24131
		break;
23932
	case SIP_SUBSCRIBE:
24132
	case SIP_SUBSCRIBE:
[+20] [20] 1941 lines
[+20] [+] static struct sip_peer *temp_peer(const char *name)
25874

    
   
26074

   
25875
	if (ast_string_field_init(peer, 512)) {
26075
	if (ast_string_field_init(peer, 512)) {
25876
		ao2_t_ref(peer, -1, "failed to string_field_init, drop peer");
26076
		ao2_t_ref(peer, -1, "failed to string_field_init, drop peer");
25877
		return NULL;
26077
		return NULL;
25878
	}
26078
	}
25879
	

   
25880
	if (!(peer->cc_params = ast_cc_config_params_init())) {

   
25881
		ao2_t_ref(peer, -1, "failed to allocate cc_params for peer");

   
25882
		return NULL;

   
25883
	}

   
25884

    
   
26079

   
25885
	ast_atomic_fetchadd_int(&apeerobjs, 1);
26080
	ast_atomic_fetchadd_int(&apeerobjs, 1);
25886
	set_peer_defaults(peer);
26081
	set_peer_defaults(peer);
25887

    
   
26082

   
25888
	ast_copy_string(peer->name, name, sizeof(peer->name));
26083
	ast_copy_string(peer->name, name, sizeof(peer->name));
[+20] [20] 881 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
26770
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26965
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26771
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26966
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26772
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26967
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26773
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26968
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26774
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
26969
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;

    
   
26970
	sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE;

    
   
26971
	sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE;
26775
	sip_cfg.allowsubscribe = FALSE;
26972
	sip_cfg.allowsubscribe = FALSE;
26776
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26973
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26777
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26974
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26778
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26975
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26779
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
26976
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
[+20] [20] 236 lines
[+20] static int reload_config(enum channelreloadreason reason)
27016
			sip_cfg.alwaysauthreject = ast_true(v->value);
27213
			sip_cfg.alwaysauthreject = ast_true(v->value);
27017
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27214
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27018
			if (ast_true(v->value)) {
27215
			if (ast_true(v->value)) {
27019
				sip_cfg.auth_options_requests = 1;
27216
				sip_cfg.auth_options_requests = 1;
27020
			}
27217
			}

    
   
27218
		} else if (!strcasecmp(v->name, "auth_message_requests")) {

    
   
27219
			sip_cfg.auth_message_requests = ast_true(v->value) ? 1 : 0;

    
   
27220
		} else if (!strcasecmp(v->name, "accept_outofcall_message")) {

    
   
27221
			sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0;
27021
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27222
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27022
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27223
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27023
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27224
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27024
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27225
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27025
		} else if (!strcasecmp(v->name, "language")) {
27226
		} else if (!strcasecmp(v->name, "language")) {
[+20] [20] 1903 lines
[+20] [+] static int load_module(void)
28929
	 * has const fields.
29130
	 * has const fields.
28930
	 */
29131
	 */
28931
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
29132
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
28932
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
29133
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
28933

    
   
29134

   

    
   
29135
	if (ast_msg_tech_register(&sip_msg_tech)) {

    
   
29136
		/* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */

    
   
29137
		return AST_MODULE_LOAD_FAILURE;

    
   
29138
	}

    
   
29139

   
28934
	/* Make sure we can register our sip channel type */
29140
	/* Make sure we can register our sip channel type */
28935
	if (ast_channel_register(&sip_tech)) {
29141
	if (ast_channel_register(&sip_tech)) {
28936
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
29142
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
28937
		io_context_destroy(io);
29143
		io_context_destroy(io);
28938
		ast_sched_context_destroy(sched);
29144
		ast_sched_context_destroy(sched);
[+20] [20] 98 lines
[+20] [+] static int unload_module(void)
29037
	ast_sched_dump(sched);
29243
	ast_sched_dump(sched);
29038
	
29244
	
29039
	/* First, take us out of the channel type list */
29245
	/* First, take us out of the channel type list */
29040
	ast_channel_unregister(&sip_tech);
29246
	ast_channel_unregister(&sip_tech);
29041

    
   
29247

   

    
   
29248
	ast_msg_tech_unregister(&sip_msg_tech);

    
   
29249

   
29042
	/* Unregister dial plan functions */
29250
	/* Unregister dial plan functions */
29043
	ast_custom_function_unregister(&sipchaninfo_function);
29251
	ast_custom_function_unregister(&sipchaninfo_function);
29044
	ast_custom_function_unregister(&sippeer_function);
29252
	ast_custom_function_unregister(&sippeer_function);
29045
	ast_custom_function_unregister(&sip_header_function);
29253
	ast_custom_function_unregister(&sip_header_function);
29046
	ast_custom_function_unregister(&checksipdomain_function);
29254
	ast_custom_function_unregister(&checksipdomain_function);
[+20] [20] 135 lines
/trunk/channels/sip/include/sip.h
Revision 299249 New Change
 
/trunk/configs/jabber.conf.sample
Revision 299249 New Change
 
/trunk/configs/sip.conf.sample
Revision 299249 New Change
 
/trunk/doc/asterisk-messaging.txt
New File
 
/trunk/include/asterisk/_private.h
Revision 299249 New Change
 
/trunk/include/asterisk/channel.h
Revision 299249 New Change
 
/trunk/include/asterisk/jabber.h
Revision 299249 New Change
 
/trunk/include/asterisk/message.h
New File
 
/trunk/main/asterisk.c
Revision 299249 New Change
 
/trunk/main/channel.c
Revision 299249 New Change
 
/trunk/main/message.c
New File
 
/trunk/res/res_jabber.c
Revision 299249 New Change
 
  1. /trunk/channels/chan_sip.c: Loading...
  2. /trunk/channels/sip/include/sip.h: Loading...
  3. /trunk/configs/jabber.conf.sample: Loading...
  4. /trunk/configs/sip.conf.sample: Loading...
  5. /trunk/doc/asterisk-messaging.txt: Loading...
  6. /trunk/include/asterisk/_private.h: Loading...
  7. /trunk/include/asterisk/channel.h: Loading...
  8. /trunk/include/asterisk/jabber.h: Loading...
  9. /trunk/include/asterisk/message.h: Loading...
  10. /trunk/main/asterisk.c: Loading...
  11. /trunk/main/channel.c: Loading...
  12. /trunk/main/message.c: Loading...
  13. /trunk/res/res_jabber.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.