|  |  |  | @ -106,8 +106,9 @@ static const char *skip_sip(const char *fromto) | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * Expects the given 'to' to be in one of the following formats: | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:endpoint[/aor] | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:endpoint[/uri] | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:uri <-- will use default outbound endpoint | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:endpoint[/uri] - Where uri is: sip[s]:user@domain | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:endpoint[@domain] | 
			
		
	
		
			
				
					|  |  |  |  |  *      sip[s]:unknown_user@domain <-- will use default outbound endpoint | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * If an optional aor is given it will try to find an associated uri | 
			
		
	
		
			
				
					|  |  |  |  |  * to return.  If an optional uri is given then that will be returned, | 
			
		
	
	
		
			
				
					|  |  |  | @ -116,50 +117,60 @@ static const char *skip_sip(const char *fromto) | 
			
		
	
		
			
				
					|  |  |  |  |  * \param to 'From' or 'To' field with possible endpoint | 
			
		
	
		
			
				
					|  |  |  |  |  * \param uri Optional uri to return | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static struct ast_sip_endpoint* get_outbound_endpoint( | 
			
		
	
		
			
				
					|  |  |  |  | 	const char *to, char **uri) | 
			
		
	
		
			
				
					|  |  |  |  | static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	char *name, *aor_uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *name; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *aor_uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_sip_endpoint *endpoint; | 
			
		
	
		
			
				
					|  |  |  |  | 	RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup); | 
			
		
	
		
			
				
					|  |  |  |  | 	RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	name = ast_strdupa(skip_sip(to)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/* attempt to extract the endpoint name */ | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((aor_uri = strchr(name, '/'))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* format was 'endpoint/' */ | 
			
		
	
		
			
				
					|  |  |  |  | 		/* format was 'endpoint/(aor_name | uri)' */ | 
			
		
	
		
			
				
					|  |  |  |  | 		*aor_uri++ = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if ((aor_uri = strchr(name, '@'))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* format was 'endpoint@' - don't use the rest */ | 
			
		
	
		
			
				
					|  |  |  |  | 		/* format was 'endpoint@domain' - discard the domain */ | 
			
		
	
		
			
				
					|  |  |  |  | 		*aor_uri = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/* at this point, if name is not empty then it
 | 
			
		
	
		
			
				
					|  |  |  |  | 	   might be an endpoint, so try to retrieve it */ | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_strlen_zero(name) || !(endpoint = ast_sorcery_retrieve_by_id( | 
			
		
	
		
			
				
					|  |  |  |  | 		      ast_sip_get_sorcery(), "endpoint", name))) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_strlen_zero(name) | 
			
		
	
		
			
				
					|  |  |  |  | 		|| !(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", | 
			
		
	
		
			
				
					|  |  |  |  | 			name))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* an endpoint was not found, so assume sending directly
 | 
			
		
	
		
			
				
					|  |  |  |  | 		   to a uri and use the default outbound endpoint */ | 
			
		
	
		
			
				
					|  |  |  |  | 		*uri = ast_strdup(to); | 
			
		
	
		
			
				
					|  |  |  |  | 		return ast_sip_default_outbound_endpoint(); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	*uri = aor_uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	if (*uri) { | 
			
		
	
		
			
				
					|  |  |  |  | 		char *end = strchr(*uri, '>'); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_strlen_zero(aor_uri)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		*uri = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		struct ast_sip_aor *aor; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct ast_sip_contact *contact = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		char *end; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		/* Trim off any stray angle bracket that shouldn't be here */ | 
			
		
	
		
			
				
					|  |  |  |  | 		end = strchr(aor_uri, '>'); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (end) { | 
			
		
	
		
			
				
					|  |  |  |  | 			*end++ = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  | 			*end = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		/* if what's in 'uri' is a retrievable aor use the uri on it
 | 
			
		
	
		
			
				
					|  |  |  |  | 		   instead, otherwise assume what's there is already a uri*/ | 
			
		
	
		
			
				
					|  |  |  |  | 		if ((aor = ast_sip_location_retrieve_aor(*uri)) && | 
			
		
	
		
			
				
					|  |  |  |  | 			(contact = ast_sip_location_retrieve_first_aor_contact(aor))) { | 
			
		
	
		
			
				
					|  |  |  |  | 			*uri = (char*)contact->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 		/*
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * if what's in 'uri' is a retrievable aor use the uri on it | 
			
		
	
		
			
				
					|  |  |  |  | 		 * instead, otherwise assume what's there is already a uri | 
			
		
	
		
			
				
					|  |  |  |  | 		 */ | 
			
		
	
		
			
				
					|  |  |  |  | 		aor = ast_sip_location_retrieve_aor(aor_uri); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (aor && (contact = ast_sip_location_retrieve_first_aor_contact(aor))) { | 
			
		
	
		
			
				
					|  |  |  |  | 			aor_uri = (char *) contact->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		/* need to copy because underlying uri goes away */ | 
			
		
	
		
			
				
					|  |  |  |  | 		*uri = ast_strdup(*uri); | 
			
		
	
		
			
				
					|  |  |  |  | 		*uri = ast_strdup(aor_uri); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		ao2_cleanup(contact); | 
			
		
	
		
			
				
					|  |  |  |  | 		ao2_cleanup(aor); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return endpoint; | 
			
		
	
	
		
			
				
					|  |  |  | @ -176,16 +187,16 @@ static struct ast_sip_endpoint* get_outbound_endpoint( | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static void update_to(pjsip_tx_data *tdata, char *to) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_name_addr *name_addr = (pjsip_name_addr *) | 
			
		
	
		
			
				
					|  |  |  |  | 		PJSIP_MSG_TO_HDR(tdata->msg)->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_uri *parsed; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_name_addr *parsed_name_addr; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((parsed = pjsip_parse_uri(tdata->pool, to, strlen(to), | 
			
		
	
		
			
				
					|  |  |  |  | 				      PJSIP_PARSE_URI_AS_NAMEADDR))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		pjsip_name_addr *parsed_name_addr = (pjsip_name_addr *)parsed; | 
			
		
	
		
			
				
					|  |  |  |  | 	parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to), | 
			
		
	
		
			
				
					|  |  |  |  | 		PJSIP_PARSE_URI_AS_NAMEADDR); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (parsed_name_addr) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (pj_strlen(&parsed_name_addr->display)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup(tdata->pool, &name_addr->display, | 
			
		
	
		
			
				
					|  |  |  |  | 				  &parsed_name_addr->display); | 
			
		
	
		
			
				
					|  |  |  |  | 			pjsip_name_addr *name_addr = | 
			
		
	
		
			
				
					|  |  |  |  | 				(pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | @ -204,22 +215,24 @@ static void update_to(pjsip_tx_data *tdata, char *to) | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static void update_from(pjsip_tx_data *tdata, char *from) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_name_addr *name_addr = (pjsip_name_addr *) | 
			
		
	
		
			
				
					|  |  |  |  | 		PJSIP_MSG_FROM_HDR(tdata->msg)->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr); | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_uri *parsed; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_name_addr *name_addr; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_sip_uri *uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_name_addr *parsed_name_addr; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_strlen_zero(from)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((parsed = pjsip_parse_uri(tdata->pool, from, strlen(from), | 
			
		
	
		
			
				
					|  |  |  |  | 				      PJSIP_PARSE_URI_AS_NAMEADDR))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		pjsip_name_addr *parsed_name_addr = (pjsip_name_addr *)parsed; | 
			
		
	
		
			
				
					|  |  |  |  | 	name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri; | 
			
		
	
		
			
				
					|  |  |  |  | 	uri = pjsip_uri_get_uri(name_addr); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from, | 
			
		
	
		
			
				
					|  |  |  |  | 		strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (parsed_name_addr) { | 
			
		
	
		
			
				
					|  |  |  |  | 		pjsip_sip_uri *parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (pj_strlen(&parsed_name_addr->display)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup(tdata->pool, &name_addr->display, | 
			
		
	
		
			
				
					|  |  |  |  | 				  &parsed_name_addr->display); | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		pj_strdup(tdata->pool, &uri->user, &parsed_uri->user); | 
			
		
	
	
		
			
				
					|  |  |  | @ -228,13 +241,19 @@ static void update_from(pjsip_tx_data *tdata, char *from) | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* assume it is 'user[@domain]' format */ | 
			
		
	
		
			
				
					|  |  |  |  | 		char *domain = strchr(from, '@'); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (domain) { | 
			
		
	
		
			
				
					|  |  |  |  | 			*domain++ = '\0'; | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup2(tdata->pool, &uri->host, domain); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_str_t pj_from; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strset3(&pj_from, from, domain); | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup(tdata->pool, &uri->user, &pj_from); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup2(tdata->pool, &uri->host, domain + 1); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			pj_strdup2(tdata->pool, &uri->user, from); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /*!
 | 
			
		
	
		
			
				
					|  |  |  |  |  * \internal | 
			
		
	
	
		
			
				
					|  |  |  | @ -538,15 +557,15 @@ static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *t | 
			
		
	
		
			
				
					|  |  |  |  | 	/* typecast to suppress const warning */ | 
			
		
	
		
			
				
					|  |  |  |  | 	mdata->msg = ast_msg_ref((struct ast_msg *) msg); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/* starts with 'pjsip:' the 'pj' needs to be removed and maybe even
 | 
			
		
	
		
			
				
					|  |  |  |  | 	   the entire string. */ | 
			
		
	
		
			
				
					|  |  |  |  | 	/* To starts with 'pjsip:' which needs to be removed. */ | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!(to = strchr(to, ':'))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ao2_ref(mdata, -1); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	++to;/* Now skip the ':' */ | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/* Make sure we start with sip: */ | 
			
		
	
		
			
				
					|  |  |  |  | 	mdata->to = ast_begins_with(to, "sip:") ? ast_strdup(++to) : ast_strdup(to - 3); | 
			
		
	
		
			
				
					|  |  |  |  | 	mdata->to = ast_begins_with(to, "sip:") ? ast_strdup(to) : ast_strdup(to - 4); | 
			
		
	
		
			
				
					|  |  |  |  | 	mdata->from = ast_strdup(from); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!mdata->to || !mdata->from) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ao2_ref(mdata, -1); | 
			
		
	
	
		
			
				
					|  |  |  | @ -572,12 +591,13 @@ static int msg_send(void *data) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	pjsip_tx_data *tdata; | 
			
		
	
		
			
				
					|  |  |  |  | 	RAII_VAR(char *, uri, NULL, ast_free); | 
			
		
	
		
			
				
					|  |  |  |  | 	RAII_VAR(struct ast_sip_endpoint *, endpoint, get_outbound_endpoint( | 
			
		
	
		
			
				
					|  |  |  |  | 			 mdata->to, &uri), ao2_cleanup); | 
			
		
	
		
			
				
					|  |  |  |  | 	RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	endpoint = get_outbound_endpoint(mdata->to, &uri); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!endpoint) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not find endpoint '%s' and " | 
			
		
	
		
			
				
					|  |  |  |  | 			"no default outbound endpoint configured\n", mdata->to); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_ERROR, | 
			
		
	
		
			
				
					|  |  |  |  | 			"PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n", | 
			
		
	
		
			
				
					|  |  |  |  | 			mdata->to); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |