/*!
 * \internal
 * \brief Create an identity header for an outgoing message
 * \param hdr_name The name of the header to create
 * \param tdata The message to place the header on
 * \param id The identification information for the new header
 * \return newly-created header
 */
static pjsip_fromto_hdr *create_new_id_hdr(const pj_str_t *hdr_name, pjsip_tx_data *tdata, const struct ast_party_id *id)
{
	pjsip_fromto_hdr *id_hdr;
	pjsip_fromto_hdr *base;
	pjsip_name_addr *id_name_addr;
	pjsip_sip_uri *id_uri;

	base = tdata->msg->type == PJSIP_REQUEST_MSG ? PJSIP_MSG_FROM_HDR(tdata->msg) :
		PJSIP_MSG_TO_HDR(tdata->msg);
	id_hdr = pjsip_from_hdr_create(tdata->pool);
	id_hdr->type = PJSIP_H_OTHER;
	pj_strdup(tdata->pool, &id_hdr->name, hdr_name);
	id_hdr->sname.slen = 0;

	id_name_addr = pjsip_uri_clone(tdata->pool, base->uri);
	id_uri = pjsip_uri_get_uri(id_name_addr->uri);

	if (id->name.valid) {
		int name_buf_len = strlen(id->name.str) * 2 + 1;
		char *name_buf = ast_alloca(name_buf_len);

		ast_escape_quoted(id->name.str, name_buf, name_buf_len);
		pj_strdup2(tdata->pool, &id_name_addr->display, name_buf);
	}

	pj_strdup2(tdata->pool, &id_uri->user, id->number.str);

	id_hdr->uri = (pjsip_uri *) id_name_addr;
	return id_hdr;
}
示例#2
1
/*!
 * \internal
 * \brief Adds diversion header information to an outbound SIP message
 *
 * \param tdata The outbound message
 * \param data The redirecting data used to fill parts of the diversion header
 */
