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 309631 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] 2686 lines
[+20] [+] static int sip_sendtext(struct ast_channel *ast, const char *text)
4232
		ast_debug(2, "Trying to send MESSAGE to device that does not support it.\n");
4234
		ast_debug(2, "Trying to send MESSAGE to device that does not support it.\n");
4233
		return(0);
4235
		return(0);
4234
	}
4236
	}
4235
	if (debug)
4237
	if (debug)
4236
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4238
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4237
	transmit_message_with_text(dialog, text);
4239
	transmit_message_with_text(dialog, text, 0, 0);
4238
	return 0;
4240
	return 0;
4239
}
4241
}
4240

    
   
4242

   
4241
/*! \brief Update peer object in realtime storage
4243
/*! \brief Update peer object in realtime storage
4242
	If the Asterisk system name is set in asterisk.conf, we will use
4244
	If the Asterisk system name is set in asterisk.conf, we will use
[+20] [20] 8568 lines
[+20] [+] static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader)
12811
	dialog_unref(p, "p is finished here at the end of transmit_register");
12813
	dialog_unref(p, "p is finished here at the end of transmit_register");
12812
	return res;
12814
	return res;
12813
}
12815
}
12814

    
   
12816

   
12815
/*! \brief Transmit text with SIP MESSAGE method */
12817
/*! \brief Transmit text with SIP MESSAGE method */
12816
static int transmit_message_with_text(struct sip_pvt *p, const char *text)
12818
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth)
12817
{
12819
{
12818
	struct sip_request req;
12820
	struct sip_request req;
12819
	
12821

   

    
   
12822
	if (init) {

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

    
   
12824
		ast_string_field_set(p, msg_body, text);

    
   
12825
		initialize_initreq(p, &req);

    
   
12826
	} else {
12820
	reqprep(&req, p, SIP_MESSAGE, 0, 1);
12827
		reqprep(&req, p, SIP_MESSAGE, 0, 1);

    
   
12828
	}

    
   
12829
	if (auth) {

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

    
   
12831
	} else {
12821
	add_text(&req, text);
12832
		add_text(&req, text);
12822
	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12833
		return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12823
}
12834
	}

    
   
12835
}
12824

    
   
12836

   
12825
/*! \brief Allocate SIP refer structure */
12837
/*! \brief Allocate SIP refer structure */
12826
static int sip_refer_allocate(struct sip_pvt *p)
12838
static int sip_refer_allocate(struct sip_pvt *p)
12827
{
12839
{
12828
	p->refer = ast_calloc(1, sizeof(struct sip_refer));
12840
	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)
13056
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
13068
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
13057
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
13069
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
13058
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
13070
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
13059
	}
13071
	}
13060

    
   
13072

   

    
   
13073
	if (sipmethod == SIP_MESSAGE) {

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

    
   
13075
	}

    
   
13076

   
13061
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
13077
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
13062
}
13078
}
13063

    
   
13079

   
13064
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
13080
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
13065
static void destroy_association(struct sip_peer *peer)
13081
static void destroy_association(struct sip_peer *peer)
[+20] [20] 2522 lines
[+20] [+] static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline)
15588
			strcat(buf, "\n"); /* safe */
15604
			strcat(buf, "\n"); /* safe */
15589
	}
15605
	}
15590
	return 0;
15606
	return 0;
15591
}
15607
}
15592

    
   
15608

   

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

    
   
15610
{

    
   
15611
	int i, res = 0;

    
   
15612

   

    
   
15613
	ast_str_reset(*buf);

    
   
15614

   

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

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

    
   
15617
		int res;

    
   
15618

   

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

    
   
15620
	}

    
   
15621

   

    
   
15622
	return res < 0 ? -1 : 0;

    
   
15623
}

    
   
15624

   

    
   
15625
AST_THREADSTORAGE(sip_msg_buf);
15593

    
   
