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 298284 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] 2669 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] 8381 lines
[+20] [+] static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader)
12607
	dialog_unref(p, "p is finished here at the end of transmit_register");
12609
	dialog_unref(p, "p is finished here at the end of transmit_register");
12608
	return res;
12610
	return res;
12609
}
12611
}
12610

    
   
12612

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

   

    
   
12618
	if (init) {

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

    
   
12620
		ast_string_field_set(p, msg_body, text);

    
   
12621
		initialize_initreq(p, &req);

    
   
12622
	} else {
12616
	reqprep(&req, p, SIP_MESSAGE, 0, 1);
12623
		reqprep(&req, p, SIP_MESSAGE, 0, 1);

    
   
12624
	}

    
   
12625
	if (auth) {

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

    
   
12627
	} else {
12617
	add_text(&req, text);
12628
		add_text(&req, text);
12618
	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12629
		return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12619
}
12630
	}

    
   
12631
}
12620

    
   
12632

   
12621
/*! \brief Allocate SIP refer structure */
12633
/*! \brief Allocate SIP refer structure */
12622
static int sip_refer_allocate(struct sip_pvt *p)
12634
static int sip_refer_allocate(struct sip_pvt *p)
12623
{
12635
{
12624
	p->refer = ast_calloc(1, sizeof(struct sip_refer));
12636
	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)
12852
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12864
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12853
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12865
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12854
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12866
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12855
	}
12867
	}
12856

    
   
12868

   

    
   
12869
	if (sipmethod == SIP_MESSAGE) {

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

    
   
12871
	}

    
   
12872

   
12857
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12873
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12858
}
12874
}
12859

    
   
12875

   
12860
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12876
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12861
static void destroy_association(struct sip_peer *peer)
12877
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)
15369
			strcat(buf, "\n"); /* safe */
15385
			strcat(buf, "\n"); /* safe */
15370
	}
15386
	}
15371
	return 0;
15387
	return 0;
15372
}
15388
}
15373

    
   
15389

   

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

    
   
15391
{

    
   
15392
	int i, res = 0;

    
   
15393

   

    
   
15394
	ast_str_reset(*buf);

    
   
15395

   

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

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

    
   
15398
		int res;

    
   
15399

   

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

    
   
15401
	}

    
   
15402

   

    
   
15403
	return res < 0 ? -1 : 0;

    
   
15404
}

    
   
15405

   

    
   
15406
AST_THREADSTORAGE(sip_msg_buf);
15374

    
   
15407

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

    
   
15416
	struct ast_msg *msg;

    
   
15417
	int res;

    
   
15418
	char *from, *to;
15383

    
   
15419

   
15384
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15420
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15385
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15421
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15386
		if (!p->owner)
15422
		if (!p->owner)
15387
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15423
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15388
		return;
15424
		return;
15389
	}
15425
	}
15390

    
   
15426

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

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

    
   
15429
		if (!p->owner) {

    
   
15430
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15431
		}

    
   
15432
		return;

    
   
15433
	}

    
   
15434

   

    
   
15435
	if (get_msg_text2(&buf, req, FALSE)) {
15392
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15436
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15393
		transmit_response(p, "202 Accepted", req);
15437
		transmit_response(p, "202 Accepted", req);
15394
		if (!p->owner)
15438
		if (!p->owner)
15395
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15439
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15396
		return;
15440
		return;
15397
	}
15441
	}
15398

    
   
15442

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

    
   
15456

   

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

    
   
15464

   

    
   
15465
	if (sip_cfg.auth_message_requests) {

    
   
15466
		int res;

    
   
15467

   

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

    
   
15469
		set_pvt_allowed_methods(p, req);

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

    
   
15471
		if (res == AUTH_CHALLENGE_SENT) {

    
   
15472
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15473
			return;

    
   
15474
		}

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

    
   
15476
			if (res == AUTH_FAKE_AUTH) {

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

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

    
   
15479
			} else {

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

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

    
   
15482
			}

    
   
15483
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15484
			return;

    
   
15485
		}

    
   
15486
		/* Auth was successful.  Proceed. */

    
   
15487
	} else {

    
   
15488
		struct sip_peer *peer;

    
   
15489

   

    
   
15490
		/*

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

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

    
   
15493
		 * it to the right context.

    
   
15494
		 */

    
   
15495

   

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

    
   
15497
		if (peer) {

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

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

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

    
   
15501
			}

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

    
   
15503
		}

    
   
15504
	}

    
   
15505

   

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

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

    
   
15508
		if (!p->owner) {

    
   
15509
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15510
		}

    
   
15511
		return;

    
   
15512
	}

    
   
15513

   

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

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

    
   
15516

   

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

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

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

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

    
   
15521

   

    
   
