rtpengine.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156
  1. /* $Id$
  2. *
  3. * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
  4. *
  5. * This file is part of Kamailio, a free SIP server.
  6. *
  7. * Kamailio is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version
  11. *
  12. * Kamailio is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * History:
  22. * ---------
  23. * 2003-10-09 nat_uac_test introduced (jiri)
  24. *
  25. * 2003-11-06 nat_uac_test permitted from onreply_route (jiri)
  26. *
  27. * 2003-12-01 unforce_rtp_proxy introduced (sobomax)
  28. *
  29. * 2004-01-07 RTP proxy support updated to support new version of the
  30. * RTP proxy (20040107).
  31. *
  32. * force_rtp_proxy() now inserts a special flag
  33. * into the SDP body to indicate that this session already
  34. * proxied and ignores sessions with such flag.
  35. *
  36. * Added run-time check for version of command protocol
  37. * supported by the RTP proxy.
  38. *
  39. * 2004-01-16 Integrated slightly modified patch from Tristan Colgate,
  40. * force_rtp_proxy function with IP as a parameter (janakj)
  41. *
  42. * 2004-01-28 nat_uac_test extended to allow testing SDP body (sobomax)
  43. *
  44. * nat_uac_test extended to allow testing top Via (sobomax)
  45. *
  46. * 2004-02-21 force_rtp_proxy now accepts option argument, which
  47. * consists of string of chars, each of them turns "on"
  48. * some feature, currently supported ones are:
  49. *
  50. * `a' - flags that UA from which message is received
  51. * doesn't support symmetric RTP;
  52. * `l' - force "lookup", that is, only rewrite SDP when
  53. * corresponding session is already exists in the
  54. * RTP proxy. Only makes sense for SIP requests,
  55. * replies are always processed in "lookup" mode;
  56. * `i' - flags that message is received from UA in the
  57. * LAN. Only makes sense when RTP proxy is running
  58. * in the bridge mode.
  59. *
  60. * force_rtp_proxy can now be invoked without any arguments,
  61. * as previously, with one argument - in this case argument
  62. * is treated as option string and with two arguments, in
  63. * which case 1st argument is option string and the 2nd
  64. * one is IP address which have to be inserted into
  65. * SDP (IP address on which RTP proxy listens).
  66. *
  67. * 2004-03-12 Added support for IPv6 addresses in SDPs. Particularly,
  68. * force_rtp_proxy now can work with IPv6-aware RTP proxy,
  69. * replacing IPv4 address in SDP with IPv6 one and vice versa.
  70. * This allows creating full-fledged IPv4<->IPv6 gateway.
  71. * See 4to6.cfg file for example.
  72. *
  73. * Two new options added into force_rtp_proxy:
  74. *
  75. * `f' - instructs nathelper to ignore marks inserted
  76. * by another nathelper in transit to indicate
  77. * that the session is already goes through another
  78. * proxy. Allows creating chain of proxies.
  79. * `r' - flags that IP address in SDP should be trusted.
  80. * Without this flag, nathelper ignores address in the
  81. * SDP and uses source address of the SIP message
  82. * as media address which is passed to the RTP proxy.
  83. *
  84. * Protocol between nathelper and RTP proxy in bridge
  85. * mode has been slightly changed. Now RTP proxy expects SER
  86. * to provide 2 flags when creating or updating session
  87. * to indicate direction of this session. Each of those
  88. * flags can be either `e' or `i'. For example `ei' means
  89. * that we received INVITE from UA on the "external" network
  90. * network and will send it to the UA on "internal" one.
  91. * Also possible `ie' (internal->external), `ii'
  92. * (internal->internal) and `ee' (external->external). See
  93. * example file alg.cfg for details.
  94. *
  95. * 2004-03-15 If the rtp proxy test failed (wrong version or not started)
  96. * retry test from time to time, when some *rtpproxy* function
  97. * is invoked. Minimum interval between retries can be
  98. * configured via rtpproxy_disable_tout module parameter (default
  99. * is 60 seconds). Setting it to -1 will disable periodic
  100. * rechecks completely, setting it to 0 will force checks
  101. * for each *rtpproxy* function call. (andrei)
  102. *
  103. * 2004-03-22 Fix assignment of rtpproxy_retr and rtpproxy_tout module
  104. * parameters.
  105. *
  106. * 2004-03-22 Fix get_body position (should be called before get_callid)
  107. * (andrei)
  108. *
  109. * 2004-03-24 Fix newport for null ip address case (e.g onhold re-INVITE)
  110. * (andrei)
  111. *
  112. * 2004-09-30 added received port != via port test (andrei)
  113. *
  114. * 2004-10-10 force_socket option introduced (jiri)
  115. *
  116. * 2005-02-24 Added support for using more than one rtp proxy, in which
  117. * case traffic will be distributed evenly among them. In addition,
  118. * each such proxy can be assigned a weight, which will specify
  119. * which share of the traffic should be placed to this particular
  120. * proxy.
  121. *
  122. * Introduce failover mechanism, so that if SER detects that one
  123. * of many proxies is no longer available it temporarily decreases
  124. * its weight to 0, so that no traffic will be assigned to it.
  125. * Such "disabled" proxies are periodically checked to see if they
  126. * are back to normal in which case respective weight is restored
  127. * resulting in traffic being sent to that proxy again.
  128. *
  129. * Those features can be enabled by specifying more than one "URI"
  130. * in the rtpproxy_sock parameter, optionally followed by the weight,
  131. * which if absent is assumed to be 1, for example:
  132. *
  133. * rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1"
  134. *
  135. * 2005-02-25 Force for pinging the socket returned by USRLOC (bogdan)
  136. *
  137. * 2005-03-22 support for multiple media streams added (netch)
  138. *
  139. * 2005-07-11 SIP ping support added (bogdan)
  140. *
  141. * 2005-07-14 SDP origin (o=) IP may be also changed (bogdan)
  142. *
  143. * 2006-03-08 fix_nated_sdp() may take one more param to force a specific IP;
  144. * force_rtp_proxy() accepts a new flag 's' to swap creation/
  145. * confirmation between requests/replies;
  146. * add_rcv_param() may take as parameter a flag telling if the
  147. * parameter should go to the contact URI or contact header;
  148. * (bogdan)
  149. * 2006-03-28 Support for changing session-level SDP connection (c=) IP when
  150. * media-description also includes connection information (bayan)
  151. * 2007-04-13 Support multiple sets of rtpproxies and set selection added
  152. * (ancuta)
  153. * 2007-04-26 Added some MI commands:
  154. * nh_enable_ping used to enable or disable natping
  155. * nh_enable_rtpp used to enable or disable a specific rtp proxy
  156. * nh_show_rtpp used to display information for all rtp proxies
  157. * (ancuta)
  158. * 2007-05-09 New function start_recording() allowing to start recording RTP
  159. * session in the RTP proxy (Carsten Bock - ported from SER)
  160. * 2007-09-11 Separate timer process and support for multiple timer processes
  161. * (bogdan)
  162. * 2008-12-12 Support for RTCP attribute in the SDP
  163. * (Min Wang/BASIS AudioNet - ported from SER)
  164. * 2010-08-05 Core SDP parser integrated into nathelper (osas)
  165. * 2010-10-08 Removal of deprecated force_rtp_proxy and swap flag (osas)
  166. */
  167. #include <sys/types.h>
  168. #include <sys/socket.h>
  169. #include <sys/time.h>
  170. #include <netinet/in.h>
  171. #include <netinet/in_systm.h>
  172. #ifndef __USE_BSD
  173. #define __USE_BSD
  174. #endif
  175. #include <netinet/ip.h>
  176. #ifndef __FAVOR_BSD
  177. #define __FAVOR_BSD
  178. #endif
  179. #include <netinet/udp.h>
  180. #include <arpa/inet.h>
  181. #include <sys/uio.h>
  182. #include <sys/un.h>
  183. #include <ctype.h>
  184. #include <errno.h>
  185. #include <netdb.h>
  186. #include <poll.h>
  187. #include <stdio.h>
  188. #include <stdlib.h>
  189. #include <string.h>
  190. #include <unistd.h>
  191. #include "../../flags.h"
  192. #include "../../sr_module.h"
  193. #include "../../dprint.h"
  194. #include "../../data_lump.h"
  195. #include "../../data_lump_rpl.h"
  196. #include "../../error.h"
  197. #include "../../forward.h"
  198. #include "../../mem/mem.h"
  199. #include "../../parser/parse_from.h"
  200. #include "../../parser/parse_to.h"
  201. #include "../../parser/parse_uri.h"
  202. #include "../../parser/parser_f.h"
  203. #include "../../parser/sdp/sdp.h"
  204. #include "../../resolve.h"
  205. #include "../../timer.h"
  206. #include "../../trim.h"
  207. #include "../../ut.h"
  208. #include "../../pt.h"
  209. #include "../../timer_proc.h"
  210. #include "../../lib/kmi/mi.h"
  211. #include "../../pvar.h"
  212. #include "../../lvalue.h"
  213. #include "../../msg_translator.h"
  214. #include "../../usr_avp.h"
  215. #include "../../socket_info.h"
  216. #include "../../mod_fix.h"
  217. #include "../../dset.h"
  218. #include "../../route.h"
  219. #include "../../modules/tm/tm_load.h"
  220. #include "rtpengine.h"
  221. #include "rtpengine_funcs.h"
  222. #include "bencode.h"
  223. MODULE_VERSION
  224. #if !defined(AF_LOCAL)
  225. #define AF_LOCAL AF_UNIX
  226. #endif
  227. #if !defined(PF_LOCAL)
  228. #define PF_LOCAL PF_UNIX
  229. #endif
  230. /* NAT UAC test constants */
  231. #define NAT_UAC_TEST_C_1918 0x01
  232. #define NAT_UAC_TEST_RCVD 0x02
  233. #define NAT_UAC_TEST_V_1918 0x04
  234. #define NAT_UAC_TEST_S_1918 0x08
  235. #define NAT_UAC_TEST_RPORT 0x10
  236. #define DEFAULT_RTPP_SET_ID 0
  237. #define MI_SET_NATPING_STATE "nh_enable_ping"
  238. #define MI_DEFAULT_NATPING_STATE 1
  239. #define MI_ENABLE_RTP_PROXY "nh_enable_rtpp"
  240. #define MI_MIN_RECHECK_TICKS 0
  241. #define MI_MAX_RECHECK_TICKS (unsigned int)-1
  242. #define MI_SHOW_RTP_PROXIES "nh_show_rtpp"
  243. #define MI_RTP_PROXY_NOT_FOUND "RTP proxy not found"
  244. #define MI_RTP_PROXY_NOT_FOUND_LEN (sizeof(MI_RTP_PROXY_NOT_FOUND)-1)
  245. #define MI_PING_DISABLED "NATping disabled from script"
  246. #define MI_PING_DISABLED_LEN (sizeof(MI_PING_DISABLED)-1)
  247. #define MI_SET "set"
  248. #define MI_SET_LEN (sizeof(MI_SET)-1)
  249. #define MI_INDEX "index"
  250. #define MI_INDEX_LEN (sizeof(MI_INDEX)-1)
  251. #define MI_DISABLED "disabled"
  252. #define MI_DISABLED_LEN (sizeof(MI_DISABLED)-1)
  253. #define MI_WEIGHT "weight"
  254. #define MI_WEIGHT_LEN (sizeof(MI_WEIGHT)-1)
  255. #define MI_RECHECK_TICKS "recheck_ticks"
  256. #define MI_RECHECK_T_LEN (sizeof(MI_RECHECK_TICKS)-1)
  257. #define CPORT "22222"
  258. enum rtpe_operation {
  259. OP_OFFER = 1,
  260. OP_ANSWER,
  261. OP_DELETE,
  262. OP_START_RECORDING,
  263. OP_QUERY,
  264. };
  265. struct ng_flags_parse {
  266. int via, to, packetize, transport;
  267. bencode_item_t *dict, *flags, *direction, *replace, *rtcp_mux;
  268. };
  269. static const char *command_strings[] = {
  270. [OP_OFFER] = "offer",
  271. [OP_ANSWER] = "answer",
  272. [OP_DELETE] = "delete",
  273. [OP_START_RECORDING] = "start recording",
  274. [OP_QUERY] = "query",
  275. };
  276. static char *gencookie();
  277. static int rtpp_test(struct rtpp_node*, int, int);
  278. static int start_recording_f(struct sip_msg *, char *, char *);
  279. static int rtpengine_answer1_f(struct sip_msg *, char *, char *);
  280. static int rtpengine_offer1_f(struct sip_msg *, char *, char *);
  281. static int rtpengine_delete1_f(struct sip_msg *, char *, char *);
  282. static int rtpengine_manage1_f(struct sip_msg *, char *, char *);
  283. static int parse_flags(struct ng_flags_parse *, struct sip_msg *, enum rtpe_operation *, const char *);
  284. static int rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op, int more);
  285. static int fixup_set_id(void ** param, int param_no);
  286. static int set_rtpengine_set_f(struct sip_msg * msg, char * str1, char * str2);
  287. static struct rtpp_set * select_rtpp_set(int id_set);
  288. static struct rtpp_node *select_rtpp_node(str, int);
  289. static char *send_rtpp_command(struct rtpp_node *, bencode_item_t *, int *);
  290. static int get_extra_id(struct sip_msg* msg, str *id_str);
  291. static int rtpengine_set_store(modparam_t type, void * val);
  292. static int rtpengine_add_rtpengine_set( char * rtp_proxies);
  293. static int mod_init(void);
  294. static int child_init(int);
  295. static void mod_destroy(void);
  296. /* Pseudo-Variables */
  297. static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
  298. /*mi commands*/
  299. static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
  300. void* param );
  301. static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
  302. void* param);
  303. static int rtpengine_disable_tout = 60;
  304. static int rtpengine_retr = 5;
  305. static int rtpengine_tout = 1;
  306. static pid_t mypid;
  307. static unsigned int myseqn = 0;
  308. static str extra_id_pv_param = {NULL, 0};
  309. static char *setid_avp_param = NULL;
  310. static char ** rtpp_strings=0;
  311. static int rtpp_sets=0; /*used in rtpengine_set_store()*/
  312. static int rtpp_set_count = 0;
  313. static unsigned int current_msg_id = (unsigned int)-1;
  314. /* RTP proxy balancing list */
  315. static struct rtpp_set_head * rtpp_set_list =0;
  316. static struct rtpp_set * active_rtpp_set =0;
  317. static struct rtpp_set * selected_rtpp_set_1 =0;
  318. static struct rtpp_set * selected_rtpp_set_2 =0;
  319. static struct rtpp_set * default_rtpp_set=0;
  320. static str body_intermediate;
  321. /* array with the sockets used by rtpporxy (per process)*/
  322. static unsigned int rtpp_no = 0;
  323. static int *rtpp_socks = 0;
  324. static int setid_avp_type;
  325. static int_str setid_avp;
  326. typedef struct rtpp_set_link {
  327. struct rtpp_set *rset;
  328. pv_spec_t *rpv;
  329. } rtpp_set_link_t;
  330. /* tm */
  331. static struct tm_binds tmb;
  332. /*0-> disabled, 1 ->enabled*/
  333. unsigned int *natping_state=0;
  334. static pv_elem_t *extra_id_pv = NULL;
  335. static cmd_export_t cmds[] = {
  336. {"set_rtpengine_set", (cmd_function)set_rtpengine_set_f, 1,
  337. fixup_set_id, 0,
  338. ANY_ROUTE},
  339. {"set_rtpengine_set", (cmd_function)set_rtpengine_set_f, 2,
  340. fixup_set_id, 0,
  341. ANY_ROUTE},
  342. {"start_recording", (cmd_function)start_recording_f, 0,
  343. 0, 0,
  344. ANY_ROUTE },
  345. {"rtpengine_offer", (cmd_function)rtpengine_offer1_f, 0,
  346. 0, 0,
  347. ANY_ROUTE},
  348. {"rtpengine_offer", (cmd_function)rtpengine_offer1_f, 1,
  349. fixup_spve_null, 0,
  350. ANY_ROUTE},
  351. {"rtpengine_answer", (cmd_function)rtpengine_answer1_f, 0,
  352. 0, 0,
  353. ANY_ROUTE},
  354. {"rtpengine_answer", (cmd_function)rtpengine_answer1_f, 1,
  355. fixup_spve_null, 0,
  356. ANY_ROUTE},
  357. {"rtpengine_manage", (cmd_function)rtpengine_manage1_f, 0,
  358. 0, 0,
  359. ANY_ROUTE},
  360. {"rtpengine_manage", (cmd_function)rtpengine_manage1_f, 1,
  361. fixup_spve_null, 0,
  362. ANY_ROUTE},
  363. {"rtpengine_delete", (cmd_function)rtpengine_delete1_f, 0,
  364. 0, 0,
  365. ANY_ROUTE},
  366. {"rtpengine_delete", (cmd_function)rtpengine_delete1_f, 1,
  367. fixup_spve_null, 0,
  368. ANY_ROUTE},
  369. {0, 0, 0, 0, 0, 0}
  370. };
  371. static pv_export_t mod_pvs[] = {
  372. {{"rtpstat", (sizeof("rtpstat")-1)}, /* RTP-Statistics */
  373. PVT_OTHER, pv_get_rtpstat_f, 0, 0, 0, 0, 0},
  374. {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
  375. };
  376. static param_export_t params[] = {
  377. {"rtpengine_sock", PARAM_STRING|USE_FUNC_PARAM,
  378. (void*)rtpengine_set_store },
  379. {"rtpengine_disable_tout",INT_PARAM, &rtpengine_disable_tout },
  380. {"rtpengine_retr", INT_PARAM, &rtpengine_retr },
  381. {"rtpengine_tout", INT_PARAM, &rtpengine_tout },
  382. {"db_url", PARAM_STR, &rtpp_db_url },
  383. {"table_name", PARAM_STR, &rtpp_table_name },
  384. {"url_col", PARAM_STR, &rtpp_url_col },
  385. {"extra_id_pv", PARAM_STR, &extra_id_pv_param },
  386. {"setid_avp", PARAM_STRING, &setid_avp_param },
  387. {0, 0, 0}
  388. };
  389. static mi_export_t mi_cmds[] = {
  390. {MI_ENABLE_RTP_PROXY, mi_enable_rtp_proxy, 0, 0, 0},
  391. {MI_SHOW_RTP_PROXIES, mi_show_rtpproxies, MI_NO_INPUT_FLAG, 0, 0},
  392. { 0, 0, 0, 0, 0}
  393. };
  394. struct module_exports exports = {
  395. "rtpengine",
  396. DEFAULT_DLFLAGS, /* dlopen flags */
  397. cmds,
  398. params,
  399. 0, /* exported statistics */
  400. mi_cmds, /* exported MI functions */
  401. mod_pvs, /* exported pseudo-variables */
  402. 0, /* extra processes */
  403. mod_init,
  404. 0, /* reply processing */
  405. mod_destroy, /* destroy function */
  406. child_init
  407. };
  408. static inline int str_eq(const str *p, const char *q) {
  409. int l = strlen(q);
  410. if (p->len != l)
  411. return 0;
  412. if (memcmp(p->s, q, l))
  413. return 0;
  414. return 1;
  415. }
  416. static inline str str_prefix(const str *p, const char *q) {
  417. str ret;
  418. ret.s = NULL;
  419. int l = strlen(q);
  420. if (p->len < l)
  421. return ret;
  422. if (memcmp(p->s, q, l))
  423. return ret;
  424. ret = *p;
  425. ret.s += l;
  426. ret.len -= l;
  427. return ret;
  428. }
  429. static int rtpengine_set_store(modparam_t type, void * val){
  430. char * p;
  431. int len;
  432. p = (char* )val;
  433. if(p==0 || *p=='\0'){
  434. return 0;
  435. }
  436. if(rtpp_sets==0){
  437. rtpp_strings = (char**)pkg_malloc(sizeof(char*));
  438. if(!rtpp_strings){
  439. LM_ERR("no pkg memory left\n");
  440. return -1;
  441. }
  442. } else {/*realloc to make room for the current set*/
  443. rtpp_strings = (char**)pkg_realloc(rtpp_strings,
  444. (rtpp_sets+1)* sizeof(char*));
  445. if(!rtpp_strings){
  446. LM_ERR("no pkg memory left\n");
  447. return -1;
  448. }
  449. }
  450. /*allocate for the current set of urls*/
  451. len = strlen(p);
  452. rtpp_strings[rtpp_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
  453. if(!rtpp_strings[rtpp_sets]){
  454. LM_ERR("no pkg memory left\n");
  455. return -1;
  456. }
  457. memcpy(rtpp_strings[rtpp_sets], p, len);
  458. rtpp_strings[rtpp_sets][len] = '\0';
  459. rtpp_sets++;
  460. return 0;
  461. }
  462. struct rtpp_set *get_rtpp_set(int set_id)
  463. {
  464. struct rtpp_set * rtpp_list;
  465. unsigned int my_current_id = 0;
  466. int new_list;
  467. if (set_id < DEFAULT_RTPP_SET_ID )
  468. {
  469. LM_ERR(" invalid rtpproxy set value [%d]\n",
  470. set_id);
  471. return NULL;
  472. }
  473. my_current_id = set_id;
  474. /*search for the current_id*/
  475. rtpp_list = rtpp_set_list ? rtpp_set_list->rset_first : 0;
  476. while( rtpp_list != 0 && rtpp_list->id_set!=my_current_id)
  477. rtpp_list = rtpp_list->rset_next;
  478. if (rtpp_list==NULL)
  479. { /*if a new id_set : add a new set of rtpp*/
  480. rtpp_list = shm_malloc(sizeof(struct rtpp_set));
  481. if(!rtpp_list)
  482. {
  483. LM_ERR("no shm memory left to create new rtpproxy set %d\n", my_current_id);
  484. return NULL;
  485. }
  486. memset(rtpp_list, 0, sizeof(struct rtpp_set));
  487. rtpp_list->id_set = my_current_id;
  488. new_list = 1;
  489. }
  490. else {
  491. new_list = 0;
  492. }
  493. if (new_list)
  494. {
  495. if(!rtpp_set_list){/*initialize the list of set*/
  496. rtpp_set_list = shm_malloc(sizeof(struct rtpp_set_head));
  497. if(!rtpp_set_list){
  498. LM_ERR("no shm memory left to create list of proxysets\n");
  499. return NULL;
  500. }
  501. memset(rtpp_set_list, 0, sizeof(struct rtpp_set_head));
  502. }
  503. /*update the list of set info*/
  504. if (!rtpp_set_list->rset_first)
  505. {
  506. rtpp_set_list->rset_first = rtpp_list;
  507. }
  508. else
  509. {
  510. rtpp_set_list->rset_last->rset_next = rtpp_list;
  511. }
  512. rtpp_set_list->rset_last = rtpp_list;
  513. rtpp_set_count++;
  514. if(my_current_id == DEFAULT_RTPP_SET_ID){
  515. default_rtpp_set = rtpp_list;
  516. }
  517. }
  518. return rtpp_list;
  519. }
  520. int add_rtpengine_socks(struct rtpp_set * rtpp_list, char * rtpproxy)
  521. {
  522. /* Make rtp proxies list. */
  523. char *p, *p1, *p2, *plim;
  524. struct rtpp_node *pnode;
  525. int weight;
  526. p = rtpproxy;
  527. plim = p + strlen(p);
  528. for(;;) {
  529. weight = 1;
  530. while (*p && isspace((int)*p))
  531. ++p;
  532. if (p >= plim)
  533. break;
  534. p1 = p;
  535. while (*p && !isspace((int)*p))
  536. ++p;
  537. if (p <= p1)
  538. break; /* may happen??? */
  539. /* Have weight specified? If yes, scan it */
  540. p2 = memchr(p1, '=', p - p1);
  541. if (p2 != NULL) {
  542. weight = strtoul(p2 + 1, NULL, 10);
  543. } else {
  544. p2 = p;
  545. }
  546. pnode = shm_malloc(sizeof(struct rtpp_node));
  547. if (pnode == NULL) {
  548. LM_ERR("no shm memory left\n");
  549. return -1;
  550. }
  551. memset(pnode, 0, sizeof(*pnode));
  552. pnode->idx = rtpp_no++;
  553. pnode->rn_recheck_ticks = 0;
  554. pnode->rn_weight = weight;
  555. pnode->rn_umode = 0;
  556. pnode->rn_disabled = 0;
  557. pnode->rn_url.s = shm_malloc(p2 - p1 + 1);
  558. if (pnode->rn_url.s == NULL) {
  559. shm_free(pnode);
  560. LM_ERR("no shm memory left\n");
  561. return -1;
  562. }
  563. memmove(pnode->rn_url.s, p1, p2 - p1);
  564. pnode->rn_url.s[p2 - p1] = 0;
  565. pnode->rn_url.len = p2-p1;
  566. LM_DBG("url is %s, len is %i\n", pnode->rn_url.s, pnode->rn_url.len);
  567. /* Leave only address in rn_address */
  568. pnode->rn_address = pnode->rn_url.s;
  569. if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
  570. pnode->rn_umode = 1;
  571. pnode->rn_address += 4;
  572. } else if (strncasecmp(pnode->rn_address, "udp6:", 5) == 0) {
  573. pnode->rn_umode = 6;
  574. pnode->rn_address += 5;
  575. } else if (strncasecmp(pnode->rn_address, "unix:", 5) == 0) {
  576. pnode->rn_umode = 0;
  577. pnode->rn_address += 5;
  578. }
  579. if (rtpp_list->rn_first == NULL) {
  580. rtpp_list->rn_first = pnode;
  581. } else {
  582. rtpp_list->rn_last->rn_next = pnode;
  583. }
  584. rtpp_list->rn_last = pnode;
  585. rtpp_list->rtpp_node_count++;
  586. }
  587. return 0;
  588. }
  589. /* 0-succes
  590. * -1 - erorr
  591. * */
  592. static int rtpengine_add_rtpengine_set( char * rtp_proxies)
  593. {
  594. char *p,*p2;
  595. struct rtpp_set * rtpp_list;
  596. unsigned int my_current_id;
  597. str id_set;
  598. /* empty definition? */
  599. p= rtp_proxies;
  600. if(!p || *p=='\0'){
  601. return 0;
  602. }
  603. for(;*p && isspace(*p);p++);
  604. if(*p=='\0'){
  605. return 0;
  606. }
  607. rtp_proxies = strstr(p, "==");
  608. if(rtp_proxies){
  609. if(*(rtp_proxies +2)=='\0'){
  610. LM_ERR("script error -invalid rtp proxy list!\n");
  611. return -1;
  612. }
  613. *rtp_proxies = '\0';
  614. p2 = rtp_proxies-1;
  615. for(;isspace(*p2); *p2 = '\0',p2--);
  616. id_set.s = p; id_set.len = p2 - p+1;
  617. if(id_set.len <= 0 ||str2int(&id_set, &my_current_id)<0 ){
  618. LM_ERR("script error -invalid set_id value!\n");
  619. return -1;
  620. }
  621. rtp_proxies+=2;
  622. }else{
  623. rtp_proxies = p;
  624. my_current_id = DEFAULT_RTPP_SET_ID;
  625. }
  626. for(;*rtp_proxies && isspace(*rtp_proxies);rtp_proxies++);
  627. if(!(*rtp_proxies)){
  628. LM_ERR("script error -empty rtp_proxy list\n");
  629. return -1;;
  630. }
  631. /*search for the current_id*/
  632. rtpp_list = get_rtpp_set(my_current_id);
  633. if (rtpp_list != NULL)
  634. {
  635. if (add_rtpengine_socks(rtpp_list, rtp_proxies) != 0)
  636. goto error;
  637. else
  638. return 0;
  639. }
  640. error:
  641. return -1;
  642. }
  643. static int fixup_set_id(void ** param, int param_no)
  644. {
  645. int int_val, err;
  646. struct rtpp_set* rtpp_list;
  647. rtpp_set_link_t *rtpl = NULL;
  648. str s;
  649. rtpl = (rtpp_set_link_t*)pkg_malloc(sizeof(rtpp_set_link_t));
  650. if(rtpl==NULL) {
  651. LM_ERR("no more pkg memory\n");
  652. return -1;
  653. }
  654. memset(rtpl, 0, sizeof(rtpp_set_link_t));
  655. s.s = (char*)*param;
  656. s.len = strlen(s.s);
  657. if(s.s[0] == PV_MARKER) {
  658. int_val = pv_locate_name(&s);
  659. if(int_val<0 || int_val!=s.len) {
  660. LM_ERR("invalid parameter %s\n", s.s);
  661. return -1;
  662. }
  663. rtpl->rpv = pv_cache_get(&s);
  664. if(rtpl->rpv == NULL) {
  665. LM_ERR("invalid pv parameter %s\n", s.s);
  666. return -1;
  667. }
  668. } else {
  669. int_val = str2s(*param, strlen(*param), &err);
  670. if (err == 0) {
  671. pkg_free(*param);
  672. if((rtpp_list = select_rtpp_set(int_val)) ==0){
  673. LM_ERR("rtpp_proxy set %i not configured\n", int_val);
  674. return E_CFG;
  675. }
  676. rtpl->rset = rtpp_list;
  677. } else {
  678. LM_ERR("bad number <%s>\n", (char *)(*param));
  679. return E_CFG;
  680. }
  681. }
  682. *param = (void*)rtpl;
  683. return 0;
  684. }
  685. static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
  686. void* param )
  687. { struct mi_node* node;
  688. str rtpp_url;
  689. unsigned int enable;
  690. struct rtpp_set * rtpp_list;
  691. struct rtpp_node * crt_rtpp;
  692. int found;
  693. found = 0;
  694. if(rtpp_set_list ==NULL)
  695. goto end;
  696. node = cmd_tree->node.kids;
  697. if(node == NULL)
  698. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  699. if(node->value.s == NULL || node->value.len ==0)
  700. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  701. rtpp_url = node->value;
  702. node = node->next;
  703. if(node == NULL)
  704. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  705. enable = 0;
  706. if( strno2int( &node->value, &enable) <0)
  707. goto error;
  708. for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
  709. rtpp_list = rtpp_list->rset_next){
  710. for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
  711. crt_rtpp = crt_rtpp->rn_next){
  712. /*found a matching rtpp*/
  713. if(crt_rtpp->rn_url.len == rtpp_url.len){
  714. if(strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0){
  715. /*set the enabled/disabled status*/
  716. found = 1;
  717. crt_rtpp->rn_recheck_ticks =
  718. enable? MI_MIN_RECHECK_TICKS : MI_MAX_RECHECK_TICKS;
  719. crt_rtpp->rn_disabled = enable?0:1;
  720. }
  721. }
  722. }
  723. }
  724. end:
  725. if(found)
  726. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  727. return init_mi_tree(404,MI_RTP_PROXY_NOT_FOUND,MI_RTP_PROXY_NOT_FOUND_LEN);
  728. error:
  729. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  730. }
  731. #define add_rtpp_node_int_info(_parent, _name, _name_len, _value, _child,\
  732. _len, _string, _error)\
  733. do {\
  734. (_string) = int2str((_value), &(_len));\
  735. if((_string) == 0){\
  736. LM_ERR("cannot convert int value\n");\
  737. goto _error;\
  738. }\
  739. if(((_child) = add_mi_node_child((_parent), MI_DUP_VALUE, (_name), \
  740. (_name_len), (_string), (_len)) ) == 0)\
  741. goto _error;\
  742. }while(0);
  743. static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
  744. void* param)
  745. {
  746. struct mi_node* node, *crt_node, *child;
  747. struct mi_root* root;
  748. struct mi_attr * attr;
  749. struct rtpp_set * rtpp_list;
  750. struct rtpp_node * crt_rtpp;
  751. char * string, *id;
  752. int id_len, len;
  753. string = id = 0;
  754. root = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  755. if (!root) {
  756. LM_ERR("the MI tree cannot be initialized!\n");
  757. return 0;
  758. }
  759. if(rtpp_set_list ==NULL)
  760. return root;
  761. node = &root->node;
  762. for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
  763. rtpp_list = rtpp_list->rset_next){
  764. for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
  765. crt_rtpp = crt_rtpp->rn_next){
  766. id = int2str(rtpp_list->id_set, &id_len);
  767. if(!id){
  768. LM_ERR("cannot convert set id\n");
  769. goto error;
  770. }
  771. if(!(crt_node = add_mi_node_child(node, 0, crt_rtpp->rn_url.s,
  772. crt_rtpp->rn_url.len, 0,0)) ) {
  773. LM_ERR("cannot add the child node to the tree\n");
  774. goto error;
  775. }
  776. LM_DBG("adding node name %s \n",crt_rtpp->rn_url.s );
  777. if((attr = add_mi_attr(crt_node, MI_DUP_VALUE, MI_SET, MI_SET_LEN,
  778. id, id_len))== 0){
  779. LM_ERR("cannot add attributes to the node\n");
  780. goto error;
  781. }
  782. add_rtpp_node_int_info(crt_node, MI_INDEX, MI_INDEX_LEN,
  783. crt_rtpp->idx, child, len,string,error);
  784. add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
  785. crt_rtpp->rn_disabled, child, len,string,error);
  786. add_rtpp_node_int_info(crt_node, MI_WEIGHT, MI_WEIGHT_LEN,
  787. crt_rtpp->rn_weight, child, len, string,error);
  788. add_rtpp_node_int_info(crt_node, MI_RECHECK_TICKS,MI_RECHECK_T_LEN,
  789. crt_rtpp->rn_recheck_ticks, child, len, string, error);
  790. }
  791. }
  792. return root;
  793. error:
  794. if (root)
  795. free_mi_tree(root);
  796. return 0;
  797. }
  798. static int
  799. mod_init(void)
  800. {
  801. int i;
  802. pv_spec_t *avp_spec;
  803. unsigned short avp_flags;
  804. str s;
  805. if(register_mi_mod(exports.name, mi_cmds)!=0)
  806. {
  807. LM_ERR("failed to register MI commands\n");
  808. return -1;
  809. }
  810. /* any rtpproxy configured? */
  811. if(rtpp_set_list)
  812. default_rtpp_set = select_rtpp_set(DEFAULT_RTPP_SET_ID);
  813. if (rtpp_db_url.s == NULL)
  814. {
  815. /* storing the list of rtp proxy sets in shared memory*/
  816. for(i=0;i<rtpp_sets;i++){
  817. if(rtpengine_add_rtpengine_set(rtpp_strings[i]) !=0){
  818. for(;i<rtpp_sets;i++)
  819. if(rtpp_strings[i])
  820. pkg_free(rtpp_strings[i]);
  821. pkg_free(rtpp_strings);
  822. return -1;
  823. }
  824. if(rtpp_strings[i])
  825. pkg_free(rtpp_strings[i]);
  826. }
  827. }
  828. else
  829. {
  830. LM_INFO("Loading rtp proxy definitions from DB\n");
  831. if ( init_rtpproxy_db() < 0)
  832. {
  833. LM_ERR("error while loading rtp proxies from database\n");
  834. return -1;
  835. }
  836. }
  837. if (extra_id_pv_param.s && *extra_id_pv_param.s) {
  838. extra_id_pv_param.len = strlen(extra_id_pv_param.s);
  839. if(pv_parse_format(&extra_id_pv_param, &extra_id_pv) < 0) {
  840. LM_ERR("malformed PV string: %s\n", extra_id_pv_param.s);
  841. return -1;
  842. }
  843. } else {
  844. extra_id_pv = NULL;
  845. }
  846. if (setid_avp_param) {
  847. s.s = setid_avp_param; s.len = strlen(s.s);
  848. avp_spec = pv_cache_get(&s);
  849. if (avp_spec==NULL || (avp_spec->type != PVT_AVP)) {
  850. LM_ERR("malformed or non AVP definition <%s>\n",
  851. setid_avp_param);
  852. return -1;
  853. }
  854. if (pv_get_avp_name(0, &(avp_spec->pvp), &setid_avp,
  855. &avp_flags) != 0) {
  856. LM_ERR("invalid AVP definition <%s>\n", setid_avp_param);
  857. return -1;
  858. }
  859. setid_avp_type = avp_flags;
  860. }
  861. if (rtpp_strings)
  862. pkg_free(rtpp_strings);
  863. if (load_tm_api( &tmb ) < 0)
  864. {
  865. LM_DBG("could not load the TM-functions - answer-offer model"
  866. " auto-detection is disabled\n");
  867. memset(&tmb, 0, sizeof(struct tm_binds));
  868. }
  869. return 0;
  870. }
  871. static int
  872. child_init(int rank)
  873. {
  874. int n;
  875. char *cp;
  876. struct addrinfo hints, *res;
  877. struct rtpp_set *rtpp_list;
  878. struct rtpp_node *pnode;
  879. if(rtpp_set_list==NULL )
  880. return 0;
  881. /* Iterate known RTP proxies - create sockets */
  882. mypid = getpid();
  883. rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
  884. if (rtpp_socks==NULL) {
  885. LM_ERR("no more pkg memory\n");
  886. return -1;
  887. }
  888. for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
  889. rtpp_list = rtpp_list->rset_next){
  890. for (pnode=rtpp_list->rn_first; pnode!=0; pnode = pnode->rn_next){
  891. char *hostname;
  892. if (pnode->rn_umode == 0) {
  893. rtpp_socks[pnode->idx] = -1;
  894. goto rptest;
  895. }
  896. /*
  897. * This is UDP or UDP6. Detect host and port; lookup host;
  898. * do connect() in order to specify peer address
  899. */
  900. hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->rn_address) + 1));
  901. if (hostname==NULL) {
  902. LM_ERR("no more pkg memory\n");
  903. return -1;
  904. }
  905. strcpy(hostname, pnode->rn_address);
  906. cp = strrchr(hostname, ':');
  907. if (cp != NULL) {
  908. *cp = '\0';
  909. cp++;
  910. }
  911. if (cp == NULL || *cp == '\0')
  912. cp = CPORT;
  913. memset(&hints, 0, sizeof(hints));
  914. hints.ai_flags = 0;
  915. hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;
  916. hints.ai_socktype = SOCK_DGRAM;
  917. if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
  918. LM_ERR("%s\n", gai_strerror(n));
  919. pkg_free(hostname);
  920. return -1;
  921. }
  922. pkg_free(hostname);
  923. rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
  924. ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
  925. if ( rtpp_socks[pnode->idx] == -1) {
  926. LM_ERR("can't create socket\n");
  927. freeaddrinfo(res);
  928. return -1;
  929. }
  930. if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
  931. LM_ERR("can't connect to a RTP proxy\n");
  932. close( rtpp_socks[pnode->idx] );
  933. rtpp_socks[pnode->idx] = -1;
  934. freeaddrinfo(res);
  935. return -1;
  936. }
  937. freeaddrinfo(res);
  938. rptest:
  939. pnode->rn_disabled = rtpp_test(pnode, 0, 1);
  940. }
  941. }
  942. return 0;
  943. }
  944. static void mod_destroy(void)
  945. {
  946. struct rtpp_set * crt_list, * last_list;
  947. struct rtpp_node * crt_rtpp, *last_rtpp;
  948. /*free the shared memory*/
  949. if (natping_state)
  950. shm_free(natping_state);
  951. if(rtpp_set_list == NULL)
  952. return;
  953. for(crt_list = rtpp_set_list->rset_first; crt_list != NULL; ){
  954. for(crt_rtpp = crt_list->rn_first; crt_rtpp != NULL; ){
  955. if(crt_rtpp->rn_url.s)
  956. shm_free(crt_rtpp->rn_url.s);
  957. last_rtpp = crt_rtpp;
  958. crt_rtpp = last_rtpp->rn_next;
  959. shm_free(last_rtpp);
  960. }
  961. last_list = crt_list;
  962. crt_list = last_list->rset_next;
  963. shm_free(last_list);
  964. }
  965. shm_free(rtpp_set_list);
  966. }
  967. static char * gencookie(void)
  968. {
  969. static char cook[34];
  970. sprintf(cook, "%d_%u ", (int)mypid, myseqn);
  971. myseqn++;
  972. return cook;
  973. }
  974. static const char *transports[] = {
  975. [0x00] = "RTP/AVP",
  976. [0x01] = "RTP/SAVP",
  977. [0x02] = "RTP/AVPF",
  978. [0x03] = "RTP/SAVPF",
  979. };
  980. static int parse_flags(struct ng_flags_parse *ng_flags, struct sip_msg *msg, enum rtpe_operation *op,
  981. const char *flags_str)
  982. {
  983. char *e;
  984. const char *err;
  985. str key, val, s;
  986. if (!flags_str)
  987. return 0;
  988. while (1) {
  989. while (*flags_str == ' ')
  990. flags_str++;
  991. key.s = (void *) flags_str;
  992. val.len = key.len = -1;
  993. val.s = NULL;
  994. e = strpbrk(key.s, " =");
  995. if (!e)
  996. e = key.s + strlen(key.s);
  997. else if (*e == '=') {
  998. key.len = e - key.s;
  999. val.s = e + 1;
  1000. e = strchr(val.s, ' ');
  1001. if (!e)
  1002. e = val.s + strlen(val.s);
  1003. val.len = e - val.s;
  1004. }
  1005. if (key.len == -1)
  1006. key.len = e - key.s;
  1007. if (!key.len)
  1008. break;
  1009. /* check for items which have their own sub-list */
  1010. s = str_prefix(&key, "replace-");
  1011. if (s.s) {
  1012. bencode_list_add_str(ng_flags->replace, &s);
  1013. goto next;
  1014. }
  1015. s = str_prefix(&key, "rtcp-mux-");
  1016. if (s.s) {
  1017. bencode_list_add_str(ng_flags->rtcp_mux, &s);
  1018. goto next;
  1019. }
  1020. /* check for specially handled items */
  1021. switch (key.len) {
  1022. case 3:
  1023. if (str_eq(&key, "RTP")) {
  1024. ng_flags->transport |= 0x100;
  1025. ng_flags->transport &= ~0x001;
  1026. }
  1027. else if (str_eq(&key, "AVP")) {
  1028. ng_flags->transport |= 0x100;
  1029. ng_flags->transport &= ~0x002;
  1030. }
  1031. else if (str_eq(&key, "TOS") && val.s)
  1032. bencode_dictionary_add_integer(ng_flags->dict, "TOS", atoi(val.s));
  1033. else
  1034. goto generic;
  1035. goto next;
  1036. break;
  1037. case 4:
  1038. if (str_eq(&key, "SRTP"))
  1039. ng_flags->transport |= 0x101;
  1040. else if (str_eq(&key, "AVPF"))
  1041. ng_flags->transport |= 0x102;
  1042. else
  1043. goto generic;
  1044. goto next;
  1045. break;
  1046. case 6:
  1047. if (str_eq(&key, "to-tag")) {
  1048. ng_flags->to = 1;
  1049. goto next;
  1050. }
  1051. break;
  1052. case 7:
  1053. if (str_eq(&key, "RTP/AVP")) {
  1054. ng_flags->transport = 0x100;
  1055. goto next;
  1056. }
  1057. break;
  1058. case 8:
  1059. if (str_eq(&key, "internal") || str_eq(&key, "external"))
  1060. bencode_list_add_str(ng_flags->direction, &key);
  1061. else if (str_eq(&key, "RTP/AVPF"))
  1062. ng_flags->transport = 0x102;
  1063. else if (str_eq(&key, "RTP/SAVP"))
  1064. ng_flags->transport = 0x101;
  1065. else
  1066. goto generic;
  1067. goto next;
  1068. break;
  1069. case 9:
  1070. if (str_eq(&key, "RTP/SAVPF"))
  1071. ng_flags->transport = 0x103;
  1072. else if (str_eq(&key, "direction"))
  1073. bencode_list_add_str(ng_flags->direction, &val);
  1074. else
  1075. goto generic;
  1076. goto next;
  1077. break;
  1078. case 10:
  1079. if (str_eq(&key, "via-branch")) {
  1080. err = "missing value";
  1081. if (!val.s)
  1082. goto error;
  1083. err = "invalid value";
  1084. if (*val.s == '1' || *val.s == '2')
  1085. ng_flags->via = *val.s - '0';
  1086. else if (str_eq(&val, "auto"))
  1087. ng_flags->via = 3;
  1088. else if (str_eq(&val, "extra"))
  1089. ng_flags->via = -1;
  1090. else
  1091. goto error;
  1092. goto next;
  1093. }
  1094. break;
  1095. case 11:
  1096. if (str_eq(&key, "repacketize")) {
  1097. err = "missing value";
  1098. if (!val.s)
  1099. goto error;
  1100. ng_flags->packetize = 0;
  1101. while (isdigit(*val.s)) {
  1102. ng_flags->packetize *= 10;
  1103. ng_flags->packetize += *val.s - '0';
  1104. val.s++;
  1105. }
  1106. err = "invalid value";
  1107. if (!ng_flags->packetize)
  1108. goto error;
  1109. bencode_dictionary_add_integer(ng_flags->dict, "repacketize", ng_flags->packetize);
  1110. goto next;
  1111. }
  1112. break;
  1113. case 12:
  1114. if (str_eq(&key, "force-answer")) {
  1115. err = "cannot force answer in non-offer command";
  1116. if (*op != OP_OFFER)
  1117. goto error;
  1118. *op = OP_ANSWER;
  1119. goto next;
  1120. }
  1121. break;
  1122. }
  1123. generic:
  1124. if (!val.s)
  1125. bencode_list_add_str(ng_flags->flags, &key);
  1126. else
  1127. bencode_dictionary_str_add_str(ng_flags->dict, &key, &val);
  1128. goto next;
  1129. next:
  1130. flags_str = e;
  1131. }
  1132. return 0;
  1133. error:
  1134. if (val.s)
  1135. LM_ERR("error processing flag `%.*s' (value '%.*s'): %s\n", key.len, key.s,
  1136. val.len, val.s, err);
  1137. else
  1138. LM_ERR("error processing flag `%.*s': %s\n", key.len, key.s, err);
  1139. return -1;
  1140. }
  1141. static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_msg *msg,
  1142. enum rtpe_operation op, const char *flags_str, str *body_out)
  1143. {
  1144. struct ng_flags_parse ng_flags;
  1145. bencode_item_t *item, *resp;
  1146. str callid, from_tag, to_tag, body, viabranch, error;
  1147. int ret;
  1148. struct rtpp_node *node;
  1149. char *cp;
  1150. /*** get & init basic stuff needed ***/
  1151. memset(&ng_flags, 0, sizeof(ng_flags));
  1152. if (get_callid(msg, &callid) == -1 || callid.len == 0) {
  1153. LM_ERR("can't get Call-Id field\n");
  1154. return NULL;
  1155. }
  1156. if (get_to_tag(msg, &to_tag) == -1) {
  1157. LM_ERR("can't get To tag\n");
  1158. return NULL;
  1159. }
  1160. if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
  1161. LM_ERR("can't get From tag\n");
  1162. return NULL;
  1163. }
  1164. if (bencode_buffer_init(bencbuf)) {
  1165. LM_ERR("could not initialize bencode_buffer_t\n");
  1166. return NULL;
  1167. }
  1168. ng_flags.dict = bencode_dictionary(bencbuf);
  1169. body.s = NULL;
  1170. if (op == OP_OFFER || op == OP_ANSWER) {
  1171. ng_flags.flags = bencode_list(bencbuf);
  1172. ng_flags.direction = bencode_list(bencbuf);
  1173. ng_flags.replace = bencode_list(bencbuf);
  1174. ng_flags.rtcp_mux = bencode_list(bencbuf);
  1175. if (extract_body(msg, &body) == -1) {
  1176. LM_ERR("can't extract body from the message\n");
  1177. goto error;
  1178. }
  1179. if (body_intermediate.s)
  1180. bencode_dictionary_add_str(ng_flags.dict, "sdp", &body_intermediate);
  1181. else
  1182. bencode_dictionary_add_str(ng_flags.dict, "sdp", &body);
  1183. }
  1184. /*** parse flags & build dictionary ***/
  1185. ng_flags.to = (op == OP_DELETE) ? 0 : 1;
  1186. if (parse_flags(&ng_flags, msg, &op, flags_str))
  1187. goto error;
  1188. /* only add those if any flags were given at all */
  1189. if (ng_flags.direction && ng_flags.direction->child)
  1190. bencode_dictionary_add(ng_flags.dict, "direction", ng_flags.direction);
  1191. if (ng_flags.flags && ng_flags.flags->child)
  1192. bencode_dictionary_add(ng_flags.dict, "flags", ng_flags.flags);
  1193. if (ng_flags.replace && ng_flags.replace->child)
  1194. bencode_dictionary_add(ng_flags.dict, "replace", ng_flags.replace);
  1195. if ((ng_flags.transport & 0x100))
  1196. bencode_dictionary_add_string(ng_flags.dict, "transport-protocol",
  1197. transports[ng_flags.transport & 0x003]);
  1198. if (ng_flags.rtcp_mux && ng_flags.rtcp_mux->child)
  1199. bencode_dictionary_add(ng_flags.dict, "rtcp-mux", ng_flags.rtcp_mux);
  1200. bencode_dictionary_add_str(ng_flags.dict, "call-id", &callid);
  1201. if (ng_flags.via) {
  1202. if (ng_flags.via == 1 || ng_flags.via == 2)
  1203. ret = get_via_branch(msg, ng_flags.via, &viabranch);
  1204. else if (ng_flags.via == -1 && extra_id_pv)
  1205. ret = get_extra_id(msg, &viabranch);
  1206. else
  1207. ret = -1;
  1208. if (ret == -1 || viabranch.len == 0) {
  1209. LM_ERR("can't get Via branch/extra ID\n");
  1210. goto error;
  1211. }
  1212. bencode_dictionary_add_str(ng_flags.dict, "via-branch", &viabranch);
  1213. }
  1214. item = bencode_list(bencbuf);
  1215. bencode_dictionary_add(ng_flags.dict, "received-from", item);
  1216. bencode_list_add_string(item, (msg->rcv.src_ip.af == AF_INET) ? "IP4" : (
  1217. (msg->rcv.src_ip.af == AF_INET6) ? "IP6" :
  1218. "?"
  1219. ) );
  1220. bencode_list_add_string(item, ip_addr2a(&msg->rcv.src_ip));
  1221. if ((msg->first_line.type == SIP_REQUEST && op != OP_ANSWER)
  1222. || (msg->first_line.type == SIP_REPLY && op == OP_ANSWER))
  1223. {
  1224. bencode_dictionary_add_str(ng_flags.dict, "from-tag", &from_tag);
  1225. if (ng_flags.to && to_tag.s && to_tag.len)
  1226. bencode_dictionary_add_str(ng_flags.dict, "to-tag", &to_tag);
  1227. }
  1228. else {
  1229. if (!to_tag.s || !to_tag.len) {
  1230. LM_ERR("No to-tag present\n");
  1231. goto error;
  1232. }
  1233. bencode_dictionary_add_str(ng_flags.dict, "from-tag", &to_tag);
  1234. bencode_dictionary_add_str(ng_flags.dict, "to-tag", &from_tag);
  1235. }
  1236. bencode_dictionary_add_string(ng_flags.dict, "command", command_strings[op]);
  1237. /*** send it out ***/
  1238. if (bencbuf->error) {
  1239. LM_ERR("out of memory - bencode failed\n");
  1240. goto error;
  1241. }
  1242. if(msg->id != current_msg_id)
  1243. active_rtpp_set = default_rtpp_set;
  1244. do {
  1245. node = select_rtpp_node(callid, 1);
  1246. if (!node) {
  1247. LM_ERR("no available proxies\n");
  1248. goto error;
  1249. }
  1250. cp = send_rtpp_command(node, ng_flags.dict, &ret);
  1251. } while (cp == NULL);
  1252. LM_DBG("proxy reply: %.*s\n", ret, cp);
  1253. /*** process reply ***/
  1254. resp = bencode_decode_expect(bencbuf, cp, ret, BENCODE_DICTIONARY);
  1255. if (!resp) {
  1256. LM_ERR("failed to decode bencoded reply from proxy: %.*s\n", ret, cp);
  1257. goto error;
  1258. }
  1259. if (!bencode_dictionary_get_strcmp(resp, "result", "error")) {
  1260. if (!bencode_dictionary_get_str(resp, "error-reason", &error))
  1261. LM_ERR("proxy return error but didn't give an error reason: %.*s\n", ret, cp);
  1262. else
  1263. LM_ERR("proxy replied with error: %.*s\n", error.len, error.s);
  1264. goto error;
  1265. }
  1266. if (body_out)
  1267. *body_out = body;
  1268. return resp;
  1269. error:
  1270. bencode_buffer_free(bencbuf);
  1271. return NULL;
  1272. }
  1273. static int rtpp_function_call_simple(struct sip_msg *msg, enum rtpe_operation op, const char *flags_str)
  1274. {
  1275. bencode_buffer_t bencbuf;
  1276. if (!rtpp_function_call(&bencbuf, msg, op, flags_str, NULL))
  1277. return -1;
  1278. bencode_buffer_free(&bencbuf);
  1279. return 1;
  1280. }
  1281. static bencode_item_t *rtpp_function_call_ok(bencode_buffer_t *bencbuf, struct sip_msg *msg,
  1282. enum rtpe_operation op, const char *flags_str, str *body)
  1283. {
  1284. bencode_item_t *ret;
  1285. ret = rtpp_function_call(bencbuf, msg, op, flags_str, body);
  1286. if (!ret)
  1287. return NULL;
  1288. if (bencode_dictionary_get_strcmp(ret, "result", "ok")) {
  1289. LM_ERR("proxy didn't return \"ok\" result\n");
  1290. bencode_buffer_free(bencbuf);
  1291. return NULL;
  1292. }
  1293. return ret;
  1294. }
  1295. static int
  1296. rtpp_test(struct rtpp_node *node, int isdisabled, int force)
  1297. {
  1298. bencode_buffer_t bencbuf;
  1299. bencode_item_t *dict;
  1300. char *cp;
  1301. int ret;
  1302. if(node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS){
  1303. LM_DBG("rtpp %s disabled for ever\n", node->rn_url.s);
  1304. return 1;
  1305. }
  1306. if (force == 0) {
  1307. if (isdisabled == 0)
  1308. return 0;
  1309. if (node->rn_recheck_ticks > get_ticks())
  1310. return 1;
  1311. }
  1312. if (bencode_buffer_init(&bencbuf)) {
  1313. LM_ERR("could not initialized bencode_buffer_t\n");
  1314. return 1;
  1315. }
  1316. dict = bencode_dictionary(&bencbuf);
  1317. bencode_dictionary_add_string(dict, "command", "ping");
  1318. if (bencbuf.error)
  1319. goto benc_error;
  1320. cp = send_rtpp_command(node, dict, &ret);
  1321. if (!cp) {
  1322. LM_ERR("proxy did not respond to ping\n");
  1323. goto error;
  1324. }
  1325. dict = bencode_decode_expect(&bencbuf, cp, ret, BENCODE_DICTIONARY);
  1326. if (!dict || bencode_dictionary_get_strcmp(dict, "result", "pong")) {
  1327. LM_ERR("proxy responded with invalid response\n");
  1328. goto error;
  1329. }
  1330. LM_INFO("rtp proxy <%s> found, support for it %senabled\n",
  1331. node->rn_url.s, force == 0 ? "re-" : "");
  1332. bencode_buffer_free(&bencbuf);
  1333. return 0;
  1334. benc_error:
  1335. LM_ERR("out of memory - bencode failed\n");
  1336. error:
  1337. bencode_buffer_free(&bencbuf);
  1338. return 1;
  1339. }
  1340. static char *
  1341. send_rtpp_command(struct rtpp_node *node, bencode_item_t *dict, int *outlen)
  1342. {
  1343. struct sockaddr_un addr;
  1344. int fd, len, i, vcnt;
  1345. char *cp;
  1346. static char buf[0x10000];
  1347. struct pollfd fds[1];
  1348. struct iovec *v;
  1349. v = bencode_iovec(dict, &vcnt, 1, 0);
  1350. if (!v) {
  1351. LM_ERR("error converting bencode to iovec\n");
  1352. return NULL;
  1353. }
  1354. len = 0;
  1355. cp = buf;
  1356. if (node->rn_umode == 0) {
  1357. memset(&addr, 0, sizeof(addr));
  1358. addr.sun_family = AF_LOCAL;
  1359. strncpy(addr.sun_path, node->rn_address,
  1360. sizeof(addr.sun_path) - 1);
  1361. #ifdef HAVE_SOCKADDR_SA_LEN
  1362. addr.sun_len = strlen(addr.sun_path);
  1363. #endif
  1364. fd = socket(AF_LOCAL, SOCK_STREAM, 0);
  1365. if (fd < 0) {
  1366. LM_ERR("can't create socket\n");
  1367. goto badproxy;
  1368. }
  1369. if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  1370. close(fd);
  1371. LM_ERR("can't connect to RTP proxy\n");
  1372. goto badproxy;
  1373. }
  1374. do {
  1375. len = writev(fd, v + 1, vcnt);
  1376. } while (len == -1 && errno == EINTR);
  1377. if (len <= 0) {
  1378. close(fd);
  1379. LM_ERR("can't send command to a RTP proxy\n");
  1380. goto badproxy;
  1381. }
  1382. do {
  1383. len = read(fd, buf, sizeof(buf) - 1);
  1384. } while (len == -1 && errno == EINTR);
  1385. close(fd);
  1386. if (len <= 0) {
  1387. LM_ERR("can't read reply from a RTP proxy\n");
  1388. goto badproxy;
  1389. }
  1390. } else {
  1391. fds[0].fd = rtpp_socks[node->idx];
  1392. fds[0].events = POLLIN;
  1393. fds[0].revents = 0;
  1394. /* Drain input buffer */
  1395. while ((poll(fds, 1, 0) == 1) &&
  1396. ((fds[0].revents & POLLIN) != 0)) {
  1397. recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
  1398. fds[0].revents = 0;
  1399. }
  1400. v[0].iov_base = gencookie();
  1401. v[0].iov_len = strlen(v[0].iov_base);
  1402. for (i = 0; i < rtpengine_retr; i++) {
  1403. do {
  1404. len = writev(rtpp_socks[node->idx], v, vcnt + 1);
  1405. } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
  1406. if (len <= 0) {
  1407. LM_ERR("can't send command to a RTP proxy\n");
  1408. goto badproxy;
  1409. }
  1410. while ((poll(fds, 1, rtpengine_tout * 1000) == 1) &&
  1411. (fds[0].revents & POLLIN) != 0) {
  1412. do {
  1413. len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
  1414. } while (len == -1 && errno == EINTR);
  1415. if (len <= 0) {
  1416. LM_ERR("can't read reply from a RTP proxy\n");
  1417. goto badproxy;
  1418. }
  1419. if (len >= (v[0].iov_len - 1) &&
  1420. memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
  1421. len -= (v[0].iov_len - 1);
  1422. cp += (v[0].iov_len - 1);
  1423. if (len != 0) {
  1424. len--;
  1425. cp++;
  1426. }
  1427. goto out;
  1428. }
  1429. fds[0].revents = 0;
  1430. }
  1431. }
  1432. if (i == rtpengine_retr) {
  1433. LM_ERR("timeout waiting reply from a RTP proxy\n");
  1434. goto badproxy;
  1435. }
  1436. }
  1437. out:
  1438. cp[len] = '\0';
  1439. *outlen = len;
  1440. return cp;
  1441. badproxy:
  1442. LM_ERR("proxy <%s> does not respond, disable it\n", node->rn_url.s);
  1443. node->rn_disabled = 1;
  1444. node->rn_recheck_ticks = get_ticks() + rtpengine_disable_tout;
  1445. return NULL;
  1446. }
  1447. /*
  1448. * select the set with the id_set id
  1449. */
  1450. static struct rtpp_set * select_rtpp_set(int id_set ){
  1451. struct rtpp_set * rtpp_list;
  1452. /*is it a valid set_id?*/
  1453. if(!rtpp_set_list || !rtpp_set_list->rset_first){
  1454. LM_ERR("no rtp_proxy configured\n");
  1455. return 0;
  1456. }
  1457. for(rtpp_list=rtpp_set_list->rset_first; rtpp_list!=0 &&
  1458. rtpp_list->id_set!=id_set; rtpp_list=rtpp_list->rset_next);
  1459. if(!rtpp_list){
  1460. LM_ERR(" script error-invalid id_set to be selected\n");
  1461. }
  1462. return rtpp_list;
  1463. }
  1464. /*
  1465. * Main balancing routine. This does not try to keep the same proxy for
  1466. * the call if some proxies were disabled or enabled; proxy death considered
  1467. * too rare. Otherwise we should implement "mature" HA clustering, which is
  1468. * too expensive here.
  1469. */
  1470. static struct rtpp_node *
  1471. select_rtpp_node(str callid, int do_test)
  1472. {
  1473. unsigned sum, sumcut, weight_sum;
  1474. struct rtpp_node* node;
  1475. int was_forced;
  1476. if(!active_rtpp_set){
  1477. LM_ERR("script error -no valid set selected\n");
  1478. return NULL;
  1479. }
  1480. /* Most popular case: 1 proxy, nothing to calculate */
  1481. if (active_rtpp_set->rtpp_node_count == 1) {
  1482. node = active_rtpp_set->rn_first;
  1483. if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks())
  1484. node->rn_disabled = rtpp_test(node, 1, 0);
  1485. return node->rn_disabled ? NULL : node;
  1486. }
  1487. /* XXX Use quick-and-dirty hashing algo */
  1488. for(sum = 0; callid.len > 0; callid.len--)
  1489. sum += callid.s[callid.len - 1];
  1490. sum &= 0xff;
  1491. was_forced = 0;
  1492. retry:
  1493. weight_sum = 0;
  1494. for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
  1495. if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){
  1496. /* Try to enable if it's time to try. */
  1497. node->rn_disabled = rtpp_test(node, 1, 0);
  1498. }
  1499. if (!node->rn_disabled)
  1500. weight_sum += node->rn_weight;
  1501. }
  1502. if (weight_sum == 0) {
  1503. /* No proxies? Force all to be redetected, if not yet */
  1504. if (was_forced)
  1505. return NULL;
  1506. was_forced = 1;
  1507. for(node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
  1508. node->rn_disabled = rtpp_test(node, 1, 1);
  1509. }
  1510. goto retry;
  1511. }
  1512. sumcut = sum % weight_sum;
  1513. /*
  1514. * sumcut here lays from 0 to weight_sum-1.
  1515. * Scan proxy list and decrease until appropriate proxy is found.
  1516. */
  1517. for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
  1518. if (node->rn_disabled)
  1519. continue;
  1520. if (sumcut < node->rn_weight)
  1521. goto found;
  1522. sumcut -= node->rn_weight;
  1523. }
  1524. /* No node list */
  1525. return NULL;
  1526. found:
  1527. if (do_test) {
  1528. node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
  1529. if (node->rn_disabled)
  1530. goto retry;
  1531. }
  1532. return node;
  1533. }
  1534. static int
  1535. get_extra_id(struct sip_msg* msg, str *id_str) {
  1536. if(msg==NULL || extra_id_pv==NULL || id_str==NULL) {
  1537. LM_ERR("bad parameters\n");
  1538. return -1;
  1539. }
  1540. if (pv_printf_s(msg, extra_id_pv, id_str)<0) {
  1541. LM_ERR("cannot print the additional id\n");
  1542. return -1;
  1543. }
  1544. return 1;
  1545. }
  1546. static int
  1547. set_rtpengine_set_from_avp(struct sip_msg *msg, int direction)
  1548. {
  1549. struct usr_avp *avp;
  1550. int_str setid_val;
  1551. if ((setid_avp_param == NULL) ||
  1552. (avp = search_first_avp(setid_avp_type, setid_avp, &setid_val, 0))
  1553. == NULL)
  1554. {
  1555. if (direction == 1 || !selected_rtpp_set_2)
  1556. active_rtpp_set = selected_rtpp_set_1;
  1557. else
  1558. active_rtpp_set = selected_rtpp_set_2;
  1559. return 1;
  1560. }
  1561. if (avp->flags&AVP_VAL_STR) {
  1562. LM_ERR("setid_avp must hold an integer value\n");
  1563. return -1;
  1564. }
  1565. active_rtpp_set = select_rtpp_set(setid_val.n);
  1566. if(active_rtpp_set == NULL) {
  1567. LM_ERR("could not locate rtpproxy set %d\n", setid_val.n);
  1568. return -1;
  1569. }
  1570. LM_DBG("using rtpengine set %d\n", setid_val.n);
  1571. current_msg_id = msg->id;
  1572. return 1;
  1573. }
  1574. static int rtpengine_delete(struct sip_msg *msg, const char *flags) {
  1575. return rtpp_function_call_simple(msg, OP_DELETE, flags);
  1576. }
  1577. static int rtpengine_rtpp_set_wrap(struct sip_msg *msg, int (*func)(struct sip_msg *msg, void *, int),
  1578. void *data, int direction)
  1579. {
  1580. int ret, more;
  1581. body_intermediate.s = NULL;
  1582. if (set_rtpengine_set_from_avp(msg, direction) == -1)
  1583. return -1;
  1584. more = 1;
  1585. if (!selected_rtpp_set_2 || selected_rtpp_set_2 == selected_rtpp_set_1)
  1586. more = 0;
  1587. ret = func(msg, data, more);
  1588. if (ret < 0)
  1589. return ret;
  1590. if (!more)
  1591. return ret;
  1592. direction = (direction == 1) ? 2 : 1;
  1593. if (set_rtpengine_set_from_avp(msg, direction) == -1)
  1594. return -1;
  1595. ret = func(msg, data, 0);
  1596. body_intermediate.s = NULL;
  1597. return ret;
  1598. }
  1599. static int rtpengine_delete_wrap(struct sip_msg *msg, void *d, int more) {
  1600. return rtpengine_delete(msg, d);
  1601. }
  1602. static int
  1603. rtpengine_delete1_f(struct sip_msg* msg, char* str1, char* str2)
  1604. {
  1605. str flags;
  1606. flags.s = NULL;
  1607. if (str1)
  1608. get_str_fparam(&flags, msg, (fparam_t *) str1);
  1609. return rtpengine_rtpp_set_wrap(msg, rtpengine_delete_wrap, flags.s, 1);
  1610. }
  1611. /* This function assumes p points to a line of requested type. */
  1612. static int
  1613. set_rtpengine_set_n(struct sip_msg *msg, rtpp_set_link_t *rtpl, struct rtpp_set **out)
  1614. {
  1615. pv_value_t val;
  1616. struct rtpp_node *node;
  1617. int nb_active_nodes = 0;
  1618. if(rtpl->rset != NULL) {
  1619. current_msg_id = msg->id;
  1620. *out = rtpl->rset;
  1621. return 1;
  1622. }
  1623. if(pv_get_spec_value(msg, rtpl->rpv, &val)<0) {
  1624. LM_ERR("cannot evaluate pv param\n");
  1625. return -1;
  1626. }
  1627. if(!(val.flags & PV_VAL_INT)) {
  1628. LM_ERR("pv param must hold an integer value\n");
  1629. return -1;
  1630. }
  1631. *out = select_rtpp_set(val.ri);
  1632. if(*out==NULL) {
  1633. LM_ERR("could not locate rtpengine set %d\n", val.ri);
  1634. return -1;
  1635. }
  1636. current_msg_id = msg->id;
  1637. node = (*out)->rn_first;
  1638. while (node != NULL)
  1639. {
  1640. if (node->rn_disabled == 0) nb_active_nodes++;
  1641. node = node->rn_next;
  1642. }
  1643. if ( nb_active_nodes > 0 )
  1644. {
  1645. LM_DBG("rtpp: selected proxy set ID %d with %d active nodes.\n",
  1646. current_msg_id, nb_active_nodes);
  1647. return nb_active_nodes;
  1648. }
  1649. else
  1650. {
  1651. LM_WARN("rtpp: selected proxy set ID %d but it has no active node.\n",
  1652. current_msg_id);
  1653. return -2;
  1654. }
  1655. }
  1656. static int
  1657. set_rtpengine_set_f(struct sip_msg * msg, char * str1, char * str2)
  1658. {
  1659. rtpp_set_link_t *rtpl1, *rtpl2;
  1660. int ret;
  1661. rtpl1 = (rtpp_set_link_t*)str1;
  1662. rtpl2 = (rtpp_set_link_t*)str2;
  1663. current_msg_id = 0;
  1664. active_rtpp_set = 0;
  1665. selected_rtpp_set_1 = 0;
  1666. selected_rtpp_set_2 = 0;
  1667. ret = set_rtpengine_set_n(msg, rtpl1, &selected_rtpp_set_1);
  1668. if (ret < 0)
  1669. return ret;
  1670. if (rtpl2) {
  1671. ret = set_rtpengine_set_n(msg, rtpl2, &selected_rtpp_set_2);
  1672. if (ret < 0)
  1673. return ret;
  1674. }
  1675. return 1;
  1676. }
  1677. static int
  1678. rtpengine_manage(struct sip_msg *msg, const char *flags)
  1679. {
  1680. int method;
  1681. int nosdp;
  1682. if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
  1683. || (msg->cseq==NULL)))
  1684. {
  1685. LM_ERR("no CSEQ header\n");
  1686. return -1;
  1687. }
  1688. method = get_cseq(msg)->method_id;
  1689. if(!(method==METHOD_INVITE || method==METHOD_ACK || method==METHOD_CANCEL
  1690. || method==METHOD_BYE || method==METHOD_UPDATE))
  1691. return -1;
  1692. if(method==METHOD_CANCEL || method==METHOD_BYE)
  1693. return rtpengine_delete(msg, flags);
  1694. if(msg->msg_flags & FL_SDP_BODY)
  1695. nosdp = 0;
  1696. else
  1697. nosdp = parse_sdp(msg);
  1698. if(msg->first_line.type == SIP_REQUEST) {
  1699. if(method==METHOD_ACK && nosdp==0)
  1700. return rtpengine_offer_answer(msg, flags, OP_ANSWER, 0);
  1701. if(method==METHOD_UPDATE && nosdp==0)
  1702. return rtpengine_offer_answer(msg, flags, OP_OFFER, 0);
  1703. if(method==METHOD_INVITE && nosdp==0) {
  1704. msg->msg_flags |= FL_SDP_BODY;
  1705. if(tmb.t_gett!=NULL && tmb.t_gett()!=NULL
  1706. && tmb.t_gett()!=T_UNDEFINED)
  1707. tmb.t_gett()->uas.request->msg_flags |= FL_SDP_BODY;
  1708. if(route_type==FAILURE_ROUTE)
  1709. return rtpengine_delete(msg, flags);
  1710. return rtpengine_offer_answer(msg, flags, OP_OFFER, 0);
  1711. }
  1712. } else if(msg->first_line.type == SIP_REPLY) {
  1713. if(msg->first_line.u.reply.statuscode>=300)
  1714. return rtpengine_delete(msg, flags);
  1715. if(nosdp==0) {
  1716. if(method==METHOD_UPDATE)
  1717. return rtpengine_offer_answer(msg, flags, OP_ANSWER, 0);
  1718. if(tmb.t_gett==NULL || tmb.t_gett()==NULL
  1719. || tmb.t_gett()==T_UNDEFINED)
  1720. return rtpengine_offer_answer(msg, flags, OP_ANSWER, 0);
  1721. if(tmb.t_gett()->uas.request->msg_flags & FL_SDP_BODY)
  1722. return rtpengine_offer_answer(msg, flags, OP_ANSWER, 0);
  1723. return rtpengine_offer_answer(msg, flags, OP_OFFER, 0);
  1724. }
  1725. }
  1726. return -1;
  1727. }
  1728. static int rtpengine_manage_wrap(struct sip_msg *msg, void *d, int more) {
  1729. return rtpengine_manage(msg, d);
  1730. }
  1731. static int
  1732. rtpengine_manage1_f(struct sip_msg *msg, char *str1, char *str2)
  1733. {
  1734. str flags;
  1735. flags.s = NULL;
  1736. if (str1)
  1737. get_str_fparam(&flags, msg, (fparam_t *) str1);
  1738. return rtpengine_rtpp_set_wrap(msg, rtpengine_manage_wrap, flags.s, 1);
  1739. }
  1740. static int rtpengine_offer_wrap(struct sip_msg *msg, void *d, int more) {
  1741. return rtpengine_offer_answer(msg, d, OP_OFFER, more);
  1742. }
  1743. static int
  1744. rtpengine_offer1_f(struct sip_msg *msg, char *str1, char *str2)
  1745. {
  1746. str flags;
  1747. flags.s = NULL;
  1748. if (str1)
  1749. get_str_fparam(&flags, msg, (fparam_t *) str1);
  1750. return rtpengine_rtpp_set_wrap(msg, rtpengine_offer_wrap, flags.s, 1);
  1751. }
  1752. static int rtpengine_answer_wrap(struct sip_msg *msg, void *d, int more) {
  1753. return rtpengine_offer_answer(msg, d, OP_ANSWER, more);
  1754. }
  1755. static int
  1756. rtpengine_answer1_f(struct sip_msg *msg, char *str1, char *str2)
  1757. {
  1758. str flags;
  1759. if (msg->first_line.type == SIP_REQUEST)
  1760. if (msg->first_line.u.request.method_value != METHOD_ACK)
  1761. return -1;
  1762. flags.s = NULL;
  1763. if (str1)
  1764. get_str_fparam(&flags, msg, (fparam_t *) str1);
  1765. return rtpengine_rtpp_set_wrap(msg, rtpengine_answer_wrap, flags.s, 2);
  1766. }
  1767. static int
  1768. rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op, int more)
  1769. {
  1770. bencode_buffer_t bencbuf;
  1771. bencode_item_t *dict;
  1772. str body, newbody;
  1773. struct lump *anchor;
  1774. dict = rtpp_function_call_ok(&bencbuf, msg, op, flags, &body);
  1775. if (!dict)
  1776. return -1;
  1777. if (!bencode_dictionary_get_str_dup(dict, "sdp", &newbody)) {
  1778. LM_ERR("failed to extract sdp body from proxy reply\n");
  1779. goto error;
  1780. }
  1781. if (body_intermediate.s)
  1782. pkg_free(body_intermediate.s);
  1783. if (more)
  1784. body_intermediate = newbody;
  1785. else {
  1786. anchor = del_lump(msg, body.s - msg->buf, body.len, 0);
  1787. if (!anchor) {
  1788. LM_ERR("del_lump failed\n");
  1789. goto error_free;
  1790. }
  1791. if (!insert_new_lump_after(anchor, newbody.s, newbody.len, 0)) {
  1792. LM_ERR("insert_new_lump_after failed\n");
  1793. goto error_free;
  1794. }
  1795. }
  1796. bencode_buffer_free(&bencbuf);
  1797. return 1;
  1798. error_free:
  1799. pkg_free(newbody.s);
  1800. error:
  1801. bencode_buffer_free(&bencbuf);
  1802. return -1;
  1803. }
  1804. static int rtpengine_start_recording_wrap(struct sip_msg *msg, void *d, int more) {
  1805. return rtpp_function_call_simple(msg, OP_START_RECORDING, NULL);
  1806. }
  1807. static int
  1808. start_recording_f(struct sip_msg* msg, char *foo, char *bar)
  1809. {
  1810. return rtpengine_rtpp_set_wrap(msg, rtpengine_start_recording_wrap, NULL, 1);
  1811. }
  1812. /*
  1813. * Returns the current RTP-Statistics from the RTP-Proxy
  1814. */
  1815. static int
  1816. pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param,
  1817. pv_value_t *res)
  1818. {
  1819. bencode_buffer_t bencbuf;
  1820. bencode_item_t *dict, *tot, *in, *out;
  1821. static char buf[256];
  1822. str ret;
  1823. dict = rtpp_function_call_ok(&bencbuf, msg, OP_QUERY, NULL, NULL);
  1824. if (!dict)
  1825. return -1;
  1826. tot = bencode_dictionary_get_expect(dict, "totals", BENCODE_DICTIONARY);
  1827. in = bencode_dictionary_get_expect(tot, "input", BENCODE_DICTIONARY);
  1828. in = bencode_dictionary_get_expect(in, "rtp", BENCODE_DICTIONARY);
  1829. out = bencode_dictionary_get_expect(tot, "output", BENCODE_DICTIONARY);
  1830. out = bencode_dictionary_get_expect(out, "rtp", BENCODE_DICTIONARY);
  1831. if (!in || !out)
  1832. goto error;
  1833. ret.s = buf;
  1834. ret.len = snprintf(buf, sizeof(buf),
  1835. "Input: %lli bytes, %lli packets, %lli errors; "
  1836. "Output: %lli bytes, %lli packets, %lli errors",
  1837. bencode_dictionary_get_integer(in, "bytes", -1),
  1838. bencode_dictionary_get_integer(in, "packets", -1),
  1839. bencode_dictionary_get_integer(in, "errors", -1),
  1840. bencode_dictionary_get_integer(out, "bytes", -1),
  1841. bencode_dictionary_get_integer(out, "packets", -1),
  1842. bencode_dictionary_get_integer(out, "errors", -1));
  1843. bencode_buffer_free(&bencbuf);
  1844. return pv_get_strval(msg, param, res, &ret);
  1845. error:
  1846. bencode_buffer_free(&bencbuf);
  1847. return -1;
  1848. }