15626

   
15594
/*! \brief  Receive SIP MESSAGE method messages
15627
/*! \brief  Receive SIP MESSAGE method messages
15595
\note	We only handle messages within current calls currently
15628
\note	We only handle messages within current calls currently
15596
	Reference: RFC 3428 */
15629
	Reference: RFC 3428 */
15597
static void receive_message(struct sip_pvt *p, struct sip_request *req)
15630
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
15598
{
15631
{
15599
	char buf[1400];	
15632
	struct ast_str *buf;
15600
	struct ast_frame f;
15633
	struct ast_frame f;
15601
	const char *content_type = get_header(req, "Content-Type");
15634
	const char *content_type = get_header(req, "Content-Type");

    
   
15635
	struct ast_msg *msg;

    
   
15636
	int res;

    
   
15637
	char *from, *to;
15602

    
   
15638

   
15603
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15639
	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
15604
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15640
		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
15605
		if (!p->owner)
15641
		if (!p->owner)
15606
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15642
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15607
		return;
15643
		return;
15608
	}
15644
	}
15609

    
   
15645

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

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

    
   
15648
		if (!p->owner) {

    
   
15649
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15650
		}

    
   
15651
		return;

    
   
15652
	}

    
   
15653

   

    
   
15654
	if (get_msg_text2(&buf, req, FALSE)) {
15611
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15655
		ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
15612
		transmit_response(p, "202 Accepted", req);
15656
		transmit_response(p, "202 Accepted", req);
15613
		if (!p->owner)
15657
		if (!p->owner)
15614
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15658
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15615
		return;
15659
		return;
15616
	}
15660
	}
15617

    
   
15661

   
15618
	if (p->owner) {
15662
	if (p->owner) {
15619
		if (sip_debug_test_pvt(p))
15663
		if (sip_debug_test_pvt(p))
15620
			ast_verbose("SIP Text message received: '%s'\n", buf);
15664
			ast_verbose("SIP Text message received: '%s'\n", ast_str_buffer(buf));
15621
		memset(&f, 0, sizeof(f));
15665
		memset(&f, 0, sizeof(f));
15622
		f.frametype = AST_FRAME_TEXT;
15666
		f.frametype = AST_FRAME_TEXT;
15623
		f.subclass.integer = 0;
15667
		f.subclass.integer = 0;
15624
		f.offset = 0;
15668
		f.offset = 0;
15625
		f.data.ptr = buf;
15669
		f.data.ptr = ast_str_buffer(buf);
15626
		f.datalen = strlen(buf) + 1;
15670
		f.datalen = ast_str_strlen(buf) + 1;
15627
		ast_queue_frame(p->owner, &f);
15671
		ast_queue_frame(p->owner, &f);
15628
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15672
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15629
		return;
15673
		return;
15630
	}
15674
	}
15631

    
   
15675

   

    
   
15676
	if (!sip_cfg.accept_outofcall_message) {
15632
	/* Message outside of a call, we do not support that */
15677
		/* Message outside of a call, we do not support that */
15633
	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);
15678
		ast_debug(1, "MESSAGE outside of a call administratively disabled.\n");
15634
	transmit_response(p, "405 Method Not Allowed", req);
15679
		transmit_response(p, "405 Method Not Allowed", req);
15635
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15680
		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15636
	return;
15681
		return;
15637
}
15682
	}
15638

    
   
15683

   

    
   
15684
	if (sip_cfg.auth_message_requests) {

    
   
15685
		int res;

    
   
15686

   

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

    
   
15688
		set_pvt_allowed_methods(p, req);

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

    
   
15690
		if (res == AUTH_CHALLENGE_SENT) {

    
   
15691
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15692
			return;

    
   
15693
		}

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

    
   
15695
			if (res == AUTH_FAKE_AUTH) {

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

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

    
   
15698
			} else {

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

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

    
   
15701
			}

    
   
15702
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15703
			return;

    
   
15704
		}

    
   
15705
		/* Auth was successful.  Proceed. */

    
   
