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 
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, NULL) < 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_head_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 }