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
Diff Revision 1 Diff Revision 2
[20] 1245 lines
[+20] [+] static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
1246
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);
1247
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);
1248
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);
1249
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);
1250
static int transmit_info_with_vidupdate(struct sip_pvt *p);
1250
static int transmit_info_with_vidupdate(struct sip_pvt *p);
1251
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init);
1251
static int transmit_message_with_text(struct sip_pvt *p, const char *text, int init, int auth);
1252
static int transmit_refer(struct sip_pvt *p, const char *dest);
1252
static int transmit_refer(struct sip_pvt *p, const char *dest);
1253
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);
1254
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);
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_cc_notify(struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state);
1256
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);
1257
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);
1258
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);
1259
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);
1260
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);
1261
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);
1262
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);
1263

    
   
1263

   
1264
/* Misc dialog routines */
1264
/* Misc dialog routines */
1265
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);
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_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *recount, const char *e, 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_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock);
1524
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);
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_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
1526
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);
1527
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);
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 int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
1529
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);
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_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
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_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
1532
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);
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_invite(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_notify(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_refer(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 void handle_response_subscribe(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);
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);
1542
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);
1543

    
   
1544

   
1544
/*------ SRTP Support -------- */
1545
/*------ SRTP Support -------- */
1545
static int setup_srtp(struct sip_srtp **srtp);
1546
static int setup_srtp(struct sip_srtp **srtp);
1546
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)
4216
		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");
4217
		return(0);
4218
		return(0);
4218
	}
4219
	}
4219
	if (debug)
4220
	if (debug)
4220
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4221
		ast_verbose("Sending text %s on %s\n", text, ast->name);
4221
	transmit_message_with_text(dialog, text, 0);
4222
	transmit_message_with_text(dialog, text, 0, 0);
4222
	return 0;	
4223
	return 0;	
4223
}
4224
}
4224

    
   
4225

   
4225
/*! \brief Update peer object in realtime storage
4226
/*! \brief Update peer object in realtime storage
4226
	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)
12608
	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");
12609
	return res;
12610
	return res;
12610
}
12611
}
12611

    
   
12612

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

    
   
12617

   
12617
	if (init) {
12618
	if (init) {
12618
		initreqprep(&req, p, SIP_MESSAGE, NULL);
12619
		initreqprep(&req, p, SIP_MESSAGE, NULL);

    
   
12620
		ast_string_field_set(p, msg_body, text);

    
   
12621
		initialize_initreq(p, &req);
12619
	} else {
12622
	} else {
12620
		reqprep(&req, p, SIP_MESSAGE, 0, 1);
12623
		reqprep(&req, p, SIP_MESSAGE, 0, 1);
12621
	}
12624
	}

    
   
12625
	if (auth) {

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

    
   
12627
	} else {
12622
	add_text(&req, text);
12628
		add_text(&req, text);
12623
	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12629
		return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
12624
}
12630
	}

    
   
12631
}
12625

    
   
12632

   
12626
/*! \brief Allocate SIP refer structure */
12633
/*! \brief Allocate SIP refer structure */
12627
static int sip_refer_allocate(struct sip_pvt *p)
12634
static int sip_refer_allocate(struct sip_pvt *p)
12628
{
12635
{
12629
	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)
12857
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12864
		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause));
12858
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12865
		snprintf(buf, sizeof(buf), "%d", p->hangupcause);
12859
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12866
		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12860
	}
12867
	}
12861

    
   
12868

   

    
   
12869
	if (sipmethod == SIP_MESSAGE) {

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

    
   
12871
	}

    
   
12872

   
12862
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12873
	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
12863
}
12874
}
12864

    
   
12875

   
12865
/*! \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 */
12866
static void destroy_association(struct sip_peer *peer)
12877
static void destroy_association(struct sip_peer *peer)
[+20] [20] 248 lines
[+20] [+] static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req)
13115
	int expire = atoi(expires);
13126
	int expire = atoi(expires);
