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 3
[20] 780 lines
[+20] [+] AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
781
static pthread_t monitor_thread = AST_PTHREADT_NULL;
781
static pthread_t monitor_thread = AST_PTHREADT_NULL;
782

    
   
782

   
783
static int sip_reloading = FALSE;                       /*!< Flag for avoiding multiple reloads at the same time */
783
static int sip_reloading = FALSE;                       /*!< Flag for avoiding multiple reloads at the same time */
784
static enum channelreloadreason sip_reloadreason;       /*!< Reason for last reload/load of configuration */
784
static enum channelreloadreason sip_reloadreason;       /*!< Reason for last reload/load of configuration */
785

    
   
785

   
786
struct sched_context *sched;     /*!< The scheduling context */
786
struct ast_sched_context *sched;     /*!< The scheduling context */
787
static struct io_context *io;           /*!< The IO context */
787
static struct io_context *io;           /*!< The IO context */
788
static int *sipsock_read_id;            /*!< ID of IO entry for sipsock FD */
788
static int *sipsock_read_id;            /*!< ID of IO entry for sipsock FD */
789
struct sip_pkt;
789
struct sip_pkt;
790
static AST_LIST_HEAD_STATIC(domain_list, domain);    /*!< The SIP domain list */
790
static AST_LIST_HEAD_STATIC(domain_list, domain);    /*!< The SIP domain list */
791

    
   
791

   
[+20] [20] 454 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
4227
	that name and store that in the "regserver" field in the sippeers
4228
	that name and store that in the "regserver" field in the sippeers
4228
	table to facilitate multi-server setups.
4229
	table to facilitate multi-server setups.
4229
*/
4230
*/
4230
static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms)
4231
static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms)
4231
{
4232
{
4232
	char port[10];
4233
	char port[10];
4233
	char ipaddr[INET_ADDRSTRLEN];
4234
	char ipaddr[INET6_ADDRSTRLEN];
4234
	char regseconds[20];
4235
	char regseconds[20];
4235
	char *tablename = NULL;
4236
	char *tablename = NULL;
4236
	char str_lastms[20];
4237
	char str_lastms[20];
4237

    
   
4238

   
4238
	const char *sysname = ast_config_AST_SYSTEM_NAME;
4239
	const char *sysname = ast_config_AST_SYSTEM_NAME;
[+20] [20] 196 lines
[+20] [+] static struct sip_peer *realtime_peer(const char *newpeername, struct ast_sockaddr *addr, int devstate_only, int which_objects)
4435
	struct sip_peer *peer;
4436
	struct sip_peer *peer;
4436
	struct ast_variable *var = NULL;
4437
	struct ast_variable *var = NULL;
4437
	struct ast_variable *varregs = NULL;
4438
	struct ast_variable *varregs = NULL;
4438
	struct ast_variable *tmp;
4439
	struct ast_variable *tmp;
4439
	struct ast_config *peerlist = NULL;
4440
	struct ast_config *peerlist = NULL;
4440
	char ipaddr[INET_ADDRSTRLEN];
4441
	char ipaddr[INET6_ADDRSTRLEN];
4441
	char portstring[6]; /*up to 5 digits plus null terminator*/
4442
	char portstring[6]; /*up to 5 digits plus null terminator*/
4442
	char *cat = NULL;
4443
	char *cat = NULL;
4443
	int realtimeregs = ast_check_realtime("sipregs");
4444
	int realtimeregs = ast_check_realtime("sipregs");
4444

    
   
4445

   
4445
	/* First check on peer name */
4446
	/* First check on peer name */
[+20] [20] 3273 lines
[+20] [+] static int sip_register(const char *value, int lineno)
7719
{
7720
{
7720
	struct sip_subscription_mwi *mwi;
7721
	struct sip_subscription_mwi *mwi;
7721
	int portnum = 0;
7722
	int portnum = 0;
7722
	enum sip_transport transport = SIP_TRANSPORT_UDP;
7723
	enum sip_transport transport = SIP_TRANSPORT_UDP;
7723
	char buf[256] = "";
7724
	char buf[256] = "";
7724
	char *username = NULL, *hostname = NULL, *secret = NULL, *authuser = NULL, *porta = NULL, *mailbox = NULL;
7725
	char *username = NULL, *hostname = NULL, *secret = NULL, *authuser = NULL, *porta = NULL, *mailbox = NULL, *at = NULL;
7725
	
7726

   
7726
	if (!value) {
7727
	if (!value) {
7727
		return -1;
7728
		return -1;
7728
	}
7729
	}
7729
	
7730

   
7730
	ast_copy_string(buf, value, sizeof(buf));
7731
	ast_copy_string(buf, value, sizeof(buf));
7731

    
   
7732

   
7732
	sip_parse_host(buf, lineno, &username, &portnum, &transport);
7733
	if (!(at = strstr(buf, "@"))) {
7733
	
7734
		return -1;
7734
	if ((hostname = strrchr(username, '@'))) {
7735
	}

    
   
7736

   

    
   
7737
	if ((hostname = strrchr(buf, '@'))) {
7735
		*hostname++ = '\0';
7738
		*hostname++ = '\0';

    
   
7739
		username = buf;
7736
	}
7740
	}
7737
	
7741

   
7738
	if ((secret = strchr(username, ':'))) {
7742
	if ((secret = strchr(username, ':'))) {
7739
		*secret++ = '\0';
7743
		*secret++ = '\0';
7740
		if ((authuser = strchr(secret, ':'))) {
7744
		if ((authuser = strchr(secret, ':'))) {
7741
			*authuser++ = '\0';
7745
			*authuser++ = '\0';
7742
		}
7746
		}
7743
	}
7747
	}
7744
	
7748

   
7745
	if ((mailbox = strchr(hostname, '/'))) {
7749
	if ((mailbox = strchr(hostname, '/'))) {
7746
		*mailbox++ = '\0';
7750
		*mailbox++ = '\0';
7747
	}
7751
	}
7748

    
   
7752

   
7749
	if (ast_strlen_zero(username) || ast_strlen_zero(hostname) || ast_strlen_zero(mailbox)) {
7753
	if (ast_strlen_zero(username) || ast_strlen_zero(hostname) || ast_strlen_zero(mailbox)) {
7750
		ast_log(LOG_WARNING, "Format for MWI subscription is user[:secret[:authuser]]@host[:port][/mailbox] at line %d\n", lineno);
7754
		ast_log(LOG_WARNING, "Format for MWI subscription is user[:secret[:authuser]]@host[:port]/mailbox at line %d\n", lineno);
7751
		return -1;
7755
		return -1;
7752
	}
7756
	}
7753
	
7757

   
7754
	if ((porta = strchr(hostname, ':'))) {
7758
	if ((porta = strchr(hostname, ':'))) {
7755
		*porta++ = '\0';
7759
		*porta++ = '\0';
7756
		if (!(portnum = atoi(porta))) {
7760
		if (!(portnum = atoi(porta))) {
7757
			ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
7761
			ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
7758
			return -1;
7762
			return -1;
7759
		}
7763
		}
7760
	}
7764
	}
7761
	
7765

   
7762
	if (!(mwi = ast_calloc_with_stringfields(1, struct sip_subscription_mwi, 256))) {
7766
	if (!(mwi = ast_calloc_with_stringfields(1, struct sip_subscription_mwi, 256))) {
7763
		return -1;
7767
		return -1;
7764
	}
7768
	}
7765
	
7769

   
7766
	ASTOBJ_INIT(mwi);
7770
	ASTOBJ_INIT(mwi);
7767
	ast_string_field_set(mwi, username, username);
7771
	ast_string_field_set(mwi, username, username);
7768
	if (secret) {
7772
	if (secret) {
7769
		ast_string_field_set(mwi, secret, secret);
7773
		ast_string_field_set(mwi, secret, secret);
7770
	}
7774
	}
7771
	if (authuser) {
7775
	if (authuser) {
7772
		ast_string_field_set(mwi, authuser, authuser);
7776
		ast_string_field_set(mwi, authuser, authuser);
7773
	}
7777
	}
7774
	ast_string_field_set(mwi, hostname, hostname);
7778
	ast_string_field_set(mwi, hostname, hostname);
7775
	ast_string_field_set(mwi, mailbox, mailbox);
7779
	ast_string_field_set(mwi, mailbox, mailbox);
7776
	mwi->resub = -1;
7780
	mwi->resub = -1;
7777
	mwi->portno = portnum;
7781
	mwi->portno = portnum;
7778
	mwi->transport = transport;
7782
	mwi->transport = transport;
7779
	
7783

   
7780
	ASTOBJ_CONTAINER_LINK(&submwil, mwi);
7784
	ASTOBJ_CONTAINER_LINK(&submwil, mwi);
7781
	ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy);
7785
	ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy);
7782
	
7786

   
7783
	return 0;
7787
	return 0;
7784
}
7788
}
7785

    
   
7789

   
7786
static void mark_method_allowed(unsigned int *allowed_methods, enum sipmethod method)
7790
static void mark_method_allowed(unsigned int *allowed_methods, enum sipmethod method)
7787
{
7791
{
[+20] [20] 4820 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");
12612
	dialog_unref(p, "p is finished here at the end of transmit_register");
12609
	return res;
12613
	return res;
12610
}
12614
}
12611

    
   
12615

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

    
   
12620

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

    
   
12623
		ast_string_field_set(p, msg_body, text);

    
   
12624
		initialize_initreq(p, &req);
12619
	} else {
12625
	} else {
12620
		reqprep(&req, p, SIP_MESSAGE, 0, 1);
12626
		reqprep(&req, p, SIP_MESSAGE, 0, 1);
12621
	}
12627
	}

    
   
12628
	if (auth) {

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

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

    
   
12634
}
12625

    
   
12635

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

    
   
12871

   

    
   
12872
	if (sipmethod == SIP_MESSAGE) {

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

    
   
12874
	}

    
   
12875

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

    
   
