Review Board 1.7.16


Use SIPS Contact headers as prescribed by RFC 3261 (res_pjsip)

Review Request #4345 - Created Jan. 15, 2015 and submitted

Mark Michelson
/branches/13/
ASTERISK-24646
Reviewers
asterisk-dev
Asterisk
PJSIP introduced a change prior to the 2.3 release that made their INVITE-handling code RFC compliant with regards to checking for SIPS URIs in Contact headers of received requests/responses. Specifically, they added checks for languaged outlined in RFC 3261 section 8.1.1.8 and 12.1.1. A simplified version of what PJSIP does is the following:

* On incoming INVITE and UPDATE requests, if the request URI is SIPS but the Contact header is not, then the request receives a 480 response
* On an incoming 200 OK response to an INVITE or UPDATE, if the request URI is SIPS but the Contact header is not, then PJSIP issues an immediate BYE to end the session.

For softphones that use PJSIP, this means they have trouble interoperating with Asterisk. This is because Asterisk never places a SIPS URI in a contact header. So if a client using PJSIP sends an INVITE to a SIPS URI in Asterisk, we were responding with a non-SIPS Contact header. The PJSIP client would then immediately send a BYE terminating the call.

This patch aims to fix this issue by implementing requirements of RFC 3261 sections 8.1.1.8 and 12.1.1
* There is a new module that registers a service that operates on all outgoing requests. If the request is to a SIPS URI, or if the topmost Route header is a SIPS URI, then we set our Contact header to a SIPS URI.
* The code that creates a UAS dialog will create the local Contact header based on whether the Request-URI or the topmost Record-Route URI is a SIPS URI.

For this patch, I have elected to keep the ;transport=tls parameter in the Contact header since I have a feeling removing it will cause more trouble than it actually fixes.

A similar patch against chan_sip for the 11 branch is posted at /r/4346
Honestly, not much. It compiles. I attempted to set up a TLS client (Jitsi, to be specific), but failed. I got no help from either Asterisk or Jitsi to explain what was going wrong. In the end, I gave that up.

What I was able to do, oddly, was use SIPp to send a SIP INVITE to Asterisk over UDP using a SIPS Request URI. I then was able to make sure that Asterisk sent a SIPS contact header back in the 200 OK. I'm not making a testsuite test out of this though because it feels like a bug that I can send a request to a SIPS URI over UDP and that Asterisk will accept the request.
/branches/13/res/res_pjsip.c
Revision 430625 New Change
[20] 2256 lines
[+20] [+] pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user)
2257
	dlg->sess_count--;
2257
	dlg->sess_count--;
2258

    
   
2258

   
2259
	return dlg;
2259
	return dlg;
2260
}
2260
}
2261

    
   
2261

   

    
   
2262
/*!

    
   
2263
 * \brief Determine if a SIPS Contact header is required.

    
   
2264
 *

    
   
2265
 * This uses the guideline provided in RFC 3261 Section 12.1.1 to

    
   
2266
 * determine if the Contact header must be a sips: URI.

    
   
2267
 *

    
   
2268
 * \param rdata The incoming dialog-starting request

    
   
2269
 * \retval 0 SIPS not required

    
   
2270
 * \retval 1 SIPS required

    
   
2271
 */

    
   
2272
static int uas_use_sips_contact(pjsip_rx_data *rdata)

    
   
2273
{

    
   
2274
	pjsip_rr_hdr *record_route;

    
   
2275

   

    
   
2276
	if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {

    
   
2277
		return 1;

    
   
2278
	}

    
   
2279

   

    
   
2280
	record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);

    
   
2281
	if (record_route) {

    
   
2282
		if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {

    
   
2283
			return 1;

    
   
2284
		}

    
   
2285
	} else {

    
   
2286
		pjsip_contact_hdr *contact;

    
   
2287

   

    
   
2288
		contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);

    
   
2289
		ast_assert(contact != NULL);

    
   
2290
		if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {

    
   
2291
			return 1;

    
   
2292
		}

    
   
2293
	}

    
   
2294

   

    
   
2295
	return 0;

    
   
2296
}

    
   
2297

   
2262
pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
2298
pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
2263
{
2299
{
2264
	pjsip_dialog *dlg;
2300
	pjsip_dialog *dlg;
2265
	pj_str_t contact;
2301
	pj_str_t contact;
2266
	pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
2302
	pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
2267

    
   
2303

   
2268
	ast_assert(status != NULL);
2304
	ast_assert(status != NULL);
2269

    
   
2305

   
2270
	contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
2306
	contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
2271
	contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
2307
	contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
2272
			"<sip:%s%.*s%s:%d%s%s>",
2308
			"<%s:%s%.*s%s:%d%s%s>",

    
   
2309
			uas_use_sips_contact(rdata) ? "sips" : "sip",
2273
			(type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
2310
			(type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
2274
			(int)rdata->tp_info.transport->local_name.host.slen,
2311
			(int)rdata->tp_info.transport->local_name.host.slen,
2275
			rdata->tp_info.transport->local_name.host.ptr,
2312
			rdata->tp_info.transport->local_name.host.ptr,
2276
			(type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
2313
			(type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
2277
			rdata->tp_info.transport->local_name.port,
2314
			rdata->tp_info.transport->local_name.port,
[+20] [20] 992 lines
/branches/13/res/res_pjsip_sips_contact.c
New File
 
  1. /branches/13/res/res_pjsip.c: Loading...
  2. /branches/13/res/res_pjsip_sips_contact.c: Loading...

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