iptrtpproxy.c 100 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106
  1. /* $Id: iptrtpproxy.c 30494 2010-07-20 15:05:24Z tma $
  2. *
  3. * Copyright (C) 2007 Tomas Mandys
  4. *
  5. * This file is part of ser, a free SIP server.
  6. *
  7. * ser 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. * For a license to use the ser software under conditions
  13. * other than those described here, or to purchase support for this
  14. * software, please contact iptel.org by e-mail at the following addresses:
  15. * [email protected]
  16. *
  17. * ser is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. *
  26. */
  27. // #include <linux/compiler.h> will be needed to define __user macro
  28. #include "../../sr_module.h"
  29. #include "../../dprint.h"
  30. #include "../../data_lump.h"
  31. #include "../../data_lump_rpl.h"
  32. #include "../../error.h"
  33. #include "../../forward.h"
  34. #include "../../mem/mem.h"
  35. #include "../../mem/shm_mem.h"
  36. #include "../../atomic_ops.h"
  37. #include "../../parser/parse_content.h"
  38. #include "../../parser/parse_uri.h"
  39. #include "../../parser/parser_f.h"
  40. #include "../../parser/parse_body.h"
  41. #include "../../resolve.h"
  42. #include "../../trim.h"
  43. #include "../../ut.h"
  44. #include "../../msg_translator.h"
  45. #include "../../socket_info.h"
  46. #include "../../select.h"
  47. #include "../../select_buf.h"
  48. #include "../../script_cb.h"
  49. #include "../../cfg_parser.h"
  50. #include "../../rand/kam_rand.h"
  51. #include <sys/types.h>
  52. #include <sys/socket.h>
  53. #include <sys/time.h>
  54. #include <netinet/in.h>
  55. #include <arpa/inet.h>
  56. #include <sys/uio.h>
  57. #include <sys/un.h>
  58. #include <ctype.h>
  59. #include <errno.h>
  60. #include <netdb.h>
  61. #include <poll.h>
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <unistd.h>
  66. #include <linux/netfilter/xt_RTPPROXY.h>
  67. #include <arpa/inet.h>
  68. MODULE_VERSION
  69. #define MODULE_NAME "iptrtpproxy"
  70. /* max.number of RTP streams per session */
  71. #define MAX_MEDIA_NUMBER XT_RTPPROXY_MAX_ALLOC_SESSION
  72. #define MAX_CODEC_NUMBER MAX_MEDIA_NUMBER*5
  73. #define MAX_SWITCHBOARD_NAME_LEN 20
  74. #define MAX_AGGREGATED_NUMBER 30
  75. /* warningless cast at 64-bit */
  76. #define PTR2INT(v) (int)(long) (v)
  77. #define INT2PTR(v) (void*)(long) (v)
  78. struct host_item_stat {
  79. int last_error_stamp;
  80. int last_ok_stamp;
  81. };
  82. struct host_item {
  83. str name;
  84. struct xt_rtpproxy_connection_rpc_params rpc_params;
  85. int local;
  86. struct xt_rtpproxy_handle handle;
  87. int handle_is_opened;
  88. struct host_item_stat *stat;
  89. struct host_item *next;
  90. };
  91. struct switchboard_item_stat {
  92. atomic_t free;
  93. atomic_t alloc;
  94. };
  95. struct switchboard_item {
  96. str name;
  97. struct xt_rtpproxy_switchboard_id switchboard_addr;
  98. unsigned int sip_ip;
  99. str hostname;
  100. struct host_item *host;
  101. unsigned int weight;
  102. struct switchboard_item_stat *stat;
  103. struct switchboard_item *next;
  104. };
  105. enum sdp_media_type {
  106. sdpmtUnknown = 0,
  107. sdpmtAudio,
  108. sdpmtVideo,
  109. sdpmtApplication,
  110. sdpmtText,
  111. sdpmtMessage,
  112. sdpmtData, /* not recommended in RFC4566 */
  113. sdpmtControl /* dtto */
  114. };
  115. #define NUM_MEDIA_TYPES (sdpmtControl+1)
  116. static str sdp_media_types_str[NUM_MEDIA_TYPES] = {
  117. STR_STATIC_INIT("unknown"),
  118. STR_STATIC_INIT("audio"),
  119. STR_STATIC_INIT("video"),
  120. STR_STATIC_INIT("application"),
  121. STR_STATIC_INIT("text"),
  122. STR_STATIC_INIT("message"),
  123. STR_STATIC_INIT("data"),
  124. STR_STATIC_INIT("control")
  125. };
  126. struct aggregation_item {
  127. str name;
  128. unsigned int switchboard_count;
  129. unsigned int sip_ip;
  130. struct switchboard_item *(*switchboards)[];
  131. struct aggregation_item *next;
  132. };
  133. struct codec_set_item_throttle {
  134. int max_streams;
  135. struct xt_rtpproxy_throttle_stat bandwidth[2]; /* RTP, RTCP */
  136. };
  137. struct codec_set_item {
  138. str name;
  139. struct {
  140. struct codec_set_item_throttle throttle;
  141. unsigned int (*codec_rights)[];
  142. } media_types[NUM_MEDIA_TYPES];
  143. struct codec_set_item *next;
  144. };
  145. struct ipt_session {
  146. unsigned int session_count;
  147. struct xt_rtpproxy_sockopt_session sessions[MAX_MEDIA_NUMBER];
  148. unsigned int sdp_media_count;
  149. int sdp_media[MAX_MEDIA_NUMBER];
  150. struct switchboard_item *switchboard;
  151. };
  152. static struct {
  153. str session_ids;
  154. str sdp_ip;
  155. str oline_user;
  156. str oline_addr;
  157. struct switchboard_item *switchboard[2];
  158. struct aggregation_item *aggregation[2];
  159. int learning_timeout;
  160. int expiration_timeout;
  161. int ttl;
  162. int always_learn;
  163. struct {
  164. u_int32_t mark;
  165. struct xt_rtpproxy_throttle_stat bandwidth[2];
  166. } throttle;
  167. struct codec_set_item *codec_set;
  168. int remove_codec_mask;
  169. unsigned int auth_rights;
  170. struct ipt_session protected_sess;
  171. } global_params;
  172. static struct switchboard_item *switchboards = NULL;
  173. static struct host_item *hosts = NULL;
  174. static struct aggregation_item *aggregations = NULL;
  175. static struct codec_set_item *codec_sets = NULL;
  176. static int switchboard_count = 0;
  177. static str iptrtpproxy_cfg_filename = STR_STATIC_INIT("/etc/iptrtpproxy.cfg");
  178. static int iptrtpproxy_cfg_flag = 0;
  179. static char* iptrtpproxy_cfg_hostname = NULL;
  180. static int rpc_heartbeat_timeout = 30;
  181. static int sdp_parsed = 999; /* we need share parsed SDP between authorize_media & alloc/update * get_param */
  182. static struct sdp_session global_sdp_sess;
  183. #define declare_find_function(x) \
  184. static struct x##_item* find_##x(str *name, struct x##_item*** prev) { \
  185. struct x##_item* p;\
  186. struct x##_item** dummy;\
  187. if (!prev) \
  188. prev = &dummy;\
  189. for (p = x##s, *prev = &x##s; p; *prev = &(**prev)->next, p=p->next) {\
  190. int len, n;\
  191. len = (name->len < p->name.len) ? name->len : p->name.len;\
  192. n = strncasecmp(name->s, p->name.s, len);\
  193. if (n == 0) {\
  194. if (name->len == p->name.len) \
  195. return p;\
  196. else if (name->len < p->name.len)\
  197. return NULL;\
  198. }\
  199. else if (n < 0) { \
  200. return NULL;\
  201. }\
  202. }\
  203. return NULL;\
  204. }
  205. declare_find_function(host)
  206. declare_find_function(switchboard)
  207. declare_find_function(aggregation)
  208. declare_find_function(codec_set)
  209. static struct switchboard_item* find_switchboard_by_addr(struct xt_rtpproxy_switchboard_id *addr) {
  210. struct switchboard_item* p;
  211. for (p = switchboards; p; p=p->next) {
  212. if (addr->ip == p->switchboard_addr.ip && addr->port == p->switchboard_addr.port) break;
  213. }
  214. return p;
  215. }
  216. enum {
  217. PAR_EXPIRATION_TIMEOUT,
  218. PAR_TTL,
  219. PAR_LEARNING_TIMEOUT,
  220. PAR_ALWAYS_LEARN,
  221. PAR_AGGREGATION_A, PAR_AGGREGATION_B,
  222. PAR_SWITCHBOARD_A, PAR_SWITCHBOARD_B,
  223. PAR_AGGREGATION_BY_SIP_IP_A, PAR_AGGREGATION_BY_SIP_IP_B,
  224. PAR_SWITCHBOARD_BY_SIP_IP_A, PAR_SWITCHBOARD_BY_SIP_IP_B,
  225. PAR_SESSION_IDS, PAR_PROTECTED_SESSION_IDS,
  226. PAR_SDP_IP, PAR_ACTIVE_MEDIA_NUM,
  227. PAR_OLINE_USER, PAR_OLINE_ADDR,
  228. PAR_THROTTLE_MARK,
  229. PAR_THROTTLE_RTP_MAX_BYTES, PAR_THROTTLE_RTP_MAX_PACKETS,
  230. PAR_THROTTLE_RTCP_MAX_BYTES, PAR_THROTTLE_RTCP_MAX_PACKETS,
  231. PAR_CODEC_SET, PAR_AUTH_RIGHTS, PAR_REMOVE_CODEC_MASK
  232. };
  233. enum {
  234. PAR_READ=0x01, PAR_WRITE=0x02, PAR_INT=0x04, PAR_STR=0x08, PAR_DIR=0x10
  235. };
  236. static struct {
  237. char *name;
  238. int id;
  239. int flags;
  240. } param_list[] = {
  241. {"expiration_timeout", PAR_EXPIRATION_TIMEOUT, PAR_READ|PAR_WRITE|PAR_INT},
  242. {"ttl", PAR_TTL, PAR_READ|PAR_WRITE|PAR_INT},
  243. {"learning_timeout", PAR_LEARNING_TIMEOUT, PAR_READ|PAR_WRITE|PAR_INT},
  244. {"always_learn", PAR_ALWAYS_LEARN, PAR_READ|PAR_WRITE|PAR_INT},
  245. {"aggregation_a", PAR_AGGREGATION_A, PAR_READ|PAR_WRITE|PAR_STR},
  246. {"aggregation_b", PAR_AGGREGATION_B, PAR_READ|PAR_WRITE|PAR_STR|PAR_DIR},
  247. {"switchboard_a", PAR_SWITCHBOARD_A, PAR_READ|PAR_WRITE|PAR_STR},
  248. {"switchboard_b", PAR_SWITCHBOARD_B, PAR_READ|PAR_WRITE|PAR_STR|PAR_DIR},
  249. {"aggregation_by_sip_ip_a", PAR_AGGREGATION_BY_SIP_IP_A, PAR_WRITE|PAR_STR},
  250. {"aggregation_by_sip_ip_b", PAR_AGGREGATION_BY_SIP_IP_B, PAR_WRITE|PAR_STR|PAR_DIR},
  251. {"switchboard_by_sip_ip_a", PAR_SWITCHBOARD_BY_SIP_IP_A, PAR_WRITE|PAR_STR},
  252. {"switchboard_by_sip_ip_b", PAR_SWITCHBOARD_BY_SIP_IP_B, PAR_WRITE|PAR_STR|PAR_DIR},
  253. {"session_ids", PAR_SESSION_IDS, PAR_READ|PAR_STR},
  254. {"protected_session_ids", PAR_PROTECTED_SESSION_IDS, PAR_WRITE|PAR_STR},
  255. {"sdp_ip", PAR_SDP_IP, PAR_READ|PAR_INT},
  256. {"active_media_num", PAR_ACTIVE_MEDIA_NUM, PAR_READ|PAR_INT},
  257. {"o_user", PAR_OLINE_USER, PAR_READ|PAR_WRITE|PAR_STR},
  258. {"o_addr", PAR_OLINE_ADDR, PAR_READ|PAR_WRITE|PAR_STR},
  259. {"throttle_mark", PAR_THROTTLE_MARK, PAR_READ|PAR_WRITE|PAR_INT},
  260. {"throttle_rtp_max_bytes", PAR_THROTTLE_RTP_MAX_BYTES, PAR_READ|PAR_WRITE|PAR_INT},
  261. {"throttle_rtp_max_packets", PAR_THROTTLE_RTP_MAX_PACKETS, PAR_READ|PAR_WRITE|PAR_INT},
  262. {"throttle_rtcp_max_bytes", PAR_THROTTLE_RTCP_MAX_BYTES, PAR_READ|PAR_WRITE|PAR_INT},
  263. {"throttle_rtcp_max_packets", PAR_THROTTLE_RTCP_MAX_PACKETS, PAR_READ|PAR_WRITE|PAR_INT},
  264. {"codec_set", PAR_CODEC_SET, PAR_READ|PAR_WRITE|PAR_STR},
  265. {"remove_codec_mask", PAR_REMOVE_CODEC_MASK, PAR_READ|PAR_WRITE|PAR_INT},
  266. {"auth_rights", PAR_AUTH_RIGHTS, PAR_READ|PAR_INT},
  267. { NULL }
  268. };
  269. static int param2idx(str *name, int rw) {
  270. int i;
  271. for (i=0; param_list[i].name; i++) {
  272. if (strlen(param_list[i].name)==name->len &&
  273. strncasecmp(param_list[i].name, name->s, name->len) == 0 &&
  274. (rw & param_list[i].flags)) {
  275. return i;
  276. }
  277. }
  278. ERR(MODULE_NAME": param2idx: unknown param '%.*s', rw:0x%0x\n", STR_FMT(name), rw);
  279. return -1;
  280. }
  281. /** if succesfull allocated sessions available @rtpproxy.session_ids
  282. */
  283. static int rtpproxy_alloc_update_fixup(void** param, int param_no) {
  284. switch (param_no) {
  285. case 1:
  286. return fixup_var_int_12(param, param_no);
  287. case 2:
  288. return fixup_var_str_12(param, param_no);
  289. default:
  290. return 0;
  291. }
  292. }
  293. static int rtpproxy_delete_fixup(void** param, int param_no) {
  294. switch (param_no) {
  295. case 1:
  296. return fixup_var_str_12(param, param_no);
  297. default:
  298. return 0;
  299. }
  300. }
  301. static int rtpproxy_set_param_fixup(void** param, int param_no) {
  302. int idx;
  303. action_u_t *a;
  304. str s;
  305. switch (param_no) {
  306. case 1:
  307. s.s = (char*)*param;
  308. s.len = strlen(s.s);
  309. idx = param2idx(&s, PAR_WRITE);
  310. if (idx < 0) {
  311. return E_CFG;
  312. }
  313. *param = INT2PTR(idx);
  314. break;
  315. case 2:
  316. a = fixup_get_param(param, param_no, 1);
  317. idx = a->u.number;
  318. if (param_list[idx].flags & PAR_STR) {
  319. return fixup_var_str_12(param, param_no);
  320. } else if (param_list[idx].flags & PAR_INT) {
  321. return fixup_var_int_12(param, param_no);
  322. }
  323. break;
  324. }
  325. return 0;
  326. }
  327. static int name2media_type(str *name) {
  328. int i;
  329. for (i = 1; i<NUM_MEDIA_TYPES; i++) {
  330. if (name->len == sdp_media_types_str[i].len &&
  331. strncasecmp(name->s, sdp_media_types_str[i].s, name->len) == 0) {
  332. return i;
  333. }
  334. }
  335. return sdpmtUnknown;
  336. }
  337. struct codec_entry {
  338. str name;
  339. /* bandwidth */
  340. int payload_type; /* -1 .. dynamic */
  341. };
  342. #define MAX_FIXED_PAYLOAD_TYPES 96
  343. static struct codec_entry(*reg_codecs)[] = NULL;
  344. static int reg_codec_count = 0;
  345. static int reg_codec_alloc_count = 0;
  346. static struct {
  347. int codec_id;
  348. } fixed_payload_types[MAX_FIXED_PAYLOAD_TYPES];
  349. /* unregistered codec .. 0 */
  350. static int name2codec_id(str *name, int *new_codec_id) {
  351. int i, j;
  352. i = 0;
  353. j = reg_codec_count - 1;
  354. while (i <= j) {
  355. int k, r;
  356. k = (i + j)/2;
  357. r = strncasecmp((*reg_codecs)[k].name.s, name->s, ((*reg_codecs)[k].name.len < name->len)?(*reg_codecs)[k].name.len:name->len);
  358. if (r == 0 && (*reg_codecs)[k].name.len == name->len) {
  359. return k+1;
  360. } else if (r > 0 || (r == 0 && (*reg_codecs)[k].name.len > name->len)) {
  361. j = k - 1;
  362. }
  363. else {
  364. i = k + 1;
  365. }
  366. }
  367. if (new_codec_id) {
  368. *new_codec_id = i + 1;
  369. }
  370. return 0;
  371. }
  372. /* return <0 if error, otherwise codec_id */
  373. static int register_codec(str *name) {
  374. int codec_id, new_codec_id = 0;
  375. if (!(codec_id = name2codec_id(name, &new_codec_id))) {
  376. int i;
  377. if (reg_codec_count + 1 > reg_codec_alloc_count) {
  378. void *p;
  379. reg_codec_alloc_count += 10;
  380. p = pkg_realloc(reg_codecs, sizeof((*reg_codecs)[0])*reg_codec_alloc_count);
  381. if (!p) {
  382. return E_OUT_OF_MEM;
  383. }
  384. reg_codecs = p;
  385. }
  386. /* do not count codec_id == 0 (unknown) */
  387. for (i=reg_codec_count-1; i >= new_codec_id-1; i--) {
  388. (*reg_codecs)[i+1] = (*reg_codecs)[i];
  389. }
  390. reg_codec_count++;
  391. (*reg_codecs)[new_codec_id-1].name = *name;
  392. codec_id = new_codec_id;
  393. }
  394. return codec_id;
  395. }
  396. enum send_rec_modifier {
  397. sdpaattr_sendonly = 1,
  398. sdpaattr_recvonly = 2,
  399. sdpaattr_sendrecv = 3,
  400. sdpaattr_inactive = 4
  401. };
  402. static str send_rec_modifiers[] = {
  403. STR_STATIC_INIT(""),
  404. STR_STATIC_INIT("sendonly"),
  405. STR_STATIC_INIT("recvonly"),
  406. STR_STATIC_INIT("sendrecv"),
  407. STR_STATIC_INIT("inactive"),
  408. };
  409. struct sdp_codec {
  410. unsigned int payload_type;
  411. unsigned int codec_id;
  412. str mline_payload_type_s;
  413. str a_rtpmap_line_s;
  414. str a_fmtp_line_s;
  415. };
  416. struct sdp_session {
  417. str oline_user_s;
  418. str oline_addr_s;
  419. unsigned int media_count;
  420. struct {
  421. int active; /* if SDP has been parsed correctly, has a IP (even 0.0.0.0), port!=0 and has supported params */
  422. unsigned short port;
  423. unsigned int ip;
  424. str ip_s;
  425. str port_s;
  426. enum sdp_media_type media_type;
  427. enum send_rec_modifier send_rec_modifier;
  428. str send_rec_modifier_line_s;
  429. int codec_count;
  430. struct sdp_codec (*codecs)[];
  431. } media[MAX_MEDIA_NUMBER];
  432. };
  433. static unsigned int s2ip4(str *s) {
  434. struct in_addr res;
  435. char c2;
  436. c2 = s->s[s->len];
  437. s->s[s->len] = '\0';
  438. if (!inet_aton(s->s, &res)) {
  439. s->s[s->len] = c2;
  440. return 0;
  441. }
  442. s->s[s->len] = c2;
  443. return res.s_addr;
  444. }
  445. static void ip42s(unsigned int ip, str *s) {
  446. struct in_addr ip2 = { ip };
  447. s->s = inet_ntoa(ip2);
  448. s->len = strlen(s->s);
  449. }
  450. #define is_alpha(_c) (((_c) >= 'a' && (_c) <= 'z') || ((_c) >= 'A' && (_c) <= 'Z') || ((_c) >= '0' && (_c) <= '9') || ((_c) == '_') || ((_c) == '-'))
  451. inline static int next_sdp_line(char** p, char* pend, char *ltype, str* lvalue, str* line) {
  452. char *cp;
  453. while (*p < pend) {
  454. while (*p < pend && (**p == '\n' || **p == '\r')) (*p)++;
  455. for (cp = *p; cp < pend && *cp != '\n' && *cp != '\r'; cp++);
  456. if (cp-*p > 2 && (*p)[1] == '=') {
  457. *ltype = **p;
  458. lvalue->s = (*p)+2;
  459. lvalue->len = cp-lvalue->s;
  460. while (cp < pend && (*cp == '\n' || *cp == '\r')) cp++;
  461. line->s = (*p);
  462. line->len = cp-line->s;
  463. *p = cp;
  464. return 0;
  465. }
  466. *p = cp;
  467. }
  468. return -1;
  469. };
  470. static int name2enum(str *name, str (*list)[]) {
  471. int i;
  472. for (i = 0; (*list)[i].s != NULL; i++) {
  473. if (name->len == (*list)[i].len &&
  474. strncasecmp(name->s, (*list)[i].s, name->len) == 0) {
  475. return i;
  476. }
  477. }
  478. return -1;
  479. }
  480. static int prefix2enum(str *line, str (*list)[]) {
  481. int i;
  482. for (i = 0; (*list)[i].s != NULL; i++) {
  483. if (line->len > (*list)[i].len &&
  484. strncmp(line->s, (*list)[i].s, (*list)[i].len) == 0) {
  485. return i;
  486. }
  487. }
  488. return -1;
  489. }
  490. /* SDP RFC2327 */
  491. static int parse_sdp_content(struct sip_msg* msg, struct sdp_session *sess) {
  492. char *p, *pend, *cp, *cp2, *lend;
  493. str line, lvalue, cline_ip_s, body;
  494. int sess_fl, i, cline_count, codec_count;
  495. char ltype, savec;
  496. unsigned int cline_ip;
  497. enum send_rec_modifier sess_send_rec_modifier;
  498. static struct sdp_codec codecs[MAX_CODEC_NUMBER];
  499. static str supported_protocols[] = {
  500. STR_STATIC_INIT("rtp/avp"),
  501. STR_STATIC_INIT("rtp/savp"),
  502. STR_STATIC_INIT("rtp/avpf"),
  503. STR_STATIC_INIT("rtp/savpf"),
  504. STR_STATIC_INIT("udp"),
  505. STR_STATIC_INIT("udptl"),
  506. STR_NULL
  507. };
  508. enum a_attr {sdpaattr_rtpmap, sdpaattr_fmtp, sdpaattr_rtcp};
  509. static str a_attrs[] = {
  510. STR_STATIC_INIT("rtpmap:"),
  511. STR_STATIC_INIT("fmtp:"),
  512. STR_STATIC_INIT("rtcp:"),
  513. STR_NULL
  514. };
  515. memset(sess, 0, sizeof(*sess));
  516. /* try to get the body part with application/sdp */
  517. body.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &body.len);
  518. if (!body.s) {
  519. ERR(MODULE_NAME": parse_sdp_content: failed to get the application/sdp body\n");
  520. return -1;
  521. }
  522. #if 0
  523. body.s = get_body(msg);
  524. if (body.s==0) {
  525. ERR(MODULE_NAME": parse_sdp_content: failed to get the message body\n");
  526. return -1;
  527. }
  528. body.len = msg->len -(int)(body.s - msg->buf);
  529. if (body.len==0) {
  530. ERR(MODULE_NAME": parse_sdp_content: message body has length zero\n");
  531. return -1;
  532. }
  533. /* no need for parse_headers(msg, EOH), get_body will parse everything */
  534. if (!msg->content_type)
  535. {
  536. WARN(MODULE_NAME": parse_sdp_content: Content-TYPE header absent!"
  537. "let's assume the content is text/plain\n");
  538. }
  539. else {
  540. trim_len(line.len, line.s, msg->content_type->body);
  541. if (line.len != sizeof("application/sdp")-1 || strncasecmp(line.s, "application/sdp", line.len) != 0) {
  542. ERR(MODULE_NAME": parse_sdp_content: bad content type '%.*s'\n", STR_FMT(&line));
  543. return -1;
  544. }
  545. }
  546. #endif
  547. /*
  548. * Parsing of SDP body.
  549. * It can contain a few session descriptions (each starts with
  550. * v-line), and each session may contain a few media descriptions
  551. * (each starts with m-line).
  552. * We have to change ports in m-lines, and also change IP addresses in
  553. * c-lines which can be placed either in session header (fallback for
  554. * all medias) or media description.
  555. * Ports should be allocated for any media. IPs all should be changed
  556. * to the same value (RTP proxy IP), so we can change all c-lines
  557. * unconditionally.
  558. * There are sendonly,recvonly modifiers which signalize one-way
  559. * streaming, it probably won't work but it's handled the same way,
  560. * RTCP commands are still bi-directional. "Inactive" modifier
  561. * is not handled anyway. See RFC3264
  562. */
  563. p = body.s;
  564. pend = body.s + body.len;
  565. sess_fl = 0;
  566. sess->media_count = 0;
  567. cline_ip_s.s = NULL; /* make gcc happy */
  568. cline_ip_s.len = 0;
  569. cline_ip = 0;
  570. cline_count = 0;
  571. codec_count = 0;
  572. memset(&codecs, 0, sizeof(codecs));
  573. sess_send_rec_modifier = 0;
  574. while (p < pend) {
  575. if (next_sdp_line(&p, pend, &ltype, &lvalue, &line) < 0) break;
  576. lend = lvalue.s + lvalue.len;
  577. switch (ltype) {
  578. case 'v':
  579. /* Protocol Version: v=0 */
  580. if (sess_fl != 0) {
  581. ERR(MODULE_NAME": parse_sdp_content: only one session allowed\n"); /* RFC3264 */
  582. return -1;
  583. }
  584. sess_fl = 1;
  585. break;
  586. case 'o':
  587. /* originator & session description: o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> */
  588. if (sess_fl != 1) {
  589. ERR(MODULE_NAME": parse_sdp_content: o= line is not in session section\n");
  590. return -1;
  591. }
  592. for (i=0; i<6; i++)
  593. if (sess->oline_addr_s.s) {
  594. ERR(MODULE_NAME": parse_sdp_content: only one o= line allowed\n");
  595. return -1;
  596. }
  597. cp = eat_token_end(lvalue.s, lend);
  598. sess->oline_user_s.len = cp-lvalue.s;
  599. if (!sess->oline_user_s.len) goto invalid_o;
  600. sess->oline_user_s.s = lvalue.s;
  601. lvalue.s = eat_space_end(cp, lend);
  602. for (i=0; i<4; i++) {
  603. cp = eat_token_end(lvalue.s, lend);
  604. if (cp-lvalue.s == 0) goto invalid_o;
  605. lvalue.s = eat_space_end(cp, lend);
  606. }
  607. cp = eat_token_end(lvalue.s, lend);
  608. sess->oline_addr_s.len = cp-lvalue.s;
  609. if (!sess->oline_addr_s.len) goto invalid_o;
  610. sess->oline_addr_s.s = lvalue.s;
  611. break;
  612. invalid_o:
  613. ERR(MODULE_NAME": parse_sdp_content: invalid o= line '%.*s'\n", (int) (lend-line.s), line.s);
  614. return -1;
  615. case 'c':
  616. /* Connection Data: c=<network type> <address type> <connection address>, ex. c=IN IP4 224.2.17.12/127 */
  617. switch (sess_fl) {
  618. case 0:
  619. ERR(MODULE_NAME": parse_sdp_content: c= line is not in session section\n");
  620. return -1;
  621. case 1:
  622. case 2:
  623. cline_count++;
  624. if (cline_count > 1) {
  625. /* multicast not supported */
  626. if (sess_fl == 2) {
  627. goto invalidate;
  628. }
  629. else {
  630. cline_ip_s.len = 0;
  631. }
  632. break;
  633. }
  634. cp = eat_token_end(lvalue.s, lend);
  635. if (cp-lvalue.s != 2 || memcmp(lvalue.s, "IN", 2) != 0) {
  636. goto invalidate;
  637. }
  638. cp = eat_space_end(cp, lend);
  639. lvalue.s = cp;
  640. cp = eat_token_end(cp, lend);
  641. if (cp-lvalue.s != 3 || memcmp(lvalue.s, "IP4", 3) != 0) {
  642. goto invalidate;
  643. }
  644. cp = eat_space_end(cp, lend);
  645. lvalue.s = cp;
  646. cp = eat_token_end(cp, lend);
  647. lvalue.len = cp-lvalue.s;
  648. if (lvalue.len == 0 || q_memchr(lvalue.s, '/', lvalue.len)) {
  649. /* multicast address not supported */
  650. goto invalidate;
  651. }
  652. if (sess_fl == 1) {
  653. cline_ip_s = lvalue;
  654. cline_ip = s2ip4(&lvalue);
  655. }
  656. else {
  657. sess->media[sess->media_count-1].ip = s2ip4(&lvalue);
  658. sess->media[sess->media_count-1].active = sess->media[sess->media_count-1].port != 0; /* IP may by specified by hostname */
  659. sess->media[sess->media_count-1].ip_s = lvalue;
  660. }
  661. break;
  662. default:
  663. ;
  664. }
  665. break;
  666. invalidate:
  667. if (sess_fl == 2) {
  668. sess->media[sess->media_count-1].active = 0;
  669. }
  670. break;
  671. case 'm':
  672. /* Media Announcements: m=<media> <port>[/<number of ports>] <transport> <fmt list>, eg. m=audio 49170 RTP/AVP 0 */
  673. /* media: "audio", "video", "application", "data" and "control" */
  674. switch (sess_fl) {
  675. case 0:
  676. ERR(MODULE_NAME": parse_sdp_content: m= line is not in session section\n");
  677. return -1;
  678. case 1:
  679. case 2:
  680. if (sess->media_count >= MAX_MEDIA_NUMBER) {
  681. ERR(MODULE_NAME": parse_sdp_content: max.number of medias (%d) exceeded\n", MAX_MEDIA_NUMBER);
  682. return -1;
  683. }
  684. cline_count = 0;
  685. sess_fl = 2;
  686. sess->media_count++;
  687. sess->media[sess->media_count-1].active = 0;
  688. sess->media[sess->media_count-1].port = 0;
  689. sess->media[sess->media_count-1].send_rec_modifier = sess_send_rec_modifier;
  690. cp = eat_token_end(lvalue.s, lend);
  691. lvalue.len = cp-lvalue.s;
  692. sess->media[sess->media_count-1].media_type = name2media_type(&lvalue);;
  693. if (!lvalue.len) {
  694. break;
  695. }
  696. cp = eat_space_end(cp, lend);
  697. lvalue.s = cp;
  698. cp = eat_token_end(cp, lend);
  699. lvalue.len = cp-lvalue.s;
  700. cp2 = q_memchr(lvalue.s, '/', lvalue.len);
  701. if (cp2) {
  702. /* strip optional number of ports, if present should be 2 */
  703. lvalue.len = cp2-lvalue.s;
  704. }
  705. sess->media[sess->media_count-1].port_s = lvalue;
  706. if (lvalue.len == 0) { /* invalid port? */
  707. break;
  708. }
  709. savec = lvalue.s[lvalue.len];
  710. lvalue.s[lvalue.len] = '\0';
  711. sess->media[sess->media_count-1].port = atol(lvalue.s);
  712. lvalue.s[lvalue.len] = savec;
  713. if (sess->media[sess->media_count-1].port == 0) {
  714. break;
  715. }
  716. cp = eat_space_end(cp, lend);
  717. lvalue.s = cp;
  718. cp = eat_token_end(cp, lend);
  719. lvalue.len = cp-lvalue.s;
  720. if (name2enum(&lvalue, &supported_protocols) >= 0) {
  721. sess->media[sess->media_count-1].active = cline_ip_s.len != 0; /* IP may by specified by hostname */
  722. sess->media[sess->media_count-1].ip_s = cline_ip_s;
  723. sess->media[sess->media_count-1].ip = cline_ip;
  724. }
  725. /* get payload types */
  726. sess->media[sess->media_count-1].codecs = (struct sdp_codec (*)[]) (codecs + codec_count);
  727. while (cp < lend) {
  728. if (codec_count >= MAX_CODEC_NUMBER) {
  729. ERR(MODULE_NAME": parse_sdp_content: max.number of codecs (%d) exceeded\n", MAX_CODEC_NUMBER);
  730. return -1;
  731. }
  732. codecs[codec_count].mline_payload_type_s.s = cp;
  733. cp = eat_space_end(cp, lend);
  734. lvalue.s = cp;
  735. cp = eat_token_end(cp, lend);
  736. codecs[codec_count].mline_payload_type_s.len = cp - codecs[codec_count].mline_payload_type_s.s;
  737. lvalue.len = cp-lvalue.s;
  738. savec = lvalue.s[lvalue.len];
  739. lvalue.s[lvalue.len] = '\0';
  740. codecs[codec_count].payload_type = atol(lvalue.s);
  741. if (codecs[codec_count].payload_type < MAX_FIXED_PAYLOAD_TYPES) {
  742. codecs[codec_count].codec_id = fixed_payload_types[codecs[codec_count].payload_type].codec_id;
  743. }
  744. lvalue.s[lvalue.len] = savec;
  745. for (i=0; i < sess->media[sess->media_count-1].codec_count; i++) {
  746. if (codecs[codec_count].payload_type == (*sess->media[sess->media_count-1].codecs)[i].payload_type) {
  747. ERR(MODULE_NAME": parse_sdp_content: duplicate payload type in '%.*s'\n", (int) (lend-line.s), line.s);
  748. return -1;
  749. }
  750. }
  751. codec_count++;
  752. sess->media[sess->media_count-1].codec_count++;
  753. }
  754. if (!sess->media[sess->media_count-1].codec_count) {
  755. ERR(MODULE_NAME": parse_sdp_content: no codec declared '%.*s'\n", (int) (lend-line.s), line.s);
  756. return -1;
  757. }
  758. break;
  759. default:
  760. ;
  761. }
  762. break;
  763. case 'a':
  764. i = name2enum(&lvalue, &send_rec_modifiers);
  765. if (i > 0) {
  766. switch (sess_fl) {
  767. case 1:
  768. if (sess_send_rec_modifier) {
  769. ERR(MODULE_NAME": parse_sdp_content: duplicate send/recv modifier in session '%.*s'\n", (int) (lend-line.s), line.s);
  770. return -1;
  771. }
  772. sess_send_rec_modifier = i;
  773. break;
  774. case 2:
  775. if (sess->media[sess->media_count-1].send_rec_modifier_line_s.s) {
  776. ERR(MODULE_NAME": parse_sdp_content: duplicate send/recv modifier in stream '%.*s'\n", (int) (lend-line.s), line.s);
  777. return -1;
  778. }
  779. sess->media[sess->media_count-1].send_rec_modifier = i;
  780. sess->media[sess->media_count-1].send_rec_modifier_line_s = line;
  781. default:
  782. ;
  783. }
  784. }
  785. else if (sess_fl == 2) {
  786. int payload_type;
  787. int a_attr;
  788. a_attr = prefix2enum(&lvalue, &a_attrs);
  789. if (a_attr < 0) {
  790. break;
  791. }
  792. lend = lvalue.s + lvalue.len;
  793. lvalue.s += a_attrs[a_attr].len;
  794. switch (a_attr) {
  795. case sdpaattr_rtpmap:
  796. /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding parameters>] , max.one a=rtpmap: per codec */
  797. case sdpaattr_fmtp:
  798. /* a=fmtp:<format/payload type> <format specific params>, max.one a=fmtp: per codec */
  799. /* we validate only things important for us. Other thinkgs not important we leave up to UA. Not tested:
  800. - payload order of a:rtpmap corresponds to m= line
  801. - all dynamic payloads have cooresponding a:rtpmap line (for us it's unknown codec)
  802. - if static payload type corresponds to codec, i.e. e.g. if 0 is PCMU
  803. */
  804. cp = eat_token_end(lvalue.s, lend);
  805. lvalue.len = cp-lvalue.s;
  806. savec = lvalue.s[lvalue.len];
  807. lvalue.s[lvalue.len] = '\0';
  808. payload_type = atol(lvalue.s);
  809. lvalue.s[lvalue.len] = savec;
  810. for (i=0; i < sess->media[sess->media_count-1].codec_count; i++) {
  811. if ((*sess->media[sess->media_count-1].codecs)[i].payload_type == payload_type) {
  812. goto found;
  813. }
  814. }
  815. ERR(MODULE_NAME": parse_sdp_content: '%.*s' payload type (%d) has not been mentioned at m= line\n", (int) (lend-line.s), line.s, payload_type);
  816. return -1;
  817. found:
  818. cp = eat_space_end(cp, lend);
  819. switch (a_attr) {
  820. case sdpaattr_rtpmap:
  821. if ((*sess->media[sess->media_count-1].codecs)[i].a_rtpmap_line_s.s) {
  822. ERR(MODULE_NAME": parse_sdp_content: '%.*s' multiple a=rtpmap lines for payload type (%d)\n", (int) (lend-line.s), line.s, payload_type);
  823. return -1;
  824. }
  825. (*sess->media[sess->media_count-1].codecs)[i].a_rtpmap_line_s = line;
  826. lvalue.s = cp;
  827. cp = eat_token2_end(cp, lend, '/');
  828. lvalue.len = cp-lvalue.s;
  829. (*sess->media[sess->media_count-1].codecs)[i].codec_id = name2codec_id(&lvalue, NULL);
  830. break;
  831. case sdpaattr_fmtp:
  832. if ((*sess->media[sess->media_count-1].codecs)[i].a_fmtp_line_s.s) {
  833. ERR(MODULE_NAME": parse_sdp_content: '%.*s' multiple a=fmtp lines for payload type (%d)\n", (int) (lend-line.s), line.s, payload_type);
  834. return -1;
  835. }
  836. (*sess->media[sess->media_count-1].codecs)[i].a_fmtp_line_s = line;
  837. break;
  838. default:
  839. break;
  840. }
  841. break;
  842. case sdpaattr_rtcp:
  843. /* a=rtcp: port [nettype space addrtype space connection-address] */
  844. ERR(MODULE_NAME": parse_sdp_content: a=rtcp parameter is ignored '%.*s', RTCP relaying may fail\n", (int) (lend-line.s), line.s);
  845. break;
  846. default:
  847. ;
  848. }
  849. }
  850. break;
  851. default:
  852. ;
  853. }
  854. }
  855. return 0;
  856. }
  857. /* simple wrapper to call parse_sdp_content() only once per request */
  858. static inline int check_parse_sdp_content(struct sip_msg* msg, struct sdp_session *sess) {
  859. switch (sdp_parsed) {
  860. case -1:
  861. case 0:
  862. return sdp_parsed;
  863. default:
  864. sdp_parsed = parse_sdp_content(msg, sess);
  865. return sdp_parsed;
  866. }
  867. }
  868. static int prepare_lumps(struct sip_msg* msg, str* position, str* s) {
  869. struct lump* anchor;
  870. char *buf;
  871. if (!position->s)
  872. return 0;
  873. //ERR("'%.*s' --> '%.*s'\n", STR_FMT(position), STR_FMT(s));
  874. anchor = del_lump(msg, position->s - msg->buf, position->len, 0);
  875. if (anchor == NULL) {
  876. ERR(MODULE_NAME": prepare_lumps: del_lump failed\n");
  877. return -1;
  878. }
  879. if (!s || !s->len) return 0;
  880. buf = pkg_malloc(s->len);
  881. if (buf == NULL) {
  882. ERR(MODULE_NAME": prepare_lumps: out of memory\n");
  883. return -1;
  884. }
  885. memcpy(buf, s->s, s->len);
  886. if (insert_new_lump_after(anchor, buf, s->len, 0) == 0) {
  887. ERR(MODULE_NAME": prepare_lumps: insert_new_lump_after failed\n");
  888. pkg_free(buf);
  889. return -1;
  890. }
  891. return 0;
  892. }
  893. static int update_sdp_content(struct sip_msg* msg, int gate_a_to_b, struct sdp_session *sdp_sess, struct ipt_session *ipt_sess) {
  894. int i, j;
  895. str s;
  896. /* we must apply lumps for relevant c= and m= lines */
  897. global_params.sdp_ip.len = 0;
  898. for (i=0; i<sdp_sess->media_count; i++) {
  899. if (sdp_sess->media[i].active) {
  900. if (ipt_sess->sdp_media[i] < 0) {
  901. goto cline_fixed;
  902. }
  903. for (j=0; j<i; j++) {
  904. if (sdp_sess->media[j].active && sdp_sess->media[i].ip_s.s == sdp_sess->media[j].ip_s.s && ipt_sess->sdp_media[j] >= 0) {
  905. goto cline_fixed;
  906. }
  907. }
  908. if (global_params.sdp_ip.len == 0) {
  909. /* takes 1st ip to be rewritten, for aux purposes only */
  910. global_params.sdp_ip = sdp_sess->media[i].ip_s;
  911. }
  912. if (sdp_sess->media[i].ip != 0) { /* we won't update 0.0.0.0 to anything because such a UA cannot receive. The session may be allocated and reused (unless expires) */
  913. /* apply lump for ip address in c= line */
  914. ip42s(ipt_sess->sessions[ipt_sess->sdp_media[i]].dir[!gate_a_to_b].switchboard.addr.ip, &s);
  915. if (prepare_lumps(msg, &sdp_sess->media[i].ip_s, &s) < 0)
  916. return -1;
  917. }
  918. cline_fixed:
  919. /* apply lump for port in m= line */
  920. s.s = int2str((ipt_sess->sdp_media[i]<0)? 0/* disable stream */: ipt_sess->sessions[ipt_sess->sdp_media[i]].dir[!gate_a_to_b].stream[0].port, &s.len);
  921. if (prepare_lumps(msg, &sdp_sess->media[i].port_s, &s) < 0)
  922. return -1;
  923. }
  924. }
  925. /* do topo hiding if all media are disabled for c= line then set address 0.0.0.0 to hide UA location */
  926. for (i=0; i<sdp_sess->media_count; i++) {
  927. if (sdp_sess->media[i].ip && (!sdp_sess->media[i].active || ipt_sess->sdp_media[i] < 0)) { /* not affected but previous loop */
  928. for (j=0; j<i; j++) {
  929. if (sdp_sess->media[i].ip_s.s == sdp_sess->media[j].ip_s.s) {
  930. goto cline_fixed2; /* must be already updated */
  931. }
  932. }
  933. for (j=i+1; j<sdp_sess->media_count; j++) {
  934. if (sdp_sess->media[i].ip_s.s == sdp_sess->media[j].ip_s.s && /* same c= line */
  935. sdp_sess->media[i].active && ipt_sess->sdp_media[i] >= 0) { /* has media enabled */
  936. goto cline_fixed2;
  937. }
  938. }
  939. /* apply lump for ip address in c= line */
  940. ip42s(0, &s);
  941. if (prepare_lumps(msg, &sdp_sess->media[i].ip_s, &s) < 0)
  942. return -1;
  943. cline_fixed2:
  944. ;
  945. }
  946. }
  947. if (sdp_sess->oline_addr_s.s) { /* o= line exists */
  948. if (global_params.oline_user.len) {
  949. if (prepare_lumps(msg, &sdp_sess->oline_user_s, &global_params.oline_user) < 0)
  950. return -1;
  951. }
  952. if (global_params.oline_addr.len) {
  953. if (prepare_lumps(msg, &sdp_sess->oline_addr_s, &global_params.oline_addr) < 0)
  954. return -1;
  955. }
  956. }
  957. return 0;
  958. }
  959. /* null terminated result is allocated at static buffer */
  960. static void serialize_ipt_session(struct ipt_session* sess, str* session_ids) {
  961. static char buf[MAX_SWITCHBOARD_NAME_LEN+1+(5+1+1+10)*MAX_MEDIA_NUMBER+1];
  962. char *p;
  963. int i;
  964. buf[0] = '\0';
  965. p = buf;
  966. if (sess->sdp_media_count) {
  967. if (sess->switchboard) {
  968. memcpy(p, sess->switchboard->name.s, sess->switchboard->name.len);
  969. p += sess->switchboard->name.len;
  970. }
  971. *p = ':';
  972. p++;
  973. for (i=0; i<sess->sdp_media_count; i++) {
  974. if (sess->sdp_media[i] >= 0) {
  975. p += sprintf(p, "%u/%u",
  976. sess->sessions[sess->sdp_media[i]].dir[0].sess_id,
  977. sess->sessions[sess->sdp_media[i]].sh.created
  978. );
  979. }
  980. *p = ',';
  981. p++;
  982. }
  983. p--;
  984. *p = '\0';
  985. }
  986. session_ids->s = buf;
  987. session_ids->len = p - buf;
  988. }
  989. /* switchboardname [":" [sess_id "/" created] [ * ( "," [sess_id "/" created] )] ] */
  990. /* sessids are placed at dir[0] */
  991. static int unserialize_ipt_session(str* session_ids, struct ipt_session* sess) {
  992. char *p, *pend, savec;
  993. str s;
  994. unsigned int sess_id, created, i;
  995. memset(sess, 0, sizeof(*sess));
  996. if (session_ids->len == 0) {
  997. return 0;
  998. }
  999. p = session_ids->s;
  1000. pend = session_ids->s+session_ids->len;
  1001. s.s = p;
  1002. while (p < pend && is_alpha(*p)) p++;
  1003. s.len = p-s.s;
  1004. sess->switchboard = find_switchboard(&s, NULL);
  1005. global_params.switchboard[0] = sess->switchboard;
  1006. if (s.len && !sess->switchboard) { /* empty switchboard is stored if all sessions are forced as disabled (port==0), SDP streams are empty but we need test medias later*/
  1007. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', switchboard '%.*s' not found\n", STR_FMT(session_ids), STR_FMT(&s));
  1008. return -1;
  1009. }
  1010. if (p == pend) return 0;
  1011. if (*p != ':') {
  1012. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', colon expected near '%.*s'\n", STR_FMT(session_ids), PTR2INT(pend-p), p);
  1013. return -1;
  1014. }
  1015. do {
  1016. if (sess->sdp_media_count >= MAX_MEDIA_NUMBER) {
  1017. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', max.media number (%d) exceeded\n", STR_FMT(session_ids), MAX_MEDIA_NUMBER);
  1018. return -1;
  1019. }
  1020. sess->sdp_media[sess->sdp_media_count] = -1;
  1021. p++;
  1022. if (p < pend && *p != ',') {
  1023. s.s = p;
  1024. while (p < pend && (*p >= '0' && *p <= '9')) p++;
  1025. s.len = p-s.s;
  1026. if (s.len == 0 || p == pend || *p != '/') {
  1027. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', '/' expected near '%.*s'\n", STR_FMT(session_ids), PTR2INT(pend-p), p);
  1028. return -1;
  1029. }
  1030. savec = s.s[s.len];
  1031. s.s[s.len] = '\0';
  1032. sess_id = atol(s.s);
  1033. s.s[s.len] = savec;
  1034. p++;
  1035. s.s = p;
  1036. while (p < pend && (*p >= '0' && *p <= '9')) p++;
  1037. s.len = p-s.s;
  1038. if (s.len == 0 || (p != pend && *p != ',')) {
  1039. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', comma expected near '%.*s'\n", STR_FMT(session_ids), PTR2INT(pend-p), p);
  1040. return -1;
  1041. }
  1042. savec = s.s[s.len];
  1043. s.s[s.len] = '\0';
  1044. created = atol(s.s);
  1045. s.s[s.len] = savec;
  1046. for (i=0; i<sess->sdp_media_count; i++) {
  1047. if (sess->sdp_media[i] >= 0 && sess->sessions[sess->sdp_media[i]].dir[0].sess_id == sess_id) {
  1048. if (sess->sessions[sess->sdp_media[i]].sh.created != created) {
  1049. ERR(MODULE_NAME": unserialize_ipt_session: '%.*s', sess-id/created mismatch '%u/(%u!=%u)'\n",
  1050. STR_FMT(session_ids), sess_id, sess->sessions[sess->sdp_media[i]].sh.created, created);
  1051. return -1;
  1052. }
  1053. sess->sdp_media[sess->sdp_media_count] = sess->sdp_media[i];
  1054. goto cont;
  1055. }
  1056. }
  1057. sess->sessions[sess->session_count].dir[0].switchboard.addr = sess->switchboard->switchboard_addr;
  1058. sess->sessions[sess->session_count].dir[0].sess_id = sess_id;
  1059. sess->sessions[sess->session_count].sh.created = created;
  1060. sess->sdp_media[sess->sdp_media_count] = sess->session_count;
  1061. sess->session_count++;
  1062. }
  1063. cont:
  1064. sess->sdp_media_count++;
  1065. } while (p < pend);
  1066. return 0;
  1067. }
  1068. static inline int check_host_err(struct host_item *hi, int ret) {
  1069. switch (hi->handle.err_no) {
  1070. case XT_RTPPROXY_ERR_CANNOT_OPEN_SOCKET:
  1071. case XT_RTPPROXY_ERR_RPC:
  1072. atomic_set_int(&hi->stat->last_error_stamp, (int) time(NULL));
  1073. break;
  1074. default:
  1075. atomic_set_int(&hi->stat->last_ok_stamp, (int) time(NULL));
  1076. }
  1077. return ret;
  1078. }
  1079. static inline int check_open_handle(struct host_item* hi) {
  1080. if (!hi->handle_is_opened) {
  1081. if (hi->local) {
  1082. if (check_host_err(hi, xt_RTPPROXY_open(&hi->handle, xt_rtpproxy_LOCAL, NULL)) < 0) goto err;
  1083. } else {
  1084. if (check_host_err(hi, xt_RTPPROXY_open(&hi->handle, xt_rtpproxy_REMOTE, &hi->rpc_params)) < 0) goto err;
  1085. }
  1086. hi->handle_is_opened = 1;
  1087. }
  1088. return 0;
  1089. err:
  1090. ERR(MODULE_NAME": %s (%d)\n", hi->handle.err_str, hi->handle.err_no);
  1091. return -1;
  1092. }
  1093. static void delete_ipt_sessions(struct host_item* hi, struct ipt_session* ipt_sess, struct ipt_session *ipt_surviving_sess) {
  1094. int i;
  1095. for (i=0; i < ipt_sess->session_count; i++) {
  1096. if (ipt_sess->switchboard == ipt_surviving_sess->switchboard) {
  1097. int j;
  1098. for (j=0; j < ipt_surviving_sess->session_count; j++) {
  1099. if (ipt_sess->sessions[i].dir[0].sess_id == ipt_surviving_sess->sessions[j].dir[0].sess_id &&
  1100. ipt_sess->sessions[i].sh.created == ipt_surviving_sess->sessions[j].sh.created ) { /* we do non need test also created */
  1101. goto skip_del;
  1102. }
  1103. }
  1104. }
  1105. ipt_sess->sessions[i].sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_DESTROY;
  1106. skip_del:
  1107. ;
  1108. }
  1109. //ERR("DEBUG_RTPPROXY: module: delete_ipt_sessions: xt_RTPPROXY_update_sessions(%d)\n", ipt_sess->session_count);
  1110. if (check_host_err(hi, xt_RTPPROXY_update_sessions(&hi->handle, ipt_sess->session_count, &ipt_sess->sessions)) < 0) {
  1111. ERR(MODULE_NAME": delete_ipt_sessions: xt_RTPPROXY_update_session error: %s (%d)\n", hi->handle.err_str, hi->handle.err_no);
  1112. /* what to do ? */
  1113. }
  1114. }
  1115. #define GATE_FLAG 0x01
  1116. #define UPDATE_SDP_ONLY_FLAG 0x02
  1117. /* gate_a_to_b has index 0, gate_b_to_a 1 */
  1118. #define GATE_A_TO_B(flags) (((flags) & GATE_FLAG) == 0)
  1119. /* SDP (sdp_session) -> ipt RTP proxy session [dir == 0] */
  1120. inline static void fill_in_session(int flags, int media_idx, struct sdp_session *sdp_sess, struct xt_rtpproxy_sockopt_session *in_session) {
  1121. int j;
  1122. for (j=0; j<2; j++) {
  1123. if (sdp_sess) {
  1124. in_session->dir[GATE_A_TO_B(flags)].stream[j].flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_ADDR;
  1125. in_session->dir[GATE_A_TO_B(flags)].stream[j].source.ip = sdp_sess->media[media_idx].ip;
  1126. in_session->dir[GATE_A_TO_B(flags)].stream[j].source.port = sdp_sess->media[media_idx].port+j;
  1127. }
  1128. if (global_params.learning_timeout > 0) {
  1129. in_session->dir[GATE_A_TO_B(flags)].stream[j].flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_LEARNING_TIMEOUT;
  1130. in_session->dir[GATE_A_TO_B(flags)].stream[j].learning_timeout = global_params.learning_timeout;
  1131. }
  1132. }
  1133. if (global_params.always_learn >= 0) {
  1134. in_session->dir[GATE_A_TO_B(flags)].always_learn = global_params.always_learn!=0;
  1135. in_session->dir[GATE_A_TO_B(flags)].flags |= XT_RTPPROXY_SOCKOPT_FLAG_ALWAYS_LEARN;
  1136. }
  1137. if (global_params.expiration_timeout > 0) {
  1138. in_session->sh.expires_timeout = global_params.expiration_timeout;
  1139. in_session->sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_EXPIRES;
  1140. }
  1141. if (global_params.ttl >= 0) {
  1142. in_session->sh.ttl = global_params.ttl;
  1143. in_session->sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_TTL;
  1144. }
  1145. }
  1146. inline static void fill_in_session_throttle(int flags, int media_idx, struct xt_rtpproxy_sockopt_session *in_session) {
  1147. int j;
  1148. if (global_params.throttle.mark > 0) {
  1149. for (j=0; j<2; j++) {
  1150. in_session->dir[GATE_A_TO_B(flags)].stream[j].throttle.mark = global_params.throttle.mark;
  1151. in_session->dir[GATE_A_TO_B(flags)].stream[j].flags |= XT_RTPPROXY_SOCKOPT_FLAG_THROTTLE_MARK;
  1152. }
  1153. }
  1154. for (j=0; j<2; j++) {
  1155. if (global_params.codec_set &&
  1156. (global_params.codec_set->media_types[global_sdp_sess.media[media_idx].media_type].throttle.bandwidth[j].packets > 0 ||
  1157. global_params.codec_set->media_types[global_sdp_sess.media[media_idx].media_type].throttle.bandwidth[j].bytes > 0)
  1158. ) {
  1159. in_session->dir[GATE_A_TO_B(flags)].stream[j].throttle.max_bandwidth = global_params.codec_set->media_types[global_sdp_sess.media[media_idx].media_type].throttle.bandwidth[j];
  1160. in_session->dir[GATE_A_TO_B(flags)].stream[j].flags |= XT_RTPPROXY_SOCKOPT_FLAG_THROTTLE_BANDWIDTH;
  1161. } else if (global_params.throttle.bandwidth[j].bytes > 0 || global_params.throttle.bandwidth[j].packets > 0 ) {
  1162. in_session->dir[GATE_A_TO_B(flags)].stream[j].throttle.max_bandwidth = global_params.throttle.bandwidth[j];
  1163. in_session->dir[GATE_A_TO_B(flags)].stream[j].flags |= XT_RTPPROXY_SOCKOPT_FLAG_THROTTLE_BANDWIDTH;
  1164. }
  1165. }
  1166. }
  1167. static int rtpproxy_alloc(struct sip_msg* msg, char* _flags, char* _dummy) {
  1168. int flags;
  1169. struct ipt_session ipt_sess;
  1170. struct host_item* hi = NULL;
  1171. struct xt_rtpproxy_switchboard_id aggregated_switchboards[MAX_AGGREGATED_NUMBER];
  1172. time_t stamp;
  1173. xt_rtpproxy_sockopt_count cnt[2];
  1174. str s;
  1175. int i, aggr_fl, reuse_existing_count;
  1176. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  1177. return -1;
  1178. }
  1179. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1180. ERR("RTPPROXY_DEBUG: sdp.media_count: %d, flags: %d\n", global_sdp_sess.media_count, flags);
  1181. if (global_params.protected_sess.switchboard) { /* any protected ? */
  1182. /* get session source address from kernel module and compare with SDP content */
  1183. for (i = 0; i < global_params.protected_sess.session_count; i++) {
  1184. global_params.protected_sess.sessions[i].sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_INFO;
  1185. }
  1186. if (check_open_handle(global_params.protected_sess.switchboard->host) < 0) {
  1187. return -1;
  1188. }
  1189. ERR("RTPPROXY_DEBUG: xt_RTPPROXY_update_sessions(sess#:%d, sdp#:%d, XT_RTPPROXY_SOCKOPT_FLAG_SESSION_INFO)\n", global_params.protected_sess.session_count, global_params.protected_sess.sdp_media_count);
  1190. if (check_host_err(global_params.protected_sess.switchboard->host, xt_RTPPROXY_update_sessions(&global_params.protected_sess.switchboard->host->handle, global_params.protected_sess.session_count, &global_params.protected_sess.sessions)) < 0) {
  1191. ERR(MODULE_NAME": rtpproxy_alloc: xt_RTPPROXY_update_session error when retrieving sessions: %s (%d)\n",
  1192. global_params.protected_sess.switchboard->host->handle.err_str,
  1193. global_params.protected_sess.switchboard->host->handle.err_no
  1194. );
  1195. return -1;
  1196. }
  1197. }
  1198. reuse_existing_count = 0;
  1199. memset(&ipt_sess, 0, sizeof(ipt_sess));
  1200. for (i = 0; i < global_sdp_sess.media_count; i++) {
  1201. ipt_sess.sdp_media[i] = -1;
  1202. if (global_sdp_sess.media[i].active) {
  1203. int j;
  1204. for (j = 0; j < i; j++) {
  1205. /* if two media streams have equal source address than we will allocate only one ipt session */
  1206. if (global_sdp_sess.media[j].active) {
  1207. if (global_sdp_sess.media[i].ip == global_sdp_sess.media[j].ip && global_sdp_sess.media[i].port == global_sdp_sess.media[j].port) {
  1208. if (global_sdp_sess.media[i].ip != 0) {
  1209. ipt_sess.sdp_media[i] = ipt_sess.sdp_media[j];
  1210. goto cont;
  1211. } else if (i < global_params.protected_sess.sdp_media_count) {
  1212. int k, l;
  1213. k = global_params.protected_sess.sdp_media[i];
  1214. l = global_params.protected_sess.sdp_media[j];
  1215. if ((global_params.protected_sess.sessions[k].sh.flags & XT_RTPPROXY_SOCKOPT_FLAG_NOT_FOUND) == 0 &&
  1216. global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.ip == global_params.protected_sess.sessions[l].dir[GATE_A_TO_B(flags)].stream[0].source.ip &&
  1217. global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.port == global_params.protected_sess.sessions[l].dir[GATE_A_TO_B(flags)].stream[0].source.port) {
  1218. /* if ip == 0, for example phone goes on-hold we'll take IP from protected sessions if possible */
  1219. ipt_sess.sdp_media[i] = ipt_sess.sdp_media[j];
  1220. goto cont;
  1221. }
  1222. }
  1223. }
  1224. }
  1225. }
  1226. /* if there are existing sessions then we take those instead of allocation new ones */
  1227. /* we can match 1:1 existing media streams against SDP sessions provided by SDP */
  1228. if (i < global_params.protected_sess.sdp_media_count) {
  1229. int k;
  1230. k = global_params.protected_sess.sdp_media[i];
  1231. ERR("RTPPROXY_DEBUG: protected.sess media:%d -> sess:%d, flags: %d\n", i, k, global_params.protected_sess.sessions[k].sh.flags);
  1232. if ((global_params.protected_sess.sessions[k].sh.flags & XT_RTPPROXY_SOCKOPT_FLAG_NOT_FOUND) == 0) {
  1233. switch (global_params.protected_sess.sessions[k].sh.state) {
  1234. case xt_rtpproxy_INIT1:
  1235. case xt_rtpproxy_INIT2:
  1236. case xt_rtpproxy_FORWARD1:
  1237. case xt_rtpproxy_FORWARD2:
  1238. /* is original ip:port of existion session equal to ip:port provided by SDP ? RTP test is sufficient */
  1239. /* Workaround: if a phone (Sipura, X-Lite, ...) goes on-hold then
  1240. c= line address is set to 0.0.0.0. It's not correct because RTCP media
  1241. can't tricle. It would not force new RTP session allocation.
  1242. So we won't update SDP c= line but get sees_id from protected sess to reuse it when on-hold terminates.
  1243. But when on-hold is too long and session expires then new session will be allocated */
  1244. ERR("DEBUG_RTPPROXY: module: CMP %x=%x & %d=%d\n", global_sdp_sess.media[i].ip, global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.ip, global_sdp_sess.media[i].port, global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.port);
  1245. if ((global_sdp_sess.media[i].ip == 0 ||
  1246. global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.ip == 0 ||
  1247. global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.ip == global_sdp_sess.media[i].ip) &&
  1248. /* global_sdp_sess.media[i].port always because active && */
  1249. global_params.protected_sess.sessions[k].dir[GATE_A_TO_B(flags)].stream[0].source.port == global_sdp_sess.media[i].port) {
  1250. /* keep all reused sess at the beginning of list, i.e. make slot */
  1251. ERR("RTPPROXY_DEBUG: REUSE!\n");
  1252. for (j=ipt_sess.session_count; j > 0; j--) {
  1253. ipt_sess.sessions[j] = ipt_sess.sessions[j-1];
  1254. }
  1255. for (j=0; j < i; j++) {
  1256. if (ipt_sess.sdp_media[j] >= 0) {
  1257. ipt_sess.sdp_media[j]++;
  1258. }
  1259. }
  1260. /* put it at slot [0], copy data from existing session */
  1261. for (j=0; j<2; j++) {
  1262. ipt_sess.sessions[0].dir[j] = global_params.protected_sess.sessions[k].dir[j];
  1263. }
  1264. ipt_sess.sessions[0].sh = global_params.protected_sess.sessions[k].sh;
  1265. ipt_sess.sdp_media[i] = 0;
  1266. reuse_existing_count++;
  1267. goto skip_fill;
  1268. }
  1269. break;
  1270. default:
  1271. ;
  1272. }
  1273. }
  1274. }
  1275. if (global_sdp_sess.media[i].ip == 0) {
  1276. switch (global_sdp_sess.media[i].send_rec_modifier) {
  1277. case sdpaattr_sendonly:
  1278. case sdpaattr_sendrecv: /* it's error because it cannot receive anything but client are weird */
  1279. break; /* they can send RTP/RTCP, not recommended in RFC3264, maybe allow only when learning possible */
  1280. default:
  1281. /* do not allocate session for on-hold stream unless reused, disable stream (sdp_media[i]) < 0 */
  1282. ERR("DEBUG_RTPPROXY: module: do not allocate session for on-hold stream unless reused\n");
  1283. goto cont;
  1284. }
  1285. }
  1286. fill_in_session(flags, i, &global_sdp_sess, ipt_sess.sessions+ipt_sess.session_count);
  1287. fill_in_session_throttle(flags, i, ipt_sess.sessions+ipt_sess.session_count);
  1288. ipt_sess.sdp_media[i] = ipt_sess.session_count;
  1289. skip_fill:
  1290. ipt_sess.session_count++;
  1291. }
  1292. cont:
  1293. ;
  1294. }
  1295. ipt_sess.sdp_media_count = global_sdp_sess.media_count;
  1296. ERR("RTPPROXY_DEBUG: session_count: %d, reuse_existing_count: %d\n", global_sdp_sess.media_count, reuse_existing_count);
  1297. if (ipt_sess.session_count > reuse_existing_count) {
  1298. stamp = time(NULL);
  1299. if (reuse_existing_count > 0) {
  1300. /* we need allocate sessions at the same switchboard as already being existed */
  1301. aggr_fl = 0;
  1302. hi = global_params.protected_sess.switchboard->host;
  1303. ipt_sess.switchboard = global_params.protected_sess.switchboard;
  1304. for (i=reuse_existing_count; i < ipt_sess.session_count; i++) {
  1305. int j;
  1306. for (j=0; j<2; j++) {
  1307. ipt_sess.sessions[i].dir[j].switchboard.addr = ipt_sess.sessions[0].dir[j].switchboard.addr;
  1308. }
  1309. }
  1310. } else {
  1311. for (i=0; i<2; i++) {
  1312. if (!global_params.switchboard[i] && !global_params.aggregation[i]) {
  1313. ERR(MODULE_NAME": rtpproxy_alloc: aggregation/switchboard not set (dir:%d)\n", i);
  1314. return -1;
  1315. }
  1316. }
  1317. aggr_fl = global_params.aggregation[0] || global_params.aggregation[1];
  1318. if (aggr_fl) {
  1319. struct switchboard_item *si;
  1320. /* calculate switchboard weights. There is minor problem when weight are calculated some time before
  1321. RPC commands are performed, i.e. if a remote RPC server become unavailable then more processes
  1322. may spend time waiting for unresponsive machine even it's been discovered by parallel process.
  1323. */
  1324. for (si=switchboards; si; si=si->next) {
  1325. unsigned int w;
  1326. int a, f;
  1327. time_t ok_stamp, err_stamp;
  1328. a = f = 0;
  1329. ok_stamp = atomic_get_int(&si->host->stat->last_ok_stamp);
  1330. err_stamp = atomic_get_int(&si->host->stat->last_error_stamp);
  1331. if (rpc_heartbeat_timeout > 0 && err_stamp > ok_stamp && (stamp-err_stamp) >= rpc_heartbeat_timeout) {
  1332. /* set max. priority to force remote rtpproxy rpc call, i.e. test if is alive or dead */
  1333. ok_stamp = err_stamp = 0;
  1334. }
  1335. if (err_stamp > ok_stamp) {
  1336. /* lowest priority */
  1337. /* prefer older error */
  1338. w = time(NULL) - err_stamp + 1;
  1339. if (w > 999) w = 999;
  1340. } else if (ok_stamp == 0) {
  1341. /* not yet acquired, highest */
  1342. w = 100000000 + (kam_rand() & 0xFFFF); /* randomize not yet asked or being hartbeated */
  1343. } else {
  1344. /* middle */
  1345. w = 1000;
  1346. a = atomic_get(&si->stat->alloc);
  1347. f = atomic_get(&si->stat->free);
  1348. if ((a + f) > 0) {
  1349. /* prefer switchboards having more free slots */
  1350. w += (1000*f)/(a+f);
  1351. }
  1352. }
  1353. si->weight = w;
  1354. //ERR(MODULE_NAME": rtpproxy_alloc: switchboard '%.*s' (ok_stamp: %u, err_stamp: %u, alloc: %u, free: %u, weight: %u)\n", STR_FMT(&si->name), (unsigned int) ok_stamp, (unsigned int) err_stamp, a, f, w);
  1355. }
  1356. hi = NULL;
  1357. }
  1358. else {
  1359. if (global_params.switchboard[0]->host != global_params.switchboard[1]->host) {
  1360. ERR(MODULE_NAME": rtpproxy_alloc: switchboard resides of different hosts '%.*s'!='%.*s'\n",
  1361. STR_FMT(&global_params.switchboard[0]->host->name),
  1362. STR_FMT(&global_params.switchboard[1]->host->name)
  1363. );
  1364. return -1;
  1365. }
  1366. hi = global_params.switchboard[0]->host;
  1367. for (i=0; i < ipt_sess.session_count; i++) {
  1368. int j;
  1369. for (j=0; j<2; j++) {
  1370. ipt_sess.sessions[i].dir[j].switchboard.addr = global_params.switchboard[j]->switchboard_addr;
  1371. }
  1372. }
  1373. }
  1374. }
  1375. try_next_host:
  1376. cnt[0] = cnt[1] = 0;
  1377. if (aggr_fl) {
  1378. int j;
  1379. hi = NULL;
  1380. if (global_params.aggregation[0] && global_params.aggregation[1]) {
  1381. int w = 0;
  1382. /* find switchboard having max. weight */
  1383. for (i=0; i<global_params.aggregation[0]->switchboard_count; i++) {
  1384. if ((*global_params.aggregation[0]->switchboards)[i]->weight > w) { /* weight==0 is skipped */
  1385. time_t err_stamp;
  1386. err_stamp = atomic_get_int(&(*global_params.aggregation[0]->switchboards)[i]->host->stat->last_error_stamp);
  1387. if (err_stamp >= stamp) {
  1388. if (w > 0) continue;
  1389. /* decrease weight to minimum, parallel process meanwhile got error */
  1390. w = 1;
  1391. } else {
  1392. w = (*global_params.aggregation[0]->switchboards)[i]->weight;
  1393. }
  1394. hi = (*global_params.aggregation[0]->switchboards)[i]->host;
  1395. }
  1396. }
  1397. } else {
  1398. for (j=0; j<2; j++) {
  1399. if (!global_params.aggregation[j] && global_params.switchboard[j]->weight) {
  1400. hi = global_params.switchboard[j]->host;
  1401. }
  1402. }
  1403. }
  1404. if (!hi) {
  1405. ERR(MODULE_NAME": rtpproxy_alloc: cannot allocate aggregated switchboard (#1)\n");
  1406. return -1;
  1407. }
  1408. for (j=0; j<2; j++) {
  1409. if (global_params.aggregation[j]) {
  1410. struct switchboard_item *aggr_switchboards[MAX_AGGREGATED_NUMBER];
  1411. for (i=0; i<global_params.aggregation[j]->switchboard_count; i++) {
  1412. if ((*global_params.aggregation[j]->switchboards)[i]->weight &&
  1413. (*global_params.aggregation[j]->switchboards)[i]->host == hi) {
  1414. int k, l;
  1415. if (cnt[0]+cnt[1] >= MAX_AGGREGATED_NUMBER) {
  1416. ERR(MODULE_NAME": rtpproxy_alloc: number of aggregated switchboard exceeded limit %d\n", MAX_AGGREGATED_NUMBER);
  1417. return -1;
  1418. }
  1419. /* put switchboard ordered by weight */
  1420. for (k=0; k<cnt[j] && aggr_switchboards[k]->weight >= (*global_params.aggregation[j]->switchboards)[i]->weight; k++);
  1421. for (l=cnt[j]; l>k; l--) {
  1422. aggr_switchboards[l] = aggr_switchboards[l-1];
  1423. }
  1424. aggr_switchboards[k] = (*global_params.aggregation[j]->switchboards)[i];
  1425. cnt[j]++;
  1426. }
  1427. }
  1428. if (!cnt[j]) {
  1429. ERR(MODULE_NAME": rtpproxy_alloc: cannot allocate aggregated switchboard (#2)\n");
  1430. return -1;
  1431. }
  1432. for (i = 0; i < cnt[j]; i++) {
  1433. aggregated_switchboards[j*cnt[0]+i] = aggr_switchboards[i]->switchboard_addr;
  1434. }
  1435. }
  1436. else {
  1437. if (cnt[0]+cnt[1] >= MAX_AGGREGATED_NUMBER) {
  1438. ERR(MODULE_NAME": rtpproxy_alloc: number of aggregated switchboard exceeded limit %d\n", MAX_AGGREGATED_NUMBER);
  1439. return -1;
  1440. }
  1441. aggregated_switchboards[cnt[0]+cnt[1]] = global_params.switchboard[j]->switchboard_addr;
  1442. cnt[j]++;
  1443. }
  1444. }
  1445. for (j=0; j<2; j++) {
  1446. if (global_params.aggregation[j]) {
  1447. for (i=0; i<global_params.aggregation[j]->switchboard_count; i++) {
  1448. if ((*global_params.aggregation[j]->switchboards)[i]->host == hi) {
  1449. /* done, do not process in next round again */
  1450. (*global_params.aggregation[j]->switchboards)[i]->weight = 0;
  1451. }
  1452. }
  1453. }
  1454. else {
  1455. global_params.switchboard[j]->weight = 0;
  1456. }
  1457. }
  1458. }
  1459. if (reuse_existing_count < ipt_sess.session_count) { /* allocation required ? */
  1460. if (check_open_handle(hi) < 0) {
  1461. if (aggr_fl) {
  1462. goto try_next_host;
  1463. }
  1464. return -1;
  1465. }
  1466. ERR("DEBUG_RTPPROXY: module: rtpproxy_alloc: xt_RTPPROXY_alloc_sessions(%d/%d/%d), host: '%.*s', flags: %d\n", cnt[0], cnt[1], ipt_sess.session_count, STR_FMT(&hi->name), flags);
  1467. if (check_host_err(hi, xt_RTPPROXY_alloc_sessions(&hi->handle,
  1468. cnt[0],
  1469. &aggregated_switchboards,
  1470. cnt[1],
  1471. (void*) &aggregated_switchboards[cnt[0]],
  1472. ipt_sess.session_count-reuse_existing_count, /* allocate only non-reused sessions */
  1473. &ipt_sess.sessions+reuse_existing_count
  1474. )) < 0) {
  1475. ERR(MODULE_NAME": rtpproxy_alloc: xt_RTPPROXY_alloc_session error: %s (%d)\n", hi->handle.err_str, hi->handle.err_no);
  1476. if (aggr_fl) {
  1477. goto try_next_host;
  1478. }
  1479. return -1;
  1480. }
  1481. }
  1482. }
  1483. if (update_sdp_content(msg, GATE_A_TO_B(flags), &global_sdp_sess, &ipt_sess) < 0) {
  1484. delete_ipt_sessions(hi, &ipt_sess, &global_params.protected_sess);
  1485. return -1;
  1486. }
  1487. if (ipt_sess.session_count) {
  1488. ipt_sess.switchboard = find_switchboard_by_addr(&ipt_sess.sessions[0].dir[0].switchboard.addr);
  1489. if (!ipt_sess.switchboard) {
  1490. BUG(MODULE_NAME": rtpproxy_alloc: switchboard-a definition not found\n");
  1491. return -1;
  1492. }
  1493. //ERR("DEBUG_RTPPROXY: module: rtpproxy_alloc: switchboard-a '%.*s'\n", STR_FMT(&ipt_sess.switchboard->name));
  1494. global_params.switchboard[0] = ipt_sess.switchboard;
  1495. global_params.switchboard[1] = find_switchboard_by_addr(&ipt_sess.sessions[0].dir[1].switchboard.addr);
  1496. if (!global_params.switchboard[1]) {
  1497. BUG(MODULE_NAME": rtpproxy_alloc: switchboard-b definition not found\n");
  1498. return -1;
  1499. }
  1500. //ERR("DEBUG_RTPPROXY: module: rtpproxy_alloc: switchboard-b '%.*s'\n", STR_FMT(&global_params.switchboard[1]->name));
  1501. atomic_set(&global_params.switchboard[0]->stat->free, ipt_sess.sessions[0].dir[0].switchboard.free);
  1502. atomic_set(&global_params.switchboard[0]->stat->alloc, ipt_sess.sessions[0].dir[0].switchboard.alloc);
  1503. if (global_params.switchboard[0] != global_params.switchboard[1]) {
  1504. atomic_set(&global_params.switchboard[1]->stat->free, ipt_sess.sessions[0].dir[1].switchboard.free);
  1505. atomic_set(&global_params.switchboard[1]->stat->alloc, ipt_sess.sessions[0].dir[1].switchboard.alloc);
  1506. }
  1507. }
  1508. else {
  1509. ipt_sess.switchboard = global_params.protected_sess.switchboard; /* we need still keep the same switchboard */
  1510. global_params.switchboard[0] = ipt_sess.switchboard;
  1511. }
  1512. serialize_ipt_session(&ipt_sess, &s);
  1513. global_params.session_ids = s; /* it's static and null terminated */
  1514. return 1;
  1515. }
  1516. static int rtpproxy_update(struct sip_msg* msg, char* _flags, char* _session_ids) {
  1517. str session_ids;
  1518. int flags, i;
  1519. struct ipt_session ipt_sess;
  1520. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  1521. return -1;
  1522. }
  1523. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  1524. return -1;
  1525. }
  1526. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  1527. return -1;
  1528. }
  1529. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1530. if (ipt_sess.sdp_media_count != global_sdp_sess.media_count) {
  1531. ERR(MODULE_NAME": rtpproxy_update: number of m= item in offer (%d) and answer (%d) do not correspond\n", ipt_sess.sdp_media_count, global_sdp_sess.media_count);
  1532. return -1;
  1533. }
  1534. /* first we check for unexpected duplicate source ports */
  1535. for (i = 0; i < global_sdp_sess.media_count; i++) {
  1536. if (ipt_sess.sdp_media[i] >= 0 && global_sdp_sess.media[i].active) {
  1537. int j;
  1538. for (j = i+1; j < global_sdp_sess.media_count; j++) {
  1539. if (ipt_sess.sdp_media[j] >= 0 && global_sdp_sess.media[j].active) {
  1540. /* if two media streams have equal source address XOR have equal session */
  1541. if ( (global_sdp_sess.media[i].ip == global_sdp_sess.media[j].ip && global_sdp_sess.media[i].port == global_sdp_sess.media[j].port) ^
  1542. (ipt_sess.sdp_media[i] == ipt_sess.sdp_media[j]) ) {
  1543. ERR(MODULE_NAME": rtpproxy_update: media (%d,%d) violation number\n", i, j);
  1544. return -1;
  1545. }
  1546. }
  1547. }
  1548. }
  1549. }
  1550. if (flags & UPDATE_SDP_ONLY_FLAG) {
  1551. /* get session source address from kernel module, do not update RTP session, only updateSDP content */
  1552. for (i = 0; i < ipt_sess.session_count; i++) {
  1553. ipt_sess.sessions[i].sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_INFO;
  1554. }
  1555. } else {
  1556. /* first we check sessions to delete, the sessions can be "undeleted" if other media still uses session */
  1557. for (i = 0; i < global_sdp_sess.media_count; i++) {
  1558. if (ipt_sess.sdp_media[i] >= 0) {
  1559. if (!global_sdp_sess.media[i].active) {
  1560. ipt_sess.sessions[ipt_sess.sdp_media[i]].sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_DESTROY;
  1561. ipt_sess.sdp_media[i] = -1;
  1562. }
  1563. }
  1564. }
  1565. for (i = 0; i < global_sdp_sess.media_count; i++) {
  1566. if (ipt_sess.sdp_media[i] >= 0) {
  1567. if (global_sdp_sess.media[i].active) {
  1568. fill_in_session(flags, i, &global_sdp_sess, ipt_sess.sessions+ipt_sess.sdp_media[i]);
  1569. fill_in_session_throttle(flags, i, ipt_sess.sessions+ipt_sess.sdp_media[i]);
  1570. ipt_sess.sessions[ipt_sess.sdp_media[i]].sh.flags &= ~XT_RTPPROXY_SOCKOPT_FLAG_SESSION_DESTROY;
  1571. }
  1572. }
  1573. }
  1574. /* we cannot also delete sessions which have been reused from other session set */
  1575. for (i = 0; i < ipt_sess.session_count; i++) {
  1576. if (ipt_sess.sessions[i].sh.flags & XT_RTPPROXY_SOCKOPT_FLAG_SESSION_DESTROY) {
  1577. if (ipt_sess.switchboard == global_params.protected_sess.switchboard) {
  1578. int j;
  1579. for (j=0; j < global_params.protected_sess.session_count; j++) {
  1580. if (ipt_sess.sessions[i].dir[0].sess_id == global_params.protected_sess.sessions[j].dir[0].sess_id &&
  1581. ipt_sess.sessions[i].sh.created == global_params.protected_sess.sessions[j].sh.created ) {
  1582. ipt_sess.sessions[i].sh.flags &= ~XT_RTPPROXY_SOCKOPT_FLAG_SESSION_DESTROY;
  1583. ipt_sess.sessions[i].sh.flags |= XT_RTPPROXY_SOCKOPT_FLAG_SESSION_INFO;
  1584. /* or we can remove from sessions TODO */
  1585. break;
  1586. }
  1587. }
  1588. }
  1589. }
  1590. }
  1591. }
  1592. //ERR("DEBUG_RTPPROXY: module: rtpproxy_update: xt_RTPPROXY_update_sessions(%d), flags:%d, switchboard:%p, sess:%.*s\n", ipt_sess.session_count, flags, ipt_sess.switchboard, STR_FMT(&session_ids));
  1593. global_params.switchboard[0] = ipt_sess.switchboard;
  1594. if (ipt_sess.switchboard) {
  1595. if (check_open_handle(ipt_sess.switchboard->host) < 0) {
  1596. return -1;
  1597. }
  1598. if (check_host_err(ipt_sess.switchboard->host, xt_RTPPROXY_update_sessions(&ipt_sess.switchboard->host->handle, ipt_sess.session_count, &ipt_sess.sessions)) < 0) {
  1599. ERR(MODULE_NAME": rtpproxy_update: xt_RTPPROXY_update_session error: %s (%d)\n",
  1600. ipt_sess.switchboard->host->handle.err_str,
  1601. ipt_sess.switchboard->host->handle.err_no
  1602. );
  1603. /* delete all sessions ? */
  1604. return -1;
  1605. }
  1606. global_params.switchboard[1] = find_switchboard_by_addr(&ipt_sess.sessions[0].dir[1].switchboard.addr);
  1607. } else {
  1608. /* disable media from answer too as we did it in request, port = 0 */
  1609. global_params.switchboard[1] = NULL;
  1610. }
  1611. if (update_sdp_content(msg, GATE_A_TO_B(flags), &global_sdp_sess, &ipt_sess) < 0) {
  1612. /* delete all sessions ? */
  1613. return -1;
  1614. }
  1615. serialize_ipt_session(&ipt_sess, &session_ids);
  1616. global_params.session_ids = session_ids; /* it's static and null terminated */
  1617. return 1;
  1618. }
  1619. static int rtpproxy_adjust_timeout(struct sip_msg* msg, char* _flags, char* _session_ids) {
  1620. str session_ids;
  1621. int flags, i;
  1622. struct ipt_session ipt_sess;
  1623. if (get_int_fparam(&flags, msg, (fparam_t*) _flags) < 0) {
  1624. return -1;
  1625. }
  1626. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  1627. return -1;
  1628. }
  1629. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  1630. return -1;
  1631. }
  1632. if (!ipt_sess.switchboard) {
  1633. return 1;
  1634. }
  1635. for (i = 0; i < ipt_sess.sdp_media_count; i++) {
  1636. if (ipt_sess.sdp_media[i] >= 0) {
  1637. fill_in_session(flags, i, NULL, ipt_sess.sessions+ipt_sess.sdp_media[i]);
  1638. /* throttle not affected */
  1639. }
  1640. }
  1641. //ERR("DEBUG_RTPPROXY: module: rtpproxy_adjust_timeout: xt_RTPPROXY_update_sessions(%d), flags:%d, sess:%.*s\n", ipt_sess.session_count, flags, STR_FMT(&session_ids));
  1642. if (check_open_handle(ipt_sess.switchboard->host) < 0) {
  1643. return -1;
  1644. }
  1645. if (check_host_err(ipt_sess.switchboard->host, xt_RTPPROXY_update_sessions(&ipt_sess.switchboard->host->handle, ipt_sess.session_count, &ipt_sess.sessions)) < 0) {
  1646. ERR(MODULE_NAME": rtpproxy_adjust_timeout: xt_RTPPROXY_adjust_timeout error: %s (%d)\n",
  1647. ipt_sess.switchboard->host->handle.err_str,
  1648. ipt_sess.switchboard->host->handle.err_no
  1649. );
  1650. return -1;
  1651. }
  1652. /* do not serialize sessions because it affect static buffer and more valuable values disappears */
  1653. return 1;
  1654. }
  1655. static int rtpproxy_delete(struct sip_msg* msg, char* _session_ids, char* _dummy) {
  1656. str session_ids;
  1657. struct ipt_session ipt_sess;
  1658. if (get_str_fparam(&session_ids, msg, (fparam_t*) _session_ids) < 0) {
  1659. return -1;
  1660. }
  1661. if (!session_ids.len) return 1;
  1662. if (unserialize_ipt_session(&session_ids, &ipt_sess) < 0) {
  1663. return -1;
  1664. }
  1665. //ERR("DEBUG_RTPPROXY: module: rtpproxy_delete: sess:%.*s\n", STR_FMT(&session_ids));
  1666. if (!ipt_sess.switchboard) {
  1667. return 1; /* nothing to delete */
  1668. }
  1669. if (check_open_handle(ipt_sess.switchboard->host) < 0) {
  1670. return -1;
  1671. }
  1672. delete_ipt_sessions(ipt_sess.switchboard->host, &ipt_sess, &global_params.protected_sess);
  1673. /* do not serialize sessions because it affect static buffer and more valuable values disappears */
  1674. return 1;
  1675. }
  1676. static int rtpproxy_authorize_media(struct sip_msg* msg, char* _dummy1, char* _dummy2) {
  1677. unsigned int media_count[MAX_MEDIA_NUMBER];
  1678. int i;
  1679. if (!global_params.codec_set) return 1;
  1680. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1681. global_params.auth_rights = 0;
  1682. memset(&media_count, 0, sizeof(media_count));
  1683. for (i=0; i<global_sdp_sess.media_count; i++) {
  1684. int j, n, fl;
  1685. if (global_sdp_sess.media[i].active != 1) continue;
  1686. n = 0;
  1687. fl = media_count[global_sdp_sess.media[i].media_type] == global_params.codec_set->media_types[global_sdp_sess.media[i].media_type].throttle.max_streams;
  1688. if (fl) {
  1689. goto remove_stream;
  1690. }
  1691. for (j=0; j<global_sdp_sess.media[i].codec_count; j++) {
  1692. unsigned int r;
  1693. struct sdp_codec *c;
  1694. c = &(*global_sdp_sess.media[i].codecs)[j];
  1695. /* codec has been already removed */
  1696. if (!c->mline_payload_type_s.s) continue;
  1697. r = (*global_params.codec_set->media_types[global_sdp_sess.media[i].media_type].codec_rights)[c->codec_id];
  1698. if (r) {
  1699. if (r > global_params.auth_rights) {
  1700. global_params.auth_rights = r;
  1701. }
  1702. if (r & global_params.remove_codec_mask) {
  1703. /* remove codec */
  1704. n++;
  1705. if (n < global_sdp_sess.media[i].codec_count) {
  1706. /* if it's last remainng codec then leave it and remove stream */
  1707. if (prepare_lumps(msg, &c->mline_payload_type_s, NULL) < 0)
  1708. return -1;
  1709. c->mline_payload_type_s.s = NULL; /* mark as removed */
  1710. if (prepare_lumps(msg, &c->a_rtpmap_line_s, NULL) < 0)
  1711. return -1;
  1712. if (prepare_lumps(msg, &c->a_fmtp_line_s, NULL) < 0)
  1713. return -1;
  1714. }
  1715. }
  1716. }
  1717. }
  1718. remove_stream:
  1719. if (n == global_sdp_sess.media[i].codec_count || fl) {
  1720. /* remove the stream */
  1721. static str zero_s = STR_STATIC_INIT("0");
  1722. if (prepare_lumps(msg, & global_sdp_sess.media[i].port_s, &zero_s) < 0)
  1723. return -1;
  1724. global_sdp_sess.media[i].active = 0;
  1725. continue;
  1726. }
  1727. media_count[global_sdp_sess.media[i].media_type]++;
  1728. }
  1729. return 1;
  1730. }
  1731. static int rtpproxy_set_param(struct sip_msg* msg, char* _idx, char* _value) {
  1732. int idx, dir;
  1733. unsigned int ip;
  1734. idx = PTR2INT(_idx);
  1735. union {
  1736. str s;
  1737. int i;
  1738. } u;
  1739. dir = (param_list[idx].flags & PAR_DIR) != 0;
  1740. if (param_list[idx].flags & PAR_INT) {
  1741. if (get_int_fparam(&u.i, msg, (fparam_t*) _value) < 0) {
  1742. return -1;
  1743. }
  1744. } else {
  1745. if (get_str_fparam(&u.s, msg, (fparam_t*) _value) < 0) {
  1746. return -1;
  1747. }
  1748. }
  1749. switch (param_list[idx].id) {
  1750. case PAR_EXPIRATION_TIMEOUT:
  1751. global_params.expiration_timeout = u.i;
  1752. break;
  1753. case PAR_TTL:
  1754. global_params.ttl = u.i;
  1755. break;
  1756. case PAR_LEARNING_TIMEOUT:
  1757. global_params.learning_timeout = u.i;
  1758. break;
  1759. case PAR_ALWAYS_LEARN:
  1760. global_params.always_learn = u.i;
  1761. break;
  1762. case PAR_SWITCHBOARD_A:
  1763. case PAR_SWITCHBOARD_B:
  1764. if (!(global_params.switchboard[dir] = find_switchboard(&u.s, NULL)))
  1765. return -1;
  1766. break;
  1767. case PAR_SWITCHBOARD_BY_SIP_IP_A:
  1768. case PAR_SWITCHBOARD_BY_SIP_IP_B:
  1769. ip = s2ip4(&u.s);
  1770. for (global_params.switchboard[dir] = switchboards;
  1771. global_params.switchboard[dir];
  1772. global_params.switchboard[dir] = global_params.switchboard[dir]->next) {
  1773. if (ip == global_params.switchboard[dir]->sip_ip) {
  1774. global_params.aggregation[dir] = NULL; /* invalidate aggregation */
  1775. return 1;
  1776. }
  1777. }
  1778. return -1;
  1779. case PAR_AGGREGATION_A:
  1780. case PAR_AGGREGATION_B:
  1781. if (!(global_params.aggregation[dir] = find_aggregation(&u.s, NULL)))
  1782. return -1;
  1783. break;
  1784. case PAR_AGGREGATION_BY_SIP_IP_A:
  1785. case PAR_AGGREGATION_BY_SIP_IP_B:
  1786. ip = s2ip4(&u.s);
  1787. for (global_params.aggregation[dir] = aggregations;
  1788. global_params.aggregation[dir];
  1789. global_params.aggregation[dir] = global_params.aggregation[dir]->next) {
  1790. if (ip == global_params.aggregation[dir]->sip_ip) {
  1791. global_params.switchboard[dir] = NULL; /* invalidate switchboard */
  1792. return 1;
  1793. }
  1794. }
  1795. return -1;
  1796. case PAR_THROTTLE_MARK:
  1797. global_params.throttle.mark = u.i;
  1798. break;
  1799. case PAR_THROTTLE_RTP_MAX_BYTES:
  1800. case PAR_THROTTLE_RTCP_MAX_BYTES:
  1801. global_params.throttle.bandwidth[param_list[idx].id==PAR_THROTTLE_RTCP_MAX_BYTES].bytes = u.i;
  1802. break;
  1803. case PAR_THROTTLE_RTP_MAX_PACKETS:
  1804. case PAR_THROTTLE_RTCP_MAX_PACKETS:
  1805. global_params.throttle.bandwidth[param_list[idx].id==PAR_THROTTLE_RTCP_MAX_PACKETS].packets = u.i;
  1806. break;
  1807. case PAR_CODEC_SET:
  1808. if (!(global_params.codec_set = find_codec_set(&u.s, NULL)))
  1809. return -1;
  1810. break;
  1811. case PAR_REMOVE_CODEC_MASK:
  1812. global_params.remove_codec_mask = u.i;
  1813. break;
  1814. case PAR_OLINE_USER: {
  1815. static char buf[30];
  1816. if (u.s.len > sizeof(buf)) {
  1817. return -1;
  1818. }
  1819. global_params.oline_user.len = u.s.len;
  1820. if (u.s.len) {
  1821. memcpy(buf, u.s.s, u.s.len);
  1822. global_params.oline_user.s = buf;
  1823. }
  1824. break;
  1825. }
  1826. case PAR_OLINE_ADDR: {
  1827. static char buf[30];
  1828. if (u.s.len > sizeof(buf)) {
  1829. return -1;
  1830. }
  1831. global_params.oline_addr.len = u.s.len;
  1832. if (u.s.len) {
  1833. memcpy(buf, u.s.s, u.s.len);
  1834. global_params.oline_addr.s = buf;
  1835. }
  1836. break;
  1837. }
  1838. case PAR_PROTECTED_SESSION_IDS:
  1839. memset(&global_params.protected_sess, 0, sizeof(global_params.protected_sess));
  1840. if (!u.s.len) break;
  1841. if (unserialize_ipt_session(&u.s, &global_params.protected_sess) < 0) {
  1842. return -1;
  1843. }
  1844. if (!global_params.protected_sess.session_count) {
  1845. global_params.protected_sess.switchboard = NULL;
  1846. }
  1847. break;
  1848. default:
  1849. ;
  1850. }
  1851. return 1;
  1852. }
  1853. /* @select implementation */
  1854. static int sel_rtpproxy(str* res, select_t* s, struct sip_msg* msg) { /* dummy */
  1855. union {int i; str s;} u;
  1856. int dir, idx;
  1857. u.s.len = 0;
  1858. if (msg == NULL && res == NULL) {
  1859. /* fixup call */
  1860. int idx;
  1861. idx = param2idx(&s->params[1].v.s, PAR_READ);
  1862. if (idx < 0) {
  1863. return -1;
  1864. }
  1865. s->params[1].v.i = idx;
  1866. s->params[1].type = SEL_PARAM_DIV;
  1867. return 1;
  1868. }
  1869. idx = s->params[1].v.i;
  1870. dir = (param_list[idx].flags & PAR_DIR) != 0;
  1871. switch (param_list[idx].id) {
  1872. case PAR_EXPIRATION_TIMEOUT:
  1873. u.i = global_params.expiration_timeout;
  1874. break;
  1875. case PAR_TTL:
  1876. u.i = global_params.ttl;
  1877. break;
  1878. case PAR_LEARNING_TIMEOUT:
  1879. u.i = global_params.learning_timeout;
  1880. break;
  1881. case PAR_ALWAYS_LEARN:
  1882. u.i = global_params.always_learn;
  1883. break;
  1884. case PAR_SWITCHBOARD_A:
  1885. case PAR_SWITCHBOARD_B:
  1886. if (global_params.switchboard[dir])
  1887. u.s = global_params.switchboard[dir]->name;
  1888. break;
  1889. case PAR_AGGREGATION_A:
  1890. case PAR_AGGREGATION_B:
  1891. if (global_params.aggregation[dir])
  1892. u.s = global_params.aggregation[dir]->name;
  1893. break;
  1894. case PAR_SDP_IP:
  1895. u.s = global_params.sdp_ip;
  1896. break;
  1897. case PAR_ACTIVE_MEDIA_NUM: {
  1898. int i;
  1899. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1900. u.i = 0;
  1901. for (i = 0; i < global_sdp_sess.media_count; i++) {
  1902. if (global_sdp_sess.media[i].active) {
  1903. u.i++;
  1904. }
  1905. }
  1906. break;
  1907. }
  1908. case PAR_OLINE_USER:
  1909. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1910. u.s = global_sdp_sess.oline_user_s;
  1911. break;
  1912. case PAR_OLINE_ADDR:
  1913. if (check_parse_sdp_content(msg, &global_sdp_sess) < 0) return -1;
  1914. u.s = global_sdp_sess.oline_addr_s;
  1915. break;
  1916. case PAR_SESSION_IDS:
  1917. u.s = global_params.session_ids;
  1918. break;
  1919. case PAR_THROTTLE_MARK:
  1920. u.i = global_params.throttle.mark;
  1921. break;
  1922. case PAR_THROTTLE_RTP_MAX_BYTES:
  1923. case PAR_THROTTLE_RTCP_MAX_BYTES:
  1924. u.i = global_params.throttle.bandwidth[param_list[idx].id==PAR_THROTTLE_RTCP_MAX_BYTES].bytes;
  1925. break;
  1926. case PAR_THROTTLE_RTP_MAX_PACKETS:
  1927. case PAR_THROTTLE_RTCP_MAX_PACKETS:
  1928. u.i = global_params.throttle.bandwidth[param_list[idx].id==PAR_THROTTLE_RTCP_MAX_PACKETS].packets;
  1929. break;
  1930. case PAR_CODEC_SET:
  1931. if (global_params.codec_set)
  1932. u.s = global_params.codec_set->name;
  1933. break;
  1934. case PAR_AUTH_RIGHTS:
  1935. u.i = global_params.auth_rights;
  1936. break;
  1937. case PAR_REMOVE_CODEC_MASK:
  1938. u.i = global_params.remove_codec_mask;
  1939. break;
  1940. default:
  1941. ;
  1942. }
  1943. if (param_list[idx].flags & PAR_STR) {
  1944. if (!u.s.len) return 1;
  1945. *res = u.s;
  1946. }
  1947. else {
  1948. return uint_to_static_buffer(res, u.i);
  1949. }
  1950. return 0;
  1951. }
  1952. select_row_t sel_declaration[] = {
  1953. { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_rtpproxy, CONSUME_NEXT_STR | FIXUP_CALL },
  1954. { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
  1955. };
  1956. static int mod_pre_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
  1957. memset(&global_params, 0, sizeof(global_params));
  1958. global_params.always_learn = -1;
  1959. global_params.ttl = -1;
  1960. sdp_parsed = 999; /* any number not in (-1,0) */
  1961. return 1;
  1962. }
  1963. static struct {
  1964. enum {iptrtpproxy_default=0x01, iptrtpproxy_switchboard=0x02, iptrtpproxy_host=0x04} flag;
  1965. str name;
  1966. struct {
  1967. struct {
  1968. struct xt_rtpproxy_switchboard_id addr;
  1969. str host;
  1970. } switchboard;
  1971. struct xt_rtpproxy_connection_rpc_params host;
  1972. } dflt, parsed;
  1973. } parse_config_vals;
  1974. static int cfg_parse_addr(void* param, cfg_parser_t* st, unsigned int flags) {
  1975. str val;
  1976. char buff[50];
  1977. val.s = buff;
  1978. val.len = sizeof(buff)-1;
  1979. if (cfg_parse_str(&val, st, CFG_EXTENDED_ALPHA|CFG_STR_STATIC) < 0) return -1;
  1980. *(uint32_t*)param = s2ip4(&val);
  1981. if (*(uint32_t*)param == 0) {
  1982. ERR(MODULE_NAME": parse_addr: bad ip address '%.*s'\n", STR_FMT(&val));
  1983. return -1;
  1984. }
  1985. return 0;
  1986. }
  1987. static int cfg_parse_uint16(void* param, cfg_parser_t* st, unsigned int flags) {
  1988. int val;
  1989. if (cfg_parse_int(&val, st, 0) < 0)
  1990. return -1;
  1991. *(uint16_t *) param = val;
  1992. return 0;
  1993. }
  1994. static int cfg_parse_default(void* param, cfg_parser_t* st, unsigned int flags) {
  1995. int ret;
  1996. cfg_token_t t;
  1997. str val, tok;
  1998. cfg_option_t* opt;
  1999. char buf[MAX_TOKEN_LEN];
  2000. tok.s = buf;
  2001. if (st->cur_opt->val.len >= sizeof(buf)-1) goto skip;
  2002. memcpy(tok.s, st->cur_opt->val.s, st->cur_opt->val.len);
  2003. tok.len = st->cur_opt->val.len;
  2004. /* we need process here options containing dash '-' because of too strict parser */
  2005. while (1) {
  2006. ret = cfg_get_token(&t, st, 0);
  2007. if (ret < 0) return ret;
  2008. if (ret > 0) return 0;
  2009. if (t.type == '=')
  2010. break;
  2011. if (tok.len+t.val.len >= sizeof(buf)-1) goto skip;
  2012. memcpy(tok.s+tok.len, t.val.s, t.val.len);
  2013. tok.len += t.val.len;
  2014. }
  2015. tok.s[tok.len] = '\0';
  2016. if ((opt = cfg_lookup_token(st->options+1/*2nd pass*/, &tok)) && ((opt->flags & CFG_DEFAULT)== 0)) {
  2017. st->cur_opt = &t;
  2018. if (opt->f(opt->param, st, opt->flags) < 0) return -1;
  2019. return 0;
  2020. }
  2021. skip:
  2022. if (cfg_parse_str(&val, st, CFG_EXTENDED_ALPHA) < 0) return -1;
  2023. return 0;
  2024. }
  2025. static int safe_parsed_values() {
  2026. #define PROC_DEFAULT(_f_, _def_) \
  2027. if (!parse_config_vals.parsed._f_) {\
  2028. parse_config_vals.parsed._f_ = parse_config_vals.dflt._f_?parse_config_vals.dflt._f_:_def_; \
  2029. }
  2030. if (parse_config_vals.flag & iptrtpproxy_default) {
  2031. if (parse_config_vals.flag & iptrtpproxy_switchboard)
  2032. parse_config_vals.dflt.switchboard = parse_config_vals.parsed.switchboard;
  2033. else if (parse_config_vals.flag & iptrtpproxy_host)
  2034. parse_config_vals.dflt.host = parse_config_vals.parsed.host;
  2035. } else if (parse_config_vals.flag) {
  2036. int fl, max_len, i;
  2037. struct switchboard_item **prev_si = NULL;
  2038. struct host_item **prev_hi = NULL;
  2039. char *s;
  2040. if (parse_config_vals.flag & iptrtpproxy_switchboard) {
  2041. fl = find_switchboard(&parse_config_vals.name, &prev_si) != NULL;
  2042. s = "switchboard";
  2043. max_len = MAX_SWITCHBOARD_NAME_LEN;
  2044. }
  2045. else {
  2046. struct host_item *p;
  2047. p = find_host(&parse_config_vals.name, &prev_hi);
  2048. fl = p != NULL;
  2049. s = "host";
  2050. max_len = HOST_NAME_MAX;
  2051. if (p && p->local) {
  2052. pkg_free(parse_config_vals.name.s);
  2053. goto local;
  2054. }
  2055. }
  2056. if (fl) {
  2057. ERR(MODULE_NAME": safe_parsed_values: %s name '%.*s' already declared\n", s, STR_FMT(&parse_config_vals.name));
  2058. return -1;
  2059. }
  2060. for (i=0; i<parse_config_vals.name.len; i++) {
  2061. if (!is_alpha(parse_config_vals.name.s[i])) {
  2062. ERR(MODULE_NAME": safe_parsed_values: bad %s name '%.*s'\n", s, STR_FMT(&parse_config_vals.name));
  2063. return -1;
  2064. }
  2065. }
  2066. if (parse_config_vals.name.len > max_len) {
  2067. ERR(MODULE_NAME": safe_parsed_values: %s name '%.*s' is too long (%d>%d)\n", s, STR_FMT(&parse_config_vals.name), parse_config_vals.name.len, max_len);
  2068. return -1;
  2069. }
  2070. if (parse_config_vals.flag & iptrtpproxy_switchboard) {
  2071. struct switchboard_item *si;
  2072. si = pkg_malloc(sizeof(*si));
  2073. if (!si) goto out_of_mem;
  2074. memset(si, 0, sizeof(*si));
  2075. si->name = parse_config_vals.name;
  2076. si->next = (*prev_si);
  2077. (*prev_si) = si;
  2078. PROC_DEFAULT(switchboard.addr.ip, 0);
  2079. PROC_DEFAULT(switchboard.addr.port, 0);
  2080. if (parse_config_vals.parsed.switchboard.host.len) {
  2081. si->hostname = parse_config_vals.parsed.switchboard.host;
  2082. }
  2083. else {
  2084. si->hostname = parse_config_vals.dflt.switchboard.host;
  2085. }
  2086. if (!si->hostname.len) {
  2087. si->hostname.s = iptrtpproxy_cfg_hostname;
  2088. si->hostname.len = strlen(si->hostname.s);
  2089. }
  2090. si->switchboard_addr = parse_config_vals.parsed.switchboard.addr;
  2091. }
  2092. else {
  2093. struct host_item *hi;
  2094. hi = pkg_malloc(sizeof(*hi));
  2095. if (!hi) goto out_of_mem;
  2096. memset(hi, 0, sizeof(*hi));
  2097. hi->name = parse_config_vals.name;
  2098. hi->next = (*prev_hi);
  2099. (*prev_hi) = hi;
  2100. PROC_DEFAULT(host.addr, 0);
  2101. PROC_DEFAULT(host.port, 0);
  2102. PROC_DEFAULT(host.request_size, XT_RTPPROXY_RPC_DEFAULT_REQUEST_SIZE);
  2103. PROC_DEFAULT(host.reply_size, XT_RTPPROXY_RPC_DEFAULT_REPLY_SIZE);
  2104. PROC_DEFAULT(host.total_timeout, XT_RTPPROXY_RPC_DEFAULT_TOTAL_TIMEOUT);
  2105. PROC_DEFAULT(host.udp_retry_timeout, XT_RTPPROXY_RPC_DEFAULT_UDP_REPLY_TIMEOUT);
  2106. hi->rpc_params = parse_config_vals.parsed.host;
  2107. }
  2108. }
  2109. local:
  2110. memset(&parse_config_vals.parsed, 0, sizeof(parse_config_vals.parsed));
  2111. memset(&parse_config_vals.name, 0, sizeof(parse_config_vals.name));
  2112. return 0;
  2113. out_of_mem:
  2114. ERR(MODULE_NAME": safe_parsed_values: not enough pkg memory\n");
  2115. return -1;
  2116. }
  2117. static cfg_option_t section_switchboard_options[] = {
  2118. /* 1st pass */
  2119. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default},
  2120. /* 2nd pass */
  2121. {"addr", .f = cfg_parse_addr, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.switchboard.addr.ip},
  2122. {"port", .f = cfg_parse_uint16, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.switchboard.addr.port},
  2123. {"host", .f = cfg_parse_str, .flags = CFG_CASE_SENSITIVE|CFG_STR_PKGMEM, .param = &parse_config_vals.parsed.switchboard.host},
  2124. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default}
  2125. };
  2126. static cfg_option_t protos[] = {
  2127. {"udp", .param = &parse_config_vals.parsed.host.proto, .val = xt_rtpproxy_connection_UDP},
  2128. {"tcp", .param = &parse_config_vals.parsed.host.proto, .val = xt_rtpproxy_connection_TCP},
  2129. {NULL, .flags = 0}
  2130. };
  2131. static cfg_option_t section_host_options[] = {
  2132. /* 1st pass */
  2133. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default},
  2134. /* 2nd pass */
  2135. {"rpc-addr", .f = cfg_parse_addr, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.addr},
  2136. {"rpc-port", .f = cfg_parse_uint16, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.port},
  2137. {"rpc-proto", .f = cfg_parse_enum, .flags = CFG_CASE_SENSITIVE, .param = protos},
  2138. {"rpc-request-size", .f = cfg_parse_int, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.request_size},
  2139. {"rpc-reply-size", .f = cfg_parse_int, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.reply_size},
  2140. {"rpc-total-timeout", .f = cfg_parse_int, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.total_timeout},
  2141. {"rpc-udp-retry-timeout", .f = cfg_parse_int, .flags = CFG_CASE_SENSITIVE, .param = &parse_config_vals.parsed.host.udp_retry_timeout},
  2142. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default}
  2143. };
  2144. static cfg_option_t section_dummy_options[] = {
  2145. /* 1st pass */
  2146. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default},
  2147. /* 2nd pass */
  2148. {NULL, .flags = CFG_DEFAULT, .f = cfg_parse_default}
  2149. };
  2150. #define DEFAULT_SECTION "default"
  2151. #define SWITCHBOARD_PREFIX "switchboard"
  2152. #define HOST_PREFIX "host"
  2153. static int parse_section_name(void* param, cfg_parser_t* st, unsigned int flags) {
  2154. cfg_token_t t;
  2155. int ret, fl;
  2156. ret = safe_parsed_values();
  2157. if (ret != 0) return ret;
  2158. cfg_set_options(st, section_dummy_options);
  2159. ret = cfg_get_token(&t, st, 0);
  2160. if (ret != 0) return ret;
  2161. if (t.type != CFG_TOKEN_ALPHA)
  2162. goto skip;
  2163. if (t.val.len == (sizeof(DEFAULT_SECTION)-1) && strncmp(t.val.s, DEFAULT_SECTION, t.val.len) == 0)
  2164. fl = iptrtpproxy_default;
  2165. else if (t.val.len == (sizeof(SWITCHBOARD_PREFIX)-1) && strncmp(t.val.s, SWITCHBOARD_PREFIX, t.val.len) == 0) {
  2166. fl = iptrtpproxy_switchboard;
  2167. } else if (t.val.len == (sizeof(HOST_PREFIX)-1) && strncmp(t.val.s, HOST_PREFIX, t.val.len) == 0) {
  2168. fl = iptrtpproxy_host;
  2169. }
  2170. else
  2171. goto skip;
  2172. ret = cfg_get_token(&t, st, 0);
  2173. if (ret != 0) return ret;
  2174. if (t.type != ':')
  2175. goto skip;
  2176. ret = cfg_parse_section(&parse_config_vals.name, st, CFG_STR_PKGMEM);
  2177. if (ret != 0) return ret;
  2178. if (fl==iptrtpproxy_default) {
  2179. if (parse_config_vals.name.len == (sizeof(SWITCHBOARD_PREFIX)-1) && strncmp(parse_config_vals.name.s, SWITCHBOARD_PREFIX, parse_config_vals.name.len) == 0) {
  2180. fl |= iptrtpproxy_switchboard;
  2181. }
  2182. else if (parse_config_vals.name.len == (sizeof(HOST_PREFIX)-1) && strncmp(parse_config_vals.name.s, HOST_PREFIX, parse_config_vals.name.len) == 0) {
  2183. fl |= iptrtpproxy_host;
  2184. }
  2185. else {
  2186. goto skip;
  2187. }
  2188. if (parse_config_vals.name.s) {
  2189. pkg_free(parse_config_vals.name.s);
  2190. parse_config_vals.name.s = NULL;
  2191. }
  2192. }
  2193. cfg_set_options(st, section_dummy_options);
  2194. if (fl) {
  2195. if (fl & iptrtpproxy_switchboard) {
  2196. cfg_set_options(st, section_switchboard_options);
  2197. } else if (fl & iptrtpproxy_host) {
  2198. cfg_set_options(st, section_host_options);
  2199. }
  2200. parse_config_vals.flag = fl;
  2201. }
  2202. return 0;
  2203. skip:
  2204. while (t.type != ']') {
  2205. ret = cfg_get_token(&t, st, 0);
  2206. if (ret != 0) return ret;
  2207. }
  2208. return cfg_eat_eol(st, 0);
  2209. }
  2210. static int parse_iptrtpproxy_cfg() {
  2211. cfg_parser_t* parser = NULL;
  2212. static char buf[HOST_NAME_MAX+1];
  2213. struct switchboard_item *si;
  2214. if (!iptrtpproxy_cfg_hostname || !strlen(iptrtpproxy_cfg_hostname)) {
  2215. if (gethostname(buf, sizeof(buf)-1) < 0) {
  2216. ERR(MODULE_NAME"parse_iptrtpproxy_cfg: gethostname error\n");
  2217. return E_CFG;
  2218. }
  2219. iptrtpproxy_cfg_hostname = buf;
  2220. }
  2221. hosts = pkg_malloc(sizeof(*hosts));
  2222. if (!hosts) return -1;
  2223. memset(hosts, 0, sizeof(*hosts));
  2224. hosts->name.s = iptrtpproxy_cfg_hostname;
  2225. hosts->name.len = strlen(hosts->name.s);
  2226. hosts->local = 1;
  2227. if ((parser = cfg_parser_init(0, &iptrtpproxy_cfg_filename)) == NULL) {
  2228. ERR(MODULE_NAME"parse_iptrtpproxy_cfg: Error while initializing configuration file parser.\n");
  2229. return -1;
  2230. }
  2231. cfg_section_parser(parser, parse_section_name, NULL);
  2232. memset(&parse_config_vals, 0, sizeof(parse_config_vals));
  2233. if (sr_cfg_parse(parser)) {
  2234. return -1;
  2235. }
  2236. cfg_parser_close(parser);
  2237. if (safe_parsed_values() < 0) {
  2238. return -1;
  2239. }
  2240. for (si = switchboards; si; si = si->next) {
  2241. si->host = find_host(&si->hostname, NULL);
  2242. if (!si->host) {
  2243. ERR(MODULE_NAME"parse_iptrtpproxy_cfg: host '%.*s' not found.\n", STR_FMT(&si->hostname));
  2244. return -1;
  2245. }
  2246. si->sip_ip = si->switchboard_addr.ip;
  2247. }
  2248. return 0;
  2249. }
  2250. static struct {
  2251. char *name;
  2252. int payload_type;
  2253. unsigned int media_type;
  2254. int clock_rate;
  2255. int channels;
  2256. } def_codecs [] = {
  2257. {"PCMU", 0, 1<<sdpmtAudio, 8000, 1},
  2258. {"GSM", 3, 1<<sdpmtAudio, 8000, 1},
  2259. {"G723", 4, 1<<sdpmtAudio, 8000, 1},
  2260. {"DVI4", 5, 1<<sdpmtAudio, 8000, 1},
  2261. {"DVI4", 6, 1<<sdpmtAudio, 16000, 1},
  2262. {"LPC", 7, 1<<sdpmtAudio, 8000, 1},
  2263. {"PCMA", 8, 1<<sdpmtAudio, 8000, 1},
  2264. {"G722", 9, 1<<sdpmtAudio, 8000, 1},
  2265. {"L16", 10, 1<<sdpmtAudio, 44100, 2},
  2266. {"L16", 11, 1<<sdpmtAudio, 44100, 1},
  2267. {"QCELP", 12, 1<<sdpmtAudio, 8000, 1},
  2268. {"CN", 13, 1<<sdpmtAudio, 8000, 1},
  2269. {"MPA", 14, 1<<sdpmtAudio, 90000},
  2270. {"G728", 15, 1<<sdpmtAudio, 8000, 1},
  2271. {"DVI4", 16, 1<<sdpmtAudio, 11025, 1},
  2272. {"DVI4", 17, 1<<sdpmtAudio, 22050, 1},
  2273. {"G729", 18, 1<<sdpmtAudio, 8000, 1},
  2274. {"CelB", 25, 1<<sdpmtVideo, 90000},
  2275. {"JPEG", 26, 1<<sdpmtVideo, 90000},
  2276. {"nv", 28, 1<<sdpmtVideo, 90000},
  2277. {"H261", 31, 1<<sdpmtVideo, 90000},
  2278. {"MPV", 32, 1<<sdpmtVideo, 90000},
  2279. {"MP2T", 33, 1<<sdpmtAudio | 1<<sdpmtVideo, 90000},
  2280. {"H263", 34, 1<<sdpmtVideo, 90000},
  2281. {"telephone-event", -1, 1<<sdpmtAudio},
  2282. {"tone", -1, 1<<sdpmtAudio},
  2283. {"red", -1, 1<<sdpmtAudio|1<<sdpmtText},
  2284. {"rtx", -1, 1<<sdpmtAudio|1<<sdpmtVideo|1<<sdpmtApplication|1<<sdpmtText},
  2285. {"parityfec", -1, 1<<sdpmtAudio|1<<sdpmtVideo|1<<sdpmtApplication|1<<sdpmtText},
  2286. {"t140c", -1, 1<<sdpmtAudio},
  2287. {"t38", -1, 1<<sdpmtAudio},
  2288. {"AMR", -1, 1<<sdpmtAudio, 8000},
  2289. {"AMR-WB", -1, 1<<sdpmtAudio, 16000},
  2290. {"L8", -1, 1<<sdpmtAudio},
  2291. {"L20", -1, 1<<sdpmtAudio},
  2292. {"L24", -1, 1<<sdpmtAudio},
  2293. {"DAT12", -1, 1<<sdpmtAudio},
  2294. {"raw", -1, 1<<sdpmtVideo},
  2295. {"pointer", -1, 1<<sdpmtVideo},
  2296. /* etc.*/
  2297. {NULL}
  2298. };
  2299. static int declare_def_codecs() {
  2300. int codec_id, i;
  2301. i = 0;
  2302. while (def_codecs[i].name) {
  2303. str s;
  2304. s.s = def_codecs[i].name;
  2305. s.len = strlen(s.s);
  2306. codec_id = register_codec(&s);
  2307. if (codec_id < 0) return codec_id;
  2308. i++;
  2309. }
  2310. return 0;
  2311. }
  2312. /* module initialization */
  2313. static int mod_init(void) {
  2314. struct switchboard_item *si;
  2315. struct aggregation_item *ai;
  2316. struct host_item *hi;
  2317. struct codec_set_item *ci;
  2318. int i;
  2319. if (iptrtpproxy_cfg_flag <= 1) {
  2320. if (parse_iptrtpproxy_cfg() < 0)
  2321. return E_CFG;
  2322. }
  2323. for (si = switchboards; si; si=si->next) {
  2324. str ips[2];
  2325. char buf1[17];
  2326. si->stat = shm_malloc(sizeof(*si->stat));
  2327. if (!si->stat) return E_OUT_OF_MEM;
  2328. memset(si->stat, 0, sizeof(*si->stat));
  2329. ip42s(si->switchboard_addr.ip, ips+0);
  2330. strncpy(buf1, ips[0].s, sizeof(buf1)-1);
  2331. ips[0].s = buf1;
  2332. ip42s(si->sip_ip, ips+1);
  2333. INFO(MODULE_NAME": mod_init: switchboard_name=%.*s;addr=%.*s;port=%d;sip-addr=%.*s;hostname=%.*s\n",
  2334. STR_FMT(&si->name),
  2335. STR_FMT(ips+0),
  2336. si->switchboard_addr.port,
  2337. STR_FMT(ips+1),
  2338. STR_FMT(&si->hostname)
  2339. );
  2340. }
  2341. for (ai = aggregations; ai; ai=ai->next) {
  2342. str ips[1];
  2343. ip42s(ai->sip_ip, ips+0);
  2344. INFO(MODULE_NAME": mod_init: aggregation '%.*s';sip-addr=%.*s\n",
  2345. STR_FMT(&ai->name),
  2346. STR_FMT(ips+0)
  2347. );
  2348. for (i=0; i<ai->switchboard_count; i++) {
  2349. ERR(MODULE_NAME": mod_init: '%.*s'\n", STR_FMT(&(*ai->switchboards)[i]->name));
  2350. }
  2351. }
  2352. for (hi = hosts; hi; hi=hi->next) {
  2353. str ips;
  2354. hi->stat = shm_malloc(sizeof(*hi->stat));
  2355. if (!hi->stat) return E_OUT_OF_MEM;
  2356. memset(hi->stat, 0, sizeof(*hi->stat));
  2357. ip42s(hi->rpc_params.addr, &ips);
  2358. INFO(MODULE_NAME": mod_init: host_name=%.*s;rpc-addr=%.*s;rpc-port=%d;rpc-proto=%d,request-size=%d,reply-size=%d,total-timeout=%d,udp-retry-timeout=%d\n",
  2359. STR_FMT(&hi->name),
  2360. STR_FMT(&ips),
  2361. hi->rpc_params.port,
  2362. hi->rpc_params.proto,
  2363. hi->rpc_params.request_size,
  2364. hi->rpc_params.reply_size,
  2365. hi->rpc_params.total_timeout,
  2366. hi->rpc_params.udp_retry_timeout
  2367. );
  2368. }
  2369. if (!reg_codecs) {
  2370. int r;
  2371. if ((r = declare_def_codecs()) < 0) {
  2372. return r;
  2373. }
  2374. }
  2375. memset(&fixed_payload_types, 0, sizeof(fixed_payload_types));
  2376. i = 0;
  2377. while (def_codecs[i].name && def_codecs[i].payload_type >= 0) {
  2378. str s;
  2379. int codec_id;
  2380. s.s = def_codecs[i].name;
  2381. s.len = strlen(s.s);
  2382. codec_id = name2codec_id(&s, NULL);
  2383. if (!codec_id) {
  2384. BUG(MODULE_NAME": mod_init: def.codec '%s' not found\n", s.s);
  2385. return -1;
  2386. }
  2387. fixed_payload_types[def_codecs[i].payload_type].codec_id = codec_id;
  2388. i++;
  2389. }
  2390. #if 0
  2391. for (i=0; i<MAX_FIXED_PAYLOAD_TYPES; i++) {
  2392. if (fixed_payload_types[i].codec_id) {
  2393. INFO(MODULE_NAME": mod_init: payload_type=%d, codec_name='%.*s'\n", i, STR_FMT(&(*reg_codecs)[fixed_payload_types[i].codec_id-1].name));
  2394. }
  2395. }
  2396. for (i=0; i<reg_codec_count; i++) {
  2397. INFO(MODULE_NAME": mod_init: codec_id=%d, codec_name='%.*s'\n", i+1, STR_FMT(&(*reg_codecs)[i].name));
  2398. }
  2399. #endif
  2400. for (ci = codec_sets; ci; ci=ci->next) {
  2401. int media_type;
  2402. INFO(MODULE_NAME": mod_init: codec_set='%.*s'\n", STR_FMT(&ci->name));
  2403. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2404. INFO(MODULE_NAME": mod_init: media_type='%.*s';max_streams=%d;rtp_bytes=%d;rtcp_bytes=%d;rtp_packets=%d;rtcp_packets=%d\n",
  2405. STR_FMT(sdp_media_types_str+media_type),
  2406. ci->media_types[media_type].throttle.max_streams,
  2407. ci->media_types[media_type].throttle.bandwidth[0].bytes,
  2408. ci->media_types[media_type].throttle.bandwidth[1].bytes,
  2409. ci->media_types[media_type].throttle.bandwidth[0].packets,
  2410. ci->media_types[media_type].throttle.bandwidth[1].packets
  2411. );
  2412. if (ci->media_types[media_type].throttle.max_streams != 0) {
  2413. for (i=0; i<reg_codec_count; i++) {
  2414. if ((*ci->media_types[media_type].codec_rights)[i] > 0) {
  2415. if (i > 0)
  2416. INFO(MODULE_NAME": mod_init: codec='%.*s', right=%d\n", STR_FMT(&(*reg_codecs)[i-1].name), (*ci->media_types[media_type].codec_rights)[i]);
  2417. else
  2418. INFO(MODULE_NAME": mod_init: codec='?', right=%d\n", (*ci->media_types[media_type].codec_rights)[i]);
  2419. }
  2420. }
  2421. }
  2422. }
  2423. }
  2424. /*register_script_cb(mod_pre_script_cb, REQ_TYPE_CB | RPL_TYPE_CB| PRE_SCRIPT_CB, 0);*/
  2425. register_script_cb(mod_pre_script_cb, REQUEST_CB | ONREPLY_CB| PRE_SCRIPT_CB, 0);
  2426. register_select_table(sel_declaration);
  2427. return 0;
  2428. }
  2429. static void mod_cleanup(void) {
  2430. struct host_item *hi;
  2431. struct switchboard_item *si;
  2432. for (si = switchboards; si; si = si->next) {
  2433. if (si->stat) {
  2434. shm_free(si->stat);
  2435. si->stat = NULL;
  2436. }
  2437. }
  2438. for (hi = hosts; hi; hi = hi->next) {
  2439. if (hi->handle_is_opened) {
  2440. xt_RTPPROXY_close(&hi->handle);
  2441. hi->handle_is_opened = 0;
  2442. }
  2443. if (hi->stat) {
  2444. shm_free(hi->stat);
  2445. hi->stat = NULL;
  2446. }
  2447. }
  2448. }
  2449. static int child_init(int rank) {
  2450. return 0;
  2451. }
  2452. #define eat_spaces(_p) \
  2453. while( *(_p)==' ' || *(_p)=='\t' ){\
  2454. (_p)++;}
  2455. static int declare_config(modparam_t type, void* val) {
  2456. if (!val) return 0;
  2457. if (iptrtpproxy_cfg_flag <= 1) {
  2458. iptrtpproxy_cfg_flag = 2;
  2459. iptrtpproxy_cfg_filename = * (str*) val;
  2460. if (parse_iptrtpproxy_cfg() == 0)
  2461. return 0;
  2462. }
  2463. else {
  2464. switch (iptrtpproxy_cfg_flag) {
  2465. case 2:
  2466. ERR(MODULE_NAME": declare_config: 'config' param may be used only once\n");
  2467. break;
  2468. case 3:
  2469. ERR(MODULE_NAME": declare_config: 'config' param may not be used after 'switchboard'\n");
  2470. break;
  2471. default:
  2472. BUG(MODULE_NAME": declare_config: unexpected 'iptrtpproxy_cfg_flag' value %d\n", iptrtpproxy_cfg_flag);
  2473. }
  2474. }
  2475. return E_CFG;
  2476. }
  2477. static int declare_hostname(modparam_t type, void* val) {
  2478. if (!val) return 0;
  2479. if (iptrtpproxy_cfg_flag == 0) {
  2480. iptrtpproxy_cfg_hostname = (char*) val;
  2481. return 0;
  2482. }
  2483. else {
  2484. switch (iptrtpproxy_cfg_flag) {
  2485. case 1:
  2486. ERR(MODULE_NAME": declare_hostname: 'hostname' param may be used only once\n");
  2487. break;
  2488. case 2:
  2489. case 3:
  2490. ERR(MODULE_NAME": declare_hostname: 'hostname' param may not be used after 'switchboard' or 'config'\n");
  2491. break;
  2492. default:
  2493. BUG(MODULE_NAME": declare_hostname: unexpected 'iptrtpproxy_cfg_flag' value %d\n", iptrtpproxy_cfg_flag);
  2494. }
  2495. }
  2496. return E_CFG;
  2497. }
  2498. struct parse_param_item {
  2499. char *name;
  2500. unsigned int id;
  2501. };
  2502. /* returns index to items, -1 if error or param not found */
  2503. static int parse_next_param(char **s, struct parse_param_item (*params)[], str *val) {
  2504. str p;
  2505. int i;
  2506. char *c;
  2507. eat_spaces(*s);
  2508. c = *s;
  2509. while ( is_alpha(*c) ) {
  2510. c++;
  2511. }
  2512. if (c == *s) {
  2513. ERR(MODULE_NAME": parse_next_param: param name expected near '%s'\n", *s);
  2514. return -1;
  2515. }
  2516. p.s = *s;
  2517. p.len = c-*s;
  2518. eat_spaces(c);
  2519. *s = c;
  2520. if (*c != '=') {
  2521. ERR(MODULE_NAME": parse_next_param: equal char expected near '%s'\n", *s);
  2522. return -1;
  2523. }
  2524. c++;
  2525. eat_spaces(c);
  2526. *s = c;
  2527. while (*c && *c != ';') c++;
  2528. val->s = *s;
  2529. val->len = c-*s;
  2530. while (val->len > 0 && val->s[val->len-1]<=' ') val->len--;
  2531. if (*c) c++;
  2532. eat_spaces(c);
  2533. *s = c;
  2534. for (i=0; (*params)[i].name; i++) {
  2535. if (strlen((*params)[i].name)==p.len && strncasecmp((*params)[i].name, p.s, p.len) == 0) {
  2536. return i;
  2537. }
  2538. }
  2539. ERR(MODULE_NAME": parse_next_param: unknown param name '%.*s'\n", STR_FMT(&p));
  2540. return -1;
  2541. }
  2542. static int declare_switchboard_param(modparam_t type, void* val) {
  2543. char *s;
  2544. int all_flag;
  2545. struct switchboard_item *si = NULL;
  2546. enum param_id {
  2547. par_Name = 0x000001,
  2548. par_Aggregation = 0x000002,
  2549. par_SipAddr = 0x000004
  2550. };
  2551. static struct parse_param_item params[] = {
  2552. {.name = "name", .id = par_Name},
  2553. {.name = "sip-addr", .id = par_SipAddr},
  2554. {.name = "aggregation", .id = par_Aggregation},
  2555. {.name = 0, .id = 0}
  2556. };
  2557. if (!val) return 0;
  2558. if (iptrtpproxy_cfg_flag <= 1) {
  2559. iptrtpproxy_cfg_flag = 3;
  2560. if (parse_iptrtpproxy_cfg() < 0)
  2561. return E_CFG;
  2562. }
  2563. s = val;
  2564. all_flag = -1;
  2565. eat_spaces(s);
  2566. if (!*s) return 0;
  2567. /* parse param: name=;aggregation=;sip-addr= */
  2568. while (*s) {
  2569. str val;
  2570. int idx;
  2571. idx = parse_next_param(&s, &params, &val);
  2572. if (idx < 0) goto err_E_CFG;
  2573. if (all_flag >= 0 && params[idx].id == par_Name) {
  2574. ERR(MODULE_NAME": declare_switchboard_param: name must be the first param\n");
  2575. goto err_E_CFG;
  2576. }
  2577. if (params[idx].id == par_Name) {
  2578. all_flag = 0;
  2579. si = find_switchboard(&val, NULL);
  2580. if (!si) {
  2581. if (val.len == 1 && val.s[0] == '*')
  2582. all_flag = 1;
  2583. else {
  2584. ERR(MODULE_NAME": declare_switchboard_param: switchboard '%.*s' not found\n", STR_FMT(&val));
  2585. goto err_E_CFG;
  2586. }
  2587. }
  2588. }
  2589. else {
  2590. if (all_flag)
  2591. si = switchboards;
  2592. while (si) {
  2593. switch (params[idx].id) {
  2594. case par_Name:
  2595. break;
  2596. case par_Aggregation: {
  2597. struct aggregation_item *ai;
  2598. struct aggregation_item **prev_ai;
  2599. int i;
  2600. ai = find_aggregation(&val, &prev_ai);
  2601. if (!ai) {
  2602. ai = pkg_malloc(sizeof(*ai));
  2603. if (!ai) return E_OUT_OF_MEM;
  2604. memset(ai, 0, sizeof(*ai));
  2605. ai->name = val;
  2606. ai->next = (*prev_ai);
  2607. (*prev_ai) = ai;
  2608. }
  2609. for (i=0; i<ai->switchboard_count; i++) {
  2610. if ((*ai->switchboards)[i] == si) goto aggr_found;
  2611. }
  2612. if (!ai->sip_ip) {
  2613. ai->sip_ip = si->sip_ip;
  2614. }
  2615. ai->switchboards = pkg_realloc(ai->switchboards, sizeof((*ai->switchboards)[0])*(ai->switchboard_count+1));
  2616. if (!ai->switchboards) return E_OUT_OF_MEM;
  2617. (*ai->switchboards)[ai->switchboard_count] = si;
  2618. ai->switchboard_count++;
  2619. aggr_found:
  2620. break;
  2621. }
  2622. case par_SipAddr:
  2623. si->sip_ip = s2ip4(&val);
  2624. if (si->sip_ip == 0) {
  2625. goto err_E_CFG;
  2626. }
  2627. break;
  2628. default:
  2629. BUG(MODULE_NAME": declare_switchboard_param: unknown id '%x\n", idx);
  2630. goto err_E_CFG;
  2631. }
  2632. if (!all_flag) break;
  2633. si = si->next;
  2634. }
  2635. }
  2636. }
  2637. if (all_flag) {
  2638. return 0;
  2639. }
  2640. switchboard_count++;
  2641. return 0;
  2642. err_E_CFG:
  2643. ERR(MODULE_NAME": declare_switchboard_param(#%d): parse error near \"%s\"\n", switchboard_count, s);
  2644. return E_CFG;
  2645. }
  2646. static int declare_codec(modparam_t type, void* val) {
  2647. int r;
  2648. str *s;
  2649. s = val;
  2650. if (!s || !s->len) return 0;
  2651. if (codec_sets) {
  2652. ERR(MODULE_NAME": declare_codec: codec declaration cannot follow codec set declaration\n");
  2653. return E_CFG;
  2654. }
  2655. if (!reg_codecs) {
  2656. int r;
  2657. if ((r = declare_def_codecs()) < 0) {
  2658. return r;
  2659. }
  2660. }
  2661. r = register_codec(s);
  2662. if (r < 0) return r;
  2663. return 0;
  2664. }
  2665. static int declare_codec_set(modparam_t type, void* val) {
  2666. char *s;
  2667. unsigned int cur_rights = 0;
  2668. unsigned int cur_media_type = 0;
  2669. struct codec_set_item *ci = NULL;
  2670. enum param_id {
  2671. par_Name = 0x000001,
  2672. par_Rights = 0x000002,
  2673. par_Codecs = 0x000003,
  2674. par_MediaType = 0x000004,
  2675. par_MaxStreams = 0x000005,
  2676. par_ThrottleRTPBytes = 0x000100,
  2677. par_ThrottleRTCPBytes = 0x000101,
  2678. par_ThrottleRTPPackets = 0x000200,
  2679. par_ThrottleRTCPPackets = 0x000201
  2680. };
  2681. static struct parse_param_item params[] = {
  2682. {.name = "name", .id = par_Name},
  2683. {.name = "media_type", .id = par_MediaType},
  2684. {.name = "rights", .id = par_Rights},
  2685. {.name = "codecs", .id = par_Codecs},
  2686. {.name = "max_streams", .id = par_MaxStreams},
  2687. {.name = "rtp_bytes", .id = par_ThrottleRTPBytes},
  2688. {.name = "rtcp_bytes", .id = par_ThrottleRTCPBytes},
  2689. {.name = "rtp_packets", .id = par_ThrottleRTPPackets},
  2690. {.name = "rtcp_packets", .id = par_ThrottleRTCPPackets},
  2691. {.name = 0, .id = 0}
  2692. };
  2693. if (!val) return 0;
  2694. if (!reg_codecs) {
  2695. int r;
  2696. if ((r = declare_def_codecs()) < 0) {
  2697. return r;
  2698. }
  2699. }
  2700. s = val;
  2701. eat_spaces(s);
  2702. if (!*s) return 0;
  2703. /* parse param: name=;media_type=audio,video;rights=<int>;codecs=<codec1>,<codec2>,..;max_streams=2 */
  2704. while (*s) {
  2705. str val;
  2706. int idx, media_type;
  2707. char *p, *pend;
  2708. struct codec_set_item **prev_ci;
  2709. idx = parse_next_param(&s, &params, &val);
  2710. if (idx < 0) return E_CFG;
  2711. if (params[idx].id != par_Name && !ci) {
  2712. ERR(MODULE_NAME": declare_codec_set: name must be the first param\n");
  2713. return E_CFG;
  2714. }
  2715. switch (params[idx].id) {
  2716. case par_Name:
  2717. ci = find_codec_set(&val, &prev_ci);
  2718. if (!ci) {
  2719. int media_type;
  2720. ci = pkg_malloc(sizeof(*ci));
  2721. if (!ci) return E_OUT_OF_MEM;
  2722. memset(ci, 0, sizeof(*ci));
  2723. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2724. ci->media_types[media_type].codec_rights = pkg_malloc(sizeof((*ci->media_types[media_type].codec_rights)[0])*(reg_codec_count+1));
  2725. if (!ci->media_types[media_type].codec_rights) return E_OUT_OF_MEM;
  2726. memset(ci->media_types[media_type].codec_rights, 0, sizeof((*ci->media_types[media_type].codec_rights)[0])*(reg_codec_count+1));
  2727. ci->media_types[media_type].throttle.max_streams = -1;
  2728. }
  2729. ci->name = val;
  2730. ci->next = (*prev_ci);
  2731. (*prev_ci) = ci;
  2732. }
  2733. break;
  2734. case par_MediaType:
  2735. cur_media_type = 0;
  2736. if (val.len == 1 && val.s[0] == '*') {
  2737. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2738. cur_media_type |= 1 << media_type;
  2739. }
  2740. }
  2741. else {
  2742. p = val.s;
  2743. pend = p + val.len;
  2744. while (p < pend) {
  2745. str s2;
  2746. s2.s = p;
  2747. while (p < pend && is_alpha(*p)) p++;
  2748. s2.len = p - s2.s;
  2749. cur_media_type |= 1 << name2media_type(&s2);
  2750. while (p < pend && !is_alpha(*p)) p++;
  2751. }
  2752. }
  2753. break;
  2754. case par_Rights:
  2755. val.s[val.len] = '\0'; /* we need not save value, it's already parsed */
  2756. cur_rights = atol(val.s);
  2757. break;
  2758. case par_MaxStreams:
  2759. val.s[val.len] = '\0'; /* we need not save value, it's already parsed */
  2760. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2761. if (cur_media_type & (1<<media_type)) {
  2762. ci->media_types[media_type].throttle.max_streams = atol(val.s);
  2763. }
  2764. }
  2765. break;
  2766. case par_ThrottleRTPBytes:
  2767. case par_ThrottleRTCPBytes:
  2768. val.s[val.len] = '\0'; /* we need not save value, it's already parsed */
  2769. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2770. if (cur_media_type & (1<<media_type)) {
  2771. ci->media_types[media_type].throttle.bandwidth[params[idx].id&1].bytes = atol(val.s);
  2772. }
  2773. }
  2774. break;
  2775. case par_ThrottleRTPPackets:
  2776. case par_ThrottleRTCPPackets:
  2777. val.s[val.len] = '\0'; /* we need not save value, it's already parsed */
  2778. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2779. if (cur_media_type & (1<<media_type)) {
  2780. ci->media_types[media_type].throttle.bandwidth[params[idx].id&1].packets = atol(val.s);
  2781. }
  2782. }
  2783. break;
  2784. case par_Codecs:
  2785. if (val.len == 1 && val.s[0] == '*') {
  2786. int codec_id;
  2787. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2788. if (cur_media_type & (1<<media_type)) {
  2789. for (codec_id=0; codec_id<reg_codec_count; codec_id++) {
  2790. (*ci->media_types[media_type].codec_rights)[codec_id] = cur_rights;
  2791. }
  2792. }
  2793. }
  2794. }
  2795. else {
  2796. p = val.s;
  2797. pend = p + val.len;
  2798. while (p < pend) {
  2799. str s2;
  2800. s2.s = p;
  2801. while (p < pend && is_alpha(*p)) p++;
  2802. s2.len = p - s2.s;
  2803. for (media_type=0; media_type<NUM_MEDIA_TYPES; media_type++) {
  2804. if (cur_media_type & (1<<media_type)) {
  2805. (*ci->media_types[media_type].codec_rights)[name2codec_id(&s2, NULL)] = cur_rights;
  2806. }
  2807. }
  2808. while (p < pend && !is_alpha(*p)) p++;
  2809. }
  2810. }
  2811. break;
  2812. default:
  2813. BUG(MODULE_NAME": declare_codec_set: unknown id '%x\n", params[idx].id);
  2814. return E_CFG;
  2815. }
  2816. }
  2817. return 0;
  2818. }
  2819. static cmd_export_t cmds[] = {
  2820. {MODULE_NAME "_alloc", rtpproxy_alloc, 1, rtpproxy_alloc_update_fixup, REQUEST_ROUTE | ONREPLY_ROUTE },
  2821. {MODULE_NAME "_update", rtpproxy_update, 2, rtpproxy_alloc_update_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  2822. {MODULE_NAME "_adjust_timeout", rtpproxy_adjust_timeout, 2, rtpproxy_alloc_update_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  2823. {MODULE_NAME "_delete", rtpproxy_delete, 1, rtpproxy_delete_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  2824. {MODULE_NAME "_set_param", rtpproxy_set_param, 2, rtpproxy_set_param_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE },
  2825. {MODULE_NAME "_authorize_media", rtpproxy_authorize_media, 0, NULL, REQUEST_ROUTE | ONREPLY_ROUTE },
  2826. {0, 0, 0, 0, 0}
  2827. };
  2828. static param_export_t params[] = {
  2829. {"config", PARAM_STR | PARAM_USE_FUNC, &declare_config},
  2830. {"switchboard", PARAM_STRING | PARAM_USE_FUNC, &declare_switchboard_param},
  2831. {"hostname", PARAM_STRING | PARAM_USE_FUNC, &declare_hostname},
  2832. {"codec_set", PARAM_STRING | PARAM_USE_FUNC, &declare_codec_set},
  2833. {"rpc_heartbeat_timeout", PARAM_INT, &rpc_heartbeat_timeout},
  2834. {"declare_codec", PARAM_STR | PARAM_USE_FUNC, &declare_codec},
  2835. {0, 0, 0}
  2836. };
  2837. struct module_exports exports = {
  2838. MODULE_NAME,
  2839. cmds,
  2840. 0, /* RPC methods */
  2841. params,
  2842. mod_init,
  2843. 0, /* reply processing */
  2844. mod_cleanup, /* destroy function */
  2845. 0, /* on_break */
  2846. child_init
  2847. };
  2848. #if !defined(NO_SHARED_LIBS) || NO_SHARED_LIBS==0
  2849. /* make compiler happy and give it missing symbols */
  2850. #ifdef IPT_RTPPROXY_IPTABLES_API
  2851. #include <iptables.h>
  2852. #undef IPT_RTPPROXY_IPTABLES_API
  2853. #else
  2854. #include <xtables.h>
  2855. #endif
  2856. #include <stdarg.h>
  2857. #ifdef xtables_error
  2858. /* iptables 1.4.8 */
  2859. struct xtables_globals *xt_params = NULL;
  2860. int xtables_check_inverse(const char option[], int *invert, int *optind, int argc, char **argv) {
  2861. return FALSE;
  2862. }
  2863. void xtables_register_target(struct xtables_target *me) {
  2864. }
  2865. #else /* xtables_error */
  2866. #ifdef _IPTABLES_COMMON_H
  2867. /* old iptables API, it uses iptables_common.h (instead of xtables.h) included from iptables.h */
  2868. /* #ifndef XTABLES_VERSION ... optional test */
  2869. #define IPT_RTPPROXY_IPTABLES_API 1
  2870. #endif
  2871. #ifdef IPT_RTPPROXY_IPTABLES_API
  2872. void register_target(struct iptables_target *me) {
  2873. }
  2874. #else
  2875. void xtables_register_target(struct xtables_target *me) {
  2876. }
  2877. #endif
  2878. #if IPT_RTPPROXY_IPTABLES_API
  2879. void exit_error(enum exittype status, char *msg, ...)
  2880. #else
  2881. void exit_error(enum exittype status, const char *msg, ...)
  2882. #endif
  2883. {
  2884. va_list args;
  2885. va_start(args, msg);
  2886. // ERR(msg/*, args*/); /* TODO: how to pass ... to macro? */
  2887. ERR(MODULE_NAME": %s", msg);
  2888. va_end(args);
  2889. }
  2890. int check_inverse(const char option[], int *invert, int *optind, int argc) {
  2891. return 0;
  2892. }
  2893. #endif /* xtables_error */
  2894. #endif