12878

   
12865
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12879
/*! \brief Remove registration data from realtime database or AST/DB when registration expires */
12866
static void destroy_association(struct sip_peer *peer)
12880
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);
13129
	int expire = atoi(expires);
13116
	char *curi, *domain, *transport;
13130
	char *curi, *domain, *transport;
13117
	int transport_type;
13131
	int transport_type;
13118
	const char *useragent;
13132
	const char *useragent;
13119
	struct ast_sockaddr oldsin, testsa;
13133
	struct ast_sockaddr oldsin, testsa;

    
   
13134
	char *firstcuri = NULL;

    
   
13135
	int start = 0;

    
   
13136
	int wildcard_found = 0;

    
   
13137
	int single_binding_found;
13120

    
   
13138

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

    
   
13140

   
13123
	if (ast_strlen_zero(expires)) {	/* No expires header, try look in Contact: */
13141
	if (ast_strlen_zero(expires)) {	/* No expires header, try look in Contact: */
13124
		char *s = strcasestr(contact, ";expires=");
13142
		char *s = strcasestr(contact, ";expires=");
13125
		if (s) {
13143
		if (s) {
13126
			expires = strsep(&s, ";"); /* trim ; and beyond */
13144
			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
		}
13151
		}
13134
	}
13152
	}
13135

    
   
13153

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

    
   
13155

   

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

    
   
13162
		if (!firstcuri) {

    
   
13163
			firstcuri = ast_strdupa(curi);

    
   
13164
		}

    
   
13165

   

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

    
   
13167
			wildcard_found = 1;

    
   
13168
		} else {

    
   
13169
			single_binding_found = 1;

    
   
13170
		}

    
   
13171

   

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

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

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

    
   
13175
			return PARSE_REGISTER_FAILED;

    
   
13176
		}

    
   
13177

   

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

    
   
13179
	} while (!ast_strlen_zero(contact));

    
   
13180
	curi = firstcuri;
13143

    
   
13181

   
13144
	/* if they did not specify Contact: or Expires:, they are querying
13182
	/* if they did not specify Contact: or Expires:, they are querying
13145
	   what we currently have stored as their contact address, so return
13183
	   what we currently have stored as their contact address, so return
13146
	   it
13184
	   it
13147
	*/
13185
	*/
[+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);
15409
AST_THREADSTORAGE(sip_msg_buf);
15372

    
   
15410

   
15373
/*! \brief  Receive SIP MESSAGE method messages
15411
/*! \brief  Receive SIP MESSAGE method messages
15374
\note	We only handle messages within current calls currently
15412
\note	We only handle messages within current calls currently
15375
	Reference: RFC 3428 */
15413
	Reference: RFC 3428 */
15376
static void receive_message(struct sip_pvt *p, struct sip_request *req)
15414
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
15377
{
15415
{
15378
	struct ast_str *buf;
15416
	struct ast_str *buf;
15379
	struct ast_frame f;
15417
	struct ast_frame f;
15380
	const char *content_type = get_header(req, "Content-Type");
15418
	const char *content_type = get_header(req, "Content-Type");
15381
	struct ast_msg *msg;
15419
	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);
15455
		ast_queue_frame(p->owner, &f);
15418
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15456
		transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */
15419
		return;
15457
		return;
15420
	}
15458
	}
15421

    
   
15459

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

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

    
   
15466
	}

    
   
15467

   

    
   
15468
	if (sip_cfg.auth_message_requests) {

    
   
15469
		int res;

    
   
15470

   

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

    
   
15472
		set_pvt_allowed_methods(p, req);

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

    
   
15474
		if (res == AUTH_CHALLENGE_SENT) {

    
   
15475
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15476
			return;

    
   
15477
		}

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

    
   
15479
			if (res == AUTH_FAKE_AUTH) {

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

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

    
   
15482
			} else {

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

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

    
   
15485
			}

    
   
15486
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);

    
   
15487
			return;

    
   
15488
		}

    
   
15489
		/* Auth was successful.  Proceed. */

    
   
15490
	} else {

    
   
15491
		struct sip_peer *peer;
15427

    
   
15492

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

    
   
15496
		 * it to the right context.
15431
	 */
15497
		 */
15432

    
   
15498

   

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

    
   
15500
		if (peer) {

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

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

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

    
   
15504
			}

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

    
   
15506
		}

    
   
15507
	}

    
   
