--- asterisk-15.2.2/res/res_pjsip_dialog_info_body_generator.c 2018-02-21 12:06:14.000000000 -0700 +++ asterisk-15.2.2/res/res_pjsip_dialog_info_body_generator.c 2018-07-09 10:56:13.462592499 -0600 @@ -31,6 +31,7 @@ #include #include "asterisk/module.h" +#include "asterisk/callerid.h" #include "asterisk/res_pjsip.h" #include "asterisk/res_pjsip_pubsub.h" #include "asterisk/res_pjsip_presence_xml.h" @@ -98,19 +99,67 @@ return 0; } +/*! + * * \internal + * * \brief Find the channel that is causing the RINGING update, ref'd + * */ +static struct ast_channel *find_ringing_channel(struct ao2_container *device_state_info) +{ + struct ao2_iterator citer; + struct ast_device_state_info *device_state; + struct ast_channel *c = NULL; + struct timeval tv = {0,}; + + /* iterate ringing devices and get the oldest of all causing channels */ + citer = ao2_iterator_init(device_state_info, 0); + for (; (device_state = ao2_iterator_next(&citer)); ao2_ref(device_state, -1)) { + if (!device_state->causing_channel || (device_state->device_state != AST_DEVICE_RINGING && + device_state->device_state != AST_DEVICE_RINGINUSE)) { + continue; + } + ast_channel_lock(device_state->causing_channel); + if (ast_tvzero(tv) || ast_tvcmp(ast_channel_creationtime(device_state->causing_channel), tv) < 0) { + c = device_state->causing_channel; + tv = ast_channel_creationtime(c); + } + ast_channel_unlock(device_state->causing_channel); + } + ao2_iterator_destroy(&citer); + return c ? ast_channel_ref(c) : NULL; +} + +/* +static int get_domain_from_uri(pjsip_uri *from, char *domain, size_t domain_size) +{ + pjsip_sip_uri *sip_from; + + if (from == NULL || + (!PJSIP_URI_SCHEME_IS_SIP(from) && !PJSIP_URI_SCHEME_IS_SIPS(from))) { + return -1; + } + sip_from = (pjsip_sip_uri *) pjsip_uri_get_uri(from); + ast_copy_pj_str(domain, &sip_from->host, domain_size); + return 1; +} +*/ + static int dialog_info_generate_body_content(void *body, void *data) { - pj_xml_node *dialog_info = body, *dialog, *state; + pj_xml_node *dialog_info = body, *dialog, *state, *remote_node, *local_node, *remote_identity_node, *remote_target_node, *local_identity_node, *local_target_node; struct ast_sip_exten_state_data *state_data = data; char *local = ast_strdupa(state_data->local), *stripped, *statestring = NULL; + char *remote = ast_strdupa(state_data->remote), *stripped_remote; char *pidfstate = NULL, *pidfnote = NULL; enum ast_sip_pidf_state local_state; unsigned int version; - char version_str[32], sanitized[PJSIP_MAX_URL_SIZE]; + char version_str[32], remote_target[PJSIP_MAX_URL_SIZE], sanitized[PJSIP_MAX_URL_SIZE], sanitized_remote[PJSIP_MAX_URL_SIZE]; struct ast_sip_endpoint *endpoint = NULL; unsigned int notify_early_inuse_ringing = 0; + struct ast_channel *callee; + const char *from_domain = NULL; + static char *invalid = "anonymous.invalid"; - if (!local || !state_data->datastores) { + if (!local || !remote || !state_data->datastores) { return -1; } @@ -120,10 +169,13 @@ } stripped = ast_strip_quoted(local, "<", ">"); + stripped_remote = ast_strip_quoted(remote, "<", ">"); ast_sip_sanitize_xml(stripped, sanitized, sizeof(sanitized)); + ast_sip_sanitize_xml(stripped_remote, sanitized_remote, sizeof(sanitized_remote)); if (state_data->sub && (endpoint = ast_sip_subscription_get_endpoint(state_data->sub))) { notify_early_inuse_ringing = endpoint->notify_early_inuse_ringing; + from_domain = endpoint ? (!ast_strlen_zero(endpoint->fromdomain) ? endpoint->fromdomain : invalid) : NULL; ao2_cleanup(endpoint); } ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, @@ -141,6 +193,78 @@ ast_sip_presence_xml_create_attr(state_data->pool, dialog, "id", state_data->exten); if (!ast_strlen_zero(statestring) && !strcmp(statestring, "early")) { ast_sip_presence_xml_create_attr(state_data->pool, dialog, "direction", "recipient"); + + callee = find_ringing_channel(state_data->device_state_info); + + if (callee) { + remote_node = ast_sip_presence_xml_create_node(state_data->pool, dialog, "remote"); + remote_identity_node = ast_sip_presence_xml_create_node(state_data->pool, remote_node, "identity"); + remote_target_node = ast_sip_presence_xml_create_node(state_data->pool, remote_node, "target"); + + static char *anonymous = "anonymous"; + char *cid_num; + char *cid_name; + char *connected_num; + // pjsip_uri *parsed_uri; + int need; + int cid_num_restricted, connected_num_restricted; + // char from_domain[255 + 1]; + + ast_log(LOG_WARNING, "From Domain emote URI domain '%s'\n", sanitized_remote); + /* + parsed_uri = pjsip_parse_uri(state_data->pool, sanitized_remote, sizeof(sanitized_remote), 0); + if (!get_domain_from_uri(parsed_uri, from_domain, sizeof(from_domain))) { + ast_log(LOG_WARNING, "could not determine remote URI\n"); + return -1; + } else { + ast_log(LOG_WARNING, "Remote URI domain '%s'\n", from_domain); + } + */ + + ast_channel_lock(callee); + + cid_num_restricted = (ast_channel_caller(callee)->id.number.presentation & + AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED; + cid_num = S_COR(ast_channel_caller(callee)->id.number.valid, + S_COR(cid_num_restricted, anonymous, + ast_channel_caller(callee)->id.number.str), ""); + + cid_name = S_COR(ast_channel_connected(callee)->id.name.valid, + S_COR((ast_channel_connected(callee)->id.name.presentation & + AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED, anonymous, + ast_channel_connected(callee)->id.name.str), ""); + + need = strlen(cid_num) + (cid_num_restricted ? strlen(invalid) : + strlen(from_domain)) + sizeof("sip:@"); + + connected_num_restricted = (ast_channel_connected(callee)->id.number.presentation & + AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED; + connected_num = S_COR(ast_channel_connected(callee)->id.number.valid, + S_COR(connected_num_restricted, anonymous, + ast_channel_connected(callee)->id.number.str), ""); + + need = strlen(connected_num) + (connected_num_restricted ? strlen(invalid) : + strlen(from_domain)) + sizeof("sip:@"); + // remote_target = ast_alloca(need); + + snprintf(remote_target, need, "sip:%s@%s", connected_num, + connected_num_restricted ? invalid : from_domain); + + ast_channel_unlock(callee); + callee = ast_channel_unref(callee); + + pj_strdup2(state_data->pool, &remote_identity_node->content, remote_target); + ast_sip_presence_xml_create_attr(state_data->pool, remote_identity_node, "display", cid_name); + ast_sip_presence_xml_create_attr(state_data->pool, remote_target_node, "uri", remote_target); + } + + local_node = ast_sip_presence_xml_create_node(state_data->pool, dialog, "local"); + local_identity_node = ast_sip_presence_xml_create_node(state_data->pool, local_node, "identity"); + local_target_node = ast_sip_presence_xml_create_node(state_data->pool, local_node, "target"); + + pj_strdup2(state_data->pool, &local_identity_node->content, sanitized); + ast_sip_presence_xml_create_attr(state_data->pool, local_target_node, "uri", sanitized); + } state = ast_sip_presence_xml_create_node(state_data->pool, dialog, "state");