15522
	if (res) {

    
   
15523
		ao2_ref(msg, -1);

    
   
15524
	} else {

    
   
15525
		ast_msg_queue(msg);

    
   
15526
	}

    
   
15527

   

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

    
   
15529
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15530
}

    
   
15531

   
15420
/*! \brief  CLI Command to show calls within limits set by call_limit */
15532
/*! \brief  CLI Command to show calls within limits set by call_limit */
15421
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15533
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15422
{
15534
{
15423
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15535
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15424
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
15536
#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)
19950
				handle_response_subscribe(p, resp, rest, req, seqno);
20062
				handle_response_subscribe(p, resp, rest, req, seqno);
19951
			else if (p->registry && sipmethod == SIP_REGISTER)
20063
			else if (p->registry && sipmethod == SIP_REGISTER)
19952
				res = handle_response_register(p, resp, rest, req, seqno);
20064
				res = handle_response_register(p, resp, rest, req, seqno);
19953
			else if (sipmethod == SIP_UPDATE) {
20065
			else if (sipmethod == SIP_UPDATE) {
19954
				handle_response_update(p, resp, rest, req, seqno);
20066
				handle_response_update(p, resp, rest, req, seqno);

    
   
20067
			} else if (sipmethod == SIP_MESSAGE) {

    
   
20068
				handle_response_message(p, resp, rest, req, seqno);
19955
			} else if (sipmethod == SIP_BYE) {
20069
			} else if (sipmethod == SIP_BYE) {
19956
				if (p->options)
20070
				if (p->options)
19957
					p->options->auth_type = resp;
20071
					p->options->auth_type = resp;
19958
				if (ast_strlen_zero(p->authname)) {
20072
				if (ast_strlen_zero(p->authname)) {
19959
					ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
20073
					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)
20306
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20420
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20307
	
20421
	
20308

    
   
20422

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

    
   
20432

   
20319
	/* Any way back to the current call??? */
20433
	/* Any way back to the current call??? */
20320
	/* Transmit response to the REFER request */
20434
	/* Transmit response to the REFER request */
[+20] [20] 2400 lines
[+20] [+] static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
22721
	}
22835
	}
22722

    
   
22836

   
22723
	return 1;
22837
	return 1;
22724
}
22838
}
22725

    
   
22839

   

    
   
22840
/*!

    
   
22841
 * \internal

    
   
22842
 * \brief Handle auth requests to a MESSAGE request

    
   
22843
 */

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

    
   
22845
{

    
   
22846
	char *header, *respheader;

    
   
22847
	char digest[1024];

    
   
22848

   

    
   
22849
	if (p->options) {

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

    
   
22851
	}

    
   
22852

   

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

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

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

    
   
22856
	}

    
   
22857

   

    
   
22858
	p->authtries++;

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

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

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

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

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

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

    
   
22865
		return;

    
   
22866
	}

    
   
22867

   

    
   
22868
	if (p->do_history) {

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

    
   
22870
	}

    
   
22871

   

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

    
   
22873
}

    
   
22874

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

    
   
22886

   

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

    
   
22888

   

    
   
22889
static const struct ast_msg_tech sip_msg_tech = {

    
   
22890
	.name = "sip",

    
   
22891
	.msg_send = sip_msg_send,

    
   
22892
};

    
   
22893

   

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

    
   
22895
{

    
   
22896
	struct sip_pvt *pvt;

    
   
22897
	int res;

    
   
22898
	char *peer;

    
   
22899

   

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

    
   
22901
		return -1;

    
   
22902
	}

    
   
22903

   

    
   
22904
	peer = ast_strdupa(to);

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

    
   
22906
		strsep(&peer, "@");

    
   
22907
	} else {

    
   
22908
		strsep(&peer, ":");

    
   
22909
	}

    
   
22910
	if (ast_strlen_zero(peer)) {

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

    
   
22912
		return -1;

    
   
22913
	}

    
   
22914

   

    
   
22915
	sip_pvt_lock(pvt);

    
   
22916

   

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

    
   
22918
		sip_pvt_unlock(pvt);

    
   
22919
		dialog_unlink_all(pvt, TRUE, TRUE);

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

    
   
22921
		return -1;

    
   
22922
	}

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

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

    
   
22925

   

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

    
   
22927

   

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

    
   
22929

   

    
   
22930
	sip_pvt_unlock(pvt);

    
   
22931
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);

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

    
   
22933

   

    
   
22934
	return res;

    
   
22935
}

    
   
