iptrtpproxy.c 100 KB

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