15508

   
15433
	if (!(msg = ast_msg_alloc())) {
15509
	if (!(msg = ast_msg_alloc())) {
15434
		transmit_response(p, "500 Internal Server Error", req);
15510
		transmit_response(p, "500 Internal Server Error", req);
15435
		if (!p->owner) {
15511
		if (!p->owner) {
15436
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15512
			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
15437
		}
15513
		}
[+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"));
15518
	from = ast_strdupa(get_header(req, "From"));
15443

    
   
15519

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

    
   
15524

   
15449
	if (res) {
15525
	if (res) {
15450
		ao2_ref(msg, -1);
15526
		ast_msg_destroy(msg);
15451
	} else {
15527
	} else {
15452
		ast_msg_queue(msg);
15528
		ast_msg_queue(msg);
15453
	}
15529
	}
15454

    
   
15530

   
15455
	transmit_response(p, "202 Accepted", req);
15531
	transmit_response(p, "202 Accepted", req);
[+20] [20] 4533 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);
20065
				handle_response_subscribe(p, resp, rest, req, seqno);
19990
			else if (p->registry && sipmethod == SIP_REGISTER)
20066
			else if (p->registry && sipmethod == SIP_REGISTER)
19991
				res = handle_response_register(p, resp, rest, req, seqno);
20067
				res = handle_response_register(p, resp, rest, req, seqno);
19992
			else if (sipmethod == SIP_UPDATE) {
20068
			else if (sipmethod == SIP_UPDATE) {
19993
				handle_response_update(p, resp, rest, req, seqno);
20069
				handle_response_update(p, resp, rest, req, seqno);

    
   
20070
			} else if (sipmethod == SIP_MESSAGE) {

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

    
   
20425

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

    
   
20435

   
20358
	/* Any way back to the current call??? */
20436
	/* Any way back to the current call??? */
20359
	/* Transmit response to the REFER request */
20437
	/* Transmit response to the REFER request */
[+20] [20] 436 lines
[+20] [+] static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e)
20796
			transmit_response(p, "489 Bad event", req);
20874
			transmit_response(p, "489 Bad event", req);
20797
			res = -1;
20875
			res = -1;
20798
		}
20876
		}
20799
	} else if (!strcmp(event, "keep-alive")) {
20877
	} else if (!strcmp(event, "keep-alive")) {
20800
		 /* Used by Sipura/Linksys for NAT pinhole,
20878
		 /* Used by Sipura/Linksys for NAT pinhole,
20801
		  * just confirm that we recieved the packet. */
20879
		  * just confirm that we received the packet. */
20802
		transmit_response(p, "200 OK", req);
20880
		transmit_response(p, "200 OK", req);
20803
	} else if (!strcmp(event, "call-completion")) {
20881
	} else if (!strcmp(event, "call-completion")) {
20804
		res = handle_cc_notify(p, req);
20882
		res = handle_cc_notify(p, req);
20805
	} else {
20883
	} else {
20806
		/* We don't understand this event. */
20884
		/* We don't understand this event. */
[+20] [20] 1953 lines
[+20] [+] static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
22760
	}
22838
	}
22761

    
   
22839

   
22762
	return 1;
22840
	return 1;
22763
}
22841
}
22764

    
   
22842

   

    
   
22843
/*!

    
   
22844
 * \internal

    
   
22845
 * \brief Handle auth requests to a MESSAGE request

    
   
22846
 */

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

    
   
22848
{

    
   
22849
	char *header, *respheader;

    
   
22850
	char digest[1024];

    
   
22851

   

    
   
22852
	if (p->options) {

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

    
   
22854
	}

    
   
22855

   

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

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

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

    
   
22859
		return;

    
   
22860
	}

    
   
22861

   

    
   
22862
	p->authtries++;

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

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

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

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

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

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

    
   
22869
		return;

    
   
22870
	}

    
   
22871

   

    
   
22872
	if (p->do_history) {

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

    
   
22874
	}

    
   
22875

   

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

    
   
22877
}

    
   
22878

   
22765
/*! \brief Handle incoming MESSAGE request */
22879
/*! \brief Handle incoming MESSAGE request */
22766
static int handle_request_message(struct sip_pvt *p, struct sip_request *req)
22880
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
22767
{
22881
{
22768
	if (!req->ignore) {
22882
	if (!req->ignore) {
22769
		if (req->debug)
22883
		if (req->debug)
22770
			ast_verbose("Receiving message!\n");
22884
			ast_verbose("Receiving message!\n");
22771
		receive_message(p, req);
22885
		receive_message(p, req, addr, e);
22772
	} else
22886
	} else
22773
		transmit_response(p, "202 Accepted", req);
22887
		transmit_response(p, "202 Accepted", req);
22774
	return 1;
22888
	return 1;
22775
}
22889
}
22776

    
   
22890

   
[+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);
22927
	ast_sip_ouraddrfor(&pvt->sa, &pvt->ourip, pvt);
22814
	ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
22928
	ast_set_flag(&pvt->flags[0], SIP_OUTGOING);
22815

    
   
22929

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

    
   
22931

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

    
   
22933

   
22820
	sip_pvt_unlock(pvt);
22934
	sip_pvt_unlock(pvt);
22821
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);
22935
	sip_scheddestroy(pvt, DEFAULT_TRANS_TIMEOUT);
22822
	dialog_unref(pvt, "sent a MESSAGE");
22936
	dialog_unref(pvt, "sent a MESSAGE");
22823

    
   