static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
{
	pjsip_fromto_hdr *hdr;
	pjsip_name_addr *name_addr;
	pjsip_sip_uri *uri;
	pjsip_param *param;
	pjsip_fromto_hdr *old_hdr;
	const char *reason_str;
	const char *quote_str;
	char *reason_buf;

	struct ast_party_id *id = &data->from;
	pjsip_uri *base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;

	if (!id->number.valid || ast_strlen_zero(id->number.str)) {
		return;
	}

	hdr = pjsip_from_hdr_create(tdata->pool);
	hdr->type = PJSIP_H_OTHER;
	pj_strdup(tdata->pool, &hdr->name, &diversion_name);
	hdr->sname = hdr->name;

	name_addr = pjsip_uri_clone(tdata->pool, base);
	uri = pjsip_uri_get_uri(name_addr->uri);

	pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
	pj_strdup2(tdata->pool, &uri->user, id->number.str);

	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
	param->name = pj_str("reason");

	reason_str = reason_code_to_str(&data->reason);

	/* Reason is either already quoted or it is a token to not need quotes added. */
	quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";

	reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
	sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */

	param->value = pj_str(reason_buf);

	pj_list_insert_before(&hdr->other_param, param);

	hdr->uri = (pjsip_uri *) name_addr;
	old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &diversion_name, NULL);
	if (old_hdr) {
		pj_list_erase(old_hdr);
	}
	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
}
/*!
 * \internal
 * \brief Overwrite fields in the outbound 'From' header
 *
 * The outbound 'From' header is created/added in ast_sip_create_request with
 * default data.  If available that data may be info specified in the 'from_user'
 * and 'from_domain' options found on the endpoint.  That information will be
 * overwritten with data in the given 'from' parameter.
 *
 * \param tdata the outbound message data structure
 * \param from info to copy into the header
 */
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;

	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;
		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, &uri->user, &parsed_uri->user);
		pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
		uri->port = parsed_uri->port;
	} else {
		/* assume it is 'user[@domain]' format */
		char *domain = strchr(from, '@');
		if (domain) {
			*domain++ = '\0';
			pj_strdup2(tdata->pool, &uri->host, domain);
		}
		pj_strdup2(tdata->pool, &uri->user, from);
	}
}
示例#4
0
/// Determine the served user for originating requests.
pjsip_uri* PJUtils::orig_served_user(pjsip_msg* msg)
{
  // The served user for originating requests is determined from the
  // P-Served-User or P-Asserted-Identity headers.  For extra compatibility,
  // we will also look at the From header if neither of the IMS headers is
  // present.
  pjsip_uri* uri = NULL;
  pjsip_routing_hdr* served_user = (pjsip_routing_hdr*)
                     pjsip_msg_find_hdr_by_name(msg, &STR_P_SERVED_USER, NULL);

  if (served_user != NULL)
  {
    uri = (pjsip_uri*)pjsip_uri_get_uri(&served_user->name_addr);
    LOG_DEBUG("Served user from P-Served-User header");
  }

  if (uri == NULL)
  {
    // No P-Served-User header present, so check for P-Asserted-Identity
    // header.
    pjsip_routing_hdr* asserted_id = (pjsip_routing_hdr*)
               pjsip_msg_find_hdr_by_name(msg, &STR_P_ASSERTED_IDENTITY, NULL);

    if (asserted_id != NULL)
    {
      uri = (pjsip_uri*)pjsip_uri_get_uri(&asserted_id->name_addr);
      LOG_DEBUG("Served user from P-Asserted-Identity header");
    }
  }

  if (uri == NULL)
  {
    // Neither IMS header is present, so use the From header.  This isn't
    // strictly speaking IMS compliant.
    LOG_DEBUG("From header %p", PJSIP_MSG_FROM_HDR(msg));
    uri = (pjsip_uri*)pjsip_uri_get_uri(PJSIP_MSG_FROM_HDR(msg)->uri);
    LOG_DEBUG("Served user from From header (%p)", uri);
  }

  return uri;
}
示例#5
0
/// Apply the mangalgorithm to the From tag, To tag (if present) and call ID of
/// req.
void MangelwurzelTsx::mangle_dialog_identifiers(pjsip_msg* req, pj_pool_t* pool)
{
  pjsip_from_hdr* from_hdr = PJSIP_MSG_FROM_HDR(req);

  if (from_hdr != NULL)
  {
    std::string from_tag = PJUtils::pj_str_to_string(&from_hdr->tag);
    mangle_string(from_tag);
    TRC_DEBUG("From tag mangled to %s", from_tag.c_str());
    from_hdr->tag = pj_strdup3(pool, from_tag.c_str());
  }

  pjsip_to_hdr* to_hdr = PJSIP_MSG_TO_HDR(req);

  if (to_hdr != NULL)
  {
    std::string to_tag = PJUtils::pj_str_to_string(&to_hdr->tag);
    mangle_string(to_tag);
    TRC_DEBUG("To tag mangled to %s", to_tag.c_str());
    to_hdr->tag = pj_strdup3(pool, to_tag.c_str());
  }

  pjsip_cid_hdr* cid_hdr = (pjsip_cid_hdr*)pjsip_msg_find_hdr(req,
                                                              PJSIP_H_CALL_ID,
                                                              NULL);
  if (cid_hdr != NULL)
  {
    std::string call_id = PJUtils::pj_str_to_string(&cid_hdr->id);
    mangle_string(call_id);
    TRC_DEBUG("Call ID manged to %s", call_id.c_str());
    cid_hdr->id = pj_strdup3(pool, call_id.c_str());

    // Report a SAS marker for the new call ID so that the two dialogs can be
    // correlated in SAS.
    TRC_DEBUG("Logging SAS Call-ID marker, Call-ID %.*s",
              cid_hdr->id.slen,
              cid_hdr->id.ptr);
    SAS::Marker cid_marker(trail(), MARKER_ID_SIP_CALL_ID, 1u);
    cid_marker.add_var_param(cid_hdr->id.slen, cid_hdr->id.ptr);
    SAS::report_marker(cid_marker, SAS::Marker::Scope::Trace);
  }
}
static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
{
	char local_buf[256];
	char remote_buf[256];
	char *uuid;
	struct hepv3_capture_info *capture_info;
	pjsip_cid_hdr *cid_hdr;
	pjsip_from_hdr *from_hdr;
	pjsip_to_hdr *to_hdr;

	capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));
	if (!capture_info) {
		return PJ_SUCCESS;
	}

	pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
	pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);

	cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);
	from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
	to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);

	uuid = assign_uuid(&cid_hdr->id, &to_hdr->tag, &from_hdr->tag);
	if (!uuid) {
		ao2_ref(capture_info, -1);
		return PJ_SUCCESS;
	}

	ast_sockaddr_parse(&capture_info->src_addr, local_buf, PARSE_PORT_REQUIRE);
	ast_sockaddr_parse(&capture_info->dst_addr, remote_buf, PARSE_PORT_REQUIRE);

	capture_info->capture_time = ast_tvnow();
	capture_info->capture_type = HEPV3_CAPTURE_TYPE_SIP;
	capture_info->uuid = uuid;
	capture_info->zipped = 0;

	hepv3_send_packet(capture_info);

	return PJ_SUCCESS;
}
/*!
 * \internal
 * \brief Adds diversion header information to an outbound SIP message
 *
 * \param tdata The outbound message
 * \param data The redirecting data used to fill parts of the diversion header
 */