15706
	} else {

    
   
15707
		struct sip_peer *peer;

    
   
15708

   

    
   
15709
		/*

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

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

    
   
15712
		 * it to the right context.

    
   
15713
		 */

    
   
15714

   

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

    
   
15716
		if (peer) {

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

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

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

    
   
15720
			}

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

    
   
15722
		}

    
   
15723
	}

    
   
15724

   

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

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

    
   
15727
		if (!p->owner) {

    
   
15728
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15729
		}

    
   
15730
		return;

    
   
15731
	}

    
   
15732

   

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

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

    
   
15735

   

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

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

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

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

    
   
15740

   

    
   
15741
	if (res) {

    
   
15742
		ast_msg_destroy(msg);

    
   
15743
	} else {

    
   
15744
		ast_msg_queue(msg);

    
   
15745
	}

    
   
15746

   

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

    
   
15748
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15749
}

    
   
15750

   
15639
/*! \brief  CLI Command to show calls within limits set by call_limit */
15751
/*! \brief  CLI Command to show calls within limits set by call_limit */
15640
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15752
static char *sip_show_inuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15641
{
15753
{
15642
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15754
#define FORMAT "%-25.25s %-15.15s %-15.15s \n"
15643
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
15755
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n"
[+20] [20] 4530 lines
[+20] [+] static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
20174
				handle_response_subscribe(p, resp, rest, req, seqno);
20286
				handle_response_subscribe(p, resp, rest, req, seqno);
20175
			else if (p->registry && sipmethod == SIP_REGISTER)
20287
			else if (p->registry && sipmethod == SIP_REGISTER)
20176
				res = handle_response_register(p, resp, rest, req, seqno);
20288
				res = handle_response_register(p, resp, rest, req, seqno);
20177
			else if (sipmethod == SIP_UPDATE) {
20289
			else if (sipmethod == SIP_UPDATE) {
20178
				handle_response_update(p, resp, rest, req, seqno);
20290
				handle_response_update(p, resp, rest, req, seqno);

    
   
20291
			} else if (sipmethod == SIP_MESSAGE) {

    
   
20292
				handle_response_message(p, resp, rest, req, seqno);
20179
			} else if (sipmethod == SIP_BYE) {
20293
			} else if (sipmethod == SIP_BYE) {
20180
				if (p->options)
20294
				if (p->options)
20181
					p->options->auth_type = resp;
20295
					p->options->auth_type = resp;
20182
				if (ast_strlen_zero(p->authname)) {
20296
				if (ast_strlen_zero(p->authname)) {
20183
					ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
20297
					ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n",
[+20] [20] 345 lines
[+20] [+] static void *sip_park_thread(void *stuff)
20529

    
   
20643

   
20530
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20644
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20531

    
   
20645

   
20532
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20646
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20533
	if (!res) {
20647
	if (!res) {
20534
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n");
20648
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0, 0);
20535
	} else {
20649
	} else {
20536
		/* Then tell the transferer what happened */
20650
		/* Then tell the transferer what happened */
20537
		sprintf(buf, "Call parked on extension '%d'", ext);
20651
		sprintf(buf, "Call parked on extension '%d'", ext);
20538
		transmit_message_with_text(transferer->tech_pvt, buf);
20652
		transmit_message_with_text(transferer->tech_pvt, buf, 0, 0);
20539
	}
20653
	}
20540
#endif
20654
#endif
20541

    
   
20655

   
20542
	/* Any way back to the current call??? */
20656
	/* Any way back to the current call??? */
20543
	/* Transmit response to the REFER request */
20657
	/* Transmit response to the REFER request */
[+20] [20] 2405 lines
[+20] [+] static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
22949
	}
23063
	}
22950

    
   
23064

   
22951
	return 1;
23065
	return 1;
22952
}
23066
}
22953

    
   
23067

   

    
   
23068
/*!

    
   
23069
 * \internal

    
   
23070
 * \brief Handle auth requests to a MESSAGE request

    
   
23071
 */

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

    
   
23073
{

    
   
23074
	char *header, *respheader;

    
   
23075
	char digest[1024];

    
   
23076

   

    
   
23077
	if (p->options) {

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

    
   
23079
	}

    
   
23080

   

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

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

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

    
   
23084
		return;

    
   
23085
	}

    
   
23086

   

    
   
23087
	p->authtries++;

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

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

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

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

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

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

    
   
23094
		return;

    
   
23095
	}

    
   