13116
	char *curi, *domain, *transport;
13127
	char *curi, *domain, *transport;
13117
	int transport_type;
13128
	int transport_type;
13118
	const char *useragent;
13129
	const char *useragent;
13119
	struct ast_sockaddr oldsin, testsa;
13130
	struct ast_sockaddr oldsin, testsa;

    
   
13131
	char *firstcuri = NULL;

    
   
13132
	int start = 0;

    
   
13133
	int wildcard_found = 0;

    
   
13134
	int single_binding_found;
13120

    
   
13135

   
13121
	ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
13136
	ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact));
13122

    
   
13137

   
13123
	if (ast_strlen_zero(expires)) {	/* No expires header, try look in Contact: */
13138
	if (ast_strlen_zero(expires)) {	/* No expires header, try look in Contact: */
13124
		char *s = strcasestr(contact, ";expires=");
13139
		char *s = strcasestr(contact, ";expires=");
13125
		if (s) {
13140
		if (s) {
13126
			expires = strsep(&s, ";"); /* trim ; and beyond */
13141
			expires = strsep(&s, ";"); /* trim ; and beyond */
[+20] [20] 6 lines
[+20] static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req)
13133
		}
13148
		}
13134
	}
13149
	}
13135

    
   
13150

   
13136
	copy_socket_data(&pvt->socket, &req->socket);
13151
	copy_socket_data(&pvt->socket, &req->socket);
13137

    
   
13152

   

    
   
13153
	do {
13138
	/* Look for brackets */
13154
		/* Look for brackets */
13139
	curi = contact;
13155
		curi = contact;
13140
	if (strchr(contact, '<') == NULL)	/* No <, check for ; and strip it */
13156
		if (strchr(contact, '<') == NULL)	/* No <, check for ; and strip it */
13141
		strsep(&curi, ";");	/* This is Header options, not URI options */
13157
			strsep(&curi, ";");	/* This is Header options, not URI options */
13142
	curi = get_in_brackets(contact);
13158
		curi = get_in_brackets(contact);

    
   
13159
		if (!firstcuri) {

    
   
13160
			firstcuri = ast_strdupa(curi);

    
   
13161
		}

    
   
13162

   

    
   
13163
		if (!strcasecmp(curi, "*")) {

    
   
13164
			wildcard_found = 1;

    
   
13165
		} else {

    
   
13166
			single_binding_found = 1;

    
   
13167
		}

    
   
13168

   

    
   
13169
		if (wildcard_found && (ast_strlen_zero(expires) || expire != 0 || single_binding_found)) {

    
   
13170
			/* Contact header parameter "*" detected, so punt if: Expires header is missing,

    
   
13171
			 * Expires value is not zero, or another Contact header is present. */

    
   
13172
			return PARSE_REGISTER_FAILED;

    
   
13173
		}

    
   
13174

   

    
   
13175
		ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact));

    
   
13176
	} while (!ast_strlen_zero(contact));

    
   
13177
	curi = firstcuri;
13143

    
   
13178

   
13144
	/* if they did not specify Contact: or Expires:, they are querying
13179
	/* if they did not specify Contact: or Expires:, they are querying
13145
	   what we currently have stored as their contact address, so return
13180
	   what we currently have stored as their contact address, so return
13146
	   it
13181
	   it
13147
	*/
13182
	*/
[+20] [20] 2223 lines
[+20] [+] static int get_msg_text2(struct ast_str **buf, struct sip_request *req, int addnewline)
15371
AST_THREADSTORAGE(sip_msg_buf);
15406
AST_THREADSTORAGE(sip_msg_buf);
15372

    
   
15407

   
15373
/*! \brief  Receive SIP MESSAGE method messages
15408
/*! \brief  Receive SIP MESSAGE method messages
15374
\note	We only handle messages within current calls currently
15409
\note	We only handle messages within current calls currently
15375
	Reference: RFC 3428 */
15410
	Reference: RFC 3428 */
