Skip to content

Commit

Permalink
SIP PN Support: Improve Feature-Caps interpretation
Browse files Browse the repository at this point in the history
Keep performing PN param-based Contact matching even when PNs are
already handled by upstream side.

Also move more common code under lib/reg
  • Loading branch information
liviuchircu committed Apr 30, 2020
1 parent 0a98da7 commit 90ad027
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 63 deletions.
69 changes: 64 additions & 5 deletions lib/reg/pn.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ enum pn_action pn_inspect_ct_params(struct sip_msg *req, const str *ct_uri)
struct hdr_field *fcaps;
fcaps_body_t *fcaps_body;
str_list *param;
int i;
int i, is_cap_query = 1, is_handled_upstream = 0;

if (parse_uri(ct_uri->s, ct_uri->len, &puri) != 0) {
LM_ERR("failed to parse URI: '%.*s'\n", ct_uri->len, ct_uri->s);
Expand Down Expand Up @@ -217,9 +217,10 @@ enum pn_action pn_inspect_ct_params(struct sip_msg *req, const str *ct_uri)

fcaps_body = (fcaps_body_t *)fcaps->parsed;
if (str_match(&fcaps_body->pns, &puri.u_val[i])) {
LM_DBG("the '%.*s' PNs are being handled by an upstream proxy\n",
LM_DBG("PNs for '%.*s' are being handled by an upstream proxy\n",
fcaps_body->pns.len, fcaps_body->pns.s);
return PN_HANDLED_UPSTREAM;
is_handled_upstream = 1;
goto match_params;
}
}

Expand All @@ -236,18 +237,76 @@ enum pn_action pn_inspect_ct_params(struct sip_msg *req, const str *ct_uri)
match_params:
for (param = pn_ct_params; param; param = param->next) {
for (int i = 0; i < puri.u_params_no; i++)
if (str_match(&param->s, &puri.u_name[i]))
if (str_match(&param->s, &puri.u_name[i])) {
if (!str_match(&param->s, &pn_provider_param))
is_cap_query = 0;
goto next_param;
}

return PN_LIST_ONE_PNS;
if (is_handled_upstream)
/* at least one required PN param is missing and PNs are already
* handled upstream anyway -- just match by URI string */
return PN_NONE;
else if (!is_cap_query)
return PN_UNSUPPORTED_PNS;

next_param:;
}

if (is_cap_query)
return PN_LIST_ONE_PNS;

if (is_handled_upstream)
return PN_MATCH_PN_PARAMS;

return PN_ON;
}


int pn_inspect_request(struct sip_msg *req, const str *ct_uri,
struct save_ctx *sctx)
{
if (sctx->cmatch.mode != CT_MATCH_NONE) {
LM_DBG("skip PN processing, matching mode already enforced\n");
return 0;
}

switch (pn_inspect_ct_params(req, ct_uri)) {
case PN_NONE:
LM_DBG("Contact URI has no PN params\n");
break;

case PN_ON:
LM_DBG("match this contact using PN params and send PN\n");
sctx->cmatch.mode = CT_MATCH_PARAMS;
sctx->cmatch.match_params = pn_ct_params;
sctx->flags |= REG_SAVE__PN_ON_FLAG;
break;

case PN_LIST_ALL_PNS:
LM_DBG("Contact URI includes PN capability query (all PNS)\n");
break;

case PN_LIST_ONE_PNS:
LM_DBG("Contact URI includes PN capability query (one PNS)\n");
break;

case PN_MATCH_PN_PARAMS:
LM_DBG("match this contact using PN params but don't send PN\n");
sctx->cmatch.mode = CT_MATCH_PARAMS;
sctx->cmatch.match_params = pn_ct_params;
break;

case PN_UNSUPPORTED_PNS:
LM_DBG("at least one required PN param is missing, reply with 555\n");
rerrno = R_PNS_UNSUP;
return -1;
}

return 0;
}