23096

   

    
   
23097
	if (p->do_history) {

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

    
   
23099
	}

    
   
23100

   

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

    
   
23102
}

    
   
23103

   
22954
/*! \brief Handle incoming MESSAGE request */
23104
/*! \brief Handle incoming MESSAGE request */
22955
static int handle_request_message(struct sip_pvt *p, struct sip_request *req)
23105
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
22956
{
23106
{
22957
	if (!req->ignore) {
23107
	if (!req->ignore) {
22958
		if (req->debug)
23108
		if (req->debug)
22959
			ast_verbose("Receiving message!\n");
23109
			ast_verbose("Receiving message!\n");
22960
		receive_message(p, req);
23110
		receive_message(p, req, addr, e);
22961
	} else
23111
	} else
22962
		transmit_response(p, "202 Accepted", req);
23112
		transmit_response(p, "202 Accepted", req);
22963
	return 1;
23113
	return 1;
22964
}
23114
}
22965

    
   
23115

   

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

    
   
23117

   

    
   
23118
static const struct ast_msg_tech sip_msg_tech = {

    
   
23119
	.name = "sip",

    
   
23120
	.msg_send = sip_msg_send,

    
   
23121
};

    
   
23122

   

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

    
   
23124
{

    
   
23125
	struct sip_pvt *pvt;

    
   
23126
	int res;

    
   
23127
	char *peer;

    
   
23128

   

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

    
   
23130
		return -1;

    
   
23131
	}

    
   
23132

   

    
   
23133
	peer = ast_strdupa(to);

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

    
   
23135
		strsep(&peer, "@");

    
   
23136
	} else {

    
   
23137
		strsep(&peer, ":");

    
   
23138
	}

    
   
23139
	if (ast_strlen_zero(peer)) {

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

    
   
23141
		return -1;

    
   
23142
	}

    
   
23143

   

    
   
23144
	sip_pvt_lock(pvt);

    
   
23145

   

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

    
   
23147
		sip_pvt_unlock(pvt);

    
   
23148
		dialog_unlink_all(pvt, TRUE, TRUE);

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

    
   
23150
		return -1;

    
   
23151
	}

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

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

    
   
23154

   

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

    
   
23156

   

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

    
   
23158

   

    
   
23159
	sip_pvt_unlock(pvt);

    
   
23160
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);

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

    
   
23162

   

    
   
23163
	return res;

    
   
23164
}

    
   
23165

   
22966
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)
23166
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)
22967
{
23167
{
22968
	int etag_present = !ast_strlen_zero(etag);
23168
	int etag_present = !ast_strlen_zero(etag);
22969
	int body_present = req->lines > 0;
23169
	int body_present = req->lines > 0;
22970

    
   
23170

   
[+20] [20] 1181 lines
[+20] [+] static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock)
24152
		break;
24352
		break;
24153
	case SIP_BYE:
24353
	case SIP_BYE:
24154
		res = handle_request_bye(p, req);
24354
		res = handle_request_bye(p, req);
24155
		break;
24355
		break;
24156
	case SIP_MESSAGE:
24356
	case SIP_MESSAGE:
24157
		res = handle_request_message(p, req);
24357
		res = handle_request_message(p, req, addr, e);
24158
		break;
24358
		break;
24159
	case SIP_PUBLISH:
24359
	case SIP_PUBLISH:
24160
		res = handle_request_publish(p, req, addr, seqno, e);
24360
		res = handle_request_publish(p, req, addr, seqno, e);
24161
		break;
24361
		break;
24162
	case SIP_SUBSCRIBE:
24362
	case SIP_SUBSCRIBE:
[+20] [20] 2864 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
27027
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
27227
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
27028
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
27228
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
27029
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
27229
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
27030
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
27230
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
27031
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
27231
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;

    
   
27232
	sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE;

    
   
27233
	sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE;
27032
	sip_cfg.allowsubscribe = FALSE;
27234
	sip_cfg.allowsubscribe = FALSE;
27033
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
27235
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
27034
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
27236
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
27035
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
27237
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
27036
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
27238
	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)
