switch_core.c 108 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605
  1. /*
  2. * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  3. * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
  4. *
  5. * Version: MPL 1.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Anthony Minessale II <anthm@freeswitch.org>
  21. * Portions created by the Initial Developer are Copyright (C)
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. *
  26. * Anthony Minessale II <anthm@freeswitch.org>
  27. * Michael Jerris <mike@jerris.com>
  28. * Paul D. Tinsley <pdt at jackhammer.org>
  29. * Marcel Barbulescu <marcelbarbulescu@gmail.com>
  30. * Joseph Sullivan <jossulli@amazon.com>
  31. * Seven Du <dujinfang@gmail.com>
  32. * Andrey Volk <andywolk@gmail.com>
  33. *
  34. * switch_core.c -- Main Core Library
  35. *
  36. */
  37. #include <switch.h>
  38. #include <switch_ssl.h>
  39. #include <switch_stun.h>
  40. #include <switch_nat.h>
  41. #include "private/switch_apr_pvt.h"
  42. #include "private/switch_core_pvt.h"
  43. #include <switch_curl.h>
  44. #include <switch_msrp.h>
  45. #ifndef WIN32
  46. #include <switch_private.h>
  47. #ifdef HAVE_SETRLIMIT
  48. #include <sys/resource.h>
  49. #endif
  50. #endif
  51. #include <errno.h>
  52. #include <sqlite3.h>
  53. #ifdef HAVE_SYS_PRCTL_H
  54. #include <sys/prctl.h>
  55. #endif
  56. #ifdef SOLARIS_PRIVILEGES
  57. #include <priv.h>
  58. #endif
  59. #ifdef __linux__
  60. #include <sys/wait.h>
  61. #ifndef _GNU_SOURCE
  62. #define _GNU_SOURCE /* Required for POSIX_SPAWN_USEVFORK */
  63. #endif
  64. #include <spawn.h>
  65. #include <poll.h>
  66. #endif
  67. #ifdef WIN32
  68. #define popen _popen
  69. #define pclose _pclose
  70. #endif
  71. #ifdef HAVE_SYSTEMD
  72. #include <systemd/sd-daemon.h>
  73. #endif
  74. SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 };
  75. SWITCH_DECLARE_DATA switch_filenames SWITCH_GLOBAL_filenames = { 0 };
  76. /* The main runtime obj we keep this hidden for ourselves */
  77. struct switch_runtime runtime = { 0 };
  78. static void switch_load_core_config(const char *file);
  79. static void send_heartbeat(void)
  80. {
  81. switch_event_t *event;
  82. switch_core_time_duration_t duration;
  83. switch_core_measure_time(switch_core_uptime(), &duration);
  84. if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {
  85. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
  86. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time",
  87. "%u year%s, "
  88. "%u day%s, "
  89. "%u hour%s, "
  90. "%u minute%s, "
  91. "%u second%s, "
  92. "%u millisecond%s, "
  93. "%u microsecond%s",
  94. duration.yr, duration.yr == 1 ? "" : "s",
  95. duration.day, duration.day == 1 ? "" : "s",
  96. duration.hr, duration.hr == 1 ? "" : "s",
  97. duration.min, duration.min == 1 ? "" : "s",
  98. duration.sec, duration.sec == 1 ? "" : "s",
  99. duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s");
  100. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", "%s", switch_version_full());
  101. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000);
  102. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
  103. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0));
  104. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps);
  105. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-Last", "%u", runtime.sps_last);
  106. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-Max", "%u", runtime.sps_peak);
  107. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-FiveMin", "%u", runtime.sps_peak_fivemin);
  108. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1);
  109. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Peak-Max", "%u", runtime.sessions_peak);
  110. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Peak-FiveMin", "%u", runtime.sessions_peak_fivemin);
  111. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu());
  112. switch_event_fire(&event);
  113. }
  114. }
  115. static char main_ip4[256] = "";
  116. static char main_ip6[256] = "";
  117. static void check_ip(void)
  118. {
  119. char guess_ip4[256] = "";
  120. char guess_ip6[256] = "";
  121. char old_ip4[256] = "";
  122. char old_ip6[256] = "";
  123. int ok4 = 1, ok6 = 1;
  124. int mask = 0;
  125. switch_status_t check6, check4;
  126. switch_event_t *event;
  127. char *hostname = switch_core_get_variable("hostname");
  128. gethostname(runtime.hostname, sizeof(runtime.hostname));
  129. if (zstr(hostname)) {
  130. switch_core_set_variable("hostname", runtime.hostname);
  131. } else if (strcmp(hostname, runtime.hostname)) {
  132. if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
  133. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "hostname-change");
  134. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "old-hostname", hostname);
  135. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "new-hostname", runtime.hostname);
  136. switch_event_fire(&event);
  137. }
  138. switch_core_set_variable("hostname", runtime.hostname);
  139. }
  140. check4 = switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET);
  141. check6 = switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6);
  142. if (check6 != SWITCH_STATUS_SUCCESS && (zstr(main_ip6) || !strcasecmp(main_ip6, "::1"))) {
  143. check6 = SWITCH_STATUS_SUCCESS;
  144. }
  145. if (check4 != SWITCH_STATUS_SUCCESS) {
  146. ok4 = 2;
  147. } else if (!*main_ip4) {
  148. switch_set_string(main_ip4, guess_ip4);
  149. } else {
  150. if (!(ok4 = !strcmp(main_ip4, guess_ip4))) {
  151. struct in_addr in;
  152. in.s_addr = mask;
  153. switch_set_string(old_ip4, main_ip4);
  154. switch_set_string(main_ip4, guess_ip4);
  155. switch_core_set_variable("local_ip_v4", guess_ip4);
  156. switch_core_set_variable("local_mask_v4", inet_ntoa(in));
  157. }
  158. }
  159. if (check6 != SWITCH_STATUS_SUCCESS) {
  160. ok6 = 2;
  161. } else if (!*main_ip6) {
  162. switch_set_string(main_ip6, guess_ip6);
  163. } else {
  164. if (!(ok6 = !strcmp(main_ip6, guess_ip6))) {
  165. switch_set_string(old_ip6, main_ip6);
  166. switch_set_string(main_ip6, guess_ip6);
  167. switch_core_set_variable("local_ip_v6", guess_ip6);
  168. }
  169. }
  170. if (!ok4 || !ok6) {
  171. if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
  172. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change");
  173. if (!ok4) {
  174. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4);
  175. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4);
  176. }
  177. if (!ok6) {
  178. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6);
  179. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6);
  180. }
  181. switch_event_fire(&event);
  182. }
  183. }
  184. if (ok4 == 2 || ok6 == 2) {
  185. if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
  186. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-outage");
  187. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-status-v4", ok4 == 2 ? "disconnected" : "active");
  188. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-v4", main_ip4);
  189. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-status-v6", ok6 == 2 ? "disconnected" : "active");
  190. switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-v6", main_ip6);
  191. switch_event_fire(&event);
  192. }
  193. }
  194. }
  195. SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)
  196. {
  197. send_heartbeat();
  198. /* reschedule this task */
  199. task->runtime = switch_epoch_time_now(NULL) + runtime.event_heartbeat_interval;
  200. }
  201. SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)
  202. {
  203. check_ip();
  204. /* reschedule this task */
  205. task->runtime = switch_epoch_time_now(NULL) + 60;
  206. }
  207. SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
  208. {
  209. if ((runtime.console = fopen(console, "a")) == 0) {
  210. fprintf(stderr, "Cannot open output file %s.\n", console);
  211. return SWITCH_STATUS_FALSE;
  212. }
  213. return SWITCH_STATUS_SUCCESS;
  214. }
  215. SWITCH_DECLARE(FILE *) switch_core_get_console(void)
  216. {
  217. return runtime.console;
  218. }
  219. #ifdef HAVE_SYS_IOCTL_H
  220. #include <sys/ioctl.h>
  221. #endif
  222. SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y)
  223. {
  224. #ifdef WIN32
  225. CONSOLE_SCREEN_BUFFER_INFO csbi;
  226. int ret;
  227. if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) {
  228. if (x) *x = csbi.dwSize.X;
  229. if (y) *y = csbi.dwSize.Y;
  230. }
  231. #elif defined(TIOCGWINSZ)
  232. struct winsize w;
  233. ioctl(0, TIOCGWINSZ, &w);
  234. if (x) *x = w.ws_col;
  235. if (y) *y = w.ws_row;
  236. #else
  237. if (x) *x = 80;
  238. if (y) *y = 24;
  239. #endif
  240. }
  241. SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel)
  242. {
  243. return runtime.console;
  244. }
  245. SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler)
  246. {
  247. int index, tmp_index = 0;
  248. const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 };
  249. switch_mutex_lock(runtime.global_mutex);
  250. for (index = 0; index < runtime.state_handler_index; index++) {
  251. const switch_state_handler_table_t *cur = runtime.state_handlers[index];
  252. runtime.state_handlers[index] = NULL;
  253. if (cur == state_handler) {
  254. continue;
  255. }
  256. tmp[tmp_index++] = cur;
  257. }
  258. runtime.state_handler_index = 0;
  259. for (index = 0; index < tmp_index; index++) {
  260. runtime.state_handlers[runtime.state_handler_index++] = tmp[index];
  261. }
  262. switch_mutex_unlock(runtime.global_mutex);
  263. }
  264. SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)
  265. {
  266. int index;
  267. switch_mutex_lock(runtime.global_mutex);
  268. index = runtime.state_handler_index;
  269. if (index > (SWITCH_MAX_STATE_HANDLERS - 1)) {
  270. index = -1;
  271. } else {
  272. runtime.state_handlers[index] = state_handler;
  273. runtime.state_handler_index++;
  274. }
  275. switch_mutex_unlock(runtime.global_mutex);
  276. return index;
  277. }
  278. SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)
  279. {
  280. if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
  281. return NULL;
  282. }
  283. return runtime.state_handlers[index];
  284. }
  285. SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream)
  286. {
  287. switch_event_header_t *hi;
  288. switch_mutex_lock(runtime.global_mutex);
  289. for (hi = runtime.global_vars->headers; hi; hi = hi->next) {
  290. stream->write_function(stream, "%s=%s\n", hi->name, hi->value);
  291. }
  292. switch_mutex_unlock(runtime.global_mutex);
  293. }
  294. SWITCH_DECLARE(const char *) switch_core_get_hostname(void)
  295. {
  296. return runtime.hostname;
  297. }
  298. SWITCH_DECLARE(const char *) switch_core_get_switchname(void)
  299. {
  300. if (!zstr(runtime.switchname)) return runtime.switchname;
  301. return runtime.hostname;
  302. }
  303. SWITCH_DECLARE(char *) switch_core_get_domain(switch_bool_t dup)
  304. {
  305. char *domain;
  306. const char *var;
  307. switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
  308. if (!(var = switch_core_get_variable("domain"))) {
  309. var = "freeswitch.local";
  310. }
  311. if (dup) {
  312. domain = strdup(var);
  313. } else {
  314. domain = (char *) var;
  315. }
  316. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  317. return domain;
  318. }
  319. SWITCH_DECLARE(switch_status_t) switch_core_get_variables(switch_event_t **event)
  320. {
  321. switch_status_t status;
  322. switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
  323. status = switch_event_dup(event, runtime.global_vars);
  324. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  325. return status;
  326. }
  327. SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
  328. {
  329. char *val;
  330. switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
  331. val = (char *) switch_event_get_header(runtime.global_vars, varname);
  332. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  333. return val;
  334. }
  335. SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname)
  336. {
  337. char *val = NULL, *v;
  338. if (varname) {
  339. switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
  340. if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
  341. val = strdup(v);
  342. }
  343. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  344. }
  345. return val;
  346. }
  347. SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool)
  348. {
  349. char *val = NULL, *v;
  350. if (varname) {
  351. switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
  352. if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
  353. val = switch_core_strdup(pool, v);
  354. }
  355. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  356. }
  357. return val;
  358. }
  359. static void switch_core_unset_variables(void)
  360. {
  361. switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
  362. switch_event_destroy(&runtime.global_vars);
  363. switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);
  364. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  365. }
  366. SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value)
  367. {
  368. char *val;
  369. if (varname) {
  370. switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
  371. val = (char *) switch_event_get_header(runtime.global_vars, varname);
  372. if (val) {
  373. switch_event_del_header(runtime.global_vars, varname);
  374. }
  375. if (value) {
  376. char *v = strdup(value);
  377. switch_string_var_check(v, SWITCH_TRUE);
  378. switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM, varname, v);
  379. free(v);
  380. } else {
  381. switch_event_del_header(runtime.global_vars, varname);
  382. }
  383. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  384. }
  385. }
  386. SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2)
  387. {
  388. char *val;
  389. if (varname) {
  390. switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
  391. val = (char *) switch_event_get_header(runtime.global_vars, varname);
  392. if (val) {
  393. if (!val2 || strcmp(val, val2) != 0) {
  394. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  395. return SWITCH_FALSE;
  396. }
  397. switch_event_del_header(runtime.global_vars, varname);
  398. } else if (!zstr(val2)) {
  399. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  400. return SWITCH_FALSE;
  401. }
  402. if (value) {
  403. char *v = strdup(value);
  404. switch_string_var_check(v, SWITCH_TRUE);
  405. switch_event_add_header_string_nodup(runtime.global_vars, SWITCH_STACK_BOTTOM, varname, v);
  406. } else {
  407. switch_event_del_header(runtime.global_vars, varname);
  408. }
  409. switch_thread_rwlock_unlock(runtime.global_var_rwlock);
  410. }
  411. return SWITCH_TRUE;
  412. }
  413. SWITCH_DECLARE(char *) switch_core_get_uuid(void)
  414. {
  415. return runtime.uuid_str;
  416. }
  417. static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj)
  418. {
  419. switch_core_session_t *session = obj;
  420. switch_channel_t *channel;
  421. switch_frame_t *read_frame = NULL;
  422. // switch_assert(thread != NULL);
  423. // switch_assert(session != NULL);
  424. if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
  425. return NULL;
  426. }
  427. switch_mutex_lock(session->frame_read_mutex);
  428. channel = switch_core_session_get_channel(session);
  429. switch_channel_set_flag(channel, CF_SERVICE);
  430. while (switch_channel_test_flag(channel, CF_SERVICE)) {
  431. if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) {
  432. switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {
  433. case SWITCH_STATUS_SUCCESS:
  434. case SWITCH_STATUS_TIMEOUT:
  435. case SWITCH_STATUS_BREAK:
  436. break;
  437. default:
  438. switch_channel_clear_flag(channel, CF_SERVICE);
  439. break;
  440. }
  441. }
  442. if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) {
  443. switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {
  444. case SWITCH_STATUS_SUCCESS:
  445. case SWITCH_STATUS_TIMEOUT:
  446. case SWITCH_STATUS_BREAK:
  447. break;
  448. default:
  449. switch_channel_clear_flag(channel, CF_SERVICE);
  450. break;
  451. }
  452. }
  453. }
  454. switch_mutex_unlock(session->frame_read_mutex);
  455. switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);
  456. switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);
  457. switch_core_session_rwunlock(session);
  458. return NULL;
  459. }
  460. /* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */
  461. SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session)
  462. {
  463. switch_channel_t *channel;
  464. switch_assert(session);
  465. channel = switch_core_session_get_channel(session);
  466. switch_assert(channel);
  467. switch_channel_clear_flag(channel, CF_SERVICE);
  468. switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);
  469. switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);
  470. switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
  471. }
  472. SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
  473. {
  474. switch_channel_t *channel;
  475. switch_assert(session);
  476. channel = switch_core_session_get_channel(session);
  477. switch_assert(channel);
  478. if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO);
  479. if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO);
  480. switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session);
  481. }
  482. /* This function abstracts the thread creation for modules by allowing you to pass a function ptr and
  483. a void object and trust that that the function will be run in a thread with arg This lets
  484. you request and activate a thread without giving up any knowledge about what is in the thread
  485. neither the core nor the calling module know anything about each other.
  486. This thread is expected to never exit until the application exits so the func is responsible
  487. to make sure that is the case.
  488. The typical use for this is so switch_loadable_module.c can start up a thread for each module
  489. passing the table of module methods as a session obj into the core without actually allowing
  490. the core to have any clue and keeping switch_loadable_module.c from needing any thread code.
  491. */
  492. SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool)
  493. {
  494. switch_thread_t *thread = NULL;
  495. switch_threadattr_t *thd_attr = NULL;
  496. switch_core_thread_session_t *ts;
  497. int mypool;
  498. mypool = pool ? 0 : 1;
  499. if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
  500. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n");
  501. return NULL;
  502. }
  503. switch_threadattr_create(&thd_attr, pool);
  504. if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) {
  505. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n");
  506. } else {
  507. if (mypool) {
  508. ts->pool = pool;
  509. }
  510. ts->objs[0] = obj;
  511. ts->objs[1] = thread;
  512. switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
  513. switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
  514. switch_thread_create(&thread, thd_attr, func, ts, pool);
  515. }
  516. return thread;
  517. }
  518. SWITCH_DECLARE(void) switch_core_set_globals(void)
  519. {
  520. #define BUFSIZE 1024
  521. #ifdef WIN32
  522. char lpPathBuffer[BUFSIZE];
  523. DWORD dwBufSize = BUFSIZE;
  524. char base_dir[1024];
  525. char *lastbacklash;
  526. char *tmp;
  527. GetModuleFileName(NULL, base_dir, BUFSIZE);
  528. lastbacklash = strrchr(base_dir, '\\');
  529. base_dir[(lastbacklash - base_dir)] = '\0';
  530. /* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */
  531. SetCurrentDirectory(base_dir);
  532. tmp = switch_string_replace(base_dir, "\\", "/");
  533. strcpy(base_dir, tmp);
  534. free(tmp);
  535. #else
  536. char base_dir[1024] = SWITCH_PREFIX_DIR;
  537. #endif
  538. /* Order of precedence for, eg, rundir:
  539. * -run
  540. * -base
  541. * --with-rundir
  542. * --prefix
  543. */
  544. if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) {
  545. if (SWITCH_GLOBAL_dirs.base_dir)
  546. switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  547. else
  548. #ifdef SWITCH_MOD_DIR
  549. switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR);
  550. #else
  551. switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR);
  552. #endif
  553. }
  554. if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) {
  555. if (SWITCH_GLOBAL_dirs.base_dir)
  556. switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  557. else
  558. #ifdef SWITCH_LIB_DIR
  559. switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR);
  560. #else
  561. switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR);
  562. #endif
  563. }
  564. if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) {
  565. if (SWITCH_GLOBAL_dirs.base_dir)
  566. switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  567. else
  568. #ifdef SWITCH_CONF_DIR
  569. switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR);
  570. #else
  571. switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR);
  572. #endif
  573. }
  574. if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) {
  575. if (SWITCH_GLOBAL_dirs.base_dir)
  576. switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  577. else
  578. #ifdef SWITCH_LOG_DIR
  579. switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR);
  580. #else
  581. switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR);
  582. #endif
  583. }
  584. if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) {
  585. if (SWITCH_GLOBAL_dirs.base_dir)
  586. switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  587. else
  588. #ifdef SWITCH_RUN_DIR
  589. switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR);
  590. #else
  591. switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR);
  592. #endif
  593. }
  594. if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) {
  595. if (SWITCH_GLOBAL_dirs.base_dir)
  596. switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  597. else
  598. #ifdef SWITCH_RECORDINGS_DIR
  599. switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR);
  600. #else
  601. switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR);
  602. #endif
  603. }
  604. if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) {
  605. if (SWITCH_GLOBAL_dirs.base_dir)
  606. switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  607. else
  608. #ifdef SWITCH_SOUNDS_DIR
  609. switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR);
  610. #else
  611. switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR);
  612. #endif
  613. }
  614. if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) {
  615. if (SWITCH_GLOBAL_dirs.base_dir)
  616. switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  617. else
  618. #ifdef SWITCH_STORAGE_DIR
  619. switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR);
  620. #else
  621. switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR);
  622. #endif
  623. }
  624. if (!SWITCH_GLOBAL_dirs.cache_dir && (SWITCH_GLOBAL_dirs.cache_dir = (char *) malloc(BUFSIZE))) {
  625. if (SWITCH_GLOBAL_dirs.base_dir)
  626. switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s%scache", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  627. else
  628. #ifdef SWITCH_CACHE_DIR
  629. switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s", SWITCH_CACHE_DIR);
  630. #else
  631. switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s%scache", base_dir, SWITCH_PATH_SEPARATOR);
  632. #endif
  633. }
  634. if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) {
  635. if (SWITCH_GLOBAL_dirs.base_dir)
  636. switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  637. else
  638. #ifdef SWITCH_DB_DIR
  639. switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR);
  640. #else
  641. switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR);
  642. #endif
  643. }
  644. if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) {
  645. if (SWITCH_GLOBAL_dirs.base_dir)
  646. switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  647. else
  648. #ifdef SWITCH_SCRIPT_DIR
  649. switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR);
  650. #else
  651. switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR);
  652. #endif
  653. }
  654. if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
  655. if (SWITCH_GLOBAL_dirs.base_dir)
  656. switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  657. else
  658. #ifdef SWITCH_HTDOCS_DIR
  659. switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR);
  660. #else
  661. switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR);
  662. #endif
  663. }
  664. if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {
  665. if (SWITCH_GLOBAL_dirs.base_dir)
  666. switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  667. else
  668. #ifdef SWITCH_GRAMMAR_DIR
  669. switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR);
  670. #else
  671. switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR);
  672. #endif
  673. }
  674. if (!SWITCH_GLOBAL_dirs.fonts_dir && (SWITCH_GLOBAL_dirs.fonts_dir = (char *) malloc(BUFSIZE))) {
  675. if (SWITCH_GLOBAL_dirs.base_dir)
  676. switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s%sfonts", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  677. else
  678. #ifdef SWITCH_FONTS_DIR
  679. switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s", SWITCH_FONTS_DIR);
  680. #else
  681. switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s%sfonts", base_dir, SWITCH_PATH_SEPARATOR);
  682. #endif
  683. }
  684. if (!SWITCH_GLOBAL_dirs.images_dir && (SWITCH_GLOBAL_dirs.images_dir = (char *) malloc(BUFSIZE))) {
  685. if (SWITCH_GLOBAL_dirs.base_dir)
  686. switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s%simages", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  687. else
  688. #ifdef SWITCH_IMAGES_DIR
  689. switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s", SWITCH_IMAGES_DIR);
  690. #else
  691. switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s%simages", base_dir, SWITCH_PATH_SEPARATOR);
  692. #endif
  693. }
  694. if (!SWITCH_GLOBAL_dirs.data_dir && (SWITCH_GLOBAL_dirs.data_dir = (char *) malloc(BUFSIZE))) {
  695. if (SWITCH_GLOBAL_dirs.base_dir)
  696. switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", SWITCH_GLOBAL_dirs.base_dir);
  697. else
  698. #ifdef SWITCH_DATA_DIR
  699. switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", SWITCH_DATA_DIR);
  700. #else
  701. switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", base_dir);
  702. #endif
  703. }
  704. if (!SWITCH_GLOBAL_dirs.localstate_dir && (SWITCH_GLOBAL_dirs.localstate_dir = (char *) malloc(BUFSIZE))) {
  705. if (SWITCH_GLOBAL_dirs.base_dir)
  706. switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", SWITCH_GLOBAL_dirs.base_dir);
  707. else
  708. #ifdef SWITCH_LOCALSTATE_DIR
  709. switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", SWITCH_LOCALSTATE_DIR);
  710. #else
  711. switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", base_dir);
  712. #endif
  713. }
  714. if (!SWITCH_GLOBAL_dirs.certs_dir && (SWITCH_GLOBAL_dirs.certs_dir = (char *) malloc(BUFSIZE))) {
  715. if (SWITCH_GLOBAL_dirs.base_dir)
  716. switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s%scert", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
  717. else
  718. #ifdef SWITCH_CERTS_DIR
  719. switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s", SWITCH_CERTS_DIR);
  720. #else
  721. switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s%scert", base_dir, SWITCH_PATH_SEPARATOR);
  722. #endif
  723. }
  724. if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) {
  725. #ifdef SWITCH_TEMP_DIR
  726. switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR);
  727. #else
  728. #ifdef WIN32
  729. GetTempPath(dwBufSize, lpPathBuffer);
  730. lpPathBuffer[strlen(lpPathBuffer)-1] = 0;
  731. tmp = switch_string_replace(lpPathBuffer, "\\", "/");
  732. strcpy(lpPathBuffer, tmp);
  733. free(tmp);
  734. switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer);
  735. #else
  736. switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp");
  737. #endif
  738. #endif
  739. }
  740. if (!SWITCH_GLOBAL_filenames.conf_name && (SWITCH_GLOBAL_filenames.conf_name = (char *) malloc(BUFSIZE))) {
  741. switch_snprintf(SWITCH_GLOBAL_filenames.conf_name, BUFSIZE, "%s", "freeswitch.xml");
  742. }
  743. /* Do this last because it being empty is part of the above logic */
  744. if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) {
  745. switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir);
  746. }
  747. switch_assert(SWITCH_GLOBAL_dirs.base_dir);
  748. switch_assert(SWITCH_GLOBAL_dirs.mod_dir);
  749. switch_assert(SWITCH_GLOBAL_dirs.lib_dir);
  750. switch_assert(SWITCH_GLOBAL_dirs.conf_dir);
  751. switch_assert(SWITCH_GLOBAL_dirs.log_dir);
  752. switch_assert(SWITCH_GLOBAL_dirs.run_dir);
  753. switch_assert(SWITCH_GLOBAL_dirs.db_dir);
  754. switch_assert(SWITCH_GLOBAL_dirs.script_dir);
  755. switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir);
  756. switch_assert(SWITCH_GLOBAL_dirs.grammar_dir);
  757. switch_assert(SWITCH_GLOBAL_dirs.fonts_dir);
  758. switch_assert(SWITCH_GLOBAL_dirs.images_dir);
  759. switch_assert(SWITCH_GLOBAL_dirs.recordings_dir);
  760. switch_assert(SWITCH_GLOBAL_dirs.sounds_dir);
  761. switch_assert(SWITCH_GLOBAL_dirs.certs_dir);
  762. switch_assert(SWITCH_GLOBAL_dirs.temp_dir);
  763. switch_assert(SWITCH_GLOBAL_dirs.data_dir);
  764. switch_assert(SWITCH_GLOBAL_dirs.localstate_dir);
  765. switch_assert(SWITCH_GLOBAL_filenames.conf_name);
  766. }
  767. SWITCH_DECLARE(int32_t) switch_core_set_process_privileges(void)
  768. {
  769. #ifdef SOLARIS_PRIVILEGES
  770. priv_set_t *basicset;
  771. /* make the process privilege-aware */
  772. setpflags(PRIV_AWARE, 1);
  773. /* reset the privileges to basic */
  774. basicset = priv_str_to_set("basic", ",", NULL);
  775. if (setppriv(PRIV_SET, PRIV_EFFECTIVE, basicset) != 0) {
  776. fprintf(stderr, "ERROR: Failed to acquire basic privileges (%s)\n", strerror(errno));
  777. }
  778. /* we need high-resolution clock, and this requires a non-basic privilege */
  779. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_CLOCK_HIGHRES, NULL) < 0) {
  780. fprintf(stderr, "ERROR: Failed to acquire proc_clock_highres privilege (%s)\n", strerror(errno));
  781. return -1;
  782. }
  783. /* need this for setrlimit */
  784. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_RESOURCE, NULL) < 0) {
  785. fprintf(stderr, "ERROR: Failed to acquire sys_resource privilege (%s)\n", strerror(errno));
  786. return -1;
  787. }
  788. /* we need to read directories belonging to other uid */
  789. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_SEARCH, NULL) < 0) {
  790. fprintf(stderr, "ERROR: Failed to acquire file_dac_search privilege (%s)\n", strerror(errno));
  791. return -1;
  792. }
  793. #endif
  794. return 0;
  795. }
  796. SWITCH_DECLARE(int32_t) set_low_priority(void)
  797. {
  798. #ifdef WIN32
  799. return SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
  800. #else
  801. #if defined(USE_SCHED_SETSCHEDULER) && ! defined(SOLARIS_PRIVILEGES)
  802. /*
  803. * Try to use a normal scheduler
  804. */
  805. struct sched_param sched = { 0 };
  806. sched.sched_priority = 0;
  807. if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0) {
  808. fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
  809. return -1;
  810. }
  811. #endif
  812. #ifdef HAVE_SETPRIORITY
  813. /*
  814. * setpriority() works on FreeBSD (6.2), nice() doesn't
  815. */
  816. if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) {
  817. fprintf(stderr, "ERROR: Could not set nice level\n");
  818. return -1;
  819. }
  820. #else
  821. if (nice(19) != 19) {
  822. fprintf(stderr, "ERROR: Could not set nice level\n");
  823. return -1;
  824. }
  825. #endif
  826. return 0;
  827. #endif
  828. }
  829. SWITCH_DECLARE(int32_t) set_realtime_priority(void)
  830. {
  831. #ifdef WIN32
  832. return SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  833. #else
  834. #ifdef USE_SCHED_SETSCHEDULER
  835. /*
  836. * Try to use a round-robin scheduler
  837. * with a fallback if that does not work
  838. */
  839. struct sched_param sched = { 0 };
  840. sched.sched_priority = SWITCH_PRI_LOW;
  841. #endif
  842. #ifdef SOLARIS_PRIVILEGES
  843. /* request the privileges to elevate the priority */
  844. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOCNTL, NULL) < 0) {
  845. #ifdef PRIV_PROC_PRIOUP
  846. /* fallback to PRIV_PROC_PRIOUP on SmartOS */
  847. fprintf(stderr, "WARN: Failed to acquire proc_priocntl privilege (%s)\n", strerror(errno));
  848. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOUP, NULL) < 0) {
  849. fprintf(stderr, "ERROR: Failed to acquire proc_prioup privilege (%s)\n", strerror(errno));
  850. return -1;
  851. }
  852. #else
  853. fprintf(stderr, "ERROR: Failed to acquire proc_priocntl privilege (%s)\n", strerror(errno));
  854. return -1;
  855. #endif
  856. }
  857. if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
  858. fprintf(stderr, "WARN: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
  859. } else {
  860. return 0;
  861. }
  862. if (setpriority(PRIO_PROCESS, 0, -10) < 0) {
  863. fprintf(stderr, "ERROR: Could not set nice level\n");
  864. return -1;
  865. }
  866. return 0;
  867. #else
  868. #ifdef USE_SCHED_SETSCHEDULER
  869. if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
  870. fprintf(stderr, "ERROR: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
  871. sched.sched_priority = 0;
  872. if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0 ) {
  873. fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
  874. return -1;
  875. }
  876. }
  877. #endif
  878. #ifdef HAVE_SETPRIORITY
  879. /*
  880. * setpriority() works on FreeBSD (6.2), nice() doesn't
  881. */
  882. if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) {
  883. fprintf(stderr, "ERROR: Could not set nice level\n");
  884. return -1;
  885. }
  886. #else
  887. if (nice(-10) != -10) {
  888. fprintf(stderr, "ERROR: Could not set nice level\n");
  889. return -1;
  890. }
  891. #endif
  892. #endif
  893. return 0;
  894. #endif
  895. }
  896. SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void)
  897. {
  898. return runtime.cpu_count;
  899. }
  900. SWITCH_DECLARE(int32_t) set_normal_priority(void)
  901. {
  902. return 0;
  903. }
  904. SWITCH_DECLARE(int32_t) set_auto_priority(void)
  905. {
  906. #ifndef WIN32
  907. runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);
  908. #else
  909. SYSTEM_INFO sysinfo;
  910. GetSystemInfo( &sysinfo );
  911. runtime.cpu_count = sysinfo.dwNumberOfProcessors;
  912. #endif
  913. if (!runtime.cpu_count) runtime.cpu_count = 1;
  914. return set_realtime_priority();
  915. // ERROR: code not reachable on Windows Visual Studio Express 2008 return 0;
  916. }
  917. SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
  918. {
  919. #ifndef WIN32
  920. uid_t runas_uid = 0;
  921. gid_t runas_gid = 0;
  922. struct passwd *runas_pw = NULL;
  923. if (user) {
  924. /*
  925. * Lookup user information in the system's db
  926. */
  927. runas_pw = getpwnam(user);
  928. if (!runas_pw) {
  929. fprintf(stderr, "ERROR: Unknown user \"%s\"\n", user);
  930. return -1;
  931. }
  932. runas_uid = runas_pw->pw_uid;
  933. }
  934. if (group) {
  935. struct group *gr = NULL;
  936. /*
  937. * Lookup group information in the system's db
  938. */
  939. gr = getgrnam(group);
  940. if (!gr) {
  941. fprintf(stderr, "ERROR: Unknown group \"%s\"\n", group);
  942. return -1;
  943. }
  944. runas_gid = gr->gr_gid;
  945. }
  946. if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) {
  947. /* already running as the right user and group, nothing to do! */
  948. return 0;
  949. }
  950. if (runas_uid) {
  951. #ifdef SOLARIS_PRIVILEGES
  952. /* request the privilege to set the UID */
  953. if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_SETID, NULL) < 0) {
  954. fprintf(stderr, "ERROR: Failed to acquire proc_setid privilege (%s)\n", strerror(errno));
  955. return -1;
  956. }
  957. #endif
  958. #ifdef HAVE_SETGROUPS
  959. /*
  960. * Drop all group memberships prior to changing anything
  961. * or else we're going to inherit the parent's list of groups
  962. * (which is not what we want...)
  963. */
  964. if (setgroups(0, NULL) < 0) {
  965. fprintf(stderr, "ERROR: Failed to drop group access list\n");
  966. return -1;
  967. }
  968. #endif
  969. if (runas_gid) {
  970. /*
  971. * A group has been passed, switch to it
  972. * (without loading the user's other groups)
  973. */
  974. if (setgid(runas_gid) < 0) {
  975. fprintf(stderr, "ERROR: Failed to change gid!\n");
  976. return -1;
  977. }
  978. } else {
  979. /*
  980. * No group has been passed, use the user's primary group in this case
  981. */
  982. if (setgid(runas_pw->pw_gid) < 0) {
  983. fprintf(stderr, "ERROR: Failed to change gid!\n");
  984. return -1;
  985. }
  986. #ifdef HAVE_INITGROUPS
  987. /*
  988. * Set all the other groups the user is a member of
  989. * (This can be really useful for fine-grained access control)
  990. */
  991. if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
  992. fprintf(stderr, "ERROR: Failed to set group access list for user\n");
  993. return -1;
  994. }
  995. #endif
  996. }
  997. /*
  998. * Finally drop all privileges by switching to the new userid
  999. */
  1000. if (setuid(runas_uid) < 0) {
  1001. fprintf(stderr, "ERROR: Failed to change uid!\n");
  1002. return -1;
  1003. }
  1004. #ifdef HAVE_SYS_PRCTL_H
  1005. if (prctl(PR_SET_DUMPABLE, 1) < 0) {
  1006. fprintf(stderr, "ERROR: Failed to enable core dumps!\n");
  1007. return -1;
  1008. }
  1009. #endif
  1010. }
  1011. #endif
  1012. return 0;
  1013. }
  1014. SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
  1015. {
  1016. #ifdef WIN32
  1017. HANDLE shutdown_event;
  1018. char path[256] = "";
  1019. #endif
  1020. if (bg) {
  1021. #ifdef WIN32
  1022. switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
  1023. shutdown_event = CreateEvent(NULL, FALSE, FALSE, path);
  1024. if (shutdown_event) {
  1025. WaitForSingleObject(shutdown_event, INFINITE);
  1026. }
  1027. #else
  1028. while (runtime.running) {
  1029. switch_yield(1000000);
  1030. }
  1031. #endif
  1032. } else {
  1033. /* wait for console input */
  1034. switch_console_loop();
  1035. }
  1036. }
  1037. SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
  1038. {
  1039. if (!ext) {
  1040. return NULL;
  1041. }
  1042. return (const char *) switch_core_hash_find(runtime.mime_types, ext);
  1043. }
  1044. SWITCH_DECLARE(const char *) switch_core_mime_type2ext(const char *mime)
  1045. {
  1046. if (!mime) {
  1047. return NULL;
  1048. }
  1049. return (const char *) switch_core_hash_find(runtime.mime_type_exts, mime);
  1050. }
  1051. SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void)
  1052. {
  1053. return switch_core_hash_first(runtime.mime_types);
  1054. }
  1055. SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext)
  1056. {
  1057. char *ptype = NULL;
  1058. char *ext_list = NULL;
  1059. int argc = 0;
  1060. char *argv[20] = { 0 };
  1061. int x;
  1062. switch_status_t status = SWITCH_STATUS_FALSE;
  1063. switch_assert(type);
  1064. switch_assert(ext);
  1065. ptype = switch_core_permanent_strdup(type);
  1066. ext_list = strdup(ext);
  1067. switch_assert(ext_list);
  1068. /* Map each file extension to this MIME type if not already mapped. Map the MIME type to the first file extension in the list if not already mapped. */
  1069. if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
  1070. int is_mapped_type = switch_core_hash_find(runtime.mime_type_exts, ptype) != NULL;
  1071. for (x = 0; x < argc; x++) {
  1072. if (argv[x] && ptype) {
  1073. if (!switch_core_hash_find(runtime.mime_types, ext)) {
  1074. switch_core_hash_insert(runtime.mime_types, argv[x], ptype);
  1075. }
  1076. if (!is_mapped_type) {
  1077. switch_core_hash_insert(runtime.mime_type_exts, ptype, switch_core_permanent_strdup(argv[x]));
  1078. is_mapped_type = 1;
  1079. }
  1080. }
  1081. }
  1082. status = SWITCH_STATUS_SUCCESS;
  1083. }
  1084. free(ext_list);
  1085. return status;
  1086. }
  1087. static void load_mime_types(void)
  1088. {
  1089. char *cf = "mime.types";
  1090. FILE *fd = NULL;
  1091. char *line_buf = NULL;
  1092. switch_size_t llen = 0;
  1093. char *mime_path = NULL;
  1094. mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf);
  1095. switch_assert(mime_path);
  1096. fd = fopen(mime_path, "rb");
  1097. if (fd == NULL) {
  1098. goto end;
  1099. }
  1100. while ((switch_fp_read_dline(fd, &line_buf, &llen))) {
  1101. char *p;
  1102. char *type = line_buf;
  1103. if (*line_buf == '#') {
  1104. continue;
  1105. }
  1106. if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) {
  1107. *p = '\0';
  1108. }
  1109. if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) {
  1110. *p++ = '\0';
  1111. while (*p == ' ' || *p == '\t') {
  1112. p++;
  1113. }
  1114. switch_core_mime_add_type(type, p);
  1115. }
  1116. }
  1117. switch_safe_free(line_buf);
  1118. fclose(fd);
  1119. end:
  1120. switch_safe_free(mime_path);
  1121. }
  1122. SWITCH_DECLARE(void) switch_core_setrlimits(void)
  1123. {
  1124. #ifdef HAVE_SETRLIMIT
  1125. struct rlimit rlp;
  1126. /*
  1127. Setting the stack size on FreeBSD results in an instant crash.
  1128. If anyone knows how to fix this,
  1129. feel free to submit a patch to https://github.com/signalwire/freeswitch
  1130. */
  1131. #ifndef __FreeBSD__
  1132. memset(&rlp, 0, sizeof(rlp));
  1133. rlp.rlim_cur = SWITCH_THREAD_STACKSIZE;
  1134. rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE;
  1135. setrlimit(RLIMIT_STACK, &rlp);
  1136. #endif
  1137. memset(&rlp, 0, sizeof(rlp));
  1138. rlp.rlim_cur = 999999;
  1139. rlp.rlim_max = 999999;
  1140. setrlimit(RLIMIT_NOFILE, &rlp);
  1141. memset(&rlp, 0, sizeof(rlp));
  1142. rlp.rlim_cur = RLIM_INFINITY;
  1143. rlp.rlim_max = RLIM_INFINITY;
  1144. setrlimit(RLIMIT_CPU, &rlp);
  1145. setrlimit(RLIMIT_DATA, &rlp);
  1146. setrlimit(RLIMIT_FSIZE, &rlp);
  1147. #ifdef RLIMIT_NPROC
  1148. setrlimit(RLIMIT_NPROC, &rlp);
  1149. #endif
  1150. #ifdef RLIMIT_RTPRIO
  1151. setrlimit(RLIMIT_RTPRIO, &rlp);
  1152. #endif
  1153. #if !defined(__OpenBSD__) && !defined(__NetBSD__)
  1154. setrlimit(RLIMIT_AS, &rlp);
  1155. #endif
  1156. #endif
  1157. return;
  1158. }
  1159. typedef struct {
  1160. switch_memory_pool_t *pool;
  1161. switch_hash_t *hash;
  1162. } switch_ip_list_t;
  1163. static switch_ip_list_t IP_LIST = { 0 };
  1164. SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token)
  1165. {
  1166. switch_network_list_t *list;
  1167. ip_t ip, mask, net;
  1168. uint32_t bits;
  1169. char *ipv6 = strchr(ip_str,':');
  1170. switch_bool_t ok = SWITCH_FALSE;
  1171. char *ipv4 = NULL;
  1172. if (!list_name) {
  1173. return SWITCH_FALSE;
  1174. }
  1175. if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(ip_str))) {
  1176. ip_str = ipv4;
  1177. ipv6 = NULL;
  1178. }
  1179. switch_mutex_lock(runtime.global_mutex);
  1180. if (ipv6) {
  1181. switch_inet_pton(AF_INET6, ip_str, &ip);
  1182. } else {
  1183. switch_inet_pton(AF_INET, ip_str, &ip);
  1184. ip.v4 = htonl(ip.v4);
  1185. }
  1186. if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) {
  1187. if (ipv6) {
  1188. ok = switch_network_list_validate_ip6_port_token(list, ip, port, token);
  1189. } else {
  1190. ok = switch_network_list_validate_ip_port_token(list, ip.v4, port, token);
  1191. }
  1192. } else if (strchr(list_name, '/')) {
  1193. if (strchr(list_name, ',')) {
  1194. char *list_name_dup = strdup(list_name);
  1195. char *argv[100]; /* MAX ACL */
  1196. int argc;
  1197. switch_assert(list_name_dup);
  1198. if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
  1199. int i;
  1200. for (i = 0; i < argc; i++) {
  1201. switch_parse_cidr(argv[i], &net, &mask, &bits);
  1202. if (ipv6) {
  1203. if ((ok = switch_testv6_subnet(ip, net, mask))){
  1204. break;
  1205. }
  1206. } else {
  1207. if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) {
  1208. break;
  1209. }
  1210. }
  1211. }
  1212. }
  1213. free(list_name_dup);
  1214. } else {
  1215. switch_parse_cidr(list_name, &net, &mask, &bits);
  1216. if (ipv6) {
  1217. ok = switch_testv6_subnet(ip, net, mask);
  1218. } else {
  1219. ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
  1220. }
  1221. }
  1222. }
  1223. switch_safe_free(ipv4);
  1224. switch_mutex_unlock(runtime.global_mutex);
  1225. return ok;
  1226. }
  1227. SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token)
  1228. {
  1229. return switch_check_network_list_ip_port_token(ip_str, 0, list_name, token);
  1230. }
  1231. SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
  1232. {
  1233. switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL;
  1234. switch_network_list_t *rfc_list, *list;
  1235. char guess_ip[16] = "";
  1236. int mask = 0;
  1237. char guess_mask[16] = "";
  1238. char *tmp_name;
  1239. struct in_addr in;
  1240. switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
  1241. in.s_addr = mask;
  1242. switch_set_string(guess_mask, inet_ntoa(in));
  1243. switch_mutex_lock(runtime.global_mutex);
  1244. if (IP_LIST.hash) {
  1245. switch_core_hash_destroy(&IP_LIST.hash);
  1246. }
  1247. if (IP_LIST.pool) {
  1248. switch_core_destroy_memory_pool(&IP_LIST.pool);
  1249. }
  1250. memset(&IP_LIST, 0, sizeof(IP_LIST));
  1251. switch_core_new_memory_pool(&IP_LIST.pool);
  1252. switch_core_hash_init(&IP_LIST.hash);
  1253. tmp_name = "rfc6598.auto";
  1254. switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
  1255. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
  1256. switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
  1257. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1258. tmp_name = "rfc1918.auto";
  1259. switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
  1260. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
  1261. switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
  1262. switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
  1263. switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
  1264. switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_TRUE);
  1265. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1266. tmp_name = "wan.auto";
  1267. switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
  1268. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
  1269. switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
  1270. switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
  1271. switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
  1272. switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
  1273. switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
  1274. switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_FALSE);
  1275. switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
  1276. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1277. tmp_name = "wan_v6.auto";
  1278. switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
  1279. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
  1280. switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
  1281. switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
  1282. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1283. tmp_name = "wan_v4.auto";
  1284. switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
  1285. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
  1286. switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
  1287. switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
  1288. switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
  1289. switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
  1290. switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
  1291. switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_FALSE);
  1292. switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
  1293. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1294. tmp_name = "any_v6.auto";
  1295. switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
  1296. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
  1297. switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
  1298. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1299. tmp_name = "any_v4.auto";
  1300. switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
  1301. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
  1302. switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
  1303. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1304. tmp_name = "nat.auto";
  1305. switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
  1306. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
  1307. if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
  1308. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name);
  1309. }
  1310. switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
  1311. switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
  1312. switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
  1313. switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
  1314. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1315. tmp_name = "loopback.auto";
  1316. switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
  1317. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
  1318. switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE);
  1319. switch_network_list_add_cidr(rfc_list, "::1/128", SWITCH_TRUE);
  1320. switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
  1321. tmp_name = "localnet.auto";
  1322. switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
  1323. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
  1324. if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
  1325. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name);
  1326. }
  1327. switch_core_hash_insert(IP_LIST.hash, tmp_name, list);
  1328. if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) {
  1329. if ((x_lists = switch_xml_child(cfg, "network-lists"))) {
  1330. for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) {
  1331. const char *name = switch_xml_attr(x_list, "name");
  1332. const char *dft = switch_xml_attr(x_list, "default");
  1333. switch_bool_t default_type = SWITCH_TRUE;
  1334. if (zstr(name)) {
  1335. continue;
  1336. }
  1337. if (dft) {
  1338. default_type = switch_true(dft);
  1339. }
  1340. if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {
  1341. abort();
  1342. }
  1343. if (reload) {
  1344. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
  1345. } else {
  1346. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
  1347. }
  1348. for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) {
  1349. const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL, *port = NULL;
  1350. switch_bool_t ok = default_type;
  1351. const char *type = switch_xml_attr(x_node, "type");
  1352. switch_network_port_range_t port_range;
  1353. char *argv[MAX_NETWORK_PORTS] = { 0 };
  1354. int argc = 0, i;
  1355. if (type) {
  1356. ok = switch_true(type);
  1357. }
  1358. cidr = switch_xml_attr(x_node, "cidr");
  1359. host = switch_xml_attr(x_node, "host");
  1360. mask = switch_xml_attr(x_node, "mask");
  1361. domain = switch_xml_attr(x_node, "domain");
  1362. memset(&port_range, 0, sizeof(switch_network_port_range_t));
  1363. if( (port = switch_xml_attr(x_node, "port")) != NULL) {
  1364. port_range.port = atoi(port);
  1365. }
  1366. if( (port = switch_xml_attr(x_node, "ports")) != NULL) {
  1367. argc = switch_separate_string((char*)port, ',', argv, (sizeof(argv) / sizeof(argv[0])));
  1368. for(i=0; i < argc; i++) {
  1369. port_range.ports[i] = atoi(argv[i]);
  1370. }
  1371. }
  1372. if( (port = switch_xml_attr(x_node, "port-min")) != NULL) {
  1373. port_range.min_port = atoi(port);
  1374. }
  1375. if( (port = switch_xml_attr(x_node, "port-max")) != NULL) {
  1376. port_range.max_port = atoi(port);
  1377. }
  1378. if (domain) {
  1379. switch_event_t *my_params = NULL;
  1380. switch_xml_t x_domain, xml_root;
  1381. switch_xml_t gt, gts, ut, uts;
  1382. switch_event_create(&my_params, SWITCH_EVENT_GENERAL);
  1383. switch_assert(my_params);
  1384. switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain);
  1385. switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list");
  1386. if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) {
  1387. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain);
  1388. switch_event_destroy(&my_params);
  1389. continue;
  1390. }
  1391. switch_event_destroy(&my_params);
  1392. if ((ut = switch_xml_child(x_domain, "users"))) {
  1393. x_domain = ut;
  1394. }
  1395. for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) {
  1396. const char *user_cidr = switch_xml_attr(ut, "cidr");
  1397. const char *id = switch_xml_attr(ut, "id");
  1398. if (id && user_cidr) {
  1399. char *token = switch_mprintf("%s@%s", id, domain);
  1400. switch_assert(token);
  1401. switch_network_list_add_cidr_token(list, user_cidr, ok, token);
  1402. free(token);
  1403. }
  1404. }
  1405. for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) {
  1406. for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) {
  1407. for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) {
  1408. for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) {
  1409. const char *user_cidr = switch_xml_attr(ut, "cidr");
  1410. const char *id = switch_xml_attr(ut, "id");
  1411. if (id && user_cidr) {
  1412. char *token = switch_mprintf("%s@%s", id, domain);
  1413. switch_assert(token);
  1414. switch_network_list_add_cidr_port_token(list, user_cidr, ok, token, &port_range);
  1415. free(token);
  1416. }
  1417. }
  1418. }
  1419. }
  1420. }
  1421. switch_xml_free(xml_root);
  1422. } else if (cidr) {
  1423. switch_network_list_add_cidr_port_token(list, cidr, ok, NULL, &port_range);
  1424. } else if (host && mask) {
  1425. switch_network_list_add_host_port_mask(list, host, mask, ok, &port_range);
  1426. }
  1427. }
  1428. switch_core_hash_insert(IP_LIST.hash, name, list);
  1429. }
  1430. }
  1431. switch_xml_free(xml);
  1432. }
  1433. switch_mutex_unlock(runtime.global_mutex);
  1434. }
  1435. SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration)
  1436. {
  1437. if (duration) {
  1438. if (duration > SWITCH_MAX_DTMF_DURATION) {
  1439. duration = SWITCH_MAX_DTMF_DURATION;
  1440. }
  1441. if (duration < SWITCH_MIN_DTMF_DURATION) {
  1442. duration = SWITCH_MIN_DTMF_DURATION;
  1443. }
  1444. runtime.max_dtmf_duration = duration;
  1445. if (duration < runtime.min_dtmf_duration) {
  1446. runtime.min_dtmf_duration = duration;
  1447. }
  1448. }
  1449. return runtime.max_dtmf_duration;
  1450. }
  1451. SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration)
  1452. {
  1453. if (duration) {
  1454. if (duration < SWITCH_MIN_DTMF_DURATION) {
  1455. duration = SWITCH_MIN_DTMF_DURATION;
  1456. }
  1457. if (duration > SWITCH_MAX_DTMF_DURATION) {
  1458. duration = SWITCH_MAX_DTMF_DURATION;
  1459. }
  1460. runtime.default_dtmf_duration = duration;
  1461. if (duration < runtime.min_dtmf_duration) {
  1462. runtime.min_dtmf_duration = duration;
  1463. }
  1464. if (duration > runtime.max_dtmf_duration) {
  1465. runtime.max_dtmf_duration = duration;
  1466. }
  1467. }
  1468. return runtime.default_dtmf_duration;
  1469. }
  1470. SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration)
  1471. {
  1472. if (duration) {
  1473. if (duration < SWITCH_MIN_DTMF_DURATION) {
  1474. duration = SWITCH_MIN_DTMF_DURATION;
  1475. }
  1476. if (duration > SWITCH_MAX_DTMF_DURATION) {
  1477. duration = SWITCH_MAX_DTMF_DURATION;
  1478. }
  1479. runtime.min_dtmf_duration = duration;
  1480. if (duration > runtime.max_dtmf_duration) {
  1481. runtime.max_dtmf_duration = duration;
  1482. }
  1483. }
  1484. return runtime.min_dtmf_duration;
  1485. }
  1486. SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu)
  1487. {
  1488. switch_status_t status = SWITCH_STATUS_FALSE;
  1489. if (cpu > -1) {
  1490. #ifdef HAVE_CPU_SET_MACROS
  1491. cpu_set_t set;
  1492. CPU_ZERO(&set);
  1493. CPU_SET(cpu, &set);
  1494. if (!sched_setaffinity(0, sizeof(set), &set)) {
  1495. status = SWITCH_STATUS_SUCCESS;
  1496. }
  1497. #else
  1498. #if WIN32
  1499. if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) {
  1500. status = SWITCH_STATUS_SUCCESS;
  1501. }
  1502. #endif
  1503. #endif
  1504. }
  1505. return status;
  1506. }
  1507. SWITCH_DECLARE(int) switch_core_test_flag(int flag)
  1508. {
  1509. return switch_test_flag((&runtime), flag);
  1510. }
  1511. SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)
  1512. {
  1513. switch_uuid_t uuid;
  1514. char guess_ip[256];
  1515. int mask = 0;
  1516. struct in_addr in;
  1517. if (runtime.runlevel > 0) {
  1518. /* one per customer */
  1519. return SWITCH_STATUS_SUCCESS;
  1520. }
  1521. memset(&runtime, 0, sizeof(runtime));
  1522. gethostname(runtime.hostname, sizeof(runtime.hostname));
  1523. runtime.shutdown_cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
  1524. runtime.max_db_handles = 50;
  1525. runtime.db_handle_timeout = 5000000;
  1526. runtime.event_heartbeat_interval = 20;
  1527. runtime.runlevel++;
  1528. runtime.dummy_cng_frame.data = runtime.dummy_data;
  1529. runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data);
  1530. runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data);
  1531. runtime.dbname = "core";
  1532. switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG);
  1533. switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);
  1534. switch_set_flag((&runtime), SCF_CLEAR_SQL);
  1535. switch_set_flag((&runtime), SCF_API_EXPANSION);
  1536. switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);
  1537. #ifdef WIN32
  1538. switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  1539. #endif
  1540. switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
  1541. if (flags & SCF_LOG_DISABLE) {
  1542. runtime.hard_log_level = SWITCH_LOG_DISABLE;
  1543. flags &= ~SCF_LOG_DISABLE;
  1544. } else {
  1545. runtime.hard_log_level = SWITCH_LOG_DEBUG;
  1546. }
  1547. runtime.mailer_app = "sendmail";
  1548. runtime.mailer_app_args = "-t";
  1549. runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION;
  1550. runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION;
  1551. runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION;
  1552. runtime.odbc_dbtype = DBTYPE_DEFAULT;
  1553. runtime.dbname = NULL;
  1554. #ifndef WIN32
  1555. runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);
  1556. #else
  1557. {
  1558. SYSTEM_INFO sysinfo;
  1559. GetSystemInfo( &sysinfo );
  1560. runtime.cpu_count = sysinfo.dwNumberOfProcessors;
  1561. }
  1562. #endif
  1563. if (!runtime.cpu_count) runtime.cpu_count = 1;
  1564. if (sqlite3_initialize() != SQLITE_OK) {
  1565. *err = "FATAL ERROR! Could not initialize SQLite\n";
  1566. return SWITCH_STATUS_MEMERR;
  1567. }
  1568. /* INIT APR and Create the pool context */
  1569. if (fspr_initialize() != SWITCH_STATUS_SUCCESS) {
  1570. *err = "FATAL ERROR! Could not initialize APR\n";
  1571. return SWITCH_STATUS_MEMERR;
  1572. }
  1573. if (!(runtime.memory_pool = switch_core_memory_init())) {
  1574. *err = "FATAL ERROR! Could not allocate memory pool\n";
  1575. return SWITCH_STATUS_MEMERR;
  1576. }
  1577. switch_assert(runtime.memory_pool != NULL);
  1578. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1579. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1580. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1581. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1582. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1583. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1584. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1585. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1586. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1587. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.fonts_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1588. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.images_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1589. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1590. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1591. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1592. switch_dir_make_recursive(SWITCH_GLOBAL_dirs.certs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
  1593. switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
  1594. switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
  1595. switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
  1596. switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
  1597. switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool);
  1598. switch_core_set_globals();
  1599. switch_core_session_init(runtime.memory_pool);
  1600. switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);
  1601. switch_core_hash_init_case(&runtime.mime_types, SWITCH_FALSE);
  1602. switch_core_hash_init_case(&runtime.mime_type_exts, SWITCH_FALSE);
  1603. switch_core_hash_init_case(&runtime.ptimes, SWITCH_FALSE);
  1604. load_mime_types();
  1605. runtime.flags |= flags;
  1606. runtime.sps_total = 30;
  1607. *err = NULL;
  1608. if (console) {
  1609. runtime.console = stdout;
  1610. }
  1611. SSL_library_init();
  1612. switch_ssl_init_ssl_locks();
  1613. OpenSSL_add_all_algorithms();
  1614. switch_curl_init();
  1615. switch_core_set_variable("hostname", runtime.hostname);
  1616. switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
  1617. switch_core_set_variable("local_ip_v4", guess_ip);
  1618. in.s_addr = mask;
  1619. switch_core_set_variable("local_mask_v4", inet_ntoa(in));
  1620. switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6);
  1621. switch_core_set_variable("local_ip_v6", guess_ip);
  1622. switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
  1623. switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir);
  1624. switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir);
  1625. switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir);
  1626. switch_core_set_variable("conf_dir", SWITCH_GLOBAL_dirs.conf_dir);
  1627. switch_core_set_variable("log_dir", SWITCH_GLOBAL_dirs.log_dir);
  1628. switch_core_set_variable("run_dir", SWITCH_GLOBAL_dirs.run_dir);
  1629. switch_core_set_variable("db_dir", SWITCH_GLOBAL_dirs.db_dir);
  1630. switch_core_set_variable("mod_dir", SWITCH_GLOBAL_dirs.mod_dir);
  1631. switch_core_set_variable("htdocs_dir", SWITCH_GLOBAL_dirs.htdocs_dir);
  1632. switch_core_set_variable("script_dir", SWITCH_GLOBAL_dirs.script_dir);
  1633. switch_core_set_variable("temp_dir", SWITCH_GLOBAL_dirs.temp_dir);
  1634. switch_core_set_variable("grammar_dir", SWITCH_GLOBAL_dirs.grammar_dir);
  1635. switch_core_set_variable("fonts_dir", SWITCH_GLOBAL_dirs.fonts_dir);
  1636. switch_core_set_variable("images_dir", SWITCH_GLOBAL_dirs.images_dir);
  1637. switch_core_set_variable("certs_dir", SWITCH_GLOBAL_dirs.certs_dir);
  1638. switch_core_set_variable("storage_dir", SWITCH_GLOBAL_dirs.storage_dir);
  1639. switch_core_set_variable("cache_dir", SWITCH_GLOBAL_dirs.cache_dir);
  1640. switch_core_set_variable("data_dir", SWITCH_GLOBAL_dirs.data_dir);
  1641. switch_core_set_variable("localstate_dir", SWITCH_GLOBAL_dirs.localstate_dir);
  1642. switch_console_init(runtime.memory_pool);
  1643. switch_event_init(runtime.memory_pool);
  1644. switch_channel_global_init(runtime.memory_pool);
  1645. if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
  1646. /* allow missing configuration if MINIMAL */
  1647. if (!(flags & SCF_MINIMAL)) {
  1648. fspr_terminate();
  1649. return SWITCH_STATUS_MEMERR;
  1650. }
  1651. }
  1652. if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
  1653. switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING));
  1654. }
  1655. switch_log_init(runtime.memory_pool, runtime.colorize_console);
  1656. runtime.tipping_point = 0;
  1657. runtime.timer_affinity = -1;
  1658. runtime.microseconds_per_tick = 20000;
  1659. if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS;
  1660. switch_load_core_config("switch.conf");
  1661. switch_core_state_machine_init(runtime.memory_pool);
  1662. switch_core_media_init();
  1663. switch_scheduler_task_thread_start();
  1664. switch_nat_late_init();
  1665. switch_rtp_init(runtime.memory_pool);
  1666. runtime.running = 1;
  1667. runtime.initiated = switch_mono_micro_time_now();
  1668. switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
  1669. switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD);
  1670. switch_uuid_get(&uuid);
  1671. switch_uuid_format(runtime.uuid_str, &uuid);
  1672. switch_core_set_variable("core_uuid", runtime.uuid_str);
  1673. return SWITCH_STATUS_SUCCESS;
  1674. }
  1675. #ifdef TRAP_BUS
  1676. static void handle_SIGBUS(int sig)
  1677. {
  1678. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n");
  1679. return;
  1680. }
  1681. #endif
  1682. static void handle_SIGHUP(int sig)
  1683. {
  1684. if (sig) {
  1685. switch_event_t *event;
  1686. if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
  1687. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP");
  1688. switch_event_fire(&event);
  1689. }
  1690. }
  1691. return;
  1692. }
  1693. SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number)
  1694. {
  1695. uint32_t *p;
  1696. if ((p = switch_core_hash_find(runtime.ptimes, name))) {
  1697. return *p;
  1698. }
  1699. return 20;
  1700. }
  1701. SWITCH_DECLARE(uint32_t) switch_default_rate(const char *name, uint32_t number)
  1702. {
  1703. if (!strcasecmp(name, "opus")) {
  1704. return 48000;
  1705. } else if (!strncasecmp(name, "h26", 3)) { // h26x
  1706. return 90000;
  1707. } else if (!strncasecmp(name, "vp", 2)) { // vp8, vp9
  1708. return 90000;
  1709. }
  1710. return 8000;
  1711. }
  1712. static uint32_t d_30 = 30;
  1713. static void switch_load_core_config(const char *file)
  1714. {
  1715. switch_xml_t xml = NULL, cfg = NULL;
  1716. switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30);
  1717. switch_core_hash_insert(runtime.ptimes, "isac", &d_30);
  1718. switch_core_hash_insert(runtime.ptimes, "G723", &d_30);
  1719. if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) {
  1720. switch_xml_t settings, param;
  1721. if ((settings = switch_xml_child(cfg, "default-ptimes"))) {
  1722. for (param = switch_xml_child(settings, "codec"); param; param = param->next) {
  1723. const char *var = switch_xml_attr_soft(param, "name");
  1724. const char *val = switch_xml_attr_soft(param, "ptime");
  1725. if (!zstr(var) && !zstr(val)) {
  1726. uint32_t *p;
  1727. uint32_t v = switch_atoul(val);
  1728. if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) {
  1729. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var);
  1730. continue;
  1731. }
  1732. if (v == 0) {
  1733. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var);
  1734. continue;
  1735. }
  1736. p = switch_core_alloc(runtime.memory_pool, sizeof(*p));
  1737. *p = v;
  1738. switch_core_hash_insert(runtime.ptimes, var, p);
  1739. }
  1740. }
  1741. }
  1742. if ((settings = switch_xml_child(cfg, "settings"))) {
  1743. for (param = switch_xml_child(settings, "param"); param; param = param->next) {
  1744. const char *var = switch_xml_attr_soft(param, "name");
  1745. const char *val = switch_xml_attr_soft(param, "value");
  1746. if (!strcasecmp(var, "loglevel")) {
  1747. int level;
  1748. if (*val > 47 && *val < 58) {
  1749. level = atoi(val);
  1750. } else {
  1751. level = switch_log_str2level(val);
  1752. }
  1753. if (level != SWITCH_LOG_INVALID) {
  1754. switch_core_session_ctl(SCSC_LOGLEVEL, &level);
  1755. }
  1756. #ifdef HAVE_SETRLIMIT
  1757. } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) {
  1758. struct rlimit rlp;
  1759. memset(&rlp, 0, sizeof(rlp));
  1760. rlp.rlim_cur = RLIM_INFINITY;
  1761. rlp.rlim_max = RLIM_INFINITY;
  1762. setrlimit(RLIMIT_CORE, &rlp);
  1763. #endif
  1764. } else if (!strcasecmp(var, "debug-level")) {
  1765. int tmp = atoi(val);
  1766. if (tmp > -1 && tmp < 11) {
  1767. switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp);
  1768. }
  1769. } else if (!strcasecmp(var, "max-db-handles")) {
  1770. long tmp = atol(val);
  1771. if (tmp > 4 && tmp < 5001) {
  1772. runtime.max_db_handles = (uint32_t) tmp;
  1773. } else {
  1774. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n");
  1775. }
  1776. } else if (!strcasecmp(var, "odbc-skip-autocommit-flip")) {
  1777. if (switch_true(val)) {
  1778. switch_odbc_skip_autocommit_flip();
  1779. }
  1780. } else if (!strcasecmp(var, "db-handle-timeout")) {
  1781. long tmp = atol(val);
  1782. if (tmp > 0 && tmp < 5001) {
  1783. runtime.db_handle_timeout = (uint32_t) tmp * 1000000;
  1784. } else {
  1785. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n");
  1786. }
  1787. } else if (!strcasecmp(var, "event-heartbeat-interval")) {
  1788. long tmp = atol(val);
  1789. if (tmp > 0) {
  1790. runtime.event_heartbeat_interval = (uint32_t) tmp;
  1791. } else {
  1792. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "heartbeat-interval must be a greater than 0\n");
  1793. }
  1794. } else if (!strcasecmp(var, "multiple-registrations")) {
  1795. runtime.multiple_registrations = switch_true(val);
  1796. } else if (!strcasecmp(var, "auto-create-schemas")) {
  1797. if (switch_true(val)) {
  1798. switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);
  1799. } else {
  1800. switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS);
  1801. }
  1802. } else if (!strcasecmp(var, "session-thread-pool")) {
  1803. if (switch_true(val)) {
  1804. switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);
  1805. } else {
  1806. switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL);
  1807. }
  1808. } else if (!strcasecmp(var, "auto-clear-sql")) {
  1809. if (switch_true(val)) {
  1810. switch_set_flag((&runtime), SCF_CLEAR_SQL);
  1811. } else {
  1812. switch_clear_flag((&runtime), SCF_CLEAR_SQL);
  1813. }
  1814. } else if (!strcasecmp(var, "api-expansion")) {
  1815. if (switch_true(val)) {
  1816. switch_set_flag((&runtime), SCF_API_EXPANSION);
  1817. } else {
  1818. switch_clear_flag((&runtime), SCF_API_EXPANSION);
  1819. }
  1820. } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) {
  1821. switch_set_flag((&runtime), SCF_EARLY_HANGUP);
  1822. } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) {
  1823. runtime.colorize_console = SWITCH_TRUE;
  1824. } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) {
  1825. runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);
  1826. } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) {
  1827. runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);
  1828. } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) {
  1829. runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);
  1830. } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) {
  1831. runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);
  1832. } else if (!strcasecmp(var, "dialplan-timestamps")) {
  1833. if (switch_true(val)) {
  1834. switch_set_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
  1835. } else {
  1836. switch_clear_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
  1837. }
  1838. } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) {
  1839. runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val);
  1840. } else if (!strcasecmp(var, "mailer-app-args") && val) {
  1841. runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val);
  1842. } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) {
  1843. switch_core_sessions_per_second(atoi(val));
  1844. } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) {
  1845. int tmp = atoi(val);
  1846. if (tmp > 0) {
  1847. switch_core_max_dtmf_duration((uint32_t) tmp);
  1848. }
  1849. } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) {
  1850. int tmp = atoi(val);
  1851. if (tmp > 0) {
  1852. switch_core_min_dtmf_duration((uint32_t) tmp);
  1853. }
  1854. } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) {
  1855. int tmp = atoi(val);
  1856. if (tmp > 0) {
  1857. switch_core_default_dtmf_duration((uint32_t) tmp);
  1858. }
  1859. } else if (!strcasecmp(var, "enable-use-system-time")) {
  1860. switch_time_set_use_system_time(switch_true(val));
  1861. } else if (!strcasecmp(var, "enable-monotonic-timing")) {
  1862. switch_time_set_monotonic(switch_true(val));
  1863. } else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
  1864. int ival = 0;
  1865. if (val) {
  1866. if (switch_true(val)) {
  1867. ival = 2;
  1868. } else {
  1869. if (strcasecmp(val, "broadcast")) {
  1870. ival = 1;
  1871. } else if (strcasecmp(val, "fd-per-timer")) {
  1872. ival = 2;
  1873. }
  1874. }
  1875. }
  1876. switch_time_set_timerfd(ival);
  1877. } else if (!strcasecmp(var, "enable-clock-nanosleep")) {
  1878. switch_time_set_nanosleep(switch_true(val));
  1879. } else if (!strcasecmp(var, "enable-cond-yield")) {
  1880. switch_time_set_cond_yield(switch_true(val));
  1881. } else if (!strcasecmp(var, "enable-timer-matrix")) {
  1882. switch_time_set_matrix(switch_true(val));
  1883. } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {
  1884. switch_core_session_limit(atoi(val));
  1885. } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) {
  1886. int v = switch_true(val);
  1887. if (v) {
  1888. switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);
  1889. } else {
  1890. switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);
  1891. }
  1892. } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) {
  1893. #ifdef WIN32
  1894. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n");
  1895. #else
  1896. int v = switch_true(val);
  1897. if (v) {
  1898. switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  1899. } else {
  1900. switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  1901. }
  1902. #endif
  1903. } else if (!strcasecmp(var, "spawn-instead-of-system") && !zstr(val)) {
  1904. #ifdef WIN32
  1905. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "spawn-instead-of-system is not implemented on this platform\n");
  1906. #else
  1907. int v = switch_true(val);
  1908. if (v) {
  1909. switch_core_set_variable("spawn_instead_of_system", "true");
  1910. } else {
  1911. switch_core_set_variable("spawn_instead_of_system", "false");
  1912. }
  1913. #endif
  1914. } else if (!strcasecmp(var, "exclude-error-log-from-xml-cdr") && !zstr(val)) {
  1915. int v = switch_true(val);
  1916. if (v) {
  1917. switch_core_set_variable("exclude_error_log_from_xml_cdr", "true");
  1918. } else {
  1919. switch_core_set_variable("exclude_error_log_from_xml_cdr", "false");
  1920. }
  1921. } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) {
  1922. switch_core_min_idle_cpu(atof(val));
  1923. } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) {
  1924. runtime.tipping_point = atoi(val);
  1925. } else if (!strcasecmp(var, "cpu-idle-smoothing-depth") && !zstr(val)) {
  1926. runtime.cpu_idle_smoothing_depth = atoi(val);
  1927. } else if (!strcasecmp(var, "events-use-dispatch") && !zstr(val)) {
  1928. runtime.events_use_dispatch = switch_true(val);
  1929. } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) {
  1930. int tmp;
  1931. if (!runtime.events_use_dispatch) {
  1932. runtime.events_use_dispatch = 1;
  1933. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
  1934. "Implicitly setting events-use-dispatch based on usage of this initial-event-threads parameter.\n");
  1935. }
  1936. tmp = atoi(val);
  1937. if (tmp > runtime.cpu_count / 2) {
  1938. tmp = runtime.cpu_count / 2;
  1939. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n",
  1940. runtime.cpu_count / 2);
  1941. }
  1942. if (tmp < 1) {
  1943. tmp = 1;
  1944. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n");
  1945. }
  1946. switch_event_launch_dispatch_threads(tmp);
  1947. } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) {
  1948. runtime.microseconds_per_tick = 1000;
  1949. } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) {
  1950. if (!strcasecmp(val, "disabled")) {
  1951. runtime.timer_affinity = -1;
  1952. } else {
  1953. runtime.timer_affinity = atoi(val);
  1954. }
  1955. } else if (!strcasecmp(var, "ice-resolve-candidate")) {
  1956. switch_core_media_set_resolveice(switch_true(val));
  1957. } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) {
  1958. switch_rtp_set_start_port((switch_port_t) atoi(val));
  1959. } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) {
  1960. switch_rtp_set_end_port((switch_port_t) atoi(val));
  1961. } else if (!strcasecmp(var, "rtp-port-usage-robustness") && switch_true(val)) {
  1962. runtime.port_alloc_flags |= SPF_ROBUST_UDP;
  1963. } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) {
  1964. runtime.dbname = switch_core_strdup(runtime.memory_pool, val);
  1965. } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) {
  1966. runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val);
  1967. } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) {
  1968. switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ);
  1969. } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) {
  1970. if (!strcasecmp(val, "MSSQL")) {
  1971. runtime.odbc_dbtype = DBTYPE_MSSQL;
  1972. } else {
  1973. runtime.odbc_dbtype = DBTYPE_DEFAULT;
  1974. }
  1975. } else if (!strcasecmp(var, "switchname") && !zstr(val)) {
  1976. runtime.switchname = switch_core_strdup(runtime.memory_pool, val);
  1977. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname);
  1978. } else if (!strcasecmp(var, "rtp-retain-crypto-keys")) {
  1979. if (switch_true(val)) {
  1980. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
  1981. "rtp-retain-crypto-keys enabled. Could be used to decrypt secure media.\n");
  1982. }
  1983. switch_core_set_variable("rtp_retain_crypto_keys", val);
  1984. } else if (!strcasecmp(var, "caller-profile-soft-variables-uses-prefix") && !zstr(val)) {
  1985. int v = switch_true(val);
  1986. if (v) {
  1987. switch_set_flag((&runtime), SCF_CPF_SOFT_PREFIX);
  1988. } else {
  1989. switch_clear_flag((&runtime), SCF_CPF_SOFT_PREFIX);
  1990. }
  1991. } else if (!strcasecmp(var, "caller-profile-soft-lookup-values") && !zstr(val)) {
  1992. int v = switch_true(val);
  1993. if (v) {
  1994. switch_set_flag((&runtime), SCF_CPF_SOFT_LOOKUP);
  1995. } else {
  1996. switch_clear_flag((&runtime), SCF_CPF_SOFT_LOOKUP);
  1997. }
  1998. } else if (!strcasecmp(var, "event-channel-key-separator") && !zstr(val)) {
  1999. runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, val);
  2000. } else if (!strcasecmp(var, "event-channel-enable-hierarchy-deliver") && !zstr(val)) {
  2001. int v = switch_true(val);
  2002. if (v) {
  2003. switch_set_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY);
  2004. } else {
  2005. switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY);
  2006. }
  2007. } else if (!strcasecmp(var, "event-channel-hierarchy-deliver-once") && !zstr(val)) {
  2008. int v = switch_true(val);
  2009. if (v) {
  2010. switch_set_flag((&runtime), SCF_EVENT_CHANNEL_HIERARCHY_DELIVERY_ONCE);
  2011. } else {
  2012. switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_HIERARCHY_DELIVERY_ONCE);
  2013. }
  2014. } else if (!strcasecmp(var, "event-channel-log-undeliverable-json") && !zstr(val)) {
  2015. int v = switch_true(val);
  2016. if (v) {
  2017. switch_set_flag((&runtime), SCF_EVENT_CHANNEL_LOG_UNDELIVERABLE_JSON);
  2018. } else {
  2019. switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_LOG_UNDELIVERABLE_JSON);
  2020. }
  2021. } else if (!strcasecmp(var, "max-audio-channels") && !zstr(val)) {
  2022. switch_core_max_audio_channels(atoi(val));
  2023. }
  2024. }
  2025. }
  2026. if (runtime.event_channel_key_separator == NULL) {
  2027. runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, ".");
  2028. }
  2029. if ((settings = switch_xml_child(cfg, "variables"))) {
  2030. for (param = switch_xml_child(settings, "variable"); param; param = param->next) {
  2031. const char *var = switch_xml_attr_soft(param, "name");
  2032. const char *val = switch_xml_attr_soft(param, "value");
  2033. if (var && val) {
  2034. switch_core_set_variable(var, val);
  2035. }
  2036. }
  2037. }
  2038. switch_xml_free(xml);
  2039. }
  2040. }
  2041. SWITCH_DECLARE(const char *) switch_core_banner(void)
  2042. {
  2043. return ("\n"
  2044. ".=============================================================.\n"
  2045. "| _____ ______ _____ _____ ____ _ _ |\n"
  2046. "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n"
  2047. "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n"
  2048. "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n"
  2049. "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n"
  2050. "| |\n"
  2051. ".=============================================================."
  2052. "\n"
  2053. "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n"
  2054. "| FreeSWITCH (http://www.freeswitch.org) |\n"
  2055. "| Paypal Donations Appreciated: paypal@freeswitch.org |\n"
  2056. "| Brought to you by ClueCon http://www.cluecon.com/ |\n"
  2057. ".=============================================================.\n"
  2058. "\n");
  2059. }
  2060. switch_status_t switch_core_sqldb_init(const char **err)
  2061. {
  2062. if (switch_core_check_core_db_dsn() != SWITCH_STATUS_SUCCESS) {
  2063. *err = "NO SUITABLE DATABASE INTERFACE IS AVAILABLE TO SERVE 'core-db-dsn'!\n";
  2064. return SWITCH_STATUS_GENERR;
  2065. }
  2066. if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
  2067. *err = "Error activating database";
  2068. return SWITCH_STATUS_GENERR;
  2069. }
  2070. return SWITCH_STATUS_SUCCESS;
  2071. }
  2072. SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err)
  2073. {
  2074. switch_event_t *event;
  2075. char *cmd;
  2076. int x = 0;
  2077. const char *use = NULL;
  2078. #include "cc.h"
  2079. if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) {
  2080. return SWITCH_STATUS_GENERR;
  2081. }
  2082. if (runtime.runlevel > 1) {
  2083. /* one per customer */
  2084. return SWITCH_STATUS_SUCCESS;
  2085. }
  2086. runtime.runlevel++;
  2087. runtime.events_use_dispatch = 1;
  2088. switch_core_set_signal_handlers();
  2089. switch_load_network_lists(SWITCH_FALSE);
  2090. switch_msrp_init();
  2091. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n");
  2092. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n");
  2093. if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
  2094. *err = "Cannot load modules";
  2095. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err);
  2096. return SWITCH_STATUS_GENERR;
  2097. }
  2098. switch_load_network_lists(SWITCH_FALSE);
  2099. switch_load_core_config("post_load_switch.conf");
  2100. switch_core_set_signal_handlers();
  2101. if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
  2102. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
  2103. switch_event_fire(&event);
  2104. }
  2105. switch_core_screen_size(&x, NULL);
  2106. use = (x > 100) ? cc : cc_s;
  2107. #ifdef WIN32
  2108. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use);
  2109. #else
  2110. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n",
  2111. SWITCH_SEQ_DEFAULT_COLOR,
  2112. SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE,
  2113. switch_core_banner(),
  2114. use, SWITCH_SEQ_DEFAULT_COLOR);
  2115. #endif
  2116. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
  2117. "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n",
  2118. switch_version_full(), switch_version_revision_human(),
  2119. switch_core_session_limit(0),
  2120. switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled");
  2121. if (x < 160) {
  2122. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n");
  2123. }
  2124. switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2125. if ((cmd = switch_core_get_variable_dup("api_on_startup"))) {
  2126. switch_stream_handle_t stream = { 0 };
  2127. SWITCH_STANDARD_STREAM(stream);
  2128. switch_console_execute(cmd, 0, &stream);
  2129. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data);
  2130. free(stream.data);
  2131. free(cmd);
  2132. }
  2133. #ifdef HAVE_SYSTEMD
  2134. sd_notifyf(0, "READY=1\n"
  2135. "MAINPID=%lu\n", (unsigned long) getpid());
  2136. #endif
  2137. return SWITCH_STATUS_SUCCESS;
  2138. }
  2139. SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration)
  2140. {
  2141. switch_time_t temp = total_ms / 1000;
  2142. memset(duration, 0, sizeof(*duration));
  2143. duration->mms = (uint32_t) (total_ms % 1000);
  2144. duration->ms = (uint32_t) (temp % 1000);
  2145. temp = temp / 1000;
  2146. duration->sec = (uint32_t) (temp % 60);
  2147. temp = temp / 60;
  2148. duration->min = (uint32_t) (temp % 60);
  2149. temp = temp / 60;
  2150. duration->hr = (uint32_t) (temp % 24);
  2151. temp = temp / 24;
  2152. duration->day = (uint32_t) (temp % 365);
  2153. duration->yr = (uint32_t) (temp / 365);
  2154. }
  2155. SWITCH_DECLARE(switch_time_t) switch_core_uptime(void)
  2156. {
  2157. return switch_mono_micro_time_now() - runtime.initiated;
  2158. }
  2159. #ifdef _MSC_VER
  2160. static void win_shutdown(void)
  2161. {
  2162. HANDLE shutdown_event;
  2163. char path[512];
  2164. /* for windows we need the event to signal for shutting down a background FreeSWITCH */
  2165. snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
  2166. /* open the event so we can signal it */
  2167. shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path);
  2168. if (shutdown_event) {
  2169. /* signal the event to shutdown */
  2170. SetEvent(shutdown_event);
  2171. /* cleanup */
  2172. CloseHandle(shutdown_event);
  2173. }
  2174. }
  2175. #endif
  2176. SWITCH_DECLARE(void) switch_core_set_signal_handlers(void)
  2177. {
  2178. /* set signal handlers */
  2179. signal(SIGINT, SIG_IGN);
  2180. #ifdef SIGPIPE
  2181. signal(SIGPIPE, SIG_IGN);
  2182. #endif
  2183. #ifdef SIGALRM
  2184. signal(SIGALRM, SIG_IGN);
  2185. #endif
  2186. #ifdef SIGQUIT
  2187. signal(SIGQUIT, SIG_IGN);
  2188. #endif
  2189. #ifdef SIGPOLL
  2190. signal(SIGPOLL, SIG_IGN);
  2191. #endif
  2192. #ifdef SIGIO
  2193. signal(SIGIO, SIG_IGN);
  2194. #endif
  2195. #ifdef TRAP_BUS
  2196. signal(SIGBUS, handle_SIGBUS);
  2197. #endif
  2198. #ifdef SIGUSR1
  2199. signal(SIGUSR1, handle_SIGHUP);
  2200. #endif
  2201. signal(SIGHUP, handle_SIGHUP);
  2202. }
  2203. SWITCH_DECLARE(uint32_t) switch_core_debug_level(void)
  2204. {
  2205. return runtime.debug_level;
  2206. }
  2207. SWITCH_DECLARE(int32_t) switch_core_sps(void)
  2208. {
  2209. return runtime.sps;
  2210. }
  2211. SWITCH_DECLARE(int32_t) switch_core_sps_last(void)
  2212. {
  2213. return runtime.sps_last;
  2214. }
  2215. SWITCH_DECLARE(int32_t) switch_core_sps_peak(void)
  2216. {
  2217. return runtime.sps_peak;
  2218. }
  2219. SWITCH_DECLARE(int32_t) switch_core_sps_peak_fivemin(void)
  2220. {
  2221. return runtime.sps_peak_fivemin;
  2222. }
  2223. SWITCH_DECLARE(int32_t) switch_core_sessions_peak(void)
  2224. {
  2225. return runtime.sessions_peak;
  2226. }
  2227. SWITCH_DECLARE(int32_t) switch_core_sessions_peak_fivemin(void)
  2228. {
  2229. return runtime.sessions_peak_fivemin;
  2230. }
  2231. SWITCH_DECLARE(uint32_t) switch_core_max_audio_channels(uint32_t limit)
  2232. {
  2233. if (limit) {
  2234. runtime.max_audio_channels = limit;
  2235. }
  2236. return runtime.max_audio_channels;
  2237. }
  2238. SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val)
  2239. {
  2240. int *intval = (int *) val;
  2241. int oldintval = 0, newintval = 0;
  2242. if (intval) {
  2243. oldintval = *intval;
  2244. }
  2245. if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) {
  2246. return -1;
  2247. }
  2248. switch (cmd) {
  2249. case SCSC_RECOVER:
  2250. {
  2251. char *arg = (char *) val;
  2252. char *tech = NULL, *prof = NULL;
  2253. int r, flush = 0;
  2254. if (!zstr(arg)) {
  2255. tech = strdup(arg);
  2256. switch_assert(tech);
  2257. if ((prof = strchr(tech, ':'))) {
  2258. *prof++ = '\0';
  2259. }
  2260. if (!strcasecmp(tech, "flush")) {
  2261. flush++;
  2262. if (prof) {
  2263. char *tech = prof;
  2264. if ((prof = strchr(tech, ':'))) {
  2265. *prof++ = '\0';
  2266. }
  2267. }
  2268. }
  2269. }
  2270. if (flush) {
  2271. switch_core_recovery_flush(tech, prof);
  2272. r = -1;
  2273. } else {
  2274. r = switch_core_recovery_recover(tech, prof);
  2275. }
  2276. switch_safe_free(tech);
  2277. return r;
  2278. }
  2279. break;
  2280. case SCSC_DEBUG_SQL:
  2281. {
  2282. if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) {
  2283. switch_clear_flag((&runtime), SCF_DEBUG_SQL);
  2284. newintval = 0;
  2285. } else {
  2286. switch_set_flag((&runtime), SCF_DEBUG_SQL);
  2287. newintval = 1;
  2288. }
  2289. }
  2290. break;
  2291. case SCSC_VERBOSE_EVENTS:
  2292. if (intval) {
  2293. if (oldintval > -1) {
  2294. if (oldintval) {
  2295. switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);
  2296. } else {
  2297. switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);
  2298. }
  2299. }
  2300. newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS);
  2301. }
  2302. break;
  2303. case SCSC_API_EXPANSION:
  2304. if (intval) {
  2305. if (oldintval > -1) {
  2306. if (oldintval) {
  2307. switch_set_flag((&runtime), SCF_API_EXPANSION);
  2308. } else {
  2309. switch_clear_flag((&runtime), SCF_API_EXPANSION);
  2310. }
  2311. }
  2312. newintval = switch_test_flag((&runtime), SCF_API_EXPANSION);
  2313. }
  2314. break;
  2315. case SCSC_THREADED_SYSTEM_EXEC:
  2316. if (intval) {
  2317. if (oldintval > -1) {
  2318. if (oldintval) {
  2319. switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  2320. } else {
  2321. switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  2322. }
  2323. }
  2324. newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
  2325. }
  2326. break;
  2327. case SCSC_CALIBRATE_CLOCK:
  2328. switch_time_calibrate_clock();
  2329. break;
  2330. case SCSC_FLUSH_DB_HANDLES:
  2331. switch_cache_db_flush_handles();
  2332. break;
  2333. case SCSC_SEND_SIGHUP:
  2334. handle_SIGHUP(1);
  2335. break;
  2336. case SCSC_SYNC_CLOCK:
  2337. switch_time_sync();
  2338. newintval = 0;
  2339. break;
  2340. case SCSC_SYNC_CLOCK_WHEN_IDLE:
  2341. newintval = switch_core_session_sync_clock();
  2342. break;
  2343. case SCSC_SQL:
  2344. if (oldintval) {
  2345. switch_core_sqldb_resume();
  2346. } else {
  2347. switch_core_sqldb_pause();
  2348. }
  2349. break;
  2350. case SCSC_PAUSE_ALL:
  2351. if (oldintval) {
  2352. switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2353. } else {
  2354. switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2355. }
  2356. break;
  2357. case SCSC_PAUSE_INBOUND:
  2358. if (oldintval) {
  2359. switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
  2360. } else {
  2361. switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
  2362. }
  2363. break;
  2364. case SCSC_PAUSE_OUTBOUND:
  2365. if (oldintval) {
  2366. switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
  2367. } else {
  2368. switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
  2369. }
  2370. break;
  2371. case SCSC_HUPALL:
  2372. switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST);
  2373. break;
  2374. case SCSC_CANCEL_SHUTDOWN:
  2375. switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
  2376. break;
  2377. case SCSC_SAVE_HISTORY:
  2378. switch_console_save_history();
  2379. break;
  2380. case SCSC_CRASH:
  2381. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n");
  2382. switch_console_save_history();
  2383. abort();
  2384. break;
  2385. case SCSC_SHUTDOWN_NOW:
  2386. switch_console_save_history();
  2387. exit(0);
  2388. break;
  2389. case SCSC_REINCARNATE_NOW:
  2390. switch_console_save_history();
  2391. exit(SWITCH_STATUS_RESTART);
  2392. break;
  2393. case SCSC_SHUTDOWN_ELEGANT:
  2394. case SCSC_SHUTDOWN_ASAP:
  2395. {
  2396. int x = 19;
  2397. uint32_t count;
  2398. switch_event_t *shutdown_requested_event = NULL;
  2399. if (switch_event_create(&shutdown_requested_event, SWITCH_EVENT_SHUTDOWN_REQUESTED) == SWITCH_STATUS_SUCCESS) {
  2400. switch_event_add_header(shutdown_requested_event, SWITCH_STACK_BOTTOM, "Event-Info", "%s", cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "elegant");
  2401. switch_event_fire(&shutdown_requested_event);
  2402. }
  2403. switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
  2404. if (cmd == SCSC_SHUTDOWN_ASAP) {
  2405. switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2406. }
  2407. while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) {
  2408. switch_yield(500000);
  2409. if (++x == 20) {
  2410. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
  2411. "Shutdown in progress, %u session(s) remain.\nShutting down %s\n",
  2412. count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls.");
  2413. x = 0;
  2414. }
  2415. }
  2416. if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) {
  2417. switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2418. #ifdef _MSC_VER
  2419. win_shutdown();
  2420. #endif
  2421. if (oldintval) {
  2422. switch_set_flag((&runtime), SCF_RESTART);
  2423. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");
  2424. } else {
  2425. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");
  2426. #ifdef HAVE_SYSTEMD
  2427. sd_notifyf(0, "STOPPING=1\n");
  2428. #endif
  2429. #ifdef _MSC_VER
  2430. fclose(stdin);
  2431. #endif
  2432. }
  2433. runtime.running = 0;
  2434. } else {
  2435. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n");
  2436. switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2437. }
  2438. }
  2439. break;
  2440. case SCSC_PAUSE_CHECK:
  2441. newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS);
  2442. break;
  2443. case SCSC_PAUSE_INBOUND_CHECK:
  2444. newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
  2445. break;
  2446. case SCSC_PAUSE_OUTBOUND_CHECK:
  2447. newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
  2448. break;
  2449. case SCSC_READY_CHECK:
  2450. newintval = switch_core_ready();
  2451. break;
  2452. case SCSC_SHUTDOWN_CHECK:
  2453. newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
  2454. break;
  2455. case SCSC_SHUTDOWN:
  2456. #ifdef _MSC_VER
  2457. win_shutdown();
  2458. #endif
  2459. if (oldintval) {
  2460. switch_set_flag((&runtime), SCF_RESTART);
  2461. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");
  2462. } else {
  2463. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");
  2464. #ifdef _MSC_VER
  2465. fclose(stdin);
  2466. #endif
  2467. }
  2468. runtime.running = 0;
  2469. break;
  2470. case SCSC_CHECK_RUNNING:
  2471. newintval = runtime.running;
  2472. break;
  2473. case SCSC_LOGLEVEL:
  2474. if (oldintval >= SWITCH_LOG_DISABLE) {
  2475. runtime.hard_log_level = oldintval;
  2476. }
  2477. if (runtime.hard_log_level > SWITCH_LOG_DEBUG) {
  2478. runtime.hard_log_level = SWITCH_LOG_DEBUG;
  2479. }
  2480. newintval = runtime.hard_log_level;
  2481. break;
  2482. case SCSC_DEBUG_LEVEL:
  2483. if (oldintval > -1) {
  2484. if (oldintval > 10)
  2485. oldintval = 10;
  2486. runtime.debug_level = oldintval;
  2487. }
  2488. newintval = runtime.debug_level;
  2489. break;
  2490. case SCSC_MIN_IDLE_CPU:
  2491. {
  2492. double *dval = (double *) val;
  2493. if (dval) {
  2494. *dval = switch_core_min_idle_cpu(*dval);
  2495. }
  2496. intval = NULL;
  2497. }
  2498. break;
  2499. case SCSC_MAX_SESSIONS:
  2500. newintval = switch_core_session_limit(oldintval);
  2501. break;
  2502. case SCSC_LAST_SPS:
  2503. newintval = runtime.sps_last;
  2504. break;
  2505. case SCSC_SPS_PEAK:
  2506. if (oldintval == -1) {
  2507. runtime.sps_peak = 0;
  2508. }
  2509. newintval = runtime.sps_peak;
  2510. break;
  2511. case SCSC_SPS_PEAK_FIVEMIN:
  2512. newintval = runtime.sps_peak_fivemin;
  2513. break;
  2514. case SCSC_SESSIONS_PEAK:
  2515. newintval = runtime.sessions_peak;
  2516. break;
  2517. case SCSC_SESSIONS_PEAK_FIVEMIN:
  2518. newintval = runtime.sessions_peak_fivemin;
  2519. break;
  2520. case SCSC_MAX_DTMF_DURATION:
  2521. newintval = switch_core_max_dtmf_duration(oldintval);
  2522. break;
  2523. case SCSC_MIN_DTMF_DURATION:
  2524. newintval = switch_core_min_dtmf_duration(oldintval);
  2525. break;
  2526. case SCSC_DEFAULT_DTMF_DURATION:
  2527. newintval = switch_core_default_dtmf_duration(oldintval);
  2528. break;
  2529. case SCSC_SPS:
  2530. switch_mutex_lock(runtime.throttle_mutex);
  2531. if (oldintval > 0) {
  2532. runtime.sps_total = oldintval;
  2533. }
  2534. newintval = runtime.sps_total;
  2535. switch_mutex_unlock(runtime.throttle_mutex);
  2536. break;
  2537. case SCSC_RECLAIM:
  2538. switch_core_memory_reclaim_all();
  2539. newintval = 0;
  2540. break;
  2541. case SCSC_MDNS_RESOLVE:
  2542. switch_core_media_set_resolveice(!!oldintval);
  2543. break;
  2544. case SCSC_SHUTDOWN_CAUSE:
  2545. runtime.shutdown_cause = oldintval;
  2546. break;
  2547. }
  2548. if (intval) {
  2549. *intval = newintval;
  2550. }
  2551. return 0;
  2552. }
  2553. SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void)
  2554. {
  2555. return runtime.flags;
  2556. }
  2557. SWITCH_DECLARE(switch_bool_t) switch_core_running(void)
  2558. {
  2559. return runtime.running ? SWITCH_TRUE : SWITCH_FALSE;
  2560. }
  2561. SWITCH_DECLARE(switch_bool_t) switch_core_ready(void)
  2562. {
  2563. return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE;
  2564. }
  2565. SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void)
  2566. {
  2567. return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;
  2568. }
  2569. SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void)
  2570. {
  2571. return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;
  2572. }
  2573. void switch_core_sqldb_destroy(void)
  2574. {
  2575. if (switch_test_flag((&runtime), SCF_USE_SQL)) {
  2576. switch_core_sqldb_stop();
  2577. }
  2578. }
  2579. SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
  2580. {
  2581. switch_event_t *event;
  2582. if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) {
  2583. switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down");
  2584. switch_event_fire(&event);
  2585. }
  2586. switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
  2587. switch_set_flag((&runtime), SCF_SHUTTING_DOWN);
  2588. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");
  2589. switch_core_session_hupall(runtime.shutdown_cause);
  2590. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");
  2591. switch_loadable_module_shutdown();
  2592. switch_curl_destroy();
  2593. switch_ssl_destroy_ssl_locks();
  2594. EVP_cleanup();
  2595. switch_scheduler_task_thread_stop();
  2596. switch_rtp_shutdown();
  2597. switch_msrp_destroy();
  2598. if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
  2599. switch_nat_shutdown();
  2600. }
  2601. switch_xml_destroy();
  2602. switch_console_shutdown();
  2603. switch_channel_global_uninit();
  2604. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");
  2605. switch_event_shutdown();
  2606. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
  2607. switch_log_shutdown();
  2608. switch_core_session_uninit();
  2609. switch_core_unset_variables();
  2610. switch_core_memory_stop();
  2611. if (runtime.console && runtime.console != stdout && runtime.console != stderr) {
  2612. fclose(runtime.console);
  2613. runtime.console = NULL;
  2614. }
  2615. switch_safe_free(SWITCH_GLOBAL_dirs.base_dir);
  2616. switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir);
  2617. switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir);
  2618. switch_safe_free(SWITCH_GLOBAL_dirs.log_dir);
  2619. switch_safe_free(SWITCH_GLOBAL_dirs.db_dir);
  2620. switch_safe_free(SWITCH_GLOBAL_dirs.script_dir);
  2621. switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir);
  2622. switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir);
  2623. switch_safe_free(SWITCH_GLOBAL_dirs.fonts_dir);
  2624. switch_safe_free(SWITCH_GLOBAL_dirs.images_dir);
  2625. switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir);
  2626. switch_safe_free(SWITCH_GLOBAL_dirs.cache_dir);
  2627. switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir);
  2628. switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir);
  2629. switch_safe_free(SWITCH_GLOBAL_dirs.run_dir);
  2630. switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir);
  2631. switch_safe_free(SWITCH_GLOBAL_dirs.data_dir);
  2632. switch_safe_free(SWITCH_GLOBAL_dirs.localstate_dir);
  2633. switch_safe_free(SWITCH_GLOBAL_dirs.certs_dir);
  2634. switch_safe_free(SWITCH_GLOBAL_dirs.lib_dir);
  2635. switch_safe_free(SWITCH_GLOBAL_filenames.conf_name);
  2636. switch_event_destroy(&runtime.global_vars);
  2637. switch_core_hash_destroy(&runtime.ptimes);
  2638. switch_core_hash_destroy(&runtime.mime_types);
  2639. switch_core_hash_destroy(&runtime.mime_type_exts);
  2640. if (IP_LIST.hash) {
  2641. switch_core_hash_destroy(&IP_LIST.hash);
  2642. }
  2643. if (IP_LIST.pool) {
  2644. switch_core_destroy_memory_pool(&IP_LIST.pool);
  2645. }
  2646. switch_core_media_deinit();
  2647. if (runtime.memory_pool) {
  2648. fspr_pool_destroy(runtime.memory_pool);
  2649. fspr_terminate();
  2650. }
  2651. sqlite3_shutdown();
  2652. return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS;
  2653. }
  2654. SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)
  2655. {
  2656. const switch_management_interface_t *ptr;
  2657. switch_status_t status = SWITCH_STATUS_FALSE;
  2658. if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) {
  2659. status = ptr->management_function(relative_oid, action, data, datalen);
  2660. }
  2661. return status;
  2662. }
  2663. SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void)
  2664. {
  2665. switch_core_memory_reclaim_logger();
  2666. switch_core_memory_reclaim_events();
  2667. switch_core_memory_reclaim();
  2668. }
  2669. struct system_thread_handle {
  2670. const char *cmd;
  2671. switch_thread_cond_t *cond;
  2672. switch_mutex_t *mutex;
  2673. switch_memory_pool_t *pool;
  2674. int ret;
  2675. int *fds;
  2676. };
  2677. static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj)
  2678. {
  2679. struct system_thread_handle *sth = (struct system_thread_handle *) obj;
  2680. #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
  2681. struct rlimit rlim;
  2682. struct rlimit rlim_save;
  2683. memset(&rlim, 0, sizeof(rlim));
  2684. getrlimit(RLIMIT_STACK, &rlim);
  2685. memset(&rlim_save, 0, sizeof(rlim_save));
  2686. getrlimit(RLIMIT_STACK, &rlim_save);
  2687. rlim.rlim_cur = rlim.rlim_max;
  2688. if (setrlimit(RLIMIT_STACK, &rlim) < 0) {
  2689. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
  2690. }
  2691. #endif
  2692. if (sth->fds) {
  2693. dup2(sth->fds[1], STDOUT_FILENO);
  2694. }
  2695. sth->ret = system(sth->cmd);
  2696. #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
  2697. if (setrlimit(RLIMIT_STACK, &rlim_save) < 0) {
  2698. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
  2699. }
  2700. #endif
  2701. switch_mutex_lock(sth->mutex);
  2702. switch_thread_cond_signal(sth->cond);
  2703. switch_mutex_unlock(sth->mutex);
  2704. switch_core_destroy_memory_pool(&sth->pool);
  2705. return NULL;
  2706. }
  2707. static int switch_system_thread(const char *cmd, switch_bool_t wait)
  2708. {
  2709. switch_thread_t *thread;
  2710. switch_threadattr_t *thd_attr;
  2711. int ret = 0;
  2712. struct system_thread_handle *sth;
  2713. switch_memory_pool_t *pool;
  2714. if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
  2715. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
  2716. return 1;
  2717. }
  2718. if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) {
  2719. switch_core_destroy_memory_pool(&pool);
  2720. return 1;
  2721. }
  2722. sth->pool = pool;
  2723. sth->cmd = switch_core_strdup(pool, cmd);
  2724. switch_thread_cond_create(&sth->cond, sth->pool);
  2725. switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool);
  2726. switch_mutex_lock(sth->mutex);
  2727. switch_threadattr_create(&thd_attr, sth->pool);
  2728. switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE);
  2729. switch_threadattr_detach_set(thd_attr, 1);
  2730. switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool);
  2731. if (wait) {
  2732. switch_thread_cond_wait(sth->cond, sth->mutex);
  2733. ret = sth->ret;
  2734. }
  2735. switch_mutex_unlock(sth->mutex);
  2736. return ret;
  2737. }
  2738. SWITCH_DECLARE(int) switch_max_file_desc(void)
  2739. {
  2740. int max = 0;
  2741. #ifndef WIN32
  2742. #if defined(HAVE_GETDTABLESIZE)
  2743. max = getdtablesize();
  2744. #else
  2745. max = sysconf(_SC_OPEN_MAX);
  2746. #endif
  2747. #endif
  2748. return max;
  2749. }
  2750. SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl)
  2751. {
  2752. int open_max = switch_max_file_desc();
  2753. int i, j;
  2754. for (i = 3; i < open_max; i++) {
  2755. if (keep) {
  2756. for (j = 0; j < keep_ttl; j++) {
  2757. if (i == keep[j]) {
  2758. goto skip;
  2759. }
  2760. }
  2761. }
  2762. close(i);
  2763. skip:
  2764. continue;
  2765. }
  2766. }
  2767. #ifdef WIN32
  2768. static int switch_system_fork(const char *cmd, switch_bool_t wait)
  2769. {
  2770. return switch_system_thread(cmd, wait);
  2771. }
  2772. SWITCH_DECLARE(pid_t) switch_fork(void)
  2773. {
  2774. return -1;
  2775. }
  2776. #else
  2777. SWITCH_DECLARE(pid_t) switch_fork(void)
  2778. {
  2779. int i = fork();
  2780. if (!i) {
  2781. set_low_priority();
  2782. }
  2783. return i;
  2784. }
  2785. static int switch_system_fork(const char *cmd, switch_bool_t wait)
  2786. {
  2787. int pid;
  2788. char *dcmd = strdup(cmd);
  2789. #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
  2790. struct rlimit rlim;
  2791. struct rlimit rlim_save;
  2792. #endif
  2793. switch_core_set_signal_handlers();
  2794. pid = switch_fork();
  2795. if (pid) {
  2796. if (wait) {
  2797. waitpid(pid, NULL, 0);
  2798. }
  2799. free(dcmd);
  2800. } else {
  2801. switch_close_extra_files(NULL, 0);
  2802. #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
  2803. memset(&rlim, 0, sizeof(rlim));
  2804. getrlimit(RLIMIT_STACK, &rlim);
  2805. memset(&rlim_save, 0, sizeof(rlim_save));
  2806. getrlimit(RLIMIT_STACK, &rlim_save);
  2807. rlim.rlim_cur = rlim.rlim_max;
  2808. if (setrlimit(RLIMIT_STACK, &rlim) < 0) {
  2809. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
  2810. }
  2811. #endif
  2812. if (system(dcmd) == -1) {
  2813. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd);
  2814. }
  2815. free(dcmd);
  2816. exit(0);
  2817. }
  2818. return 0;
  2819. }
  2820. #endif
  2821. SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait)
  2822. {
  2823. int retval = 0;
  2824. #ifdef __linux__
  2825. switch_bool_t spawn_instead_of_system = switch_true(switch_core_get_variable("spawn_instead_of_system"));
  2826. #else
  2827. switch_bool_t spawn_instead_of_system = SWITCH_FALSE;
  2828. #endif
  2829. if (spawn_instead_of_system) {
  2830. retval = switch_stream_spawn(cmd, SWITCH_TRUE, wait, NULL);
  2831. } else if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) {
  2832. retval = switch_system_thread(cmd, wait);
  2833. } else {
  2834. retval = switch_system_fork(cmd, wait);
  2835. }
  2836. return retval;
  2837. }
  2838. SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream)
  2839. {
  2840. return switch_stream_system(cmd, stream);
  2841. }
  2842. #ifdef __linux__
  2843. extern char **environ;
  2844. #endif
  2845. SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t shell, switch_bool_t wait, switch_stream_handle_t *stream)
  2846. {
  2847. #ifndef __linux__
  2848. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "posix_spawn is unsupported on current platform\n");
  2849. return 1;
  2850. #else
  2851. int status = 0;
  2852. char buffer[1024];
  2853. pid_t pid;
  2854. char *pdata = NULL, *argv[64];
  2855. posix_spawn_file_actions_t action;
  2856. posix_spawnattr_t *attr;
  2857. int cout_pipe[2];
  2858. int cerr_pipe[2];
  2859. struct pollfd pfds[2] = { {0} };
  2860. if (zstr(cmd)) {
  2861. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to execute switch_spawn_stream because of empty command\n");
  2862. return 1;
  2863. }
  2864. if (shell) {
  2865. argv[0] = switch_core_get_variable("spawn_system_shell");
  2866. argv[1] = "-c";
  2867. argv[2] = (char *)cmd;
  2868. argv[3] = NULL;
  2869. if (zstr(argv[0])) {
  2870. argv[0] = "/bin/sh";
  2871. }
  2872. } else {
  2873. if (!(pdata = strdup(cmd))) {
  2874. return 1;
  2875. }
  2876. if (!switch_separate_string(pdata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
  2877. free(pdata);
  2878. return 1;
  2879. }
  2880. }
  2881. if (!(attr = malloc(sizeof(posix_spawnattr_t)))) {
  2882. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute switch_spawn_stream because of a memory error: %s\n", cmd);
  2883. switch_safe_free(pdata);
  2884. return 1;
  2885. }
  2886. if (stream) {
  2887. if (pipe(cout_pipe)) {
  2888. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute switch_spawn_stream because of a pipe error: %s\n", cmd);
  2889. free(attr);
  2890. switch_safe_free(pdata);
  2891. return 1;
  2892. }
  2893. if (pipe(cerr_pipe)) {
  2894. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute switch_spawn_stream because of a pipe error: %s\n", cmd);
  2895. close(cout_pipe[0]);
  2896. close(cout_pipe[1]);
  2897. free(attr);
  2898. switch_safe_free(pdata);
  2899. return 1;
  2900. }
  2901. }
  2902. memset(attr, 0, sizeof(posix_spawnattr_t));
  2903. posix_spawnattr_init(attr);
  2904. posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK);
  2905. posix_spawn_file_actions_init(&action);
  2906. if (stream) {
  2907. posix_spawn_file_actions_addclose(&action, cout_pipe[0]);
  2908. posix_spawn_file_actions_addclose(&action, cerr_pipe[0]);
  2909. posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 1);
  2910. posix_spawn_file_actions_adddup2(&action, cerr_pipe[1], 2);
  2911. posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
  2912. posix_spawn_file_actions_addclose(&action, cerr_pipe[1]);
  2913. }
  2914. if (posix_spawnp(&pid, argv[0], &action, attr, argv, environ) != 0) {
  2915. status = 1;
  2916. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to execute posix_spawnp: %s\n", cmd);
  2917. if (stream) {
  2918. close(cout_pipe[0]), close(cerr_pipe[0]);
  2919. close(cout_pipe[1]), close(cerr_pipe[1]);
  2920. }
  2921. } else {
  2922. if (stream) {
  2923. close(cout_pipe[1]), close(cerr_pipe[1]); /* close child-side of pipes */
  2924. pfds[0] = (struct pollfd) {
  2925. .fd = cout_pipe[0],
  2926. .events = POLLIN,
  2927. .revents = 0
  2928. };
  2929. pfds[1] = (struct pollfd) {
  2930. .fd = cerr_pipe[0],
  2931. .events = POLLIN,
  2932. .revents = 0
  2933. };
  2934. while (poll(pfds, 2, /*timeout*/-1) > 0) {
  2935. if (pfds[0].revents & POLLIN) {
  2936. int bytes_read = read(cout_pipe[0], buffer, sizeof(buffer));
  2937. stream->raw_write_function(stream, (unsigned char *)buffer, bytes_read);
  2938. } else if (pfds[1].revents & POLLIN) {
  2939. int bytes_read = read(cerr_pipe[0], buffer, sizeof(buffer));
  2940. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "STDERR of cmd (%s): %.*s\n", cmd, bytes_read, buffer);
  2941. } else {
  2942. break; /* nothing left to read */
  2943. }
  2944. }
  2945. close(cout_pipe[0]), close(cerr_pipe[0]);
  2946. }
  2947. if (wait) {
  2948. if (waitpid(pid, &status, 0) != pid) {
  2949. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "waitpid failed: %s\n", cmd);
  2950. } else if (status != 0) {
  2951. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Exit status (%d): %s\n", status, cmd);
  2952. }
  2953. }
  2954. }
  2955. posix_spawnattr_destroy(attr);
  2956. free(attr);
  2957. posix_spawn_file_actions_destroy(&action);
  2958. switch_safe_free(pdata);
  2959. return status;
  2960. #endif
  2961. }
  2962. SWITCH_DECLARE(int) switch_spawn(const char *cmd, switch_bool_t wait)
  2963. {
  2964. return switch_stream_spawn(cmd, SWITCH_FALSE, wait, NULL);
  2965. }
  2966. SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max)
  2967. {
  2968. #ifdef HAVE_SETRLIMIT
  2969. struct rlimit rlp;
  2970. memset(&rlp, 0, sizeof(rlp));
  2971. getrlimit(RLIMIT_STACK, &rlp);
  2972. *cur = rlp.rlim_cur;
  2973. *max = rlp.rlim_max;
  2974. return SWITCH_STATUS_SUCCESS;
  2975. #else
  2976. return SWITCH_STATUS_FALSE;
  2977. #endif
  2978. }
  2979. SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream)
  2980. {
  2981. #ifdef __linux__
  2982. switch_bool_t spawn_instead_of_system = switch_true(switch_core_get_variable("spawn_instead_of_system"));
  2983. #else
  2984. switch_bool_t spawn_instead_of_system = SWITCH_FALSE;
  2985. #endif
  2986. if (spawn_instead_of_system){
  2987. return switch_stream_spawn(cmd, SWITCH_TRUE, SWITCH_TRUE, stream);
  2988. } else {
  2989. char buffer[128];
  2990. size_t bytes;
  2991. FILE* pipe = popen(cmd, "r");
  2992. if (!pipe) return 1;
  2993. while (!feof(pipe)) {
  2994. while ((bytes = fread(buffer, 1, 128, pipe)) > 0) {
  2995. if (stream != NULL) {
  2996. stream->raw_write_function(stream, (unsigned char *)buffer, bytes);
  2997. }
  2998. }
  2999. }
  3000. if (ferror(pipe)) {
  3001. pclose(pipe);
  3002. return 1;
  3003. }
  3004. pclose(pipe);
  3005. return 0;
  3006. }
  3007. }
  3008. SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_start_port(void)
  3009. {
  3010. uint16_t start_port = 0;
  3011. /* By default pass rtp port range start value as zero in order to get actual
  3012. * RTP port range start value as configured */
  3013. start_port = (uint16_t)switch_rtp_set_start_port((switch_port_t)start_port);
  3014. return start_port;
  3015. }
  3016. SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_end_port(void)
  3017. {
  3018. uint16_t end_port = 0;
  3019. /* By default pass rtp port range end value as zero in order to get actual
  3020. * RTP port range end value as configured */
  3021. end_port = (uint16_t)switch_rtp_set_end_port((switch_port_t)end_port);
  3022. return end_port;
  3023. }
  3024. SWITCH_DECLARE(const char *) switch_core_get_event_channel_key_separator(void)
  3025. {
  3026. return runtime.event_channel_key_separator;
  3027. }
  3028. /* For Emacs:
  3029. * Local Variables:
  3030. * mode:c
  3031. * indent-tabs-mode:t
  3032. * tab-width:4
  3033. * c-basic-offset:4
  3034. * End:
  3035. * For VIM:
  3036. * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
  3037. */