regpv.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Export vontact attrs as PV
00005  *
00006  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 
00025 /*!
00026  * \file
00027  * \brief SIP registrar module - export contacts as PV
00028  * \ingroup registrar   
00029  */  
00030 
00031 
00032 #include <string.h>
00033 #include "../../dprint.h"
00034 #include "../../mem/mem.h"
00035 #include "../../mod_fix.h"
00036 #include "../usrloc/usrloc.h"
00037 #include "reg_mod.h"
00038 #include "common.h"
00039 #include "regpv.h"
00040 
00041 typedef struct _regpv_profile {
00042    str pname;
00043    str domain;
00044    str aor;
00045    int flags;
00046    unsigned int aorhash;
00047    int nrc;
00048    ucontact_t* contacts;
00049    struct _regpv_profile *next;
00050 } regpv_profile_t;
00051 
00052 typedef struct _regpv_name {
00053    regpv_profile_t *rp;
00054    int attr;
00055 } regpv_name_t;
00056 
00057 static regpv_profile_t *_regpv_profile_list = NULL;
00058 
00059 static inline regpv_profile_t* regpv_get_profile(str *name)
00060 {
00061    regpv_profile_t *rp;
00062 
00063    if(name==NULL || name->len<=0)
00064    {
00065       LM_ERR("invalid parameters\n");
00066       return NULL;
00067    }
00068 
00069    rp = _regpv_profile_list;
00070    while(rp)
00071    {
00072       if(rp->pname.len == name->len
00073             && strncmp(rp->pname.s, name->s, name->len)==0)
00074          return rp;
00075       rp = rp->next;
00076    }
00077 
00078    rp = (regpv_profile_t*)pkg_malloc(sizeof(regpv_profile_t));
00079    if(rp==NULL)
00080    {
00081       LM_ERR("no more pkg\n");
00082       return NULL;
00083    }
00084    memset(rp, 0, sizeof(regpv_profile_t));
00085    rp->pname.s = (char*)pkg_malloc((name->len+1)*sizeof(char));
00086    if(rp->pname.s==NULL)
00087    {
00088       LM_ERR("no more pkg\n");
00089       pkg_free(rp);
00090       return NULL;
00091    }
00092    memcpy(rp->pname.s, name->s, name->len);
00093    rp->pname.s[name->len] = '\0';
00094    rp->pname.len = name->len;
00095 
00096    rp->next = _regpv_profile_list;
00097    _regpv_profile_list = rp;
00098    return rp;
00099 }
00100 
00101 static void regpv_free_profile(regpv_profile_t *rpp)
00102 {
00103    ucontact_t* ptr;
00104    ucontact_t* ptr0;
00105 
00106    if(rpp==NULL)
00107       return;
00108 
00109    ptr = rpp->contacts;
00110    while(ptr)
00111    {
00112       ptr0 = ptr;
00113       ptr = ptr->next;
00114       pkg_free(ptr0);
00115    }
00116    if(rpp->domain.s!=NULL)
00117    {
00118       rpp->domain.s = 0;
00119       rpp->domain.len = 0;
00120    }
00121    if(rpp->aor.s!=NULL)
00122    {
00123       pkg_free(rpp->aor.s);
00124       rpp->aor.s = 0;
00125       rpp->aor.len = 0;
00126    }
00127 
00128    rpp->flags = 0;
00129    rpp->aorhash = 0;
00130    rpp->nrc = 0;
00131    rpp->contacts = 0;
00132 
00133 }
00134 
00135 void regpv_free_profiles(void)
00136 {
00137    regpv_profile_t *rp;
00138    regpv_profile_t *rp0;
00139 
00140    rp = _regpv_profile_list;
00141 
00142    while(rp)
00143    {
00144       if(rp->pname.s!=NULL)
00145          pkg_free(rp->pname.s);
00146       rp0 = rp;
00147       regpv_free_profile(rp0);
00148       rp = rp->next;
00149    }
00150    _regpv_profile_list = 0;
00151 }
00152 
00153 int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
00154       pv_value_t *res)
00155 {
00156    regpv_name_t *rp;
00157    regpv_profile_t *rpp;
00158    ucontact_t *c;
00159    int idx;
00160    int i;
00161 
00162    if(param==NULL)
00163    {
00164       LM_ERR("invalid params\n");
00165       return -1;
00166    }
00167    rp = (regpv_name_t*)param->pvn.u.dname;
00168    if(rp==NULL || rp->rp==NULL)
00169    {
00170       LM_DBG("no profile in params\n");
00171       return pv_get_null(msg, param, res);
00172    }
00173    rpp = rp->rp;
00174 
00175    if(rpp->flags==0 || rpp->contacts==NULL)
00176    {
00177       LM_DBG("profile not set or no contacts there\n");
00178       return pv_get_null(msg, param, res);
00179    }
00180    /* get index */
00181    if(pv_get_spec_index(msg, param, &idx, &i)!=0)
00182    {
00183       LM_ERR("invalid index\n");
00184       return -1;
00185    }
00186 
00187    /* work only with positive indexes by now */
00188    if(idx<0)
00189       idx = 0;
00190 
00191    /* get contact */
00192    i = 0;
00193    c = rpp->contacts;
00194    while(rpp)
00195    {
00196       if(i == idx)
00197          break;
00198       i++;
00199       c = c->next;
00200    }
00201    if(c==NULL)
00202       return pv_get_null(msg, param, res);
00203 
00204    switch(rp->attr)
00205    {
00206       case 0: /* aor */
00207          return  pv_get_strval(msg, param, res, &rpp->aor);
00208       break;
00209       case 1: /* domain */
00210          return  pv_get_strval(msg, param, res, &rpp->domain);
00211       break;
00212       case 2: /* aorhash */
00213          return pv_get_uintval(msg, param, res, rpp->aorhash);
00214       break;
00215       case 3: /* addr */
00216          return  pv_get_strval(msg, param, res, &c->c);
00217       break;
00218       case 4: /* path */
00219          return  pv_get_strval(msg, param, res, &c->path);
00220       break;
00221       case 5: /* received */
00222          return  pv_get_strval(msg, param, res, &c->received);
00223       break;
00224       case 6: /* expires */
00225          return pv_get_uintval(msg, param, res,
00226                (unsigned int)c->expires);
00227       break;
00228       case 7: /* callid */
00229          return  pv_get_strval(msg, param, res, &c->callid);
00230       break;
00231       case 8: /* q */
00232          return pv_get_sintval(msg, param, res, (int)c->q);
00233       break;
00234       case 9: /* cseq */
00235          return pv_get_sintval(msg, param, res, c->cseq);
00236       break;
00237       case 10: /* flags */
00238          return pv_get_uintval(msg, param, res, c->flags);
00239       break;
00240       case 11: /* cflags */
00241          return pv_get_uintval(msg, param, res, c->cflags);
00242       break;
00243       case 12: /* user agent */
00244          return  pv_get_strval(msg, param, res, &c->user_agent);
00245       break;
00246       case 14: /* socket */
00247          if(c->sock==NULL)
00248             return pv_get_null(msg, param, res);
00249          return pv_get_strval(msg, param, res, &c->sock->sock_str);
00250       break;
00251       case 15: /* modified */
00252          return pv_get_uintval(msg, param, res,
00253                (unsigned int)c->last_modified);
00254       break;
00255       case 16: /* methods */
00256          return pv_get_uintval(msg, param, res, c->methods);
00257       break;
00258       case 17: /* count */
00259          return pv_get_sintval(msg, param, res, rpp->nrc);
00260       break;
00261    }
00262 
00263    return pv_get_null(msg, param, res);
00264 }
00265 
00266 int pv_set_ulc(struct sip_msg* msg, pv_param_t *param,
00267       int op, pv_value_t *val)
00268 {
00269    return 0;
00270 }
00271 
00272 int pv_parse_ulc_name(pv_spec_p sp, str *in)
00273 {
00274    str pn;
00275    str pa;
00276    regpv_name_t *rp;
00277    regpv_profile_t *rpp;
00278 
00279    if(sp==NULL || in==NULL || in->len<=0)
00280       return -1;
00281 
00282    pa.s = in->s;
00283    while(pa.s < in->s + in->len - 2)
00284    {
00285       if(*pa.s=='=')
00286          break;
00287       pa.s++;
00288    }
00289    
00290    if(pa.s >= in->s + in->len - 2)
00291    {
00292       LM_ERR("invalid contact pv name %.*s\n", in->len, in->s);
00293       return -1;
00294    }
00295    if(*(pa.s+1) != '>')
00296    {
00297       LM_ERR("invalid contact pv name %.*s.\n", in->len, in->s);
00298       return -1;
00299    }
00300 
00301    pn.s = in->s;
00302    pn.len = pa.s - pn.s;
00303 
00304    LM_DBG("get profile [%.*s]\n", pn.len, pn.s);
00305 
00306    rpp = regpv_get_profile(&pn);
00307    if(rpp==NULL)
00308    {
00309       LM_ERR("cannot get profile [%.*s]\n", pn.len, pn.s);
00310       return -1;
00311    }
00312    pa.s += 2;
00313    pa.len = in->s + in->len - pa.s;
00314    LM_DBG("get attr [%.*s]\n", pa.len, pa.s);
00315 
00316    rp = (regpv_name_t*)pkg_malloc(sizeof(regpv_name_t));
00317    if(rp==0)
00318    {
00319       LM_ERR("no more pkg\n");
00320       return -1;
00321    }
00322    memset(rp, 0, sizeof(regpv_name_t));
00323    rp->rp = rpp;
00324 
00325    switch(pa.len)
00326    {
00327       case 1: 
00328          if(strncmp(pa.s, "q", 1)==0)
00329             rp->attr = 8;
00330          else goto error;
00331       break;
00332       case 3: 
00333          if(strncmp(pa.s, "aor", 3)==0)
00334             rp->attr = 0;
00335          else goto error;
00336       break;
00337       case 4: 
00338          if(strncmp(pa.s, "addr", 4)==0)
00339             rp->attr = 3;
00340          else if(strncmp(pa.s, "path", 4)==0)
00341             rp->attr = 4;
00342          else if(strncmp(pa.s, "cseq", 4)==0)
00343             rp->attr = 9;
00344          else goto error;
00345       break;
00346       case 5: 
00347          if(strncmp(pa.s, "flags", 5)==0)
00348             rp->attr = 10;
00349          else if(strncmp(pa.s, "count", 5)==0)
00350             rp->attr = 17;
00351          else goto error;
00352       break;
00353       case 6: 
00354          if(strncmp(pa.s, "domain", 6)==0)
00355             rp->attr = 1;
00356          else if(strncmp(pa.s, "callid", 6)==0)
00357             rp->attr = 7;
00358          else if(strncmp(pa.s, "cflags", 6)==0)
00359             rp->attr = 11;
00360          else if(strncmp(pa.s, "socket", 6)==0)
00361             rp->attr = 14;
00362          else goto error;
00363       break;
00364       case 7: 
00365          if(strncmp(pa.s, "aorhash", 7)==0)
00366             rp->attr = 2;
00367          else if(strncmp(pa.s, "expires", 7)==0)
00368             rp->attr = 6;
00369          else if(strncmp(pa.s, "methods", 7)==0)
00370             rp->attr = 16;
00371          else goto error;
00372       break;
00373       case 8: 
00374          if(strncmp(pa.s, "received", 8)==0)
00375             rp->attr = 5;
00376          else if(strncmp(pa.s, "modified", 8)==0)
00377             rp->attr = 15;
00378          else goto error;
00379       break;
00380       case 10: 
00381          if(strncmp(pa.s, "user_agent", 10)==0)
00382             rp->attr = 12;
00383          else goto error;
00384       break;
00385       default:
00386          goto error;
00387    }
00388    sp->pvp.pvn.u.dname = (void*)rp;
00389    sp->pvp.pvn.type = PV_NAME_PVAR;
00390 
00391    return 0;
00392 
00393 error:
00394    LM_ERR("unknown contact attr name in %.*s\n", in->len, in->s);
00395    return -1;
00396 }
00397 
00398 int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
00399       char* profile)
00400 {
00401    urecord_t* r;
00402    ucontact_t* ptr;
00403    ucontact_t* ptr0;
00404    ucontact_t* c0;
00405    regpv_profile_t *rpp;
00406    str aor = {0, 0};
00407    str u = {0, 0};
00408    int res;
00409    int olen;
00410    int ilen;
00411    int n;
00412    char *p;
00413 
00414    rpp = regpv_get_profile((str*)profile);
00415    if(rpp==0)
00416    {
00417       LM_ERR("invalid parameters\n");
00418       return -1;
00419    }
00420 
00421    /* check and free if profile already set */
00422    if(rpp->flags)
00423       regpv_free_profile(rpp);
00424 
00425    if(fixup_get_svalue(msg, (gparam_p)uri, &u)!=0 || u.len<=0)
00426    {
00427       LM_ERR("invalid uri parameter\n");
00428       return -1;
00429    }
00430 
00431    if (extract_aor(&u, &aor) < 0) {
00432       LM_ERR("failed to extract Address Of Record\n");
00433       return -1;
00434    }
00435 
00436    /* copy aor and ul domain */
00437    rpp->aor.s = (char*)pkg_malloc(aor.len*sizeof(char));
00438    if(rpp->aor.s==NULL)
00439    {
00440       LM_ERR("no more pkg\n");
00441       return -1;
00442    }
00443    memcpy(rpp->aor.s, aor.s, aor.len);
00444    rpp->aor.len = aor.len;
00445    rpp->domain = *((udomain_t*)table)->name;
00446    rpp->flags = 1;
00447 
00448    /* copy contacts */
00449    ilen = sizeof(ucontact_t);
00450    ul.lock_udomain((udomain_t*)table, &aor);
00451    res = ul.get_urecord((udomain_t*)table, &aor, &r);
00452    if (res > 0) {
00453       LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
00454       ul.unlock_udomain((udomain_t*)table, &aor);
00455       return -1;
00456    }
00457 
00458    ptr = r->contacts;
00459    ptr0 = NULL;
00460    n = 0;
00461    while(ptr)
00462    {
00463       olen = (ptr->c.len + ptr->received.len + ptr->path.len
00464          + ptr->callid.len + ptr->user_agent.len)*sizeof(char) + ilen;
00465       c0 = (ucontact_t*)pkg_malloc(olen);
00466       if(c0==NULL)
00467       {
00468          LM_ERR("no more pkg\n");
00469          ul.unlock_udomain((udomain_t*)table, &aor);
00470          goto error;
00471       }
00472       memcpy(c0, ptr, ilen);
00473       c0->domain = NULL;
00474       c0->aor = NULL;
00475       c0->next = NULL;
00476       c0->prev = NULL;
00477 
00478       c0->c.s = (char*)c0 + ilen;
00479       memcpy(c0->c.s, ptr->c.s, ptr->c.len);
00480       c0->c.len = ptr->c.len;
00481       p = c0->c.s + c0->c.len;
00482       
00483       if(ptr->received.s!=NULL)
00484       {
00485          c0->received.s = p;
00486          memcpy(c0->received.s, ptr->received.s, ptr->received.len);
00487          c0->received.len = ptr->received.len;
00488          p += c0->received.len;
00489       }
00490       if(ptr->path.s!=NULL)
00491       {
00492          c0->path.s = p;
00493          memcpy(c0->path.s, ptr->path.s, ptr->path.len);
00494          c0->path.len = ptr->path.len;
00495          p += c0->path.len;
00496       }
00497       c0->callid.s = p;
00498       memcpy(c0->callid.s, ptr->callid.s, ptr->callid.len);
00499       c0->callid.len = ptr->callid.len;
00500       p += c0->callid.len;
00501       if(ptr->user_agent.s!=NULL)
00502       {
00503          c0->user_agent.s = p;
00504          memcpy(c0->user_agent.s, ptr->user_agent.s, ptr->user_agent.len);
00505          c0->user_agent.len = ptr->user_agent.len;
00506          p += c0->user_agent.len;
00507       }
00508 
00509       if(ptr0==NULL)
00510       {
00511          rpp->contacts = c0;
00512       } else {
00513          ptr0->next = c0;
00514          c0->prev = ptr0;
00515       }
00516       n++;
00517       ptr0 = c0;
00518       ptr = ptr->next;
00519    }
00520    ul.unlock_udomain((udomain_t*)table, &aor);
00521    rpp->nrc = n;
00522    LM_DBG("fetched <%d> contacts for <%.*s> in [%.*s]\n",
00523          n, aor.len, aor.s, rpp->pname.len, rpp->pname.s);
00524    return 1;
00525 
00526 error:
00527    regpv_free_profile(rpp);
00528    return -1;
00529 }
00530 int pv_free_contacts(struct sip_msg* msg, char* profile, char* s2)
00531 {
00532    regpv_profile_t *rpp;
00533 
00534    rpp = regpv_get_profile((str*)profile);
00535    if(rpp==0)
00536       return -1;
00537 
00538    regpv_free_profile(rpp);
00539 
00540    return 1;
00541 }

Generated on Thu May 24 10:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6