22937

   
[+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 */
23849
/*! \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)
23850
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
23737
{
23851
{
23738
	enum check_auth_result res;
23852
	enum check_auth_result res;
23739

    
   
23853

   

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

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

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

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

    
   
23858
		return -1;

    
   
23859
	}

    
   
23860

   
23740
	/* Use this as the basis */
23861
	/* Use this as the basis */
23741
	copy_request(&p->initreq, req);
23862
	copy_request(&p->initreq, req);
23742
	if (sipdebug)
23863
	if (sipdebug)
23743
		ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
23864
		ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
23744
	check_via(p, req);
23865
	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;
24122
		break;
24002
	case SIP_BYE:
24123
	case SIP_BYE:
24003
		res = handle_request_bye(p, req);
24124
		res = handle_request_bye(p, req);
24004
		break;
24125
		break;
24005
	case SIP_MESSAGE:
24126
	case SIP_MESSAGE:
24006
		res = handle_request_message(p, req);
24127
		res = handle_request_message(p, req, addr, e);
24007
		break;
24128
		break;
24008
	case SIP_PUBLISH:
24129
	case SIP_PUBLISH:
24009
		res = handle_request_publish(p, req, addr, seqno, e);
24130
		res = handle_request_publish(p, req, addr, seqno, e);
24010
		break;
24131
		break;
24011
	case SIP_SUBSCRIBE:
24132
	case SIP_SUBSCRIBE:
[+20] [20] 2832 lines
[+20] [+] static int reload_config(enum channelreloadreason reason)
26844
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26965
	sip_cfg.notifycid = DEFAULT_NOTIFYCID;
26845
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26966
	sip_cfg.notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
26846
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26967
	sip_cfg.directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
26847
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26968
	sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
26848
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
26969
	sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;

    
   
26970
	sip_cfg.auth_message_requests = DEFAULT_AUTH_MESSAGE;

    
   
26971
	sip_cfg.accept_outofcall_message = DEFAULT_ACCEPT_OUTOFCALL_MESSAGE;
26849
	sip_cfg.allowsubscribe = FALSE;
26972
	sip_cfg.allowsubscribe = FALSE;
26850
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26973
	sip_cfg.disallowed_methods = SIP_UNKNOWN;
26851
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26974
	sip_cfg.contact_ha = NULL;		/* Reset the contact ACL */
26852
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26975
	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
26853
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
26976
	snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
[+20] [20] 236 lines
[+20] static int reload_config(enum channelreloadreason reason)
27090
			sip_cfg.alwaysauthreject = ast_true(v->value);
27213
			sip_cfg.alwaysauthreject = ast_true(v->value);
27091
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27214
		} else if (!strcasecmp(v->name, "auth_options_requests")) {
27092
			if (ast_true(v->value)) {
27215
			if (ast_true(v->value)) {
27093
				sip_cfg.auth_options_requests = 1;
27216
				sip_cfg.auth_options_requests = 1;
27094
			}
27217
			}

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

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

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

    
   
27221
			sip_cfg.accept_outofcall_message = ast_true(v->value) ? 1 : 0;
27095
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27222
		} else if (!strcasecmp(v->name, "mohinterpret")) {
27096
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27223
			ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
27097
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27224
		} else if (!strcasecmp(v->name, "mohsuggest")) {
27098
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27225
			ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
27099
		} else if (!strcasecmp(v->name, "language")) {
27226
		} else if (!strcasecmp(v->name, "language")) {
[+20] [20] 1484 lines
[+20] [+] static void sip_unregister_tests(void)
28584
	sip_request_parser_unregister_tests();
28711
	sip_request_parser_unregister_tests();
28585
	sip_dialplan_function_unregister_tests();
28712
	sip_dialplan_function_unregister_tests();
28586
}
28713
}
28587

    
   
28714

   
28588
#ifdef TEST_FRAMEWORK
28715
#ifdef TEST_FRAMEWORK

    
   
28716
AST_TEST_DEFINE(test_sip_mwi_subscribe_parse)

    
   
28717
{

    
   
28718
	int found = 0;

    
   
28719
	enum ast_test_result_state res = AST_TEST_PASS;

    
   
28720
	const char *mwi1 = "1234@mysipprovider.com/1234";

    
   
28721
	const char *mwi2 = "1234:password@mysipprovider.com/1234";

    
   
28722
	const char *mwi3 = "1234:password@mysipprovider.com:5061/1234";

    
   
28723
	const char *mwi4 = "1234:password:authuser@mysipprovider.com/1234";

    
   
28724
	const char *mwi5 = "1234:password:authuser@mysipprovider.com:5061/1234";

    
   
28725
	const char *mwi6 = "1234:password";

    
   
28726

   

    
   
28727
	switch (cmd) {

    
   
28728
	case TEST_INIT:

    
   
28729
		info->name = "sip_mwi_subscribe_parse_test";

    
   
28730
		info->category = "/channels/chan_sip/";

    
   
28731
		info->summary = "SIP MWI subscribe line parse unit test";

    
   
28732
		info->description =

    
   
28733
			"Tests the parsing of mwi subscription lines (e.g., mwi => from sip.conf)";

    
   
28734
		return AST_TEST_NOT_RUN;

    
   
28735
	case TEST_EXECUTE:

    
   
28736
		break;

    
   
28737
	}

    
   
28738

   

    
   
28739
	if (sip_subscribe_mwi(mwi1, 1)) {

    
   
28740
		res = AST_TEST_FAIL;

    
   
28741
	} else {

    
   
28742
		found = 0;

    
   
28743
		res = AST_TEST_FAIL;

    
   
28744
		ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {

    
   
28745
			ASTOBJ_WRLOCK(iterator);

    
   
28746
			if (

    
   
28747
				!strcmp(iterator->hostname, "mysipprovider.com") &&

    
   
28748
				!strcmp(iterator->username, "1234") &&

    
   
28749
				!strcmp(iterator->secret, "") &&

    
   
28750
				!strcmp(iterator->authuser, "") &&

    
   
28751
				!strcmp(iterator->mailbox, "1234") &&

    
   
28752
				iterator->portno == 0) {

    
   
28753
				found = 1;

    
   
28754
				res = AST_TEST_PASS;

    
   
28755
			}

    
   
28756
			ASTOBJ_UNLOCK(iterator);

    
   
28757
		} while(0));

    
   
28758
		if (!found) {

    
   
28759
			ast_test_status_update(test, "sip_subscribe_mwi test 1 failed\n");

    
   
28760
		}

    
   
28761
	}

    
   