15376
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)
15377
{
15412
{
15378
	struct ast_str *buf;
15413
	struct ast_str *buf;
15379
	struct ast_frame f;
15414
	struct ast_frame f;
15380
	const char *content_type = get_header(req, "Content-Type");
15415
	const char *content_type = get_header(req, "Content-Type");
15381
	struct ast_msg *msg;
15416
	struct ast_msg *msg;
[+20] [20] 35 lines
[+20] static void receive_message(struct sip_pvt *p, struct sip_request *req) [+] static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
15417
		ast_queue_frame(p->owner, &f);
15452
		ast_queue_frame(p->owner, &f);
15418
		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 */
15419
		return;
15454
		return;
15420
	}
15455
	}
15421

    
   
15456

   
15422
#if 0
15457
	if (!sip_cfg.accept_outofcall_message) {
15423
	/* Message outside of a call, we do not support that */
15458
		/* Message outside of a call, we do not support that */

    
   
15459
		ast_debug(1, "MESSAGE outside of a call administratively disabled.\n");
15424
	transmit_response(p, "405 Method Not Allowed", req);
15460
		transmit_response(p, "405 Method Not Allowed", req);
15425
	sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15461
		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15426
#endif
15462
		return;

    
   
15463
	}

    
   
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;
15427

    
   
15489

   
15428
	/*
15490
		/*
15429
	 * XXX Need to optionally authenticate MESSAGE.  Also, make passing MESSAGE up to
15491
		 * MESSAGE outside of a call, not authenticating it.
15430
	 * the dialplan configurable.
15492
		 * Check to see if we match a peer anyway so that we can direct

    
   
15493
		 * it to the right context.
15431
	 */
15494
		 */
15432

    
   
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

   
15433
	if (!(msg = ast_msg_alloc())) {
15506
	if (!(msg = ast_msg_alloc())) {
15434
		transmit_response(p, "500 Internal Server Error", req);
15507
		transmit_response(p, "500 Internal Server Error", req);
15435
		if (!p->owner) {
15508
		if (!p->owner) {
15436
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15509
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15437
		}
15510
		}
[+20] [20] 4 lines
[+20] static void receive_message(struct sip_pvt *p, struct sip_request *req) static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
15442
	from = ast_strdupa(get_header(req, "From"));
15515
	from = ast_strdupa(get_header(req, "From"));
15443

    
   
15516

   
15444
	res = ast_msg_set_to(msg, "%s", to);
15517
	res = ast_msg_set_to(msg, "%s", to);
15445
	res |= ast_msg_set_from(msg, "%s", get_in_brackets(from));
15518
	res |= ast_msg_set_from(msg, "%s", get_in_brackets(from));
15446
	res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf));
15519
	res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf));
15447
	/* XXX set configurable context */
15520
	res |= ast_msg_set_context(msg, "%s", p->context);
15448

    
   
