Module: sip-router
Branch: pd/outbound
Commit: 65dc9c8cf35fc3e631380d65e8c99e8f84d465cc
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=65dc9c8cf35fc3e631380d65e8c99e8f84d465cc

Author: Peter Dunkley <[email protected]>
Committer: Peter Dunkley <[email protected]>
Date:   Thu Feb 28 14:40:41 2013 +0000

modules/registrar: RFC 5626 section 6 support

- Behaviour when outbound in use but first edge proxy does not
  support it.

---

 modules/registrar/reply.c  |   11 ++++--
 modules/registrar/rerrno.h |    3 +-
 modules/registrar/save.c   |   79 ++++++++++++++++++++++++++++++++++++--------
 3 files changed, 75 insertions(+), 18 deletions(-)

diff --git a/modules/registrar/reply.c b/modules/registrar/reply.c
index 4b05aa7..129e7d6 100644
--- a/modules/registrar/reply.c
+++ b/modules/registrar/reply.c
@@ -375,6 +375,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define MSG_400 "Bad Request"
 #define MSG_420 "Bad Extension"
 #define MSG_421 "Extension Required"
+#define MSG_439 "First Hop Lacks Outbound Support"
 #define MSG_500 "Server Internal Error"
 #define MSG_503 "Service Unavailable"
 
@@ -410,6 +411,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define EI_R_PATH_UNSUP  "No support for found Path indicated"      /* 
R_PATH_UNSUP */
 #define EI_R_OB_UNSUP    "No support for Outbound indicated"        /* 
R_OB_UNSUP */
 #define EI_R_OB_REQD     "No support for Outbound on server"        /* 
R_OB_REQD */
+#define EI_R_OB_UNSUP_EDGE "No support for Outbound on edge proxy"  /* 
R_OB_UNSUP_EDGE */
 
 
 str error_info[] = {
@@ -444,7 +446,8 @@ str error_info[] = {
        {EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
        {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1},
        {EI_R_OB_UNSUP,   sizeof(EI_R_OB_UNSUP) - 1},
-       {EI_R_OB_REQD,   sizeof(EI_R_OB_REQD) - 1},
+       {EI_R_OB_REQD,    sizeof(EI_R_OB_REQD) - 1},
+       {EI_R_OB_UNSUP_EDGE, sizeof(EI_R_OB_UNSUP_EDGE) - 1},
 };
 
 int codes[] = {
@@ -479,7 +482,8 @@ int codes[] = {
        400, /* R_PARSE_PATH */
        420, /* R_PATH_UNSUP */
        421, /* R_OB_UNSUP */
-       420  /* R_OB_REQD */
+       420, /* R_OB_REQD */
+       439, /* R_OB_UNSUP_EDGE */
 };
 
 
@@ -700,7 +704,8 @@ int reg_send_reply(struct sip_msg* _m)
        case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1;break;
        case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
        case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
-       case 421: msg.s = MSG_420; msg.len = sizeof(MSG_421)-1;break;
+       case 421: msg.s = MSG_421; msg.len = sizeof(MSG_421)-1;break;
+       case 439: msg.s = MSG_439; msg.len = sizeof(MSG_439)-1;break;
        case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
        case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
        }
diff --git a/modules/registrar/rerrno.h b/modules/registrar/rerrno.h
index 9bc9338..535be04 100644
--- a/modules/registrar/rerrno.h
+++ b/modules/registrar/rerrno.h
@@ -65,7 +65,8 @@ typedef enum rerr {
        R_PARSE_PATH, /*!< Error while parsing Path */
        R_PATH_UNSUP, /*!< Path not supported by UAC */
        R_OB_UNSUP,   /*!< Outbound not supported by UAC */
-       R_OB_REQD     /*!< Outbound required by UAC but not supported on server 
*/
+       R_OB_REQD,    /*!< Outbound required by UAC but not supported on server 
*/
+       R_OB_UNSUP_EDGE, /*!< Outbound needed for this registration but not 
supported on edge proxy */
 
 } rerr_t;
 
diff --git a/modules/registrar/save.c b/modules/registrar/save.c
index b7a4035..d568334 100644
--- a/modules/registrar/save.c
+++ b/modules/registrar/save.c
@@ -50,6 +50,7 @@
 #include "../../parser/parse_allow.h"
 #include "../../parser/parse_methods.h"
 #include "../../parser/msg_parser.h"
+#include "../../parser/parse_rr.h"
 #include "../../parser/parse_to.h"
 #include "../../parser/parse_uri.h"
 #include "../../dprint.h"
@@ -217,8 +218,7 @@ static inline int no_contacts(sip_msg_t *_m, udomain_t* _d, 
str* _a, str* _h)
 /*! \brief
  * Fills the common part (for all contacts) of the info structure
  */
-static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
-                                                                               
        unsigned int _e, unsigned int _f)
+static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, 
unsigned int _e, unsigned int _f, int _use_regid)
 {
        static ucontact_info_t ci;
        static str no_ua = str_init("n/a");
@@ -365,7 +365,7 @@ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, 
contact_t* _c,
                }
                if(_c->instance!=NULL && _c->instance->body.len>0)
                        ci.instance = _c->instance->body;