28762

   

    
   
28763
	if (sip_subscribe_mwi(mwi2, 1)) {

    
   
28764
		res = AST_TEST_FAIL;

    
   
28765
	} else {

    
   
28766
		found = 0;

    
   
28767
		res = AST_TEST_FAIL;

    
   
28768
		ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {

    
   
28769
			ASTOBJ_WRLOCK(iterator);

    
   
28770
			if (

    
   
28771
				!strcmp(iterator->hostname, "mysipprovider.com") &&

    
   
28772
				!strcmp(iterator->username, "1234") &&

    
   
28773
				!strcmp(iterator->secret, "password") &&

    
   
28774
				!strcmp(iterator->authuser, "") &&

    
   
28775
				!strcmp(iterator->mailbox, "1234") &&

    
   
28776
				iterator->portno == 0) {

    
   
28777
				found = 1;

    
   
28778
				res = AST_TEST_PASS;

    
   
28779
			}

    
   
28780
			ASTOBJ_UNLOCK(iterator);

    
   
28781
		} while(0));

    
   
28782
		if (!found) {

    
   
28783
			ast_test_status_update(test, "sip_subscribe_mwi test 2 failed\n");

    
   
28784
		}

    
   
28785
	}

    
   
28786

   

    
   
28787
	if (sip_subscribe_mwi(mwi3, 1)) {

    
   
28788
		res = AST_TEST_FAIL;

    
   
28789
	} else {

    
   
28790
		found = 0;

    
   
28791
		res = AST_TEST_FAIL;

    
   
28792
		ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {

    
   
28793
			ASTOBJ_WRLOCK(iterator);

    
   
28794
			if (

    
   
28795
				!strcmp(iterator->hostname, "mysipprovider.com") &&

    
   
28796
				!strcmp(iterator->username, "1234") &&

    
   
28797
				!strcmp(iterator->secret, "password") &&

    
   
28798
				!strcmp(iterator->authuser, "") &&

    
   
28799
				!strcmp(iterator->mailbox, "1234") &&

    
   
28800
				iterator->portno == 5061) {

    
   
28801
				found = 1;

    
   
28802
				res = AST_TEST_PASS;

    
   
28803
			}

    
   
28804
			ASTOBJ_UNLOCK(iterator);

    
   
28805
		} while(0));

    
   
28806
		if (!found) {

    
   
28807
			ast_test_status_update(test, "sip_subscribe_mwi test 3 failed\n");

    
   
28808
		}

    
   
28809
	}

    
   
28810

   

    
   
28811
	if (sip_subscribe_mwi(mwi4, 1)) {

    
   
28812
		res = AST_TEST_FAIL;

    
   
28813
	} else {

    
   
28814
		found = 0;

    
   
28815
		res = AST_TEST_FAIL;

    
   
28816
		ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {

    
   
28817
			ASTOBJ_WRLOCK(iterator);

    
   
28818
			if (

    
   
28819
				!strcmp(iterator->hostname, "mysipprovider.com") &&

    
   
28820
				!strcmp(iterator->username, "1234") &&

    
   
28821
				!strcmp(iterator->secret, "password") &&

    
   
28822
				!strcmp(iterator->authuser, "authuser") &&

    
   
28823
				!strcmp(iterator->mailbox, "1234") &&

    
   
28824
				iterator->portno == 0) {

    
   
28825
				found = 1;

    
   
28826
				res = AST_TEST_PASS;

    
   
28827
			}

    
   
28828
			ASTOBJ_UNLOCK(iterator);

    
   
28829
		} while(0));

    
   
28830
		if (!found) {

    
   
28831
			ast_test_status_update(test, "sip_subscribe_mwi test 4 failed\n");

    
   
28832
		}

    
   
28833
	}

    
   
28834

   

    
   