15521

   
15449
	if (res) {
15522
	if (res) {
15450
		ao2_ref(msg, -1);
15523
		ao2_ref(msg, -1);
15451
	} else {
15524
	} else {
15452
		ast_msg_queue(msg);
15525
		ast_msg_queue(msg);
[+20] [20] 4536 lines
[+20] [+] static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
19989
				handle_response_subscribe(p, resp, rest, req, seqno);
20062
				handle_response_subscribe(p, resp, rest, req, seqno);
19990
			else if (p->registry && sipmethod == SIP_REGISTER)
20063
			else if (p->registry && sipmethod == SIP_REGISTER)
19991
				res = handle_response_register(p, resp, rest, req, seqno);
20064
				res = handle_response_register(p, resp, rest, req, seqno);
19992
			else if (sipmethod == SIP_UPDATE) {
20065
			else if (sipmethod == SIP_UPDATE) {
19993
				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);
19994
			} else if (sipmethod == SIP_BYE) {
20069
			} else if (sipmethod == SIP_BYE) {
19995
				if (p->options)
20070
				if (p->options)
19996
					p->options->auth_type = resp;
20071
					p->options->auth_type = resp;
19997
				if (ast_strlen_zero(p->authname)) {
20072
				if (ast_strlen_zero(p->authname)) {
19998
					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)
20345
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20420
	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
20346
	
20421
	
20347

    
   
20422

   
20348
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20423
#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
20349
	if (!res) {
20424
	if (!res) {
20350
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0);
20425
		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n", 0, 0);
20351
	} else {
20426
	} else {
20352
		/* Then tell the transferer what happened */
20427
		/* Then tell the transferer what happened */
20353
		sprintf(buf, "Call parked on extension '%d'", ext);
20428
		sprintf(buf, "Call parked on extension '%d'", ext);
20354
		transmit_message_with_text(transferer->tech_pvt, buf, 0);
20429
		transmit_message_with_text(transferer->tech_pvt, buf, 0, 0);
20355
	}
20430
	}
20356
#endif
20431
#endif
20357

    
   
20432

   
20358
	/* Any way back to the current call??? */
20433
	/* Any way back to the current call??? */
20359
	/* 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)
22760
	}
22835
	}
22761

    
   
22836

   
22762
	return 1;
22837
	return 1;
22763
}
22838
}
22764

    
   
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

   
22765
/*! \brief Handle incoming MESSAGE request */
22875
/*! \brief Handle incoming MESSAGE request */
22766
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)
22767
{
22877
{
22768
	if (!req->ignore) {
22878
	if (!req->ignore) {
22769
		if (req->debug)
22879
		if (req->debug)
22770
			ast_verbose("Receiving message!\n");
22880
			ast_verbose("Receiving message!\n");
22771
		receive_message(p, req);
22881
		receive_message(p, req, addr, e);
22772
	} else
22882
	} else
22773
		transmit_response(p, "202 Accepted", req);
22883
		transmit_response(p, "202 Accepted", req);
22774
	return 1;
22884
	return 1;
22775
}
22885
}
22776

    
   
22886

   
[+20] [20] 36 lines
[+20] [+] static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from)
22813
	ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);
22923
	ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);
22814
	ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
22924
	ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
22815

    
   
22925

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

    
   
22927

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

    
   
22929

   
22820
	sip_pvt_unlock(pvt);
22930
	sip_pvt_unlock(pvt);
22821
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);
22931
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);
22822
	dialog_unref(pvt, "sent a MESSAGE");
22932
	dialog_unref(pvt, "sent a MESSAGE");
22823

    
   
22933

   
[+20] [20] 911 lines
[+20] [+] static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e)
23735
/*! \brief Handle incoming REGISTER request */
23845
/*! \brief Handle incoming REGISTER request */
23736
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
23846
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
23737
{
23847
{
23738
	enum check_auth_result res;
23848
	enum check_auth_result res;
23739

    
   
23849

   

    
   
23850
	/* If this is not the intial request, and the initial request isn't

    
   
23851
	 * a register, something screwy happened, so bail */

    
   
23852
	if (p->initreq.headers && p->initreq.method != SIP_REGISTER) {

    
   
23853
		ast_log(LOG_WARNING, "Ignoring spurious REGISTER with Call-ID: %s\n", p->callid);

    
   
23854
		return -1;

    
   
23855
	}

    
   
23856

   
23740
	/* Use this as the basis */
23857
	/* Use this as the basis */
23741
	copy_request(&p->initreq, req);
23858
	copy_request(&p->initreq, req);
23742
	if (sipdebug)
23859
	if (sipdebug)
23743
		ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
23860
		ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
23744
	check_via(p, req);
23861
	check_via(p, req);
[+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)
24001
		break;
24118
		break;
24002
	case SIP_BYE:
24119
	case SIP_BYE:
24003
		res = handle_request_bye(p, req);
24120
		res = handle_request_bye(p, req);
24004
		break;
24121
		break;
24005
	case SIP_MESSAGE:
24122
	case SIP_MESSAGE:
24006
		res = handle_request_message(p, req);
24123
		res = handle_request_message(p, req, addr, e);
24007
		break;
24124
		break;
24008
	case SIP_PUBLISH:
24125
	case SIP_PUBLISH:
24009
		res = handle_request_publish(p, req, addr, seqno, e);
24126
		res = handle_request_publish(p, req, addr, seqno, e);
24010
		break;
24127
		break;
24011
	case SIP_SUBSCRIBE:
24128
	case SIP_SUBSCRIBE:
[+20] [20] 2832 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
26844
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26961
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26845
	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 */
26846
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26963
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26847
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26964
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26848
	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;
26849
	sip_cfg.allowsubscribe = FALSE;
26968
	sip_cfg.allowsubscribe = FALSE;
26850
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26969
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26851
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26970
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26852
	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());
26853
	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)