22936

   
22738
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)
22937
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)
22739
{
22938
{
22740
	int etag_present = !ast_strlen_zero(etag);
22939
	int etag_present = !ast_strlen_zero(etag);
22741
	int body_present = req->lines > 0;
22940
	int body_present = req->lines > 0;
22742

    
   
22941

   
[+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)
23919
		break;
24118
		break;
23920
	case SIP_BYE:
24119
	case SIP_BYE:
23921
		res = handle_request_bye(p, req);
24120
		res = handle_request_bye(p, req);
23922
		break;
24121
		break;
23923
	case SIP_MESSAGE:
24122
	case SIP_MESSAGE:
23924
		res = handle_request_message(p, req);
24123
		res = handle_request_message(p, req, addr, e);
23925
		break;
24124
		break;
23926
	case SIP_PUBLISH:
24125
	case SIP_PUBLISH:
23927
		res = handle_request_publish(p, req, addr, seqno, e);
24126
		res = handle_request_publish(p, req, addr, seqno, e);
23928
		break;
24127
		break;
23929
	case SIP_SUBSCRIBE:
24128
	case SIP_SUBSCRIBE:
[+20] [20] 2832 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
26762
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26961
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26763
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26962
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26764
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26963
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26765
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26964
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26766
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
26965
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;

    
   
26966
	sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE;

    
   
26967
	sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE;
26767
	sip_cfg.allowsubscribe = FALSE;
26968
	sip_cfg.allowsubscribe = FALSE;
26768
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26969
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26769
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26970
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26770
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26971
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26771
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
26972
	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)
27008
			sip_cfg.alwaysauthreject = ast_true(v->value);
27209
			sip_cfg.alwaysauthreject = ast_true(v->value);
27009
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27210
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27010
			if (ast_true(v->value)) {
27211
			if (ast_true(v->value)) {
27011
				sip_cfg.auth_options_requests = 1;
27212
				sip_cfg.auth_options_requests = 1;
27012
			}
27213
			}

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

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

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

    
   
27217
			sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0;
27013
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27218
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27014
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27219
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27015
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27220
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27016
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27221
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27017
		} else if (!strcasecmp(v->name, "language")) {
27222
		} else if (!strcasecmp(v->name, "language")) {
[+20] [20] 1752 lines
[+20] [+] static int load_module(void)
28770
	 * has const fields.
28975
	 * has const fields.
28771
	 */
28976
	 */
28772
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
28977
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
28773
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
28978
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
28774

    
   
28979

   

    
   
28980
	if (ast_msg_tech_register(&sip_msg_tech)) {

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

    
   
28982
		return AST_MODULE_LOAD_FAILURE;

    
   
28983
	}

    
   
28984

   
28775
	/* Make sure we can register our sip channel type */
28985
	/* Make sure we can register our sip channel type */
28776
	if (ast_channel_register(&sip_tech)) {
28986
	if (ast_channel_register(&sip_tech)) {
28777
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
28987
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
28778
		io_context_destroy(io);
28988
		io_context_destroy(io);
28779
		sched_context_destroy(sched);
28989
		sched_context_destroy(sched);
[+20] [20] 97 lines
[+20] [+] static int unload_module(void)
28877
	ast_sched_dump(sched);
29087
	ast_sched_dump(sched);
28878
	
29088
	
28879
	/* First, take us out of the channel type list */
29089
	/* First, take us out of the channel type list */
28880
	ast_channel_unregister(&sip_tech);
29090
	ast_channel_unregister(&sip_tech);
28881

    
   
29091

   

    
   
29092
	ast_msg_tech_unregister(&sip_msg_tech);

    
   
29093

   
28882
	/* Unregister dial plan functions */
29094
	/* Unregister dial plan functions */
28883
	ast_custom_function_unregister(&sipchaninfo_function);
29095
	ast_custom_function_unregister(&sipchaninfo_function);
28884
	ast_custom_function_unregister(&sippeer_function);
29096
	ast_custom_function_unregister(&sippeer_function);
28885
	ast_custom_function_unregister(&sip_header_function);
29097
	ast_custom_function_unregister(&sip_header_function);
28886
	ast_custom_function_unregister(&checksipdomain_function);
29098
	ast_custom_function_unregister(&checksipdomain_function);
[+20] [20] 134 lines
/trunk/channels/sip/include/sip.h
Revision 298284 New Change
 
/trunk/configs/jabber.conf.sample
Revision 298284 New Change
 
/trunk/configs/sip.conf.sample
Revision 298284 New Change
 
/trunk/doc/asterisk-messaging.txt
New File
 
/trunk/include/asterisk/_private.h
Revision 298284 New Change
 
/trunk/include/asterisk/channel.h
Revision 298284 New Change
 
/trunk/include/asterisk/jabber.h
Revision 298284 New Change
 
/trunk/include/asterisk/message.h
New File
 
/trunk/main/asterisk.c
Revision 298284 New Change
 
/trunk/main/channel.c
Revision 298284 New Change
 
/trunk/main/message.c
New File
 
/trunk/res/res_jabber.c
Revision 298284 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.