加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
pvar.c 104.36 KB
一键复制 编辑 原始数据 按行查看 历史
Vlad Paiu 提交于 2014-09-01 12:22 . Added EVENT_ROUTE in $rT output
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798
/**
* $Id$
*
* Copyright (C) 2001-2003 FhG Fokus
* Copyright (C) 2005-2009 Voice Sistem SRL
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* History:
* --------
* 2004-10-20 - added header name specifier (ramona)
* 2005-06-14 - added avp name specifier (ramona)
* 2005-06-18 - added color printing support via escape sequesnces
* contributed by Ingo Flaschberger (daniel)
* 2005-06-22 - created this file from modules/xlog/pv_lib.c (daniel)
* 2009-04-28 - $ct and $ct.fields() PVs added (bogdan)
* 2009-05-02 - $branch() added, $br, $bR, $bf, $bF removed (bogdan)
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include "dprint.h"
#include "mem/mem.h"
#include "mem/shm_mem.h"
#include "ut.h"
#include "trim.h"
#include "dset.h"
#include "action.h"
#include "socket_info.h"
#include "route_struct.h"
#include "usr_avp.h"
#include "errinfo.h"
#include "transformations.h"
#include "script_var.h"
#include "pvar.h"
#include "xlog.h"
#include "parser/parse_from.h"
#include "parser/parse_uri.h"
#include "parser/parse_hname2.h"
#include "parser/parse_content.h"
#include "parser/parse_refer_to.h"
#include "parser/parse_rpid.h"
#include "parser/parse_diversion.h"
#include "parser/parse_ppi.h"
#include "parser/parse_pai.h"
#include "parser/digest/digest.h"
#include "parser/contact/parse_contact.h"
#define is_in_str(p, in) (p<in->s+in->len && *p)
typedef struct _pv_extra
{
pv_export_t pve;
struct _pv_extra *next;
} pv_extra_t, *pv_extra_p;
pv_extra_p *_pv_extra_list=0;
static str str_marker = { PV_MARKER_STR, 1 };
/* IMPORTANT : the "const" strings returned by the var functions must
be read-write (as they may be changed by the script interpreter), so
we need to allocated as array and not as pointing to RO data segment
*/
static char _str_null_hlp[7] = {'<','n','u','l','l','>',0};
static str str_null = { _str_null_hlp, 6 };
static char _str_empty_hlp[1] = { 0 };
static str str_empty = { _str_empty_hlp, 0 };
static char _str_5060_hlp[5] = {'5','0','6','0',0};
static str str_5060 = { _str_5060_hlp, 4 };
static char _str_udp_hlp[4] = {'u','d','p',0};
static str str_udp = { _str_udp_hlp, 3 };
static char _str_tcp_hlp[4] = {'t','c','p',0};
static str str_tcp = { _str_tcp_hlp, 3 };
static char _str_tls_hlp[4] = {'t','l','s',0};
static str str_tls = { _str_tls_hlp, 3 };
static char _str_sctp_hlp[5] = {'s','c','t','p',0};
static str str_sctp = { _str_sctp_hlp, 4 };
static char _str_request_route_hlp[] = {'r','e','q','u','e','s','t','_','r','o','u','t','e',0};
static str str_request_route = { _str_request_route_hlp, 13 };
static char _str_failure_route_hlp[] = {'f','a','i','l','u','r','e','_','r','o','u','t','e',0};
static str str_failure_route = { _str_failure_route_hlp, 13 };
static char _str_onreply_route_hlp[] = {'o','n','r','e','p','l','y','_','r','o','u','t','e',0};
static str str_onreply_route = { _str_onreply_route_hlp, 13 };
static char _str_branch_route_hlp[] = {'b','r','a','n','c','h','_','r','o','u','t','e',0};
static str str_branch_route = { _str_branch_route_hlp, 12 };
static char _str_error_route_hlp[] = {'e','r','r','o','r','_','r','o','u','t','e',0};
static str str_error_route = { _str_error_route_hlp, 11 };
static char _str_local_route_hlp[] = {'l','o','c','a','l','_','r','o','u','t','e',0};
static str str_local_route = { _str_local_route_hlp, 11 };
static char _str_startup_route_hlp[] = {'s','t','a','r','t','u','p','_','r','o','u','t','e',0};
static str str_startup_route = { _str_startup_route_hlp, 13 };
static char _str_timer_route_hlp[] = {'t','i','m','e','r','_','r','o','u','t','e',0};
static str str_timer_route = { _str_timer_route_hlp, 11 };
static char _str_event_route_hlp[] = {'e','v','e','n','t','_','r','o','u','t','e',0};
static str str_event_route = { _str_event_route_hlp, 11 };
int _pv_pid = 0;
#define PV_FIELD_DELIM ", "
#define PV_FIELD_DELIM_LEN (sizeof(PV_FIELD_DELIM) - 1)
#define PV_LOCAL_BUF_SIZE 511
static char pv_local_buf[PV_LOCAL_BUF_SIZE+1];
/* pv context list */
pv_context_t* pv_context_lst = NULL;
pv_context_t* pv_get_context(str* name);
pv_context_t* add_pv_context(str* name, pv_contextf_t get_context);
static int pvc_before_check = 1;
/* route param variable */
extern action_elem_t *route_params;
extern int route_params_number;
static int pv_get_param(struct sip_msg *msg, pv_param_t *ip, pv_value_t *res);
static int pv_parse_param_name(pv_spec_p sp, str *in);
/********** helper functions ********/
/**
* convert unsigned int to pv_value_t
*/
int pv_get_uintval(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, unsigned int uival)
{
int l = 0;
char *ch = NULL;
if(res==NULL)
return -1;
ch = int2str(uival, &l);
res->rs.s = ch;
res->rs.len = l;
res->ri = (int)uival;
res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
return 0;
}
/**
* convert signed int to pv_value_t
*/
int pv_get_sintval(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, int sival)
{
int l = 0;
char *ch = NULL;
if(res==NULL)
return -1;
ch = sint2str(sival, &l);
res->rs.s = ch;
res->rs.len = l;
res->ri = sival;
res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
return 0;
}
/**
* convert str to pv_value_t
*/
int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, str *sval)
{
if(res==NULL)
return -1;
res->rs = *sval;
res->flags = PV_VAL_STR;
return 0;
}
/**
* convert str-int to pv_value_t (type is str)
*/
int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, str *sval, int ival)
{
if(res==NULL)
return -1;
res->rs = *sval;
res->ri = ival;
res->flags = PV_VAL_STR|PV_VAL_INT;
return 0;
}
/**
* convert int-str to pv_value_t (type is int)
*/
int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, int ival, str *sval)
{
if(res==NULL)
return -1;
res->rs = *sval;
res->ri = ival;
res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
return 0;
}
/************************************************************/
static int pv_get_marker(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
return pv_get_strintval(msg, param, res, &str_marker, (int)str_marker.s[0]);
}
int pv_get_null(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
if(res==NULL)
return -1;
res->rs = str_empty;
res->ri = 0;
res->flags = PV_VAL_NULL;
return 0;
}
static int pv_get_udp(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
return pv_get_strintval(msg, param, res, &str_udp, (int)PROTO_UDP);
}
static int pv_get_5060(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
return pv_get_strintval(msg, param, res, &str_5060, 5060);
}
/************************************************************/
static int pv_get_pid(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(_pv_pid == 0)
_pv_pid = (int)getpid();
return pv_get_sintval(msg, param, res, _pv_pid);
}
extern int return_code;
static int pv_get_return_code(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
return pv_get_sintval(msg, param, res, return_code);
}
static int pv_get_times(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
return pv_get_uintval(msg, param, res, (unsigned int)time(NULL));
}
static int pv_get_timem(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
struct timeval TP;
if(msg==NULL)
return -1;
gettimeofday(&TP, NULL);
return pv_get_uintval(msg, param, res, (unsigned int)TP.tv_usec);
}
static int pv_get_start_times(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
return pv_get_uintval(msg, param, res, (unsigned int)startup_time);
}
static int pv_parse_time_name(pv_spec_p sp, str *in)
{
sp->pvp.pvn.type = PV_NAME_INTSTR;
sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
sp->pvp.pvn.u.isname.name.s.s = pkg_malloc(in->len + 1);
if (sp->pvp.pvn.u.isname.name.s.s==NULL) {
LM_ERR("failed to allocated private mem\n");
return -1;
}
memcpy(sp->pvp.pvn.u.isname.name.s.s, in->s, in->len);
sp->pvp.pvn.u.isname.name.s.s[in->len] = 0;
sp->pvp.pvn.u.isname.name.s.len = in->len;
return 0;
}
static int pv_get_formated_time(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
static char buf[128];
time_t t;
if(msg==NULL)
return -1;
time( &t );
res->rs.len = strftime( buf, 127, param->pvn.u.isname.name.s.s,
localtime( &t ) );
if (res->rs.len<=0)
return pv_get_null(msg, param, res);
res->rs.s = buf;
res->flags = PV_VAL_STR;
return 0;
}
static int pv_get_timef(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
time_t t;
str s;
if(msg==NULL)
return -1;
t = time(NULL);
s.s = ctime(&t);
s.len = strlen(s.s)-1;
return pv_get_strintval(msg, param, res, &s, (int)t);
}
static int pv_get_msgid(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
return pv_get_uintval(msg, param, res, msg->id);
}
static int pv_get_method(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->first_line.type == SIP_REQUEST)
{
return pv_get_strintval(msg, param, res,
&msg->first_line.u.request.method,
(int)msg->first_line.u.request.method_value);
}
if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1) ||
(msg->cseq==NULL)))
{
LM_ERR("no CSEQ header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strintval(msg, param, res,
&get_cseq(msg)->method,
get_cseq(msg)->method_id);
}
static int pv_get_status(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->first_line.type != SIP_REPLY)
return pv_get_null(msg, param, res);
return pv_get_intstrval(msg, param, res,
(int)msg->first_line.u.reply.statuscode,
&msg->first_line.u.reply.status);
}
static int pv_get_reason(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->first_line.type != SIP_REPLY)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &msg->first_line.u.reply.reason);
}
static int pv_get_ruri(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL || res==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY) /* REPLY doesnt have a ruri */
return pv_get_null(msg, param, res);
if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0)
{
LM_ERR("failed to parse the R-URI\n");
return pv_get_null(msg, param, res);
}
if (msg->new_uri.s!=NULL)
return pv_get_strval(msg, param, res, &msg->new_uri);
return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri);
}
static int pv_get_ru_q(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL || res==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY)
return pv_get_null(msg, param, res);
return pv_get_sintval(msg, param, res, get_ruri_q());
}
static int pv_get_ouri(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL || res==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY) /* REPLY doesnt have a ruri */
return pv_get_null(msg, param, res);
if(msg->parsed_orig_ruri_ok==0
/* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0)
{
LM_ERR("failed to parse the R-URI\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri);
}
static int pv_get_xuri_attr(struct sip_msg *msg, struct sip_uri *parsed_uri,
pv_param_t *param, pv_value_t *res)
{
if(param->pvn.u.isname.name.n==1) /* username */
{
if(parsed_uri->user.s==NULL || parsed_uri->user.len<=0)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &parsed_uri->user);
} else if(param->pvn.u.isname.name.n==2) /* domain */ {
if(parsed_uri->host.s==NULL || parsed_uri->host.len<=0)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &parsed_uri->host);
} else if(param->pvn.u.isname.name.n==3) /* port */ {
if(parsed_uri->port.s==NULL)
return pv_get_5060(msg, param, res);
return pv_get_strintval(msg, param, res, &parsed_uri->port,
(int)parsed_uri->port_no);
} else if(param->pvn.u.isname.name.n==4) /* protocol */ {
if(parsed_uri->transport_val.s==NULL)
return pv_get_udp(msg, param, res);
return pv_get_strintval(msg, param, res, &parsed_uri->transport_val,
(int)parsed_uri->proto);
}
LM_ERR("unknown specifier\n");
return pv_get_null(msg, param, res);
}
static int pv_get_ruri_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY) /* REPLY doesnt have a ruri */
return pv_get_null(msg, param, res);
if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0)
{
LM_ERR("failed to parse the R-URI\n");
return pv_get_null(msg, param, res);
}
return pv_get_xuri_attr(msg, &(msg->parsed_uri), param, res);
}
static int pv_get_ouri_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY) /* REPLY doesnt have a ruri */
return pv_get_null(msg, param, res);
if(msg->parsed_orig_ruri_ok==0
/* orig R-URI not parsed*/ && parse_orig_ruri(msg)<0)
{
LM_ERR("failed to parse the R-URI\n");
return pv_get_null(msg, param, res);
}
return pv_get_xuri_attr(msg, &(msg->parsed_orig_ruri), param, res);
}
static int pv_get_path(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(!msg->path_vec.s)
{
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->path_vec);
}
#define CT_NAME_S "name"
#define CT_NAME_LEN (sizeof(CT_NAME_S)-1)
#define CT_NAME_ID 1
#define CT_URI_S "uri"
#define CT_URI_LEN (sizeof(CT_URI_S)-1)
#define CT_URI_ID 2
#define CT_Q_S "q"
#define CT_Q_LEN (sizeof(CT_Q_S)-1)
#define CT_Q_ID 3
#define CT_EXPIRES_S "expires"
#define CT_EXPIRES_LEN (sizeof(CT_EXPIRES_S)-1)
#define CT_EXPIRES_ID 4
#define CT_METHODS_S "methods"
#define CT_METHODS_LEN (sizeof(CT_METHODS_S)-1)
#define CT_METHODS_ID 5
#define CT_RECEIVED_S "received"
#define CT_RECEIVED_LEN (sizeof(CT_RECEIVED_S)-1)
#define CT_RECEIVED_ID 6
#define CT_PARAMS_S "params"
#define CT_PARAMS_LEN (sizeof(CT_PARAMS_S)-1)
#define CT_PARAMS_ID 7
int pv_parse_ct_name(pv_spec_p sp, str *in)
{
if (sp==NULL)
return -1;
sp->pvp.pvn.type = PV_NAME_INTSTR;
sp->pvp.pvn.u.isname.type = 0;
if (in==NULL || in->s==NULL || in->len==0) {
sp->pvp.pvn.u.isname.name.n = 0;
} else
if (in->len==CT_NAME_LEN &&
strncasecmp(in->s, CT_NAME_S, CT_NAME_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_NAME_ID;
} else
if (in->len==CT_URI_LEN &&
strncasecmp(in->s, CT_URI_S, CT_URI_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_URI_ID;
} else
if (in->len==CT_Q_LEN &&
strncasecmp(in->s, CT_Q_S, CT_Q_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_Q_ID;
} else
if (in->len==CT_EXPIRES_LEN &&
strncasecmp(in->s, CT_EXPIRES_S, CT_EXPIRES_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_EXPIRES_ID;
} else
if (in->len==CT_METHODS_LEN &&
strncasecmp(in->s, CT_METHODS_S, CT_METHODS_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_METHODS_ID;
} else
if (in->len==CT_RECEIVED_LEN &&
strncasecmp(in->s, CT_RECEIVED_S, CT_RECEIVED_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_RECEIVED_ID;
} else
if (in->len==CT_PARAMS_LEN &&
strncasecmp(in->s, CT_PARAMS_S, CT_PARAMS_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = CT_PARAMS_ID;
} else {
LM_ERR("unsupported CT field <%.*s>\n",in->len,in->s);
return -1;
}
return 0;
}
static inline int get_contact_body_field(pv_value_t *res,struct hdr_field *cth,
contact_t *ct, pv_name_t *pvn)
{
param_t *p;
if (ct==NULL) {
/* star contact hdr */
if (pvn->u.isname.name.n==0) {
res->rs = cth->body;
res->flags = PV_VAL_STR;
return 0;
}
return pv_get_null(NULL, NULL, res);
}
switch (pvn->u.isname.name.n) {
case 0: /* all body */
res->rs.s = ct->name.s?ct->name.s:ct->uri.s;
res->rs.len = ct->len;
break;
case CT_NAME_ID: /* name only */
if (ct->name.s==NULL || ct->name.len==0)
return pv_get_null(NULL, NULL, res);
res->rs = ct->name;
break;
case CT_URI_ID: /* uri only */
res->rs = ct->uri;
break;
case CT_Q_ID: /* Q param only */
if ( !ct->q || !ct->q->body.s || !ct->q->body.len)
return pv_get_null(NULL, NULL, res);
res->rs = ct->q->body;
break;
case CT_EXPIRES_ID: /* EXPIRES param only */
if (!ct->expires||!ct->expires->body.s||!ct->expires->body.len)
return pv_get_null(NULL, NULL, res);
res->rs = ct->expires->body;
break;
case CT_METHODS_ID: /* METHODS param only */
if (!ct->methods||!ct->methods->body.s||!ct->methods->body.len)
return pv_get_null(NULL, NULL, res);
res->rs = ct->methods->body;
break;
case CT_RECEIVED_ID: /* RECEIVED param only */
if(!ct->received||!ct->received->body.s||!ct->received->body.len)
return pv_get_null(NULL, NULL, res);
res->rs = ct->received->body;
break;
case CT_PARAMS_ID: /* all param */
if (!ct->params)
return pv_get_null(NULL, NULL, res);
res->rs.s = ct->params->name.s;
for( p=ct->params ; p->next ; p=p->next);
res->rs.len = p->name.s + p->len - res->rs.s;
break;
default:
LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.type);
return pv_get_null(NULL, NULL, res);
}
res->flags = PV_VAL_STR;
return 0;
}
static int pv_get_contact_body(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
struct hdr_field *ct_h;
contact_body_t *ct_b;
contact_t *ct;
int idx;
int idxf;
char *p;
if(msg==NULL)
return -1;
/* get all CONTACT headers */
if(msg->contact==NULL && parse_headers(msg, HDR_EOH_F, 0)==-1)
{
LM_DBG("no contact header\n");
return pv_get_null(msg, param, res);
}
if(!msg->contact || !msg->contact->body.s || msg->contact->body.len<=0)
{
LM_DBG("no contact header!\n");
return pv_get_null(msg, param, res);
}
ct_h = msg->contact;
if (parse_contact( ct_h )!=0) {
LM_ERR("failed to parse contact hdr\n");
return -1;
}
ct_b = (contact_body_t*)ct_h->parsed;
if (ct_b==NULL)
return pv_get_null(msg, param, res);
ct = ct_b->contacts;
/* get the index */
if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
LM_ERR("invalid index\n");
return -1;
}
if( idxf!=PV_IDX_ALL && idx==0) {
/* no index specified -> return the first contact body */
return get_contact_body_field( res , ct_h, ct, &param->pvn);
}
if(idxf==PV_IDX_ALL) {
/* return all contact bodies */
p = pv_local_buf;
do {
if(p!=pv_local_buf) {
if (p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE){
LM_ERR("local buffer length exceeded\n");
return pv_get_null(msg, param, res);
}
memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
p += PV_FIELD_DELIM_LEN;
}
get_contact_body_field( res , ct_h, ct, &param->pvn);
if (p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE) {
LM_ERR("local buffer length exceeded!\n");
return pv_get_null(msg, param, res);
}
memcpy(p, res->rs.s, res->rs.len);
p += res->rs.len;
ct = ct?ct->next:NULL;
while (ct==NULL && ct_h!=NULL) {
ct_h = ct_h->sibling;
if (ct_h) {
if (parse_contact( ct_h )!=0) {
LM_ERR("failed to parse contact hdr\n");
return -1;
}
ct_b = (contact_body_t*)ct_h->parsed;
ct = ct_b->contacts;
}
}
} while (ct_h);
res->rs.s = pv_local_buf;
res->rs.len = p - pv_local_buf;
res->flags = PV_VAL_STR;
return 0;
}
/* numerical index */
if (idx<0) {
/* index from the end */
idxf=0;
while(ct_h) {
idxf++;
ct = ct?ct->next:NULL;
while (ct==NULL && ct_h!=NULL) {
ct_h = ct_h->sibling;
if (ct_h) {
if (parse_contact( ct_h)!=0) {
LM_ERR("failed to parse contact hdr\n");
return -1;
}
ct_b = (contact_body_t*)ct_h->parsed;
ct = ct_b->contacts;
}
}
}
if (-idx>idxf)
return pv_get_null(msg, param, res);
idx = idxf +idx;
ct_h = msg->contact;
ct_b = (contact_body_t*)ct_h->parsed;
ct = ct_b->contacts;
}
while (idx!=0 && ct_h) {
/* get to the next contact body */
idx--;
ct = ct?ct->next:NULL;
while (ct==NULL && ct_h!=NULL) {
ct_h = ct_h->sibling;
if (ct_h) {
if (parse_contact( ct_h )!=0) {
LM_ERR("failed to parse contact hdr\n");
return -1;
}
ct_b = (contact_body_t*)ct_h->parsed;
ct = ct_b->contacts;
}
}
}
/* nothing found ?*/
if (ct==NULL)
return pv_get_null(msg, param, res);
/* take the current body */
return get_contact_body_field( res , ct_h, ct, &param->pvn);
}
extern err_info_t _oser_err_info;
static int pv_get_errinfo_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(param->pvn.u.isname.name.n==0) /* class */ {
return pv_get_sintval(msg, param, res, _oser_err_info.eclass);
} else if(param->pvn.u.isname.name.n==1) /* level */ {
return pv_get_sintval(msg, param, res, _oser_err_info.level);
} else if(param->pvn.u.isname.name.n==2) /* info */ {
if(_oser_err_info.info.s==NULL)
pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &_oser_err_info.info);
} else if(param->pvn.u.isname.name.n==3) /* rcode */ {
return pv_get_sintval(msg, param, res, _oser_err_info.rcode);
} else if(param->pvn.u.isname.name.n==4) /* rreason */ {
if(_oser_err_info.rreason.s==NULL)
pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &_oser_err_info.rreason);
} else {
LM_DBG("invalid attribute!\n");
return pv_get_null(msg, param, res);
}
}
static int pv_get_xto_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res, struct to_body *xto, int type)
{
struct sip_uri *uri;
if(xto==NULL)
return -1;
if(param->pvn.u.isname.name.n==1) /* uri */
return pv_get_strval(msg, param, res, &xto->uri);
if(param->pvn.u.isname.name.n==4) /* tag */
{
if (xto->tag_value.s==NULL || xto->tag_value.len<=0)
{
LM_DBG("no Tag parameter\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &xto->tag_value);
}
if(param->pvn.u.isname.name.n==5) /* display name */
{
if(xto->display.s==NULL || xto->display.len<=0)
{
LM_DBG("no Display name\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &xto->display);
}
if(type==0)
{
if((uri=parse_to_uri(msg))==NULL)
{
LM_ERR("cannot parse To URI\n");
return pv_get_null(msg, param, res);
}
} else {
if((uri=parse_from_uri(msg))==NULL)
{
LM_ERR("cannot parse From URI\n");
return pv_get_null(msg, param, res);
}
}
if(param->pvn.u.isname.name.n==2) /* username */
{
if(uri->user.s==NULL || uri->user.len<=0)
{
LM_DBG("no username\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &uri->user);
} else if(param->pvn.u.isname.name.n==3) /* domain */ {
if(uri->host.s==NULL || uri->host.len<=0)
{
LM_DBG("no domain\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &uri->host);
}
LM_ERR("unknown specifier\n");
return pv_get_null(msg, param, res);
}
static int pv_get_to_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->to==NULL && parse_headers(msg, HDR_TO_F, 0)==-1)
{
LM_ERR("cannot parse To header\n");
return pv_get_null(msg, param, res);
}
if(msg->to==NULL || get_to(msg)==NULL) {
LM_DBG("no To header\n");
return pv_get_null(msg, param, res);
}
return pv_get_xto_attr(msg, param, res, get_to(msg), 0);
}
static int pv_get_from_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(parse_from_header(msg)<0)
{
LM_ERR("cannot parse From header\n");
return pv_get_null(msg, param, res);
}
if(msg->from==NULL || get_from(msg)==NULL) {
LM_DBG("no From header\n");
return pv_get_null(msg, param, res);
}
return pv_get_xto_attr(msg, param, res, get_from(msg), 1);
}
static int pv_get_cseq(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
|| (msg->cseq==NULL)) )
{
LM_ERR("cannot parse CSEQ header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &(get_cseq(msg)->number));
}
static int pv_get_msg_buf(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
if(msg==NULL)
return -1;
s.s = msg->buf;
s.len = msg->len;
return pv_get_strval(msg, param, res, &s);
}
static int pv_get_msg_len(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
return pv_get_uintval(msg, param, res, msg->len);
}
static int pv_get_flags(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str buf;
if (!msg)
return -1;
buf = bitmask_to_flag_list(FLAG_TYPE_MSG, msg->flags);
return pv_get_strval(msg, param, res, &buf);
}
static inline char* int_to_8hex(int val)
{
unsigned short digit;
int i;
static char outbuf[9];
outbuf[8] = '\0';
for(i=0; i<8; i++)
{
if(val!=0)
{
digit = val & 0x0f;
outbuf[7-i] = digit >= 10 ? digit + 'a' - 10 : digit + '0';
val >>= 4;
}
else
outbuf[7-i] = '0';
}
return outbuf;
}
static int pv_get_bflags(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str buf;
if (!msg)
return -1;
buf = bitmask_to_flag_list(FLAG_TYPE_BRANCH, getb0flags());
return pv_get_strval(msg, param, res, &buf);
}
static int pv_get_sflags(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str buf;
if (!msg)
return -1;
buf = bitmask_to_flag_list(FLAG_TYPE_SCRIPT, getsflags());
return pv_get_strval(msg, param, res, &buf);
}
static int pv_get_callid(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->callid==NULL && ((parse_headers(msg, HDR_CALLID_F, 0)==-1) ||
(msg->callid==NULL)) )
{
LM_ERR("cannot parse Call-Id header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->callid->body);
}
static int pv_get_srcip(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
if(msg==NULL)
return -1;
s.s = ip_addr2a(&msg->rcv.src_ip);
s.len = strlen(s.s);
return pv_get_strval(msg, param, res, &s);
}
static int pv_get_srcport(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
return pv_get_uintval(msg, param, res, msg->rcv.src_port);
}
static int pv_get_rcvip(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->rcv.bind_address==NULL
|| msg->rcv.bind_address->address_str.s==NULL)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &msg->rcv.bind_address->address_str);
}
static int pv_get_rcvport(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->rcv.bind_address==NULL
|| msg->rcv.bind_address->port_no_str.s==NULL)
return pv_get_null(msg, param, res);
return pv_get_intstrval(msg, param, res,
(int)msg->rcv.bind_address->port_no,
&msg->rcv.bind_address->port_no_str);
}
static int pv_get_force_sock(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if (msg->force_send_socket==0)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &msg->force_send_socket->sock_str);
}
static int pv_get_useragent(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->user_agent==NULL && ((parse_headers(msg, HDR_USERAGENT_F, 0)==-1)
|| (msg->user_agent==NULL)))
{
LM_DBG("no User-Agent header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->user_agent->body);
}
static int pv_get_refer_to(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(parse_refer_to_header(msg)==-1)
{
LM_DBG("no Refer-To header\n");
return pv_get_null(msg, param, res);
}
if(msg->refer_to==NULL || get_refer_to(msg)==NULL)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &(get_refer_to(msg)->uri));
}
static int pv_get_route_type(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
switch(route_type)
{
case REQUEST_ROUTE:
s = str_request_route;
break;
case FAILURE_ROUTE:
s = str_failure_route;
break;
case ONREPLY_ROUTE:
s = str_onreply_route;
break;
case BRANCH_ROUTE:
s = str_branch_route;
break;
case ERROR_ROUTE:
s = str_error_route;
break;
case LOCAL_ROUTE:
s = str_local_route;
break;
case STARTUP_ROUTE:
s = str_startup_route;
break;
case TIMER_ROUTE:
s = str_timer_route;
break;
case EVENT_ROUTE:
s = str_event_route;
default:
s = str_null;
}
return pv_get_strval(msg, param, res, &s);
}
static int pv_get_diversion(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str *val;
str name;
if(msg == NULL)
return -1;
if(parse_diversion_header(msg) == -1)
{
LM_DBG("no Diversion header\n");
return pv_get_null(msg, param, res);
}
if(msg->diversion == NULL || get_diversion(msg) == NULL)
{
LM_DBG("no Diversion header\n");
return pv_get_null(msg, param, res);
}
if(param->pvn.u.isname.name.n == 1) { /* uri */
return pv_get_strval(msg, param, res, &(get_diversion(msg)->uri));
}
if(param->pvn.u.isname.name.n == 2) { /* reason param */
name.s = "reason";
name.len = 6;
val = diversion_param(msg, name);
if (val) {
return pv_get_strval(msg, param, res, val);
} else {
return pv_get_null(msg, param, res);
}
}
if(param->pvn.u.isname.name.n == 3) { /* privacy param */
name.s = "privacy";
name.len = 7;
val = diversion_param(msg, name);
if (val) {
return pv_get_strval(msg, param, res, val);
} else {
return pv_get_null(msg, param, res);
}
}
LM_ERR("unknown diversion specifier\n");
return pv_get_null(msg, param, res);
}
static int pv_get_rpid(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(parse_rpid_header(msg)==-1)
{
LM_DBG("no RPID header\n");
return pv_get_null(msg, param, res);
}
if(msg->rpid==NULL || get_rpid(msg)==NULL)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &(get_rpid(msg)->uri));
}
static int pv_get_ppi_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
struct sip_uri *uri;
if(msg==NULL)
return -1;
if(parse_ppi_header(msg) < 0) {
LM_DBG("no P-Preferred-Identity header\n");
return pv_get_null(msg, param, res);
}
if(msg->ppi == NULL || get_ppi(msg) == NULL) {
LM_DBG("no P-Preferred-Identity header\n");
return pv_get_null(msg, param, res);
}
if(param->pvn.u.isname.name.n == 1) { /* uri */
return pv_get_strval(msg, param, res, &(get_ppi(msg)->uri));
}
if(param->pvn.u.isname.name.n==4) { /* display name */
if(get_ppi(msg)->display.s == NULL ||
get_ppi(msg)->display.len <= 0) {
LM_DBG("no P-Preferred-Identity display name\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &(get_ppi(msg)->display));
}
if((uri=parse_ppi_uri(msg))==NULL) {
LM_ERR("cannot parse P-Preferred-Identity URI\n");
return pv_get_null(msg, param, res);
}
if(param->pvn.u.isname.name.n==2) { /* username */
if(uri->user.s==NULL || uri->user.len<=0) {
LM_DBG("no P-Preferred-Identity username\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &uri->user);
} else if(param->pvn.u.isname.name.n==3) { /* domain */
if(uri->host.s==NULL || uri->host.len<=0) {
LM_DBG("no P-Preferred-Identity domain\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &uri->host);
}
LM_ERR("unknown specifier\n");
return pv_get_null(msg, param, res);
}
static int pv_get_pai(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(parse_pai_header(msg)==-1)
{
LM_DBG("no P-Asserted-Identity header\n");
return pv_get_null(msg, param, res);
}
if(msg->pai==NULL || get_pai(msg)==NULL) {
LM_DBG("no P-Asserted-Identity header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &(get_pai(msg)->uri));
}
/* proto of received message: $pr or $proto*/
static int pv_get_proto(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
if(msg==NULL)
return -1;
switch(msg->rcv.proto)
{
case PROTO_UDP:
s = str_udp;
break;
case PROTO_TCP:
s = str_tcp;
break;
case PROTO_TLS:
s = str_tls;
break;
case PROTO_SCTP:
s = str_sctp;
break;
default:
s = str_null;
}
return pv_get_strintval(msg, param, res, &s, (int)msg->rcv.proto);
}
static int pv_get_dset(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
if(msg==NULL)
return -1;
s.s = print_dset(msg, &s.len);
if (s.s == NULL)
return pv_get_null(msg, param, res);
s.len -= CRLF_LEN;
return pv_get_strval(msg, param, res, &s);
}
static int pv_get_dsturi(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if (msg->dst_uri.s == NULL) {
LM_DBG("no destination URI\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->dst_uri);
}
static int pv_get_dsturi_attr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
struct sip_uri uri;
if(msg==NULL)
return -1;
if (msg->dst_uri.s == NULL) {
LM_DBG("no destination URI\n");
return pv_get_null(msg, param, res);
}
if(parse_uri(msg->dst_uri.s, msg->dst_uri.len, &uri)!=0)
{
LM_ERR("failed to parse dst uri\n");
return pv_get_null(msg, param, res);
}
if(param->pvn.u.isname.name.n==1) /* domain */
{
if(uri.host.s==NULL || uri.host.len<=0)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &uri.host);
} else if(param->pvn.u.isname.name.n==2) /* port */ {
if(uri.port.s==NULL)
return pv_get_5060(msg, param, res);
return pv_get_strintval(msg, param, res, &uri.port, (int)uri.port_no);
} else if(param->pvn.u.isname.name.n==3) /* proto */ {
if(uri.transport_val.s==NULL)
return pv_get_udp(msg, param, res);
return pv_get_strintval(msg, param, res, &uri.transport_val,
(int)uri.proto);
}
LM_ERR("invalid specifier\n");
return pv_get_null(msg, param, res);
}
static int pv_get_content_type(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->content_type==NULL
&& ((parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1)
|| (msg->content_type==NULL)))
{
LM_DBG("no Content-Type header\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &msg->content_type->body);
}
static int pv_get_content_length(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
if(msg==NULL)
return -1;
if(msg->content_length==NULL
&& ((parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1)
|| (msg->content_length==NULL)))
{
LM_DBG("no Content-Length header\n");
return pv_get_null(msg, param, res);
}
return pv_get_intstrval(msg, param, res,
(int)(long)msg->content_length->parsed,
&msg->content_length->body);
}
static int pv_get_msg_body(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str s;
if(msg==NULL)
return -1;
if (get_body( msg, &s)!=0 || s.len==0 )
{
LM_DBG("no message body\n");
return pv_get_null(msg, param, res);
}
return pv_get_strval(msg, param, res, &s);
}
static int pv_get_authattr(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
struct hdr_field *hdr;
str *s;
if(msg==NULL)
return -1;
if ((msg->REQ_METHOD==METHOD_ACK) || (msg->REQ_METHOD==METHOD_CANCEL)) {
LM_DBG("no [Proxy-]Authorization header\n");
return pv_get_null(msg, param, res);
}
if ((parse_headers(msg, HDR_PROXYAUTH_F|HDR_AUTHORIZATION_F, 0)==-1)
|| (msg->proxy_auth==0 && msg->authorization==0))
{
LM_DBG("no [Proxy-]Authorization header\n");
return pv_get_null(msg, param, res);
}
hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth;
if(parse_credentials(hdr)!=0) {
LM_ERR("failed to parse credentials\n");
return pv_get_null(msg, param, res);
}
switch(param->pvn.u.isname.name.n)
{
case 11:
s = &((auth_body_t*)(hdr->parsed))->digest.nc;
break;
case 10:
s = &((auth_body_t*)(hdr->parsed))->digest.qop.qop_str;
break;
case 9:
s = &((auth_body_t*)(hdr->parsed))->digest.alg.alg_str;
break;
case 8:
s = &((auth_body_t*)(hdr->parsed))->digest.opaque;
break;
case 7:
s = &((auth_body_t*)(hdr->parsed))->digest.cnonce;
break;
case 6:
s = &((auth_body_t*)(hdr->parsed))->digest.response;
break;
case 5:
s = &((auth_body_t*)(hdr->parsed))->digest.nonce;
break;
case 4:
s = &((auth_body_t*)(hdr->parsed))->digest.username.domain;
break;
case 3:
s = &((auth_body_t*)(hdr->parsed))->digest.uri;
break;
case 2:
s = &((auth_body_t*)(hdr->parsed))->digest.realm;
break;
case 1:
s = &((auth_body_t*)(hdr->parsed))->digest.username.user;
break;
default:
s = &((auth_body_t*)(hdr->parsed))->digest.username.whole;
}
if (s->len==0)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, s);
}
static inline str *cred_user(struct sip_msg *rq)
{
struct hdr_field* h;
auth_body_t* cred;
get_authorized_cred(rq->proxy_auth, &h);
if (!h) get_authorized_cred(rq->authorization, &h);
if (!h) return 0;
cred=(auth_body_t*)(h->parsed);
if (!cred || !cred->digest.username.user.len)
return 0;
return &cred->digest.username.user;
}
static inline str *cred_realm(struct sip_msg *rq)
{
str* realm;
struct hdr_field* h;
auth_body_t* cred;
get_authorized_cred(rq->proxy_auth, &h);
if (!h) get_authorized_cred(rq->authorization, &h);
if (!h) return 0;
cred=(auth_body_t*)(h->parsed);
if (!cred) return 0;
realm = GET_REALM(&cred->digest);
if (!realm->len || !realm->s) {
return 0;
}
return realm;
}
static int pv_get_acc_username(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
static char buf[MAX_URI_SIZE];
str* user;
str* realm;
struct sip_uri puri;
struct to_body* from;
str s;
/* try to take it from credentials */
user = cred_user(msg);
if (user) {
realm = cred_realm(msg);
if (realm) {
s.len = user->len+1+realm->len;
if (s.len > MAX_URI_SIZE) {
LM_ERR("uri too long\n");
return pv_get_null(msg, param, res);
}
s.s = buf;
memcpy(s.s, user->s, user->len);
(s.s)[user->len] = '@';
memcpy(s.s+user->len+1, realm->s, realm->len);
return pv_get_strval(msg, param, res, &s);
}
return pv_get_strval(msg, param, res, user);
}
/* from from uri */
if(parse_from_header(msg)<0)
{
LM_ERR("cannot parse FROM header\n");
return pv_get_null(msg, param, res);
}
if (msg->from && (from=get_from(msg)) && from->uri.len) {
if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) {
LM_ERR("bad From URI\n");
return pv_get_null(msg, param, res);
}
s.len = puri.user.len + 1 + puri.host.len;
if (s.len > MAX_URI_SIZE) {
LM_ERR("from URI too long\n");
return pv_get_null(msg, param, res);
}
s.s = buf;
memcpy(s.s, puri.user.s, puri.user.len);
(s.s)[puri.user.len] = '@';
memcpy(s.s + puri.user.len + 1, puri.host.s, puri.host.len);
} else {
s.len = 0;
s.s = 0;
}
return pv_get_strval(msg, param, res, &s);
}
#define BR_URI_S "uri"
#define BR_URI_LEN (sizeof(BR_URI_S)-1)
#define BR_URI_ID 1
#define BR_DURI_S "duri"
#define BR_DURI_LEN (sizeof(BR_DURI_S)-1)
#define BR_DURI_ID 2
#define BR_Q_S "q"
#define BR_Q_LEN (sizeof(BR_Q_S)-1)
#define BR_Q_ID 3
#define BR_PATH_S "path"
#define BR_PATH_LEN (sizeof(BR_PATH_S)-1)
#define BR_PATH_ID 4
#define BR_FLAGS_S "flags"
#define BR_FLAGS_LEN (sizeof(BR_FLAGS_S)-1)
#define BR_FLAGS_ID 5
#define BR_SOCKET_S "socket"
#define BR_SOCKET_LEN (sizeof(BR_SOCKET_S)-1)
#define BR_SOCKET_ID 6
int pv_parse_branch_name(pv_spec_p sp, str *in)
{
if (sp==NULL || in==NULL || in->s==NULL || in->len==0)
return -1;
sp->pvp.pvn.type = PV_NAME_INTSTR;
sp->pvp.pvn.u.isname.type = 0;
if (in->len==BR_URI_LEN &&
strncasecmp(in->s, BR_URI_S, BR_URI_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_URI_ID;
} else
if (in->len==BR_DURI_LEN &&
strncasecmp(in->s, BR_DURI_S, BR_DURI_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_DURI_ID;
} else
if (in->len==BR_Q_LEN &&
strncasecmp(in->s, BR_Q_S, BR_Q_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_Q_ID;
} else
if (in->len==BR_PATH_LEN &&
strncasecmp(in->s, BR_PATH_S, BR_PATH_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_PATH_ID;
} else
if (in->len==BR_FLAGS_LEN &&
strncasecmp(in->s, BR_FLAGS_S, BR_FLAGS_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_FLAGS_ID;
} else
if (in->len==BR_SOCKET_LEN &&
strncasecmp(in->s, BR_SOCKET_S, BR_SOCKET_LEN)==0 ) {
sp->pvp.pvn.u.isname.name.n = BR_SOCKET_ID;
} else {
LM_ERR("unsupported BRANCH field <%.*s>\n",in->len,in->s);
return -1;
}
return 0;
}
static inline int get_branch_field( int idx, pv_name_t *pvn, pv_value_t *res)
{
str uri;
qvalue_t q;
str duri;
str path;
unsigned int flags;
struct socket_info *si;
uri.s = get_branch(idx, &uri.len, &q, &duri, &path, &flags, &si);
if (!uri.s)
return pv_get_null( NULL, NULL, res);
/* got a valid branch, return the field */
switch (pvn->u.isname.name.n) {
case 0:
case BR_URI_ID: /* return URI */
res->rs = uri;
res->flags = PV_VAL_STR;
break;
case BR_Q_ID: /* return Q */
res->rs.s = q2str(q, (unsigned int*)&res->rs.len);
res->flags = PV_VAL_STR;
break;
case BR_DURI_ID: /* return DURI */
if ( !duri.s || !duri.len)
return pv_get_null(NULL, NULL, res);
res->rs = duri;
res->flags = PV_VAL_STR;
break;
case BR_PATH_ID: /* return PATH */
if ( !path.s || !path.len)
return pv_get_null(NULL, NULL, res);
res->rs = path;
res->flags = PV_VAL_STR;
break;
case BR_FLAGS_ID: /* return FLAGS */
res->rs.s = int2str( flags, &res->rs.len);
res->ri = flags;
res->flags = PV_VAL_STR|PV_VAL_INT;
break;
case BR_SOCKET_ID: /* return SOCKET */
if ( !si )
return pv_get_null(NULL, NULL, res);
res->rs = si->sock_str;
res->flags = PV_VAL_STR;
break;
default:
LM_CRIT("BUG - unsupported ID %d\n",pvn->u.isname.name.n);
return pv_get_null(NULL, NULL, res);
}
return 0;
}
static int pv_get_branch_fields(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
str uri;
qvalue_t q;
int idx;
int idxf;
char *p;
if(msg==NULL || res==NULL)
return -1;
if(msg->first_line.type == SIP_REPLY || nr_branches==0 )
return pv_get_null(msg, param, res);
/* get the index */
if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
LM_ERR("invalid index\n");
return -1;
}
if (idxf!=PV_IDX_ALL && idx==0) {
/* no index specified -> return the first branch */
return get_branch_field( 0, &param->pvn, res);
}
if(idxf==PV_IDX_ALL) {
/* return all branches */
p = pv_local_buf;
idx = 0;
while ( (uri.s=get_branch(idx, &uri.len, &q, 0, 0, 0, 0))!=NULL ) {
if ( pv_local_buf + PV_LOCAL_BUF_SIZE <=
p + uri.len + PV_FIELD_DELIM_LEN ) {
LM_ERR("local buffer length exceeded\n");
return pv_get_null(msg, param, res);
}
if (idx) {
memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
p += PV_FIELD_DELIM_LEN;
}
memcpy(p, uri.s, uri.len);
p += uri.len;
idx++;
}
res->rs.s = pv_local_buf;
res->rs.len = p - pv_local_buf;
res->flags = PV_VAL_STR;
return 0;
}
/* numerical index */
if (idx<0) {
/* index from the end */
if (-idx > nr_branches)
return pv_get_null(msg, param, res);
idx = nr_branches + idx;
}
/* return the request branch info */
return get_branch_field( idx, &param->pvn, res);
}
/************************************************************/
/**
*
*/
static int pv_get_avp(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
unsigned short name_type;
int avp_name;
int_str avp_value;
struct usr_avp *avp;
int_str avp_value0;
struct usr_avp *avp0;
int idx;
int idxf;
char *p;
int n=0;
if(msg==NULL || res==NULL || param==NULL)
return -1;
/* get the name */
if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
{
LM_ERR("invalid name\n");
return -1;
}
/* get the index */
if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
{
LM_ERR("invalid index\n");
return -1;
}
if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0)
return pv_get_null(msg, param, res);
res->flags = PV_VAL_STR;
if (idxf!=PV_IDX_ALL && idx==0)
{
if(avp->flags & AVP_VAL_STR)
{
res->rs = avp_value.s;
} else {
res->rs.s = sint2str(avp_value.n, &res->rs.len);
res->ri = avp_value.n;
res->flags |= PV_VAL_INT|PV_TYPE_INT;
}
return 0;
}
/* print the entire AVP array */
if(idxf==PV_IDX_ALL)
{
p = pv_local_buf;
/* separately handle the first AVP */
if(avp->flags & AVP_VAL_STR)
{
res->rs = avp_value.s;
} else {
res->rs.s = sint2str(avp_value.n, &res->rs.len);
}
if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
{
LM_ERR("local buffer length exceeded!\n");
return pv_get_null(msg, param, res);
}
memcpy(p, res->rs.s, res->rs.len);
p += res->rs.len;
/* print subsequent AVPs as [DELIM AVP]* */
while ((avp = search_first_avp(name_type, avp_name, &avp_value, avp)))
{
if(avp->flags & AVP_VAL_STR)
{
res->rs = avp_value.s;
} else {
res->rs.s = sint2str(avp_value.n, &res->rs.len);
}
if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
{
LM_ERR("local buffer length exceeded\n");
return pv_get_null(msg, param, res);
}
memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
p += PV_FIELD_DELIM_LEN;
if(p-pv_local_buf+res->rs.len+1>PV_LOCAL_BUF_SIZE)
{
LM_ERR("local buffer length exceeded!\n");
return pv_get_null(msg, param, res);
}
memcpy(p, res->rs.s, res->rs.len);
p += res->rs.len;
}
*p = 0;
res->rs.s = pv_local_buf;
res->rs.len = p - pv_local_buf;
return 0;
}
/* we have a numeric index */
if(idx<0)
{
n = 1;
avp0 = avp;
while ((avp0=search_first_avp(name_type, avp_name,
&avp_value0, avp0))!=0) n++;
idx = -idx;
if(idx>n)
{
LM_DBG("index out of range\n");
return pv_get_null(msg, param, res);
}
idx = n - idx;
if(idx==0)
{
if(avp->flags & AVP_VAL_STR)
{
res->rs = avp_value.s;
} else {
res->rs.s = sint2str(avp_value.n, &res->rs.len);
res->ri = avp_value.n;
res->flags |= PV_VAL_INT|PV_TYPE_INT;
}
return 0;
}
}
n=0;
while(n<idx
&& (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0)
n++;
if(avp!=0)
{
if(avp->flags & AVP_VAL_STR)
{
res->rs = avp_value.s;
} else {
res->rs.s = sint2str(avp_value.n, &res->rs.len);
res->ri = avp_value.n;
res->flags |= PV_VAL_INT|PV_TYPE_INT;
}
return 0;
}
LM_DBG("index out of range\n");
return pv_get_null(msg, param, res);
}
static int pv_get_hdr_prolog(struct sip_msg *msg, pv_param_t *param, pv_value_t *res, pv_value_t* tv)
{
if(msg==NULL || res==NULL || param==NULL)
return -1;
/* get the name */
if(param->pvn.type == PV_NAME_PVAR)
{
if(pv_get_spec_name(msg, param, tv)!=0 || (!(tv->flags&PV_VAL_STR)))
{
LM_ERR("invalid name\n");
return -1;
}
} else {
if(param->pvn.u.isname.type == AVP_NAME_STR)
{
tv->flags = PV_VAL_STR;
tv->rs = param->pvn.u.isname.name.s;
} else {
tv->flags = 0;
tv->ri = param->pvn.u.isname.name.n;
}
}
/* we need to be sure we have parsed all headers */
if(parse_headers(msg, HDR_EOH_F, 0)<0)
{
LM_ERR("error parsing headers\n");
return pv_get_null(msg, param, res);
}
return 1;
}
static int pv_get_hdrcnt(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
pv_value_t tv;
struct hdr_field *hf;
unsigned int n;
int ret;
if ( (ret=pv_get_hdr_prolog(msg, param, res, &tv)) <= 0 )
return ret;
n = 0;
if (tv.flags==0) {
/* it is a known header -> use type to find it */
for (hf=msg->headers; hf; hf=hf->next) {
if (tv.ri==hf->type)
++n;
}
} else {
/* it is an un-known header -> use name to find it */
for (hf=msg->headers; hf; hf=hf->next) {
if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
&& strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
++n;
}
}
return pv_get_uintval(msg, param, res, n);
}
static int pv_get_hdr(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
int idx;
int idxf;
pv_value_t tv;
struct hdr_field *hf;
struct hdr_field *hf0;
char *p;
int n;
int ret;
if ( (ret=pv_get_hdr_prolog(msg, param, res, &tv)) <= 0 )
return ret;
if (tv.flags==0) {
/* it is a known header -> use type to find it */
for (hf=msg->headers; hf; hf=hf->next) {
if (tv.ri==hf->type)
break;
}
} else {
/* it is an un-known header -> use name to find it */
for (hf=msg->headers; hf; hf=hf->next) {
if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
&& strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
break;
}
}
if(hf==NULL)
return pv_get_null(msg, param, res);
/* get the index */
if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
{
LM_ERR("invalid index\n");
return -1;
}
/* get the value */
res->flags = PV_VAL_STR;
if(idxf!=PV_IDX_ALL && idx==0)
{
res->rs = hf->body;
return 0;
}
if(idxf==PV_IDX_ALL)
{
p = pv_local_buf;
do {
if(p!=pv_local_buf)
{
if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE)
{
LM_ERR("local buffer length exceeded\n");
return pv_get_null(msg, param, res);
}
memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
p += PV_FIELD_DELIM_LEN;
}
if(p-pv_local_buf+hf->body.len+1>PV_LOCAL_BUF_SIZE)
{
LM_ERR("local buffer length exceeded!\n");
return pv_get_null(msg, param, res);
}
memcpy(p, hf->body.s, hf->body.len);
p += hf->body.len;
/* next hf */
if (tv.flags==0) {
/* it is a known header -> use type to find it */
for (hf=hf->next ; hf; hf=hf->next) {
if (tv.ri==hf->type)
break;
}
} else {
/* it is an un-known header -> use name to find it */
for (hf=hf->next ; hf; hf=hf->next) {
if (hf->type==HDR_OTHER_T && hf->name.len==tv.rs.len
&& strncasecmp(hf->name.s, tv.rs.s, hf->name.len)==0)
break;
}
}
} while (hf);
*p = 0;
res->rs.s = pv_local_buf;
res->rs.len = p - pv_local_buf;
return 0;
}
/* we have a numeric index */
hf0 = 0;
if(idx<0)
{
n = 1;
/* count headers */
if (tv.flags==0 ) {
/* it is a known header -> use type to find it */
for (hf0=hf->next; hf0; hf0=hf0->next) {
if (tv.ri==hf0->type)
n++;
}
} else {
/* it is an un-known header -> use name to find it */
for (hf0=hf->next; hf0; hf0=hf0->next) {
if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
&& strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0)
n++;
}
}
idx = -idx;
if(idx>n)
{
LM_DBG("index out of range\n");
return pv_get_null(msg, param, res);
}
idx = n - idx;
if(idx==0)
{
res->rs = hf->body;
return 0;
}
}
n=0;
while(n<idx)
{
if (tv.flags==0) {
/* it is a known header -> use type to find it */
for (hf0=hf->next; hf0; hf0=hf0->next) {
if (tv.ri==hf0->type) {
n++;
if(n==idx) break;
}
}
} else {
/* it is an un-known header -> use name to find it */
for (hf0=hf->next; hf0; hf0=hf0->next) {
if (hf0->type==HDR_OTHER_T && hf0->name.len==tv.rs.len
&& strncasecmp(hf0->name.s, tv.rs.s, hf0->name.len)==0) {
n++;
if(n==idx) break;
}
}
}
if(hf0==NULL)
break;
}
if(hf0!=0)
{
res->rs = hf0->body;
return 0;
}
LM_DBG("index out of range\n");
return pv_get_null(msg, param, res);
}
static int pv_get_scriptvar(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
int ival = 0;
char *sval = NULL;
script_var_t *sv=NULL;
if(msg==NULL || res==NULL)
return -1;
if(param==NULL || param->pvn.u.dname==0)
return pv_get_null(msg, param, res);
sv= (script_var_t*)param->pvn.u.dname;
if (sv->v.flags&VAR_VAL_NULL)
return pv_get_null(msg, param, res);
if(sv->v.flags&VAR_VAL_STR)
{
res->rs = sv->v.value.s;
res->flags = PV_VAL_STR;
} else {
sval = sint2str(sv->v.value.n, &ival);
res->rs.s = sval;
res->rs.len = ival;
res->ri = sv->v.value.n;
res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
}
return 0;
}
/********* end PV get functions *********/
/********* start PV set functions *********/
int pv_set_avp(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
int avp_name;
int_str avp_val;
int flags;
unsigned short name_type;
int idx, idxf;
if(param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
{
LM_ALERT("BUG in getting dst AVP name\n");
goto error;
}
/* get the index */
if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
{
LM_ERR("invalid index\n");
return -1;
}
if(val == NULL)
{
if(op == COLONEQ_T || idxf == PV_IDX_ALL)
destroy_avps(name_type, avp_name, 1);
else
{
if(idx < 0)
{
LM_ERR("Index with negative value\n");
return -1;
}
destroy_index_avp(name_type, avp_name, idx);
}
return 0;
}
if(op == COLONEQ_T || idxf == PV_IDX_ALL)
destroy_avps(name_type, avp_name, 1);
flags = name_type;
if(val->flags&PV_TYPE_INT)
{
avp_val.n = val->ri;
} else {
avp_val.s = val->rs;
flags |= AVP_VAL_STR;
}
if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) /* if the avp is indexed */
{
if(replace_avp(flags, avp_name, avp_val, idx)< 0)
{
LM_ERR("Failed to replace avp\n");
goto error;
}
}
else {
if (add_avp(flags, avp_name, avp_val)<0)
{
LM_ERR("error - cannot add AVP\n");
goto error;
}
}
return 0;
error:
return -1;
}
int pv_set_scriptvar(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
int_str avp_val;
int flags;
if(param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(param->pvn.u.dname==0)
{
LM_ERR("error - cannot find svar\n");
goto error;
}
if(val == NULL)
{
set_var_value((script_var_t*)param->pvn.u.dname, NULL, VAR_VAL_NULL);
return 0;
}
if(val->flags&PV_TYPE_INT)
{
avp_val.n = val->ri;
flags = 0;
} else {
avp_val.s = val->rs;
flags = VAR_VAL_STR;
}
if(set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, flags)==NULL)
{
LM_ERR("error - cannot set svar [%.*s] \n",
((script_var_t*)param->pvn.u.dname)->name.len,
((script_var_t*)param->pvn.u.dname)->name.s);
goto error;
}
return 0;
error:
return -1;
}
int pv_set_dsturi(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(val == NULL)
{
memset(&act, 0, sizeof(act));
act.type = RESET_DSTURI_T;
if (do_action(&act, msg)<0)
{
LM_ERR("error - do action failed)\n");
goto error;
}
return 1;
}
if(!(val->flags&PV_VAL_STR))
{
LM_ERR("error - str value requred to set dst uri\n");
goto error;
}
if(set_dst_uri(msg, &val->rs)!=0)
goto error;
return 0;
error:
return -1;
}
int pv_set_ruri(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
if(msg==NULL || param==NULL || val==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_STR))
{
LM_ERR("str value required to set R-URI\n");
goto error;
}
if (set_ruri( msg, &val->rs)!=0) {
LM_ERR("failed to set RURI\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_ru_q(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
if(msg==NULL || param==NULL || val==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_INT))
{
LM_ERR("int value required to set r-uri queue value\n");
return -1;
}
if (val->ri > 1000) {
LM_WARN("queue value too big %d - setting queue to "
"maximum value (1000)\n", val->ri);
set_ruri_q(1000);
} else
set_ruri_q(val->ri);
return 0;
}
int pv_set_ruri_user(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(val == NULL)
{
memset(&act, 0, sizeof(act));
act.type = SET_USER_T;
act.elem[0].type = STRING_ST;
act.elem[0].u.string = "";
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed)\n");
goto error;
}
return 0;
}
if(!(val->flags&PV_VAL_STR))
{
LM_ERR("str value required to set R-URI user\n");
goto error;
}
memset(&act, 0, sizeof(act));
act.elem[0].type = STR_ST;
act.elem[0].u.s = val->rs;
act.type = SET_USER_T;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_ruri_host(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL || val==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_STR))
{
LM_ERR("str value required to set R-URI hostname\n");
goto error;
}
memset(&act, 0, sizeof(act));
act.elem[0].type = STR_ST;
act.elem[0].u.s = val->rs;
act.type = SET_HOST_T;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_dsturi_host(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL || val==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(!(val->flags&PV_VAL_STR))
{
LM_ERR("str value required to set DST-URI hostname\n");
goto error;
}
memset(&act, 0, sizeof(act));
act.elem[0].type = STR_ST;
act.elem[0].u.s = val->rs;
act.type = SET_DSTHOST_T;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_dsturi_port(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(val == NULL)
{
memset(&act, 0, sizeof(act));
act.type = SET_DSTPORT_T;
act.elem[0].type = STR_ST;
act.elem[0].u.s.s = "";
act.elem[0].u.s.len = 0;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed)\n");
goto error;
}
return 0;
}
if(!(val->flags&PV_VAL_STR))
{
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags |= PV_VAL_STR;
}
memset(&act, 0, sizeof(act));
act.elem[0].type = STR_ST;
act.elem[0].u.s = val->rs;
act.type = SET_DSTPORT_T;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_ruri_port(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct action act;
if(msg==NULL || param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(val == NULL)
{
memset(&act, 0, sizeof(act));
act.type = SET_PORT_T;
act.elem[0].type = STR_ST;
act.elem[0].u.s.s = "";
act.elem[0].u.s.len = 0;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed)\n");
goto error;
}
return 0;
}
if(!(val->flags&PV_VAL_STR))
{
val->rs.s = int2str(val->ri, &val->rs.len);
val->flags |= PV_VAL_STR;
}
memset(&act, 0, sizeof(act));
act.elem[0].type = STR_ST;
act.elem[0].u.s = val->rs;
act.type = SET_PORT_T;
if (do_action(&act, msg)<0)
{
LM_ERR("do action failed\n");
goto error;
}
return 0;
error:
return -1;
}
int pv_set_branch(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
if (msg==NULL || param==NULL) {
LM_ERR("bad parameters\n");
return -1;
}
if (msg->first_line.type == SIP_REPLY)
return -1;
if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
val->rs.len==0 ) {
LM_ERR("str value required to create a new branch\n");
return -1;
}
if (append_branch( msg, &val->rs, NULL, NULL, Q_UNSPECIFIED, 0, NULL)!=1){
LM_ERR("failed to append new branch\n");
return -1;
}
return 0;
}
int pv_set_branch_fields(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
int idx;
int idxf;
str *s;
qvalue_t q;
unsigned int flags;
struct socket_info *si;
if (msg==NULL || param==NULL) {
LM_ERR("bad parameters\n");
return -1;
}
if (msg->first_line.type == SIP_REPLY)
return -1;
/* get the index */
if (pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
LM_ERR("invalid index\n");
return -1;
}
if(idxf==PV_IDX_ALL) {
LM_ERR("SCRIPT BUG - * not allowed in branch assigment\n");
return -1;
}
if (idx<0) {
idx = nr_branches + idx;
}
if (idx<0 || idx>=nr_branches) {
LM_ERR("SCRIPT BUG - inexisting branch assigment [%d/%d]\n",
nr_branches, idx);
return -1;
}
switch (param->pvn.u.isname.name.n) {
case BR_URI_ID: /* set URI */
if (!val || !(val->flags&PV_VAL_STR) || val->flags&(PV_VAL_NULL) ||
val->rs.len==0 ) {
LM_ERR("str value required to set the branch URI\n");
return -1;
}
s = &val->rs;
return update_branch( idx, &s, NULL,
NULL, NULL, NULL, NULL);
case BR_Q_ID: /* set Q */
if ( val && !(val->flags&PV_VAL_INT) ) {
LM_ERR("INT value required to set the branch Q\n");
return -1;
}
q = (!val||val->flags&PV_VAL_NULL)? Q_UNSPECIFIED : val->ri;
return update_branch( idx, NULL, NULL,
NULL, &q, NULL, NULL);
case BR_DURI_ID: /* set DURI */
if ( val && !(val->flags&PV_VAL_STR) ) {
LM_ERR("STR value required to set the branch DURI\n");
return -1;
}
s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
return update_branch( idx, NULL, &s,
NULL, NULL, NULL, NULL);
case BR_PATH_ID: /* set PATH */
if ( val && !(val->flags&PV_VAL_STR) ) {
LM_ERR("STR value required to set the branch PATH\n");
return -1;
}
s = (!val||val->flags&PV_VAL_NULL)? NULL : &val->rs;
return update_branch( idx, NULL, NULL,
&s, NULL, NULL, NULL);
case BR_FLAGS_ID: /* set FLAGS */
if ( val && !(val->flags&PV_VAL_INT) ) {
LM_ERR("INT value required to set the branch FLAGS\n");
return -1;
}
flags = (!val||val->flags&PV_VAL_NULL)? 0 : val->ri;
return update_branch( idx, NULL, NULL,
NULL, NULL, &flags, NULL);
case BR_SOCKET_ID: /* set SOCKET */
if ( val && !(val->flags&PV_VAL_STR) ) {
LM_ERR("STR value required to set the branch SOCKET\n");
return -1;
}
if (!val || val->flags&PV_VAL_NULL) {
si = NULL;
} else {
str host;
int port, proto;
if (parse_phostport(val->rs.s, val->rs.len, &host.s, &host.len,
&port, &proto) < 0) {
LM_ERR("invalid socket specification\n");
return -1;
}
set_sip_defaults( port, proto);
si = grep_sock_info(&host, (unsigned short)port,
(unsigned short)proto);
if (si==NULL)
return -1;
}
return update_branch( idx, NULL, NULL,
NULL, NULL, NULL, &si);
default:
LM_CRIT("BUG - unsupported ID %d\n",param->pvn.u.isname.type);
return -1;
}
}
int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val)
{
struct socket_info *si;
int port, proto;
str host;
if(msg==NULL || param==NULL)
{
LM_ERR("bad parameters\n");
return -1;
}
if(val==NULL)
{
msg->force_send_socket = NULL;
return 0;
}
if(!(val->flags&PV_VAL_STR) || val->rs.len<=0)
{
LM_ERR("str value required to set the force send sock\n");
goto error;
}
if (parse_phostport(val->rs.s, val->rs.len, &host.s, &host.len, &port, &proto) < 0)
{
LM_ERR("invalid socket specification\n");
goto error;
}
set_sip_defaults( port, proto);
si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto);
if (si!=NULL)
{
msg->force_send_socket = si;
} else {
LM_WARN("no socket found to match [%.*s]\n",
val->rs.len, val->rs.s);
}
return 0;
error:
return -1;
}
/********* end PV set functions *********/
int pv_parse_scriptvar_name(pv_spec_p sp, str *in)
{
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
sp->pvp.pvn.type = PV_NAME_PVAR;
sp->pvp.pvn.u.dname = (void*)add_var(in);
if(sp->pvp.pvn.u.dname==NULL)
{
LM_ERR("cannot register var [%.*s]\n", in->len, in->s);
return -1;
}
return 0;
}
int pv_parse_hdr_name(pv_spec_p sp, str *in)
{
str s;
char *p;
pv_spec_p nsp = 0;
struct hdr_field hdr;
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
p = in->s;
if(*p==PV_MARKER)
{
nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
if(nsp==NULL)
{
LM_ERR("no more memory\n");
return -1;
}
p = pv_parse_spec(in, nsp);
if(p==NULL)
{
LM_ERR("invalid name [%.*s]\n", in->len, in->s);
pv_spec_free(nsp);
return -1;
}
//LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
//pv_print_spec(nsp);
sp->pvp.pvn.type = PV_NAME_PVAR;
sp->pvp.pvn.u.dname = (void*)nsp;
return 0;
}
if(in->len>=PV_LOCAL_BUF_SIZE-1)
{
LM_ERR("name too long\n");
return -1;
}
memcpy(pv_local_buf, in->s, in->len);
pv_local_buf[in->len] = ':';
s.s = pv_local_buf;
s.len = in->len+1;
if (parse_hname2(s.s, s.s + ((s.len<4)?4:s.len), &hdr)==0)
{
LM_ERR("error parsing header name [%.*s]\n", s.len, s.s);
goto error;
}
sp->pvp.pvn.type = PV_NAME_INTSTR;
if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
{
LM_DBG("using hdr type (%d) instead of <%.*s>\n",
hdr.type, in->len, in->s);
sp->pvp.pvn.u.isname.type = 0;
sp->pvp.pvn.u.isname.name.n = hdr.type;
} else {
sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
sp->pvp.pvn.u.isname.name.s = *in;
}
return 0;
error:
return -1;
}
int pv_parse_avp_name(pv_spec_p sp, str *in)
{
char *p;
char *s;
pv_spec_p nsp = 0;
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
p = in->s;
if(*p==PV_MARKER)
{
nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
if(nsp==NULL)
{
LM_ERR("no more memory\n");
return -1;
}
s = pv_parse_spec(in, nsp);
if(s==NULL)
{
LM_ERR("invalid name [%.*s]\n", in->len, in->s);
pv_spec_free(nsp);
return -1;
}
//LM_ERR("dynamic name [%.*s]\n", in->len, in->s);
//pv_print_spec(nsp);
sp->pvp.pvn.type = PV_NAME_PVAR;
sp->pvp.pvn.u.dname = (void*)nsp;
return 0;
}
/*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
/* always an int type from now */
sp->pvp.pvn.u.isname.type = 0;
if(parse_avp_spec(in, &sp->pvp.pvn.u.isname.name.n)!=0)
{
LM_ERR("bad avp name [%.*s]\n", in->len, in->s);
return -1;
}
sp->pvp.pvn.type = PV_NAME_INTSTR;
return 0;
}
int pv_parse_index(pv_spec_p sp, str *in)
{
char *p;
char *s;
int sign;
pv_spec_p nsp = 0;
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
p = in->s;
if(*p==PV_MARKER)
{
nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
if(nsp==NULL)
{
LM_ERR("no more memory\n");
return -1;
}
memset(nsp, 0, sizeof(pv_spec_t));
s = pv_parse_spec(in, nsp);
if(s==NULL)
{
LM_ERR("invalid index [%.*s]\n", in->len, in->s);
pv_spec_free(nsp);
return -1;
}
sp->pvp.pvi.type = PV_IDX_PVAR;
sp->pvp.pvi.u.dval = (void*)nsp;
return 0;
}
if(*p=='*' && in->len==1)
{
sp->pvp.pvi.type = PV_IDX_ALL;
return 0;
}
sign = 1;
if(*p=='-')
{
sign = -1;
p++;
}
sp->pvp.pvi.u.ival = 0;
while(p<in->s+in->len && *p>='0' && *p<='9')
{
sp->pvp.pvi.u.ival = sp->pvp.pvi.u.ival * 10 + *p - '0';
p++;
}
if(p!=in->s+in->len)
{
LM_ERR("invalid index [%.*s]\n", in->len, in->s);
return -1;
}
sp->pvp.pvi.u.ival *= sign;
sp->pvp.pvi.type = PV_IDX_INT;
return 0;
}
int pv_init_iname(pv_spec_p sp, int param)
{
if(sp==NULL)
return -1;
sp->pvp.pvn.type = PV_NAME_INTSTR;
sp->pvp.pvn.u.isname.name.n = param;
return 0;
}
/**
* the table with core pseudo-variables
*/
static pv_export_t _pv_names_table[] = {
{{"avp", (sizeof("avp")-1)}, PVT_AVP, pv_get_avp, pv_set_avp,
pv_parse_avp_name, pv_parse_index, 0, 0},
{{"hdr", (sizeof("hdr")-1)}, PVT_HDR, pv_get_hdr, 0, pv_parse_hdr_name,
pv_parse_index, 0, 0},
{{"hdrcnt", (sizeof("hdrcnt")-1)}, PVT_HDRCNT, pv_get_hdrcnt, 0, pv_parse_hdr_name, 0, 0, 0},
{{"var", (sizeof("var")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
{{"ai", (sizeof("ai")-1)}, /* */
PVT_PAI_URI, pv_get_pai, 0,
0, 0, 0, 0},
{{"au", (sizeof("au")-1)}, /* */
PVT_AUTH_USERNAME, pv_get_authattr, 0,
0, 0, pv_init_iname, 1},
{{"ar", (sizeof("ar")-1)}, /* auth realm */
PVT_AUTH_REALM, pv_get_authattr, 0,
0, 0, pv_init_iname, 2},
{{"adu", (sizeof("adu")-1)}, /* auth digest uri */
PVT_AUTH_DURI, pv_get_authattr, 0,
0, 0, pv_init_iname, 3},
{{"ad", (sizeof("ad")-1)}, /* */
PVT_AUTH_DOMAIN, pv_get_authattr, 0,
0, 0, pv_init_iname, 4},
{{"an", (sizeof("an")-1)}, /* */
PVT_AUTH_NONCE, pv_get_authattr, 0,
0, 0, pv_init_iname, 5},
{{"auth.nonce", (sizeof("auth.nonce")-1)}, /* */
PVT_AUTH_NONCE, pv_get_authattr, 0,
0, 0, pv_init_iname, 5},
{{"auth.resp", (sizeof("auth.resp")-1)}, /* */
PVT_AUTH_RESPONSE, pv_get_authattr, 0,
0, 0, pv_init_iname, 6},
{{"auth.cnonce", (sizeof("auth.cnonce")-1)}, /* */
PVT_AUTH_CNONCE, pv_get_authattr, 0,
0, 0, pv_init_iname, 7},
{{"auth.opaque", (sizeof("auth.opaque")-1)}, /* */
PVT_AUTH_OPAQUE, pv_get_authattr, 0,
0, 0, pv_init_iname, 8},
{{"auth.alg", (sizeof("auth.alg")-1)}, /* */
PVT_AUTH_ALGORITHM, pv_get_authattr, 0,
0, 0, pv_init_iname, 9},
{{"auth.qop", (sizeof("auth.qop")-1)}, /* */
PVT_AUTH_QOP, pv_get_authattr, 0,
0, 0, pv_init_iname, 10},
{{"auth.nc", (sizeof("auth.nc")-1)}, /* */
PVT_AUTH_NONCE_COUNT, pv_get_authattr, 0,
0, 0, pv_init_iname, 11},
{{"aU", (sizeof("aU")-1)}, /* */
PVT_AUTH_USERNAME_WHOLE, pv_get_authattr, 0,
0, 0, pv_init_iname, 99},
{{"Au", (sizeof("Au")-1)}, /* */
PVT_ACC_USERNAME, pv_get_acc_username, 0,
0, 0, pv_init_iname, 1},
{{"bf", (sizeof("bf")-1)}, /* */
PVT_BFLAGS, pv_get_bflags, 0,
0, 0, 0, 0},
{{"branch", (sizeof("branch")-1)}, /* */
PVT_BRANCH, pv_get_branch_fields, pv_set_branch,
0, 0, 0, 0},
{{"branch", (sizeof("branch")-1)}, /* */
PVT_BRANCH, pv_get_branch_fields, pv_set_branch_fields,
pv_parse_branch_name, pv_parse_index, 0, 0},
{{"ci", (sizeof("ci")-1)}, /* */
PVT_CALLID, pv_get_callid, 0,
0, 0, 0, 0},
{{"cl", (sizeof("cl")-1)}, /* */
PVT_CONTENT_LENGTH, pv_get_content_length, 0,
0, 0, 0, 0},
{{"cs", (sizeof("cs")-1)}, /* */
PVT_CSEQ, pv_get_cseq, 0,
0, 0, 0, 0},
{{"ct", (sizeof("ct")-1)}, /* */
PVT_CONTACT, pv_get_contact_body, 0,
0, pv_parse_index, 0, 0},
{{"ct.fields", (sizeof("ct.fields")-1)}, /* */
PVT_CONTACT, pv_get_contact_body, 0,
pv_parse_ct_name, pv_parse_index, 0, 0},
{{"cT", (sizeof("cT")-1)}, /* */
PVT_CONTENT_TYPE, pv_get_content_type, 0,
0, 0, 0, 0},
{{"dd", (sizeof("dd")-1)}, /* */
PVT_DSTURI_DOMAIN, pv_get_dsturi_attr, pv_set_dsturi_host,
0, 0, pv_init_iname, 1},
{{"di", (sizeof("di")-1)}, /* */
PVT_DIVERSION_URI, pv_get_diversion, 0,
0, 0, pv_init_iname, 1},
{{"dir", (sizeof("dir")-1)}, /* */
PVT_DIV_REASON, pv_get_diversion, 0,
0, 0, pv_init_iname, 2},
{{"dip", (sizeof("dis")-1)}, /* */
PVT_DIV_PRIVACY, pv_get_diversion, 0,
0, 0, pv_init_iname, 3},
{{"dp", (sizeof("dp")-1)}, /* */
PVT_DSTURI_PORT, pv_get_dsturi_attr, pv_set_dsturi_port,
0, 0, pv_init_iname, 2},
{{"dP", (sizeof("dP")-1)}, /* */
PVT_DSTURI_PROTOCOL, pv_get_dsturi_attr, 0,
0, 0, pv_init_iname, 3},
{{"ds", (sizeof("ds")-1)}, /* */
PVT_DSET, pv_get_dset, 0,
0, 0, 0, 0},
{{"du", (sizeof("du")-1)}, /* */
PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
0, 0, 0, 0},
{{"duri", (sizeof("duri")-1)}, /* */
PVT_DSTURI, pv_get_dsturi, pv_set_dsturi,
0, 0, 0, 0},
{{"err.class", (sizeof("err.class")-1)}, /* */
PVT_ERR_CLASS, pv_get_errinfo_attr, 0,
0, 0, 0, 0},
{{"err.level", (sizeof("err.level")-1)}, /* */
PVT_ERR_LEVEL, pv_get_errinfo_attr, 0,
0, 0, pv_init_iname, 1},
{{"err.info", (sizeof("err.info")-1)}, /* */
PVT_ERR_INFO, pv_get_errinfo_attr, 0,
0, 0, pv_init_iname, 2},
{{"err.rcode", (sizeof("err.rcode")-1)}, /* */
PVT_ERR_RCODE, pv_get_errinfo_attr, 0,
0, 0, pv_init_iname, 3},
{{"err.rreason", (sizeof("err.rreason")-1)}, /* */
PVT_ERR_RREASON, pv_get_errinfo_attr, 0,
0, 0, pv_init_iname, 4},
{{"fd", (sizeof("fd")-1)}, /* */
PVT_FROM_DOMAIN, pv_get_from_attr, 0,
0, 0, pv_init_iname, 3},
{{"from.domain", (sizeof("from.domain")-1)}, /* */
PVT_FROM_DOMAIN, pv_get_from_attr, 0,
0, 0, pv_init_iname, 3},
{{"fn", (sizeof("fn")-1)}, /* */
PVT_FROM_DISPLAYNAME, pv_get_from_attr, 0,
0, 0, pv_init_iname, 5},
{{"fs", (sizeof("fs")-1)}, /* */
PVT_FORCE_SOCK, pv_get_force_sock, pv_set_force_sock,
0, 0, 0, 0},
{{"ft", (sizeof("ft")-1)}, /* */
PVT_FROM_TAG, pv_get_from_attr, 0,
0, 0, pv_init_iname, 4},
{{"fu", (sizeof("fu")-1)}, /* */
PVT_FROM, pv_get_from_attr, 0,
0, 0, pv_init_iname, 1},
{{"from", (sizeof("from")-1)}, /* */
PVT_FROM, pv_get_from_attr, 0,
0, 0, pv_init_iname, 1},
{{"fU", (sizeof("fU")-1)}, /* */
PVT_FROM_USERNAME, pv_get_from_attr, 0,
0, 0, pv_init_iname, 2},
{{"from.user", (sizeof("from.user")-1)}, /* */
PVT_FROM_USERNAME, pv_get_from_attr, 0,
0, 0, pv_init_iname, 2},
{{"mb", (sizeof("mb")-1)}, /* */
PVT_MSG_BUF, pv_get_msg_buf, 0,
0, 0, 0, 0},
{{"mf", (sizeof("mf")-1)}, /* */
PVT_FLAGS, pv_get_flags, 0,
0, 0, 0, 0},
{{"mi", (sizeof("mi")-1)}, /* */
PVT_MSGID, pv_get_msgid, 0,
0, 0, 0, 0},
{{"ml", (sizeof("ml")-1)}, /* */
PVT_MSG_LEN, pv_get_msg_len, 0,
0, 0, 0, 0},
{{"od", (sizeof("od")-1)}, /* */
PVT_OURI_DOMAIN, pv_get_ouri_attr, 0,
0, 0, pv_init_iname, 2},
{{"op", (sizeof("op")-1)}, /* */
PVT_OURI_PORT, pv_get_ouri_attr, 0,
0, 0, pv_init_iname, 3},
{{"oP", (sizeof("oP")-1)}, /* */
PVT_OURI_PROTOCOL, pv_get_ouri_attr, 0,
0, 0, pv_init_iname, 4},
{{"ou", (sizeof("ou")-1)}, /* */
PVT_OURI, pv_get_ouri, 0,
0, 0, 0, 0},
{{"ouri", (sizeof("ouri")-1)}, /* */
PVT_OURI, pv_get_ouri, 0,
0, 0, 0, 0},
{{"oU", (sizeof("oU")-1)}, /* */
PVT_OURI_USERNAME, pv_get_ouri_attr, 0,
0, 0, pv_init_iname, 1},
{{"path", (sizeof("path")-1)}, /* */
PVT_PATH, pv_get_path, 0,
0, 0, 0, 0},
{{"pd", (sizeof("pd")-1)}, /* */
PVT_PPI_DOMAIN, pv_get_ppi_attr, 0,
0, 0, pv_init_iname, 3},
{{"pn", (sizeof("pn")-1)}, /* */
PVT_PPI_DISPLAYNAME, pv_get_ppi_attr, 0,
0, 0, pv_init_iname, 4},
{{"pp", (sizeof("pp")-1)}, /* */
PVT_PID, pv_get_pid, 0,
0, 0, 0, 0},
{{"pr", (sizeof("pr")-1)}, /* */
PVT_PROTO, pv_get_proto, 0,
0, 0, 0, 0},
{{"proto", (sizeof("proto")-1)}, /* */
PVT_PROTO, pv_get_proto, 0,
0, 0, 0, 0},
{{"pu", (sizeof("pu")-1)}, /* */
PVT_PPI, pv_get_ppi_attr, 0,
0, 0, pv_init_iname, 1},
{{"pU", (sizeof("pU")-1)}, /* */
PVT_PPI_USERNAME, pv_get_ppi_attr, 0,
0, 0, pv_init_iname, 2},
{{"rb", (sizeof("rb")-1)}, /* */
PVT_MSG_BODY, pv_get_msg_body, 0,
0, 0, 0, 0},
{{"rc", (sizeof("rc")-1)}, /* */
PVT_RETURN_CODE, pv_get_return_code, 0,
0, 0, 0, 0},
{{"retcode", (sizeof("retcode")-1)}, /* */
PVT_RETURN_CODE, pv_get_return_code, 0,
0, 0, 0, 0},
{{"rd", (sizeof("rd")-1)}, /* */
PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
0, 0, pv_init_iname, 2},
{{"ruri.domain", (sizeof("ruri.domain")-1)}, /* */
PVT_RURI_DOMAIN, pv_get_ruri_attr, pv_set_ruri_host,
0, 0, pv_init_iname, 2},
{{"re", (sizeof("re")-1)}, /* */
PVT_RPID_URI, pv_get_rpid, 0,
0, 0, 0, 0},
{{"rm", (sizeof("rm")-1)}, /* */
PVT_METHOD, pv_get_method, 0,
0, 0, 0, 0},
{{"rp", (sizeof("rp")-1)}, /* */
PVT_RURI_PORT, pv_get_ruri_attr, pv_set_ruri_port,
0, 0, pv_init_iname, 3},
{{"rP", (sizeof("rP")-1)}, /* */
PVT_RURI_PROTOCOL, pv_get_ruri_attr, 0,
0, 0, pv_init_iname, 4},
{{"rr", (sizeof("rr")-1)}, /* */
PVT_REASON, pv_get_reason, 0,
0, 0, 0, 0},
{{"rs", (sizeof("rs")-1)}, /* */
PVT_STATUS, pv_get_status, 0,
0, 0, 0, 0},
{{"rt", (sizeof("rt")-1)}, /* */
PVT_REFER_TO, pv_get_refer_to, 0,
0, 0, 0, 0},
{{"rT", (sizeof("rt")-1)}, /* */
PVT_ROUTE_TYPE, pv_get_route_type, 0,
0, 0, 0, 0},
{{"ru", (sizeof("ru")-1)}, /* */
PVT_RURI, pv_get_ruri, pv_set_ruri,
0, 0, 0, 0},
{{"ruri", (sizeof("ruri")-1)}, /* */
PVT_RURI, pv_get_ruri, pv_set_ruri,
0, 0, 0, 0},
{{"ru_q", (sizeof("ru_q")-1)}, /* */
PVT_RU_Q, pv_get_ru_q, pv_set_ru_q,
0, 0, 0, 0},
{{"rU", (sizeof("rU")-1)}, /* */
PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
0, 0, pv_init_iname, 1},
{{"ruri.user", (sizeof("ruri.user")-1)}, /* */
PVT_RURI_USERNAME, pv_get_ruri_attr, pv_set_ruri_user,
0, 0, pv_init_iname, 1},
{{"Ri", (sizeof("Ri")-1)}, /* */
PVT_RCVIP, pv_get_rcvip, 0,
0, 0, 0, 0},
{{"Rp", (sizeof("Rp")-1)}, /* */
PVT_RCVPORT, pv_get_rcvport, 0,
0, 0, 0, 0},
{{"sf", (sizeof("sf")-1)}, /* */
PVT_SFLAGS, pv_get_sflags, 0,
0, 0, 0, 0},
{{"src_ip", (sizeof("src_ip")-1)}, /* */
PVT_SRCIP, pv_get_srcip, 0,
0, 0, 0, 0},
{{"si", (sizeof("si")-1)}, /* */
PVT_SRCIP, pv_get_srcip, 0,
0, 0, 0, 0},
{{"sp", (sizeof("sp")-1)}, /* */
PVT_SRCPORT, pv_get_srcport, 0,
0, 0, 0, 0},
{{"td", (sizeof("td")-1)}, /* */
PVT_TO_DOMAIN, pv_get_to_attr, 0,
0, 0, pv_init_iname, 3},
{{"to.domain", (sizeof("to.domain")-1)}, /* */
PVT_TO_DOMAIN, pv_get_to_attr, 0,
0, 0, pv_init_iname, 3},
{{"time", (sizeof("time")-1)}, /* */
PVT_TIME, pv_get_formated_time, 0,
pv_parse_time_name, 0, 0, 0},
{{"tn", (sizeof("tn")-1)}, /* */
PVT_TO_DISPLAYNAME, pv_get_to_attr, 0,
0, 0, pv_init_iname, 5},
{{"tt", (sizeof("tt")-1)}, /* */
PVT_TO_TAG, pv_get_to_attr, 0,
0, 0, pv_init_iname, 4},
{{"tu", (sizeof("tu")-1)}, /* */
PVT_TO, pv_get_to_attr, 0,
0, 0, pv_init_iname, 1},
{{"to", (sizeof("to")-1)}, /* */
PVT_TO, pv_get_to_attr, 0,
0, 0, pv_init_iname, 1},
{{"tU", (sizeof("tU")-1)}, /* */
PVT_TO_USERNAME, pv_get_to_attr, 0,
0, 0, pv_init_iname, 2},
{{"to.user", (sizeof("to.user")-1)}, /* */
PVT_TO_USERNAME, pv_get_to_attr, 0,
0, 0, pv_init_iname, 2},
{{"Tf", (sizeof("Tf")-1)}, /* */
PVT_TIMEF, pv_get_timef, 0,
0, 0, 0, 0},
{{"Ts", (sizeof("Ts")-1)}, /* */
PVT_TIMES, pv_get_times, 0,
0, 0, 0, 0},
{{"Tsm", (sizeof("Tsm")-1)}, /* */
PVT_TIMES, pv_get_timem, 0,
0, 0, 0, 0},
{{"TS", (sizeof("TS")-1)}, /* */
PVT_TIMES, pv_get_start_times, 0,
0, 0, 0, 0},
{{"ua", (sizeof("ua")-1)}, /* */
PVT_USERAGENT, pv_get_useragent, 0,
0, 0, 0, 0},
{{"C", sizeof("C")-1}, PVT_COLOR, pv_get_color, 0,
pv_parse_color_name, 0, 0, 0 },
{{"argv", sizeof("argv")-1}, PVT_ARGV, pv_get_argv, 0,
pv_parse_argv_name, 0, 0, 0 },
{{"param", sizeof("param")-1}, PVT_ROUTE_PARAM, pv_get_param, 0,
pv_parse_param_name, 0, 0, 0 },
{{0,0}, 0, 0, 0, 0, 0, 0, 0}
};
pv_export_t* pv_lookup_spec_name(str *pvname, pv_spec_p e, int has_name)
{
int i;
pv_extra_p pvi;
int found;
if(pvname==0 || e==0)
{
LM_ERR("bad parameters\n");
return NULL;
}
/* search in main table */
for(i=0; _pv_names_table[i].name.s!=0; i++)
{
if(_pv_names_table[i].name.len==pvname->len
&& !((has_name?1:0) ^ (_pv_names_table[i].parse_name?1:0))
&& memcmp(_pv_names_table[i].name.s, pvname->s, pvname->len)==0)
{
/*LM_DBG("found [%.*s] [%d]\n", pvname->len, pvname->s,
_pv_names_table[i].type);*/
/* copy data from table to spec */
e->type = _pv_names_table[i].type;
e->getf = _pv_names_table[i].getf;
e->setf = _pv_names_table[i].setf;
return &_pv_names_table[i];
}
}
/* search in extra list */
if(_pv_extra_list==0)
{
LM_DBG("extra items list is empty\n");
return NULL;
}
pvi = *_pv_extra_list;
while(pvi)
{
if(pvi->pve.name.len>pvname->len)
break;
if(pvi->pve.name.len==pvname->len)
{
found = strncmp(pvi->pve.name.s, pvname->s, pvname->len);
if(found>0)
break;
if(found==0)
{
LM_DBG("found in extra list [%.*s]\n", pvname->len, pvname->s);
/* copy data from export to spec */
e->type = pvi->pve.type;
e->getf = pvi->pve.getf;
e->setf = pvi->pve.setf;
return &(pvi->pve);
}
}
pvi = pvi->next;
}
return NULL;
}
static int is_pv_valid_char(char c)
{
if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
|| (c=='_') || (c=='.'))
return 1;
return 0;
}
char* pv_parse_spec(str *in, pv_spec_p e)
{
char *p;
str s;
str pvname;
str pvcontext;
int pvstate;
int has_inner_name;
trans_t *tr = NULL;
pv_export_t *pte = NULL;
int n=0;
if(in==NULL || in->s==NULL || e==NULL || *in->s!=PV_MARKER)
{
LM_ERR("bad parameters\n");
return NULL;
}
// LM_DBG("***** input [%.*s] (%d)\n", in->len, in->s, in->len);
tr = 0;
pvstate = 0;
memset(e, 0, sizeof(pv_spec_t));
p = in->s;
p++;
if(*p==PV_LNBRACKET)
{
p++;
pvstate = 1;
}
pvname.s = p;
if(*p == PV_MARKER) {
p++;
if(pvstate==1)
{
if(*p!=PV_RNBRACKET)
goto error;
p++;
}
e->getf = pv_get_marker;
e->type = PVT_MARKER;
pvname.len = 1;
goto done_all;
}
if (*p==PV_LCBRACKET)
{ /* context definition*/
p++;
pvcontext.s = p;
while(is_in_str(p,in) && is_pv_valid_char(*p))
p++;
if(*p != PV_RCBRACKET)
{
LM_ERR("Expected to find the end of the context\n");
return 0;
}
pvcontext.len = p - pvcontext.s;
LM_DBG("Context name is %.*s\n", pvcontext.len, pvcontext.s);
p++;
e->pvc = pv_get_context(&pvcontext);
if(e->pvc == NULL)
{
if(!pvc_before_check)
{
LM_ERR("Requested a non existing pv context\n");
return 0;
}
LM_DBG("No context definition found for [%.*s]\n", pvcontext.len, pvcontext.s);
/* create a dummy context strcuture to be filled by the register functions */
e->pvc = add_pv_context(&pvcontext, 0);
if(e->pvc == NULL )
{
LM_ERR("Failed to new context\n");
return 0;
}
}
}
pvname.s = p;
while(is_in_str(p,in) && is_pv_valid_char(*p))
p++;
pvname.len = p - pvname.s;
if(pvstate==1)
{
if(*p==PV_RNBRACKET)
{ /* full pv name ended here*/
goto done_inm;
} else if(*p==PV_LNBRACKET) {
p++;
pvstate = 2;
} else if(*p==PV_LIBRACKET) {
p++;
pvstate = 3;
} else if(*p==TR_LBRACKET) {
p++;
pvstate = 4;
}
else {
LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
pvstate);
goto error;
}
} else {
if(!is_in_str(p, in)) {
p--;
goto done_inm;
} else if(*p==PV_LNBRACKET) {
p++;
pvstate = 5;
} else {
/* still in input str, but end of PV */
/* p is increased at the end, so decrement here */
p--;
goto done_inm;
}
}
done_inm:
has_inner_name = (pvstate==2||pvstate==5)?1:0;
if((pte = pv_lookup_spec_name(&pvname, e, has_inner_name))==NULL)
{
LM_ERR("pvar \"%.*s\"%s not found\n", pvname.len, pvname.s,
has_inner_name?"(inner_name)":"");
goto error;
}
if(pvstate==2 || pvstate==5)
{
s.s = p;
n = 0;
while(is_in_str(p, in))
{
if(*p==PV_RNBRACKET)
{
if(n==0)
break;
n--;
}
if(*p == PV_LNBRACKET)
n++;
p++;
}
if(!is_in_str(p, in))
goto error;
if(p==s.s)
{
LM_ERR("pvar \"%.*s\" does not get empty name param\n",
pvname.len, pvname.s);
goto error;
}
s.len = p - s.s;
if(pte->parse_name(e, &s)!=0)
{
LM_ERR("pvar \"%.*s\" has an invalid name param [%.*s]\n",
pvname.len, pvname.s, s.len, s.s);
goto error;
}
if(pvstate==2)
{
p++;
if(*p==PV_RNBRACKET)
{ /* full pv name ended here*/
goto done_vnm;
} else if(*p==PV_LIBRACKET) {
p++;
pvstate = 3;
} else if(*p==TR_LBRACKET) {
p++;
pvstate = 4;
} else {
LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
pvstate);
goto error;
}
} else {
if(*p==PV_RNBRACKET)
{ /* full pv name ended here*/
p++;
goto done_all;
} else {
LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
pvstate);
goto error;
}
}
}
done_vnm:
if(pvstate==3)
{
if(pte->parse_index==NULL)
{
LM_ERR("pvar \"%.*s\" does not get index param\n",
pvname.len, pvname.s);
goto error;
}
s.s = p;
n = 0;
while(is_in_str(p, in))
{
if(*p==PV_RIBRACKET)
{
if(n==0)
break;
n--;
}
if(*p == PV_LIBRACKET)
n++;
p++;
}
if(!is_in_str(p, in))
goto error;
if(p==s.s)
{
LM_ERR("pvar \"%.*s\" does not get empty index param\n",
pvname.len, pvname.s);
goto error;
}
s.len = p - s.s;
if(pte->parse_index(e, &s)!=0)
{
LM_ERR("pvar \"%.*s\" has an invalid index param [%.*s]\n",
pvname.len, pvname.s, s.len, s.s);
goto error;
}
p++;
if(*p==PV_RNBRACKET)
{ /* full pv name ended here*/
goto done_idx;
} else if(*p==TR_LBRACKET) {
p++;
pvstate = 4;
} else {
LM_ERR("invalid char '%c' in [%.*s] (%d)\n", *p, in->len, in->s,
pvstate);
goto error;
}
}
done_idx:
if(pvstate==4)
{
s.s = p-1;
n = 0;
while(is_in_str(p, in))
{
if(*p==TR_RBRACKET)
{
if(n==0)
{
/* yet another transformation */
p++;
while(is_in_str(p, in) && (*p==' ' || *p=='\t')) p++;
if(!is_in_str(p, in) || *p != TR_LBRACKET)
{
p--;
break;
}
}
n--;
}
if(*p == TR_LBRACKET)
n++;
p++;
}
if(!is_in_str(p, in))
goto error;
if(p==s.s)
{
LM_ERR("pvar \"%.*s\" does not get empty index param\n",
pvname.len, pvname.s);
goto error;
}
s.len = p - s.s + 1;
p = parse_transformation(&s, &tr);
if(p==NULL)
{
LM_ERR("ERROR:bad tr in pvar name \"%.*s\"\n",
pvname.len, pvname.s);
goto error;
}
if(*p!=PV_RNBRACKET)
{
LM_ERR("bad pvar name \"%.*s\" (%c)!\n", in->len, in->s, *p);
goto error;
}
e->trans = (void*)tr;
}
p++;
done_all:
if(pte!=NULL && pte->init_param)
pte->init_param(e, pte->iparam);
return p;
error:
if(p!=NULL)
LM_ERR("wrong char [%c/%d] in [%.*s] at [%d (%d)]\n", *p, (int)*p,
in->len, in->s, (int)(p-in->s), pvstate);
else
LM_ERR("invalid parsing in [%.*s] at (%d)\n", in->len, in->s, pvstate);
return NULL;
} /* end: pv_parse_spec */
/**
*
*/
int pv_parse_format(str *in, pv_elem_p *el)
{
char *p, *p0;
int n = 0;
pv_elem_p e, e0;
str s;
if(in==NULL || in->s==NULL || el==NULL)
return -1;
/*LM_DBG("parsing [%.*s]\n", in->len, in->s);*/
if(in->len == 0)
{
*el = pkg_malloc(sizeof(pv_elem_t));
if(*el == NULL) {
LM_ERR("not enough pkg memory for PV element (1)\n");
goto error;
}
memset(*el, 0, sizeof(pv_elem_t));
(*el)->text = *in;
return 0;
}
p = in->s;
*el = NULL;
e = e0 = NULL;
while(is_in_str(p,in))
{
e0 = e;
e = pkg_malloc(sizeof(pv_elem_t));
if(!e) {
LM_ERR("not enough pkg memory for PV element (2)\n");
goto error;
}
memset(e, 0, sizeof(pv_elem_t));
n++;
if(*el == NULL)
*el = e;
if(e0)
e0->next = e;
e->text.s = p;
while(is_in_str(p,in) && *p!=PV_MARKER)
p++;
e->text.len = p - e->text.s;
if(!is_in_str(p,in))
break;
s.s = p;
s.len = in->s+in->len-p;
p0 = pv_parse_spec(&s, &e->spec);
if(p0==NULL) {
LM_ERR("parsing PV spec failed\n");
goto error;
}
if(!is_in_str(p0,in))
break;
p = p0;
}
/*LM_DBG("format parsed OK: [%d] items\n", n);*/
if(*el == NULL)
return -1;
return 0;
error:
pv_elem_free_all(*el);
*el = NULL;
return -1;
}
int pv_get_spec_name(struct sip_msg* msg, pv_param_p ip, pv_value_t *name)
{
if(msg==NULL || ip==NULL || name==NULL)
return -1;
memset(name, 0, sizeof(pv_value_t));
if(ip->pvn.type==PV_NAME_INTSTR)
{
if(ip->pvn.u.isname.type&AVP_NAME_STR)
{
name->rs = ip->pvn.u.isname.name.s;
name->flags = PV_VAL_STR;
} else {
name->ri = ip->pvn.u.isname.name.n;
name->flags = PV_VAL_INT|PV_TYPE_INT;
}
return 0;
}
/* pvar */
if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), name)!=0)
{
LM_ERR("cannot get name value\n");
return -1;
}
if(name->flags&PV_VAL_NULL || name->flags&PV_VAL_EMPTY)
{
LM_ERR("null or empty name\n");
return -1;
}
return 0;
}
int pv_get_avp_name(struct sip_msg* msg, pv_param_p ip, int *avp_name,
unsigned short *name_type)
{
pv_value_t tv;
if(ip==NULL || avp_name==NULL || name_type==NULL)
return -1;
*avp_name = 0;
*name_type = 0;
if(ip->pvn.type==PV_NAME_INTSTR)
{
*name_type = ip->pvn.u.isname.type;
*avp_name = ip->pvn.u.isname.name.n;
*name_type &= AVP_SCRIPT_MASK;
return 0;
}
/* pvar */
if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
{
LM_ERR("cannot get avp value\n");
return -1;
}
if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
{
LM_ERR("null or empty name\n");
return -1;
}
if(!(tv.flags&PV_VAL_STR))
tv.rs.s = int2str(tv.ri, &tv.rs.len);
/* search the name here */
*avp_name = get_avp_id(&tv.rs);
if (*avp_name == 0) {
LM_ERR("cannot find avp %.*s\n", tv.rs.len, tv.rs.s);
return -1;
}
return 0;
}
int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
{
pv_value_t tv;
if(ip==NULL || idx==NULL || flags==NULL)
return -1;
*idx = 0;
*flags = ip->pvi.type;
if(ip->pvi.type == 0)
return 0;
if(ip->pvi.type == PV_IDX_ALL) {
return 0;
}
if(ip->pvi.type == PV_IDX_INT)
{
*idx = ip->pvi.u.ival;
return 0;
}
/* pvar */
if(pv_get_spec_value(msg, (pv_spec_p)ip->pvi.u.dval, &tv)!=0)
{
LM_ERR("cannot get index value\n");
return -1;
}
if(!(tv.flags & PV_VAL_INT))
{
LM_ERR("invalid index value\n");
return -1;
}
*idx = tv.ri;
return 0;
}
/* function to set pv value */
int pv_set_value(struct sip_msg* msg, pv_spec_p sp,
int op, pv_value_t *value)
{
struct sip_msg* pv_msg;
if(msg==NULL || sp==NULL || sp->setf==NULL || sp->type==PVT_NONE)
{
LM_ERR("bad parameters\n");
return -1;
}
if(sp->pvc && sp->pvc->contextf)
{
pv_msg = sp->pvc->contextf(msg);
if(pv_msg == NULL || pv_msg==FAKED_REPLY)
{
LM_DBG("Invalid %p pv context message\n",pv_msg);
return -1;
}
}
else
pv_msg = msg;
return (*sp->setf)(pv_msg, &(sp->pvp), op, value);
}
int pv_get_spec_value(struct sip_msg* msg, pv_spec_p sp, pv_value_t *value)
{
int ret = 0;
struct sip_msg* pv_msg;
if(msg==NULL || sp==NULL || sp->getf==NULL || value==NULL
|| sp->type==PVT_NONE)
{
LM_ERR("bad parameters\n");
return -1;
}
memset(value, 0, sizeof(pv_value_t));
if(sp->pvc && sp->pvc->contextf)
{
LM_DBG("Found context function %p\n", sp->pvc->contextf);
pv_msg = sp->pvc->contextf(msg);
if(pv_msg == NULL || pv_msg==FAKED_REPLY)
{
LM_DBG("Invalid %p pv context message\n",pv_msg);
return pv_get_null( NULL, NULL, value);
}
} else {
pv_msg = msg;
}
ret = (*sp->getf)(pv_msg, &(sp->pvp), value);
if(ret!=0)
return ret;
if(sp->trans)
return run_transformations(pv_msg, (trans_t*)sp->trans, value);
return ret;
}
int pv_print_spec(struct sip_msg* msg, pv_spec_p sp, char *buf, int *len)
{
pv_value_t tok;
if(msg==NULL || sp==NULL || buf==NULL || len==NULL)
return -1;
if(*len <= 0)
return -1;
memset(&tok, 0, sizeof(pv_value_t));
/* put the value of the specifier */
if(pv_get_spec_value(msg, sp, &tok)==0)
{
if(tok.flags&PV_VAL_NULL)
tok.rs = str_null;
if(tok.rs.len < *len)
memcpy(buf, tok.rs.s, tok.rs.len);
else
goto overflow;
}
*len = tok.rs.len;
buf[tok.rs.len] = '\0';
return 0;
overflow:
LM_ERR("buffer overflow -- increase the buffer size...\n");
return -1;
}
int pv_printf(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
{
int n;
pv_value_t tok;
pv_elem_p it;
char *cur;
char *p;
int l;
if(msg==NULL || list==NULL || buf==NULL || len==NULL)
return -1;
if(*len <= 0)
return -1;
*buf = '\0';
cur = buf;
n = 0;
for (it=list; it; it=it->next)
{
/* put the text */
if(it->text.s && it->text.len>0)
{
if(n+it->text.len < *len)
{
memcpy(cur, it->text.s, it->text.len);
n += it->text.len;
cur += it->text.len;
} else {
LM_ERR("no more space for text [%d][%d]\n", n, it->text.len);
goto overflow;
}
}
/* put the value of the specifier */
if(it->spec.type!=PVT_NONE
&& pv_get_spec_value(msg, &(it->spec), &tok)==0)
{
if(tok.flags&PV_VAL_NULL)
tok.rs = str_null;
if (tok.flags&PV_VAL_STR || tok.flags&PV_VAL_NULL) {
if(n+tok.rs.len < *len)
{
if(tok.rs.len>0)
{
memcpy(cur, tok.rs.s, tok.rs.len);
n += tok.rs.len;
cur += tok.rs.len;
}
} else {
LM_ERR("no more space for spec value [%d][%d]\n",
n, tok.rs.len);
goto overflow;
}
} else if (tok.flags&(PV_VAL_INT|PV_TYPE_INT)){
p = int2str(tok.ri, &l);
if (n+l < *len)
{
memcpy(cur, p, l);
n += l;
cur += l;
} else {
LM_ERR("no more space for spec value [%d][%d]\n",
n, tok.rs.len);
goto overflow;
}
} else {
LM_ERR("unkown type %x\n", tok.flags);
return -1;
}
}
}
goto done;
overflow:
LM_ERR("buffer overflow -- increase the buffer size from [%d]...\n",*len);
return -1;
done:
#ifdef EXTRA_DEBUG
LM_DBG("final buffer length %d\n", n);
#endif
*cur = '\0';
*len = n;
return 0;
}
pvname_list_t* parse_pvname_list(str *in, unsigned int type)
{
pvname_list_t* head = NULL;
pvname_list_t* al = NULL;
pvname_list_t* last = NULL;
char *p;
pv_spec_t spec;
str s;
if(in==NULL || in->s==NULL)
{
LM_ERR("bad parameters\n");
return NULL;
}
p = in->s;
while(is_in_str(p, in))
{
while(is_in_str(p, in) && (*p==' '||*p=='\t'||*p==','||*p==';'))
p++;
if(!is_in_str(p, in))
{
if(head==NULL)
LM_ERR("wrong item name list [%.*s]\n", in->len, in->s);
return head;
}
s.s=p;
s.len = in->s+in->len-p;
p = pv_parse_spec(&s, &spec);
if(p==NULL || (type && spec.type!=type))
{
LM_ERR("wrong item name list [%.*s]!\n", in->len, in->s);
goto error;
}
al = (pvname_list_t*)pkg_malloc(sizeof(pvname_list_t));
if(al==NULL)
{
LM_ERR("no more memory!\n");
goto error;
}
memset(al, 0, sizeof(pvname_list_t));
memcpy(&al->sname, &spec, sizeof(pv_spec_t));
if(last==NULL)
{
head = al;
last = al;
} else {
last->next = al;
last = al;
}
}
return head;
error:
while(head)
{
al = head;
head=head->next;
pkg_free(al);
}
return NULL;
}
int pv_elem_free_all(pv_elem_p log)
{
pv_elem_p t;
while(log)
{
t = log;
log = log->next;
pkg_free(t);
}
return 0;
}
void pv_value_destroy(pv_value_t *val)
{
if(val==0) return;
if(val->flags&PV_VAL_PKG) pkg_free(val->rs.s);
if(val->flags&PV_VAL_SHM) shm_free(val->rs.s);
memset(val, 0, sizeof(pv_value_t));
}
#define PV_PRINT_BUF_SIZE 1024
#define PV_PRINT_BUF_NO 7
/*IMPORTANT NOTE - even if the function prints and returns a static buffer, it
* has built-in support for 3 levels of nesting (or concurrent usage).
* If you think it's not enough for you, either use pv_printf() directly,
* either increase PV_PRINT_BUF_NO --bogdan */
int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
{
static int buf_itr = 0;
static char buf[PV_PRINT_BUF_NO][PV_PRINT_BUF_SIZE];
if (list->next==0 && list->spec.getf==0) {
*s = list->text;
return 0;
} else {
s->s = buf[buf_itr];
s->len = PV_PRINT_BUF_SIZE;
buf_itr = (buf_itr+1)%PV_PRINT_BUF_NO;
return pv_printf( msg, list, s->s, &s->len);
}
}
void pv_spec_free(pv_spec_t *spec)
{
if(spec==0) return;
/* TODO: free name if it is PV */
if(spec->trans)
free_transformation((trans_t*)spec->trans);
pkg_free(spec);
}
int pv_spec_dbg(pv_spec_p sp)
{
if(sp==NULL)
{
LM_DBG("spec: <<NULL>>\n");
return 0;
}
LM_DBG("<spec>\n");
LM_DBG("type: %d\n", sp->type);
LM_DBG("getf: %p\n", sp->getf);
LM_DBG("setf: %p\n", sp->setf);
LM_DBG("tran: %p\n", sp->trans);
LM_DBG("<param>\n");
LM_DBG("<name>\n");
LM_DBG("type: %d\n", sp->pvp.pvn.type);
if(sp->pvp.pvn.type==PV_NAME_INTSTR)
{
LM_DBG("sub-type: %d\n", sp->pvp.pvn.u.isname.type);
if (sp->pvp.pvn.u.isname.type&AVP_NAME_STR)
{
LM_DBG("name str: %.*s\n",
sp->pvp.pvn.u.isname.name.s.len,
sp->pvp.pvn.u.isname.name.s.s);
} else {
LM_DBG("name in: %d\n",
sp->pvp.pvn.u.isname.name.n);
}
} else if(sp->pvp.pvn.type==PV_NAME_PVAR) {
pv_spec_dbg((pv_spec_p)sp->pvp.pvn.u.dname);
} else {
LM_DBG("name: unknown\n");
}
LM_DBG("</name>\n");
LM_DBG("<index>\n");
LM_DBG("type: %d\n", sp->pvp.pvi.type);
if(sp->pvp.pvi.type==PV_IDX_INT)
{
LM_DBG("index: %d\n", sp->pvp.pvi.u.ival);
} else if(sp->pvp.pvi.type==PV_IDX_PVAR) {
pv_spec_dbg((pv_spec_p)sp->pvp.pvi.u.dval);
} else if(sp->pvp.pvi.type==PV_IDX_ALL){
LM_DBG("index: *\n");
} else {
LM_DBG("index: unknown\n");
}
LM_DBG("</index>\n");
LM_DBG("</param>\n");
LM_DBG("</spec\n");
return 0;
}
/**
*
*/
int pv_init_extra_list(void)
{
_pv_extra_list = (pv_extra_p*)pkg_malloc(sizeof(pv_extra_p));
if(_pv_extra_list==0)
{
LM_ERR("cannot alloc extra items list\n");
return -1;
}
*_pv_extra_list=0;
return 0;
}
int pv_add_extra(pv_export_t *e)
{
char *p;
str *in;
pv_extra_t *pvi = NULL;
pv_extra_t *pvj = NULL;
pv_extra_t *pvn = NULL;
int found;
if(e==NULL || e->name.s==NULL || e->getf==NULL || e->type==PVT_NONE)
{
LM_ERR("invalid parameters\n");
return -1;
}
if(_pv_extra_list==0)
{
LM_DBG("extra items list is not initialized\n");
if(pv_init_extra_list()!=0)
{
LM_ERR("cannot intit extra list\n");
return -1;
}
}
in = &(e->name);
p = in->s;
while(is_in_str(p,in) && is_pv_valid_char(*p))
p++;
if(is_in_str(p,in))
{
LM_ERR("invalid char [%c] in [%.*s]\n", *p, in->len, in->s);
return -1;
}
found = 0;
pvi = *_pv_extra_list;
while(pvi)
{
if(pvi->pve.name.len > in->len)
break;
if(pvi->pve.name.len==in->len)
{
found = strncmp(pvi->pve.name.s, in->s, in->len);
if(found>0)
break;
if(found==0)
{
LM_ERR("pvar [%.*s] already exists\n", in->len, in->s);
return -1;
}
}
pvj = pvi;
pvi = pvi->next;
}
pvn = (pv_extra_t*)pkg_malloc(sizeof(pv_extra_t));
if(pvn==0)
{
LM_ERR("no more memory\n");
return -1;
}
memcpy(pvn, e, sizeof(pv_extra_t));
pvn->pve.type += PVT_EXTRA;
if(pvj==0)
{
pvn->next = *_pv_extra_list;
*_pv_extra_list = pvn;
goto done;
}
pvn->next = pvj->next;
pvj->next = pvn;
done:
return 0;
}
int register_pvars_mod(char *mod_name, pv_export_t *items)
{
int ret;
int i;
if (items==0)
return 0;
for ( i=0 ; items[i].name.s ; i++ ) {
ret = pv_add_extra(&items[i]);
if (ret!=0) {
LM_ERR("failed to register pseudo-variable <%.*s> for module %s\n",
items[i].name.len, items[i].name.s, mod_name);
}
}
return 0;
}
/**
*
*/
int pv_free_extra_list(void)
{
pv_extra_p xe;
pv_extra_p xe1;
if(_pv_extra_list!=0)
{
xe = *_pv_extra_list;
while(xe!=0)
{
xe1 = xe;
xe = xe->next;
pkg_free(xe1);
}
pkg_free(_pv_extra_list);
_pv_extra_list = 0;
}
return 0;
}
pv_context_t* new_pv_context(str* name, pv_contextf_t get_context)
{
pv_context_t* pvc_new = NULL;
int size;
/*
if(get_context == NULL)
{
LM_ERR("NULL pointer to function\n");
return 0;
}
*/
size = sizeof(pv_context_t) + name->len;
pvc_new = (pv_context_t*)pkg_malloc(size);
if(pvc_new == NULL)
{
LM_ERR("No more memory\n");
return 0;
}
memset(pvc_new, 0, size);
pvc_new->name.s = (char*)pvc_new + sizeof(pv_context_t);
memcpy(pvc_new->name.s, name->s, name->len);
pvc_new->name.len = name->len;
pvc_new->contextf = get_context;
return pvc_new;
}
int register_pv_context(char* cname, pv_contextf_t get_context)
{
pv_context_t* pvc = pv_context_lst;
str name;
if(cname == NULL)
{
LM_DBG("NULL parameter\n");
return -1;
}
name.s = cname;
name.len = strlen(cname);
LM_DBG("Registered new context: %.*s / %p\n", name.len, name.s, get_context);
pvc = pv_get_context(&name);
if(pvc == NULL)
{
LM_DBG("Context not found\n");
if(add_pv_context(&name, get_context) == NULL)
{
LM_ERR("Failed to add context\n");
return -1;
}
return 1;
}
if(pvc->contextf!=NULL)
{
LM_ERR("Context already registered [%s]\n", cname);
return -1;
}
if(get_context == NULL)
{
LM_ERR("NULL context getter function\n");
return -1;
}
pvc->contextf= get_context;
return 1;
}
/* function to register a pv context getter */
pv_context_t* add_pv_context(str* name, pv_contextf_t get_context)
{
pv_context_t* pvc = pv_context_lst;
pv_context_t* pvc_new, *pvc_prev;
if(pvc == NULL)
{
pvc_new = new_pv_context(name, get_context);
if(pvc_new == NULL)
{
LM_ERR("Failed to allocate context\n");
return 0;
}
pv_context_lst = pvc_new;
return pvc_new;
}
while(pvc)
{
if(pvc->name.len == name->len && strncmp(pvc->name.s, name->s, name->len)==0)
{
LM_ERR("PV Context already registered [%.*s]\n", name->len, name->s);
return 0;
}
pvc_prev = pvc;
pvc = pvc->next;
}
pvc_new = new_pv_context(name, get_context);
if(pvc_new == NULL)
{
LM_ERR("Failed to allocate context\n");
return 0;
}
LM_DBG("Registered new context: %.*s\n", name->len, name->s);
pvc_prev->next = pvc_new;
return pvc_new;
}
pv_context_t* pv_get_context(str* name)
{
pv_context_t* pvc = pv_context_lst;
while(pvc)
{
if(pvc->name.len == name->len &&
strncmp(pvc->name.s, name->s, name->len) == 0)
{
return pvc;
}
pvc = pvc->next;
}
return 0;
}
int pv_contextlist_check(void)
{
pv_context_t* pvc = pv_context_lst;
while(pvc)
{
if(pvc->contextf == NULL)
return -1;
pvc = pvc->next;
}
pvc_before_check = 0;
return 0;
}
/* argument options '-o' */
argv_p argv_vars = NULL;
argv_p search_argv(str *name)
{
argv_p it;
for (it = argv_vars; it; it = it->next) {
if (it->name.len == name->len &&
!strncmp(it->name.s, name->s, name->len))
return it;
}
return 0;
}
int add_arg_var(char *opt)
{
char *eq;
str name;
argv_p new = NULL;
if (!opt) {
LM_ERR("cannot receive null option\n");
return -1;
}
eq = strchr(opt, '=');
if (!eq) {
LM_ERR("invalid option format - '=' char cannot be found\n");
return -1;
}
if (eq <= opt) {
LM_ERR("no option name specified\n");
return -1;
}
name.s = opt;
name.len = eq - name.s;
/* check for duplicate option name */
if (search_argv(&name)) {
LM_ERR("duplicate option name <%.*s>\n", name.len, name.s);
return -1;
}
new = (argv_p)pkg_malloc(sizeof(argv_t));
if (!new) {
LM_ERR("no more pkg memory\n");
return -1;
}
memset(new, 0, sizeof(argv_t));
new->name.s = name.s;
new->name.len = name.len;
new->value.s = eq+1;
new->value.len = strlen(opt) + opt - new->value.s;
if (!new->value.len)
new->value.s = 0;
new->next = argv_vars;
argv_vars = new;
LM_DBG("added argument name <%.*s> = <%.*s>\n",
name.len, name.s, new->value.len, new->value.s);
return 0;
}
int pv_parse_argv_name(pv_spec_p sp, str *in)
{
argv_p v_arg;
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
v_arg = search_argv(in);
if (!v_arg) {
LM_DBG("$argv(%.*s) not found\n", in->len, in->s);
sp->pvp.pvv.len = 0;
sp->pvp.pvv.s = 0;
} else {
sp->pvp.pvv = v_arg->value;
sp->pvp.pvn.u.isname.name.s = v_arg->name;
}
sp->pvp.pvn.type = PV_NAME_PVAR;
return 0;
}
int pv_get_argv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
if (!param) {
LM_ERR("null parameter received\n");
return -1;
}
if (param->pvv.len == 0 || !param->pvv.s)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &param->pvv);
}
static int pv_parse_param_name(pv_spec_p sp, str *in)
{
char *p;
char *s;
pv_spec_p nsp = 0;
if(in==NULL || in->s==NULL || sp==NULL)
return -1;
p = in->s;
if(*p==PV_MARKER)
{
nsp = (pv_spec_p)pkg_malloc(sizeof(pv_spec_t));
if(nsp==NULL)
{
LM_ERR("no more memory\n");
return -1;
}
s = pv_parse_spec(in, nsp);
if(s==NULL)
{
LM_ERR("invalid name [%.*s]\n", in->len, in->s);
pv_spec_free(nsp);
return -1;
}
sp->pvp.pvn.type = PV_NAME_PVAR;
sp->pvp.pvn.u.dname = (void*)nsp;
return 0;
}
/*LM_DBG("static name [%.*s]\n", in->len, in->s);*/
/* always an int type from now */
sp->pvp.pvn.u.isname.type = 0;
sp->pvp.pvn.type = PV_NAME_INTSTR;
if (str2int(in, (unsigned int *)&sp->pvp.pvn.u.isname.name.n) < 0)
{
LM_ERR("bad param index [%.*s]\n", in->len, in->s);
return -1;
}
return 0;
}
static int pv_get_param(struct sip_msg *msg, pv_param_t *ip, pv_value_t *res)
{
int index;
pv_value_t tv;
if (!ip)
{
LM_ERR("null parameter received\n");
return -1;
}
if (!route_params || !route_params_number)
{
LM_DBG("no parameter specified for this route\n");
return pv_get_null(msg, ip, res);
}
if(ip->pvn.type==PV_NAME_INTSTR)
{
index = ip->pvn.u.isname.name.n;
} else
{
/* pvar */
if(pv_get_spec_value(msg, (pv_spec_p)(ip->pvn.u.dname), &tv)!=0)
{
LM_ERR("cannot get spec value\n");
return -1;
}
if(tv.flags&PV_VAL_NULL || tv.flags&PV_VAL_EMPTY)
{
LM_ERR("null or empty name\n");
return -1;
}
if (!(tv.flags&PV_VAL_INT) || str2int(&tv.rs,(unsigned int*)&index) < 0)
{
LM_ERR("invalid index <%.*s>\n", tv.rs.len, tv.rs.s);
return -1;
}
}
if (index < 1 || index > route_params_number)
{
LM_DBG("no such parameter index %d\n", index);
return pv_get_null(msg, ip, res);
}
/* the parameters start at 0, whereas the index starts from 1 */
index--;
switch (route_params[index].type)
{
case STRING_ST:
res->rs.s = route_params[index].u.string;
res->rs.len = strlen(res->rs.s);
res->flags = PV_VAL_STR;
break;
case NUMBER_ST:
res->rs.s = int2str(route_params[index].u.number, &res->rs.len);
res->ri = route_params[index].u.number;
res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
break;
case SCRIPTVAR_ST:
if(pv_get_spec_value(msg, (pv_spec_p)route_params[index].u.data, res)!=0)
{
LM_ERR("cannot get spec value\n");
return -1;
}
break;
default:
LM_ALERT("BUG: invalid parameter type %d\n",
route_params[index].type);
return -1;
}
return 0;
}
void destroy_argv_list(void)
{
argv_p arg;
while (argv_vars) {
arg = argv_vars;
argv_vars = argv_vars->next;
pkg_free(arg);
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化