1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923 |
- /* $Id$
- *
- * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio 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
- *
- * Kamailio 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:
- * ---------
- * 2003-10-09 nat_uac_test introduced (jiri)
- *
- * 2003-11-06 nat_uac_test permitted from onreply_route (jiri)
- *
- * 2003-12-01 unforce_rtp_proxy introduced (sobomax)
- *
- * 2004-01-07 RTP proxy support updated to support new version of the
- * RTP proxy (20040107).
- *
- * force_rtp_proxy() now inserts a special flag
- * into the SDP body to indicate that this session already
- * proxied and ignores sessions with such flag.
- *
- * Added run-time check for version of command protocol
- * supported by the RTP proxy.
- *
- * 2004-01-16 Integrated slightly modified patch from Tristan Colgate,
- * force_rtp_proxy function with IP as a parameter (janakj)
- *
- * 2004-01-28 nat_uac_test extended to allow testing SDP body (sobomax)
- *
- * nat_uac_test extended to allow testing top Via (sobomax)
- *
- * 2004-02-21 force_rtp_proxy now accepts option argument, which
- * consists of string of chars, each of them turns "on"
- * some feature, currently supported ones are:
- *
- * `a' - flags that UA from which message is received
- * doesn't support symmetric RTP;
- * `l' - force "lookup", that is, only rewrite SDP when
- * corresponding session is already exists in the
- * RTP proxy. Only makes sense for SIP requests,
- * replies are always processed in "lookup" mode;
- * `i' - flags that message is received from UA in the
- * LAN. Only makes sense when RTP proxy is running
- * in the bridge mode.
- *
- * force_rtp_proxy can now be invoked without any arguments,
- * as previously, with one argument - in this case argument
- * is treated as option string and with two arguments, in
- * which case 1st argument is option string and the 2nd
- * one is IP address which have to be inserted into
- * SDP (IP address on which RTP proxy listens).
- *
- * 2004-03-12 Added support for IPv6 addresses in SDPs. Particularly,
- * force_rtp_proxy now can work with IPv6-aware RTP proxy,
- * replacing IPv4 address in SDP with IPv6 one and vice versa.
- * This allows creating full-fledged IPv4<->IPv6 gateway.
- * See 4to6.cfg file for example.
- *
- * Two new options added into force_rtp_proxy:
- *
- * `f' - instructs nathelper to ignore marks inserted
- * by another nathelper in transit to indicate
- * that the session is already goes through another
- * proxy. Allows creating chain of proxies.
- * `r' - flags that IP address in SDP should be trusted.
- * Without this flag, nathelper ignores address in the
- * SDP and uses source address of the SIP message
- * as media address which is passed to the RTP proxy.
- *
- * Protocol between nathelper and RTP proxy in bridge
- * mode has been slightly changed. Now RTP proxy expects SER
- * to provide 2 flags when creating or updating session
- * to indicate direction of this session. Each of those
- * flags can be either `e' or `i'. For example `ei' means
- * that we received INVITE from UA on the "external" network
- * network and will send it to the UA on "internal" one.
- * Also possible `ie' (internal->external), `ii'
- * (internal->internal) and `ee' (external->external). See
- * example file alg.cfg for details.
- *
- * 2004-03-15 If the rtp proxy test failed (wrong version or not started)
- * retry test from time to time, when some *rtpproxy* function
- * is invoked. Minimum interval between retries can be
- * configured via rtpproxy_disable_tout module parameter (default
- * is 60 seconds). Setting it to -1 will disable periodic
- * rechecks completely, setting it to 0 will force checks
- * for each *rtpproxy* function call. (andrei)
- *
- * 2004-03-22 Fix assignment of rtpproxy_retr and rtpproxy_tout module
- * parameters.
- *
- * 2004-03-22 Fix get_body position (should be called before get_callid)
- * (andrei)
- *
- * 2004-03-24 Fix newport for null ip address case (e.g onhold re-INVITE)
- * (andrei)
- *
- * 2004-09-30 added received port != via port test (andrei)
- *
- * 2004-10-10 force_socket option introduced (jiri)
- *
- * 2005-02-24 Added support for using more than one rtp proxy, in which
- * case traffic will be distributed evenly among them. In addition,
- * each such proxy can be assigned a weight, which will specify
- * which share of the traffic should be placed to this particular
- * proxy.
- *
- * Introduce failover mechanism, so that if SER detects that one
- * of many proxies is no longer available it temporarily decreases
- * its weight to 0, so that no traffic will be assigned to it.
- * Such "disabled" proxies are periodically checked to see if they
- * are back to normal in which case respective weight is restored
- * resulting in traffic being sent to that proxy again.
- *
- * Those features can be enabled by specifying more than one "URI"
- * in the rtpproxy_sock parameter, optionally followed by the weight,
- * which if absent is assumed to be 1, for example:
- *
- * rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1"
- *
- * 2005-02-25 Force for pinging the socket returned by USRLOC (bogdan)
- *
- * 2005-03-22 support for multiple media streams added (netch)
- *
- * 2005-07-11 SIP ping support added (bogdan)
- *
- * 2005-07-14 SDP origin (o=) IP may be also changed (bogdan)
- *
- * 2006-03-08 fix_nated_sdp() may take one more param to force a specific IP;
- * force_rtp_proxy() accepts a new flag 's' to swap creation/
- * confirmation between requests/replies;
- * add_rcv_param() may take as parameter a flag telling if the
- * parameter should go to the contact URI or contact header;
- * (bogdan)
- * 2006-03-28 Support for changing session-level SDP connection (c=) IP when
- * media-description also includes connection information (bayan)
- * 2007-04-13 Support multiple sets of rtpproxies and set selection added
- * (ancuta)
- * 2007-04-26 Added some MI commands:
- * nh_enable_ping used to enable or disable natping
- * nh_enable_rtpp used to enable or disable a specific rtp proxy
- * nh_show_rtpp used to display information for all rtp proxies
- * (ancuta)
- * 2007-05-09 New function start_recording() allowing to start recording RTP
- * session in the RTP proxy (Carsten Bock - ported from SER)
- * 2007-09-11 Separate timer process and support for multiple timer processes
- * (bogdan)
- * 2008-12-12 Support for RTCP attribute in the SDP
- * (Min Wang/BASIS AudioNet - ported from SER)
- * 2010-08-05 Core SDP parser integrated into nathelper (osas)
- * 2010-10-08 Removal of deprecated force_rtp_proxy and swap flag (osas)
- */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #ifndef __USE_BSD
- #define __USE_BSD
- #endif
- #include <netinet/ip.h>
- #ifndef __FAVOR_BSD
- #define __FAVOR_BSD
- #endif
- #include <netinet/udp.h>
- #include <arpa/inet.h>
- #include <sys/uio.h>
- #include <sys/un.h>
- #include <ctype.h>
- #include <errno.h>
- #include <netdb.h>
- #include <poll.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "../../flags.h"
- #include "../../sr_module.h"
- #include "../../dprint.h"
- #include "../../data_lump.h"
- #include "../../data_lump_rpl.h"
- #include "../../error.h"
- #include "../../forward.h"
- #include "../../mem/mem.h"
- #include "../../parser/parse_from.h"
- #include "../../parser/parse_to.h"
- #include "../../parser/parse_uri.h"
- #include "../../parser/parser_f.h"
- #include "../../parser/sdp/sdp.h"
- #include "../../resolve.h"
- #include "../../timer.h"
- #include "../../trim.h"
- #include "../../ut.h"
- #include "../../pt.h"
- #include "../../timer_proc.h"
- #include "../../lib/kmi/mi.h"
- #include "../../pvar.h"
- #include "../../lvalue.h"
- #include "../../msg_translator.h"
- #include "../../usr_avp.h"
- #include "../../socket_info.h"
- #include "../../mod_fix.h"
- #include "../../dset.h"
- #include "../../route.h"
- #include "../../modules/tm/tm_load.h"
- #include "rtpproxy.h"
- #include "rtpproxy_funcs.h"
- #include "rtpproxy_stream.h"
-
- MODULE_VERSION
- #if !defined(AF_LOCAL)
- #define AF_LOCAL AF_UNIX
- #endif
- #if !defined(PF_LOCAL)
- #define PF_LOCAL PF_UNIX
- #endif
- /* NAT UAC test constants */
- #define NAT_UAC_TEST_C_1918 0x01
- #define NAT_UAC_TEST_RCVD 0x02
- #define NAT_UAC_TEST_V_1918 0x04
- #define NAT_UAC_TEST_S_1918 0x08
- #define NAT_UAC_TEST_RPORT 0x10
- #define DEFAULT_RTPP_SET_ID 0
- #define MI_SET_NATPING_STATE "nh_enable_ping"
- #define MI_DEFAULT_NATPING_STATE 1
- #define MI_ENABLE_RTP_PROXY "nh_enable_rtpp"
- #define MI_MIN_RECHECK_TICKS 0
- #define MI_MAX_RECHECK_TICKS (unsigned int)-1
- #define MI_SHOW_RTP_PROXIES "nh_show_rtpp"
- #define MI_RTP_PROXY_NOT_FOUND "RTP proxy not found"
- #define MI_RTP_PROXY_NOT_FOUND_LEN (sizeof(MI_RTP_PROXY_NOT_FOUND)-1)
- #define MI_PING_DISABLED "NATping disabled from script"
- #define MI_PING_DISABLED_LEN (sizeof(MI_PING_DISABLED)-1)
- #define MI_SET "set"
- #define MI_SET_LEN (sizeof(MI_SET)-1)
- #define MI_INDEX "index"
- #define MI_INDEX_LEN (sizeof(MI_INDEX)-1)
- #define MI_DISABLED "disabled"
- #define MI_DISABLED_LEN (sizeof(MI_DISABLED)-1)
- #define MI_WEIGHT "weight"
- #define MI_WEIGHT_LEN (sizeof(MI_WEIGHT)-1)
- #define MI_RECHECK_TICKS "recheck_ticks"
- #define MI_RECHECK_T_LEN (sizeof(MI_RECHECK_TICKS)-1)
- /* Supported version of the RTP proxy command protocol */
- #define SUP_CPROTOVER 20040107
- /* Required additional version of the RTP proxy command protocol */
- #define REQ_CPROTOVER "20050322"
- /* Additional version necessary for re-packetization support */
- #define REP_CPROTOVER "20071116"
- #define PTL_CPROTOVER "20081102"
- #define CPORT "22222"
- static int extract_mediaip(str *, str *, int *, char *);
- static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
- static int alter_mediaport(struct sip_msg *, str *, str *, str *, int);
- static int alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport);
- static char *gencookie();
- static int rtpp_test(struct rtpp_node*, int, int);
- static int unforce_rtp_proxy_f(struct sip_msg *, char *, char *);
- static int force_rtp_proxy(struct sip_msg *, char *, char *, int, int);
- static int start_recording_f(struct sip_msg *, char *, char *);
- static int rtpproxy_answer1_f(struct sip_msg *, char *, char *);
- static int rtpproxy_answer2_f(struct sip_msg *, char *, char *);
- static int rtpproxy_offer1_f(struct sip_msg *, char *, char *);
- static int rtpproxy_offer2_f(struct sip_msg *, char *, char *);
- static int rtpproxy_manage0(struct sip_msg *msg, char *flags, char *ip);
- static int rtpproxy_manage1(struct sip_msg *msg, char *flags, char *ip);
- static int rtpproxy_manage2(struct sip_msg *msg, char *flags, char *ip);
- static int add_rtpproxy_socks(struct rtpp_set * rtpp_list, char * rtpproxy);
- static int fixup_set_id(void ** param, int param_no);
- static int set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2);
- static struct rtpp_set * select_rtpp_set(int id_set);
- static int rtpproxy_set_store(modparam_t type, void * val);
- static int rtpproxy_add_rtpproxy_set( char * rtp_proxies);
- static int mod_init(void);
- static int child_init(int);
- static void mod_destroy(void);
- /* Pseudo-Variables */
- static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
- /*mi commands*/
- static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
- void* param );
- static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
- void* param);
- static int rtpproxy_disable_tout = 60;
- static int rtpproxy_retr = 5;
- static int rtpproxy_tout = 1;
- static pid_t mypid;
- static unsigned int myseqn = 0;
- static str nortpproxy_str = str_init("a=nortpproxy:yes");
- static str extra_id_pv_param = {NULL, 0};
- static char ** rtpp_strings=0;
- static int rtpp_sets=0; /*used in rtpproxy_set_store()*/
- static int rtpp_set_count = 0;
- static unsigned int current_msg_id = (unsigned int)-1;
- /* RTP proxy balancing list */
- struct rtpp_set_head * rtpp_set_list =0;
- struct rtpp_set * selected_rtpp_set =0;
- struct rtpp_set * default_rtpp_set=0;
- static char *ice_candidate_priority_avp_param = NULL;
- static int ice_candidate_priority_avp_type;
- static int_str ice_candidate_priority_avp;
- /* array with the sockets used by rtpporxy (per process)*/
- static unsigned int rtpp_no = 0;
- static int *rtpp_socks = 0;
- typedef struct rtpp_set_link {
- struct rtpp_set *rset;
- pv_spec_t *rpv;
- } rtpp_set_link_t;
- /* tm */
- static struct tm_binds tmb;
- /*0-> disabled, 1 ->enabled*/
- unsigned int *natping_state=0;
- static str timeout_socket_str = {0, 0};
- static pv_elem_t *extra_id_pv = NULL;
- static cmd_export_t cmds[] = {
- {"set_rtp_proxy_set", (cmd_function)set_rtp_proxy_set_f, 1,
- fixup_set_id, 0,
- ANY_ROUTE},
- {"unforce_rtp_proxy", (cmd_function)unforce_rtp_proxy_f, 0,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_destroy", (cmd_function)unforce_rtp_proxy_f, 0,
- 0, 0,
- ANY_ROUTE},
- {"unforce_rtp_proxy", (cmd_function)unforce_rtp_proxy_f, 1,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_destroy", (cmd_function)unforce_rtp_proxy_f, 1,
- 0, 0,
- ANY_ROUTE},
- {"start_recording", (cmd_function)start_recording_f, 0,
- 0, 0,
- ANY_ROUTE },
- {"rtpproxy_offer", (cmd_function)rtpproxy_offer1_f, 0,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_offer", (cmd_function)rtpproxy_offer1_f, 1,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_offer", (cmd_function)rtpproxy_offer2_f, 2,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_answer", (cmd_function)rtpproxy_answer1_f, 0,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_answer", (cmd_function)rtpproxy_answer1_f, 1,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_answer", (cmd_function)rtpproxy_answer2_f, 2,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_stream2uac",(cmd_function)rtpproxy_stream2uac2_f, 2,
- fixup_var_str_int, 0,
- ANY_ROUTE },
- {"rtpproxy_stream2uas",(cmd_function)rtpproxy_stream2uas2_f, 2,
- fixup_var_str_int, 0,
- ANY_ROUTE },
- {"rtpproxy_stop_stream2uac",(cmd_function)rtpproxy_stop_stream2uac2_f,0,
- NULL, 0,
- ANY_ROUTE },
- {"rtpproxy_stop_stream2uas",(cmd_function)rtpproxy_stop_stream2uas2_f,0,
- NULL, 0,
- ANY_ROUTE },
- {"rtpproxy_manage", (cmd_function)rtpproxy_manage0, 0,
- 0, 0,
- ANY_ROUTE},
- {"rtpproxy_manage", (cmd_function)rtpproxy_manage1, 1,
- fixup_spve_null, fixup_free_spve_null,
- ANY_ROUTE},
- {"rtpproxy_manage", (cmd_function)rtpproxy_manage2, 2,
- fixup_spve_spve, fixup_free_spve_spve,
- ANY_ROUTE},
- {0, 0, 0, 0, 0, 0}
- };
- static pv_export_t mod_pvs[] = {
- {{"rtpstat", (sizeof("rtpstat")-1)}, /* RTP-Statistics */
- PVT_OTHER, pv_get_rtpstat_f, 0, 0, 0, 0, 0},
- {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
- };
- static param_export_t params[] = {
- {"nortpproxy_str", STR_PARAM, &nortpproxy_str.s },
- {"rtpproxy_sock", STR_PARAM|USE_FUNC_PARAM,
- (void*)rtpproxy_set_store },
- {"rtpproxy_disable_tout", INT_PARAM, &rtpproxy_disable_tout },
- {"rtpproxy_retr", INT_PARAM, &rtpproxy_retr },
- {"rtpproxy_tout", INT_PARAM, &rtpproxy_tout },
- {"timeout_socket", STR_PARAM, &timeout_socket_str.s },
- {"ice_candidate_priority_avp", STR_PARAM,
- &ice_candidate_priority_avp_param},
- {"extra_id_pv", STR_PARAM, &extra_id_pv_param.s },
- {0, 0, 0}
- };
- static mi_export_t mi_cmds[] = {
- {MI_ENABLE_RTP_PROXY, mi_enable_rtp_proxy, 0, 0, 0},
- {MI_SHOW_RTP_PROXIES, mi_show_rtpproxies, MI_NO_INPUT_FLAG, 0, 0},
- { 0, 0, 0, 0, 0}
- };
- struct module_exports exports = {
- "rtpproxy",
- DEFAULT_DLFLAGS, /* dlopen flags */
- cmds,
- params,
- 0, /* exported statistics */
- mi_cmds, /* exported MI functions */
- mod_pvs, /* exported pseudo-variables */
- 0, /* extra processes */
- mod_init,
- 0, /* reply processing */
- mod_destroy, /* destroy function */
- child_init
- };
- static int rtpproxy_set_store(modparam_t type, void * val){
- char * p;
- int len;
- p = (char* )val;
- if(p==0 || *p=='\0'){
- return 0;
- }
- if(rtpp_sets==0){
- rtpp_strings = (char**)pkg_malloc(sizeof(char*));
- if(!rtpp_strings){
- LM_ERR("no pkg memory left\n");
- return -1;
- }
- } else {/*realloc to make room for the current set*/
- rtpp_strings = (char**)pkg_realloc(rtpp_strings,
- (rtpp_sets+1)* sizeof(char*));
- if(!rtpp_strings){
- LM_ERR("no pkg memory left\n");
- return -1;
- }
- }
-
- /*allocate for the current set of urls*/
- len = strlen(p);
- rtpp_strings[rtpp_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
- if(!rtpp_strings[rtpp_sets]){
- LM_ERR("no pkg memory left\n");
- return -1;
- }
-
- memcpy(rtpp_strings[rtpp_sets], p, len);
- rtpp_strings[rtpp_sets][len] = '\0';
- rtpp_sets++;
- return 0;
- }
- static int add_rtpproxy_socks(struct rtpp_set * rtpp_list,
- char * rtpproxy){
- /* Make rtp proxies list. */
- char *p, *p1, *p2, *plim;
- struct rtpp_node *pnode;
- int weight;
- p = rtpproxy;
- plim = p + strlen(p);
- for(;;) {
- weight = 1;
- while (*p && isspace((int)*p))
- ++p;
- if (p >= plim)
- break;
- p1 = p;
- while (*p && !isspace((int)*p))
- ++p;
- if (p <= p1)
- break; /* may happen??? */
- /* Have weight specified? If yes, scan it */
- p2 = memchr(p1, '=', p - p1);
- if (p2 != NULL) {
- weight = strtoul(p2 + 1, NULL, 10);
- } else {
- p2 = p;
- }
- pnode = shm_malloc(sizeof(struct rtpp_node));
- if (pnode == NULL) {
- LM_ERR("no shm memory left\n");
- return -1;
- }
- memset(pnode, 0, sizeof(*pnode));
- pnode->idx = rtpp_no++;
- pnode->rn_recheck_ticks = 0;
- pnode->rn_weight = weight;
- pnode->rn_umode = 0;
- pnode->rn_disabled = 0;
- pnode->rn_url.s = shm_malloc(p2 - p1 + 1);
- if (pnode->rn_url.s == NULL) {
- shm_free(pnode);
- LM_ERR("no shm memory left\n");
- return -1;
- }
- memmove(pnode->rn_url.s, p1, p2 - p1);
- pnode->rn_url.s[p2 - p1] = 0;
- pnode->rn_url.len = p2-p1;
- LM_DBG("url is %s, len is %i\n", pnode->rn_url.s, pnode->rn_url.len);
- /* Leave only address in rn_address */
- pnode->rn_address = pnode->rn_url.s;
- if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
- pnode->rn_umode = 1;
- pnode->rn_address += 4;
- } else if (strncasecmp(pnode->rn_address, "udp6:", 5) == 0) {
- pnode->rn_umode = 6;
- pnode->rn_address += 5;
- } else if (strncasecmp(pnode->rn_address, "unix:", 5) == 0) {
- pnode->rn_umode = 0;
- pnode->rn_address += 5;
- }
- if (rtpp_list->rn_first == NULL) {
- rtpp_list->rn_first = pnode;
- } else {
- rtpp_list->rn_last->rn_next = pnode;
- }
- rtpp_list->rn_last = pnode;
- rtpp_list->rtpp_node_count++;
- }
- return 0;
- }
- /* 0-succes
- * -1 - erorr
- * */
- static int rtpproxy_add_rtpproxy_set( char * rtp_proxies)
- {
- char *p,*p2;
- struct rtpp_set * rtpp_list;
- unsigned int my_current_id;
- str id_set;
- int new_list;
- /* empty definition? */
- p= rtp_proxies;
- if(!p || *p=='\0'){
- return 0;
- }
- for(;*p && isspace(*p);p++);
- if(*p=='\0'){
- return 0;
- }
- rtp_proxies = strstr(p, "==");
- if(rtp_proxies){
- if(*(rtp_proxies +2)=='\0'){
- LM_ERR("script error -invalid rtp proxy list!\n");
- return -1;
- }
-
- *rtp_proxies = '\0';
- p2 = rtp_proxies-1;
- for(;isspace(*p2); *p2 = '\0',p2--);
- id_set.s = p; id_set.len = p2 - p+1;
-
- if(id_set.len <= 0 ||str2int(&id_set, &my_current_id)<0 ){
- LM_ERR("script error -invalid set_id value!\n");
- return -1;
- }
-
- rtp_proxies+=2;
- }else{
- rtp_proxies = p;
- my_current_id = DEFAULT_RTPP_SET_ID;
- }
- for(;*rtp_proxies && isspace(*rtp_proxies);rtp_proxies++);
- if(!(*rtp_proxies)){
- LM_ERR("script error -empty rtp_proxy list\n");
- return -1;;
- }
- /*search for the current_id*/
- rtpp_list = rtpp_set_list ? rtpp_set_list->rset_first : 0;
- while( rtpp_list != 0 && rtpp_list->id_set!=my_current_id)
- rtpp_list = rtpp_list->rset_next;
- if(rtpp_list==NULL){ /*if a new id_set : add a new set of rtpp*/
- rtpp_list = shm_malloc(sizeof(struct rtpp_set));
- if(!rtpp_list){
- LM_ERR("no shm memory left\n");
- return -1;
- }
- memset(rtpp_list, 0, sizeof(struct rtpp_set));
- rtpp_list->id_set = my_current_id;
- new_list = 1;
- } else {
- new_list = 0;
- }
- if(add_rtpproxy_socks(rtpp_list, rtp_proxies)!= 0){
- /*if this list will not be inserted, clean it up*/
- goto error;
- }
- if (new_list) {
- if(!rtpp_set_list){/*initialize the list of set*/
- rtpp_set_list = shm_malloc(sizeof(struct rtpp_set_head));
- if(!rtpp_set_list){
- LM_ERR("no shm memory left\n");
- return -1;
- }
- memset(rtpp_set_list, 0, sizeof(struct rtpp_set_head));
- }
- /*update the list of set info*/
- if(!rtpp_set_list->rset_first){
- rtpp_set_list->rset_first = rtpp_list;
- }else{
- rtpp_set_list->rset_last->rset_next = rtpp_list;
- }
- rtpp_set_list->rset_last = rtpp_list;
- rtpp_set_count++;
- if(my_current_id == DEFAULT_RTPP_SET_ID){
- default_rtpp_set = rtpp_list;
- }
- }
- return 0;
- error:
- return -1;
- }
- static int fixup_set_id(void ** param, int param_no)
- {
- int int_val, err;
- struct rtpp_set* rtpp_list;
- rtpp_set_link_t *rtpl = NULL;
- str s;
- rtpl = (rtpp_set_link_t*)pkg_malloc(sizeof(rtpp_set_link_t));
- if(rtpl==NULL) {
- LM_ERR("no more pkg memory\n");
- return -1;
- }
- memset(rtpl, 0, sizeof(rtpp_set_link_t));
- s.s = (char*)*param;
- s.len = strlen(s.s);
- if(s.s[0] == PV_MARKER) {
- int_val = pv_locate_name(&s);
- if(int_val<0 || int_val!=s.len) {
- LM_ERR("invalid parameter %s\n", s.s);
- return -1;
- }
- rtpl->rpv = pv_cache_get(&s);
- if(rtpl->rpv == NULL) {
- LM_ERR("invalid pv parameter %s\n", s.s);
- return -1;
- }
- } else {
- int_val = str2s(*param, strlen(*param), &err);
- if (err == 0) {
- pkg_free(*param);
- if((rtpp_list = select_rtpp_set(int_val)) ==0){
- LM_ERR("rtpp_proxy set %i not configured\n", int_val);
- return E_CFG;
- }
- rtpl->rset = rtpp_list;
- } else {
- LM_ERR("bad number <%s>\n", (char *)(*param));
- return E_CFG;
- }
- }
- *param = (void*)rtpl;
- return 0;
- }
- static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
- void* param )
- { struct mi_node* node;
- str rtpp_url;
- unsigned int enable;
- struct rtpp_set * rtpp_list;
- struct rtpp_node * crt_rtpp;
- int found;
- found = 0;
- if(rtpp_set_list ==NULL)
- goto end;
- node = cmd_tree->node.kids;
- if(node == NULL)
- return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
- if(node->value.s == NULL || node->value.len ==0)
- return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
- rtpp_url = node->value;
- node = node->next;
- if(node == NULL)
- return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
- enable = 0;
- if( strno2int( &node->value, &enable) <0)
- goto error;
- for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
- rtpp_list = rtpp_list->rset_next){
- for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
- crt_rtpp = crt_rtpp->rn_next){
- /*found a matching rtpp*/
-
- if(crt_rtpp->rn_url.len == rtpp_url.len){
-
- if(strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0){
- /*set the enabled/disabled status*/
- found = 1;
- crt_rtpp->rn_recheck_ticks =
- enable? MI_MIN_RECHECK_TICKS : MI_MAX_RECHECK_TICKS;
- crt_rtpp->rn_disabled = enable?0:1;
- }
- }
- }
- }
- end:
- if(found)
- return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
- return init_mi_tree(404,MI_RTP_PROXY_NOT_FOUND,MI_RTP_PROXY_NOT_FOUND_LEN);
- error:
- return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
- }
- #define add_rtpp_node_int_info(_parent, _name, _name_len, _value, _child,\
- _len, _string, _error)\
- do {\
- (_string) = int2str((_value), &(_len));\
- if((_string) == 0){\
- LM_ERR("cannot convert int value\n");\
- goto _error;\
- }\
- if(((_child) = add_mi_node_child((_parent), MI_DUP_VALUE, (_name), \
- (_name_len), (_string), (_len)) ) == 0)\
- goto _error;\
- }while(0);
- static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
- void* param)
- {
- struct mi_node* node, *crt_node, *child;
- struct mi_root* root;
- struct mi_attr * attr;
- struct rtpp_set * rtpp_list;
- struct rtpp_node * crt_rtpp;
- char * string, *id;
- int id_len, len;
- string = id = 0;
- root = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
- if (!root) {
- LM_ERR("the MI tree cannot be initialized!\n");
- return 0;
- }
- if(rtpp_set_list ==NULL)
- return root;
- node = &root->node;
- for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
- rtpp_list = rtpp_list->rset_next){
- for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
- crt_rtpp = crt_rtpp->rn_next){
- id = int2str(rtpp_list->id_set, &id_len);
- if(!id){
- LM_ERR("cannot convert set id\n");
- goto error;
- }
- if(!(crt_node = add_mi_node_child(node, 0, crt_rtpp->rn_url.s,
- crt_rtpp->rn_url.len, 0,0)) ) {
- LM_ERR("cannot add the child node to the tree\n");
- goto error;
- }
- LM_DBG("adding node name %s \n",crt_rtpp->rn_url.s );
- if((attr = add_mi_attr(crt_node, MI_DUP_VALUE, MI_SET, MI_SET_LEN,
- id, id_len))== 0){
- LM_ERR("cannot add attributes to the node\n");
- goto error;
- }
- add_rtpp_node_int_info(crt_node, MI_INDEX, MI_INDEX_LEN,
- crt_rtpp->idx, child, len,string,error);
- add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
- crt_rtpp->rn_disabled, child, len,string,error);
- add_rtpp_node_int_info(crt_node, MI_WEIGHT, MI_WEIGHT_LEN,
- crt_rtpp->rn_weight, child, len, string,error);
- add_rtpp_node_int_info(crt_node, MI_RECHECK_TICKS,MI_RECHECK_T_LEN,
- crt_rtpp->rn_recheck_ticks, child, len, string, error);
- }
- }
- return root;
- error:
- if (root)
- free_mi_tree(root);
- return 0;
- }
- static int
- mod_init(void)
- {
- int i;
- pv_spec_t avp_spec;
- str s;
- unsigned short avp_flags;
- if(register_mi_mod(exports.name, mi_cmds)!=0)
- {
- LM_ERR("failed to register MI commands\n");
- return -1;
- }
- /* any rtpproxy configured? */
- if(rtpp_set_list)
- default_rtpp_set = select_rtpp_set(DEFAULT_RTPP_SET_ID);
- if (nortpproxy_str.s==NULL || nortpproxy_str.s[0]==0) {
- nortpproxy_str.len = 0;
- nortpproxy_str.s = NULL;
- } else {
- nortpproxy_str.len = strlen(nortpproxy_str.s);
- while (nortpproxy_str.len > 0 && (nortpproxy_str.s[nortpproxy_str.len - 1] == '\r' ||
- nortpproxy_str.s[nortpproxy_str.len - 1] == '\n'))
- nortpproxy_str.len--;
- if (nortpproxy_str.len == 0)
- nortpproxy_str.s = NULL;
- }
- /* storing the list of rtp proxy sets in shared memory*/
- for(i=0;i<rtpp_sets;i++){
- if(rtpproxy_add_rtpproxy_set(rtpp_strings[i]) !=0){
- for(;i<rtpp_sets;i++)
- if(rtpp_strings[i])
- pkg_free(rtpp_strings[i]);
- pkg_free(rtpp_strings);
- return -1;
- }
- if(rtpp_strings[i])
- pkg_free(rtpp_strings[i]);
- }
- if (timeout_socket_str.s==NULL || timeout_socket_str.s[0]==0) {
- timeout_socket_str.len = 0;
- timeout_socket_str.s = NULL;
- } else {
- timeout_socket_str.len = strlen(timeout_socket_str.s);
- }
- if (ice_candidate_priority_avp_param) {
- s.s = ice_candidate_priority_avp_param; s.len = strlen(s.s);
- if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) {
- LM_ERR("malformed or non AVP definition <%s>\n", ice_candidate_priority_avp_param);
- return -1;
- }
- if (pv_get_avp_name(0, &(avp_spec.pvp), &ice_candidate_priority_avp, &avp_flags) != 0) {
- LM_ERR("invalid AVP definition <%s>\n", ice_candidate_priority_avp_param);
- return -1;
- }
- ice_candidate_priority_avp_type = avp_flags;
- }
- if (extra_id_pv_param.s && *extra_id_pv_param.s) {
- extra_id_pv_param.len = strlen(extra_id_pv_param.s);
- if(pv_parse_format(&extra_id_pv_param, &extra_id_pv) < 0) {
- LM_ERR("malformed PV string: %s\n", extra_id_pv_param.s);
- return -1;
- }
- } else {
- extra_id_pv = NULL;
- }
- if (rtpp_strings)
- pkg_free(rtpp_strings);
- if (load_tm_api( &tmb ) < 0)
- {
- LM_DBG("could not load the TM-functions - answer-offer model"
- " auto-detection is disabled\n");
- memset(&tmb, 0, sizeof(struct tm_binds));
- }
- return 0;
- }
- static int
- child_init(int rank)
- {
- int n;
- char *cp;
- struct addrinfo hints, *res;
- struct rtpp_set *rtpp_list;
- struct rtpp_node *pnode;
- if(rtpp_set_list==NULL )
- return 0;
- /* Iterate known RTP proxies - create sockets */
- mypid = getpid();
- rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
- if (rtpp_socks==NULL) {
- LM_ERR("no more pkg memory\n");
- return -1;
- }
- for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
- rtpp_list = rtpp_list->rset_next){
- for (pnode=rtpp_list->rn_first; pnode!=0; pnode = pnode->rn_next){
- char *hostname;
- if (pnode->rn_umode == 0) {
- rtpp_socks[pnode->idx] = -1;
- goto rptest;
- }
- /*
- * This is UDP or UDP6. Detect host and port; lookup host;
- * do connect() in order to specify peer address
- */
- hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->rn_address) + 1));
- if (hostname==NULL) {
- LM_ERR("no more pkg memory\n");
- return -1;
- }
- strcpy(hostname, pnode->rn_address);
- cp = strrchr(hostname, ':');
- if (cp != NULL) {
- *cp = '\0';
- cp++;
- }
- if (cp == NULL || *cp == '\0')
- cp = CPORT;
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = 0;
- hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
- LM_ERR("%s\n", gai_strerror(n));
- pkg_free(hostname);
- return -1;
- }
- pkg_free(hostname);
- rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
- ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
- if ( rtpp_socks[pnode->idx] == -1) {
- LM_ERR("can't create socket\n");
- freeaddrinfo(res);
- return -1;
- }
- if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
- LM_ERR("can't connect to a RTP proxy\n");
- close( rtpp_socks[pnode->idx] );
- rtpp_socks[pnode->idx] = -1;
- freeaddrinfo(res);
- return -1;
- }
- freeaddrinfo(res);
- rptest:
- pnode->rn_disabled = rtpp_test(pnode, 0, 1);
- }
- }
- return 0;
- }
- static void mod_destroy(void)
- {
- struct rtpp_set * crt_list, * last_list;
- struct rtpp_node * crt_rtpp, *last_rtpp;
- /*free the shared memory*/
- if (natping_state)
- shm_free(natping_state);
- if(rtpp_set_list == NULL)
- return;
- for(crt_list = rtpp_set_list->rset_first; crt_list != NULL; ){
- for(crt_rtpp = crt_list->rn_first; crt_rtpp != NULL; ){
- if(crt_rtpp->rn_url.s)
- shm_free(crt_rtpp->rn_url.s);
- last_rtpp = crt_rtpp;
- crt_rtpp = last_rtpp->rn_next;
- shm_free(last_rtpp);
- }
- last_list = crt_list;
- crt_list = last_list->rset_next;
- shm_free(last_list);
- }
- shm_free(rtpp_set_list);
- }
- static int
- isnulladdr(str *sx, int pf)
- {
- char *cp;
- if (pf == AF_INET6) {
- for(cp = sx->s; cp < sx->s + sx->len; cp++)
- if (*cp != '0' && *cp != ':')
- return 0;
- return 1;
- }
- return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
- }
- #define ADD_ADIRECTION 0x01
- #define FIX_MEDIP 0x02
- #define ADD_ANORTPPROXY 0x04
- #define FIX_ORGIP 0x08
- #define ADIRECTION "a=direction:active"
- #define ADIRECTION_LEN (sizeof(ADIRECTION) - 1)
- #define AOLDMEDIP "a=oldmediaip:"
- #define AOLDMEDIP_LEN (sizeof(AOLDMEDIP) - 1)
- #define AOLDMEDIP6 "a=oldmediaip6:"
- #define AOLDMEDIP6_LEN (sizeof(AOLDMEDIP6) - 1)
- #define AOLDMEDPRT "a=oldmediaport:"
- #define AOLDMEDPRT_LEN (sizeof(AOLDMEDPRT) - 1)
- static inline int
- replace_sdp_ip(struct sip_msg* msg, str *org_body, char *line, str *ip)
- {
- str body1, oldip, newip;
- str body = *org_body;
- unsigned hasreplaced = 0;
- int pf, pf1 = 0;
- str body2;
- char *bodylimit = body.s + body.len;
- /* Iterate all lines and replace ips in them. */
- if (!ip) {
- newip.s = ip_addr2a(&msg->rcv.src_ip);
- newip.len = strlen(newip.s);
- } else {
- newip = *ip;
- }
- body1 = body;
- for(;;) {
- if (extract_mediaip(&body1, &oldip, &pf,line) == -1)
- break;
- if (pf != AF_INET) {
- LM_ERR("not an IPv4 address in '%s' SDP\n",line);
- return -1;
- }
- if (!pf1)
- pf1 = pf;
- else if (pf != pf1) {
- LM_ERR("mismatching address families in '%s' SDP\n",line);
- return -1;
- }
- body2.s = oldip.s + oldip.len;
- body2.len = bodylimit - body2.s;
- if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf,1) == -1) {
- LM_ERR("can't alter '%s' IP\n",line);
- return -1;
- }
- hasreplaced = 1;
- body1 = body2;
- }
- if (!hasreplaced) {
- LM_ERR("can't extract '%s' IP from the SDP\n",line);
- return -1;
- }
- return 0;
- }
- static int
- extract_mediaip(str *body, str *mediaip, int *pf, char *line)
- {
- char *cp, *cp1;
- int len, nextisip;
- cp1 = NULL;
- for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
- cp1 = ser_memmem(cp, line, len, 2);
- if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
- break;
- cp = cp1 + 2;
- }
- if (cp1 == NULL)
- return -1;
- mediaip->s = cp1 + 2;
- mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
- trim_len(mediaip->len, mediaip->s, *mediaip);
- nextisip = 0;
- for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
- len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
- if (nextisip == 1) {
- mediaip->s = cp;
- mediaip->len = len;
- nextisip++;
- break;
- }
- if (len == 3 && memcmp(cp, "IP", 2) == 0) {
- switch (cp[2]) {
- case '4':
- nextisip = 1;
- *pf = AF_INET;
- break;
- case '6':
- nextisip = 1;
- *pf = AF_INET6;
- break;
- default:
- break;
- }
- }
- cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
- }
- if (nextisip != 2 || mediaip->len == 0) {
- LM_ERR("no `IP[4|6]' in `%s' field\n",line);
- return -1;
- }
- return 1;
- }
- static int
- alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
- str *newip, int newpf, int preserve)
- {
- char *buf;
- int offset;
- struct lump* anchor;
- str omip, nip, oip;
- /* check that updating mediaip is really necessary */
- if (oldpf == newpf && isnulladdr(oldip, oldpf))
- return 0;
- if (newip->len == oldip->len &&
- memcmp(newip->s, oldip->s, newip->len) == 0)
- return 0;
- if (preserve != 0) {
- anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
- if (anchor == NULL) {
- LM_ERR("anchor_lump failed\n");
- return -1;
- }
- if (oldpf == AF_INET6) {
- omip.s = AOLDMEDIP6;
- omip.len = AOLDMEDIP6_LEN;
- } else {
- omip.s = AOLDMEDIP;
- omip.len = AOLDMEDIP_LEN;
- }
- buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
- if (buf == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- memcpy(buf, CRLF, CRLF_LEN);
- memcpy(buf + CRLF_LEN, omip.s, omip.len);
- memcpy(buf + CRLF_LEN + omip.len, oldip->s, oldip->len);
- if (insert_new_lump_after(anchor, buf,
- omip.len + oldip->len + CRLF_LEN, 0) == NULL) {
- LM_ERR("insert_new_lump_after failed\n");
- pkg_free(buf);
- return -1;
- }
- }
- if (oldpf == newpf) {
- nip.len = newip->len;
- nip.s = pkg_malloc(nip.len);
- if (nip.s == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- memcpy(nip.s, newip->s, newip->len);
- } else {
- nip.len = newip->len + 2;
- nip.s = pkg_malloc(nip.len);
- if (nip.s == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- memcpy(nip.s + 2, newip->s, newip->len);
- nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
- nip.s[1] = ' ';
- }
- oip = *oldip;
- if (oldpf != newpf) {
- do {
- oip.s--;
- oip.len++;
- } while (*oip.s != '6' && *oip.s != '4');
- }
- offset = oip.s - msg->buf;
- anchor = del_lump(msg, offset, oip.len, 0);
- if (anchor == NULL) {
- LM_ERR("del_lump failed\n");
- pkg_free(nip.s);
- return -1;
- }
- if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
- LM_ERR("insert_new_lump_after failed\n");
- pkg_free(nip.s);
- return -1;
- }
- return 0;
- }
- static int
- alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
- int preserve)
- {
- char *buf;
- int offset;
- struct lump* anchor;
- /* check that updating mediaport is really necessary */
- if (newport->len == oldport->len &&
- memcmp(newport->s, oldport->s, newport->len) == 0)
- return 0;
- /*
- * Since rewriting the same info twice will mess SDP up,
- * apply simple anti foot shooting measure - put flag on
- * messages that have been altered and check it when
- * another request comes.
- */
- #if 0
- /* disabled: - it propagates to the reply and we don't want this
- * -- andrei */
- if (msg->msg_flags & FL_SDP_PORT_AFS) {
- LM_ERR("you can't rewrite the same SDP twice, check your config!\n");
- return -1;
- }
- #endif
- if (preserve != 0) {
- anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
- if (anchor == NULL) {
- LM_ERR("anchor_lump failed\n");
- return -1;
- }
- buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);
- if (buf == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- memcpy(buf, CRLF, CRLF_LEN);
- memcpy(buf + CRLF_LEN, AOLDMEDPRT, AOLDMEDPRT_LEN);
- memcpy(buf + CRLF_LEN + AOLDMEDPRT_LEN, oldport->s, oldport->len);
- if (insert_new_lump_after(anchor, buf,
- AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {
- LM_ERR("insert_new_lump_after failed\n");
- pkg_free(buf);
- return -1;
- }
- }
- buf = pkg_malloc(newport->len);
- if (buf == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- offset = oldport->s - msg->buf;
- anchor = del_lump(msg, offset, oldport->len, 0);
- if (anchor == NULL) {
- LM_ERR("del_lump failed\n");
- pkg_free(buf);
- return -1;
- }
- memcpy(buf, newport->s, newport->len);
- if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
- LM_ERR("insert_new_lump_after failed\n");
- pkg_free(buf);
- return -1;
- }
- #if 0
- msg->msg_flags |= FL_SDP_PORT_AFS;
- #endif
- return 0;
- }
- /*
- * this function is ported from SER
- */
- static int
- alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport)
- {
- char *buf;
- int offset;
- struct lump* anchor;
- /* check that updating rtcpport is really necessary */
- if (newport->len == oldport->len &&
- memcmp(newport->s, oldport->s, newport->len) == 0)
- return 0;
- buf = pkg_malloc(newport->len);
- if (buf == NULL) {
- LM_ERR("alter_rtcp: out of memory\n");
- return -1;
- }
- offset = oldport->s - msg->buf;
- anchor = del_lump(msg, offset, oldport->len, 0);
- if (anchor == NULL) {
- LM_ERR("alter_rtcp: del_lump failed\n");
- pkg_free(buf);
- return -1;
- }
- memcpy(buf, newport->s, newport->len);
- if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
- LM_ERR("alter_rtcp: insert_new_lump_after failed\n");
- pkg_free(buf);
- return -1;
- }
- return 0;
- }
- static char *
- append_filtered_ip(char *at, str *ip)
- {
- int i;
- for (i = 0; i < ip->len; i++) {
- if (isdigit(ip->s[i])) {
- append_chr(at, ip->s[i]);
- }
- }
- return at;
- }
-
- static int
- insert_candidates(struct sip_msg *msg, char *where, str *ip, unsigned int port,
- int priority)
- {
- char *buf, *at;
- struct lump* anchor;
- str rtp_port;
- str rtcp_port;
- rtcp_port.s = int2str(port+1, &rtcp_port.len); /* beware static buffer */
- buf = pkg_malloc(24 + 78 + 14 + 24 + 2*ip->len + 2 + 2*rtcp_port.len + 24);
- if (buf == NULL) {
- LM_ERR("insert_candidates: out of memory\n");
- return -1;
- }
- at = buf;
- append_str(at, "a=candidate:", 12);
- at = append_filtered_ip(at, ip);
- append_str(at, " 2 UDP ", 7);
- if (priority == 2) {
- append_str(at, "16777214 ", 9);
- } else {
- append_str(at, "2197815294 ", 11);
- }
- append_str(at, ip->s, ip->len);
- append_chr(at, ' ');
- append_str(at, rtcp_port.s, rtcp_port.len);
- append_str(at, " typ relay\r\n", 12);
- rtp_port.s = int2str(port, &rtp_port.len); /* beware static buffer */
- append_str(at, "a=candidate:", 12);
- at = append_filtered_ip(at, ip);
- append_str(at, " 1 UDP ", 7);
- if (priority == 2) {
- append_str(at, "16777215 ", 9);
- } else {
- append_str(at, "2197815295 ", 11);
- }
- append_str(at, ip->s, ip->len);
- append_chr(at, ' ');
- append_str(at, rtp_port.s, rtp_port.len);
- append_str(at, " typ relay\r\n", 12);
- LM_DBG("inserting '%.*s'\n", (int)(at - buf), buf);
- anchor = anchor_lump(msg, where - msg->buf, 0, 0);
- if (anchor == 0) {
- LOG(L_ERR, "insert_candidates: can't get anchor\n");
- pkg_free(buf);
- return -1;
- }
- if (insert_new_lump_before(anchor, buf, at - buf, 0) == 0) {
- LM_ERR("insert_candidates: insert_new_lump_before failed\n");
- pkg_free(buf);
- return -1;
- }
- return 0;
- }
-
- static char * gencookie(void)
- {
- static char cook[34];
- sprintf(cook, "%d_%u ", (int)mypid, myseqn);
- myseqn++;
- return cook;
- }
- static int
- rtpp_checkcap(struct rtpp_node *node, char *cap, int caplen)
- {
- char *cp;
- struct iovec vf[4] = {{NULL, 0}, {"VF", 2}, {" ", 1}, {NULL, 0}};
- vf[3].iov_base = cap;
- vf[3].iov_len = caplen;
- cp = send_rtpp_command(node, vf, 4);
- if (cp == NULL)
- return -1;
- if (cp[0] == 'E' || atoi(cp) != 1)
- return 0;
- return 1;
- }
- static int
- rtpp_test(struct rtpp_node *node, int isdisabled, int force)
- {
- int rtpp_ver, rval;
- char *cp;
- struct iovec v[2] = {{NULL, 0}, {"V", 1}};
- if(node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS){
- LM_DBG("rtpp %s disabled for ever\n", node->rn_url.s);
- return 1;
- }
- if (force == 0) {
- if (isdisabled == 0)
- return 0;
- if (node->rn_recheck_ticks > get_ticks())
- return 1;
- }
- cp = send_rtpp_command(node, v, 2);
- if (cp == NULL) {
- LM_WARN("can't get version of the RTP proxy\n");
- goto error;
- }
- rtpp_ver = atoi(cp);
- if (rtpp_ver != SUP_CPROTOVER) {
- LM_WARN("unsupported version of RTP proxy <%s> found: %d supported,"
- "%d present\n", node->rn_url.s, SUP_CPROTOVER, rtpp_ver);
- goto error;
- }
- rval = rtpp_checkcap(node, REQ_CPROTOVER, sizeof(REQ_CPROTOVER) - 1);
- if (rval == -1) {
- LM_WARN("RTP proxy went down during version query\n");
- goto error;
- }
- if (rval == 0) {
- LM_WARN("of RTP proxy <%s> doesn't support required protocol version"
- "%s\n", node->rn_url.s, REQ_CPROTOVER);
- goto error;
- }
- LM_INFO("rtp proxy <%s> found, support for it %senabled\n",
- node->rn_url.s, force == 0 ? "re-" : "");
- /* Check for optional capabilities */
- rval = rtpp_checkcap(node, REP_CPROTOVER, sizeof(REP_CPROTOVER) - 1);
- if (rval != -1) {
- node->rn_rep_supported = rval;
- } else {
- node->rn_rep_supported = 0;
- }
- rval = rtpp_checkcap(node, PTL_CPROTOVER, sizeof(PTL_CPROTOVER) - 1);
- if (rval != -1) {
- node->rn_ptl_supported = rval;
- } else {
- node->rn_ptl_supported = 0;
- }
- return 0;
- error:
- LM_WARN("support for RTP proxy <%s> has been disabled%s\n", node->rn_url.s,
- rtpproxy_disable_tout < 0 ? "" : " temporarily");
- if (rtpproxy_disable_tout >= 0)
- node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
- return 1;
- }
- char *
- send_rtpp_command(struct rtpp_node *node, struct iovec *v, int vcnt)
- {
- struct sockaddr_un addr;
- int fd, len, i;
- char *cp;
- static char buf[256];
- struct pollfd fds[1];
- len = 0;
- cp = buf;
- if (node->rn_umode == 0) {
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_LOCAL;
- strncpy(addr.sun_path, node->rn_address,
- sizeof(addr.sun_path) - 1);
- #ifdef HAVE_SOCKADDR_SA_LEN
- addr.sun_len = strlen(addr.sun_path);
- #endif
- fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (fd < 0) {
- LM_ERR("can't create socket\n");
- goto badproxy;
- }
- if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(fd);
- LM_ERR("can't connect to RTP proxy\n");
- goto badproxy;
- }
- do {
- len = writev(fd, v + 1, vcnt - 1);
- } while (len == -1 && errno == EINTR);
- if (len <= 0) {
- close(fd);
- LM_ERR("can't send command to a RTP proxy\n");
- goto badproxy;
- }
- do {
- len = read(fd, buf, sizeof(buf) - 1);
- } while (len == -1 && errno == EINTR);
- close(fd);
- if (len <= 0) {
- LM_ERR("can't read reply from a RTP proxy\n");
- goto badproxy;
- }
- } else {
- fds[0].fd = rtpp_socks[node->idx];
- fds[0].events = POLLIN;
- fds[0].revents = 0;
- /* Drain input buffer */
- while ((poll(fds, 1, 0) == 1) &&
- ((fds[0].revents & POLLIN) != 0)) {
- recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
- fds[0].revents = 0;
- }
- v[0].iov_base = gencookie();
- v[0].iov_len = strlen(v[0].iov_base);
- for (i = 0; i < rtpproxy_retr; i++) {
- do {
- len = writev(rtpp_socks[node->idx], v, vcnt);
- } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
- if (len <= 0) {
- LM_ERR("can't send command to a RTP proxy\n");
- goto badproxy;
- }
- while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&
- (fds[0].revents & POLLIN) != 0) {
- do {
- len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
- } while (len == -1 && errno == EINTR);
- if (len <= 0) {
- LM_ERR("can't read reply from a RTP proxy\n");
- goto badproxy;
- }
- if (len >= (v[0].iov_len - 1) &&
- memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
- len -= (v[0].iov_len - 1);
- cp += (v[0].iov_len - 1);
- if (len != 0) {
- len--;
- cp++;
- }
- goto out;
- }
- fds[0].revents = 0;
- }
- }
- if (i == rtpproxy_retr) {
- LM_ERR("timeout waiting reply from a RTP proxy\n");
- goto badproxy;
- }
- }
- out:
- cp[len] = '\0';
- return cp;
- badproxy:
- LM_ERR("proxy <%s> does not respond, disable it\n", node->rn_url.s);
- node->rn_disabled = 1;
- node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
-
- return NULL;
- }
- /*
- * select the set with the id_set id
- */
- static struct rtpp_set * select_rtpp_set(int id_set ){
- struct rtpp_set * rtpp_list;
- /*is it a valid set_id?*/
-
- if(!rtpp_set_list || !rtpp_set_list->rset_first){
- LM_ERR("no rtp_proxy configured\n");
- return 0;
- }
- for(rtpp_list=rtpp_set_list->rset_first; rtpp_list!=0 &&
- rtpp_list->id_set!=id_set; rtpp_list=rtpp_list->rset_next);
- if(!rtpp_list){
- LM_ERR(" script error-invalid id_set to be selected\n");
- }
- return rtpp_list;
- }
- /*
- * Main balancing routine. This does not try to keep the same proxy for
- * the call if some proxies were disabled or enabled; proxy death considered
- * too rare. Otherwise we should implement "mature" HA clustering, which is
- * too expensive here.
- */
- struct rtpp_node *
- select_rtpp_node(str callid, int do_test)
- {
- unsigned sum, sumcut, weight_sum;
- struct rtpp_node* node;
- int was_forced;
- if(!selected_rtpp_set){
- LM_ERR("script error -no valid set selected\n");
- return NULL;
- }
- /* Most popular case: 1 proxy, nothing to calculate */
- if (selected_rtpp_set->rtpp_node_count == 1) {
- node = selected_rtpp_set->rn_first;
- if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks())
- node->rn_disabled = rtpp_test(node, 1, 0);
- return node->rn_disabled ? NULL : node;
- }
- /* XXX Use quick-and-dirty hashing algo */
- for(sum = 0; callid.len > 0; callid.len--)
- sum += callid.s[callid.len - 1];
- sum &= 0xff;
- was_forced = 0;
- retry:
- weight_sum = 0;
- for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
- if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){
- /* Try to enable if it's time to try. */
- node->rn_disabled = rtpp_test(node, 1, 0);
- }
- if (!node->rn_disabled)
- weight_sum += node->rn_weight;
- }
- if (weight_sum == 0) {
- /* No proxies? Force all to be redetected, if not yet */
- if (was_forced)
- return NULL;
- was_forced = 1;
- for(node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
- node->rn_disabled = rtpp_test(node, 1, 1);
- }
- goto retry;
- }
- sumcut = sum % weight_sum;
- /*
- * sumcut here lays from 0 to weight_sum-1.
- * Scan proxy list and decrease until appropriate proxy is found.
- */
- for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
- if (node->rn_disabled)
- continue;
- if (sumcut < node->rn_weight)
- goto found;
- sumcut -= node->rn_weight;
- }
- /* No node list */
- return NULL;
- found:
- if (do_test) {
- node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
- if (node->rn_disabled)
- goto retry;
- }
- return node;
- }
- static int
- get_extra_id(struct sip_msg* msg, str *id_str) {
- if(msg==NULL || extra_id_pv==NULL || id_str==NULL) {
- LM_ERR("bad parameters\n");
- return 0;
- }
- if (pv_printf_s(msg, extra_id_pv, id_str)<0) {
- LM_ERR("cannot print the additional id\n");
- return 0;
- }
- return 1;
- }
- static int
- unforce_rtp_proxy_f(struct sip_msg* msg, char* flags, char* str2)
- {
- str callid, from_tag, to_tag, viabranch;
- char *cp;
- int via = 0;
- int to = 1;
- int extra = 0;
- str extra_id;
- int ret;
- struct rtpp_node *node;
- struct iovec v[1 + 4 + 3 + 2] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
- /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */
- for (cp = flags; cp && *cp; cp++) {
- switch (*cp) {
- case '1':
- via = 1;
- break;
- case '2':
- via = 2;
- break;
- case '3':
- if(msg && msg->first_line.type == SIP_REPLY)
- via = 2;
- else
- via = 1;
- break;
- case 't':
- case 'T':
- to = 0;
- break;
- case 'b':
- extra = 1;
- break;
- case 'a':
- case 'A':
- case 'i':
- case 'I':
- case 'e':
- case 'E':
- case 'l':
- case 'L':
- case 'f':
- case 'F':
- case 'r':
- case 'R':
- case 'c':
- case 'C':
- case 'o':
- case 'O':
- case 'x':
- case 'X':
- case 'w':
- case 'W':
- case 'z':
- case 'Z':
- /* ignore them - they can be sent by rtpproxy_manage() */
- break;
- default:
- LM_ERR("unknown option `%c'\n", *cp);
- return -1;
- }
- }
- if (get_callid(msg, &callid) == -1 || callid.len == 0) {
- LM_ERR("can't get Call-Id field\n");
- return -1;
- }
- to_tag.s = 0;
- to_tag.len = 0;
- if ((to == 1) && get_to_tag(msg, &to_tag) == -1) {
- LM_ERR("can't get To tag\n");
- return -1;
- }
- if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
- LM_ERR("can't get From tag\n");
- return -1;
- }
- if (via) {
- if (via == 1)
- ret = get_via_branch(msg, 1, &viabranch);
- else /* (via == 2) */
- ret = get_via_branch(msg, 2, &viabranch);
- if (ret == -1 || viabranch.len == 0) {
- LM_ERR("can't get Via branch\n");
- return -1;
- }
- v[4].iov_base = ";";
- v[4].iov_len = 1;
- STR2IOVEC(viabranch, v[5]);
- } else
- /* Append extra id to call-id */
- if (extra && extra_id_pv && get_extra_id(msg, &extra_id)) {
- v[4].iov_base = ";";
- v[4].iov_len = 1;
- STR2IOVEC(extra_id, v[5]);
- }
- STR2IOVEC(callid, v[3]);
- STR2IOVEC(from_tag, v[7]);
- STR2IOVEC(to_tag, v[9]);
-
- if(msg->id != current_msg_id){
- selected_rtpp_set = default_rtpp_set;
- }
-
- node = select_rtpp_node(callid, 1);
- if (!node) {
- LM_ERR("no available proxies\n");
- return -1;
- }
- send_rtpp_command(node, v, (to_tag.len > 0) ? 10 : 8);
- return 1;
- }
- /* This function assumes p points to a line of requested type. */
- static int
- set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2)
- {
- rtpp_set_link_t *rtpl;
- pv_value_t val;
- rtpl = (rtpp_set_link_t*)str1;
- current_msg_id = 0;
- selected_rtpp_set = 0;
- if(rtpl->rset != NULL) {
- current_msg_id = msg->id;
- selected_rtpp_set = rtpl->rset;
- } else {
- if(pv_get_spec_value(msg, rtpl->rpv, &val)<0) {
- LM_ERR("cannot evaluate pv param\n");
- return -1;
- }
- if(!(val.flags & PV_VAL_INT)) {
- LM_ERR("pv param must hold an integer value\n");
- return -1;
- }
- selected_rtpp_set = select_rtpp_set(val.ri);
- if(selected_rtpp_set==NULL) {
- LM_ERR("could not locate rtpproxy set %d\n", val.ri);
- return -1;
- }
- current_msg_id = msg->id;
- }
- return 1;
- }
- static int
- rtpproxy_manage(struct sip_msg *msg, char *flags, char *ip)
- {
- char *cp = NULL;
- char newip[IP_ADDR_MAX_STR_SIZE];
- int method;
- int nosdp;
- if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
- || (msg->cseq==NULL)))
- {
- LM_ERR("no CSEQ header\n");
- return -1;
- }
- method = get_cseq(msg)->method_id;
- if(!(method==METHOD_INVITE || method==METHOD_ACK || method==METHOD_CANCEL
- || method==METHOD_BYE || method==METHOD_UPDATE || method==METHOD_PRACK))
- return -1;
- if(method==METHOD_CANCEL || method==METHOD_BYE)
- return unforce_rtp_proxy_f(msg, flags, 0);
- if(ip==NULL)
- {
- cp = ip_addr2a(&msg->rcv.dst_ip);
- strcpy(newip, cp);
- }
- if(msg->msg_flags & FL_SDP_BODY)
- nosdp = 0;
- else
- nosdp = parse_sdp(msg);
- if(msg->first_line.type == SIP_REQUEST) {
- if(method==METHOD_ACK && nosdp==0)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
- (ip!=NULL)?1:0);
- if(method==METHOD_PRACK && nosdp==0)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
- (ip!=NULL)?1:0);
- if(method==METHOD_UPDATE && nosdp==0)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
- (ip!=NULL)?1:0);
- if(method==METHOD_INVITE && nosdp==0) {
- msg->msg_flags |= FL_SDP_BODY;
- if(tmb.t_gett!=NULL && tmb.t_gett()!=NULL
- && tmb.t_gett()!=T_UNDEFINED)
- tmb.t_gett()->uas.request->msg_flags |= FL_SDP_BODY;
- if(route_type==FAILURE_ROUTE)
- return unforce_rtp_proxy_f(msg, flags, 0);
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
- (ip!=NULL)?1:0);
- }
- } else if(msg->first_line.type == SIP_REPLY) {
- if(msg->first_line.u.reply.statuscode>=300)
- return unforce_rtp_proxy_f(msg, flags, 0);
- if(nosdp==0) {
- if(method==METHOD_PRACK)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
- (ip!=NULL)?1:0);
- if(method==METHOD_UPDATE)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
- (ip!=NULL)?1:0);
- if(tmb.t_gett==NULL || tmb.t_gett()==NULL
- || tmb.t_gett()==T_UNDEFINED)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
- (ip!=NULL)?1:0);
- if(tmb.t_gett()->uas.request->msg_flags & FL_SDP_BODY)
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 0,
- (ip!=NULL)?1:0);
- return force_rtp_proxy(msg, flags, (cp!=NULL)?newip:ip, 1,
- (ip!=NULL)?1:0);
- }
- }
- return -1;
- }
- static int
- rtpproxy_manage0(struct sip_msg *msg, char *flags, char *ip)
- {
- return rtpproxy_manage(msg, 0, 0);
- }
- static int
- rtpproxy_manage1(struct sip_msg *msg, char *flags, char *ip)
- {
- str flag_str;
- if(fixup_get_svalue(msg, (gparam_p)flags, &flag_str)<0)
- {
- LM_ERR("invalid flags parameter\n");
- return -1;
- }
- return rtpproxy_manage(msg, flag_str.s, 0);
- }
- static int
- rtpproxy_manage2(struct sip_msg *msg, char *flags, char *ip)
- {
- str flag_str;
- str ip_str;
- if(fixup_get_svalue(msg, (gparam_p)flags, &flag_str)<0)
- {
- LM_ERR("invalid flags parameter\n");
- return -1;
- }
- if(fixup_get_svalue(msg, (gparam_p)ip, &ip_str)<0)
- {
- LM_ERR("invalid IP parameter\n");
- return -1;
- }
- return rtpproxy_manage(msg, flag_str.s, ip_str.s);
- }
- static int
- rtpproxy_offer1_f(struct sip_msg *msg, char *str1, char *str2)
- {
- char *cp;
- char newip[IP_ADDR_MAX_STR_SIZE];
- cp = ip_addr2a(&msg->rcv.dst_ip);
- strcpy(newip, cp);
- return force_rtp_proxy(msg, str1, newip, 1, 0);
- }
- static int
- rtpproxy_offer2_f(struct sip_msg *msg, char *param1, char *param2)
- {
- return force_rtp_proxy(msg, param1, param2, 1, 1);
- }
- static int
- rtpproxy_answer1_f(struct sip_msg *msg, char *str1, char *str2)
- {
- char *cp;
- char newip[IP_ADDR_MAX_STR_SIZE];
- if (msg->first_line.type == SIP_REQUEST)
- if (msg->first_line.u.request.method_value != METHOD_ACK)
- return -1;
- cp = ip_addr2a(&msg->rcv.dst_ip);
- strcpy(newip, cp);
- return force_rtp_proxy(msg, str1, newip, 0, 0);
- }
- static int
- rtpproxy_answer2_f(struct sip_msg *msg, char *param1, char *param2)
- {
- if (msg->first_line.type == SIP_REQUEST)
- if (msg->first_line.u.request.method_value != METHOD_ACK)
- return -1;
- return force_rtp_proxy(msg, param1, param2, 0, 1);
- }
- struct options {
- str s;
- int oidx;
- };
- static int
- append_opts(struct options *op, char ch)
- {
- void *p;
- if (op->s.len <= op->oidx) {
- p = pkg_realloc(op->s.s, op->oidx + 32);
- if (p == NULL) {
- return (-1);
- }
- op->s.s = p;
- op->s.len = op->oidx + 32;
- }
- op->s.s[op->oidx++] = ch;
- return (0);
- }
- static void
- free_opts(struct options *op1, struct options *op2, struct options *op3)
- {
- if (op1->s.len > 0 && op1->s.s != NULL) {
- pkg_free(op1->s.s);
- op1->s.len = 0;
- }
- if (op2->s.len > 0 && op2->s.s != NULL) {
- pkg_free(op2->s.s);
- op2->s.len = 0;
- }
- if (op3->s.len > 0 && op3->s.s != NULL) {
- pkg_free(op3->s.s);
- op3->s.len = 0;
- }
- }
- #define FORCE_RTP_PROXY_RET(e) \
- do { \
- free_opts(&opts, &rep_opts, &pt_opts); \
- return (e); \
- } while (0);
- static int
- force_rtp_proxy(struct sip_msg* msg, char* str1, char* str2, int offer, int forcedIP)
- {
- str body, body1, oldport, oldip, newport, newip;
- str callid, from_tag, to_tag, tmp, payload_types;
- str newrtcp = {0, 0};
- str viabranch;
- int create, port, len, flookup, argc, proxied, real, via, ret;
- int orgip, commip;
- int pf, pf1, force;
- struct options opts, rep_opts, pt_opts;
- char *cp, *cp1;
- char *cpend, *next;
- char **ap, *argv[10];
- struct lump* anchor;
- struct rtpp_node *node;
- struct iovec v[] = {
- {NULL, 0}, /* reserved (cookie) */
- {NULL, 0}, /* command & common options */
- {NULL, 0}, /* per-media/per-node options 1 */
- {NULL, 0}, /* per-media/per-node options 2 */
- {" ", 1}, /* separator */
- {NULL, 0}, /* callid */
- {NULL, 0}, /* via-branch separator ";" */
- {NULL, 0}, /* via-branch */
- {" ", 1}, /* separator */
- {NULL, 7}, /* newip */
- {" ", 1}, /* separator */
- {NULL, 1}, /* oldport */
- {" ", 1}, /* separator */
- {NULL, 0}, /* from_tag */
- {";", 1}, /* separator */
- {NULL, 0}, /* medianum */
- {" ", 1}, /* separator */
- {NULL, 0}, /* to_tag */
- {";", 1}, /* separator */
- {NULL, 0}, /* medianum */
- {" ", 1}, /* separator */
- {NULL, 0}, /* Timeout-Socket */
- };
- int iovec_param_count;
- int autobridge_ipv4v6;
- int extra;
- str extra_id;
- char *c1p, *c2p, *bodylimit, *o1p;
- char itoabuf_buf[20];
- int medianum, media_multi;
- str itoabuf_str;
- int c1p_altered;
- int sdp_session_num, sdp_stream_num;
- sdp_session_cell_t* sdp_session;
- sdp_stream_cell_t* sdp_stream;
- int_str ice_candidate_priority_val;
- memset(&opts, '\0', sizeof(opts));
- memset(&rep_opts, '\0', sizeof(rep_opts));
- memset(&pt_opts, '\0', sizeof(pt_opts));
- /* Leave space for U/L prefix TBD later */
- if (append_opts(&opts, '?') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- flookup = force = real = orgip = commip = via = autobridge_ipv4v6 = extra = 0;
- for (cp = str1; cp != NULL && *cp != '\0'; cp++) {
- switch (*cp) {
- case '1':
- via = 1;
- break;
- case '2':
- via = 2;
- break;
- case '3':
- if(msg && msg->first_line.type == SIP_REPLY)
- via = 2;
- else
- via = 1;
- break;
- case 'a':
- case 'A':
- if (append_opts(&opts, 'A') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- real = 1;
- break;
- case 'b':
- extra = 1;
- break;
- case 'i':
- case 'I':
- if (append_opts(&opts, 'I') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- break;
- case 'e':
- case 'E':
- if (append_opts(&opts, 'E') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- break;
- case 'l':
- case 'L':
- if (offer == 0) {
- FORCE_RTP_PROXY_RET (-1);
- }
- flookup = 1;
- break;
- case 'f':
- case 'F':
- force = 1;
- break;
- case 'r':
- case 'R':
- real = 1;
- break;
- case 'c':
- case 'C':
- commip = 1;
- break;
- case 'o':
- case 'O':
- orgip = 1;
- break;
- case 'x':
- case 'X':
- autobridge_ipv4v6 = 1;
- break;
- case 'w':
- case 'W':
- if (append_opts(&opts, 'S') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- break;
- case 'z':
- case 'Z':
- if (append_opts(&rep_opts, 'Z') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- /* If there are any digits following Z copy them into the command */
- for (; cp[1] != '\0' && isdigit(cp[1]); cp++) {
- if (append_opts(&rep_opts, cp[1]) == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- }
- break;
- case 't':
- case 'T':
- /* Only used in rtpproxy_destroy */
- break;
- default:
- LM_ERR("unknown option `%c'\n", *cp);
- FORCE_RTP_PROXY_RET (-1);
- }
- }
- if (offer != 0) {
- create = 1;
- } else {
- create = 0;
- }
- /* extract_body will also parse all the headers in the message as
- * a side effect => don't move get_callid/get_to_tag in front of it
- * -- andrei */
- if (extract_body(msg, &body) == -1) {
- LM_ERR("can't extract body from the message\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- if (get_callid(msg, &callid) == -1 || callid.len == 0) {
- LM_ERR("can't get Call-Id field\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- to_tag.s = 0;
- if (get_to_tag(msg, &to_tag) == -1) {
- LM_ERR("can't get To tag\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
- LM_ERR("can't get From tag\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- if (via) {
- if (via == 1)
- ret = get_via_branch(msg, 1, &viabranch);
- else /* (via == 2) */
- ret = get_via_branch(msg, 2, &viabranch);
- if (ret == -1 || viabranch.len == 0) {
- LM_ERR("can't get Via branch\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- v[6].iov_base = ";";
- v[6].iov_len = 1;
- STR2IOVEC(viabranch, v[7]);
- } else
- /* Append extra id to call-id */
- if (extra && extra_id_pv && get_extra_id(msg, &extra_id)) {
- v[6].iov_base = ";";
- v[6].iov_len = 1;
- STR2IOVEC(extra_id, v[7]);
- }
- if (flookup != 0) {
- if (to_tag.len == 0) {
- FORCE_RTP_PROXY_RET (-1);
- }
- create = 0;
- } else if ((msg->first_line.type == SIP_REPLY && offer != 0)
- || (msg->first_line.type == SIP_REQUEST && offer == 0)) {
- if (to_tag.len == 0) {
- FORCE_RTP_PROXY_RET (-1);
- }
- tmp = from_tag;
- from_tag = to_tag;
- to_tag = tmp;
- }
- proxied = 0;
- if (nortpproxy_str.len) {
- for ( cp=body.s ; (len=body.s+body.len-cp) >= nortpproxy_str.len ; ) {
- cp1 = ser_memmem(cp, nortpproxy_str.s, len, nortpproxy_str.len);
- if (cp1 == NULL)
- break;
- if (cp1[-1] == '\n' || cp1[-1] == '\r') {
- proxied = 1;
- break;
- }
- cp = cp1 + nortpproxy_str.len;
- }
- }
- if (proxied != 0 && force == 0) {
- FORCE_RTP_PROXY_RET (-2);
- }
- /*
- * Parsing of SDP body.
- * It can contain a few session descriptions (each starts with
- * v-line), and each session may contain a few media descriptions
- * (each starts with m-line).
- * We have to change ports in m-lines, and also change IP addresses in
- * c-lines which can be placed either in session header (fallback for
- * all medias) or media description.
- * Ports should be allocated for any media. IPs all should be changed
- * to the same value (RTP proxy IP), so we can change all c-lines
- * unconditionally.
- */
- if(0 != parse_sdp(msg)) {
- LM_ERR("Unable to parse sdp\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- #ifdef EXTRA_DEBUG
- print_sdp((sdp_info_t*)msg->body, L_DBG);
- #endif
- bodylimit = body.s + body.len;
- if(msg->id != current_msg_id){
- selected_rtpp_set = default_rtpp_set;
- }
- opts.s.s[0] = (create == 0) ? 'L' : 'U';
- v[1].iov_base = opts.s.s;
- v[1].iov_len = opts.oidx;
- STR2IOVEC(callid, v[5]);
- STR2IOVEC(from_tag, v[13]);
- STR2IOVEC(to_tag, v[17]);
- if (ice_candidate_priority_avp_param) {
- if (search_first_avp(ice_candidate_priority_avp_type,
- ice_candidate_priority_avp,
- &ice_candidate_priority_val, 0)
- == NULL) {
- ice_candidate_priority_val.n = 2;
- } else if ((ice_candidate_priority_val.n < 1) ||
- (ice_candidate_priority_val.n > 2)) {
- LM_ERR("invalid ice candidate priority value %d\n",
- ice_candidate_priority_val.n);
- FORCE_RTP_PROXY_RET (-1);
- }
- } else {
- ice_candidate_priority_val.n = 0;
- }
- /* check if this is a single or a multi stream SDP offer/answer */
- sdp_stream_num = get_sdp_stream_num(msg);
- switch (sdp_stream_num) {
- case 0:
- LM_ERR("sdp w/o streams\n");
- FORCE_RTP_PROXY_RET (-1);
- break;
- case 1:
- media_multi = 0;
- break;
- default:
- media_multi = 1;
- }
- #ifdef EXTRA_DEBUG
- LM_DBG("my new media_multi=%d\n", media_multi);
- #endif
- medianum = 0;
- sdp_session_num = 0;
- for(;;) {
- sdp_session = get_sdp_session(msg, sdp_session_num);
- if(!sdp_session) break;
- sdp_stream_num = 0;
- c1p_altered = 0;
- o1p = sdp_session->o_ip_addr.s;
- for(;;) {
- sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
- if (!sdp_stream ||
- (ice_candidate_priority_val.n && sdp_stream->remote_candidates.len)) break;
- if (sdp_stream->ip_addr.s && sdp_stream->ip_addr.len>0) {
- oldip = sdp_stream->ip_addr;
- pf = sdp_stream->pf;
- } else {
- oldip = sdp_session->ip_addr;
- pf = sdp_session->pf;
- }
- oldport = sdp_stream->port;
- payload_types = sdp_stream->payloads;
- medianum++;
- if (real != 0) {
- newip = oldip;
- } else {
- newip.s = ip_addr2a(&msg->rcv.src_ip);
- newip.len = strlen(newip.s);
- }
- /* XXX must compare address families in all addresses */
- if (pf == AF_INET6) {
- if (autobridge_ipv4v6 != 0) {
- if ((append_opts(&opts, 'E') == -1) || (append_opts(&opts, 'I') == -1)) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- /* Only execute once */
- autobridge_ipv4v6 = 0;
- }
- if (append_opts(&opts, '6') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- /* We need to update the pointers and the length here, it has changed. */
- v[1].iov_base = opts.s.s;
- v[1].iov_len = opts.oidx;
- } else {
- if (autobridge_ipv4v6 != 0) {
- if ((append_opts(&opts, 'I') == -1) || (append_opts(&opts, 'E') == -1)) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- /* We need to update the pointers and the length here, it has changed. */
- v[1].iov_base = opts.s.s;
- v[1].iov_len = opts.oidx;
- /* Only execute once */
- autobridge_ipv4v6 = 0;
- }
- }
- STR2IOVEC(newip, v[9]);
- STR2IOVEC(oldport, v[11]);
- #ifdef EXTRA_DEBUG
- LM_DBG("STR2IOVEC(newip[%.*s], v[9])", newip.len, newip.s);
- LM_DBG("STR2IOVEC(oldport[%.*s], v[11])", oldport.len, oldport.s);
- #endif
- if (1 || media_multi) /* XXX netch: can't choose now*/
- {
- snprintf(itoabuf_buf, sizeof itoabuf_buf, "%d", medianum);
- itoabuf_str.s = itoabuf_buf;
- itoabuf_str.len = strlen(itoabuf_buf);
- STR2IOVEC(itoabuf_str, v[15]);
- STR2IOVEC(itoabuf_str, v[19]);
- #ifdef EXTRA_DEBUG
- LM_DBG("STR2IOVEC(itoabuf_str, v[15])\n");
- LM_DBG("STR2IOVEC(itoabuf_str, v[19])\n");
- #endif
- } else {
- v[14].iov_len = v[15].iov_len = 0;
- v[18].iov_len = v[19].iov_len = 0;
- }
- do {
- node = select_rtpp_node(callid, 1);
- if (!node) {
- LM_ERR("no available proxies\n");
- FORCE_RTP_PROXY_RET (-3);
- }
- if (rep_opts.oidx > 0) {
- if (node->rn_rep_supported == 0) {
- LM_WARN("re-packetization is requested but is not "
- "supported by the selected RTP proxy node\n");
- v[2].iov_len = 0;
- } else {
- v[2].iov_base = rep_opts.s.s;
- v[2].iov_len += rep_opts.oidx;
- }
- }
- #ifdef EXTRA_DEBUG
- LM_DBG("payload_types='%.*s'\n", payload_types.len, payload_types.s);
- #endif
- if (sdp_stream->is_rtp && payload_types.len > 0 && node->rn_ptl_supported != 0) {
- pt_opts.oidx = 0;
- if (append_opts(&pt_opts, 'c') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- /*
- * Convert space-separated payload types list into
- * a comma-separated list.
- */
- for (cp = payload_types.s;
- cp < payload_types.s + payload_types.len; cp++) {
- if (isdigit(*cp)) {
- if (append_opts(&pt_opts, *cp) == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- continue;
- }
- do {
- cp++;
- } while (!isdigit(*cp) &&
- cp < payload_types.s + payload_types.len);
- /* Check EOL */
- if (cp >= payload_types.s + payload_types.len)
- break;
- if (append_opts(&pt_opts, ',') == -1) {
- LM_ERR("out of pkg memory\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- cp--;
- }
- v[3].iov_base = pt_opts.s.s;
- v[3].iov_len = pt_opts.oidx;
- } else {
- v[3].iov_len = 0;
- }
- if (to_tag.len > 0) {
- iovec_param_count = 20;
- if (opts.s.s[0] == 'U' && timeout_socket_str.len > 0) {
- iovec_param_count = 22;
- STR2IOVEC(timeout_socket_str, v[21]);
- }
- } else {
- iovec_param_count = 16;
- }
- cp = send_rtpp_command(node, v, iovec_param_count);
- } while (cp == NULL);
- LM_DBG("proxy reply: %s\n", cp);
- /* Parse proxy reply to <argc,argv> */
- argc = 0;
- memset(argv, 0, sizeof(argv));
- cpend=cp+strlen(cp);
- next=eat_token_end(cp, cpend);
- for (ap=argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
- *next=0;
- if (*cp != '\0') {
- *ap=cp;
- argc++;
- if ((char*)++ap >= ((char*)argv+sizeof(argv)))
- break;
- }
- }
- if (argc < 1) {
- LM_ERR("no reply from rtp proxy\n");
- FORCE_RTP_PROXY_RET (-1);
- }
- port = atoi(argv[0]);
- if (port <= 0 || port > 65535) {
- if (port != 0 || flookup == 0)
- LM_ERR("incorrect port %i in reply "
- "from rtp proxy\n",port);
- FORCE_RTP_PROXY_RET (-1);
- }
- pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;
- if (isnulladdr(&oldip, pf)) {
- if (pf1 == AF_INET6) {
- newip.s = "::";
- newip.len = 2;
- } else {
- newip.s = "0.0.0.0";
- newip.len = 7;
- }
- } else {
- if (forcedIP) {
- newip.s = str2;
- newip.len = strlen(newip.s);
- #ifdef EXTRA_DEBUG
- LM_DBG("forcing IP='%.*s'\n", newip.len, newip.s);
- #endif
- } else {
- newip.s = (argc < 2) ? str2 : argv[1];
- newip.len = strlen(newip.s);
- }
- }
- /* marker to double check : newport goes: str -> int -> str ?!?! */
- newport.s = int2str(port, &newport.len); /* beware static buffer */
- /* Alter port. */
- body1.s = sdp_stream->media.s;
- body1.len = bodylimit - body1.s;
- #ifdef EXTRA_DEBUG
- LM_DBG("alter port body1='%.*s'\n", body1.len, body1.s);
- #endif
- /* do not do it if old port was 0 (means media disable)
- * - check if actually should be better done in rtpptoxy,
- * by returning also 0
- * - or by not sending to rtpproxy the old port if 0
- */
- if(oldport.len!=1 || oldport.s[0]!='0')
- {
- if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- }
-
- /*
- * Alter RTCP attribute if present. Inserting RTP port + 1 (as allocated
- * by RTP proxy). No IP-address is needed in the new RTCP attribute as the
- * 'c' attribute (altered below) will contain the RTP proxy IP address.
- * See RFC 3605 for definition of RTCP attribute.
- * ported from ser
- */
- if (sdp_stream->rtcp_port.s && sdp_stream->rtcp_port.len) {
- newrtcp.s = int2str(port+1, &newrtcp.len); /* beware static buffer */
- /* Alter port. */
- body1.s = sdp_stream->rtcp_port.s;
- body1.len = bodylimit - body1.s;
- #ifdef EXTRA_DEBUG
- LM_DBG("alter rtcp body1='%.*s'\n", body1.len, body1.s);
- #endif
- if (alter_rtcp(msg, &body1, &sdp_stream->rtcp_port, &newrtcp) == -1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- }
- /* Add ice relay candidates */
- if (ice_candidate_priority_val.n && sdp_stream->ice_attrs_num > 0) {
- body1.s = sdp_stream->ice_attr->foundation.s - 12;
- body1.len = bodylimit - body1.s;
- if (insert_candidates(msg, sdp_stream->ice_attr->foundation.s - 12,
- &newip, port, ice_candidate_priority_val.n) == -1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- }
- c1p = sdp_session->ip_addr.s;
- c2p = sdp_stream->ip_addr.s;
- /*
- * Alter IP. Don't alter IP common for the session
- * more than once.
- */
- if (c2p != NULL || !c1p_altered) {
- body1.s = c2p ? c2p : c1p;
- body1.len = bodylimit - body1.s;
- #ifdef EXTRA_DEBUG
- LM_DBG("alter ip body1='%.*s'\n", body1.len, body1.s);
- #endif
- if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0)==-1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- if (!c2p)
- c1p_altered = 1;
- }
- /*
- * Alter common IP if required, but don't do it more than once.
- */
- if (commip && c1p && !c1p_altered) {
- body1.s = c1p;
- body1.len = bodylimit - body1.s;
- #ifdef EXTRA_DEBUG
- LM_DBG("alter common ip body1='%.*s'\n", body1.len, body1.s);
- #endif
- if (alter_mediaip(msg, &body1, &sdp_session->ip_addr, sdp_session->pf, &newip, pf1, 0)==-1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- c1p_altered = 1;
- }
- /*
- * Alter the IP in "o=", but only once per session
- */
- if (o1p) {
- body1.s = o1p;
- body1.len = bodylimit - body1.s;
- #ifdef EXTRA_DEBUG
- LM_DBG("alter media ip body1='%.*s'\n", body1.len, body1.s);
- #endif
- if (alter_mediaip(msg, &body1, &sdp_session->o_ip_addr, sdp_session->o_pf, &newip, pf1, 0)==-1) {
- FORCE_RTP_PROXY_RET (-1);
- }
- o1p = 0;
- }
- sdp_stream_num++;
- }
- sdp_session_num++;
- }
- free_opts(&opts, &rep_opts, &pt_opts);
- if (proxied == 0 && nortpproxy_str.len) {
- cp = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
- if (cp == NULL) {
- LM_ERR("out of pkg memory\n");
- return -1;
- }
- anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
- if (anchor == NULL) {
- LM_ERR("anchor_lump failed\n");
- pkg_free(cp);
- return -1;
- }
- memcpy(cp, CRLF, CRLF_LEN);
- memcpy(cp + CRLF_LEN, nortpproxy_str.s, nortpproxy_str.len);
- if (insert_new_lump_after(anchor, cp, nortpproxy_str.len + CRLF_LEN, 0) == NULL) {
- LM_ERR("insert_new_lump_after failed\n");
- pkg_free(cp);
- return -1;
- }
- }
- return 1;
- }
- static int start_recording_f(struct sip_msg* msg, char *foo, char *bar)
- {
- int nitems;
- str callid = {0, 0};
- str from_tag = {0, 0};
- str to_tag = {0, 0};
- struct rtpp_node *node;
- struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"R", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
- /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 1 */
- if (get_callid(msg, &callid) == -1 || callid.len == 0) {
- LM_ERR("can't get Call-Id field\n");
- return -1;
- }
- if (get_to_tag(msg, &to_tag) == -1) {
- LM_ERR("can't get To tag\n");
- return -1;
- }
- if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
- LM_ERR("can't get From tag\n");
- return -1;
- }
- if(msg->id != current_msg_id){
- selected_rtpp_set = default_rtpp_set;
- }
- STR2IOVEC(callid, v[3]);
- STR2IOVEC(from_tag, v[5]);
- STR2IOVEC(to_tag, v[7]);
- node = select_rtpp_node(callid, 1);
- if (!node) {
- LM_ERR("no available proxies\n");
- return -1;
- }
- nitems = 8;
- if (msg->first_line.type == SIP_REPLY) {
- if (to_tag.len == 0)
- return -1;
- STR2IOVEC(to_tag, v[5]);
- STR2IOVEC(from_tag, v[7]);
- } else {
- STR2IOVEC(from_tag, v[5]);
- STR2IOVEC(to_tag, v[7]);
- if (to_tag.len <= 0)
- nitems = 6;
- }
- send_rtpp_command(node, v, nitems);
- return 1;
- }
- /*
- * Returns the current RTP-Statistics from the RTP-Proxy
- */
- static int
- pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param,
- pv_value_t *res)
- {
- str ret_val = {0, 0};
- int nitems;
- str callid = {0, 0};
- str from_tag = {0, 0};
- str to_tag = {0, 0};
- struct rtpp_node *node;
- struct iovec v[1 + 4 + 3 + 1] = {{NULL, 0}, {"Q", 1}, {" ", 1}, {NULL, 0},
- {" ", 1}, {NULL, 0}, {";1 ", 3}, {";1", }, {NULL, 0}};
- if (get_callid(msg, &callid) == -1 || callid.len == 0) {
- LM_ERR("can't get Call-Id field\n");
- return pv_get_null(msg, param, res);
- }
- if (get_to_tag(msg, &to_tag) == -1) {
- LM_ERR("can't get To tag\n");
- return pv_get_null(msg, param, res);
- }
- if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
- LM_ERR("can't get From tag\n");
- return pv_get_null(msg, param, res);
- }
- if(msg->id != current_msg_id){
- selected_rtpp_set = default_rtpp_set;
- }
- STR2IOVEC(callid, v[3]);
- STR2IOVEC(from_tag, v[5]);
- STR2IOVEC(to_tag, v[7]);
- node = select_rtpp_node(callid, 1);
- if (!node) {
- LM_ERR("no available proxies\n");
- return -1;
- }
- nitems = 8;
- if (msg->first_line.type == SIP_REPLY) {
- if (to_tag.len == 0)
- return -1;
- STR2IOVEC(to_tag, v[5]);
- STR2IOVEC(from_tag, v[7]);
- } else {
- STR2IOVEC(from_tag, v[5]);
- STR2IOVEC(to_tag, v[7]);
- if (to_tag.len <= 0)
- nitems = 6;
- }
- ret_val.s = send_rtpp_command(node, v, nitems);
- if(ret_val.s==NULL)
- return pv_get_null(msg, param, res);
- ret_val.len = strlen(ret_val.s);
- return pv_get_strval(msg, param, res, &ret_val);
- }
|