void pn_append_feature_caps(struct sip_msg *msg, int append_to_reply, str *hf)
{
struct pn_provider *prov;
Expand Down
26 changes: 24 additions & 2 deletions lib/reg/pn.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "../../modules/usrloc/ucontact.h"
#include "regtime.h"
#include "save_flags.h"

struct pn_provider {
str name;
Expand All @@ -41,11 +42,22 @@ struct pn_provider {

enum pn_action {
PN_NONE, /* no 'pn-provider' was given */
PN_HANDLED_UPSTREAM, /* a Feature-Caps hf is present, so PNs are handled */
PN_UNSUPPORTED_PNS, /* the given 'pn-provider' value is not supported */

/* Query Network PNS Capabilities */
PN_LIST_ALL_PNS, /* cap query: only 'pn-provider' given, no value */
PN_LIST_ONE_PNS, /* cap query: a known 'pn-provider' value was given */
PN_ON, /* enable PN: all required 'pn-*' params are present */

/* while the 'pn-*' params are present and the contact must be matched
* using them, we must _not_ send any Push Notifications, since an upstream
* proxy has already indicated that it is doing so */
PN_MATCH_PN_PARAMS,

/* fully enable PN:
* 1. all required 'pn-*' params are present -- match these exclusively
* 2. generate PNs to this contact as required
*/
PN_ON,
};

/* common registrar PN modparams */
Expand Down Expand Up @@ -85,6 +97,16 @@ extern str_list *pn_ct_params; /* list of parsed match params */
int pn_init(void);


/**
* Perform any required RFC 8599 processing for a SIP request, including
* handling for Feature-Caps headers arriving from upstream.
*
* Return: 0 on success, -1 on failure and should reply immediately
*/
int pn_inspect_request(struct sip_msg *req, const str *ct_uri,
struct save_ctx *sctx);


/**
* Look for any RFC 8599 URI parameters and take the appropriate action
*/
Expand Down
31 changes: 3 additions & 28 deletions modules/mid_registrar/save.c
Original file line number Diff line number Diff line change
Expand Up @@ -2498,34 +2498,9 @@ int mid_reg_save(struct sip_msg *msg, udomain_t *d, str *flags_str,
goto quick_reply;
}

if (pn_enable && sctx.cmatch.mode == CT_MATCH_NONE) {
switch (pn_inspect_ct_params(msg, &c->uri)) {
case PN_NONE:
LM_DBG("Contact URI has no PN params\n");
break;

case PN_ON:
LM_DBG("Contact URI includes all required PN params\n");
sctx.cmatch.mode = CT_MATCH_PARAMS;
sctx.cmatch.match_params = pn_ct_params;
sctx.flags |= REG_SAVE__PN_ON_FLAG;
break;

case PN_LIST_ALL_PNS:
LM_DBG("Contact URI includes PN capability query (all PNS)\n");
break;

case PN_LIST_ONE_PNS:
LM_DBG("Contact URI includes PN capability query (one PNS)\n");
break;

case PN_HANDLED_UPSTREAM:
break;

case PN_UNSUPPORTED_PNS:
rerrno = R_PNS_UNSUP;
goto quick_reply;
}
if (pn_enable && pn_inspect_request(msg, &c->uri, &sctx) != 0) {
LM_DBG("SIP PN processing failed\n");
goto quick_reply;
}

/* mid-registrar always rewrites the Contact, so any Path hf must go! */
Expand Down
31 changes: 3 additions & 28 deletions modules/registrar/save.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,34 +642,9 @@ int save_aux(struct sip_msg* _m, str* forced_binding, void* _d, str* flags_s,
c = get_first_contact(_m);
}

if (pn_enable && sctx.cmatch.mode == CT_MATCH_NONE) {
switch (pn_inspect_ct_params(_m, &c->uri)) {
case PN_NONE:
LM_DBG("Contact URI has no PN params\n");
break;

case PN_ON:
LM_DBG("Contact URI includes all required PN params\n");
sctx.cmatch.mode = CT_MATCH_PARAMS;
sctx.cmatch.match_params = pn_ct_params;
sctx.flags |= REG_SAVE__PN_ON_FLAG;
break;

case PN_LIST_ALL_PNS:
LM_DBG("Contact URI includes PN capability query (all PNS)\n");
break;

case PN_LIST_ONE_PNS:
LM_DBG("Contact URI includes PN capability query (one PNS)\n");
break;

case PN_HANDLED_UPSTREAM:
break;

case PN_UNSUPPORTED_PNS:
rerrno = R_PNS_UNSUP;
goto error;
}
if (pn_enable && pn_inspect_request(_m, &c->uri, &sctx) != 0) {
LM_DBG("SIP PN processing failed\n");
goto error;
}

update_act_time();
Expand Down

0 comments on commit 90ad027

Please sign in to comment.