static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
{
	pjsip_fromto_hdr *hdr;
	pjsip_name_addr *name_addr;
	pjsip_sip_uri *uri;
	pjsip_param *param;
	pjsip_fromto_hdr *old_hdr;

	struct ast_party_id *id = &data->from;
	pjsip_uri *base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;

	if (!id->number.valid || ast_strlen_zero(id->number.str)) {
		return;
	}

	hdr = pjsip_from_hdr_create(tdata->pool);
	hdr->type = PJSIP_H_OTHER;
	pj_strdup(tdata->pool, &hdr->name, &diversion_name);
	hdr->sname.slen = 0;

	name_addr = pjsip_uri_clone(tdata->pool, base);
	uri = pjsip_uri_get_uri(name_addr->uri);

	pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
	pj_strdup2(tdata->pool, &uri->user, id->number.str);

	param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
	param->name = pj_str("reason");
	param->value = pj_str((char*)reason_code_to_str(&data->reason));
	pj_list_insert_before(&hdr->other_param, param);

	hdr->uri = (pjsip_uri *) name_addr;
	old_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &diversion_name, NULL);
	if (old_hdr) {
		pj_list_erase(old_hdr);
	}
	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
}
示例#8
0
static void diversion_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata)
{
	static const pj_str_t contact_name = { "Contact", 7 };

	pjsip_status_line status = rdata->msg_info.msg->line.status;
	pjsip_fromto_hdr *div_hdr;
	pjsip_contact_hdr *contact_hdr;

	if ((status.code != 302) && (status.code != 181)) {
		return;
	}

	/* use the diversion header info if there is one. if not one then use the
           session caller id info. if that doesn't exist use info from the To hdr*/
	if (!(div_hdr = get_diversion_header(rdata)) && !session->id.number.valid) {
		div_hdr = PJSIP_MSG_TO_HDR(rdata->msg_info.msg);
	}

	contact_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &contact_name, NULL);

	set_redirecting(session, div_hdr, contact_hdr ?	(pjsip_name_addr*)contact_hdr->uri :
			(pjsip_name_addr*)PJSIP_MSG_FROM_HDR(rdata->msg_info.msg)->uri);
}
示例#9
0
static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
{
	char local_buf[256];
	char remote_buf[256];
	char *uuid;
	struct hepv3_capture_info *capture_info;
	pjsip_cid_hdr *cid_hdr;
	pjsip_from_hdr *from_hdr;
	pjsip_to_hdr *to_hdr;

	capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));
	if (!capture_info) {
		return PJ_SUCCESS;
	}

	if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
		pjsip_tpmgr_fla2_param prm;

		/* Attempt to determine what IP address will we send this packet out of */
		pjsip_tpmgr_fla2_param_default(&prm);
		prm.tp_type = tdata->tp_info.transport->key.type;
		pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
		prm.local_if = PJ_TRUE;

		/* If we can't get the local address use what we have already */
		if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
			pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
		} else {
			if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
				snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
					(int)pj_strlen(&prm.ret_addr),
					pj_strbuf(&prm.ret_addr),
					prm.ret_port);
			} else {
				snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
					(int)pj_strlen(&prm.ret_addr),
					pj_strbuf(&prm.ret_addr),
					prm.ret_port);
			}
		}
	} else {
		/* For reliable transports they can only ever come from the transport
		 * local address.
		 */
		pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
	}

	pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);

	cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);
	from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
	to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);

	uuid = assign_uuid(&cid_hdr->id, &to_hdr->tag, &from_hdr->tag);
	if (!uuid) {
		ao2_ref(capture_info, -1);
		return PJ_SUCCESS;
	}

	ast_sockaddr_parse(&capture_info->src_addr, local_buf, PARSE_PORT_REQUIRE);
	ast_sockaddr_parse(&capture_info->dst_addr, remote_buf, PARSE_PORT_REQUIRE);

	capture_info->protocol_id = transport_to_protocol_id(tdata->tp_info.transport);
	capture_info->capture_time = ast_tvnow();
	capture_info->capture_type = HEPV3_CAPTURE_TYPE_SIP;
	capture_info->uuid = uuid;
	capture_info->zipped = 0;

	hepv3_send_packet(capture_info);

	return PJ_SUCCESS;
}
示例#10
0
void MementoAppServerTsx::on_initial_request(pjsip_msg* req)
{
  TRC_DEBUG("Memento processing an initial request of type %s",
           (req->line.req.method.id == PJSIP_INVITE_METHOD) ? "INVITE" : "BYE");

  // Get the current time
  time_t rawtime;
  time(&rawtime);
  tm* start_time = localtime(&rawtime);
  _start_time_xml = create_formatted_timestamp(start_time, XML_PATTERN);
  _start_time_cassandra = create_formatted_timestamp(start_time, TIMESTAMP_PATTERN);

  // Is the call originating or terminating?
  std::string served_user;
  pjsip_routing_hdr* psu_hdr = (pjsip_routing_hdr*)
                     pjsip_msg_find_hdr_by_name(req, &P_SERVED_USER, NULL);

  if (psu_hdr != NULL)
  {
    pjsip_uri* uri = (pjsip_uri*)pjsip_uri_get_uri(&psu_hdr->name_addr);
    served_user = uri_to_string(PJSIP_URI_IN_ROUTING_HDR, uri);

    pjsip_param* sescase = pjsip_param_find(&psu_hdr->other_param, &SESCASE);

    if ((sescase != NULL) &&
        (pj_stricmp(&sescase->value, &ORIG) == 0))
    {
      TRC_DEBUG("Request is originating");

      _outgoing = true;
    }
  }

  // Get the caller, callee and impu values
  if (_outgoing)
  {
    // Get the callee's URI amd name from the To header.
    _callee_uri = uri_to_string(PJSIP_URI_IN_FROMTO_HDR,
                    (pjsip_uri*)pjsip_uri_get_uri(PJSIP_MSG_TO_HDR(req)->uri));
    _callee_name = pj_str_to_string(&((pjsip_name_addr*)
                                       (PJSIP_MSG_TO_HDR(req)->uri))->display);

    // Get the caller's URI and name from the P-Asserted Identity header. If
    // this is missing, use the From header.
    pjsip_routing_hdr* asserted_id = (pjsip_routing_hdr*)
               pjsip_msg_find_hdr_by_name(req, &P_ASSERTED_IDENTITY, NULL);

    if (asserted_id != NULL)
    {
      _caller_uri = uri_to_string(PJSIP_URI_IN_FROMTO_HDR,
                       (pjsip_uri*)pjsip_uri_get_uri(&asserted_id->name_addr));
      _caller_name = pj_str_to_string(&asserted_id->name_addr.display);
    }
    else
    {
      TRC_WARNING("INVITE missing P-Asserted-Identity");
      send_request(req);
      return;
    }

    // Set the IMPU equal to the caller's URI
    _impu = _caller_uri;
  }
  else
  {
    // Get the callee's URI from the request URI. There can be no name value.
    _callee_uri =  uri_to_string(PJSIP_URI_IN_FROMTO_HDR, req->line.req.uri);

    // Get the caller's URI and name from the From header.
    _caller_uri = uri_to_string(PJSIP_URI_IN_FROMTO_HDR,
                (pjsip_uri*)pjsip_uri_get_uri(PJSIP_MSG_FROM_HDR(req)->uri));
    _caller_name = pj_str_to_string(&((pjsip_name_addr*)
                                   (PJSIP_MSG_FROM_HDR(req)->uri))->display);

    // Set the IMPU equal to the callee's URI
    _impu = _callee_uri;
  }

  // Add a unique ID containing the IMPU to the record route header.
  // This has the format:
  //     <YYYYMMDDHHMMSS>_<unique_id>_<base64 encoded impu>.memento.<home domain>
  _unique_id = std::to_string(Utils::generate_unique_integer(0,0));
  std::string encoded_impu =
     base64_encode(reinterpret_cast<const unsigned char*>(_impu.c_str()),
                                                          _impu.length());
  std::string dialog_id = std::string(_start_time_cassandra).
                          append("_").
                          append(_unique_id).
                          append("_").
                          append(encoded_impu);

  add_to_dialog(dialog_id);
  send_request(req);
}