28835
	if (sip_subscribe_mwi(mwi5, 1)) {

    
   
28836
		res = AST_TEST_FAIL;

    
   
28837
	} else {

    
   
28838
		found = 0;

    
   
28839
		res = AST_TEST_FAIL;

    
   
28840
		ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {

    
   
28841
			ASTOBJ_WRLOCK(iterator);

    
   
28842
			if (

    
   
28843
				!strcmp(iterator->hostname, "mysipprovider.com") &&

    
   
28844
				!strcmp(iterator->username, "1234") &&

    
   
28845
				!strcmp(iterator->secret, "password") &&

    
   
28846
				!strcmp(iterator->authuser, "authuser") &&

    
   
28847
				!strcmp(iterator->mailbox, "1234") &&

    
   
28848
				iterator->portno == 5061) {

    
   
28849
				found = 1;

    
   
28850
				res = AST_TEST_PASS;

    
   
28851
			}

    
   
28852
			ASTOBJ_UNLOCK(iterator);

    
   
28853
		} while(0));

    
   
28854
		if (!found) {

    
   
28855
			ast_test_status_update(test, "sip_subscribe_mwi test 5 failed\n");

    
   
28856
		}

    
   
28857
	}

    
   
28858
	

    
   
28859
	if (sip_subscribe_mwi(mwi6, 1)) {

    
   
28860
		res = AST_TEST_PASS;

    
   
28861
	} else {

    
   
28862
		res = AST_TEST_FAIL;

    
   
28863
	}

    
   
28864
	return res;

    
   
28865
}

    
   
28866

   
28589
AST_TEST_DEFINE(test_sip_peers_get)
28867
AST_TEST_DEFINE(test_sip_peers_get)
28590
{
28868
{
28591
	struct sip_peer *peer;
28869
	struct sip_peer *peer;
28592
	struct ast_data *node;
28870
	struct ast_data *node;
28593
	struct ast_data_query query = {
28871
	struct ast_data_query query = {
[+20] [20] 233 lines
[+20] [+] static int load_module(void)
28827
	threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table");
29105
	threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table");
28828
	
29106
	
28829
	ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
29107
	ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
28830
	ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
29108
	ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
28831

    
   
29109

   
28832
	if (!(sched = sched_context_create())) {
29110
	if (!(sched = ast_sched_context_create())) {
28833
		ast_log(LOG_ERROR, "Unable to create scheduler context\n");
29111
		ast_log(LOG_ERROR, "Unable to create scheduler context\n");
28834
		return AST_MODULE_LOAD_FAILURE;
29112
		return AST_MODULE_LOAD_FAILURE;
28835
	}
29113
	}
28836

    
   
29114

   
28837
	if (!(io = io_context_create())) {
29115
	if (!(io = io_context_create())) {
28838
		ast_log(LOG_ERROR, "Unable to create I/O context\n");
29116
		ast_log(LOG_ERROR, "Unable to create I/O context\n");
28839
		sched_context_destroy(sched);
29117
		ast_sched_context_destroy(sched);
28840
		return AST_MODULE_LOAD_FAILURE;
29118
		return AST_MODULE_LOAD_FAILURE;
28841
	}
29119
	}
28842

    
   
29120

   
28843
	sip_reloadreason = CHANNEL_MODULE_LOAD;
29121
	sip_reloadreason = CHANNEL_MODULE_LOAD;
28844

    
   
29122

   
[+20] [20] 16 lines
[+20] static int load_module(void)
28861

    
   
29139

   
28862
	/* Make sure we can register our sip channel type */
29140
	/* Make sure we can register our sip channel type */
28863
	if (ast_channel_register(&sip_tech)) {
29141
	if (ast_channel_register(&sip_tech)) {
28864
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
29142
		ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
28865
		io_context_destroy(io);
29143
		io_context_destroy(io);
28866
		sched_context_destroy(sched);
29144
		ast_sched_context_destroy(sched);
28867
		return AST_MODULE_LOAD_FAILURE;
29145
		return AST_MODULE_LOAD_FAILURE;
28868
	}
29146
	}
28869

    
   
29147

   
28870
#ifdef TEST_FRAMEWORK
29148
#ifdef TEST_FRAMEWORK
28871
	AST_TEST_REGISTER(test_sip_peers_get);
29149
	AST_TEST_REGISTER(test_sip_peers_get);

    
   
29150
	AST_TEST_REGISTER(test_sip_mwi_subscribe_parse);
28872
#endif
29151
#endif
28873

    
   
29152

   
28874
	/* Register AstData providers */
29153
	/* Register AstData providers */
28875
	ast_data_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers));
29154
	ast_data_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers));
28876

    
   
29155

   
[+20] [20] 55 lines
[+20] static int load_module(void)
28932
	/* And start the monitor for the first time */
29211
	/* And start the monitor for the first time */
28933
	restart_monitor();
29212
	restart_monitor();
28934

    
   
29213

   
28935
	ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers",
29214
	ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers",
28936
		"name", RQ_CHAR, 10,
29215
		"name", RQ_CHAR, 10,
28937
		"ipaddr", RQ_CHAR, 15,
29216
		"ipaddr", RQ_CHAR, INET6_ADDRSTRLEN - 1,
28938
		"port", RQ_UINTEGER2, 5,