27090
			sip_cfg.alwaysauthreject = ast_true(v->value);
27209
			sip_cfg.alwaysauthreject = ast_true(v->value);
27091
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27210
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27092
			if (ast_true(v->value)) {
27211
			if (ast_true(v->value)) {
27093
				sip_cfg.auth_options_requests = 1;
27212
				sip_cfg.auth_options_requests = 1;
27094
			}
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;
27095
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27218
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27096
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27219
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27097
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27220
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27098
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27221
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27099
		} else if (!strcasecmp(v->name, "language")) {
27222
		} else if (!strcasecmp(v->name, "language")) {
[+20] [20] 2010 lines
/trunk/channels/sip/include/sip.h
Diff Revision 1 Diff Revision 2
 
/trunk/configs/jabber.conf.sample
Diff Revision 1 Diff Revision 2
 
/trunk/configs/sip.conf.sample
Diff Revision 1 Diff Revision 2
 
/trunk/doc/asterisk-messaging.txt
Diff Revision 1 Diff Revision 2
 
/trunk/include/asterisk/_private.h
Diff Revision 1 Diff Revision 2
 
/trunk/include/asterisk/channel.h
Diff Revision 1 Diff Revision 2
 
/trunk/include/asterisk/jabber.h
Diff Revision 1 Diff Revision 2
 
/trunk/main/asterisk.c
Diff Revision 1 Diff Revision 2
 
/trunk/main/channel.c
Diff Revision 1 Diff Revision 2
 
/trunk/res/res_jabber.c
Diff Revision 1 Diff Revision 2
 
/trunk/testsuite-tests/message_from_call/run-test
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_from_call/test-config.yaml
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_from_call/configs/ast1/extensions.conf
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_from_call/sipp/call.xml
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_from_call/sipp/message_recv.xml
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_unauth/run-test
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_unauth/test-config.yaml
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_unauth/configs/ast1/extensions.conf
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_unauth/sipp/message.xml
Diff Revision 1 Diff Revision 2 - File Reverted
 
/trunk/testsuite-tests/message_unauth/sipp/message_recv.xml
Diff Revision 1 Diff Revision 2 - File Reverted
 
  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/main/asterisk.c: Loading...
  10. /trunk/main/channel.c: Loading...
  11. /trunk/res/res_jabber.c: Loading...
  12. /trunk/testsuite-tests/message_from_call/run-test: Loading...
  13. /trunk/testsuite-tests/message_from_call/test-config.yaml: Loading...
  14. /trunk/testsuite-tests/message_from_call/configs/ast1/extensions.conf: Loading...
  15. /trunk/testsuite-tests/message_from_call/sipp/call.xml: Loading...
  16. /trunk/testsuite-tests/message_from_call/sipp/message_recv.xml: Loading...
  17. /trunk/testsuite-tests/message_unauth/run-test: Loading...
  18. /trunk/testsuite-tests/message_unauth/test-config.yaml: Loading...
  19. /trunk/testsuite-tests/message_unauth/configs/ast1/extensions.conf: Loading...
  20. /trunk/testsuite-tests/message_unauth/sipp/message.xml: Loading...
  21. /trunk/testsuite-tests/message_unauth/sipp/message_recv.xml: 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.