-               if(_c->instance!=NULL && _c->reg_id!=NULL && 
_c->reg_id->body.len>0) {
+               if(_use_regid && _c->instance!=NULL && _c->reg_id!=NULL && 
_c->reg_id->body.len>0) {
                        if(str2int(&_c->reg_id->body, &ci.reg_id)<0 || 
ci.reg_id==0)
                        {
                                LM_ERR("invalid reg-id value\n");
@@ -424,7 +424,7 @@ int reg_get_crt_max_contacts(void)
  * and insert all contacts from the message that have expires
  * > 0
  */
-static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a)
+static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a, 
int _use_regid)
 {
        ucontact_info_t* ci;
        urecord_t* r = NULL;
@@ -480,7 +480,7 @@ static inline int insert_contacts(struct sip_msg* _m, 
udomain_t* _d, str* _a)
                }
 
                /* pack the contact_info */
-               if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags))==0 ) {
+               if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags, 
_use_regid))==0 ) {
                        LM_ERR("failed to extract contact info\n");
                        goto error;
                }
@@ -607,8 +607,7 @@ static int test_max_contacts(struct sip_msg* _m, urecord_t* 
_r, contact_t* _c,
  * 3) If contact in usrloc exists and expires
  *    == 0, delete contact
  */
-static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
-                                                                               
int _mode)
+static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, int 
_mode, int _use_regid)
 {
        ucontact_info_t *ci;
        ucontact_t *c, *ptr, *ptr0;
@@ -627,7 +626,7 @@ static inline int update_contacts(struct sip_msg* _m, 
urecord_t* _r,
 
        rc = 0;
        /* pack the contact_info */
-       if ( (ci=pack_ci( _m, 0, 0, flags))==0 ) {
+       if ( (ci=pack_ci( _m, 0, 0, flags, _use_regid))==0 ) {
                LM_ERR("failed to initial pack contact info\n");
                goto error;
        }
@@ -658,7 +657,7 @@ static inline int update_contacts(struct sip_msg* _m, 
urecord_t* _r,
                calc_contact_expires(_m, _c->expires, &expires);
 
                /* pack the contact info */
-               if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
+               if ( (ci=pack_ci( 0, _c, expires, 0, _use_regid))==0 ) {
                        LM_ERR("failed to pack contact specific info\n");
                        goto error;
                }
@@ -774,7 +773,7 @@ error:
  * contained some contact header fields
  */
 static inline int add_contacts(struct sip_msg* _m, udomain_t* _d,
-               str* _a, int _mode)
+               str* _a, int _mode, int _use_regid)
 {
        int res;
        int ret;
@@ -796,7 +795,7 @@ static inline int add_contacts(struct sip_msg* _m, 
udomain_t* _d,
        }
 
        if (res == 0) { /* Contacts found */
-               if ((ret=update_contacts(_m, r, _mode)) < 0) {
+               if ((ret=update_contacts(_m, r, _mode, _use_regid)) < 0) {
                        build_contact(_m, r->contacts, &u->host);
                        ul.release_urecord(r);
                        ul.unlock_udomain(_d, _a);
@@ -805,7 +804,7 @@ static inline int add_contacts(struct sip_msg* _m, 
udomain_t* _d,
                build_contact(_m, r->contacts, &u->host);
                ul.release_urecord(r);
        } else {
-               if (insert_contacts(_m, _d, _a) < 0) {
+               if (insert_contacts(_m, _d, _a, _use_regid) < 0) {
                        ul.unlock_udomain(_d, _a);
                        return -4;
                }
@@ -827,6 +826,12 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, 
str *_uri)
        str aor;
        int ret;
        sip_uri_t *u;
+       rr_t *route;
+       struct sip_uri puri;
+       param_hooks_t hooks;
+       param_t *params;
+       contact_t *contact;
+       int use_ob = 1, use_regid = 1;
 
        u = parse_to_uri(_m);
        if(u==NULL)
@@ -855,12 +860,58 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, 
str *_uri)
        if (parse_require(_m) == 0) {
                if (!(get_require(_m) & F_OPTION_TAG_OUTBOUND)
                                && reg_outbound_mode == REG_OUTBOUND_NONE) {
-                       LM_WARN("Outbound required by client and not supported 
by server\n");
+                       LM_WARN("Outbound required by UAC and not supported by 
server\n");
                        rerrno = R_OB_REQD;
                        goto error;
                }
        }
 
+       if (reg_outbound_mode != REG_OUTBOUND_NONE
+               && !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0
+                       || _m->via2->error != PARSE_OK)) {
+               /* Outbound supported on server, and more than one Via: - not 
the first hop */
+
+               if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) 
{
+                       if (parse_rr_body(_m->path->body.s, _m->path->body.len, 
&route) < 0) {
+                               LM_ERR("Failed to parse Path: header body\n");
+                               goto error;
+                       }
+                       if (parse_uri(route->nameaddr.uri.s, 
route->nameaddr.uri.len, &puri) < 0) {
+                               LM_ERR("Failed to parse Path: URI\n");
+                               goto error;
+                       }
+                       if (parse_params(&puri.params, CLASS_URI, &hooks, 
&params) != 0) {
+                               LM_ERR("Failed to parse Path: URI 
parameters\n");
+                               goto error;
+                       }
+                       if (!hooks.uri.ob) {
+                               /* No ;ob parameter to top Path: URI - no 
outbound */
+                               use_ob = 0;
+                       }
+
+               } else {
+                       /* No Path: header - no outbound */
+                       use_ob = 0;
+
+               }
+
+               contact = ((contact_body_t *) _m->contact->parsed)->contacts;
+               if (!contact) {
+                       LM_ERR("empty Contact:\n");
+                       goto error;
+               }
+
+               if (use_ob == 0 && (get_supported(_m) & F_OPTION_TAG_OUTBOUND)
+                       && contact->reg_id) {
+                       LM_WARN("Outbound used by UAC but not supported by edge 
proxy\n");
+                       rerrno = R_OB_UNSUP_EDGE;
+                       goto error;
+               } else {
+                       /* ignore ;reg-id parameter */
+                       use_regid = 0;
+               }
+       }
+
        
        get_act_time();
        c = get_first_contact(_m);
@@ -882,7 +933,7 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, 
str *_uri)
                }
        } else {
                mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
-               if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode)) < 0)
+               if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, 
use_regid)) < 0)
                        goto error;
                ret = (ret==0)?1:ret;
        }


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to