27273
			sip_cfg.alwaysauthreject = ast_true(v->value);
27475
			sip_cfg.alwaysauthreject = ast_true(v->value);
27274
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27476
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27275
			if (ast_true(v->value)) {
27477
			if (ast_true(v->value)) {
27276
				sip_cfg.auth_options_requests = 1;
27478
				sip_cfg.auth_options_requests = 1;
27277
			}
27479
			}

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

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

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

    
   
27483
			sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0;
27278
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27484
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27279
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27485
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27280
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27486
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27281
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27487
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27282
		} else if (!strcasecmp(v->name, "language")) {
27488
		} else if (!strcasecmp(v->name, "language")) {
[+20] [20] 1943 lines
[+20] [+] static int load_module(void)
29226
	 * has const fields.
29432
	 * has const fields.
29227
	 */
29433
	 */
29228
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
29434
	memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
29229
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
29435
	memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
29230

    
   
29436

   

    
   
29437
	if (ast_msg_tech_register(&sip_msg_tech)) {

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

    
   
29439
		return AST_MODULE_LOAD_FAILURE;

    
   
29440
	}

    
   
29441

   
29231
	/* Make sure we can register our sip channel type */
29442
	/* Make sure we can register our sip channel type */
29232
	if (ast_channel_register(&sip_tech)) {
29443
	if (ast_channel_register(&sip_tech)) {
29233
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
29444
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
29234
		io_context_destroy(io);
29445
		io_context_destroy(io);
29235
		ast_sched_context_destroy(sched);
29446
		ast_sched_context_destroy(sched);
[+20] [20] 98 lines
[+20] [+] static int unload_module(void)
29334
	ast_sched_dump(sched);
29545
	ast_sched_dump(sched);
29335
	
29546
	
29336
	/* First, take us out of the channel type list */
29547
	/* First, take us out of the channel type list */
29337
	ast_channel_unregister(&sip_tech);
29548
	ast_channel_unregister(&sip_tech);
29338

    
   
29549

   

    
   
29550
	ast_msg_tech_unregister(&sip_msg_tech);

    
   
29551

   
29339
	/* Unregister dial plan functions */
29552
	/* Unregister dial plan functions */
29340
	ast_custom_function_unregister(&sipchaninfo_function);
29553
	ast_custom_function_unregister(&sipchaninfo_function);
29341
	ast_custom_function_unregister(&sippeer_function);
29554
	ast_custom_function_unregister(&sippeer_function);
29342
	ast_custom_function_unregister(&sip_header_function);
29555
	ast_custom_function_unregister(&sip_header_function);
29343
	ast_custom_function_unregister(&checksipdomain_function);
29556
	ast_custom_function_unregister(&checksipdomain_function);
[+20] [20] 138 lines
/trunk/channels/sip/include/sip.h
Revision 309631 New Change
 
/trunk/configs/jabber.conf.sample
Revision 309631 New Change
 
/trunk/configs/sip.conf.sample
Revision 309631 New Change
 
/trunk/doc/asterisk-messaging.txt
New File
 
/trunk/include/asterisk/_private.h
Revision 309631 New Change
 
/trunk/include/asterisk/channel.h
Revision 309631 New Change
 
/trunk/include/asterisk/jabber.h
Revision 309631 New Change
 
/trunk/include/asterisk/message.h
New File
 
/trunk/main/asterisk.c
Revision 309631 New Change
 
/trunk/main/channel.c
Revision 309631 New Change
 
/trunk/main/message.c
New File
 
/trunk/res/res_jabber.c
Revision 309631 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.