29217
		"port", RQ_UINTEGER2, 5,
28939
		"regseconds", RQ_INTEGER4, 11,
29218
		"regseconds", RQ_INTEGER4, 11,
28940
		"defaultuser", RQ_CHAR, 10,
29219
		"defaultuser", RQ_CHAR, 10,
28941
		"fullcontact", RQ_CHAR, 35,
29220
		"fullcontact", RQ_CHAR, 35,
28942
		"regserver", RQ_CHAR, 20,
29221
		"regserver", RQ_CHAR, 20,
[+20] [20] 36 lines
[+20] [+] static int unload_module(void)
28979
	ast_unregister_application(app_sipaddheader);
29258
	ast_unregister_application(app_sipaddheader);
28980
	ast_unregister_application(app_sipremoveheader);
29259
	ast_unregister_application(app_sipremoveheader);
28981

    
   
29260

   
28982
#ifdef TEST_FRAMEWORK
29261
#ifdef TEST_FRAMEWORK
28983
	AST_TEST_UNREGISTER(test_sip_peers_get);
29262
	AST_TEST_UNREGISTER(test_sip_peers_get);

    
   
29263
	AST_TEST_UNREGISTER(test_sip_mwi_subscribe_parse);
28984
#endif
29264
#endif
28985
	/* Unregister all the AstData providers */
29265
	/* Unregister all the AstData providers */
28986
	ast_data_unregister(NULL);
29266
	ast_data_unregister(NULL);
28987

    
   
29267

   
28988
	/* Unregister CLI commands */
29268
	/* Unregister CLI commands */
[+20] [20] 93 lines
[+20] static int unload_module(void)
29082
	ao2_t_ref(threadt, -1, "unref the thread table");
29362
	ao2_t_ref(threadt, -1, "unref the thread table");
29083

    
   
29363

   
29084
	clear_sip_domains();
29364
	clear_sip_domains();
29085
	ast_free_ha(sip_cfg.contact_ha);
29365
	ast_free_ha(sip_cfg.contact_ha);
29086
	close(sipsock);
29366
	close(sipsock);
29087
	sched_context_destroy(sched);
29367
	ast_sched_context_destroy(sched);
29088
	con = ast_context_find(used_context);
29368
	con = ast_context_find(used_context);
29089
	if (con) {
29369
	if (con) {
29090
		ast_context_destroy(con, "SIP");
29370
		ast_context_destroy(con, "SIP");
29091
	}
29371
	}
29092
	ast_unload_realtime("sipregs");
29372
	ast_unload_realtime("sipregs");
[+20] [20] 17 lines
/trunk/channels/sip/include/sip.h
Diff Revision 1 Diff Revision 3
 
/trunk/configs/jabber.conf.sample
Diff Revision 1 Diff Revision 3
 
/trunk/configs/sip.conf.sample
Diff Revision 1 Diff Revision 3
 
/trunk/doc/asterisk-messaging.txt
Diff Revision 1 Diff Revision 3
 
/trunk/include/asterisk/_private.h
Diff Revision 1 Diff Revision 3
 
/trunk/include/asterisk/channel.h
Diff Revision 1 Diff Revision 3
 
/trunk/include/asterisk/jabber.h
Diff Revision 1 Diff Revision 3
 
/trunk/include/asterisk/message.h
Diff Revision 1 Diff Revision 3
 
/trunk/main/asterisk.c
Diff Revision 1 Diff Revision 3
 
/trunk/main/channel.c
Diff Revision 1 Diff Revision 3
 
/trunk/main/message.c
Diff Revision 1 Diff Revision 3
 
/trunk/res/res_jabber.c
Diff Revision 1 Diff Revision 3
 
/trunk/testsuite-tests/message_from_call/run-test
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_from_call/test-config.yaml
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_from_call/configs/ast1/extensions.conf
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_from_call/sipp/call.xml
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_from_call/sipp/message_recv.xml
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_unauth/run-test
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_unauth/test-config.yaml
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_unauth/configs/ast1/extensions.conf
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_unauth/sipp/message.xml
Diff Revision 1 Diff Revision 3 - File Reverted
 
/trunk/testsuite-tests/message_unauth/sipp/message_recv.xml
Diff Revision 1 Diff Revision 3 - 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/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...
  14. /trunk/testsuite-tests/message_from_call/run-test: Loading...
  15. /trunk/testsuite-tests/message_from_call/test-config.yaml: Loading...
  16. /trunk/testsuite-tests/message_from_call/configs/ast1/extensions.conf: Loading...
  17. /trunk/testsuite-tests/message_from_call/sipp/call.xml: Loading...
  18. /trunk/testsuite-tests/message_from_call/sipp/message_recv.xml: Loading...
  19. /trunk/testsuite-tests/message_unauth/run-test: Loading...
  20. /trunk/testsuite-tests/message_unauth/test-config.yaml: Loading...
  21. /trunk/testsuite-tests/message_unauth/configs/ast1/extensions.conf: Loading...
  22. /trunk/testsuite-tests/message_unauth/sipp/message.xml: Loading...
  23. /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.