mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-10 06:29:34 +00:00
Allow access to headers from INVITE
This adds a sip profile parameter parse-all-invite-headers that when set parses all headers from an INVITE into channel variables. The headers are converted to lowercase, underscores are replaced with dashes, and the result is prefixed with sip_i_. Headers than exist more than once are set as arrays. FS-6075 --resolve Thanks-to: Peter Olsson <peter@olssononline.se>
This commit is contained in:
parent
eab969815a
commit
19dbd07ff8
@ -271,6 +271,7 @@ typedef enum {
|
||||
PFLAG_TCP_PINGPONG,
|
||||
PFLAG_TCP_PING2PONG,
|
||||
PFLAG_MESSAGES_RESPOND_200_OK,
|
||||
PFLAG_PARSE_ALL_INVITE_HEADERS,
|
||||
/* No new flags below this line */
|
||||
PFLAG_MAX
|
||||
} PFLAGS;
|
||||
|
@ -325,7 +325,196 @@ static void extract_vars(sofia_profile_t *profile, sip_t const *sip,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a specific SIP INVITE header to the channel variables, prefixed with "sip_i_"
|
||||
*/
|
||||
static void sofia_add_invite_header_to_chanvars(switch_channel_t *channel, nua_handle_t *nh, void *sip_header, const char *var)
|
||||
{
|
||||
switch_assert(channel);
|
||||
switch_assert(nh);
|
||||
switch_assert(var);
|
||||
|
||||
if (sip_header) {
|
||||
char *full;
|
||||
if ((full = sip_header_as_string(nh->nh_home, sip_header))) {
|
||||
switch_channel_set_variable(channel, var, full);
|
||||
su_free(nh->nh_home, full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep search into the SIP message to recreate the original headers, including multiple Diversions, etc.
|
||||
* Finally sets the "sip_invite_headers" to a string containing the 'original' SIP headers, except that the order may have changed.
|
||||
* Multiple headers will have the original internal order, though.
|
||||
*
|
||||
* @param sip A sip_t struct containing the parsed message
|
||||
* @param session A call session
|
||||
* @param nh A NUA handle for string allocation
|
||||
*/
|
||||
static void sofia_parse_all_invite_headers(sip_t const *sip, switch_core_session_t *session, nua_handle_t *nh)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
sip_unknown_t *un;
|
||||
sip_p_asserted_identity_t *passerted;
|
||||
sip_p_preferred_identity_t *ppreferred;
|
||||
sip_remote_party_id_t *rpid;
|
||||
sip_reply_to_t *reply_to;
|
||||
sip_alert_info_t *alert_info;
|
||||
|
||||
if (!sip) return;
|
||||
|
||||
/* Add simple (unique) headers first */
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_from, "sip_i_from");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_to, "sip_i_to");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_call_id, "sip_i_call_id");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_cseq, "sip_i_cseq");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_route, "sip_i_route");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_max_forwards, "sip_i_max_forwards");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_proxy_require, "sip_i_proxy_require");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_contact, "sip_i_contact");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_user_agent, "sip_i_user_agent");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_subject, "sip_i_subject");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_priority, "sip_i_priority");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_organization, "sip_i_organization");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_in_reply_to, "sip_i_in_reply_to");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_accept_encoding, "sip_i_accept_encoding");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_accept_language, "sip_i_accept_language");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_allow, "sip_i_allow");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_require, "sip_i_require");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_supported, "sip_i_supported");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_date, "sip_i_date");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_timestamp, "sip_i_timestamp");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_expires, "sip_i_expires");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_min_expires, "sip_i_min_expires");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_session_expires, "sip_i_session_expires");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_min_se, "sip_i_min_se");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_privacy, "sip_i_privacy");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_mime_version, "sip_i_mime_version");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_type, "sip_i_content_type");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_encoding, "sip_i_content_encoding");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_language, "sip_i_content_language");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_disposition, "sip_i_content_disposition");
|
||||
sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_length, "sip_i_content_length");
|
||||
|
||||
/* Add all other headers - which might exist more than once */
|
||||
|
||||
if (sip->sip_via) {
|
||||
sip_via_t *vp;
|
||||
for (vp = sip->sip_via; vp; vp = vp->v_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_via", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_record_route) {
|
||||
sip_record_route_t *rrp;
|
||||
for (rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
|
||||
char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_record_route", rr, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, rr);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_proxy_authorization) {
|
||||
sip_proxy_authorization_t *vp;
|
||||
for (vp = sip->sip_proxy_authorization; vp; vp = vp->au_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_proxy_authorization", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_call_info) {
|
||||
sip_call_info_t *vp;
|
||||
for (vp = sip->sip_call_info; vp; vp = vp->ci_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_call_info", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_accept) {
|
||||
sip_accept_t *vp;
|
||||
for (vp = sip->sip_accept; vp; vp = vp->ac_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_accept", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_authorization) {
|
||||
sip_authorization_t *vp;
|
||||
for (vp = sip->sip_authorization; vp; vp = vp->au_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_authorization", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((alert_info = sip_alert_info(sip))) {
|
||||
sip_alert_info_t *vp;
|
||||
for (vp = alert_info; vp; vp = vp->ai_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_alert_info", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((passerted = sip_p_asserted_identity(sip))) {
|
||||
sip_p_asserted_identity_t *vp;
|
||||
for (vp = passerted; vp; vp = vp->paid_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_p_asserted_identity", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ppreferred = sip_p_preferred_identity(sip))) {
|
||||
sip_p_preferred_identity_t *vp;
|
||||
for (vp = ppreferred; vp; vp = vp->ppid_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_p_preferred_identity", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((rpid = sip_remote_party_id(sip))) {
|
||||
sip_remote_party_id_t *vp;
|
||||
for (vp = rpid; vp; vp = vp->rpid_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_remote_party_id", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((reply_to = sip_reply_to(sip))) {
|
||||
sip_reply_to_t *vp;
|
||||
for (vp = reply_to; vp; vp = vp->rplyto_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
switch_channel_add_variable_var_check(channel, "sip_i_reply_to", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
su_free(nh->nh_home, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop through the unknown headers */
|
||||
for (un = sip->sip_unknown; un; un = un->un_next) {
|
||||
if (!zstr(un->un_name) && !zstr(un->un_value)) {
|
||||
char *parsed_name;
|
||||
if ((parsed_name = switch_mprintf("sip_i_%s", un->un_name))) {
|
||||
char *p, *x = parsed_name;
|
||||
switch_tolower_max(x);
|
||||
while ((p = strchr(x, '-'))) {
|
||||
*p = '_';
|
||||
x = ++p;
|
||||
}
|
||||
switch_channel_add_variable_var_check(channel, parsed_name, un->un_value, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
free(parsed_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
|
||||
char const *phrase,
|
||||
@ -4546,6 +4735,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
|
||||
} else {
|
||||
sofia_clear_flag(profile, TFLAG_ENABLE_SOA);
|
||||
}
|
||||
} else if (!strcasecmp(var, "parse-all-invite-headers")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS);
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS);
|
||||
}
|
||||
} else if (!strcasecmp(var, "bitpacking")) {
|
||||
if (!strcasecmp(val, "aal2")) {
|
||||
profile->codec_flags = SWITCH_CODEC_FLAG_AAL2;
|
||||
@ -9139,6 +9334,10 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
|
||||
sofia_presence_set_chat_hash(tech_pvt, sip);
|
||||
}
|
||||
|
||||
if (sofia_test_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS)) {
|
||||
sofia_parse_all_invite_headers(sip, session, nh);
|
||||
}
|
||||
|
||||
if (sip->sip_to) {
|
||||
to = sip->sip_to->a_url;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user