app_rpt.c 200 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2002-2005, Jim Dixon, WB6NIL
  5. *
  6. * Jim Dixon, WB6NIL <jim@lambdatel.com>
  7. * Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*! \file
  20. *
  21. * \brief Radio Repeater / Remote Base program
  22. * version 0.48 06/13/06
  23. *
  24. * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
  25. *
  26. * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
  27. *
  28. * See http://www.zapatatelephony.org/app_rpt.html
  29. *
  30. *
  31. * Repeater / Remote Functions:
  32. * "Simple" Mode: * - autopatch access, # - autopatch hangup
  33. * Normal mode:
  34. * See the function list in rpt.conf (autopatchup, autopatchdn)
  35. * autopatchup can optionally take comma delimited setting=value pairs:
  36. *
  37. *
  38. * context=string : Override default context with "string"
  39. * dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)
  40. * farenddisconnect=1 : Automatically disconnect when called party hangs up
  41. * noct=1 : Don't send repeater courtesy tone during autopatch calls
  42. * quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
  43. *
  44. *
  45. * Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
  46. *
  47. * To send an asterisk (*) while dialing or talking on phone,
  48. * use the autopatch acess code.
  49. *
  50. *
  51. * status cmds:
  52. *
  53. * 1 - Force ID
  54. * 2 - Give Time of Day
  55. * 3 - Give software Version
  56. *
  57. * cop (control operator) cmds:
  58. *
  59. * 1 - System warm boot
  60. * 2 - System enable
  61. * 3 - System disable
  62. * 4 - Test Tone On
  63. * 5 - Dump System Variables on Console (debug)
  64. * 6 - PTT (phone mode only)
  65. *
  66. * ilink cmds:
  67. *
  68. * 1 - Disconnect specified link
  69. * 2 - Connect specified link -- monitor only
  70. * 3 - Connect specified link -- tranceive
  71. * 4 - Enter command mode on specified link
  72. * 5 - System status
  73. * 6 - Disconnect all links
  74. *
  75. * remote cmds:
  76. *
  77. * 1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
  78. * 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
  79. * 3 - Set Rx PL Tone HHH*D*
  80. * 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
  81. * 5 - Link Status (long)
  82. * 6 - Set operating mode M (FM, USB, LSB, AM, etc)
  83. * 100 - RX PL off (Default)
  84. * 101 - RX PL On
  85. * 102 - TX PL Off (Default)
  86. * 103 - TX PL On
  87. * 104 - Low Power
  88. * 105 - Med Power
  89. * 106 - Hi Power
  90. * 107 - Bump Down 20 Hz
  91. * 108 - Bump Down 100 Hz
  92. * 109 - Bump Down 500 Hz
  93. * 110 - Bump Up 20 Hz
  94. * 111 - Bump Up 100 Hz
  95. * 112 - Bump Up 500 Hz
  96. * 113 - Scan Down Slow
  97. * 114 - Scan Down Medium
  98. * 115 - Scan Down Fast
  99. * 116 - Scan Up Slow
  100. * 117 - Scan Up Medium
  101. * 118 - Scan Up Fast
  102. * 119 - Transmit allowing auto-tune
  103. * 140 - Link Status (brief)
  104. *
  105. *
  106. *
  107. * 'duplex' modes: (defaults to duplex=2)
  108. *
  109. * 0 - Only remote links key Tx and no main repeat audio.
  110. * 1 - Everything other then main Rx keys Tx, no main repeat audio.
  111. * 2 - Normal mode
  112. * 3 - Normal except no main repeat audio.
  113. * 4 - Normal except no main repeat audio during autopatch only
  114. *
  115. */
  116. /*** MODULEINFO
  117. <depend>dahdi</depend>
  118. <depend>tonezone</depend>
  119. <defaultenabled>no</defaultenabled>
  120. ***/
  121. /* Un-comment the following to include support for MDC-1200 digital tone
  122. signalling protocol (using KA6SQG's GPL'ed implementation) */
  123. /* #include "mdc_decode.c" */
  124. /* Un-comment the following to include support for notch filters in the
  125. rx audio stream (using Tony Fisher's mknotch (mkfilter) implementation) */
  126. /* #include "rpt_notch.c" */
  127. /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
  128. #define MAXDTMF 32
  129. #define MAXMACRO 2048
  130. #define MAXGOSUB 2048
  131. #define MACROTIME 100
  132. #define GOSUBTIME 100
  133. #define MACROPTIME 500
  134. #define GOSUBPTIME 500
  135. #define DTMF_TIMEOUT 3
  136. #ifdef __RPT_NOTCH
  137. #define MAXFILTERS 10
  138. #endif
  139. #define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
  140. #define MAX_RETRIES 5
  141. #define REDUNDANT_TX_TIME 2000
  142. #define RETRY_TIMER_MS 5000
  143. #define MAXPEERSTR 31
  144. #define MAXREMSTR 15
  145. #define DELIMCHR ','
  146. #define QUOTECHR 34
  147. #define NODES "nodes"
  148. #define MEMORY "memory"
  149. #define MACRO "macro"
  150. #define GOSUB "gosub"
  151. #define FUNCTIONS "functions"
  152. #define TELEMETRY "telemetry"
  153. #define MORSE "morse"
  154. #define FUNCCHAR '*'
  155. #define ENDCHAR '#'
  156. #define DEFAULT_IOBASE 0x378
  157. #define MAXCONNECTTIME 5000
  158. #define MAXNODESTR 300
  159. #define MAXPATCHCONTEXT 100
  160. #define ACTIONSIZE 32
  161. #define TELEPARAMSIZE 256
  162. #define REM_SCANTIME 100
  163. enum {REM_OFF, REM_MONITOR, REM_TX};
  164. enum {ID, PROC, TERM, COMPLETE, UNKEY, REMDISC, REMALREADY, REMNOTFOUND, REMGO,
  165. CONNECTED, CONNFAIL, STATUS, TIMEOUT, ID1, STATS_TIME,
  166. STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
  167. TAILMSG, MACRO_NOTFOUND, GOSUB_NOTFOUND, MACRO_BUSY, GOSUB_BUSY, LASTNODEKEY};
  168. enum {REM_SIMPLEX, REM_MINUS, REM_PLUS};
  169. enum {REM_LOWPWR, REM_MEDPWR, REM_HIPWR};
  170. enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
  171. enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
  172. enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
  173. enum {REM_MODE_FM, REM_MODE_USB, REM_MODE_LSB, REM_MODE_AM};
  174. enum {HF_SCAN_OFF, HF_SCAN_DOWN_SLOW, HF_SCAN_DOWN_QUICK,
  175. HF_SCAN_DOWN_FAST, HF_SCAN_UP_SLOW, HF_SCAN_UP_QUICK, HF_SCAN_UP_FAST};
  176. #include "asterisk.h"
  177. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  178. #include <signal.h>
  179. #include <search.h>
  180. #include <sys/stat.h>
  181. #include <dirent.h>
  182. #include <ctype.h>
  183. #include <sys/time.h>
  184. #include <sys/file.h>
  185. #include <sys/ioctl.h>
  186. #include <sys/io.h>
  187. #include <math.h>
  188. #include <dahdi/user.h>
  189. #include <dahdi/tonezone.h>
  190. #include <netinet/in.h>
  191. #include <arpa/inet.h>
  192. #include "asterisk/utils.h"
  193. #include "asterisk/lock.h"
  194. #include "asterisk/file.h"
  195. #include "asterisk/channel.h"
  196. #include "asterisk/callerid.h"
  197. #include "asterisk/pbx.h"
  198. #include "asterisk/module.h"
  199. #include "asterisk/translate.h"
  200. #include "asterisk/features.h"
  201. #include "asterisk/cli.h"
  202. #include "asterisk/config.h"
  203. #include "asterisk/say.h"
  204. #include "asterisk/localtime.h"
  205. #include "asterisk/app.h"
  206. static char *app = "Rpt";
  207. static char *synopsis = "Radio Repeater/Remote Base Control System";
  208. static char *descrip =
  209. " Rpt(nodename[,options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
  210. "\n"
  211. " Not specifying an option puts it in normal endpoint mode (where source\n"
  212. " IP and nodename are verified).\n"
  213. "\n"
  214. " Options are as follows:\n"
  215. "\n"
  216. " X - Normal endpoint mode WITHOUT security check. Only specify\n"
  217. " this if you have checked security already (like with an IAX2\n"
  218. " user/password or something).\n"
  219. "\n"
  220. " Rannounce-string[,timeout[,timeout-destination]] - Amateur Radio\n"
  221. " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
  222. " specified by the 'announce-string') is played on radio system.\n"
  223. " Users of radio system can access autopatch, dial specified\n"
  224. " code, and pick up call. Announce-string is list of names of\n"
  225. " recordings, or \"PARKED\" to substitute code for un-parking,\n"
  226. " or \"NODE\" to substitute node number.\n"
  227. "\n"
  228. " P - Phone Control mode. This allows a regular phone user to have\n"
  229. " full control and audio access to the radio system. For the\n"
  230. " user to have DTMF control, the 'phone_functions' parameter\n"
  231. " must be specified for the node in 'rpt.conf'. An additional\n"
  232. " function (cop,6) must be listed so that PTT control is available.\n"
  233. "\n"
  234. " D - Dumb Phone Control mode. This allows a regular phone user to\n"
  235. " have full control and audio access to the radio system. In this\n"
  236. " mode, the PTT is activated for the entire length of the call.\n"
  237. " For the user to have DTMF control (not generally recomended in\n"
  238. " this mode), the 'dphone_functions' parameter must be specified\n"
  239. " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
  240. " available to the phone user.\n"
  241. "\n";
  242. static unsigned int vmajor = 0;
  243. static unsigned int vminor = 47;
  244. static int debug = 0; /* FIXME Set this >0 for extra debug output */
  245. static int nrpts = 0;
  246. char *discstr = "!!DISCONNECT!!";
  247. static char *remote_rig_ft897 = "ft897";
  248. static char *remote_rig_rbi = "rbi";
  249. #define MSWAIT 200
  250. #define HANGTIME 5000
  251. #define TOTIME 180000
  252. #define IDTIME 300000
  253. #define MAXRPTS 20
  254. #define MAX_STAT_LINKS 32
  255. #define POLITEID 30000
  256. #define FUNCTDELAY 1500
  257. static pthread_t rpt_master_thread;
  258. struct rpt;
  259. struct rpt_link
  260. {
  261. struct rpt_link *next;
  262. struct rpt_link *prev;
  263. char mode; /* 1 if in tx mode */
  264. char isremote;
  265. char phonemode;
  266. char name[MAXNODESTR]; /* identifier (routing) string */
  267. char lasttx;
  268. char lastrx;
  269. char connected;
  270. char hasconnected;
  271. char outbound;
  272. char disced;
  273. char killme;
  274. long elaptime;
  275. long disctime;
  276. long retrytimer;
  277. long retxtimer;
  278. int retries;
  279. int reconnects;
  280. long long connecttime;
  281. struct ast_channel *chan;
  282. struct ast_channel *pchan;
  283. } ;
  284. struct rpt_lstat
  285. {
  286. struct rpt_lstat *next;
  287. struct rpt_lstat *prev;
  288. char peer[MAXPEERSTR];
  289. char name[MAXNODESTR];
  290. char mode;
  291. char outbound;
  292. char reconnects;
  293. long long connecttime;
  294. } ;
  295. struct rpt_tele
  296. {
  297. struct rpt_tele *next;
  298. struct rpt_tele *prev;
  299. struct rpt *rpt;
  300. struct ast_channel *chan;
  301. int mode;
  302. struct rpt_link mylink;
  303. char param[TELEPARAMSIZE];
  304. pthread_t threadid;
  305. } ;
  306. struct function_table_tag
  307. {
  308. char action[ACTIONSIZE];
  309. int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
  310. int command_source, struct rpt_link *mylink);
  311. } ;
  312. /* Used to store the morse code patterns */
  313. struct morse_bits
  314. {
  315. int len;
  316. int ddcomb;
  317. } ;
  318. struct telem_defaults
  319. {
  320. char name[20];
  321. char value[80];
  322. } ;
  323. static struct rpt
  324. {
  325. ast_mutex_t lock;
  326. struct ast_config *cfg;
  327. char reload;
  328. char *name;
  329. char *rxchanname;
  330. char *txchanname;
  331. char *remote;
  332. struct {
  333. char ourcontext[80];
  334. char ourcallerid[80];
  335. char acctcode[21];
  336. char ident[80];
  337. char tonezone[80];
  338. char simple;
  339. char functions[80];
  340. char link_functions[80];
  341. char phone_functions[80];
  342. char dphone_functions[80];
  343. char nodes[80];
  344. int hangtime;
  345. int totime;
  346. int idtime;
  347. int tailmessagetime;
  348. int tailsquashedtime;
  349. int duplex;
  350. int politeid;
  351. char *tailmsgbuf;
  352. AST_DECLARE_APP_ARGS(tailmsg,
  353. AST_APP_ARG(msgs)[100];
  354. );
  355. char memory[80];
  356. char macro[80];
  357. char gosub[80];
  358. char startupmacro[80];
  359. char startupgosub[80];
  360. int iobase;
  361. char funcchar;
  362. char endchar;
  363. char nobusyout;
  364. } p;
  365. struct rpt_link links;
  366. int unkeytocttimer;
  367. char keyed;
  368. char exttx;
  369. char localtx;
  370. char remoterx;
  371. char remotetx;
  372. char remoteon;
  373. char tounkeyed;
  374. char tonotify;
  375. char enable;
  376. char dtmfbuf[MAXDTMF];
  377. char macrobuf[MAXMACRO];
  378. char gosubbuf[MAXGOSUB];
  379. char rem_dtmfbuf[MAXDTMF];
  380. char lastdtmfcommand[MAXDTMF];
  381. char cmdnode[50];
  382. struct ast_channel *rxchannel, *txchannel;
  383. struct ast_channel *pchannel, *txpchannel, *remchannel;
  384. struct rpt_tele tele;
  385. struct timeval lasttv, curtv;
  386. pthread_t rpt_call_thread, rpt_thread;
  387. time_t dtmf_time, rem_dtmf_time, dtmf_time_rem;
  388. int tailtimer, totimer, idtimer, txconf, conf, callmode, cidx, scantimer, tmsgtimer, skedtimer;
  389. int mustid, tailid;
  390. int tailevent;
  391. int telemrefcount;
  392. int dtmfidx, rem_dtmfidx;
  393. int dailytxtime, dailykerchunks, totalkerchunks, dailykeyups, totalkeyups, timeouts;
  394. int totalexecdcommands, dailyexecdcommands;
  395. long retxtimer;
  396. long long totaltxtime;
  397. char mydtmf;
  398. char exten[AST_MAX_EXTENSION];
  399. char freq[MAXREMSTR], rxpl[MAXREMSTR], txpl[MAXREMSTR];
  400. char offset;
  401. char powerlevel;
  402. char txplon;
  403. char rxplon;
  404. char remmode;
  405. char tunerequest;
  406. char hfscanmode;
  407. int hfscanstatus;
  408. char lastlinknode[MAXNODESTR];
  409. char stopgen;
  410. char patchfarenddisconnect;
  411. char patchnoct;
  412. char patchquiet;
  413. char patchcontext[MAXPATCHCONTEXT];
  414. int patchdialtime;
  415. int macro_longest;
  416. int gosub_longest;
  417. int phone_longestfunc;
  418. int dphone_longestfunc;
  419. int link_longestfunc;
  420. int longestfunc;
  421. int longestnode;
  422. int threadrestarts;
  423. int tailmessagen;
  424. time_t disgorgetime;
  425. time_t lastthreadrestarttime;
  426. long macrotimer;
  427. long gosubtimer;
  428. char lastnodewhichkeyedusup[MAXNODESTR];
  429. #ifdef __RPT_NOTCH
  430. struct rptfilter
  431. {
  432. char desc[100];
  433. float x0;
  434. float x1;
  435. float x2;
  436. float y0;
  437. float y1;
  438. float y2;
  439. float gain;
  440. float const0;
  441. float const1;
  442. float const2;
  443. } filters[MAXFILTERS];
  444. #endif
  445. #ifdef _MDC_DECODE_H_
  446. mdc_decoder_t *mdc;
  447. unsigned short lastunit;
  448. #endif
  449. } rpt_vars[MAXRPTS];
  450. #ifdef APP_RPT_LOCK_DEBUG
  451. #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
  452. #define MAXLOCKTHREAD 100
  453. #define rpt_mutex_lock(x) _rpt_mutex_lock(x, myrpt, __LINE__)
  454. #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x, myrpt, __LINE__)
  455. struct lockthread
  456. {
  457. pthread_t id;
  458. int lockcount;
  459. int lastlock;
  460. int lastunlock;
  461. } lockthreads[MAXLOCKTHREAD];
  462. struct by_lightning
  463. {
  464. int line;
  465. struct timeval tv;
  466. struct rpt *rpt;
  467. struct lockthread lockthread;
  468. } lock_ring[32];
  469. int lock_ring_index = 0;
  470. AST_MUTEX_DEFINE_STATIC(locklock);
  471. static struct lockthread *get_lockthread(pthread_t id)
  472. {
  473. int i;
  474. for (i = 0; i < MAXLOCKTHREAD; i++) {
  475. if (lockthreads[i].id == id)
  476. return(&lockthreads[i]);
  477. }
  478. return NULL;
  479. }
  480. static struct lockthread *put_lockthread(pthread_t id)
  481. {
  482. int i;
  483. for (i = 0; i < MAXLOCKTHREAD; i++) {
  484. if (lockthreads[i].id == id)
  485. return(&lockthreads[i]);
  486. }
  487. for (i = 0; i < MAXLOCKTHREAD; i++) {
  488. if (!lockthreads[i].id) {
  489. lockthreads[i].lockcount = 0;
  490. lockthreads[i].lastlock = 0;
  491. lockthreads[i].lastunlock = 0;
  492. lockthreads[i].id = id;
  493. return &lockthreads[i];
  494. }
  495. }
  496. return NULL;
  497. }
  498. static void rpt_mutex_spew(void)
  499. {
  500. struct by_lightning lock_ring_copy[32];
  501. int lock_ring_index_copy;
  502. int i, j;
  503. long long diff;
  504. char a[100] = "";
  505. struct ast_tm tm;
  506. struct timeval lasttv;
  507. ast_mutex_lock(&locklock);
  508. memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
  509. lock_ring_index_copy = lock_ring_index;
  510. ast_mutex_unlock(&locklock);
  511. lasttv.tv_sec = lasttv.tv_usec = 0;
  512. for (i = 0; i < 32; i++) {
  513. j = (i + lock_ring_index_copy) % 32;
  514. ast_strftime(a, sizeof(a) - 1, "%m/%d/%Y %H:%M:%S",
  515. ast_localtime(&lock_ring_copy[j].tv, &tm, NULL));
  516. diff = 0;
  517. if (lasttv.tv_sec) {
  518. diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec) * 1000000;
  519. diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
  520. }
  521. lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
  522. lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
  523. if (!lock_ring_copy[j].tv.tv_sec)
  524. continue;
  525. if (lock_ring_copy[j].line < 0) {
  526. ast_log(LOG_NOTICE, "LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
  527. i - 31, -lock_ring_copy[j].line, lock_ring_copy[j].rpt->name,
  528. (int) lock_ring_copy[j].lockthread.id, diff, a, (int)lock_ring_copy[j].tv.tv_usec);
  529. } else {
  530. ast_log(LOG_NOTICE, "LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
  531. i - 31, lock_ring_copy[j].line, lock_ring_copy[j].rpt->name,
  532. (int) lock_ring_copy[j].lockthread.id, diff, a, (int)lock_ring_copy[j].tv.tv_usec);
  533. }
  534. }
  535. }
  536. static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
  537. {
  538. struct lockthread *t;
  539. pthread_t id;
  540. id = pthread_self();
  541. ast_mutex_lock(&locklock);
  542. t = put_lockthread(id);
  543. if (!t) {
  544. ast_mutex_unlock(&locklock);
  545. return;
  546. }
  547. if (t->lockcount) {
  548. int lastline = t->lastlock;
  549. ast_mutex_unlock(&locklock);
  550. ast_log(LOG_NOTICE, "rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",
  551. line, myrpt->name, (int) t->id, lastline);
  552. rpt_mutex_spew();
  553. return;
  554. }
  555. t->lastlock = line;
  556. t->lockcount = 1;
  557. gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
  558. lock_ring[lock_ring_index].rpt = myrpt;
  559. memcpy(&lock_ring[lock_ring_index].lockthread, t, sizeof(struct lockthread));
  560. lock_ring[lock_ring_index++].line = line;
  561. if (lock_ring_index == 32)
  562. lock_ring_index = 0;
  563. ast_mutex_unlock(&locklock);
  564. ast_mutex_lock(lockp);
  565. }
  566. static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
  567. {
  568. struct lockthread *t;
  569. pthread_t id;
  570. id = pthread_self();
  571. ast_mutex_lock(&locklock);
  572. t = put_lockthread(id);
  573. if (!t) {
  574. ast_mutex_unlock(&locklock);
  575. return;
  576. }
  577. if (!t->lockcount) {
  578. int lastline = t->lastunlock;
  579. ast_mutex_unlock(&locklock);
  580. ast_log(LOG_NOTICE, "rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",
  581. line, myrpt->name, (int) t->id, lastline);
  582. rpt_mutex_spew();
  583. return;
  584. }
  585. t->lastunlock = line;
  586. t->lockcount = 0;
  587. gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
  588. lock_ring[lock_ring_index].rpt = myrpt;
  589. memcpy(&lock_ring[lock_ring_index].lockthread, t, sizeof(struct lockthread));
  590. lock_ring[lock_ring_index++].line = -line;
  591. if (lock_ring_index == 32)
  592. lock_ring_index = 0;
  593. ast_mutex_unlock(&locklock);
  594. ast_mutex_unlock(lockp);
  595. }
  596. #else /* APP_RPT_LOCK_DEBUG */
  597. #define rpt_mutex_lock(x) ast_mutex_lock(x)
  598. #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
  599. #endif /* APP_RPT_LOCK_DEBUG */
  600. /*
  601. * CLI extensions
  602. */
  603. /* Debug mode */
  604. static char *handle_cli_rpt_debug_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  605. static char *handle_cli_rpt_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  606. static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  607. static char *handle_cli_rpt_lstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  608. static char *handle_cli_rpt_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  609. static char *handle_cli_rpt_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
  610. static struct ast_cli_entry cli_rpt[] = {
  611. AST_CLI_DEFINE(handle_cli_rpt_debug_level, "Enable app_rpt debuggin"),
  612. AST_CLI_DEFINE(handle_cli_rpt_dump, "Dump app_rpt structs for debugging"),
  613. AST_CLI_DEFINE(handle_cli_rpt_stats, "Dump node statistics"),
  614. AST_CLI_DEFINE(handle_cli_rpt_lstats, "Dump link statistics"),
  615. AST_CLI_DEFINE(handle_cli_rpt_reload, "Reload app_rpt config"),
  616. AST_CLI_DEFINE(handle_cli_rpt_restart, "Restart app_rpt")
  617. };
  618. /*
  619. * Telemetry defaults
  620. */
  621. static struct telem_defaults tele_defs[] = {
  622. {"ct1", "|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
  623. {"ct2", "|t(660,880,150,3072)"},
  624. {"ct3", "|t(440,0,150,3072)"},
  625. {"ct4", "|t(550,0,150,3072)"},
  626. {"ct5", "|t(660,0,150,3072)"},
  627. {"ct6", "|t(880,0,150,3072)"},
  628. {"ct7", "|t(660,440,150,3072)"},
  629. {"ct8", "|t(700,1100,150,3072)"},
  630. {"remotemon", "|t(1600,0,75,2048)"},
  631. {"remotetx", "|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
  632. {"cmdmode", "|t(900,904,200,2048)"},
  633. {"functcomplete", "|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
  634. } ;
  635. /*
  636. * Forward decl's - these suppress compiler warnings when funcs coded further down the file than their invocation
  637. */
  638. static int setrbi(struct rpt *myrpt);
  639. /*
  640. * Define function protos for function table here
  641. */
  642. static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  643. static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  644. static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  645. static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  646. static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  647. static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  648. static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  649. static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  650. /*
  651. * Function table
  652. */
  653. static struct function_table_tag function_table[] = {
  654. {"cop", function_cop},
  655. {"autopatchup", function_autopatchup},
  656. {"autopatchdn", function_autopatchdn},
  657. {"ilink", function_ilink},
  658. {"status", function_status},
  659. {"remote", function_remote},
  660. {"macro", function_macro},
  661. {"gosub", function_gosub},
  662. } ;
  663. /*
  664. * Match a keyword in a list, and return index of string plus 1 if there was a match,
  665. * else return 0. If param is passed in non-null, then it will be set to the first character past the match
  666. */
  667. static int matchkeyword(char *string, char **param, char *keywords[])
  668. {
  669. int i, ls;
  670. for (i = 0; keywords[i]; i++) {
  671. ls = strlen(keywords[i]);
  672. if (!ls) {
  673. *param = NULL;
  674. return 0;
  675. }
  676. if (!strncmp(string, keywords[i], ls)) {
  677. if (param)
  678. *param = string + ls;
  679. return i + 1;
  680. }
  681. }
  682. param = NULL;
  683. return 0;
  684. }
  685. /*
  686. * Skip characters in string which are in charlist, and return a pointer to the
  687. * first non-matching character
  688. */
  689. static char *skipchars(char *string, char *charlist)
  690. {
  691. int i;
  692. while (*string) {
  693. for (i = 0; charlist[i] ; i++) {
  694. if (*string == charlist[i]) {
  695. string++;
  696. break;
  697. }
  698. }
  699. if (!charlist[i])
  700. return string;
  701. }
  702. return string;
  703. }
  704. static int myatoi(const char *str)
  705. {
  706. int ret;
  707. if (str == NULL)
  708. return -1;
  709. /* leave this %i alone, non-base-10 input is useful here */
  710. if (sscanf(str, "%30i", &ret) != 1)
  711. return -1;
  712. return ret;
  713. }
  714. #ifdef __RPT_NOTCH
  715. /* rpt filter routine */
  716. static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
  717. {
  718. int i, j;
  719. struct rptfilter *f;
  720. for (i = 0; i < len; i++) {
  721. for (j = 0; j < MAXFILTERS; j++) {
  722. f = &myrpt->filters[j];
  723. if (!*f->desc)
  724. continue;
  725. f->x0 = f->x1; f->x1 = f->x2;
  726. f->x2 = ((float)buf[i]) / f->gain;
  727. f->y0 = f->y1; f->y1 = f->y2;
  728. f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
  729. + (f->const1 * f->y0) + (f->const2 * f->y1);
  730. buf[i] = (short)f->y2;
  731. }
  732. }
  733. }
  734. #endif
  735. /* Retrieve an int from a config file */
  736. static int retrieve_astcfgint(struct rpt *myrpt, const char *category, const char *name, int min, int max, int defl)
  737. {
  738. const char *var = ast_variable_retrieve(myrpt->cfg, category, name);
  739. int ret;
  740. if (var) {
  741. ret = myatoi(var);
  742. if (ret < min)
  743. ret = min;
  744. else if (ret > max)
  745. ret = max;
  746. } else
  747. ret = defl;
  748. return ret;
  749. }
  750. static void load_rpt_vars(int n, int init)
  751. {
  752. int j;
  753. struct ast_variable *vp, *var;
  754. struct ast_config *cfg;
  755. struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
  756. #ifdef __RPT_NOTCH
  757. AST_DECLARE_APP_ARGS(strs,
  758. AST_APP_ARG(str)[100];
  759. );
  760. #endif
  761. ast_verb(3, "%s config for repeater %s\n",
  762. (init) ? "Loading initial" : "Re-Loading", rpt_vars[n].name);
  763. ast_mutex_lock(&rpt_vars[n].lock);
  764. if (rpt_vars[n].cfg)
  765. ast_config_destroy(rpt_vars[n].cfg);
  766. cfg = ast_config_load("rpt.conf", config_flags);
  767. if (!cfg) {
  768. ast_mutex_unlock(&rpt_vars[n].lock);
  769. ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
  770. pthread_exit(NULL);
  771. }
  772. rpt_vars[n].cfg = cfg;
  773. /* Free previously malloc'ed buffer */
  774. if (!init && rpt_vars[n].p.tailmsgbuf)
  775. ast_free(rpt_vars[n].p.tailmsgbuf);
  776. memset(&rpt_vars[n].p, 0, sizeof(rpt_vars[n].p));
  777. if (init) {
  778. /* clear all the fields in the structure after 'p' */
  779. memset(&rpt_vars[n].p + sizeof(rpt_vars[0].p), 0, sizeof(rpt_vars[0]) - sizeof(rpt_vars[0].p) - offsetof(typeof(rpt_vars[0]), p));
  780. rpt_vars[n].tele.next = &rpt_vars[n].tele;
  781. rpt_vars[n].tele.prev = &rpt_vars[n].tele;
  782. rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
  783. rpt_vars[n].tailmessagen = 0;
  784. }
  785. #ifdef __RPT_NOTCH
  786. /* zot out filters stuff */
  787. memset(&rpt_vars[n].filters, 0, sizeof(rpt_vars[n].filters));
  788. #endif
  789. /* Defaults */
  790. ast_copy_string(rpt_vars[n].p.ourcontext, rpt_vars[n].name, sizeof(rpt_vars[n].p.ourcontext));
  791. rpt_vars[n].p.hangtime = HANGTIME;
  792. rpt_vars[n].p.totime = TOTIME;
  793. rpt_vars[n].p.duplex = 2;
  794. rpt_vars[n].p.idtime = IDTIME;
  795. rpt_vars[n].p.politeid = POLITEID;
  796. ast_copy_string(rpt_vars[n].p.memory, MEMORY, sizeof(rpt_vars[n].p.memory));
  797. ast_copy_string(rpt_vars[n].p.macro, MACRO, sizeof(rpt_vars[n].p.macro));
  798. ast_copy_string(rpt_vars[n].p.gosub, GOSUB, sizeof(rpt_vars[n].p.gosub));
  799. rpt_vars[n].p.iobase = DEFAULT_IOBASE;
  800. ast_copy_string(rpt_vars[n].p.functions, FUNCTIONS, sizeof(rpt_vars[n].p.functions));
  801. rpt_vars[n].p.simple = 1;
  802. rpt_vars[n].p.funcchar = FUNCCHAR;
  803. rpt_vars[n].p.endchar = ENDCHAR;
  804. ast_copy_string(rpt_vars[n].p.nodes, NODES, sizeof(rpt_vars[n].p.nodes));
  805. for (var = ast_variable_browse(cfg, rpt_vars[n].name); var; var = var->next) {
  806. if (!strcmp(var->name, "context")) {
  807. ast_copy_string(rpt_vars[n].p.ourcontext, var->value, sizeof(rpt_vars[n].p.ourcontext));
  808. } else if (!strcmp(var->name, "callerid")) {
  809. ast_copy_string(rpt_vars[n].p.ourcallerid, var->value, sizeof(rpt_vars[n].p.ourcallerid));
  810. } else if (!strcmp(var->name, "accountcode")) {
  811. ast_copy_string(rpt_vars[n].p.acctcode, var->value, sizeof(rpt_vars[n].p.acctcode));
  812. } else if (!strcmp(var->name, "idrecording")) {
  813. ast_copy_string(rpt_vars[n].p.ident, var->value, sizeof(rpt_vars[n].p.ident));
  814. } else if (!strcmp(var->name, "hangtime")) {
  815. rpt_vars[n].p.hangtime = atoi(var->value);
  816. } else if (!strcmp(var->name, "totime")) {
  817. rpt_vars[n].p.totime = atoi(var->value);
  818. } else if (!strcmp(var->name, "tailmessagetime")) {
  819. rpt_vars[n].p.tailmessagetime = atoi(var->value);
  820. if (rpt_vars[n].p.tailmessagetime < 0)
  821. rpt_vars[n].p.tailmessagetime = 0;
  822. else if (rpt_vars[n].p.tailmessagetime > 2400000)
  823. rpt_vars[n].p.tailmessagetime = 2400000;
  824. } else if (!strcmp(var->name, "tailsquashedtime")) {
  825. rpt_vars[n].p.tailsquashedtime = atoi(var->value);
  826. if (rpt_vars[n].p.tailsquashedtime < 0)
  827. rpt_vars[n].p.tailsquashedtime = 0;
  828. else if (rpt_vars[n].p.tailsquashedtime > 2400000)
  829. rpt_vars[n].p.tailsquashedtime = 2400000;
  830. } else if (!strcmp(var->name, "duplex")) {
  831. rpt_vars[n].p.duplex = atoi(var->value);
  832. if (rpt_vars[n].p.duplex < 0)
  833. rpt_vars[n].p.duplex = 0;
  834. else if (rpt_vars[n].p.duplex > 4)
  835. rpt_vars[n].p.duplex = 4;
  836. } else if (!strcmp(var->name, "idtime")) {
  837. rpt_vars[n].p.idtime = atoi(var->value);
  838. if (rpt_vars[n].p.idtime < 60000)
  839. rpt_vars[n].p.idtime = 60000;
  840. else if (rpt_vars[n].p.idtime > 2400000)
  841. rpt_vars[n].p.idtime = 2400000;
  842. } else if (!strcmp(var->name, "politeid")) {
  843. rpt_vars[n].p.politeid = atoi(var->value);
  844. if (rpt_vars[n].p.politeid < 30000)
  845. rpt_vars[n].p.politeid = 30000;
  846. else if (rpt_vars[n].p.politeid > 300000)
  847. rpt_vars[n].p.politeid = 300000;
  848. } else if (!strcmp(var->name, "tonezone")) {
  849. ast_copy_string(rpt_vars[n].p.tonezone, var->value, sizeof(rpt_vars[n].p.tonezone));
  850. } else if (!strcmp(var->name, "tailmessagelist")) {
  851. rpt_vars[n].p.tailmsgbuf = ast_strdup(var->value);
  852. AST_STANDARD_APP_ARGS(rpt_vars[n].p.tailmsg, rpt_vars[n].p.tailmsgbuf);
  853. } else if (!strcmp(var->name, "memory")) {
  854. ast_copy_string(rpt_vars[n].p.memory, var->value, sizeof(rpt_vars[n].p.memory));
  855. } else if (!strcmp(var->name, "macro")) {
  856. ast_copy_string(rpt_vars[n].p.macro, var->value, sizeof(rpt_vars[n].p.macro));
  857. } else if (!strcmp(var->name, "gosub")) {
  858. ast_copy_string(rpt_vars[n].p.gosub, var->value, sizeof(rpt_vars[n].p.gosub));
  859. } else if (!strcmp(var->name, "startup_macro")) {
  860. ast_copy_string(rpt_vars[n].p.startupmacro, var->value, sizeof(rpt_vars[n].p.startupmacro));
  861. } else if (!strcmp(var->name, "startup_gosub")) {
  862. ast_copy_string(rpt_vars[n].p.startupgosub, var->value, sizeof(rpt_vars[n].p.startupgosub));
  863. } else if (!strcmp(var->name, "iobase")) {
  864. /* do not use atoi() here, we need to be able to have
  865. the input specified in hex or decimal so we use
  866. sscanf with a %i */
  867. if (sscanf(var->value, "%30i", &rpt_vars[n].p.iobase) != 1)
  868. rpt_vars[n].p.iobase = DEFAULT_IOBASE;
  869. } else if (!strcmp(var->name, "functions")) {
  870. rpt_vars[n].p.simple = 0;
  871. ast_copy_string(rpt_vars[n].p.functions, var->value, sizeof(rpt_vars[n].p.functions));
  872. } else if (!strcmp(var->name, "link_functions")) {
  873. ast_copy_string(rpt_vars[n].p.link_functions, var->value, sizeof(rpt_vars[n].p.link_functions));
  874. } else if (!strcmp(var->name, "phone_functions")) {
  875. ast_copy_string(rpt_vars[n].p.phone_functions, var->value, sizeof(rpt_vars[n].p.phone_functions));
  876. } else if (!strcmp(var->name, "dphone_functions")) {
  877. ast_copy_string(rpt_vars[n].p.dphone_functions, var->value, sizeof(rpt_vars[n].p.dphone_functions));
  878. } else if (!strcmp(var->name, "funcchar")) {
  879. rpt_vars[n].p.funcchar = *var->value;
  880. } else if (!strcmp(var->name, "endchar")) {
  881. rpt_vars[n].p.endchar = *var->value;
  882. } else if (!strcmp(var->name, "nobusyout")) {
  883. rpt_vars[n].p.nobusyout = ast_true(var->value);
  884. } else if (!strcmp(var->name, "nodes")) {
  885. ast_copy_string(rpt_vars[n].p.nodes, var->value, sizeof(rpt_vars[n].p.nodes));
  886. #ifdef __RPT_NOTCH
  887. } else if (!strcmp(var->name, "rxnotch")) {
  888. char *tmp = ast_strdupa(val);
  889. AST_STANDARD_APP_ARGS(strs, tmp);
  890. strs.argc &= ~1; /* force an even number, rounded down */
  891. if (strs.argc >= 2) {
  892. for (j = 0; j < strs.argc; j += 2) {
  893. rpt_mknotch(atof(strs.str[j]), atof(strs.str[j + 1]),
  894. &rpt_vars[n].filters[j >> 1].gain,
  895. &rpt_vars[n].filters[j >> 1].const0,
  896. &rpt_vars[n].filters[j >> 1].const1,
  897. &rpt_vars[n].filters[j >> 1].const2);
  898. sprintf(rpt_vars[n].filters[j >> 1].desc, "%s Hz, BW = %s",
  899. strs.str[j], strs.str[j + 1]);
  900. }
  901. }
  902. #endif
  903. }
  904. }
  905. /* If these aren't specified, copy them from the functions property. */
  906. if (ast_strlen_zero(rpt_vars[n].p.link_functions))
  907. ast_copy_string(rpt_vars[n].p.link_functions, rpt_vars[n].p.functions, sizeof(rpt_vars[n].p.link_functions));
  908. rpt_vars[n].longestnode = 0;
  909. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes); vp; vp = vp->next) {
  910. if ((j = strlen(vp->name)) > rpt_vars[n].longestnode)
  911. rpt_vars[n].longestnode = j;
  912. }
  913. /*
  914. * For this repeater, Determine the length of the longest function
  915. */
  916. rpt_vars[n].longestfunc = 0;
  917. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.functions); vp; vp = vp->next) {
  918. if ((j = strlen(vp->name)) > rpt_vars[n].longestfunc)
  919. rpt_vars[n].longestfunc = j;
  920. }
  921. rpt_vars[n].link_longestfunc = 0;
  922. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions); vp; vp = vp->next) {
  923. if ((j = strlen(vp->name)) > rpt_vars[n].link_longestfunc)
  924. rpt_vars[n].link_longestfunc = j;
  925. }
  926. rpt_vars[n].phone_longestfunc = 0;
  927. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions); vp; vp = vp->next) {
  928. if ((j = strlen(vp->name)) > rpt_vars[n].phone_longestfunc)
  929. rpt_vars[n].phone_longestfunc = j;
  930. }
  931. rpt_vars[n].dphone_longestfunc = 0;
  932. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions); vp; vp = vp->next) {
  933. if ((j = strlen(vp->name)) > rpt_vars[n].dphone_longestfunc)
  934. rpt_vars[n].dphone_longestfunc = j;
  935. }
  936. rpt_vars[n].macro_longest = 1;
  937. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.macro); vp; vp = vp->next) {
  938. if ((j = strlen(vp->name)) > rpt_vars[n].macro_longest)
  939. rpt_vars[n].macro_longest = j;
  940. }
  941. rpt_vars[n].gosub_longest = 1;
  942. for (vp = ast_variable_browse(cfg, rpt_vars[n].p.gosub); vp; vp = vp->next) {
  943. if ((j = strlen(vp->name)) > rpt_vars[n].gosub_longest)
  944. rpt_vars[n].gosub_longest = j;
  945. }
  946. ast_mutex_unlock(&rpt_vars[n].lock);
  947. }
  948. /*
  949. * Enable or disable debug output at a given level at the console
  950. */
  951. static char *handle_cli_rpt_debug_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  952. {
  953. int newlevel;
  954. switch (cmd) {
  955. case CLI_INIT:
  956. e->command = "rpt debug level";
  957. e->usage =
  958. "Usage: rpt debug level {0-7}\n"
  959. " Enables debug messages in app_rpt\n";
  960. return NULL;
  961. case CLI_GENERATE:
  962. return NULL;
  963. }
  964. if (a->argc != e->args)
  965. return CLI_SHOWUSAGE;
  966. newlevel = myatoi(a->argv[3]);
  967. if ((newlevel < 0) || (newlevel > 7))
  968. return CLI_SHOWUSAGE;
  969. if (newlevel)
  970. ast_cli(a->fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
  971. else
  972. ast_cli(a->fd, "app_rpt Debugging disabled\n");
  973. debug = newlevel;
  974. return CLI_SUCCESS;
  975. }
  976. /*
  977. * Dump rpt struct debugging onto console
  978. */
  979. static char *handle_cli_rpt_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  980. {
  981. int i;
  982. switch (cmd) {
  983. case CLI_INIT:
  984. e->command = "rpt dump";
  985. e->usage =
  986. "Usage: rpt dump <nodename>\n"
  987. " Dumps struct debug info to log\n";
  988. return NULL;
  989. case CLI_GENERATE:
  990. return NULL;
  991. }
  992. if (a->argc != 3)
  993. return CLI_SHOWUSAGE;
  994. for (i = 0; i < nrpts; i++) {
  995. if (!strcmp(a->argv[2], rpt_vars[i].name)) {
  996. rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
  997. ast_cli(a->fd, "app_rpt struct dump requested for node %s\n", a->argv[2]);
  998. return CLI_SUCCESS;
  999. }
  1000. }
  1001. return CLI_FAILURE;
  1002. }
  1003. /*
  1004. * Dump statistics onto console
  1005. */
  1006. static char *handle_cli_rpt_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  1007. {
  1008. int i, j;
  1009. int dailytxtime, dailykerchunks;
  1010. int totalkerchunks, dailykeyups, totalkeyups, timeouts;
  1011. int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
  1012. long long totaltxtime;
  1013. struct rpt_link *l;
  1014. char *listoflinks[MAX_STAT_LINKS];
  1015. char *lastnodewhichkeyedusup, *lastdtmfcommand;
  1016. char *tot_state, *ider_state, *patch_state;
  1017. char *reverse_patch_state, *enable_state, *input_signal, *called_number;
  1018. struct rpt *myrpt;
  1019. static char *not_applicable = "N/A";
  1020. switch (cmd) {
  1021. case CLI_INIT:
  1022. e->command = "rpt stats";
  1023. e->usage =
  1024. "Usage: rpt stats <nodename>\n"
  1025. " Dumps node statistics to console\n";
  1026. return NULL;
  1027. case CLI_GENERATE:
  1028. return NULL;
  1029. }
  1030. if (a->argc != 3)
  1031. return CLI_SHOWUSAGE;
  1032. for (i = 0 ; i <= MAX_STAT_LINKS; i++)
  1033. listoflinks[i] = NULL;
  1034. tot_state = ider_state =
  1035. patch_state = reverse_patch_state =
  1036. input_signal = called_number =
  1037. lastdtmfcommand = not_applicable;
  1038. for (i = 0; i < nrpts; i++) {
  1039. if (!strcmp(a->argv[2], rpt_vars[i].name)) {
  1040. /* Make a copy of all stat variables while locked */
  1041. myrpt = &rpt_vars[i];
  1042. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  1043. dailytxtime = myrpt->dailytxtime;
  1044. totaltxtime = myrpt->totaltxtime;
  1045. dailykeyups = myrpt->dailykeyups;
  1046. totalkeyups = myrpt->totalkeyups;
  1047. dailykerchunks = myrpt->dailykerchunks;
  1048. totalkerchunks = myrpt->totalkerchunks;
  1049. dailyexecdcommands = myrpt->dailyexecdcommands;
  1050. totalexecdcommands = myrpt->totalexecdcommands;
  1051. timeouts = myrpt->timeouts;
  1052. /* Traverse the list of connected nodes */
  1053. reverse_patch_state = "DOWN";
  1054. j = 0;
  1055. l = myrpt->links.next;
  1056. while (l != &myrpt->links) {
  1057. if (l->name[0] == '0') { /* Skip '0' nodes */
  1058. reverse_patch_state = "UP";
  1059. l = l->next;
  1060. continue;
  1061. }
  1062. listoflinks[j] = ast_strdupa(l->name);
  1063. if (listoflinks[j])
  1064. j++;
  1065. l = l->next;
  1066. }
  1067. lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);
  1068. if ((!lastnodewhichkeyedusup) || (ast_strlen_zero(lastnodewhichkeyedusup)))
  1069. lastnodewhichkeyedusup = not_applicable;
  1070. if (myrpt->keyed)
  1071. input_signal = "YES";
  1072. else
  1073. input_signal = "NO";
  1074. if (myrpt->enable)
  1075. enable_state = "YES";
  1076. else
  1077. enable_state = "NO";
  1078. if (!myrpt->totimer)
  1079. tot_state = "TIMED OUT!";
  1080. else if (myrpt->totimer != myrpt->p.totime)
  1081. tot_state = "ARMED";
  1082. else
  1083. tot_state = "RESET";
  1084. if (myrpt->tailid)
  1085. ider_state = "QUEUED IN TAIL";
  1086. else if (myrpt->mustid)
  1087. ider_state = "QUEUED FOR CLEANUP";
  1088. else
  1089. ider_state = "CLEAN";
  1090. switch (myrpt->callmode) {
  1091. case 1:
  1092. patch_state = "DIALING";
  1093. break;
  1094. case 2:
  1095. patch_state = "CONNECTING";
  1096. break;
  1097. case 3:
  1098. patch_state = "UP";
  1099. break;
  1100. case 4:
  1101. patch_state = "CALL FAILED";
  1102. break;
  1103. default:
  1104. patch_state = "DOWN";
  1105. }
  1106. if (!ast_strlen_zero(myrpt->exten))
  1107. called_number = ast_strdupa(myrpt->exten);
  1108. if (!ast_strlen_zero(myrpt->lastdtmfcommand))
  1109. lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
  1110. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  1111. ast_cli(a->fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
  1112. ast_cli(a->fd, "Signal on input..................................: %s\n", input_signal);
  1113. ast_cli(a->fd, "Transmitter enabled..............................: %s\n", enable_state);
  1114. ast_cli(a->fd, "Time out timer state.............................: %s\n", tot_state);
  1115. ast_cli(a->fd, "Time outs since system initialization............: %d\n", timeouts);
  1116. ast_cli(a->fd, "Identifier state.................................: %s\n", ider_state);
  1117. ast_cli(a->fd, "Kerchunks today..................................: %d\n", dailykerchunks);
  1118. ast_cli(a->fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
  1119. ast_cli(a->fd, "Keyups today.....................................: %d\n", dailykeyups);
  1120. ast_cli(a->fd, "Keyups since system initialization...............: %d\n", totalkeyups);
  1121. ast_cli(a->fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
  1122. ast_cli(a->fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
  1123. ast_cli(a->fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
  1124. hours = dailytxtime / 3600000;
  1125. dailytxtime %= 3600000;
  1126. minutes = dailytxtime / 60000;
  1127. dailytxtime %= 60000;
  1128. seconds = dailytxtime / 1000;
  1129. dailytxtime %= 1000;
  1130. ast_cli(a->fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
  1131. hours, minutes, seconds, dailytxtime);
  1132. hours = (int) totaltxtime / 3600000;
  1133. totaltxtime %= 3600000;
  1134. minutes = (int) totaltxtime / 60000;
  1135. totaltxtime %= 60000;
  1136. seconds = (int) totaltxtime / 1000;
  1137. totaltxtime %= 1000;
  1138. ast_cli(a->fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
  1139. hours, minutes, seconds, (int) totaltxtime);
  1140. ast_cli(a->fd, "Nodes currently connected to us..................: ");
  1141. for (j = 0;; j++) {
  1142. if (!listoflinks[j]) {
  1143. if (!j) {
  1144. ast_cli(a->fd, "<NONE>");
  1145. }
  1146. break;
  1147. }
  1148. ast_cli(a->fd, "%s", listoflinks[j]);
  1149. if (j % 4 == 3) {
  1150. ast_cli(a->fd, "\n");
  1151. ast_cli(a->fd, " : ");
  1152. } else {
  1153. if (listoflinks[j + 1])
  1154. ast_cli(a->fd, ", ");
  1155. }
  1156. }
  1157. ast_cli(a->fd, "\n");
  1158. ast_cli(a->fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
  1159. ast_cli(a->fd, "Autopatch state..................................: %s\n", patch_state);
  1160. ast_cli(a->fd, "Autopatch called number..........................: %s\n", called_number);
  1161. ast_cli(a->fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state);
  1162. return CLI_SUCCESS;
  1163. }
  1164. }
  1165. return CLI_FAILURE;
  1166. }
  1167. /*
  1168. * Link stats function
  1169. */
  1170. static char *handle_cli_rpt_lstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  1171. {
  1172. int i, j;
  1173. struct rpt *myrpt;
  1174. struct rpt_link *l;
  1175. struct rpt_lstat *s, *t;
  1176. struct rpt_lstat s_head;
  1177. switch (cmd) {
  1178. case CLI_INIT:
  1179. e->command = "rpt lstats";
  1180. e->usage =
  1181. "Usage: rpt lstats <nodename>\n"
  1182. " Dumps link statistics to console\n";
  1183. return NULL;
  1184. case CLI_GENERATE:
  1185. return NULL;
  1186. }
  1187. if (a->argc != 3)
  1188. return CLI_SHOWUSAGE;
  1189. s = NULL;
  1190. s_head.next = &s_head;
  1191. s_head.prev = &s_head;
  1192. for (i = 0; i < nrpts; i++) {
  1193. if (!strcmp(a->argv[2], rpt_vars[i].name)) {
  1194. /* Make a copy of all stat variables while locked */
  1195. myrpt = &rpt_vars[i];
  1196. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  1197. /* Traverse the list of connected nodes */
  1198. j = 0;
  1199. l = myrpt->links.next;
  1200. while (l != &myrpt->links) {
  1201. if (l->name[0] == '0') { /* Skip '0' nodes */
  1202. l = l->next;
  1203. continue;
  1204. }
  1205. if ((s = ast_calloc(1, sizeof(*s))) == NULL) {
  1206. ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
  1207. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  1208. return CLI_FAILURE;
  1209. }
  1210. ast_copy_string(s->name, l->name, MAXREMSTR);
  1211. pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
  1212. s->mode = l->mode;
  1213. s->outbound = l->outbound;
  1214. s->reconnects = l->reconnects;
  1215. s->connecttime = l->connecttime;
  1216. insque((struct qelem *) s, (struct qelem *) s_head.next);
  1217. l = l->next;
  1218. }
  1219. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  1220. ast_cli(a->fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME\n");
  1221. ast_cli(a->fd, "---- ---- ---------- --------- ------------\n");
  1222. for (s = s_head.next; s != &s_head; s = s->next) {
  1223. int hours, minutes, seconds;
  1224. long long connecttime = s->connecttime;
  1225. char conntime[31];
  1226. hours = (int) connecttime/3600000;
  1227. connecttime %= 3600000;
  1228. minutes = (int) connecttime/60000;
  1229. connecttime %= 60000;
  1230. seconds = (int) connecttime/1000;
  1231. connecttime %= 1000;
  1232. snprintf(conntime, sizeof(conntime), "%02d:%02d:%02d.%d",
  1233. hours, minutes, seconds, (int) connecttime);
  1234. ast_cli(a->fd, "%-10s%-20s%-12d%-11s%-30s\n",
  1235. s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime);
  1236. }
  1237. /* destroy our local link queue */
  1238. s = s_head.next;
  1239. while (s != &s_head) {
  1240. t = s;
  1241. s = s->next;
  1242. remque((struct qelem *)t);
  1243. ast_free(t);
  1244. }
  1245. return CLI_SUCCESS;
  1246. }
  1247. }
  1248. return CLI_FAILURE;
  1249. }
  1250. /*
  1251. * reload vars
  1252. */
  1253. static char *handle_cli_rpt_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  1254. {
  1255. int n;
  1256. switch (cmd) {
  1257. case CLI_INIT:
  1258. e->command = "rpt reload";
  1259. e->usage =
  1260. "Usage: rpt reload\n"
  1261. " Reloads app_rpt running config parameters\n";
  1262. return NULL;
  1263. case CLI_GENERATE:
  1264. return NULL;
  1265. }
  1266. if (a->argc > 2)
  1267. return CLI_SHOWUSAGE;
  1268. for (n = 0; n < nrpts; n++)
  1269. rpt_vars[n].reload = 1;
  1270. return CLI_SUCCESS;
  1271. }
  1272. /*
  1273. * restart app_rpt
  1274. */
  1275. static char *handle_cli_rpt_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  1276. {
  1277. int i;
  1278. switch (cmd) {
  1279. case CLI_INIT:
  1280. e->command = "rpt restart";
  1281. e->usage =
  1282. "Usage: rpt restart\n"
  1283. " Restarts app_rpt\n";
  1284. return NULL;
  1285. case CLI_GENERATE:
  1286. return NULL;
  1287. }
  1288. if (a->argc > 2)
  1289. return CLI_SHOWUSAGE;
  1290. for (i = 0; i < nrpts; i++) {
  1291. if (rpt_vars[i].rxchannel)
  1292. ast_softhangup(rpt_vars[i].rxchannel, AST_SOFTHANGUP_DEV);
  1293. }
  1294. return CLI_SUCCESS;
  1295. }
  1296. static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
  1297. {
  1298. int res;
  1299. if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
  1300. return res;
  1301. while (chan->generatordata) {
  1302. if (ast_safe_sleep(chan, 1))
  1303. return -1;
  1304. }
  1305. return 0;
  1306. }
  1307. static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
  1308. {
  1309. return play_tone_pair(chan, freq, 0, duration, amplitude);
  1310. }
  1311. static int play_silence(struct ast_channel *chan, int duration)
  1312. {
  1313. return play_tone_pair(chan, 0, 0, duration, 0);
  1314. }
  1315. static int send_morse(struct ast_channel *chan, const char *string, int speed, int freq, int amplitude)
  1316. {
  1317. static struct morse_bits mbits[] = {
  1318. {0, 0}, /* SPACE */
  1319. {0, 0},
  1320. {6, 18},/* " */
  1321. {0, 0},
  1322. {7, 72},/* $ */
  1323. {0, 0},
  1324. {0, 0},
  1325. {6, 30},/* ' */
  1326. {5, 13},/* ( */
  1327. {6, 29},/* ) */
  1328. {0, 0},
  1329. {5, 10},/* + */
  1330. {6, 51},/* , */
  1331. {6, 33},/* - */
  1332. {6, 42},/* . */
  1333. {5, 9}, /* / */
  1334. {5, 31},/* 0 */
  1335. {5, 30},/* 1 */
  1336. {5, 28},/* 2 */
  1337. {5, 24},/* 3 */
  1338. {5, 16},/* 4 */
  1339. {5, 0}, /* 5 */
  1340. {5, 1}, /* 6 */
  1341. {5, 3}, /* 7 */
  1342. {5, 7}, /* 8 */
  1343. {5, 15},/* 9 */
  1344. {6, 7}, /* : */
  1345. {6, 21},/* ; */
  1346. {0, 0},
  1347. {5, 33},/* = */
  1348. {0, 0},
  1349. {6, 12},/* ? */
  1350. {0, 0},
  1351. {2, 2}, /* A */
  1352. {4, 1}, /* B */
  1353. {4, 5}, /* C */
  1354. {3, 1}, /* D */
  1355. {1, 0}, /* E */
  1356. {4, 4}, /* F */
  1357. {3, 3}, /* G */
  1358. {4, 0}, /* H */
  1359. {2, 0}, /* I */
  1360. {4, 14},/* J */
  1361. {3, 5}, /* K */
  1362. {4, 2}, /* L */
  1363. {2, 3}, /* M */
  1364. {2, 1}, /* N */
  1365. {3, 7}, /* O */
  1366. {4, 6}, /* P */
  1367. {4, 11},/* Q */
  1368. {3, 2}, /* R */
  1369. {3, 0}, /* S */
  1370. {1, 1}, /* T */
  1371. {3, 4}, /* U */
  1372. {4, 8}, /* V */
  1373. {3, 6}, /* W */
  1374. {4, 9}, /* X */
  1375. {4, 13},/* Y */
  1376. {4, 3} /* Z */
  1377. };
  1378. int dottime;
  1379. int dashtime;
  1380. int intralettertime;
  1381. int interlettertime;
  1382. int interwordtime;
  1383. int len, ddcomb;
  1384. int res;
  1385. int c;
  1386. int i;
  1387. int flags;
  1388. res = 0;
  1389. /* Approximate the dot time from the speed arg. */
  1390. dottime = 900 / speed;
  1391. /* Establish timing relationships */
  1392. dashtime = 3 * dottime;
  1393. intralettertime = dottime;
  1394. interlettertime = dottime * 4 ;
  1395. interwordtime = dottime * 7;
  1396. for (; (*string) && (!res); string++) {
  1397. c = *string;
  1398. /* Convert lower case to upper case */
  1399. if ((c >= 'a') && (c <= 'z'))
  1400. c -= 0x20;
  1401. /* Can't deal with any char code greater than Z, skip it */
  1402. if (c > 'Z')
  1403. continue;
  1404. /* If space char, wait the inter word time */
  1405. if (c == ' ') {
  1406. if (!res)
  1407. res = play_silence(chan, interwordtime);
  1408. continue;
  1409. }
  1410. /* Subtract out control char offset to match our table */
  1411. c -= 0x20;
  1412. /* Get the character data */
  1413. len = mbits[c].len;
  1414. ddcomb = mbits[c].ddcomb;
  1415. /* Send the character */
  1416. for (; len ; len--) {
  1417. if (!res)
  1418. res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
  1419. if (!res)
  1420. res = play_silence(chan, intralettertime);
  1421. ddcomb >>= 1;
  1422. }
  1423. /* Wait the interletter time */
  1424. if (!res)
  1425. res = play_silence(chan, interlettertime - intralettertime);
  1426. }
  1427. /* Wait for all the frames to be sent */
  1428. if (!res)
  1429. res = ast_waitstream(chan, "");
  1430. ast_stopstream(chan);
  1431. /*
  1432. * Wait for the dahdi driver to physically write the tone blocks to the hardware
  1433. */
  1434. for (i = 0; i < 20 ; i++) {
  1435. flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
  1436. res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
  1437. if (flags & DAHDI_IOMUX_WRITEEMPTY)
  1438. break;
  1439. if ( ast_safe_sleep(chan, 50)) {
  1440. res = -1;
  1441. break;
  1442. }
  1443. }
  1444. return res;
  1445. }
  1446. static int send_tone_telemetry(struct ast_channel *chan, const char *tonestring)
  1447. {
  1448. char *stringp;
  1449. char *tonesubset;
  1450. int f1, f2;
  1451. int duration;
  1452. int amplitude;
  1453. int res;
  1454. int i;
  1455. int flags;
  1456. res = 0;
  1457. stringp = ast_strdupa(tonestring);
  1458. for (;tonestring;) {
  1459. tonesubset = strsep(&stringp, ")");
  1460. if (!tonesubset)
  1461. break;
  1462. if (sscanf(tonesubset, "(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &amplitude) != 4)
  1463. break;
  1464. res = play_tone_pair(chan, f1, f2, duration, amplitude);
  1465. if (res)
  1466. break;
  1467. }
  1468. if (!res)
  1469. res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
  1470. if (!res)
  1471. res = ast_waitstream(chan, "");
  1472. ast_stopstream(chan);
  1473. /*
  1474. * Wait for the dahdi driver to physically write the tone blocks to the hardware
  1475. */
  1476. for (i = 0; i < 20 ; i++) {
  1477. flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
  1478. res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
  1479. if (flags & DAHDI_IOMUX_WRITEEMPTY)
  1480. break;
  1481. if (ast_safe_sleep(chan, 50)) {
  1482. res = -1;
  1483. break;
  1484. }
  1485. }
  1486. return res;
  1487. }
  1488. static int sayfile(struct ast_channel *mychannel, const char *fname)
  1489. {
  1490. int res;
  1491. res = ast_streamfile(mychannel, fname, mychannel->language);
  1492. if (!res)
  1493. res = ast_waitstream(mychannel, "");
  1494. else
  1495. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1496. ast_stopstream(mychannel);
  1497. return res;
  1498. }
  1499. static int saycharstr(struct ast_channel *mychannel, char *str)
  1500. {
  1501. int res;
  1502. res = ast_say_character_str(mychannel, str, NULL, mychannel->language);
  1503. if (!res)
  1504. res = ast_waitstream(mychannel, "");
  1505. else
  1506. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1507. ast_stopstream(mychannel);
  1508. return res;
  1509. }
  1510. static int saynum(struct ast_channel *mychannel, int num)
  1511. {
  1512. int res;
  1513. res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
  1514. if (!res)
  1515. res = ast_waitstream(mychannel, "");
  1516. else
  1517. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1518. ast_stopstream(mychannel);
  1519. return res;
  1520. }
  1521. static int saydigits(struct ast_channel *mychannel, int num)
  1522. {
  1523. int res;
  1524. res = ast_say_digits(mychannel, num, NULL, mychannel->language);
  1525. if (!res)
  1526. res = ast_waitstream(mychannel, "");
  1527. else
  1528. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1529. ast_stopstream(mychannel);
  1530. return res;
  1531. }
  1532. static int telem_any(struct rpt *myrpt, struct ast_channel *chan, const char *entry)
  1533. {
  1534. int res;
  1535. char c;
  1536. static int morsespeed;
  1537. static int morsefreq;
  1538. static int morseampl;
  1539. static int morseidfreq = 0;
  1540. static int morseidampl;
  1541. static char mcat[] = MORSE;
  1542. res = 0;
  1543. if (!morseidfreq) { /* Get the morse parameters if not already loaded */
  1544. morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
  1545. morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
  1546. morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
  1547. morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
  1548. morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
  1549. }
  1550. /* Is it a file, or a tone sequence? */
  1551. if (entry[0] == '|') {
  1552. c = entry[1];
  1553. if ((c >= 'a') && (c <= 'z'))
  1554. c -= 0x20;
  1555. switch (c) {
  1556. case 'I': /* Morse ID */
  1557. res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
  1558. break;
  1559. case 'M': /* Morse Message */
  1560. res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
  1561. break;
  1562. case 'T': /* Tone sequence */
  1563. res = send_tone_telemetry(chan, entry + 2);
  1564. break;
  1565. default:
  1566. res = -1;
  1567. }
  1568. } else
  1569. res = sayfile(chan, entry); /* File */
  1570. return res;
  1571. }
  1572. /*
  1573. * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
  1574. *
  1575. * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
  1576. */
  1577. static int telem_lookup(struct rpt *myrpt, struct ast_channel *chan, const char *node, const char *name)
  1578. {
  1579. int res = 0;
  1580. int i;
  1581. const char *entry = NULL;
  1582. const char *telemetry;
  1583. /* Retrieve the section name for telemetry from the node section */
  1584. if ((telemetry = ast_variable_retrieve(myrpt->cfg, node, TELEMETRY)))
  1585. entry = ast_variable_retrieve(myrpt->cfg, telemetry, name);
  1586. /* Try to look up the telemetry name */
  1587. if (!entry) {
  1588. /* Telemetry name wasn't found in the config file, use the default */
  1589. for (i = 0; i < sizeof(tele_defs) / sizeof(struct telem_defaults); i++) {
  1590. if (!strcasecmp(tele_defs[i].name, name))
  1591. entry = tele_defs[i].value;
  1592. }
  1593. }
  1594. if (entry) {
  1595. if (!ast_strlen_zero(entry))
  1596. telem_any(myrpt, chan, entry);
  1597. } else {
  1598. res = -1;
  1599. }
  1600. return res;
  1601. }
  1602. /*
  1603. * Retrieve a wait interval
  1604. */
  1605. static int get_wait_interval(struct rpt *myrpt, int type)
  1606. {
  1607. int interval = 1000;
  1608. const char *wait_times = ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
  1609. switch (type) {
  1610. case DLY_TELEM:
  1611. if (wait_times)
  1612. interval = retrieve_astcfgint(myrpt, wait_times, "telemwait", 500, 5000, 1000);
  1613. break;
  1614. case DLY_ID:
  1615. if (wait_times)
  1616. interval = retrieve_astcfgint(myrpt, wait_times, "idwait", 250, 5000, 500);
  1617. else
  1618. interval = 500;
  1619. break;
  1620. case DLY_UNKEY:
  1621. if (wait_times)
  1622. interval = retrieve_astcfgint(myrpt, wait_times, "unkeywait", 500, 5000, 1000);
  1623. break;
  1624. case DLY_CALLTERM:
  1625. if (wait_times)
  1626. interval = retrieve_astcfgint(myrpt, wait_times, "calltermwait", 500, 5000, 1500);
  1627. break;
  1628. default:
  1629. return 0;
  1630. }
  1631. return interval;
  1632. }
  1633. /*
  1634. * Wait a configurable interval of time
  1635. */
  1636. static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
  1637. {
  1638. int interval;
  1639. interval = get_wait_interval(myrpt, type);
  1640. if (debug)
  1641. ast_log(LOG_NOTICE, " Delay interval = %d\n", interval);
  1642. if (interval)
  1643. ast_safe_sleep(chan, interval);
  1644. if (debug)
  1645. ast_log(LOG_NOTICE, "Delay complete\n");
  1646. return;
  1647. }
  1648. static void *rpt_tele_thread(void *this)
  1649. {
  1650. struct dahdi_confinfo ci; /* conference info */
  1651. int res = 0, haslink, hastx, hasremote, imdone = 0, unkeys_queued, x;
  1652. struct rpt_tele *mytele = (struct rpt_tele *)this;
  1653. struct rpt_tele *tlist;
  1654. struct rpt *myrpt;
  1655. struct rpt_link *l, *m, linkbase;
  1656. struct ast_channel *mychannel;
  1657. const char *p, *ct;
  1658. struct timeval tv;
  1659. struct ast_tm localtm;
  1660. #ifdef APP_RPT_LOCK_DEBUG
  1661. struct lockthread *t;
  1662. #endif
  1663. /* get a pointer to myrpt */
  1664. myrpt = mytele->rpt;
  1665. /* Snag copies of a few key myrpt variables */
  1666. rpt_mutex_lock(&myrpt->lock);
  1667. rpt_mutex_unlock(&myrpt->lock);
  1668. /* allocate a pseudo-channel thru asterisk */
  1669. mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  1670. if (!mychannel) {
  1671. ast_log(LOG_WARNING, "rpt: unable to obtain pseudo channel\n");
  1672. rpt_mutex_lock(&myrpt->lock);
  1673. remque((struct qelem *)mytele);
  1674. ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  1675. rpt_mutex_unlock(&myrpt->lock);
  1676. ast_free(mytele);
  1677. pthread_exit(NULL);
  1678. }
  1679. rpt_mutex_lock(&myrpt->lock);
  1680. mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */
  1681. rpt_mutex_unlock(&myrpt->lock);
  1682. /* make a conference for the tx */
  1683. ci.chan = 0;
  1684. /* If there's an ID queued, or tail message queued, */
  1685. /* only connect the ID audio to the local tx conference so */
  1686. /* linked systems can't hear it */
  1687. ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
  1688. (mytele->mode == TAILMSG)) ?
  1689. myrpt->txconf : myrpt->conf);
  1690. ci.confmode = DAHDI_CONF_CONFANN;
  1691. /* first put the channel on the conference in announce mode */
  1692. if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  1693. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  1694. rpt_mutex_lock(&myrpt->lock);
  1695. remque((struct qelem *)mytele);
  1696. rpt_mutex_unlock(&myrpt->lock);
  1697. ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  1698. ast_free(mytele);
  1699. ast_hangup(mychannel);
  1700. pthread_exit(NULL);
  1701. }
  1702. ast_stopstream(mychannel);
  1703. switch (mytele->mode) {
  1704. case ID:
  1705. case ID1:
  1706. /* wait a bit */
  1707. wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM, mychannel);
  1708. res = telem_any(myrpt, mychannel, myrpt->p.ident);
  1709. imdone=1;
  1710. break;
  1711. case TAILMSG:
  1712. res = ast_streamfile(mychannel, myrpt->p.tailmsg.msgs[myrpt->tailmessagen], mychannel->language);
  1713. break;
  1714. case IDTALKOVER:
  1715. p = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
  1716. if (p)
  1717. res = telem_any(myrpt, mychannel, p);
  1718. imdone = 1;
  1719. break;
  1720. case PROC:
  1721. /* wait a little bit longer */
  1722. wait_interval(myrpt, DLY_TELEM, mychannel);
  1723. res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
  1724. if (res < 0) { /* Then default message */
  1725. res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
  1726. }
  1727. break;
  1728. case TERM:
  1729. /* wait a little bit longer */
  1730. wait_interval(myrpt, DLY_CALLTERM, mychannel);
  1731. res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
  1732. if (res < 0) { /* Then default message */
  1733. res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
  1734. }
  1735. break;
  1736. case COMPLETE:
  1737. /* wait a little bit */
  1738. wait_interval(myrpt, DLY_TELEM, mychannel);
  1739. res = telem_lookup(myrpt, mychannel, myrpt->name, "functcomplete");
  1740. break;
  1741. case MACRO_NOTFOUND:
  1742. /* wait a little bit */
  1743. wait_interval(myrpt, DLY_TELEM, mychannel);
  1744. res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
  1745. break;
  1746. case GOSUB_NOTFOUND:
  1747. /* wait a little bit */
  1748. wait_interval(myrpt, DLY_TELEM, mychannel);
  1749. res = ast_streamfile(mychannel, "rpt/gosub_notfound", mychannel->language);
  1750. break;
  1751. case MACRO_BUSY:
  1752. /* wait a little bit */
  1753. wait_interval(myrpt, DLY_TELEM, mychannel);
  1754. res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
  1755. break;
  1756. case GOSUB_BUSY:
  1757. /* wait a little bit */
  1758. wait_interval(myrpt, DLY_TELEM, mychannel);
  1759. res = ast_streamfile(mychannel, "rpt/gosub_busy", mychannel->language);
  1760. break;
  1761. case UNKEY:
  1762. if (myrpt->patchnoct && myrpt->callmode) { /* If no CT during patch configured, then don't send one */
  1763. imdone = 1;
  1764. break;
  1765. }
  1766. /*
  1767. * Reset the Unkey to CT timer
  1768. */
  1769. x = get_wait_interval(myrpt, DLY_UNKEY);
  1770. rpt_mutex_lock(&myrpt->lock);
  1771. myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
  1772. rpt_mutex_unlock(&myrpt->lock);
  1773. /*
  1774. * If there's one already queued, don't do another
  1775. */
  1776. tlist = myrpt->tele.next;
  1777. unkeys_queued = 0;
  1778. if (tlist != &myrpt->tele) {
  1779. rpt_mutex_lock(&myrpt->lock);
  1780. while (tlist != &myrpt->tele) {
  1781. if (tlist->mode == UNKEY)
  1782. unkeys_queued++;
  1783. tlist = tlist->next;
  1784. }
  1785. rpt_mutex_unlock(&myrpt->lock);
  1786. }
  1787. if (unkeys_queued > 1) {
  1788. imdone = 1;
  1789. break;
  1790. }
  1791. /* Wait for the telemetry timer to expire */
  1792. /* Periodically check the timer since it can be re-initialized above */
  1793. while (myrpt->unkeytocttimer) {
  1794. int ctint;
  1795. if (myrpt->unkeytocttimer > 100)
  1796. ctint = 100;
  1797. else
  1798. ctint = myrpt->unkeytocttimer;
  1799. ast_safe_sleep(mychannel, ctint);
  1800. rpt_mutex_lock(&myrpt->lock);
  1801. if (myrpt->unkeytocttimer < ctint)
  1802. myrpt->unkeytocttimer = 0;
  1803. else
  1804. myrpt->unkeytocttimer -= ctint;
  1805. rpt_mutex_unlock(&myrpt->lock);
  1806. }
  1807. /*
  1808. * Now, the carrier on the rptr rx should be gone.
  1809. * If it re-appeared, then forget about sending the CT
  1810. */
  1811. if (myrpt->keyed) {
  1812. imdone = 1;
  1813. break;
  1814. }
  1815. rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */
  1816. myrpt->dailykerchunks++;
  1817. myrpt->totalkerchunks++;
  1818. rpt_mutex_unlock(&myrpt->lock);
  1819. haslink = 0;
  1820. hastx = 0;
  1821. hasremote = 0;
  1822. l = myrpt->links.next;
  1823. if (l != &myrpt->links) {
  1824. rpt_mutex_lock(&myrpt->lock);
  1825. while (l != &myrpt->links) {
  1826. if (l->name[0] == '0') {
  1827. l = l->next;
  1828. continue;
  1829. }
  1830. haslink = 1;
  1831. if (l->mode) {
  1832. hastx++;
  1833. if (l->isremote)
  1834. hasremote++;
  1835. }
  1836. l = l->next;
  1837. }
  1838. rpt_mutex_unlock(&myrpt->lock);
  1839. }
  1840. if (haslink) {
  1841. res = telem_lookup(myrpt, mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
  1842. if (res)
  1843. ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
  1844. /* if in remote cmd mode, indicate it */
  1845. if (myrpt->cmdnode[0]) {
  1846. ast_safe_sleep(mychannel, 200);
  1847. res = telem_lookup(myrpt, mychannel, myrpt->name, "cmdmode");
  1848. if (res)
  1849. ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
  1850. ast_stopstream(mychannel);
  1851. }
  1852. } else if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "unlinkedct"))) { /* Unlinked Courtesy Tone */
  1853. res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
  1854. if (res)
  1855. ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
  1856. }
  1857. if (hasremote && (!myrpt->cmdnode[0])) {
  1858. /* set for all to hear */
  1859. ci.chan = 0;
  1860. ci.confno = myrpt->conf;
  1861. ci.confmode = DAHDI_CONF_CONFANN;
  1862. /* first put the channel on the conference in announce mode */
  1863. if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  1864. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  1865. rpt_mutex_lock(&myrpt->lock);
  1866. remque((struct qelem *)mytele);
  1867. rpt_mutex_unlock(&myrpt->lock);
  1868. ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  1869. ast_free(mytele);
  1870. ast_hangup(mychannel);
  1871. pthread_exit(NULL);
  1872. }
  1873. if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "remotect"))) { /* Unlinked Courtesy Tone */
  1874. ast_safe_sleep(mychannel, 200);
  1875. res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
  1876. if (res)
  1877. ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
  1878. }
  1879. }
  1880. #ifdef _MDC_DECODE_H_
  1881. if (myrpt->lastunit) {
  1882. char mystr[10];
  1883. ast_safe_sleep(mychannel, 200);
  1884. /* set for all to hear */
  1885. ci.chan = 0;
  1886. ci.confno = myrpt->txconf;
  1887. ci.confmode = DAHDI_CONF_CONFANN;
  1888. /* first put the channel on the conference in announce mode */
  1889. if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  1890. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  1891. rpt_mutex_lock(&myrpt->lock);
  1892. remque((struct qelem *)mytele);
  1893. rpt_mutex_unlock(&myrpt->lock);
  1894. ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  1895. ast_free(mytele);
  1896. ast_hangup(mychannel);
  1897. pthread_exit(NULL);
  1898. }
  1899. snprintf(mystr, sizeof(mystr), "%04x", myrpt->lastunit);
  1900. myrpt->lastunit = 0;
  1901. ast_say_character_str(mychannel, mystr, NULL, mychannel->language);
  1902. break;
  1903. }
  1904. #endif
  1905. imdone = 1;
  1906. break;
  1907. case REMDISC:
  1908. /* wait a little bit */
  1909. wait_interval(myrpt, DLY_TELEM, mychannel);
  1910. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  1911. if (!res)
  1912. res = ast_waitstream(mychannel, "");
  1913. else
  1914. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1915. ast_stopstream(mychannel);
  1916. ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
  1917. res = ast_streamfile(mychannel, ((mytele->mylink.connected) ?
  1918. "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
  1919. break;
  1920. case REMALREADY:
  1921. /* wait a little bit */
  1922. wait_interval(myrpt, DLY_TELEM, mychannel);
  1923. res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
  1924. break;
  1925. case REMNOTFOUND:
  1926. /* wait a little bit */
  1927. wait_interval(myrpt, DLY_TELEM, mychannel);
  1928. res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
  1929. break;
  1930. case REMGO:
  1931. /* wait a little bit */
  1932. wait_interval(myrpt, DLY_TELEM, mychannel);
  1933. res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
  1934. break;
  1935. case CONNECTED:
  1936. /* wait a little bit */
  1937. wait_interval(myrpt, DLY_TELEM, mychannel);
  1938. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  1939. if (!res)
  1940. res = ast_waitstream(mychannel, "");
  1941. else
  1942. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1943. ast_stopstream(mychannel);
  1944. ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
  1945. res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
  1946. break;
  1947. case CONNFAIL:
  1948. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  1949. if (!res)
  1950. res = ast_waitstream(mychannel, "");
  1951. else
  1952. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1953. ast_stopstream(mychannel);
  1954. ast_say_character_str(mychannel, mytele->mylink.name, NULL, mychannel->language);
  1955. res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
  1956. break;
  1957. case STATUS:
  1958. /* wait a little bit */
  1959. wait_interval(myrpt, DLY_TELEM, mychannel);
  1960. hastx = 0;
  1961. linkbase.next = &linkbase;
  1962. linkbase.prev = &linkbase;
  1963. rpt_mutex_lock(&myrpt->lock);
  1964. /* make our own list of links */
  1965. l = myrpt->links.next;
  1966. while (l != &myrpt->links) {
  1967. if (l->name[0] == '0') {
  1968. l = l->next;
  1969. continue;
  1970. }
  1971. m = ast_malloc(sizeof(*m));
  1972. if (!m) {
  1973. ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
  1974. remque((struct qelem *)mytele);
  1975. rpt_mutex_unlock(&myrpt->lock);
  1976. ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  1977. ast_free(mytele);
  1978. ast_hangup(mychannel);
  1979. pthread_exit(NULL);
  1980. }
  1981. memcpy(m, l, sizeof(struct rpt_link));
  1982. m->next = m->prev = NULL;
  1983. insque((struct qelem *)m, (struct qelem *)linkbase.next);
  1984. l = l->next;
  1985. }
  1986. rpt_mutex_unlock(&myrpt->lock);
  1987. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  1988. if (!res)
  1989. res = ast_waitstream(mychannel, "");
  1990. else
  1991. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1992. ast_stopstream(mychannel);
  1993. ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language);
  1994. if (!res)
  1995. res = ast_waitstream(mychannel, "");
  1996. else
  1997. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  1998. ast_stopstream(mychannel);
  1999. if (myrpt->callmode) {
  2000. hastx = 1;
  2001. res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
  2002. if (!res)
  2003. res = ast_waitstream(mychannel, "");
  2004. else
  2005. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2006. ast_stopstream(mychannel);
  2007. }
  2008. l = linkbase.next;
  2009. while (l != &linkbase) {
  2010. hastx = 1;
  2011. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  2012. if (!res)
  2013. res = ast_waitstream(mychannel, "");
  2014. else
  2015. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2016. ast_stopstream(mychannel);
  2017. ast_say_character_str(mychannel, l->name, NULL, mychannel->language);
  2018. if (!res)
  2019. res = ast_waitstream(mychannel, "");
  2020. else
  2021. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2022. ast_stopstream(mychannel);
  2023. res = ast_streamfile(mychannel, ((l->mode) ?
  2024. "rpt/tranceive" : "rpt/monitor"), mychannel->language);
  2025. if (!res)
  2026. res = ast_waitstream(mychannel, "");
  2027. else
  2028. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2029. ast_stopstream(mychannel);
  2030. l = l->next;
  2031. }
  2032. if (!hastx) {
  2033. res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
  2034. if (!res)
  2035. res = ast_waitstream(mychannel, "");
  2036. else
  2037. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2038. ast_stopstream(mychannel);
  2039. }
  2040. /* destroy our local link queue */
  2041. l = linkbase.next;
  2042. while (l != &linkbase) {
  2043. m = l;
  2044. l = l->next;
  2045. remque((struct qelem *)m);
  2046. ast_free(m);
  2047. }
  2048. imdone = 1;
  2049. break;
  2050. case LASTNODEKEY: /* Identify last node which keyed us up */
  2051. rpt_mutex_lock(&myrpt->lock);
  2052. if (myrpt->lastnodewhichkeyedusup)
  2053. p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
  2054. else
  2055. p = NULL;
  2056. rpt_mutex_unlock(&myrpt->lock);
  2057. if (!p) {
  2058. imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
  2059. break;
  2060. }
  2061. wait_interval(myrpt, DLY_TELEM, mychannel);
  2062. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  2063. if (!res)
  2064. res = ast_waitstream(mychannel, "");
  2065. else
  2066. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2067. ast_stopstream(mychannel);
  2068. ast_say_character_str(mychannel, p, NULL, mychannel->language);
  2069. if (!res)
  2070. res = ast_waitstream(mychannel, "");
  2071. else
  2072. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2073. ast_stopstream(mychannel);
  2074. imdone = 1;
  2075. break;
  2076. case TIMEOUT:
  2077. res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
  2078. if (!res)
  2079. res = ast_waitstream(mychannel, "");
  2080. else
  2081. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2082. ast_stopstream(mychannel);
  2083. ast_say_character_str(mychannel, myrpt->name, NULL, mychannel->language);
  2084. res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
  2085. break;
  2086. case STATS_TIME:
  2087. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  2088. tv = ast_tvnow();
  2089. ast_localtime(&tv, &localtm, NULL);
  2090. /* Say the phase of the day is before the time */
  2091. if ((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
  2092. p = "rpt/goodmorning";
  2093. else if ((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
  2094. p = "rpt/goodafternoon";
  2095. else
  2096. p = "rpt/goodevening";
  2097. if (sayfile(mychannel, p) == -1) {
  2098. imdone = 1;
  2099. break;
  2100. }
  2101. /* Say the time is ... */
  2102. if (sayfile(mychannel, "rpt/thetimeis") == -1) {
  2103. imdone = 1;
  2104. break;
  2105. }
  2106. /* Say the time */
  2107. res = ast_say_time(mychannel, tv.tv_sec, "", mychannel->language);
  2108. if (!res)
  2109. res = ast_waitstream(mychannel, "");
  2110. ast_stopstream(mychannel);
  2111. imdone = 1;
  2112. break;
  2113. case STATS_VERSION:
  2114. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  2115. /* Say "version" */
  2116. if (sayfile(mychannel, "rpt/version") == -1) {
  2117. imdone = 1;
  2118. break;
  2119. }
  2120. if (!res) /* Say "X" */
  2121. ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
  2122. if (!res)
  2123. res = ast_waitstream(mychannel, "");
  2124. ast_stopstream(mychannel);
  2125. if (saycharstr(mychannel, ".") == -1) {
  2126. imdone = 1;
  2127. break;
  2128. }
  2129. if (!res) /* Say "Y" */
  2130. ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
  2131. if (!res) {
  2132. res = ast_waitstream(mychannel, "");
  2133. ast_stopstream(mychannel);
  2134. } else
  2135. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2136. imdone = 1;
  2137. break;
  2138. case ARB_ALPHA:
  2139. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  2140. if (mytele->param)
  2141. saycharstr(mychannel, mytele->param);
  2142. imdone = 1;
  2143. break;
  2144. case REV_PATCH:
  2145. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  2146. if (mytele->param) {
  2147. /* Parts of this section taken from app_parkandannounce */
  2148. char *tpl_working, *tpl_current;
  2149. char *tmp[100], *myparm;
  2150. int looptemp=0, i = 0, dres = 0;
  2151. tpl_working = ast_strdupa(mytele->param);
  2152. myparm = strsep(&tpl_working, ",");
  2153. tpl_current = strsep(&tpl_working, ":");
  2154. while (tpl_current && looptemp < sizeof(tmp)) {
  2155. tmp[looptemp] = tpl_current;
  2156. looptemp++;
  2157. tpl_current = strsep(&tpl_working, ":");
  2158. }
  2159. for (i = 0; i < looptemp; i++) {
  2160. if (!strcmp(tmp[i], "PARKED")) {
  2161. ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
  2162. } else if (!strcmp(tmp[i], "NODE")) {
  2163. ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
  2164. } else {
  2165. dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
  2166. if (!dres) {
  2167. dres = ast_waitstream(mychannel, "");
  2168. } else {
  2169. ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
  2170. dres = 0;
  2171. }
  2172. }
  2173. }
  2174. }
  2175. imdone = 1;
  2176. break;
  2177. case TEST_TONE:
  2178. imdone = 1;
  2179. myrpt->stopgen = 0;
  2180. if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
  2181. break;
  2182. while (mychannel->generatordata && (!myrpt->stopgen)) {
  2183. if (ast_safe_sleep(mychannel, 1)) break;
  2184. imdone = 1;
  2185. }
  2186. break;
  2187. default:
  2188. break;
  2189. }
  2190. myrpt->stopgen = 0;
  2191. if (!imdone) {
  2192. if (!res)
  2193. res = ast_waitstream(mychannel, "");
  2194. else {
  2195. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  2196. res = 0;
  2197. }
  2198. }
  2199. ast_stopstream(mychannel);
  2200. rpt_mutex_lock(&myrpt->lock);
  2201. if (mytele->mode == TAILMSG) {
  2202. if (!res) {
  2203. myrpt->tailmessagen++;
  2204. if (myrpt->tailmessagen >= myrpt->p.tailmsg.argc)
  2205. myrpt->tailmessagen = 0;
  2206. } else {
  2207. myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
  2208. }
  2209. }
  2210. remque((struct qelem *)mytele);
  2211. rpt_mutex_unlock(&myrpt->lock);
  2212. ast_free(mytele);
  2213. ast_hangup(mychannel);
  2214. #ifdef APP_RPT_LOCK_DEBUG
  2215. sleep(5);
  2216. ast_mutex_lock(&locklock);
  2217. t = get_lockthread(pthread_self());
  2218. if (t)
  2219. memset(t, 0, sizeof(struct lockthread));
  2220. ast_mutex_unlock(&locklock);
  2221. #endif
  2222. pthread_exit(NULL);
  2223. }
  2224. static void rpt_telemetry(struct rpt *myrpt, int mode, void *data)
  2225. {
  2226. struct rpt_tele *tele;
  2227. struct rpt_link *mylink = (struct rpt_link *) data;
  2228. int res;
  2229. tele = ast_calloc(1, sizeof(*tele));
  2230. if (!tele) {
  2231. ast_log(LOG_WARNING, "Unable to allocate memory\n");
  2232. pthread_exit(NULL);
  2233. }
  2234. tele->rpt = myrpt;
  2235. tele->mode = mode;
  2236. rpt_mutex_lock(&myrpt->lock);
  2237. if ((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)) {
  2238. if (mylink) {
  2239. memcpy(&tele->mylink, mylink, sizeof(struct rpt_link));
  2240. }
  2241. } else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
  2242. ast_copy_string(tele->param, (char *) data, sizeof(tele->param));
  2243. }
  2244. insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
  2245. rpt_mutex_unlock(&myrpt->lock);
  2246. res = ast_pthread_create_detached(&tele->threadid, NULL, rpt_tele_thread, (void *) tele);
  2247. if (res != 0) {
  2248. rpt_mutex_lock(&myrpt->lock);
  2249. remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
  2250. rpt_mutex_unlock(&myrpt->lock);
  2251. ast_log(LOG_WARNING, "Could not create telemetry thread: %s\n", strerror(res));
  2252. }
  2253. return;
  2254. }
  2255. static void *rpt_call(void *this)
  2256. {
  2257. struct dahdi_confinfo ci; /* conference info */
  2258. struct rpt *myrpt = (struct rpt *)this;
  2259. int res;
  2260. struct ast_frame wf;
  2261. int stopped, congstarted, dialtimer, lastcidx, aborted;
  2262. struct ast_channel *mychannel, *genchannel;
  2263. myrpt->mydtmf = 0;
  2264. /* allocate a pseudo-channel thru asterisk */
  2265. mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  2266. if (!mychannel) {
  2267. ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n");
  2268. pthread_exit(NULL);
  2269. }
  2270. ci.chan = 0;
  2271. ci.confno = myrpt->conf; /* use the pseudo conference */
  2272. ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
  2273. | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
  2274. /* first put the channel on the conference */
  2275. if (ioctl(mychannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2276. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2277. ast_hangup(mychannel);
  2278. myrpt->callmode = 0;
  2279. pthread_exit(NULL);
  2280. }
  2281. /* allocate a pseudo-channel thru asterisk */
  2282. genchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  2283. if (!genchannel) {
  2284. ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n");
  2285. ast_hangup(mychannel);
  2286. pthread_exit(NULL);
  2287. }
  2288. ci.chan = 0;
  2289. ci.confno = myrpt->conf;
  2290. ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
  2291. | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
  2292. /* first put the channel on the conference */
  2293. if (ioctl(genchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2294. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2295. ast_hangup(mychannel);
  2296. ast_hangup(genchannel);
  2297. myrpt->callmode = 0;
  2298. pthread_exit(NULL);
  2299. }
  2300. if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0], myrpt->p.tonezone) == -1)) {
  2301. ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
  2302. ast_hangup(mychannel);
  2303. ast_hangup(genchannel);
  2304. myrpt->callmode = 0;
  2305. pthread_exit(NULL);
  2306. }
  2307. if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0], myrpt->p.tonezone) == -1)) {
  2308. ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
  2309. ast_hangup(mychannel);
  2310. ast_hangup(genchannel);
  2311. myrpt->callmode = 0;
  2312. pthread_exit(NULL);
  2313. }
  2314. /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
  2315. if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0], DAHDI_TONE_DIALTONE) < 0)) {
  2316. ast_log(LOG_WARNING, "Cannot start dialtone\n");
  2317. ast_hangup(mychannel);
  2318. ast_hangup(genchannel);
  2319. myrpt->callmode = 0;
  2320. pthread_exit(NULL);
  2321. }
  2322. stopped = 0;
  2323. congstarted = 0;
  2324. dialtimer = 0;
  2325. lastcidx = 0;
  2326. aborted = 0;
  2327. while ((myrpt->callmode == 1) || (myrpt->callmode == 4)) {
  2328. if ((myrpt->patchdialtime) && (myrpt->callmode == 1) && (myrpt->cidx != lastcidx)) {
  2329. dialtimer = 0;
  2330. lastcidx = myrpt->cidx;
  2331. }
  2332. if ((myrpt->patchdialtime) && (dialtimer >= myrpt->patchdialtime)) {
  2333. rpt_mutex_lock(&myrpt->lock);
  2334. aborted = 1;
  2335. myrpt->callmode = 0;
  2336. rpt_mutex_unlock(&myrpt->lock);
  2337. break;
  2338. }
  2339. if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0)) {
  2340. stopped = 1;
  2341. /* stop dial tone */
  2342. tone_zone_play_tone(mychannel->fds[0], -1);
  2343. }
  2344. if (myrpt->callmode == 4) {
  2345. if (!congstarted) {
  2346. congstarted = 1;
  2347. /* start congestion tone */
  2348. tone_zone_play_tone(mychannel->fds[0], DAHDI_TONE_CONGESTION);
  2349. }
  2350. }
  2351. res = ast_safe_sleep(mychannel, MSWAIT);
  2352. if (res < 0) {
  2353. ast_hangup(mychannel);
  2354. ast_hangup(genchannel);
  2355. rpt_mutex_lock(&myrpt->lock);
  2356. myrpt->callmode = 0;
  2357. rpt_mutex_unlock(&myrpt->lock);
  2358. pthread_exit(NULL);
  2359. }
  2360. dialtimer += MSWAIT;
  2361. }
  2362. /* stop any tone generation */
  2363. tone_zone_play_tone(mychannel->fds[0], -1);
  2364. /* end if done */
  2365. if (!myrpt->callmode) {
  2366. ast_hangup(mychannel);
  2367. ast_hangup(genchannel);
  2368. rpt_mutex_lock(&myrpt->lock);
  2369. myrpt->callmode = 0;
  2370. rpt_mutex_unlock(&myrpt->lock);
  2371. if ((!myrpt->patchquiet) && aborted)
  2372. rpt_telemetry(myrpt, TERM, NULL);
  2373. pthread_exit(NULL);
  2374. }
  2375. if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid) {
  2376. char *name, *loc, *instr;
  2377. instr = ast_strdup(myrpt->p.ourcallerid);
  2378. if (instr) {
  2379. ast_callerid_parse(instr, &name, &loc);
  2380. if (loc) {
  2381. if (mychannel->cid.cid_num)
  2382. ast_free(mychannel->cid.cid_num);
  2383. mychannel->cid.cid_num = ast_strdup(loc);
  2384. }
  2385. if (name) {
  2386. if (mychannel->cid.cid_name)
  2387. ast_free(mychannel->cid.cid_name);
  2388. mychannel->cid.cid_name = ast_strdup(name);
  2389. }
  2390. ast_free(instr);
  2391. }
  2392. }
  2393. ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten));
  2394. ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context));
  2395. if (myrpt->p.acctcode)
  2396. ast_string_field_set(mychannel, accountcode, myrpt->p.acctcode);
  2397. mychannel->priority = 1;
  2398. ast_channel_undefer_dtmf(mychannel);
  2399. if (ast_pbx_start(mychannel) < 0) {
  2400. ast_log(LOG_WARNING, "Unable to start PBX!!\n");
  2401. ast_hangup(mychannel);
  2402. ast_hangup(genchannel);
  2403. rpt_mutex_lock(&myrpt->lock);
  2404. myrpt->callmode = 0;
  2405. rpt_mutex_unlock(&myrpt->lock);
  2406. pthread_exit(NULL);
  2407. }
  2408. usleep(10000);
  2409. rpt_mutex_lock(&myrpt->lock);
  2410. myrpt->callmode = 3;
  2411. /* set appropriate conference for the pseudo */
  2412. ci.chan = 0;
  2413. ci.confno = myrpt->conf;
  2414. ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
  2415. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  2416. /* first put the channel on the conference in announce mode */
  2417. if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2418. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2419. ast_hangup(mychannel);
  2420. ast_hangup(genchannel);
  2421. myrpt->callmode = 0;
  2422. pthread_exit(NULL);
  2423. }
  2424. while (myrpt->callmode) {
  2425. if ((!mychannel->pbx) && (myrpt->callmode != 4)) {
  2426. if (myrpt->patchfarenddisconnect) { /* If patch is setup for far end disconnect */
  2427. myrpt->callmode = 0;
  2428. if (!myrpt->patchquiet) {
  2429. rpt_mutex_unlock(&myrpt->lock);
  2430. rpt_telemetry(myrpt, TERM, NULL);
  2431. rpt_mutex_lock(&myrpt->lock);
  2432. }
  2433. } else { /* Send congestion until patch is downed by command */
  2434. myrpt->callmode = 4;
  2435. rpt_mutex_unlock(&myrpt->lock);
  2436. /* start congestion tone */
  2437. tone_zone_play_tone(genchannel->fds[0], DAHDI_TONE_CONGESTION);
  2438. rpt_mutex_lock(&myrpt->lock);
  2439. }
  2440. }
  2441. if (myrpt->mydtmf) {
  2442. wf.frametype = AST_FRAME_DTMF;
  2443. wf.subclass = myrpt->mydtmf;
  2444. wf.offset = 0;
  2445. wf.mallocd = 0;
  2446. wf.data = NULL;
  2447. wf.datalen = 0;
  2448. wf.samples = 0;
  2449. rpt_mutex_unlock(&myrpt->lock);
  2450. ast_write(genchannel, &wf);
  2451. rpt_mutex_lock(&myrpt->lock);
  2452. myrpt->mydtmf = 0;
  2453. }
  2454. rpt_mutex_unlock(&myrpt->lock);
  2455. usleep(MSWAIT * 1000);
  2456. rpt_mutex_lock(&myrpt->lock);
  2457. }
  2458. rpt_mutex_unlock(&myrpt->lock);
  2459. tone_zone_play_tone(genchannel->fds[0], -1);
  2460. if (mychannel->pbx)
  2461. ast_softhangup(mychannel, AST_SOFTHANGUP_DEV);
  2462. ast_hangup(genchannel);
  2463. rpt_mutex_lock(&myrpt->lock);
  2464. myrpt->callmode = 0;
  2465. rpt_mutex_unlock(&myrpt->lock);
  2466. /* set appropriate conference for the pseudo */
  2467. ci.chan = 0;
  2468. ci.confno = myrpt->conf;
  2469. ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
  2470. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  2471. /* first put the channel on the conference in announce mode */
  2472. if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2473. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2474. }
  2475. pthread_exit(NULL);
  2476. }
  2477. static void send_link_dtmf(struct rpt *myrpt, char c)
  2478. {
  2479. char str[300];
  2480. struct ast_frame wf;
  2481. struct rpt_link *l;
  2482. snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
  2483. wf.frametype = AST_FRAME_TEXT;
  2484. wf.subclass = 0;
  2485. wf.offset = 0;
  2486. wf.mallocd = 1;
  2487. wf.datalen = strlen(str) + 1;
  2488. wf.samples = 0;
  2489. l = myrpt->links.next;
  2490. /* first, see if our dude is there */
  2491. while (l != &myrpt->links) {
  2492. if (l->name[0] == '0') {
  2493. l = l->next;
  2494. continue;
  2495. }
  2496. /* if we found it, write it and were done */
  2497. if (!strcmp(l->name, myrpt->cmdnode)) {
  2498. wf.data = ast_strdup(str);
  2499. if (l->chan)
  2500. ast_write(l->chan, &wf);
  2501. return;
  2502. }
  2503. l = l->next;
  2504. }
  2505. l = myrpt->links.next;
  2506. /* if not, give it to everyone */
  2507. while (l != &myrpt->links) {
  2508. wf.data = ast_strdup(str);
  2509. if (l->chan)
  2510. ast_write(l->chan, &wf);
  2511. l = l->next;
  2512. }
  2513. return;
  2514. }
  2515. /*
  2516. * Internet linking function
  2517. */
  2518. static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
  2519. {
  2520. const char *val;
  2521. char *s, *tele;
  2522. char deststr[300] = "", modechange = 0;
  2523. char digitbuf[MAXNODESTR];
  2524. struct rpt_link *l;
  2525. int reconnects = 0;
  2526. struct dahdi_confinfo ci; /* conference info */
  2527. AST_DECLARE_APP_ARGS(args,
  2528. AST_APP_ARG(s1);
  2529. AST_APP_ARG(s2); /* XXX Never used. Scratch? XXX */
  2530. );
  2531. if (!param)
  2532. return DC_ERROR;
  2533. if (!myrpt->enable)
  2534. return DC_ERROR;
  2535. ast_copy_string(digitbuf, digits, sizeof(digitbuf));
  2536. ast_debug(1, "@@@@ ilink param = %s, digitbuf = %s\n", S_OR(param, "(null)"), digitbuf);
  2537. switch (myatoi(param)) {
  2538. case 1: /* Link off */
  2539. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  2540. strcpy(digitbuf, myrpt->lastlinknode);
  2541. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
  2542. if (!val) {
  2543. if (strlen(digitbuf) >= myrpt->longestnode)
  2544. return DC_ERROR;
  2545. break;
  2546. }
  2547. rpt_mutex_lock(&myrpt->lock);
  2548. l = myrpt->links.next;
  2549. /* try to find this one in queue */
  2550. while (l != &myrpt->links) {
  2551. if (l->name[0] == '0') {
  2552. l = l->next;
  2553. continue;
  2554. }
  2555. /* if found matching string */
  2556. if (!strcmp(l->name, digitbuf))
  2557. break;
  2558. l = l->next;
  2559. }
  2560. if (l != &myrpt->links) { /* if found */
  2561. struct ast_frame wf;
  2562. ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
  2563. l->retries = MAX_RETRIES + 1;
  2564. l->disced = 1;
  2565. rpt_mutex_unlock(&myrpt->lock);
  2566. wf.frametype = AST_FRAME_TEXT;
  2567. wf.subclass = 0;
  2568. wf.offset = 0;
  2569. wf.mallocd = 1;
  2570. wf.datalen = strlen(discstr) + 1;
  2571. wf.samples = 0;
  2572. wf.data = ast_strdup(discstr);
  2573. if (l->chan) {
  2574. ast_write(l->chan, &wf);
  2575. if (ast_safe_sleep(l->chan, 250) == -1)
  2576. return DC_ERROR;
  2577. ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
  2578. }
  2579. rpt_telemetry(myrpt, COMPLETE, NULL);
  2580. return DC_COMPLETE;
  2581. }
  2582. rpt_mutex_unlock(&myrpt->lock);
  2583. return DC_COMPLETE;
  2584. case 2: /* Link Monitor */
  2585. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  2586. strcpy(digitbuf, myrpt->lastlinknode);
  2587. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
  2588. if (!val) {
  2589. if (strlen(digitbuf) >= myrpt->longestnode)
  2590. return DC_ERROR;
  2591. break;
  2592. }
  2593. s = ast_strdupa(val);
  2594. AST_STANDARD_APP_ARGS(args, s);
  2595. rpt_mutex_lock(&myrpt->lock);
  2596. l = myrpt->links.next;
  2597. /* try to find this one in queue */
  2598. while (l != &myrpt->links) {
  2599. if (l->name[0] == '0') {
  2600. l = l->next;
  2601. continue;
  2602. }
  2603. /* if found matching string */
  2604. if (!strcmp(l->name, digitbuf))
  2605. break;
  2606. l = l->next;
  2607. }
  2608. /* if found */
  2609. if (l != &myrpt->links) {
  2610. /* if already in this mode, just ignore */
  2611. if ((!l->mode) || (!l->chan)) {
  2612. rpt_mutex_unlock(&myrpt->lock);
  2613. rpt_telemetry(myrpt, REMALREADY, NULL);
  2614. return DC_COMPLETE;
  2615. }
  2616. reconnects = l->reconnects;
  2617. rpt_mutex_unlock(&myrpt->lock);
  2618. if (l->chan)
  2619. ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
  2620. l->retries = MAX_RETRIES + 1;
  2621. l->disced = 2;
  2622. modechange = 1;
  2623. } else
  2624. rpt_mutex_unlock(&myrpt->lock);
  2625. ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
  2626. /* establish call in monitor mode */
  2627. l = ast_calloc(1, sizeof(*l));
  2628. if (!l) {
  2629. ast_log(LOG_WARNING, "Unable to malloc\n");
  2630. return DC_ERROR;
  2631. }
  2632. snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1);
  2633. tele = strchr(deststr, '/');
  2634. if (!tele) {
  2635. ast_log(LOG_ERROR, "link2:Dial number (%s) must be in format tech/number\n", deststr);
  2636. return DC_ERROR;
  2637. }
  2638. *tele++ = 0;
  2639. l->isremote = (s && ast_true(s));
  2640. ast_copy_string(l->name, digitbuf, MAXNODESTR);
  2641. l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
  2642. if (modechange)
  2643. l->connected = 1;
  2644. if (l->chan) {
  2645. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  2646. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  2647. l->chan->whentohangup = 0;
  2648. l->chan->appl = "Apprpt";
  2649. l->chan->data = "(Remote Rx)";
  2650. ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n",
  2651. deststr, tele, l->chan->name);
  2652. if (l->chan->cid.cid_num)
  2653. ast_free(l->chan->cid.cid_num);
  2654. l->chan->cid.cid_num = ast_strdup(myrpt->name);
  2655. ast_call(l->chan, tele, 0);
  2656. } else {
  2657. rpt_telemetry(myrpt, CONNFAIL, l);
  2658. ast_free(l);
  2659. ast_verb(3, "Unable to place call to %s/%s on %s\n",
  2660. deststr, tele, l->chan->name);
  2661. return DC_ERROR;
  2662. }
  2663. /* allocate a pseudo-channel thru asterisk */
  2664. l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  2665. if (!l->pchan) {
  2666. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
  2667. ast_hangup(l->chan);
  2668. ast_free(l);
  2669. return DC_ERROR;
  2670. }
  2671. ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
  2672. ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
  2673. /* make a conference for the pseudo-one */
  2674. ci.chan = 0;
  2675. ci.confno = myrpt->conf;
  2676. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
  2677. /* first put the channel on the conference in proper mode */
  2678. if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2679. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2680. ast_hangup(l->chan);
  2681. ast_hangup(l->pchan);
  2682. ast_free(l);
  2683. return DC_ERROR;
  2684. }
  2685. rpt_mutex_lock(&myrpt->lock);
  2686. l->reconnects = reconnects;
  2687. /* insert at end of queue */
  2688. insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
  2689. rpt_mutex_unlock(&myrpt->lock);
  2690. rpt_telemetry(myrpt, COMPLETE, NULL);
  2691. return DC_COMPLETE;
  2692. case 3: /* Link transceive */
  2693. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  2694. strcpy(digitbuf, myrpt->lastlinknode);
  2695. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
  2696. if (!val) {
  2697. if (strlen(digitbuf) >= myrpt->longestnode)
  2698. return DC_ERROR;
  2699. break;
  2700. }
  2701. s = ast_strdupa(val);
  2702. AST_STANDARD_APP_ARGS(args, s);
  2703. rpt_mutex_lock(&myrpt->lock);
  2704. l = myrpt->links.next;
  2705. /* try to find this one in queue */
  2706. while (l != &myrpt->links) {
  2707. if (l->name[0] == '0') {
  2708. l = l->next;
  2709. continue;
  2710. }
  2711. /* if found matching string */
  2712. if (!strcmp(l->name, digitbuf))
  2713. break;
  2714. l = l->next;
  2715. }
  2716. /* if found */
  2717. if (l != &myrpt->links) {
  2718. /* if already in this mode, just ignore */
  2719. if ((l->mode) || (!l->chan)) {
  2720. rpt_mutex_unlock(&myrpt->lock);
  2721. rpt_telemetry(myrpt, REMALREADY, NULL);
  2722. return DC_COMPLETE;
  2723. }
  2724. reconnects = l->reconnects;
  2725. rpt_mutex_unlock(&myrpt->lock);
  2726. if (l->chan)
  2727. ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
  2728. l->retries = MAX_RETRIES + 1;
  2729. l->disced = 2;
  2730. modechange = 1;
  2731. } else
  2732. rpt_mutex_unlock(&myrpt->lock);
  2733. ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
  2734. /* establish call in tranceive mode */
  2735. l = ast_calloc(1, sizeof(*l));
  2736. if (!l) {
  2737. ast_log(LOG_WARNING, "Unable to malloc\n");
  2738. return DC_ERROR;
  2739. }
  2740. l->mode = 1;
  2741. l->outbound = 1;
  2742. ast_copy_string(l->name, digitbuf, MAXNODESTR);
  2743. l->isremote = (s && ast_true(s));
  2744. if (modechange)
  2745. l->connected = 1;
  2746. snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1);
  2747. tele = strchr(deststr, '/');
  2748. if (!tele) {
  2749. ast_log(LOG_ERROR, "link3:Dial number (%s) must be in format tech/number\n", deststr);
  2750. ast_free(l);
  2751. return DC_ERROR;
  2752. }
  2753. *tele++ = 0;
  2754. l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
  2755. if (l->chan) {
  2756. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  2757. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  2758. l->chan->whentohangup = 0;
  2759. l->chan->appl = "Apprpt";
  2760. l->chan->data = "(Remote Rx)";
  2761. ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n",
  2762. deststr, tele, l->chan->name);
  2763. if (l->chan->cid.cid_num)
  2764. ast_free(l->chan->cid.cid_num);
  2765. l->chan->cid.cid_num = ast_strdup(myrpt->name);
  2766. ast_call(l->chan, tele, 999);
  2767. } else {
  2768. rpt_telemetry(myrpt, CONNFAIL, l);
  2769. ast_free(l);
  2770. ast_verb(3, "Unable to place call to %s/%s on %s\n",
  2771. deststr, tele, l->chan->name);
  2772. return DC_ERROR;
  2773. }
  2774. /* allocate a pseudo-channel thru asterisk */
  2775. l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  2776. if (!l->pchan) {
  2777. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
  2778. ast_hangup(l->chan);
  2779. ast_free(l);
  2780. return DC_ERROR;
  2781. }
  2782. ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
  2783. ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
  2784. /* make a conference for the tx */
  2785. ci.chan = 0;
  2786. ci.confno = myrpt->conf;
  2787. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
  2788. /* first put the channel on the conference in proper mode */
  2789. if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) {
  2790. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  2791. ast_hangup(l->chan);
  2792. ast_hangup(l->pchan);
  2793. ast_free(l);
  2794. return DC_ERROR;
  2795. }
  2796. rpt_mutex_lock(&myrpt->lock);
  2797. l->reconnects = reconnects;
  2798. /* insert at end of queue */
  2799. insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
  2800. rpt_mutex_unlock(&myrpt->lock);
  2801. rpt_telemetry(myrpt, COMPLETE, NULL);
  2802. return DC_COMPLETE;
  2803. case 4: /* Enter Command Mode */
  2804. /* if doesnt allow link cmd, or no links active, return */
  2805. if (((command_source != SOURCE_RPT) &&
  2806. (command_source != SOURCE_PHONE) &&
  2807. (command_source != SOURCE_DPHONE)) ||
  2808. (myrpt->links.next == &myrpt->links))
  2809. return DC_COMPLETE;
  2810. /* if already in cmd mode, or selected self, fughetabahtit */
  2811. if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))) {
  2812. rpt_telemetry(myrpt, REMALREADY, NULL);
  2813. return DC_COMPLETE;
  2814. }
  2815. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  2816. strcpy(digitbuf, myrpt->lastlinknode);
  2817. /* node must at least exist in list */
  2818. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
  2819. if (!val) {
  2820. if (strlen(digitbuf) >= myrpt->longestnode)
  2821. return DC_ERROR;
  2822. break;
  2823. }
  2824. rpt_mutex_lock(&myrpt->lock);
  2825. strcpy(myrpt->lastlinknode, digitbuf);
  2826. ast_copy_string(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode));
  2827. rpt_mutex_unlock(&myrpt->lock);
  2828. rpt_telemetry(myrpt, REMGO, NULL);
  2829. return DC_COMPLETE;
  2830. case 5: /* Status */
  2831. rpt_telemetry(myrpt, STATUS, NULL);
  2832. return DC_COMPLETE;
  2833. case 6: /* All Links Off */
  2834. l = myrpt->links.next;
  2835. while (l != &myrpt->links) { /* This code is broke and needs to be changed to work with the reconnect kludge */
  2836. if (l->chan)
  2837. ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
  2838. l = l->next;
  2839. }
  2840. rpt_telemetry(myrpt, COMPLETE, NULL);
  2841. break;
  2842. case 7: /* Identify last node which keyed us up */
  2843. rpt_telemetry(myrpt, LASTNODEKEY, NULL);
  2844. break;
  2845. default:
  2846. return DC_ERROR;
  2847. }
  2848. return DC_INDETERMINATE;
  2849. }
  2850. /*
  2851. * Autopatch up
  2852. */
  2853. static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  2854. {
  2855. int i, index;
  2856. char *value = NULL;
  2857. AST_DECLARE_APP_ARGS(params,
  2858. AST_APP_ARG(list)[20];
  2859. );
  2860. static char *keywords[] = {
  2861. "context",
  2862. "dialtime",
  2863. "farenddisconnect",
  2864. "noct",
  2865. "quiet",
  2866. NULL
  2867. };
  2868. if (!myrpt->enable)
  2869. return DC_ERROR;
  2870. ast_debug(1, "@@@@ Autopatch up\n");
  2871. if (!myrpt->callmode) {
  2872. /* Set defaults */
  2873. myrpt->patchnoct = 0;
  2874. myrpt->patchdialtime = 0;
  2875. myrpt->patchfarenddisconnect = 0;
  2876. myrpt->patchquiet = 0;
  2877. ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext));
  2878. if (param) {
  2879. /* Process parameter list */
  2880. char *tmp = ast_strdupa(param);
  2881. AST_STANDARD_APP_ARGS(params, tmp);
  2882. for (i = 0; i < params.argc; i++) {
  2883. index = matchkeyword(params.list[i], &value, keywords);
  2884. if (value)
  2885. value = skipchars(value, "= ");
  2886. switch (index) {
  2887. case 1: /* context */
  2888. ast_copy_string(myrpt->patchcontext, value, sizeof(myrpt->patchcontext)) ;
  2889. break;
  2890. case 2: /* dialtime */
  2891. myrpt->patchdialtime = atoi(value);
  2892. break;
  2893. case 3: /* farenddisconnect */
  2894. myrpt->patchfarenddisconnect = atoi(value);
  2895. break;
  2896. case 4: /* noct */
  2897. myrpt->patchnoct = atoi(value);
  2898. break;
  2899. case 5: /* quiet */
  2900. myrpt->patchquiet = atoi(value);
  2901. break;
  2902. default:
  2903. break;
  2904. }
  2905. }
  2906. }
  2907. }
  2908. rpt_mutex_lock(&myrpt->lock);
  2909. /* if on call, force * into current audio stream */
  2910. if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
  2911. myrpt->mydtmf = myrpt->p.funcchar;
  2912. }
  2913. if (myrpt->callmode) {
  2914. rpt_mutex_unlock(&myrpt->lock);
  2915. return DC_COMPLETE;
  2916. }
  2917. myrpt->callmode = 1;
  2918. myrpt->cidx = 0;
  2919. myrpt->exten[myrpt->cidx] = 0;
  2920. rpt_mutex_unlock(&myrpt->lock);
  2921. ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *) myrpt);
  2922. return DC_COMPLETE;
  2923. }
  2924. /*
  2925. * Autopatch down
  2926. */
  2927. static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  2928. {
  2929. if (!myrpt->enable)
  2930. return DC_ERROR;
  2931. ast_debug(1, "@@@@ Autopatch down\n");
  2932. rpt_mutex_lock(&myrpt->lock);
  2933. if (!myrpt->callmode) {
  2934. rpt_mutex_unlock(&myrpt->lock);
  2935. return DC_COMPLETE;
  2936. }
  2937. myrpt->callmode = 0;
  2938. rpt_mutex_unlock(&myrpt->lock);
  2939. rpt_telemetry(myrpt, TERM, NULL);
  2940. return DC_COMPLETE;
  2941. }
  2942. /*
  2943. * Status
  2944. */
  2945. static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  2946. {
  2947. if (!param)
  2948. return DC_ERROR;
  2949. if (!myrpt->enable)
  2950. return DC_ERROR;
  2951. ast_debug(1, "@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  2952. switch (myatoi(param)) {
  2953. case 1: /* System ID */
  2954. rpt_telemetry(myrpt, ID1, NULL);
  2955. return DC_COMPLETE;
  2956. case 2: /* System Time */
  2957. rpt_telemetry(myrpt, STATS_TIME, NULL);
  2958. return DC_COMPLETE;
  2959. case 3: /* app_rpt.c version */
  2960. rpt_telemetry(myrpt, STATS_VERSION, NULL);
  2961. default:
  2962. return DC_ERROR;
  2963. }
  2964. /* Never reached */
  2965. return DC_INDETERMINATE;
  2966. }
  2967. /*
  2968. * Macro-oni (without Salami)
  2969. */
  2970. static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  2971. {
  2972. const char *val;
  2973. int i;
  2974. struct ast_channel *mychannel;
  2975. if ((!myrpt->remote) && (!myrpt->enable))
  2976. return DC_ERROR;
  2977. ast_debug(1, "@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  2978. mychannel = myrpt->remchannel;
  2979. if (ast_strlen_zero(digitbuf)) /* needs 1 digit */
  2980. return DC_INDETERMINATE;
  2981. for (i = 0; i < digitbuf[i]; i++) {
  2982. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  2983. return DC_ERROR;
  2984. }
  2985. if (*digitbuf == '0')
  2986. val = myrpt->p.startupmacro;
  2987. else
  2988. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
  2989. /* param was 1 for local buf */
  2990. if (!val) {
  2991. rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
  2992. return DC_COMPLETE;
  2993. }
  2994. rpt_mutex_lock(&myrpt->lock);
  2995. if ((sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf)) < strlen(val)) {
  2996. rpt_mutex_unlock(&myrpt->lock);
  2997. rpt_telemetry(myrpt, MACRO_BUSY, NULL);
  2998. return DC_ERROR;
  2999. }
  3000. myrpt->macrotimer = MACROTIME;
  3001. strncat(myrpt->macrobuf, val, sizeof(myrpt->macrobuf) - strlen(myrpt->macrobuf) - 1);
  3002. rpt_mutex_unlock(&myrpt->lock);
  3003. return DC_COMPLETE;
  3004. }
  3005. /*
  3006. * Gosub
  3007. */
  3008. static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  3009. {
  3010. const char *val;
  3011. int i;
  3012. struct ast_channel *mychannel;
  3013. if ((!myrpt->remote) && (!myrpt->enable))
  3014. return DC_ERROR;
  3015. if (debug)
  3016. ast_log(LOG_DEBUG, "@@@@ gosub param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  3017. mychannel = myrpt->remchannel;
  3018. if (ast_strlen_zero(digitbuf)) /* needs 1 digit */
  3019. return DC_INDETERMINATE;
  3020. for (i = 0; i < digitbuf[i]; i++) {
  3021. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  3022. return DC_ERROR;
  3023. }
  3024. if (*digitbuf == '0')
  3025. val = myrpt->p.startupgosub;
  3026. else
  3027. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.gosub, digitbuf);
  3028. /* param was 1 for local buf */
  3029. if (!val) {
  3030. rpt_telemetry(myrpt, GOSUB_NOTFOUND, NULL);
  3031. return DC_COMPLETE;
  3032. }
  3033. rpt_mutex_lock(&myrpt->lock);
  3034. if ((sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf)) < strlen(val)) {
  3035. rpt_mutex_unlock(&myrpt->lock);
  3036. rpt_telemetry(myrpt, GOSUB_BUSY, NULL);
  3037. return DC_ERROR;
  3038. }
  3039. myrpt->gosubtimer = GOSUBTIME;
  3040. strncat(myrpt->gosubbuf, val, sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf) - 1);
  3041. rpt_mutex_unlock(&myrpt->lock);
  3042. return DC_COMPLETE;
  3043. }
  3044. /*
  3045. * COP - Control operator
  3046. */
  3047. static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  3048. {
  3049. if (!param)
  3050. return DC_ERROR;
  3051. switch(myatoi(param)) {
  3052. case 1: /* System reset */
  3053. ast_cli_command(STDERR_FILENO, "restart now"); /* A little less drastic than what was previously here. */
  3054. return DC_COMPLETE;
  3055. case 2:
  3056. myrpt->enable = 1;
  3057. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
  3058. return DC_COMPLETE;
  3059. case 3:
  3060. myrpt->enable = 0;
  3061. return DC_COMPLETE;
  3062. case 4: /* test tone on */
  3063. rpt_telemetry(myrpt, TEST_TONE, NULL);
  3064. return DC_COMPLETE;
  3065. case 5: /* Disgorge variables to log for debug purposes */
  3066. myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
  3067. return DC_COMPLETE;
  3068. case 6: /* Simulate COR being activated (phone only) */
  3069. if (command_source != SOURCE_PHONE)
  3070. return DC_INDETERMINATE;
  3071. return DC_DOKEY;
  3072. }
  3073. return DC_INDETERMINATE;
  3074. }
  3075. /*
  3076. * Collect digits one by one until something matches
  3077. */
  3078. static int collect_function_digits(struct rpt *myrpt, char *digits, int command_source, struct rpt_link *mylink)
  3079. {
  3080. int i;
  3081. char *stringp, *functiondigits;
  3082. char function_table_name[30] = "";
  3083. struct ast_variable *vp;
  3084. AST_DECLARE_APP_ARGS(args,
  3085. AST_APP_ARG(action);
  3086. AST_APP_ARG(param);
  3087. );
  3088. ast_debug(1, "@@@@ Digits collected: %s, source: %d\n", digits, command_source);
  3089. if (command_source == SOURCE_DPHONE) {
  3090. if (!myrpt->p.dphone_functions)
  3091. return DC_INDETERMINATE;
  3092. ast_copy_string(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name));
  3093. } else if (command_source == SOURCE_PHONE) {
  3094. if (!myrpt->p.phone_functions)
  3095. return DC_INDETERMINATE;
  3096. ast_copy_string(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name));
  3097. } else if (command_source == SOURCE_LNK)
  3098. ast_copy_string(function_table_name, myrpt->p.link_functions, sizeof(function_table_name));
  3099. else
  3100. ast_copy_string(function_table_name, myrpt->p.functions, sizeof(function_table_name));
  3101. for (vp = ast_variable_browse(myrpt->cfg, function_table_name); vp; vp = vp->next) {
  3102. if (!strncasecmp(vp->name, digits, strlen(vp->name)))
  3103. break;
  3104. }
  3105. if (!vp) {
  3106. int n;
  3107. n = myrpt->longestfunc;
  3108. if (command_source == SOURCE_LNK)
  3109. n = myrpt->link_longestfunc;
  3110. else if (command_source == SOURCE_PHONE)
  3111. n = myrpt->phone_longestfunc;
  3112. else if (command_source == SOURCE_DPHONE)
  3113. n = myrpt->dphone_longestfunc;
  3114. if (strlen(digits) >= n)
  3115. return DC_ERROR;
  3116. else
  3117. return DC_INDETERMINATE;
  3118. }
  3119. /* Found a match, retrieve value part and parse */
  3120. stringp = ast_strdupa(vp->value);
  3121. AST_STANDARD_APP_ARGS(args, stringp);
  3122. ast_debug(1, "@@@@ action: %s, param = %s\n", args.action, S_OR(args.param, "(null)"));
  3123. /* Look up the action */
  3124. for (i = 0; i < (sizeof(function_table) / sizeof(struct function_table_tag)); i++) {
  3125. if (!strncasecmp(args.action, function_table[i].action, strlen(args.action)))
  3126. break;
  3127. }
  3128. ast_debug(1, "@@@@ table index i = %d\n", i);
  3129. if (i == (sizeof(function_table) / sizeof(struct function_table_tag))) {
  3130. /* Error, action not in table */
  3131. return DC_ERROR;
  3132. }
  3133. if (function_table[i].function == NULL) {
  3134. /* Error, function undefined */
  3135. ast_debug(1, "@@@@ NULL for action: %s\n", args.action);
  3136. return DC_ERROR;
  3137. }
  3138. functiondigits = digits + strlen(vp->name);
  3139. return (*function_table[i].function)(myrpt, args.param, functiondigits, command_source, mylink);
  3140. }
  3141. static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink, char *str)
  3142. {
  3143. /* XXX ATTENTION: if you change the size of these arrays you MUST
  3144. * change the limits in corresponding sscanf() calls below. */
  3145. char cmd[300] = "", dest[300], src[300], c;
  3146. int seq, res;
  3147. struct rpt_link *l;
  3148. struct ast_frame wf;
  3149. wf.frametype = AST_FRAME_TEXT;
  3150. wf.subclass = 0;
  3151. wf.offset = 0;
  3152. wf.mallocd = 1;
  3153. wf.datalen = strlen(str) + 1;
  3154. wf.samples = 0;
  3155. if (!strcmp(str, discstr)) {
  3156. mylink->disced = 1;
  3157. mylink->retries = MAX_RETRIES + 1;
  3158. ast_softhangup(mylink->chan, AST_SOFTHANGUP_DEV);
  3159. return;
  3160. }
  3161. if (sscanf(str, "%299s %299s %299s %30d %1c", cmd, dest, src, &seq, &c) != 5) {
  3162. ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
  3163. return;
  3164. }
  3165. if (strcmp(cmd, "D")) {
  3166. ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
  3167. return;
  3168. }
  3169. if (dest[0] == '0') {
  3170. strcpy(dest, myrpt->name);
  3171. }
  3172. /* if not for me, redistribute to all links */
  3173. if (strcmp(dest, myrpt->name)) {
  3174. l = myrpt->links.next;
  3175. /* see if this is one in list */
  3176. while (l != &myrpt->links) {
  3177. if (l->name[0] == '0') {
  3178. l = l->next;
  3179. continue;
  3180. }
  3181. /* dont send back from where it came */
  3182. if ((l == mylink) || (!strcmp(l->name, mylink->name))) {
  3183. l = l->next;
  3184. continue;
  3185. }
  3186. /* if it is, send it and we're done */
  3187. if (!strcmp(l->name, dest)) {
  3188. /* send, but not to src */
  3189. if (strcmp(l->name, src)) {
  3190. wf.data = ast_strdup(str);
  3191. if (l->chan)
  3192. ast_write(l->chan, &wf);
  3193. }
  3194. return;
  3195. }
  3196. l = l->next;
  3197. }
  3198. l = myrpt->links.next;
  3199. /* otherwise, send it to all of em */
  3200. while (l != &myrpt->links) {
  3201. if (l->name[0] == '0') {
  3202. l = l->next;
  3203. continue;
  3204. }
  3205. /* dont send back from where it came */
  3206. if ((l == mylink) || (!strcmp(l->name, mylink->name))) {
  3207. l = l->next;
  3208. continue;
  3209. }
  3210. /* send, but not to src */
  3211. if (strcmp(l->name, src)) {
  3212. wf.data = ast_strdup(str);
  3213. if (l->chan)
  3214. ast_write(l->chan, &wf);
  3215. }
  3216. l = l->next;
  3217. }
  3218. return;
  3219. }
  3220. rpt_mutex_lock(&myrpt->lock);
  3221. if (c == myrpt->p.endchar)
  3222. myrpt->stopgen = 1;
  3223. if (myrpt->callmode == 1) {
  3224. myrpt->exten[myrpt->cidx++] = c;
  3225. myrpt->exten[myrpt->cidx] = 0;
  3226. /* if this exists */
  3227. if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  3228. myrpt->callmode = 2;
  3229. if (!myrpt->patchquiet) {
  3230. rpt_mutex_unlock(&myrpt->lock);
  3231. rpt_telemetry(myrpt, PROC, NULL);
  3232. rpt_mutex_lock(&myrpt->lock);
  3233. }
  3234. }
  3235. /* if can continue, do so */
  3236. if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  3237. /* call has failed, inform user */
  3238. myrpt->callmode = 4;
  3239. }
  3240. }
  3241. if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
  3242. myrpt->mydtmf = c;
  3243. }
  3244. if (c == myrpt->p.funcchar) {
  3245. myrpt->rem_dtmfidx = 0;
  3246. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  3247. time(&myrpt->rem_dtmf_time);
  3248. rpt_mutex_unlock(&myrpt->lock);
  3249. return;
  3250. } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) {
  3251. time(&myrpt->rem_dtmf_time);
  3252. if (myrpt->rem_dtmfidx < MAXDTMF) {
  3253. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
  3254. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  3255. rpt_mutex_unlock(&myrpt->lock);
  3256. ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd));
  3257. res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
  3258. rpt_mutex_lock(&myrpt->lock);
  3259. switch (res) {
  3260. case DC_INDETERMINATE:
  3261. break;
  3262. case DC_REQ_FLUSH:
  3263. myrpt->rem_dtmfidx = 0;
  3264. myrpt->rem_dtmfbuf[0] = 0;
  3265. break;
  3266. case DC_COMPLETE:
  3267. myrpt->totalexecdcommands++;
  3268. myrpt->dailyexecdcommands++;
  3269. ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
  3270. myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
  3271. myrpt->rem_dtmfbuf[0] = 0;
  3272. myrpt->rem_dtmfidx = -1;
  3273. myrpt->rem_dtmf_time = 0;
  3274. break;
  3275. case DC_ERROR:
  3276. default:
  3277. myrpt->rem_dtmfbuf[0] = 0;
  3278. myrpt->rem_dtmfidx = -1;
  3279. myrpt->rem_dtmf_time = 0;
  3280. break;
  3281. }
  3282. }
  3283. }
  3284. rpt_mutex_unlock(&myrpt->lock);
  3285. return;
  3286. }
  3287. static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink, char c)
  3288. {
  3289. char cmd[300];
  3290. int res;
  3291. rpt_mutex_lock(&myrpt->lock);
  3292. if (c == myrpt->p.endchar) {
  3293. if (mylink->lastrx) {
  3294. mylink->lastrx = 0;
  3295. rpt_mutex_unlock(&myrpt->lock);
  3296. return;
  3297. }
  3298. myrpt->stopgen = 1;
  3299. if (myrpt->cmdnode[0]) {
  3300. myrpt->cmdnode[0] = 0;
  3301. myrpt->dtmfidx = -1;
  3302. myrpt->dtmfbuf[0] = 0;
  3303. rpt_mutex_unlock(&myrpt->lock);
  3304. rpt_telemetry(myrpt, COMPLETE, NULL);
  3305. return;
  3306. }
  3307. }
  3308. if (myrpt->cmdnode[0]) {
  3309. rpt_mutex_unlock(&myrpt->lock);
  3310. send_link_dtmf(myrpt, c);
  3311. return;
  3312. }
  3313. if (myrpt->callmode == 1) {
  3314. myrpt->exten[myrpt->cidx++] = c;
  3315. myrpt->exten[myrpt->cidx] = 0;
  3316. /* if this exists */
  3317. if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  3318. myrpt->callmode = 2;
  3319. if (!myrpt->patchquiet) {
  3320. rpt_mutex_unlock(&myrpt->lock);
  3321. rpt_telemetry(myrpt, PROC, NULL);
  3322. rpt_mutex_lock(&myrpt->lock);
  3323. }
  3324. }
  3325. /* if can continue, do so */
  3326. if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  3327. /* call has failed, inform user */
  3328. myrpt->callmode = 4;
  3329. }
  3330. }
  3331. if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
  3332. myrpt->mydtmf = c;
  3333. }
  3334. if (c == myrpt->p.funcchar) {
  3335. myrpt->rem_dtmfidx = 0;
  3336. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  3337. time(&myrpt->rem_dtmf_time);
  3338. rpt_mutex_unlock(&myrpt->lock);
  3339. return;
  3340. } else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0)) {
  3341. time(&myrpt->rem_dtmf_time);
  3342. if (myrpt->rem_dtmfidx < MAXDTMF) {
  3343. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
  3344. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  3345. rpt_mutex_unlock(&myrpt->lock);
  3346. ast_copy_string(cmd, myrpt->rem_dtmfbuf, sizeof(cmd));
  3347. switch(mylink->phonemode) {
  3348. case 1:
  3349. res = collect_function_digits(myrpt, cmd,
  3350. SOURCE_PHONE, mylink);
  3351. break;
  3352. case 2:
  3353. res = collect_function_digits(myrpt, cmd,
  3354. SOURCE_DPHONE, mylink);
  3355. break;
  3356. default:
  3357. res = collect_function_digits(myrpt, cmd,
  3358. SOURCE_LNK, mylink);
  3359. break;
  3360. }
  3361. rpt_mutex_lock(&myrpt->lock);
  3362. switch(res) {
  3363. case DC_INDETERMINATE:
  3364. break;
  3365. case DC_DOKEY:
  3366. mylink->lastrx = 1;
  3367. break;
  3368. case DC_REQ_FLUSH:
  3369. myrpt->rem_dtmfidx = 0;
  3370. myrpt->rem_dtmfbuf[0] = 0;
  3371. break;
  3372. case DC_COMPLETE:
  3373. myrpt->totalexecdcommands++;
  3374. myrpt->dailyexecdcommands++;
  3375. ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
  3376. myrpt->rem_dtmfbuf[0] = 0;
  3377. myrpt->rem_dtmfidx = -1;
  3378. myrpt->rem_dtmf_time = 0;
  3379. break;
  3380. case DC_ERROR:
  3381. default:
  3382. myrpt->rem_dtmfbuf[0] = 0;
  3383. myrpt->rem_dtmfidx = -1;
  3384. myrpt->rem_dtmf_time = 0;
  3385. break;
  3386. }
  3387. }
  3388. }
  3389. rpt_mutex_unlock(&myrpt->lock);
  3390. return;
  3391. }
  3392. /* Doug Hall RBI-1 serial data definitions:
  3393. *
  3394. * Byte 0: Expansion external outputs
  3395. * Byte 1:
  3396. * Bits 0-3 are BAND as follows:
  3397. * Bits 4-5 are POWER bits as follows:
  3398. * 00 - Low Power
  3399. * 01 - Hi Power
  3400. * 02 - Med Power
  3401. * Bits 6-7 are always set
  3402. * Byte 2:
  3403. * Bits 0-3 MHZ in BCD format
  3404. * Bits 4-5 are offset as follows:
  3405. * 00 - minus
  3406. * 01 - plus
  3407. * 02 - simplex
  3408. * 03 - minus minus (whatever that is)
  3409. * Bit 6 is the 0/5 KHZ bit
  3410. * Bit 7 is always set
  3411. * Byte 3:
  3412. * Bits 0-3 are 10 KHZ in BCD format
  3413. * Bits 4-7 are 100 KHZ in BCD format
  3414. * Byte 4: PL Tone code and encode/decode enable bits
  3415. * Bits 0-5 are PL tone code (comspec binary codes)
  3416. * Bit 6 is encode enable/disable
  3417. * Bit 7 is decode enable/disable
  3418. */
  3419. /* take the frequency from the 10 mhz digits (and up) and convert it
  3420. to a band number */
  3421. static int rbi_mhztoband(char *str)
  3422. {
  3423. int i;
  3424. i = atoi(str) / 10; /* get the 10's of mhz */
  3425. switch (i) {
  3426. case 2:
  3427. return 10;
  3428. case 5:
  3429. return 11;
  3430. case 14:
  3431. return 2;
  3432. case 22:
  3433. return 3;
  3434. case 44:
  3435. return 4;
  3436. case 124:
  3437. return 0;
  3438. case 125:
  3439. return 1;
  3440. case 126:
  3441. return 8;
  3442. case 127:
  3443. return 5;
  3444. case 128:
  3445. return 6;
  3446. case 129:
  3447. return 7;
  3448. default:
  3449. break;
  3450. }
  3451. return -1;
  3452. }
  3453. /* take a PL frequency and turn it into a code */
  3454. static int rbi_pltocode(char *str)
  3455. {
  3456. int i;
  3457. char *s;
  3458. s = strchr(str, '.');
  3459. i = 0;
  3460. if (s)
  3461. i = atoi(s + 1);
  3462. i += atoi(str) * 10;
  3463. switch(i) {
  3464. case 670:
  3465. return 0;
  3466. case 719:
  3467. return 1;
  3468. case 744:
  3469. return 2;
  3470. case 770:
  3471. return 3;
  3472. case 797:
  3473. return 4;
  3474. case 825:
  3475. return 5;
  3476. case 854:
  3477. return 6;
  3478. case 885:
  3479. return 7;
  3480. case 915:
  3481. return 8;
  3482. case 948:
  3483. return 9;
  3484. case 974:
  3485. return 10;
  3486. case 1000:
  3487. return 11;
  3488. case 1035:
  3489. return 12;
  3490. case 1072:
  3491. return 13;
  3492. case 1109:
  3493. return 14;
  3494. case 1148:
  3495. return 15;
  3496. case 1188:
  3497. return 16;
  3498. case 1230:
  3499. return 17;
  3500. case 1273:
  3501. return 18;
  3502. case 1318:
  3503. return 19;
  3504. case 1365:
  3505. return 20;
  3506. case 1413:
  3507. return 21;
  3508. case 1462:
  3509. return 22;
  3510. case 1514:
  3511. return 23;
  3512. case 1567:
  3513. return 24;
  3514. case 1622:
  3515. return 25;
  3516. case 1679:
  3517. return 26;
  3518. case 1738:
  3519. return 27;
  3520. case 1799:
  3521. return 28;
  3522. case 1862:
  3523. return 29;
  3524. case 1928:
  3525. return 30;
  3526. case 2035:
  3527. return 31;
  3528. case 2107:
  3529. return 32;
  3530. case 2181:
  3531. return 33;
  3532. case 2257:
  3533. return 34;
  3534. case 2336:
  3535. return 35;
  3536. case 2418:
  3537. return 36;
  3538. case 2503:
  3539. return 37;
  3540. }
  3541. return -1;
  3542. }
  3543. /*
  3544. * Shift out a formatted serial bit stream
  3545. */
  3546. static void rbi_out_parallel(struct rpt *myrpt, unsigned char *data)
  3547. {
  3548. int i, j;
  3549. unsigned char od, d;
  3550. for (i = 0; i < 5; i++) {
  3551. od = *data++;
  3552. for (j = 0; j < 8; j++) {
  3553. d = od & 1;
  3554. outb(d, myrpt->p.iobase);
  3555. usleep(15);
  3556. od >>= 1;
  3557. outb(d | 2, myrpt->p.iobase);
  3558. usleep(30);
  3559. outb(d, myrpt->p.iobase);
  3560. usleep(10);
  3561. }
  3562. }
  3563. /* >= 50 us */
  3564. usleep(50);
  3565. }
  3566. static void rbi_out(struct rpt *myrpt, unsigned char *data)
  3567. {
  3568. struct dahdi_radio_param r = { 0, };
  3569. r.radpar = DAHDI_RADPAR_REMMODE;
  3570. r.data = DAHDI_RADPAR_REM_RBI1;
  3571. /* if setparam ioctl fails, its probably not a pciradio card */
  3572. if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &r) == -1) {
  3573. rbi_out_parallel(myrpt, data);
  3574. return;
  3575. }
  3576. r.radpar = DAHDI_RADPAR_REMCOMMAND;
  3577. memcpy(&r.data, data, 5);
  3578. if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &r) == -1) {
  3579. ast_log(LOG_WARNING, "Cannot send RBI command for channel %s\n", myrpt->rxchannel->name);
  3580. return;
  3581. }
  3582. }
  3583. static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes, char *rxbuf, int rxmaxbytes, int asciiflag)
  3584. {
  3585. int i;
  3586. struct dahdi_radio_param prm;
  3587. char *buf = alloca(30 + txbytes * 3);
  3588. int len;
  3589. ast_copy_string(buf, "String output was: ", 30 + txbytes * 3);
  3590. len = strlen(buf);
  3591. for (i = 0; i < txbytes; i++)
  3592. len += snprintf(buf + len, 30 + txbytes * 3 - len, "%02X ", (unsigned char) txbuf[i]);
  3593. strcat(buf + len, "\n");
  3594. ast_debug(1, "%s", buf);
  3595. prm.radpar = DAHDI_RADPAR_REMMODE;
  3596. if (asciiflag)
  3597. prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
  3598. else
  3599. prm.data = DAHDI_RADPAR_REM_SERIAL;
  3600. if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &prm) == -1)
  3601. return -1;
  3602. prm.radpar = DAHDI_RADPAR_REMCOMMAND;
  3603. prm.data = rxmaxbytes;
  3604. memcpy(prm.buf, txbuf, txbytes);
  3605. prm.index = txbytes;
  3606. if (ioctl(myrpt->rxchannel->fds[0], DAHDI_RADIO_SETPARAM, &prm) == -1)
  3607. return -1;
  3608. if (rxbuf) {
  3609. *rxbuf = 0;
  3610. memcpy(rxbuf, prm.buf, prm.index);
  3611. }
  3612. return(prm.index);
  3613. }
  3614. static int setrbi(struct rpt *myrpt)
  3615. {
  3616. char tmp[MAXREMSTR] = "", *s;
  3617. unsigned char rbicmd[5];
  3618. int band, txoffset = 0, txpower = 0, txpl;
  3619. /* must be a remote system */
  3620. if (!myrpt->remote)
  3621. return(0);
  3622. /* must have rbi hardware */
  3623. if (strncmp(myrpt->remote, remote_rig_rbi, 3))
  3624. return(0);
  3625. ast_copy_string(tmp, myrpt->freq, sizeof(tmp));
  3626. s = strchr(tmp, '.');
  3627. /* if no decimal, is invalid */
  3628. if (s == NULL) {
  3629. ast_debug(1, "@@@@ Frequency needs a decimal\n");
  3630. return -1;
  3631. }
  3632. *s++ = 0;
  3633. if (strlen(tmp) < 2) {
  3634. ast_debug(1, "@@@@ Bad MHz digits: %s\n", tmp);
  3635. return -1;
  3636. }
  3637. if (strlen(s) < 3) {
  3638. ast_debug(1, "@@@@ Bad KHz digits: %s\n", s);
  3639. return -1;
  3640. }
  3641. if ((s[2] != '0') && (s[2] != '5')) {
  3642. ast_debug(1, "@@@@ KHz must end in 0 or 5: %c\n", s[2]);
  3643. return -1;
  3644. }
  3645. band = rbi_mhztoband(tmp);
  3646. if (band == -1) {
  3647. ast_debug(1, "@@@@ Bad Band: %s\n", tmp);
  3648. return -1;
  3649. }
  3650. txpl = rbi_pltocode(myrpt->txpl);
  3651. if (txpl == -1) {
  3652. ast_debug(1, "@@@@ Bad TX PL: %s\n", myrpt->txpl);
  3653. return -1;
  3654. }
  3655. switch (myrpt->offset) {
  3656. case REM_MINUS:
  3657. txoffset = 0;
  3658. break;
  3659. case REM_PLUS:
  3660. txoffset = 0x10;
  3661. break;
  3662. case REM_SIMPLEX:
  3663. txoffset = 0x20;
  3664. break;
  3665. }
  3666. switch(myrpt->powerlevel) {
  3667. case REM_LOWPWR:
  3668. txpower = 0;
  3669. break;
  3670. case REM_MEDPWR:
  3671. txpower = 0x20;
  3672. break;
  3673. case REM_HIPWR:
  3674. txpower = 0x10;
  3675. break;
  3676. }
  3677. rbicmd[0] = 0;
  3678. rbicmd[1] = band | txpower | 0xc0;
  3679. rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
  3680. if (s[2] == '5')
  3681. rbicmd[2] |= 0x40;
  3682. rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
  3683. rbicmd[4] = txpl;
  3684. if (myrpt->txplon)
  3685. rbicmd[4] |= 0x40;
  3686. if (myrpt->rxplon)
  3687. rbicmd[4] |= 0x80;
  3688. rbi_out(myrpt, rbicmd);
  3689. return 0;
  3690. }
  3691. /* Check for valid rbi frequency */
  3692. /* Hard coded limits now, configurable later, maybe? */
  3693. static int check_freq_rbi(int m, int d, int *defmode)
  3694. {
  3695. int dflmd = REM_MODE_FM;
  3696. if (m == 50) { /* 6 meters */
  3697. if (d < 10100)
  3698. return -1;
  3699. } else if ((m >= 51) && ( m < 54)) {
  3700. /* nada */
  3701. } else if (m == 144) { /* 2 meters */
  3702. if (d < 10100)
  3703. return -1;
  3704. } else if ((m >= 145) && (m < 148)) {
  3705. /* nada */
  3706. } else if ((m >= 222) && (m < 225)) { /* 1.25 meters */
  3707. /* nada */
  3708. } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
  3709. /* nada */
  3710. } else if ((m >= 1240) && (m < 1300)) { /* 23 centimeters */
  3711. /* nada */
  3712. } else
  3713. return -1;
  3714. if (defmode)
  3715. *defmode = dflmd;
  3716. return 0;
  3717. }
  3718. static int split_decimal(char *input, int *ints, int *decs, int places)
  3719. {
  3720. double input2 = 0.0;
  3721. long long modifier = (long long)pow(10.0, (double)places);
  3722. if (sscanf(input, "%30lf", &input2) == 1) {
  3723. long long input3 = input2 * modifier;
  3724. *ints = input3 / modifier;
  3725. *decs = input3 % modifier;
  3726. return 0;
  3727. } else
  3728. return -1;
  3729. }
  3730. /*
  3731. * Split frequency into mhz and decimals
  3732. */
  3733. #define split_freq(mhz, decimal, freq) split_decimal(freq, mhz, decimal, 5)
  3734. /*
  3735. * Split ctcss frequency into hertz and decimal
  3736. */
  3737. #define split_ctcss_freq(hertz, decimal, freq) split_decimal(freq, hertz, decimal, 1)
  3738. /*
  3739. * FT-897 I/O handlers
  3740. */
  3741. /* Check to see that the frequency is valid */
  3742. /* Hard coded limits now, configurable later, maybe? */
  3743. static int check_freq_ft897(int m, int d, int *defmode)
  3744. {
  3745. int dflmd = REM_MODE_FM;
  3746. if (m == 1) { /* 160 meters */
  3747. dflmd = REM_MODE_LSB;
  3748. if (d < 80001)
  3749. return -1;
  3750. } else if (m == 3) { /* 80 meters */
  3751. dflmd = REM_MODE_LSB;
  3752. if (d < 75001)
  3753. return -1;
  3754. } else if (m == 7) { /* 40 meters */
  3755. dflmd = REM_MODE_LSB;
  3756. if ((d < 15001) || (d > 29999))
  3757. return -1;
  3758. } else if (m == 14) { /* 20 meters */
  3759. dflmd = REM_MODE_USB;
  3760. if ((d < 15001) || (d > 34999))
  3761. return -1;
  3762. } else if (m == 18) { /* 17 meters */
  3763. dflmd = REM_MODE_USB;
  3764. if ((d < 11001) || (d > 16797))
  3765. return -1;
  3766. } else if (m == 21) { /* 15 meters */
  3767. dflmd = REM_MODE_USB;
  3768. if ((d < 20001) || (d > 44999))
  3769. return -1;
  3770. } else if (m == 24) { /* 12 meters */
  3771. dflmd = REM_MODE_USB;
  3772. if ((d < 93001) || (d > 98999))
  3773. return -1;
  3774. } else if (m == 28) { /* 10 meters */
  3775. dflmd = REM_MODE_USB;
  3776. if (d < 30001)
  3777. return -1;
  3778. } else if (m == 29) {
  3779. if (d >= 51000)
  3780. dflmd = REM_MODE_FM;
  3781. else
  3782. dflmd = REM_MODE_USB;
  3783. if (d > 69999)
  3784. return -1;
  3785. } else if (m == 50) { /* 6 meters */
  3786. if (d < 10100)
  3787. return -1;
  3788. if (d >= 30000)
  3789. dflmd = REM_MODE_FM;
  3790. else
  3791. dflmd = REM_MODE_USB;
  3792. } else if ((m >= 51) && ( m < 54)) {
  3793. dflmd = REM_MODE_FM;
  3794. } else if (m == 144) { /* 2 meters */
  3795. if (d < 10100)
  3796. return -1;
  3797. if (d >= 30000)
  3798. dflmd = REM_MODE_FM;
  3799. else
  3800. dflmd = REM_MODE_USB;
  3801. } else if ((m >= 145) && (m < 148)) {
  3802. dflmd = REM_MODE_FM;
  3803. } else if ((m >= 430) && (m < 450)) { /* 70 centimeters */
  3804. if (m < 438)
  3805. dflmd = REM_MODE_USB;
  3806. else
  3807. dflmd = REM_MODE_FM;
  3808. ;
  3809. } else
  3810. return -1;
  3811. if (defmode)
  3812. *defmode = dflmd;
  3813. return 0;
  3814. }
  3815. /*
  3816. * Set a new frequency for the FT897
  3817. */
  3818. static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
  3819. {
  3820. unsigned char cmdstr[5];
  3821. int fd, m, d;
  3822. fd = 0;
  3823. ast_debug(1, "New frequency: %s\n", newfreq);
  3824. if (split_freq(&m, &d, newfreq))
  3825. return -1;
  3826. /* The FT-897 likes packed BCD frequencies */
  3827. cmdstr[0] = ((m / 100) << 4) + ((m % 100) / 10); /* 100MHz 10Mhz */
  3828. cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */
  3829. cmdstr[2] = (((d % 10000) / 1000) << 4) + ((d % 1000) / 100); /* 10KHz 1KHz */
  3830. cmdstr[3] = (((d % 100) / 10) << 4) + (d % 10); /* 100Hz 10Hz */
  3831. cmdstr[4] = 0x01; /* command */
  3832. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3833. }
  3834. /* ft-897 simple commands */
  3835. static int simple_command_ft897(struct rpt *myrpt, char command)
  3836. {
  3837. unsigned char cmdstr[5] = { 0, 0, 0, 0, command };
  3838. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3839. }
  3840. /* ft-897 offset */
  3841. static int set_offset_ft897(struct rpt *myrpt, char offset)
  3842. {
  3843. unsigned char cmdstr[5] = "";
  3844. switch (offset) {
  3845. case REM_SIMPLEX:
  3846. cmdstr[0] = 0x89;
  3847. break;
  3848. case REM_MINUS:
  3849. cmdstr[0] = 0x09;
  3850. break;
  3851. case REM_PLUS:
  3852. cmdstr[0] = 0x49;
  3853. break;
  3854. default:
  3855. return -1;
  3856. }
  3857. cmdstr[4] = 0x09;
  3858. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3859. }
  3860. /* ft-897 mode */
  3861. static int set_mode_ft897(struct rpt *myrpt, char newmode)
  3862. {
  3863. unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x07 };
  3864. switch (newmode) {
  3865. case REM_MODE_FM:
  3866. cmdstr[0] = 0x08;
  3867. break;
  3868. case REM_MODE_USB:
  3869. cmdstr[0] = 0x01;
  3870. break;
  3871. case REM_MODE_LSB:
  3872. cmdstr[0] = 0x00;
  3873. break;
  3874. case REM_MODE_AM:
  3875. cmdstr[0] = 0x04;
  3876. break;
  3877. default:
  3878. return -1;
  3879. }
  3880. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3881. }
  3882. /* Set tone encode and decode modes */
  3883. static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
  3884. {
  3885. unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0A };
  3886. if (rxplon && txplon)
  3887. cmdstr[0] = 0x2A; /* Encode and Decode */
  3888. else if (!rxplon && txplon)
  3889. cmdstr[0] = 0x4A; /* Encode only */
  3890. else if (rxplon && !txplon)
  3891. cmdstr[0] = 0x3A; /* Encode only */
  3892. else
  3893. cmdstr[0] = 0x8A; /* OFF */
  3894. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3895. }
  3896. /* Set transmit and receive ctcss tone frequencies */
  3897. static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
  3898. {
  3899. unsigned char cmdstr[5] = { 0, 0, 0, 0, 0x0B };
  3900. int hertz, decimal;
  3901. if (split_ctcss_freq(&hertz, &decimal, txtone))
  3902. return -1;
  3903. cmdstr[0] = ((hertz / 100) << 4) + (hertz % 100) / 10;
  3904. cmdstr[1] = ((hertz % 10) << 4) + (decimal % 10);
  3905. if (rxtone) {
  3906. if (split_ctcss_freq(&hertz, &decimal, rxtone))
  3907. return -1;
  3908. cmdstr[2] = ((hertz / 100) << 4) + (hertz % 100)/ 10;
  3909. cmdstr[3] = ((hertz % 10) << 4) + (decimal % 10);
  3910. }
  3911. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  3912. }
  3913. static int set_ft897(struct rpt *myrpt)
  3914. {
  3915. int res;
  3916. ast_debug(1, "@@@@ lock on\n");
  3917. res = simple_command_ft897(myrpt, 0x00); /* LOCK on */
  3918. ast_debug(1, "@@@@ ptt off\n");
  3919. if (!res)
  3920. res = simple_command_ft897(myrpt, 0x88); /* PTT off */
  3921. ast_debug(1, "Modulation mode\n");
  3922. if (!res)
  3923. res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */
  3924. ast_debug(1, "Split off\n");
  3925. if (!res)
  3926. simple_command_ft897(myrpt, 0x82); /* Split off */
  3927. ast_debug(1, "Frequency\n");
  3928. if (!res)
  3929. res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */
  3930. if ((myrpt->remmode == REM_MODE_FM)) {
  3931. ast_debug(1, "Offset\n");
  3932. if (!res)
  3933. res = set_offset_ft897(myrpt, myrpt->offset); /* Offset if FM */
  3934. if ((!res)&&(myrpt->rxplon || myrpt->txplon)) {
  3935. ast_debug(1, "CTCSS tone freqs.\n");
  3936. res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
  3937. }
  3938. if (!res) {
  3939. ast_debug(1, "CTCSS mode\n");
  3940. res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
  3941. }
  3942. }
  3943. if ((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)) {
  3944. ast_debug(1, "Clarifier off\n");
  3945. simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */
  3946. }
  3947. return res;
  3948. }
  3949. static int closerem_ft897(struct rpt *myrpt)
  3950. {
  3951. simple_command_ft897(myrpt, 0x88); /* PTT off */
  3952. return 0;
  3953. }
  3954. /*
  3955. * Bump frequency up or down by a small amount
  3956. * Return 0 if the new frequnecy is valid, or -1 if invalid
  3957. * Interval is in Hz, resolution is 10Hz
  3958. */
  3959. static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
  3960. {
  3961. int m, d;
  3962. ast_debug(1, "Before bump: %s\n", myrpt->freq);
  3963. if (split_freq(&m, &d, myrpt->freq))
  3964. return -1;
  3965. d += (interval / 10); /* 10Hz resolution */
  3966. if (d < 0) {
  3967. m--;
  3968. d += 100000;
  3969. } else if (d >= 100000) {
  3970. m++;
  3971. d -= 100000;
  3972. }
  3973. if (check_freq_ft897(m, d, NULL)) {
  3974. ast_debug(1, "Bump freq invalid\n");
  3975. return -1;
  3976. }
  3977. snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
  3978. ast_debug(1, "After bump: %s\n", myrpt->freq);
  3979. return set_freq_ft897(myrpt, myrpt->freq);
  3980. }
  3981. /*
  3982. * Dispatch to correct I/O handler
  3983. */
  3984. static int setrem(struct rpt *myrpt)
  3985. {
  3986. return 0; /* XXX BROKEN!! */
  3987. if (!strcmp(myrpt->remote, remote_rig_ft897))
  3988. return set_ft897(myrpt);
  3989. else if (!strcmp(myrpt->remote, remote_rig_rbi))
  3990. return setrbi(myrpt);
  3991. else
  3992. return -1;
  3993. }
  3994. static int closerem(struct rpt *myrpt)
  3995. {
  3996. return 0; /* XXX BROKEN!! */
  3997. if (!strcmp(myrpt->remote, remote_rig_ft897))
  3998. return closerem_ft897(myrpt);
  3999. else
  4000. return 0;
  4001. }
  4002. /*
  4003. * Dispatch to correct frequency checker
  4004. */
  4005. static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
  4006. {
  4007. if (!strcmp(myrpt->remote, remote_rig_ft897))
  4008. return check_freq_ft897(m, d, defmode);
  4009. else if (!strcmp(myrpt->remote, remote_rig_rbi))
  4010. return check_freq_rbi(m, d, defmode);
  4011. else
  4012. return -1;
  4013. }
  4014. /*
  4015. * Return 1 if rig is multimode capable
  4016. */
  4017. static int multimode_capable(struct rpt *myrpt)
  4018. {
  4019. if (!strcmp(myrpt->remote, remote_rig_ft897))
  4020. return 1;
  4021. return 0;
  4022. }
  4023. /*
  4024. * Dispatch to correct frequency bumping function
  4025. */
  4026. static int multimode_bump_freq(struct rpt *myrpt, int interval)
  4027. {
  4028. if (!strcmp(myrpt->remote, remote_rig_ft897))
  4029. return multimode_bump_freq_ft897(myrpt, interval);
  4030. else
  4031. return -1;
  4032. }
  4033. /*
  4034. * Queue announcment that scan has been stopped
  4035. */
  4036. static void stop_scan(struct rpt *myrpt, int flag)
  4037. {
  4038. myrpt->hfscanmode = 0;
  4039. myrpt->hfscanstatus = ((flag) ? -2 : -1);
  4040. }
  4041. /*
  4042. * This is called periodically when in scan mode
  4043. */
  4044. static int service_scan(struct rpt *myrpt)
  4045. {
  4046. int res, interval, mhz, decimals;
  4047. char k10=0, k100=0;
  4048. switch (myrpt->hfscanmode) {
  4049. case HF_SCAN_DOWN_SLOW:
  4050. interval = -10; /* 100Hz /sec */
  4051. break;
  4052. case HF_SCAN_DOWN_QUICK:
  4053. interval = -50; /* 500Hz /sec */
  4054. break;
  4055. case HF_SCAN_DOWN_FAST:
  4056. interval = -200; /* 2KHz /sec */
  4057. break;
  4058. case HF_SCAN_UP_SLOW:
  4059. interval = 10; /* 100Hz /sec */
  4060. break;
  4061. case HF_SCAN_UP_QUICK:
  4062. interval = 50; /* 500 Hz/sec */
  4063. break;
  4064. case HF_SCAN_UP_FAST:
  4065. interval = 200; /* 2KHz /sec */
  4066. break;
  4067. default:
  4068. myrpt->hfscanmode = 0; /* Huh? */
  4069. return -1;
  4070. }
  4071. res = split_freq(&mhz, &decimals, myrpt->freq);
  4072. if (!res) {
  4073. k100 = decimals / 10000;
  4074. k10 = (decimals / 1000) % 10;
  4075. res = multimode_bump_freq(myrpt, interval);
  4076. }
  4077. if (!res)
  4078. res = split_freq(&mhz, &decimals, myrpt->freq);
  4079. if (res) {
  4080. stop_scan(myrpt, 1);
  4081. return -1;
  4082. }
  4083. /* Announce 10KHz boundaries */
  4084. if (k10 != (decimals / 1000) % 10) {
  4085. int myhund = (interval < 0) ? k100 : decimals / 10000;
  4086. int myten = (interval < 0) ? k10 : (decimals / 1000) % 10;
  4087. myrpt->hfscanstatus = (myten == 0) ? (myhund) * 100 : (myten) * 10;
  4088. }
  4089. return res;
  4090. }
  4091. static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
  4092. {
  4093. myrpt->remotetx = 0;
  4094. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  4095. if (!myrpt->remoterx)
  4096. ast_indicate(chan, AST_CONTROL_RADIO_KEY);
  4097. if (ast_safe_sleep(chan, delay) == -1)
  4098. return -1;
  4099. return 0;
  4100. }
  4101. static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
  4102. {
  4103. struct dahdi_params par;
  4104. if (ioctl(myrpt->txchannel->fds[0], DAHDI_GET_PARAMS, &par) == -1) {
  4105. return -1;
  4106. }
  4107. if (!par.rxisoffhook) {
  4108. ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_UNKEY);
  4109. myrpt->remoterx = 0;
  4110. } else {
  4111. myrpt->remoterx = 1;
  4112. }
  4113. return 0;
  4114. }
  4115. static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
  4116. {
  4117. int res;
  4118. res = rmt_telem_start(myrpt, chan, delay);
  4119. if (!res)
  4120. res = sayfile(chan, filename);
  4121. if (!res)
  4122. res = rmt_telem_finish(myrpt, chan);
  4123. return res;
  4124. }
  4125. static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
  4126. {
  4127. int res;
  4128. res = rmt_telem_start(myrpt, chan, delay);
  4129. if (!res)
  4130. res = saycharstr(chan, charstr);
  4131. if (!res)
  4132. res = rmt_telem_finish(myrpt, chan);
  4133. return res;
  4134. }
  4135. /*
  4136. * Remote base function
  4137. */
  4138. static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  4139. {
  4140. char *s, *modestr;
  4141. const char *val;
  4142. int i, j, ht, k, l, ls2, res, offset, offsave, modesave, defmode = 0;
  4143. char multimode = 0;
  4144. char oc;
  4145. char tmp[20], freq[20] = "", savestr[20] = "";
  4146. int mhz = 0, decimals = 0;
  4147. struct ast_channel *mychannel;
  4148. AST_DECLARE_APP_ARGS(args1,
  4149. AST_APP_ARG(freq);
  4150. AST_APP_ARG(xpl);
  4151. AST_APP_ARG(mode);
  4152. );
  4153. AST_DECLARE_APP_ARGS(args,
  4154. AST_APP_ARG(s1);
  4155. AST_APP_ARG(s2);
  4156. );
  4157. if ((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
  4158. return DC_ERROR;
  4159. multimode = multimode_capable(myrpt);
  4160. mychannel = myrpt->remchannel;
  4161. switch (myatoi(param)) {
  4162. case 1: /* retrieve memory */
  4163. if (strlen(digitbuf) < 2) /* needs 2 digits */
  4164. break;
  4165. for (i = 0 ; i < 2 ; i++) {
  4166. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  4167. return DC_ERROR;
  4168. }
  4169. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, digitbuf);
  4170. if (!val) {
  4171. if (ast_safe_sleep(mychannel, 1000) == -1)
  4172. return DC_ERROR;
  4173. sayfile(mychannel, "rpt/memory_notfound");
  4174. return DC_COMPLETE;
  4175. }
  4176. s = ast_strdupa(val);
  4177. AST_STANDARD_APP_ARGS(args1, s);
  4178. if (args1.argc < 3)
  4179. return DC_ERROR;
  4180. ast_copy_string(myrpt->freq, args1.freq, sizeof(myrpt->freq));
  4181. ast_copy_string(myrpt->rxpl, args1.xpl, sizeof(myrpt->rxpl));
  4182. ast_copy_string(myrpt->txpl, args1.xpl, sizeof(myrpt->rxpl));
  4183. myrpt->remmode = REM_MODE_FM;
  4184. myrpt->offset = REM_SIMPLEX;
  4185. myrpt->powerlevel = REM_MEDPWR;
  4186. myrpt->txplon = myrpt->rxplon = 0;
  4187. modestr = args1.mode;
  4188. while (*modestr) {
  4189. switch (*modestr++) {
  4190. case 'A':
  4191. case 'a':
  4192. strcpy(myrpt->rxpl, "100.0");
  4193. strcpy(myrpt->txpl, "100.0");
  4194. myrpt->remmode = REM_MODE_AM;
  4195. break;
  4196. case 'B':
  4197. case 'b':
  4198. strcpy(myrpt->rxpl, "100.0");
  4199. strcpy(myrpt->txpl, "100.0");
  4200. myrpt->remmode = REM_MODE_LSB;
  4201. break;
  4202. case 'F':
  4203. myrpt->remmode = REM_MODE_FM;
  4204. break;
  4205. case 'L':
  4206. case 'l':
  4207. myrpt->powerlevel = REM_LOWPWR;
  4208. break;
  4209. case 'H':
  4210. case 'h':
  4211. myrpt->powerlevel = REM_HIPWR;
  4212. break;
  4213. case 'M':
  4214. case 'm':
  4215. myrpt->powerlevel = REM_MEDPWR;
  4216. break;
  4217. case '-':
  4218. myrpt->offset = REM_MINUS;
  4219. break;
  4220. case '+':
  4221. myrpt->offset = REM_PLUS;
  4222. break;
  4223. case 'S':
  4224. case 's':
  4225. myrpt->offset = REM_SIMPLEX;
  4226. break;
  4227. case 'T':
  4228. case 't':
  4229. myrpt->txplon = 1;
  4230. break;
  4231. case 'R':
  4232. case 'r':
  4233. myrpt->rxplon = 1;
  4234. break;
  4235. case 'U':
  4236. case 'u':
  4237. strcpy(myrpt->rxpl, "100.0");
  4238. strcpy(myrpt->txpl, "100.0");
  4239. myrpt->remmode = REM_MODE_USB;
  4240. break;
  4241. }
  4242. }
  4243. if (setrem(myrpt) == -1)
  4244. return DC_ERROR;
  4245. return DC_COMPLETE;
  4246. case 2: /* set freq and offset */
  4247. for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for M+*K+*O or M+*H+* depending on mode */
  4248. if (digitbuf[i] == '*') {
  4249. j++;
  4250. continue;
  4251. }
  4252. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  4253. goto invalid_freq;
  4254. else {
  4255. if (j == 0)
  4256. l++; /* # of digits before first * */
  4257. if (j == 1)
  4258. k++; /* # of digits after first * */
  4259. }
  4260. }
  4261. i = strlen(digitbuf) - 1;
  4262. if (multimode) {
  4263. if ((j > 2) || (l > 3) || (k > 6))
  4264. goto invalid_freq; /* &^@#! */
  4265. } else {
  4266. if ((j > 2) || (l > 4) || (k > 3))
  4267. goto invalid_freq; /* &^@#! */
  4268. }
  4269. /* Wait for M+*K+* */
  4270. if (j < 2)
  4271. break; /* Not yet */
  4272. /* We have a frequency */
  4273. s = ast_strdupa(digitbuf);
  4274. AST_NONSTANDARD_APP_ARGS(args, s, '*');
  4275. ls2 = strlen(args.s2);
  4276. switch (ls2) { /* Allow partial entry of khz and hz digits for laziness support */
  4277. case 1:
  4278. ht = 0;
  4279. k = 100 * atoi(args.s2);
  4280. break;
  4281. case 2:
  4282. ht = 0;
  4283. k = 10 * atoi(args.s2);
  4284. break;
  4285. case 3:
  4286. if (!multimode) {
  4287. if ((args.s2[2] != '0') && (args.s2[2] != '5'))
  4288. goto invalid_freq;
  4289. }
  4290. ht = 0;
  4291. k = atoi(args.s2);
  4292. break;
  4293. case 4:
  4294. k = atoi(args.s2) / 10;
  4295. ht = 10 * (atoi(args.s2 + (ls2 - 1)));
  4296. break;
  4297. case 5:
  4298. k = atoi(args.s2) / 100;
  4299. ht = (atoi(args.s2 + (ls2 - 2)));
  4300. break;
  4301. default:
  4302. goto invalid_freq;
  4303. }
  4304. /* Check frequency for validity and establish a default mode */
  4305. snprintf(freq, sizeof(freq), "%s.%03d%02d", args.s1, k, ht);
  4306. ast_debug(1, "New frequency: %s\n", freq);
  4307. split_freq(&mhz, &decimals, freq);
  4308. if (check_freq(myrpt, mhz, decimals, &defmode)) /* Check to see if frequency entered is legit */
  4309. goto invalid_freq;
  4310. if ((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
  4311. break; /* Not yet */
  4312. offset = REM_SIMPLEX; /* Assume simplex */
  4313. if (defmode == REM_MODE_FM) {
  4314. oc = *s; /* Pick off offset */
  4315. if (oc) {
  4316. switch (oc) {
  4317. case '1':
  4318. offset = REM_MINUS;
  4319. break;
  4320. case '2':
  4321. offset = REM_SIMPLEX;
  4322. break;
  4323. case '3':
  4324. offset = REM_PLUS;
  4325. break;
  4326. default:
  4327. goto invalid_freq;
  4328. }
  4329. }
  4330. }
  4331. offsave = myrpt->offset;
  4332. modesave = myrpt->remmode;
  4333. ast_copy_string(savestr, myrpt->freq, sizeof(savestr));
  4334. ast_copy_string(myrpt->freq, freq, sizeof(myrpt->freq));
  4335. myrpt->offset = offset;
  4336. myrpt->remmode = defmode;
  4337. if (setrem(myrpt) == -1) {
  4338. myrpt->offset = offsave;
  4339. myrpt->remmode = modesave;
  4340. ast_copy_string(myrpt->freq, savestr, sizeof(myrpt->freq));
  4341. goto invalid_freq;
  4342. }
  4343. return DC_COMPLETE;
  4344. invalid_freq:
  4345. rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
  4346. return DC_ERROR;
  4347. case 3: /* set rx PL tone */
  4348. for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */
  4349. if (digitbuf[i] == '*') {
  4350. j++;
  4351. continue;
  4352. }
  4353. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  4354. return DC_ERROR;
  4355. else {
  4356. if (j)
  4357. l++;
  4358. else
  4359. k++;
  4360. }
  4361. }
  4362. if ((j > 1) || (k > 3) || (l > 1))
  4363. return DC_ERROR; /* &$@^! */
  4364. i = strlen(digitbuf) - 1;
  4365. if ((j != 1) || (k < 2)|| (l != 1))
  4366. break; /* Not yet */
  4367. ast_debug(1, "PL digits entered %s\n", digitbuf);
  4368. ast_copy_string(tmp, digitbuf, sizeof(tmp));
  4369. /* see if we have at least 1 */
  4370. s = strchr(tmp, '*');
  4371. if (s)
  4372. *s = '.';
  4373. ast_copy_string(savestr, myrpt->rxpl, sizeof(savestr));
  4374. ast_copy_string(myrpt->rxpl, tmp, sizeof(myrpt->rxpl));
  4375. if (setrem(myrpt) == -1) {
  4376. ast_copy_string(myrpt->rxpl, savestr, sizeof(myrpt->rxpl));
  4377. return DC_ERROR;
  4378. }
  4379. return DC_COMPLETE;
  4380. case 4: /* set tx PL tone */
  4381. for (i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++) { /* look for N+*N */
  4382. if (digitbuf[i] == '*') {
  4383. j++;
  4384. continue;
  4385. }
  4386. if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  4387. return DC_ERROR;
  4388. else {
  4389. if (j)
  4390. l++;
  4391. else
  4392. k++;
  4393. }
  4394. }
  4395. if ((j > 1) || (k > 3) || (l > 1))
  4396. return DC_ERROR; /* &$@^! */
  4397. i = strlen(digitbuf) - 1;
  4398. if ((j != 1) || (k < 2)|| (l != 1))
  4399. break; /* Not yet */
  4400. ast_debug(1, "PL digits entered %s\n", digitbuf);
  4401. ast_copy_string(tmp, digitbuf, sizeof(tmp));
  4402. /* see if we have at least 1 */
  4403. s = strchr(tmp, '*');
  4404. if (s)
  4405. *s = '.';
  4406. ast_copy_string(savestr, myrpt->txpl, sizeof(savestr));
  4407. ast_copy_string(myrpt->txpl, tmp, sizeof(myrpt->txpl));
  4408. if (setrem(myrpt) == -1) {
  4409. ast_copy_string(myrpt->txpl, savestr, sizeof(myrpt->txpl));
  4410. return DC_ERROR;
  4411. }
  4412. return DC_COMPLETE;
  4413. case 6: /* MODE (FM,USB,LSB,AM) */
  4414. if (strlen(digitbuf) < 1)
  4415. break;
  4416. if (!multimode)
  4417. return DC_ERROR; /* Multimode radios only */
  4418. switch (*digitbuf) {
  4419. case '1':
  4420. split_freq(&mhz, &decimals, myrpt->freq);
  4421. if (mhz < 29) /* No FM allowed below 29MHz! */
  4422. return DC_ERROR;
  4423. myrpt->remmode = REM_MODE_FM;
  4424. res = rmt_saycharstr(myrpt, mychannel, 1000, "FM");
  4425. break;
  4426. case '2':
  4427. myrpt->remmode = REM_MODE_USB;
  4428. res = rmt_saycharstr(myrpt, mychannel, 1000, "USB");
  4429. break;
  4430. case '3':
  4431. myrpt->remmode = REM_MODE_LSB;
  4432. res = rmt_saycharstr(myrpt, mychannel, 1000, "LSB");
  4433. break;
  4434. case '4':
  4435. myrpt->remmode = REM_MODE_AM;
  4436. res = rmt_saycharstr(myrpt, mychannel, 1000, "AM");
  4437. break;
  4438. default:
  4439. return DC_ERROR;
  4440. }
  4441. if (res)
  4442. return DC_ERROR;
  4443. if (setrem(myrpt))
  4444. return DC_ERROR;
  4445. return DC_COMPLETE;
  4446. case 100: /* other stuff */
  4447. case 101:
  4448. case 102:
  4449. case 103:
  4450. case 104:
  4451. case 105:
  4452. case 106:
  4453. res = rmt_telem_start(myrpt, mychannel, 1000);
  4454. switch (myatoi(param)) { /* Quick commands requiring a setrem call */
  4455. case 100: /* RX PL Off */
  4456. myrpt->rxplon = 0;
  4457. if (!res)
  4458. res = sayfile(mychannel, "rpt/rxpl");
  4459. if (!res)
  4460. sayfile(mychannel, "rpt/off");
  4461. break;
  4462. case 101: /* RX PL On */
  4463. myrpt->rxplon = 1;
  4464. if (!res)
  4465. res = sayfile(mychannel, "rpt/rxpl");
  4466. if (!res)
  4467. sayfile(mychannel, "rpt/on");
  4468. break;
  4469. case 102: /* TX PL Off */
  4470. myrpt->txplon = 0;
  4471. if (!res)
  4472. res = sayfile(mychannel, "rpt/txpl");
  4473. if (!res)
  4474. sayfile(mychannel, "rpt/off");
  4475. break;
  4476. case 103: /* TX PL On */
  4477. myrpt->txplon = 1;
  4478. if (!res)
  4479. res = sayfile(mychannel, "rpt/txpl");
  4480. if (!res)
  4481. sayfile(mychannel, "rpt/on");
  4482. break;
  4483. case 104: /* Low Power */
  4484. myrpt->powerlevel = REM_LOWPWR;
  4485. if (!res)
  4486. res = sayfile(mychannel, "rpt/lopwr");
  4487. break;
  4488. case 105: /* Medium Power */
  4489. myrpt->powerlevel = REM_MEDPWR;
  4490. if (!res)
  4491. res = sayfile(mychannel, "rpt/medpwr");
  4492. break;
  4493. case 106: /* Hi Power */
  4494. myrpt->powerlevel = REM_HIPWR;
  4495. if (!res)
  4496. res = sayfile(mychannel, "rpt/hipwr");
  4497. break;
  4498. default:
  4499. if (!res)
  4500. rmt_telem_finish(myrpt, mychannel);
  4501. return DC_ERROR;
  4502. }
  4503. if (!res)
  4504. res = rmt_telem_finish(myrpt, mychannel);
  4505. if (res)
  4506. return DC_ERROR;
  4507. if (setrem(myrpt) == -1)
  4508. return DC_ERROR;
  4509. return DC_COMPLETE;
  4510. case 107: /* Bump down 20Hz */
  4511. multimode_bump_freq(myrpt, -20);
  4512. return DC_COMPLETE;
  4513. case 108: /* Bump down 100Hz */
  4514. multimode_bump_freq(myrpt, -100);
  4515. return DC_COMPLETE;
  4516. case 109: /* Bump down 500Hz */
  4517. multimode_bump_freq(myrpt, -500);
  4518. return DC_COMPLETE;
  4519. case 110: /* Bump up 20Hz */
  4520. multimode_bump_freq(myrpt, 20);
  4521. return DC_COMPLETE;
  4522. case 111: /* Bump up 100Hz */
  4523. multimode_bump_freq(myrpt, 100);
  4524. return DC_COMPLETE;
  4525. case 112: /* Bump up 500Hz */
  4526. multimode_bump_freq(myrpt, 500);
  4527. return DC_COMPLETE;
  4528. case 113:
  4529. case 114:
  4530. case 115:
  4531. case 116:
  4532. case 117:
  4533. case 118:
  4534. myrpt->remotetx = 0;
  4535. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  4536. if (!myrpt->remoterx)
  4537. ast_indicate(mychannel, AST_CONTROL_RADIO_KEY);
  4538. if (ast_safe_sleep(mychannel, 1000) == -1)
  4539. return DC_ERROR;
  4540. switch (myatoi(param)) {
  4541. case 113: /* Scan down slow */
  4542. res = sayfile(mychannel, "rpt/down");
  4543. if (!res)
  4544. res = sayfile(mychannel, "rpt/slow");
  4545. if (!res) {
  4546. myrpt->scantimer = REM_SCANTIME;
  4547. myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
  4548. }
  4549. break;
  4550. case 114: /* Scan down quick */
  4551. res = sayfile(mychannel, "rpt/down");
  4552. if (!res)
  4553. res = sayfile(mychannel, "rpt/quick");
  4554. if (!res) {
  4555. myrpt->scantimer = REM_SCANTIME;
  4556. myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
  4557. }
  4558. break;
  4559. case 115: /* Scan down fast */
  4560. res = sayfile(mychannel, "rpt/down");
  4561. if (!res)
  4562. res = sayfile(mychannel, "rpt/fast");
  4563. if (!res) {
  4564. myrpt->scantimer = REM_SCANTIME;
  4565. myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
  4566. }
  4567. break;
  4568. case 116: /* Scan up slow */
  4569. res = sayfile(mychannel, "rpt/up");
  4570. if (!res)
  4571. res = sayfile(mychannel, "rpt/slow");
  4572. if (!res) {
  4573. myrpt->scantimer = REM_SCANTIME;
  4574. myrpt->hfscanmode = HF_SCAN_UP_SLOW;
  4575. }
  4576. break;
  4577. case 117: /* Scan up quick */
  4578. res = sayfile(mychannel, "rpt/up");
  4579. if (!res)
  4580. res = sayfile(mychannel, "rpt/quick");
  4581. if (!res) {
  4582. myrpt->scantimer = REM_SCANTIME;
  4583. myrpt->hfscanmode = HF_SCAN_UP_QUICK;
  4584. }
  4585. break;
  4586. case 118: /* Scan up fast */
  4587. res = sayfile(mychannel, "rpt/up");
  4588. if (!res)
  4589. res = sayfile(mychannel, "rpt/fast");
  4590. if (!res) {
  4591. myrpt->scantimer = REM_SCANTIME;
  4592. myrpt->hfscanmode = HF_SCAN_UP_FAST;
  4593. }
  4594. break;
  4595. }
  4596. rmt_telem_finish(myrpt, mychannel);
  4597. return DC_COMPLETE;
  4598. case 119: /* Tune Request */
  4599. myrpt->tunerequest = 1;
  4600. return DC_COMPLETE;
  4601. case 5: /* Long Status */
  4602. case 140: /* Short Status */
  4603. res = rmt_telem_start(myrpt, mychannel, 1000);
  4604. res = sayfile(mychannel, "rpt/node");
  4605. if (!res)
  4606. res = saycharstr(mychannel, myrpt->name);
  4607. if (!res)
  4608. res = sayfile(mychannel, "rpt/frequency");
  4609. if (!res)
  4610. res = split_freq(&mhz, &decimals, myrpt->freq);
  4611. if (!res) {
  4612. if (mhz < 100)
  4613. res = saynum(mychannel, mhz);
  4614. else
  4615. res = saydigits(mychannel, mhz);
  4616. }
  4617. if (!res)
  4618. res = sayfile(mychannel, "letters/dot");
  4619. if (!res)
  4620. res = saydigits(mychannel, decimals);
  4621. if (res) {
  4622. rmt_telem_finish(myrpt, mychannel);
  4623. return DC_ERROR;
  4624. }
  4625. if (myrpt->remmode == REM_MODE_FM) { /* Mode FM? */
  4626. switch (myrpt->offset) {
  4627. case REM_MINUS:
  4628. res = sayfile(mychannel, "rpt/minus");
  4629. break;
  4630. case REM_SIMPLEX:
  4631. res = sayfile(mychannel, "rpt/simplex");
  4632. break;
  4633. case REM_PLUS:
  4634. res = sayfile(mychannel, "rpt/plus");
  4635. break;
  4636. default:
  4637. return DC_ERROR;
  4638. }
  4639. } else { /* Must be USB, LSB, or AM */
  4640. switch (myrpt->remmode) {
  4641. case REM_MODE_USB:
  4642. res = saycharstr(mychannel, "USB");
  4643. break;
  4644. case REM_MODE_LSB:
  4645. res = saycharstr(mychannel, "LSB");
  4646. break;
  4647. case REM_MODE_AM:
  4648. res = saycharstr(mychannel, "AM");
  4649. break;
  4650. default:
  4651. return DC_ERROR;
  4652. }
  4653. }
  4654. if (res == -1) {
  4655. rmt_telem_finish(myrpt, mychannel);
  4656. return DC_ERROR;
  4657. }
  4658. if (myatoi(param) == 140) { /* Short status? */
  4659. if (!res)
  4660. res = rmt_telem_finish(myrpt, mychannel);
  4661. if (res)
  4662. return DC_ERROR;
  4663. return DC_COMPLETE;
  4664. }
  4665. switch (myrpt->powerlevel) {
  4666. case REM_LOWPWR:
  4667. res = sayfile(mychannel, "rpt/lopwr") ;
  4668. break;
  4669. case REM_MEDPWR:
  4670. res = sayfile(mychannel, "rpt/medpwr");
  4671. break;
  4672. case REM_HIPWR:
  4673. res = sayfile(mychannel, "rpt/hipwr");
  4674. break;
  4675. }
  4676. if (res || (sayfile(mychannel, "rpt/rxpl") == -1) ||
  4677. (sayfile(mychannel, "rpt/frequency") == -1) ||
  4678. (saycharstr(mychannel, myrpt->rxpl) == -1) ||
  4679. (sayfile(mychannel, "rpt/txpl") == -1) ||
  4680. (sayfile(mychannel, "rpt/frequency") == -1) ||
  4681. (saycharstr(mychannel, myrpt->txpl) == -1) ||
  4682. (sayfile(mychannel, "rpt/txpl") == -1) ||
  4683. (sayfile(mychannel, ((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
  4684. (sayfile(mychannel, "rpt/rxpl") == -1) ||
  4685. (sayfile(mychannel, ((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
  4686. {
  4687. rmt_telem_finish(myrpt, mychannel);
  4688. return DC_ERROR;
  4689. }
  4690. if (!res)
  4691. res = rmt_telem_finish(myrpt, mychannel);
  4692. if (res)
  4693. return DC_ERROR;
  4694. return DC_COMPLETE;
  4695. default:
  4696. return DC_ERROR;
  4697. }
  4698. return DC_INDETERMINATE;
  4699. }
  4700. static int handle_remote_dtmf_digit(struct rpt *myrpt, char c, char *keyed, int phonemode)
  4701. {
  4702. time_t now;
  4703. int ret, res = 0, src;
  4704. /* Stop scan mode if in scan mode */
  4705. if (myrpt->hfscanmode) {
  4706. stop_scan(myrpt, 0);
  4707. return 0;
  4708. }
  4709. time(&now);
  4710. /* if timed-out */
  4711. if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now) {
  4712. myrpt->dtmfidx = -1;
  4713. myrpt->dtmfbuf[0] = 0;
  4714. myrpt->dtmf_time_rem = 0;
  4715. }
  4716. /* if decode not active */
  4717. if (myrpt->dtmfidx == -1) {
  4718. /* if not lead-in digit, dont worry */
  4719. if (c != myrpt->p.funcchar)
  4720. return 0;
  4721. myrpt->dtmfidx = 0;
  4722. myrpt->dtmfbuf[0] = 0;
  4723. myrpt->dtmf_time_rem = now;
  4724. return 0;
  4725. }
  4726. /* if too many in buffer, start over */
  4727. if (myrpt->dtmfidx >= MAXDTMF) {
  4728. myrpt->dtmfidx = 0;
  4729. myrpt->dtmfbuf[0] = 0;
  4730. myrpt->dtmf_time_rem = now;
  4731. }
  4732. if (c == myrpt->p.funcchar) {
  4733. /* if star at beginning, or 2 together, erase buffer */
  4734. if ((myrpt->dtmfidx < 1) || (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar)) {
  4735. myrpt->dtmfidx = 0;
  4736. myrpt->dtmfbuf[0] = 0;
  4737. myrpt->dtmf_time_rem = now;
  4738. return 0;
  4739. }
  4740. }
  4741. myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
  4742. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  4743. myrpt->dtmf_time_rem = now;
  4744. src = SOURCE_RMT;
  4745. if (phonemode > 1)
  4746. src = SOURCE_DPHONE;
  4747. else if (phonemode)
  4748. src = SOURCE_PHONE;
  4749. ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
  4750. switch(ret) {
  4751. case DC_INDETERMINATE:
  4752. res = 0;
  4753. break;
  4754. case DC_DOKEY:
  4755. if (keyed)
  4756. *keyed = 1;
  4757. res = 0;
  4758. break;
  4759. case DC_REQ_FLUSH:
  4760. myrpt->dtmfidx = 0;
  4761. myrpt->dtmfbuf[0] = 0;
  4762. res = 0;
  4763. break;
  4764. case DC_COMPLETE:
  4765. myrpt->totalexecdcommands++;
  4766. myrpt->dailyexecdcommands++;
  4767. ast_copy_string(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF);
  4768. myrpt->dtmfbuf[0] = 0;
  4769. myrpt->dtmfidx = -1;
  4770. myrpt->dtmf_time_rem = 0;
  4771. res = 1;
  4772. break;
  4773. case DC_ERROR:
  4774. default:
  4775. myrpt->dtmfbuf[0] = 0;
  4776. myrpt->dtmfidx = -1;
  4777. myrpt->dtmf_time_rem = 0;
  4778. res = 0;
  4779. }
  4780. return res;
  4781. }
  4782. static int handle_remote_data(struct rpt *myrpt, char *str)
  4783. {
  4784. /* XXX ATTENTION: if you change the size of these arrays you MUST
  4785. * change the limits in corresponding sscanf() calls below. */
  4786. char cmd[300], dest[300], src[300], c;
  4787. int seq, res;
  4788. if (!strcmp(str, discstr))
  4789. return 0;
  4790. /* XXX WARNING: be very careful with the limits on the folowing
  4791. * sscanf() call, make sure they match the values defined above */
  4792. if (sscanf(str, "%299s %299s %299s %30d %1c", cmd, dest, src, &seq, &c) != 5) {
  4793. ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
  4794. return 0;
  4795. }
  4796. if (strcmp(cmd, "D")) {
  4797. ast_log(LOG_WARNING, "Unable to parse link string %s\n", str);
  4798. return 0;
  4799. }
  4800. /* if not for me, ignore */
  4801. if (strcmp(dest, myrpt->name))
  4802. return 0;
  4803. res = handle_remote_dtmf_digit(myrpt, c, NULL, 0);
  4804. if (res != 1)
  4805. return res;
  4806. myrpt->remotetx = 0;
  4807. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  4808. if (!myrpt->remoterx) {
  4809. ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
  4810. }
  4811. if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
  4812. return -1;
  4813. res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete");
  4814. rmt_telem_finish(myrpt, myrpt->remchannel);
  4815. return res;
  4816. }
  4817. static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
  4818. {
  4819. int res;
  4820. if (keyed && *keyed && (c == myrpt->p.endchar)) {
  4821. *keyed = 0;
  4822. return DC_INDETERMINATE;
  4823. }
  4824. res = handle_remote_dtmf_digit(myrpt, c, keyed, phonemode);
  4825. if (res != 1)
  4826. return res;
  4827. myrpt->remotetx = 0;
  4828. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  4829. if (!myrpt->remoterx) {
  4830. ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
  4831. }
  4832. if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
  4833. return -1;
  4834. res = telem_lookup(myrpt, myrpt->remchannel, myrpt->name, "functcomplete");
  4835. rmt_telem_finish(myrpt, myrpt->remchannel);
  4836. return res;
  4837. }
  4838. static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
  4839. {
  4840. const char *val;
  4841. char *s, *tele;
  4842. char deststr[300] = "";
  4843. AST_DECLARE_APP_ARGS(args,
  4844. AST_APP_ARG(channel);
  4845. AST_APP_ARG(extra);
  4846. );
  4847. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, l->name);
  4848. if (!val) {
  4849. ast_log(LOG_ERROR, "attempt_reconnect: cannot find node %s\n", l->name);
  4850. return -1;
  4851. }
  4852. rpt_mutex_lock(&myrpt->lock);
  4853. /* remove from queue */
  4854. remque((struct qelem *) l);
  4855. rpt_mutex_unlock(&myrpt->lock);
  4856. s = ast_strdupa(val);
  4857. AST_STANDARD_APP_ARGS(args, s);
  4858. /* XXX This section doesn't make any sense. Why not just use args.channel? XXX */
  4859. snprintf(deststr, sizeof(deststr), "IAX2/%s", args.channel);
  4860. tele = strchr(deststr, '/');
  4861. if (!tele) {
  4862. ast_log(LOG_ERROR, "attempt_reconnect:Dial number (%s) must be in format tech/number\n", deststr);
  4863. return -1;
  4864. }
  4865. *tele++ = 0;
  4866. l->elaptime = 0;
  4867. l->connecttime = 0;
  4868. l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
  4869. if (l->chan) {
  4870. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  4871. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  4872. l->chan->whentohangup = 0;
  4873. l->chan->appl = "Apprpt";
  4874. l->chan->data = "(Remote Rx)";
  4875. ast_verb(3, "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
  4876. deststr, tele, l->chan->name);
  4877. if (l->chan->cid.cid_num)
  4878. ast_free(l->chan->cid.cid_num);
  4879. l->chan->cid.cid_num = ast_strdup(myrpt->name);
  4880. ast_call(l->chan, tele, 999);
  4881. } else {
  4882. ast_verb(3, "Unable to place call to %s/%s on %s\n",
  4883. deststr, tele, l->chan->name);
  4884. return -1;
  4885. }
  4886. rpt_mutex_lock(&myrpt->lock);
  4887. /* put back in queue */
  4888. insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
  4889. rpt_mutex_unlock(&myrpt->lock);
  4890. ast_log(LOG_NOTICE, "Reconnect Attempt to %s in process\n", l->name);
  4891. return 0;
  4892. }
  4893. /* 0 return=continue, 1 return = break, -1 return = error */
  4894. static void local_dtmf_helper(struct rpt *myrpt, char c)
  4895. {
  4896. int res;
  4897. char cmd[MAXDTMF+1] = "";
  4898. if (c == myrpt->p.endchar) {
  4899. /* if in simple mode, kill autopatch */
  4900. if (myrpt->p.simple && myrpt->callmode) {
  4901. rpt_mutex_lock(&myrpt->lock);
  4902. myrpt->callmode = 0;
  4903. rpt_mutex_unlock(&myrpt->lock);
  4904. rpt_telemetry(myrpt, TERM, NULL);
  4905. return;
  4906. }
  4907. rpt_mutex_lock(&myrpt->lock);
  4908. myrpt->stopgen = 1;
  4909. if (myrpt->cmdnode[0]) {
  4910. myrpt->cmdnode[0] = 0;
  4911. myrpt->dtmfidx = -1;
  4912. myrpt->dtmfbuf[0] = 0;
  4913. rpt_mutex_unlock(&myrpt->lock);
  4914. rpt_telemetry(myrpt, COMPLETE, NULL);
  4915. } else
  4916. rpt_mutex_unlock(&myrpt->lock);
  4917. return;
  4918. }
  4919. rpt_mutex_lock(&myrpt->lock);
  4920. if (myrpt->cmdnode[0]) {
  4921. rpt_mutex_unlock(&myrpt->lock);
  4922. send_link_dtmf(myrpt, c);
  4923. return;
  4924. }
  4925. if (!myrpt->p.simple) {
  4926. if (c == myrpt->p.funcchar) {
  4927. myrpt->dtmfidx = 0;
  4928. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  4929. rpt_mutex_unlock(&myrpt->lock);
  4930. time(&myrpt->dtmf_time);
  4931. return;
  4932. } else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0)) {
  4933. time(&myrpt->dtmf_time);
  4934. if (myrpt->dtmfidx < MAXDTMF) {
  4935. myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
  4936. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  4937. ast_copy_string(cmd, myrpt->dtmfbuf, sizeof(cmd));
  4938. rpt_mutex_unlock(&myrpt->lock);
  4939. res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
  4940. rpt_mutex_lock(&myrpt->lock);
  4941. switch(res) {
  4942. case DC_INDETERMINATE:
  4943. break;
  4944. case DC_REQ_FLUSH:
  4945. myrpt->dtmfidx = 0;
  4946. myrpt->dtmfbuf[0] = 0;
  4947. break;
  4948. case DC_COMPLETE:
  4949. myrpt->totalexecdcommands++;
  4950. myrpt->dailyexecdcommands++;
  4951. ast_copy_string(myrpt->lastdtmfcommand, cmd, MAXDTMF);
  4952. myrpt->dtmfbuf[0] = 0;
  4953. myrpt->dtmfidx = -1;
  4954. myrpt->dtmf_time = 0;
  4955. break;
  4956. case DC_ERROR:
  4957. default:
  4958. myrpt->dtmfbuf[0] = 0;
  4959. myrpt->dtmfidx = -1;
  4960. myrpt->dtmf_time = 0;
  4961. break;
  4962. }
  4963. if (res != DC_INDETERMINATE) {
  4964. rpt_mutex_unlock(&myrpt->lock);
  4965. return;
  4966. }
  4967. }
  4968. }
  4969. } else /* if simple */ {
  4970. if ((!myrpt->callmode) && (c == myrpt->p.funcchar)) {
  4971. myrpt->callmode = 1;
  4972. myrpt->patchnoct = 0;
  4973. myrpt->patchquiet = 0;
  4974. myrpt->patchfarenddisconnect = 0;
  4975. myrpt->patchdialtime = 0;
  4976. ast_copy_string(myrpt->patchcontext, myrpt->p.ourcontext, sizeof(myrpt->patchcontext));
  4977. myrpt->cidx = 0;
  4978. myrpt->exten[myrpt->cidx] = 0;
  4979. rpt_mutex_unlock(&myrpt->lock);
  4980. ast_pthread_create_detached(&myrpt->rpt_call_thread, NULL, rpt_call, (void *)myrpt);
  4981. return;
  4982. }
  4983. }
  4984. if (myrpt->callmode == 1) {
  4985. myrpt->exten[myrpt->cidx++] = c;
  4986. myrpt->exten[myrpt->cidx] = 0;
  4987. /* if this exists */
  4988. if (ast_exists_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  4989. myrpt->callmode = 2;
  4990. rpt_mutex_unlock(&myrpt->lock);
  4991. if (!myrpt->patchquiet)
  4992. rpt_telemetry(myrpt, PROC, NULL);
  4993. return;
  4994. }
  4995. /* if can continue, do so */
  4996. if (!ast_canmatch_extension(myrpt->pchannel, myrpt->patchcontext, myrpt->exten, 1, NULL)) {
  4997. /* call has failed, inform user */
  4998. myrpt->callmode = 4;
  4999. }
  5000. rpt_mutex_unlock(&myrpt->lock);
  5001. return;
  5002. }
  5003. if ((myrpt->callmode == 2) || (myrpt->callmode == 3)) {
  5004. myrpt->mydtmf = c;
  5005. }
  5006. rpt_mutex_unlock(&myrpt->lock);
  5007. return;
  5008. }
  5009. /* place an ID event in the telemetry queue */
  5010. static void queue_id(struct rpt *myrpt)
  5011. {
  5012. myrpt->mustid = myrpt->tailid = 0;
  5013. myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
  5014. rpt_mutex_unlock(&myrpt->lock);
  5015. rpt_telemetry(myrpt, ID, NULL);
  5016. rpt_mutex_lock(&myrpt->lock);
  5017. }
  5018. /* Scheduler */
  5019. static void do_scheduler(struct rpt *myrpt)
  5020. {
  5021. int res;
  5022. struct ast_tm tmnow;
  5023. memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
  5024. if ( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
  5025. ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
  5026. /* Try to get close to a 1 second resolution */
  5027. if (myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
  5028. return;
  5029. ast_localtime(&myrpt->curtv, &tmnow, NULL);
  5030. /* If midnight, then reset all daily statistics */
  5031. if ((tmnow.tm_hour == 0) && (tmnow.tm_min == 0) && (tmnow.tm_sec == 0)) {
  5032. myrpt->dailykeyups = 0;
  5033. myrpt->dailytxtime = 0;
  5034. myrpt->dailykerchunks = 0;
  5035. myrpt->dailyexecdcommands = 0;
  5036. }
  5037. }
  5038. /* single thread with one file (request) to dial */
  5039. static void *rpt(void *this)
  5040. {
  5041. struct rpt *myrpt = (struct rpt *)this;
  5042. char *tele, c;
  5043. const char *idtalkover;
  5044. int ms = MSWAIT, i, lasttx=0, val, remrx=0, identqueued, othertelemqueued, tailmessagequeued, ctqueued;
  5045. struct ast_channel *who;
  5046. struct dahdi_confinfo ci; /* conference info */
  5047. time_t t;
  5048. struct rpt_link *l, *m;
  5049. struct rpt_tele *telem;
  5050. char tmpstr[300];
  5051. rpt_mutex_lock(&myrpt->lock);
  5052. telem = myrpt->tele.next;
  5053. while (telem != &myrpt->tele) {
  5054. ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
  5055. telem = telem->next;
  5056. }
  5057. rpt_mutex_unlock(&myrpt->lock);
  5058. /* find our index, and load the vars initially */
  5059. for (i = 0; i < nrpts; i++) {
  5060. if (&rpt_vars[i] == myrpt) {
  5061. load_rpt_vars(i, 0);
  5062. break;
  5063. }
  5064. }
  5065. rpt_mutex_lock(&myrpt->lock);
  5066. ast_copy_string(tmpstr, myrpt->rxchanname, sizeof(tmpstr));
  5067. tele = strchr(tmpstr, '/');
  5068. if (!tele) {
  5069. ast_log(LOG_ERROR, "rpt:Rxchannel Dial number (%s) must be in format tech/number\n", myrpt->rxchanname);
  5070. rpt_mutex_unlock(&myrpt->lock);
  5071. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5072. pthread_exit(NULL);
  5073. }
  5074. *tele++ = 0;
  5075. myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL);
  5076. if (myrpt->rxchannel) {
  5077. if (myrpt->rxchannel->_state == AST_STATE_BUSY) {
  5078. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
  5079. rpt_mutex_unlock(&myrpt->lock);
  5080. ast_hangup(myrpt->rxchannel);
  5081. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5082. pthread_exit(NULL);
  5083. }
  5084. ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
  5085. ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
  5086. myrpt->rxchannel->whentohangup = 0;
  5087. myrpt->rxchannel->appl = "Apprpt";
  5088. myrpt->rxchannel->data = "(Repeater Rx)";
  5089. ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
  5090. tmpstr, tele, myrpt->rxchannel->name);
  5091. ast_call(myrpt->rxchannel, tele, 999);
  5092. if (myrpt->rxchannel->_state != AST_STATE_UP) {
  5093. rpt_mutex_unlock(&myrpt->lock);
  5094. ast_hangup(myrpt->rxchannel);
  5095. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5096. pthread_exit(NULL);
  5097. }
  5098. } else {
  5099. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
  5100. rpt_mutex_unlock(&myrpt->lock);
  5101. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5102. pthread_exit(NULL);
  5103. }
  5104. if (myrpt->txchanname) {
  5105. ast_copy_string(tmpstr, myrpt->txchanname, sizeof(tmpstr));
  5106. tele = strchr(tmpstr, '/');
  5107. if (!tele) {
  5108. ast_log(LOG_ERROR, "rpt:Txchannel Dial number (%s) must be in format tech/number\n", myrpt->txchanname);
  5109. rpt_mutex_unlock(&myrpt->lock);
  5110. ast_hangup(myrpt->rxchannel);
  5111. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5112. pthread_exit(NULL);
  5113. }
  5114. *tele++ = 0;
  5115. myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, tele, NULL);
  5116. if (myrpt->txchannel) {
  5117. if (myrpt->txchannel->_state == AST_STATE_BUSY) {
  5118. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
  5119. rpt_mutex_unlock(&myrpt->lock);
  5120. ast_hangup(myrpt->txchannel);
  5121. ast_hangup(myrpt->rxchannel);
  5122. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5123. pthread_exit(NULL);
  5124. }
  5125. ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
  5126. ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
  5127. myrpt->txchannel->whentohangup = 0;
  5128. myrpt->txchannel->appl = "Apprpt";
  5129. myrpt->txchannel->data = "(Repeater Tx)";
  5130. ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
  5131. tmpstr, tele, myrpt->txchannel->name);
  5132. ast_call(myrpt->txchannel, tele, 999);
  5133. if (myrpt->rxchannel->_state != AST_STATE_UP) {
  5134. rpt_mutex_unlock(&myrpt->lock);
  5135. ast_hangup(myrpt->rxchannel);
  5136. ast_hangup(myrpt->txchannel);
  5137. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5138. pthread_exit(NULL);
  5139. }
  5140. } else {
  5141. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
  5142. rpt_mutex_unlock(&myrpt->lock);
  5143. ast_hangup(myrpt->rxchannel);
  5144. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5145. pthread_exit(NULL);
  5146. }
  5147. } else {
  5148. myrpt->txchannel = myrpt->rxchannel;
  5149. }
  5150. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
  5151. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  5152. /* allocate a pseudo-channel thru asterisk */
  5153. myrpt->pchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  5154. if (!myrpt->pchannel) {
  5155. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
  5156. rpt_mutex_unlock(&myrpt->lock);
  5157. if (myrpt->txchannel != myrpt->rxchannel)
  5158. ast_hangup(myrpt->txchannel);
  5159. ast_hangup(myrpt->rxchannel);
  5160. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5161. pthread_exit(NULL);
  5162. }
  5163. /* make a conference for the tx */
  5164. ci.chan = 0;
  5165. ci.confno = -1; /* make a new conf */
  5166. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
  5167. /* first put the channel on the conference in proper mode */
  5168. if (ioctl(myrpt->txchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  5169. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  5170. rpt_mutex_unlock(&myrpt->lock);
  5171. ast_hangup(myrpt->pchannel);
  5172. if (myrpt->txchannel != myrpt->rxchannel)
  5173. ast_hangup(myrpt->txchannel);
  5174. ast_hangup(myrpt->rxchannel);
  5175. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5176. pthread_exit(NULL);
  5177. }
  5178. /* save tx conference number */
  5179. myrpt->txconf = ci.confno;
  5180. /* make a conference for the pseudo */
  5181. ci.chan = 0;
  5182. ci.confno = -1; /* make a new conf */
  5183. ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
  5184. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  5185. /* first put the channel on the conference in announce mode */
  5186. if (ioctl(myrpt->pchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  5187. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  5188. rpt_mutex_unlock(&myrpt->lock);
  5189. ast_hangup(myrpt->pchannel);
  5190. if (myrpt->txchannel != myrpt->rxchannel)
  5191. ast_hangup(myrpt->txchannel);
  5192. ast_hangup(myrpt->rxchannel);
  5193. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5194. pthread_exit(NULL);
  5195. }
  5196. /* save pseudo channel conference number */
  5197. myrpt->conf = ci.confno;
  5198. /* allocate a pseudo-channel thru asterisk */
  5199. myrpt->txpchannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  5200. if (!myrpt->txpchannel) {
  5201. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
  5202. rpt_mutex_unlock(&myrpt->lock);
  5203. ast_hangup(myrpt->pchannel);
  5204. if (myrpt->txchannel != myrpt->rxchannel)
  5205. ast_hangup(myrpt->txchannel);
  5206. ast_hangup(myrpt->rxchannel);
  5207. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5208. pthread_exit(NULL);
  5209. }
  5210. /* make a conference for the tx */
  5211. ci.chan = 0;
  5212. ci.confno = myrpt->txconf;
  5213. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
  5214. /* first put the channel on the conference in proper mode */
  5215. if (ioctl(myrpt->txpchannel->fds[0], DAHDI_SETCONF, &ci) == -1) {
  5216. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  5217. rpt_mutex_unlock(&myrpt->lock);
  5218. ast_hangup(myrpt->txpchannel);
  5219. ast_hangup(myrpt->pchannel);
  5220. if (myrpt->txchannel != myrpt->rxchannel)
  5221. ast_hangup(myrpt->txchannel);
  5222. ast_hangup(myrpt->rxchannel);
  5223. myrpt->rpt_thread = AST_PTHREADT_STOP;
  5224. pthread_exit(NULL);
  5225. }
  5226. /* Now, the idea here is to copy from the physical rx channel buffer
  5227. into the pseudo tx buffer, and from the pseudo rx buffer into the
  5228. tx channel buffer */
  5229. myrpt->links.next = &myrpt->links;
  5230. myrpt->links.prev = &myrpt->links;
  5231. myrpt->tailtimer = 0;
  5232. myrpt->totimer = 0;
  5233. myrpt->tmsgtimer = myrpt->p.tailmessagetime;
  5234. myrpt->idtimer = myrpt->p.politeid;
  5235. myrpt->mustid = myrpt->tailid = 0;
  5236. myrpt->callmode = 0;
  5237. myrpt->tounkeyed = 0;
  5238. myrpt->tonotify = 0;
  5239. myrpt->retxtimer = 0;
  5240. myrpt->skedtimer = 0;
  5241. myrpt->tailevent = 0;
  5242. lasttx = 0;
  5243. myrpt->keyed = 0;
  5244. idtalkover = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
  5245. myrpt->dtmfidx = -1;
  5246. myrpt->dtmfbuf[0] = 0;
  5247. myrpt->rem_dtmfidx = -1;
  5248. myrpt->rem_dtmfbuf[0] = 0;
  5249. myrpt->dtmf_time = 0;
  5250. myrpt->rem_dtmf_time = 0;
  5251. myrpt->enable = 1;
  5252. myrpt->disgorgetime = 0;
  5253. myrpt->lastnodewhichkeyedusup[0] = '\0';
  5254. myrpt->dailytxtime = 0;
  5255. myrpt->totaltxtime = 0;
  5256. myrpt->dailykeyups = 0;
  5257. myrpt->totalkeyups = 0;
  5258. myrpt->dailykerchunks = 0;
  5259. myrpt->totalkerchunks = 0;
  5260. myrpt->dailyexecdcommands = 0;
  5261. myrpt->totalexecdcommands = 0;
  5262. myrpt->timeouts = 0;
  5263. myrpt->exten[0] = '\0';
  5264. myrpt->lastdtmfcommand[0] = '\0';
  5265. if (myrpt->p.startupmacro) {
  5266. snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
  5267. }
  5268. if (myrpt->p.startupgosub) {
  5269. snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
  5270. }
  5271. rpt_mutex_unlock(&myrpt->lock);
  5272. val = 0;
  5273. ast_channel_setoption(myrpt->rxchannel, AST_OPTION_TONE_VERIFY, &val, sizeof(char), 0);
  5274. val = 1;
  5275. ast_channel_setoption(myrpt->rxchannel, AST_OPTION_RELAXDTMF, &val, sizeof(char), 0);
  5276. while (ms >= 0) {
  5277. struct ast_frame *f;
  5278. struct ast_channel *cs[300];
  5279. int totx=0, elap=0, n, toexit = 0;
  5280. /* DEBUG Dump */
  5281. if ((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)) {
  5282. struct rpt_link *zl;
  5283. struct rpt_tele *zt;
  5284. myrpt->disgorgetime = 0;
  5285. ast_log(LOG_NOTICE, "********** Variable Dump Start (app_rpt) **********\n");
  5286. ast_log(LOG_NOTICE, "totx = %d\n", totx);
  5287. ast_log(LOG_NOTICE, "remrx = %d\n", remrx);
  5288. ast_log(LOG_NOTICE, "lasttx = %d\n", lasttx);
  5289. ast_log(LOG_NOTICE, "elap = %d\n", elap);
  5290. ast_log(LOG_NOTICE, "toexit = %d\n", toexit);
  5291. ast_log(LOG_NOTICE, "myrpt->keyed = %d\n", myrpt->keyed);
  5292. ast_log(LOG_NOTICE, "myrpt->localtx = %d\n", myrpt->localtx);
  5293. ast_log(LOG_NOTICE, "myrpt->callmode = %d\n", myrpt->callmode);
  5294. ast_log(LOG_NOTICE, "myrpt->enable = %d\n", myrpt->enable);
  5295. ast_log(LOG_NOTICE, "myrpt->mustid = %d\n", myrpt->mustid);
  5296. ast_log(LOG_NOTICE, "myrpt->tounkeyed = %d\n", myrpt->tounkeyed);
  5297. ast_log(LOG_NOTICE, "myrpt->tonotify = %d\n", myrpt->tonotify);
  5298. ast_log(LOG_NOTICE, "myrpt->retxtimer = %ld\n", myrpt->retxtimer);
  5299. ast_log(LOG_NOTICE, "myrpt->totimer = %d\n", myrpt->totimer);
  5300. ast_log(LOG_NOTICE, "myrpt->tailtimer = %d\n", myrpt->tailtimer);
  5301. ast_log(LOG_NOTICE, "myrpt->tailevent = %d\n", myrpt->tailevent);
  5302. zl = myrpt->links.next;
  5303. while (zl != &myrpt->links) {
  5304. ast_log(LOG_NOTICE, "*** Link Name: %s ***\n", zl->name);
  5305. ast_log(LOG_NOTICE, " link->lasttx %d\n", zl->lasttx);
  5306. ast_log(LOG_NOTICE, " link->lastrx %d\n", zl->lastrx);
  5307. ast_log(LOG_NOTICE, " link->connected %d\n", zl->connected);
  5308. ast_log(LOG_NOTICE, " link->hasconnected %d\n", zl->hasconnected);
  5309. ast_log(LOG_NOTICE, " link->outbound %d\n", zl->outbound);
  5310. ast_log(LOG_NOTICE, " link->disced %d\n", zl->disced);
  5311. ast_log(LOG_NOTICE, " link->killme %d\n", zl->killme);
  5312. ast_log(LOG_NOTICE, " link->disctime %ld\n", zl->disctime);
  5313. ast_log(LOG_NOTICE, " link->retrytimer %ld\n", zl->retrytimer);
  5314. ast_log(LOG_NOTICE, " link->retries = %d\n", zl->retries);
  5315. ast_log(LOG_NOTICE, " link->reconnects = %d\n", zl->reconnects);
  5316. zl = zl->next;
  5317. }
  5318. zt = myrpt->tele.next;
  5319. if (zt != &myrpt->tele)
  5320. ast_log(LOG_NOTICE, "*** Telemetry Queue ***\n");
  5321. while (zt != &myrpt->tele) {
  5322. ast_log(LOG_NOTICE, " Telemetry mode: %d\n", zt->mode);
  5323. zt = zt->next;
  5324. }
  5325. ast_log(LOG_NOTICE, "******* Variable Dump End (app_rpt) *******\n");
  5326. }
  5327. if (myrpt->reload) {
  5328. struct rpt_tele *telem;
  5329. rpt_mutex_lock(&myrpt->lock);
  5330. telem = myrpt->tele.next;
  5331. while (telem != &myrpt->tele) {
  5332. ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV);
  5333. telem = telem->next;
  5334. }
  5335. myrpt->reload = 0;
  5336. rpt_mutex_unlock(&myrpt->lock);
  5337. usleep(10000);
  5338. /* find our index, and load the vars */
  5339. for (i = 0; i < nrpts; i++) {
  5340. if (&rpt_vars[i] == myrpt) {
  5341. load_rpt_vars(i, 0);
  5342. break;
  5343. }
  5344. }
  5345. }
  5346. rpt_mutex_lock(&myrpt->lock);
  5347. if (ast_check_hangup(myrpt->rxchannel)) break;
  5348. if (ast_check_hangup(myrpt->txchannel)) break;
  5349. if (ast_check_hangup(myrpt->pchannel)) break;
  5350. if (ast_check_hangup(myrpt->txpchannel)) break;
  5351. /* Update local tx with keyed if not parsing a command */
  5352. myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
  5353. /* If someone's connected, and they're transmitting from their end to us, set remrx true */
  5354. l = myrpt->links.next;
  5355. remrx = 0;
  5356. while (l != &myrpt->links) {
  5357. if (l->lastrx) {
  5358. remrx = 1;
  5359. if (l->name[0] != '0') /* Ignore '0' nodes */
  5360. strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */
  5361. }
  5362. l = l->next;
  5363. }
  5364. /* Create a "must_id" flag for the cleanup ID */
  5365. myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
  5366. /* Build a fresh totx from myrpt->keyed and autopatch activated */
  5367. totx = myrpt->callmode;
  5368. /* If full duplex, add local tx to totx */
  5369. if (myrpt->p.duplex > 1) totx = totx || myrpt->localtx;
  5370. /* Traverse the telemetry list to see what's queued */
  5371. identqueued = 0;
  5372. othertelemqueued = 0;
  5373. tailmessagequeued = 0;
  5374. ctqueued = 0;
  5375. telem = myrpt->tele.next;
  5376. while (telem != &myrpt->tele) {
  5377. if ((telem->mode == ID) || (telem->mode == IDTALKOVER)) {
  5378. identqueued = 1; /* Identification telemetry */
  5379. } else if (telem->mode == TAILMSG) {
  5380. tailmessagequeued = 1; /* Tail message telemetry */
  5381. } else {
  5382. if (telem->mode != UNKEY)
  5383. othertelemqueued = 1; /* Other telemetry */
  5384. else
  5385. ctqueued = 1; /* Courtesy tone telemetry */
  5386. }
  5387. telem = telem->next;
  5388. }
  5389. /* Add in any "other" telemetry, if 3/4 or full duplex */
  5390. if (myrpt->p.duplex > 0)
  5391. totx = totx || othertelemqueued;
  5392. /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
  5393. myrpt->exttx = totx;
  5394. /* If half or 3/4 duplex, add localtx to external link tx */
  5395. if (myrpt->p.duplex < 2)
  5396. myrpt->exttx = myrpt->exttx || myrpt->localtx;
  5397. /* Add in ID telemetry to local transmitter */
  5398. totx = totx || remrx;
  5399. /* If 3/4 or full duplex, add in ident and CT telemetry */
  5400. if (myrpt->p.duplex > 0)
  5401. totx = totx || identqueued || ctqueued;
  5402. /* Reset time out timer variables if there is no activity */
  5403. if (!totx) {
  5404. myrpt->totimer = myrpt->p.totime;
  5405. myrpt->tounkeyed = 0;
  5406. myrpt->tonotify = 0;
  5407. } else
  5408. myrpt->tailtimer = myrpt->p.hangtime; /* Initialize tail timer */
  5409. /* Disable the local transmitter if we are timed out */
  5410. totx = totx && myrpt->totimer;
  5411. /* if timed-out and not said already, say it */
  5412. if ((!myrpt->totimer) && (!myrpt->tonotify)) {
  5413. myrpt->tonotify = 1;
  5414. myrpt->timeouts++;
  5415. rpt_mutex_unlock(&myrpt->lock);
  5416. rpt_telemetry(myrpt, TIMEOUT, NULL);
  5417. rpt_mutex_lock(&myrpt->lock);
  5418. }
  5419. /* If unkey and re-key, reset time out timer */
  5420. if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed)) {
  5421. myrpt->tounkeyed = 1;
  5422. }
  5423. if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed) {
  5424. myrpt->totimer = myrpt->p.totime;
  5425. myrpt->tounkeyed = 0;
  5426. myrpt->tonotify = 0;
  5427. rpt_mutex_unlock(&myrpt->lock);
  5428. continue;
  5429. }
  5430. /* if timed-out and in circuit busy after call */
  5431. if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4)) {
  5432. myrpt->callmode = 0;
  5433. }
  5434. /* get rid of tail if timed out */
  5435. if (!myrpt->totimer)
  5436. myrpt->tailtimer = 0;
  5437. /* if not timed-out, add in tail */
  5438. if (myrpt->totimer)
  5439. totx = totx || myrpt->tailtimer;
  5440. /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
  5441. /* If tail message, kill the message if someone keys up over it */
  5442. if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
  5443. int hasid = 0, hastalkover = 0;
  5444. telem = myrpt->tele.next;
  5445. while (telem != &myrpt->tele) {
  5446. if (telem->mode == ID) {
  5447. if (telem->chan)
  5448. ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
  5449. hasid = 1;
  5450. }
  5451. if (telem->mode == TAILMSG) {
  5452. if (telem->chan)
  5453. ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
  5454. }
  5455. if (telem->mode == IDTALKOVER)
  5456. hastalkover = 1;
  5457. telem = telem->next;
  5458. }
  5459. rpt_mutex_unlock(&myrpt->lock);
  5460. if (hasid && (!hastalkover))
  5461. rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
  5462. rpt_mutex_lock(&myrpt->lock);
  5463. }
  5464. /* Try to be polite */
  5465. /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
  5466. /* If within 30 seconds of the time to ID, try do it in the tail */
  5467. /* else if at ID time limit, do it right over the top of them */
  5468. /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
  5469. if (myrpt->mustid && (!myrpt->idtimer))
  5470. queue_id(myrpt);
  5471. if ((totx && (!myrpt->exttx) &&
  5472. (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) {
  5473. myrpt->tailid = 1;
  5474. }
  5475. /* If tail timer expires, then check for tail messages */
  5476. if (myrpt->tailevent) {
  5477. myrpt->tailevent = 0;
  5478. if (myrpt->tailid) {
  5479. totx = 1;
  5480. queue_id(myrpt);
  5481. }
  5482. else if ((myrpt->p.tailmsg.msgs[0]) &&
  5483. (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)) {
  5484. totx = 1;
  5485. myrpt->tmsgtimer = myrpt->p.tailmessagetime;
  5486. rpt_mutex_unlock(&myrpt->lock);
  5487. rpt_telemetry(myrpt, TAILMSG, NULL);
  5488. rpt_mutex_lock(&myrpt->lock);
  5489. }
  5490. }
  5491. /* Main TX control */
  5492. /* let telemetry transmit anyway (regardless of timeout) */
  5493. if (myrpt->p.duplex > 0)
  5494. totx = totx || (myrpt->tele.next != &myrpt->tele);
  5495. if (totx && (!lasttx)) {
  5496. lasttx = 1;
  5497. myrpt->dailykeyups++;
  5498. myrpt->totalkeyups++;
  5499. rpt_mutex_unlock(&myrpt->lock);
  5500. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
  5501. rpt_mutex_lock(&myrpt->lock);
  5502. }
  5503. totx = totx && myrpt->enable;
  5504. if ((!totx) && lasttx) {
  5505. lasttx = 0;
  5506. rpt_mutex_unlock(&myrpt->lock);
  5507. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  5508. rpt_mutex_lock(&myrpt->lock);
  5509. }
  5510. time(&t);
  5511. /* if DTMF timeout */
  5512. if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t)) {
  5513. myrpt->dtmfidx = -1;
  5514. myrpt->dtmfbuf[0] = 0;
  5515. }
  5516. /* if remote DTMF timeout */
  5517. if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t)) {
  5518. myrpt->rem_dtmfidx = -1;
  5519. myrpt->rem_dtmfbuf[0] = 0;
  5520. }
  5521. /* Reconnect */
  5522. l = myrpt->links.next;
  5523. while (l != &myrpt->links) {
  5524. if (l->killme) {
  5525. /* remove from queue */
  5526. remque((struct qelem *) l);
  5527. if (!strcmp(myrpt->cmdnode, l->name))
  5528. myrpt->cmdnode[0] = 0;
  5529. rpt_mutex_unlock(&myrpt->lock);
  5530. /* hang-up on call to device */
  5531. if (l->chan)
  5532. ast_hangup(l->chan);
  5533. ast_hangup(l->pchan);
  5534. ast_free(l);
  5535. rpt_mutex_lock(&myrpt->lock);
  5536. /* re-start link traversal */
  5537. l = myrpt->links.next;
  5538. continue;
  5539. }
  5540. l = l->next;
  5541. }
  5542. n = 0;
  5543. cs[n++] = myrpt->rxchannel;
  5544. cs[n++] = myrpt->pchannel;
  5545. cs[n++] = myrpt->txpchannel;
  5546. if (myrpt->txchannel != myrpt->rxchannel)
  5547. cs[n++] = myrpt->txchannel;
  5548. l = myrpt->links.next;
  5549. while (l != &myrpt->links) {
  5550. if ((!l->killme) && (!l->disctime) && l->chan) {
  5551. cs[n++] = l->chan;
  5552. cs[n++] = l->pchan;
  5553. }
  5554. l = l->next;
  5555. }
  5556. rpt_mutex_unlock(&myrpt->lock);
  5557. ms = MSWAIT;
  5558. who = ast_waitfor_n(cs, n, &ms);
  5559. if (who == NULL)
  5560. ms = 0;
  5561. elap = MSWAIT - ms;
  5562. rpt_mutex_lock(&myrpt->lock);
  5563. l = myrpt->links.next;
  5564. while (l != &myrpt->links) {
  5565. if (!l->lasttx) {
  5566. if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME) {
  5567. l->retxtimer = 0;
  5568. if (l->chan)
  5569. ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY);
  5570. }
  5571. } else
  5572. l->retxtimer = 0;
  5573. if (l->disctime) { /* Disconnect timer active on a channel ? */
  5574. l->disctime -= elap;
  5575. if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */
  5576. l->disctime = 0; /* Yep */
  5577. }
  5578. if (l->retrytimer) {
  5579. l->retrytimer -= elap;
  5580. if (l->retrytimer < 0)
  5581. l->retrytimer = 0;
  5582. }
  5583. /* Tally connect time */
  5584. l->connecttime += elap;
  5585. /* ignore non-timing channels */
  5586. if (l->elaptime < 0) {
  5587. l = l->next;
  5588. continue;
  5589. }
  5590. l->elaptime += elap;
  5591. /* if connection has taken too long */
  5592. if ((l->elaptime > MAXCONNECTTIME) &&
  5593. ((!l->chan) || (l->chan->_state != AST_STATE_UP))) {
  5594. l->elaptime = 0;
  5595. rpt_mutex_unlock(&myrpt->lock);
  5596. if (l->chan)
  5597. ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
  5598. rpt_mutex_lock(&myrpt->lock);
  5599. break;
  5600. }
  5601. if ((!l->chan) && (!l->retrytimer) && l->outbound &&
  5602. (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
  5603. if (l->chan)
  5604. ast_hangup(l->chan);
  5605. rpt_mutex_unlock(&myrpt->lock);
  5606. if ((l->name[0] != '0') && (!l->isremote)) {
  5607. l->retrytimer = MAX_RETRIES + 1;
  5608. } else {
  5609. if (attempt_reconnect(myrpt, l) == -1) {
  5610. l->retrytimer = RETRY_TIMER_MS;
  5611. }
  5612. }
  5613. rpt_mutex_lock(&myrpt->lock);
  5614. break;
  5615. }
  5616. if ((!l->chan) && (!l->retrytimer) && l->outbound && (l->retries >= MAX_RETRIES)) {
  5617. /* remove from queue */
  5618. remque((struct qelem *) l);
  5619. if (!strcmp(myrpt->cmdnode, l->name))
  5620. myrpt->cmdnode[0] = 0;
  5621. rpt_mutex_unlock(&myrpt->lock);
  5622. if (l->name[0] != '0') {
  5623. if (!l->hasconnected)
  5624. rpt_telemetry(myrpt, CONNFAIL, l);
  5625. else
  5626. rpt_telemetry(myrpt, REMDISC, l);
  5627. }
  5628. /* hang-up on call to device */
  5629. ast_hangup(l->pchan);
  5630. ast_free(l);
  5631. rpt_mutex_lock(&myrpt->lock);
  5632. break;
  5633. }
  5634. if ((!l->chan) && (!l->disctime) && (!l->outbound)) {
  5635. /* remove from queue */
  5636. remque((struct qelem *) l);
  5637. if (!strcmp(myrpt->cmdnode, l->name))
  5638. myrpt->cmdnode[0] = 0;
  5639. rpt_mutex_unlock(&myrpt->lock);
  5640. if (l->name[0] != '0') {
  5641. rpt_telemetry(myrpt, REMDISC, l);
  5642. }
  5643. /* hang-up on call to device */
  5644. ast_hangup(l->pchan);
  5645. ast_free(l);
  5646. rpt_mutex_lock(&myrpt->lock);
  5647. break;
  5648. }
  5649. l = l->next;
  5650. }
  5651. if (totx) {
  5652. myrpt->dailytxtime += elap;
  5653. myrpt->totaltxtime += elap;
  5654. }
  5655. i = myrpt->tailtimer;
  5656. if (myrpt->tailtimer)
  5657. myrpt->tailtimer -= elap;
  5658. if (myrpt->tailtimer < 0)
  5659. myrpt->tailtimer = 0;
  5660. if ((i) && (myrpt->tailtimer == 0))
  5661. myrpt->tailevent = 1;
  5662. if (myrpt->totimer)
  5663. myrpt->totimer -= elap;
  5664. if (myrpt->totimer < 0)
  5665. myrpt->totimer = 0;
  5666. if (myrpt->idtimer)
  5667. myrpt->idtimer -= elap;
  5668. if (myrpt->idtimer < 0)
  5669. myrpt->idtimer = 0;
  5670. if (myrpt->tmsgtimer)
  5671. myrpt->tmsgtimer -= elap;
  5672. if (myrpt->tmsgtimer < 0)
  5673. myrpt->tmsgtimer = 0;
  5674. /* do macro timers */
  5675. if (myrpt->macrotimer)
  5676. myrpt->macrotimer -= elap;
  5677. if (myrpt->macrotimer < 0)
  5678. myrpt->macrotimer = 0;
  5679. /* do gosub timers */
  5680. if (myrpt->gosubtimer)
  5681. myrpt->gosubtimer -= elap;
  5682. if (myrpt->gosubtimer < 0)
  5683. myrpt->gosubtimer = 0;
  5684. /* Execute scheduler appx. every 2 tenths of a second */
  5685. if (myrpt->skedtimer <= 0) {
  5686. myrpt->skedtimer = 200;
  5687. do_scheduler(myrpt);
  5688. } else
  5689. myrpt->skedtimer -= elap;
  5690. if (!ms) {
  5691. rpt_mutex_unlock(&myrpt->lock);
  5692. continue;
  5693. }
  5694. c = myrpt->macrobuf[0];
  5695. if (c && (!myrpt->macrotimer)) {
  5696. myrpt->macrotimer = MACROTIME;
  5697. memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1);
  5698. if ((c == 'p') || (c == 'P'))
  5699. myrpt->macrotimer = MACROPTIME;
  5700. rpt_mutex_unlock(&myrpt->lock);
  5701. local_dtmf_helper(myrpt, c);
  5702. } else
  5703. rpt_mutex_unlock(&myrpt->lock);
  5704. c = myrpt->gosubbuf[0];
  5705. if (c && (!myrpt->gosubtimer)) {
  5706. myrpt->gosubtimer = GOSUBTIME;
  5707. memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
  5708. if ((c == 'p') || (c == 'P'))
  5709. myrpt->gosubtimer = GOSUBPTIME;
  5710. rpt_mutex_unlock(&myrpt->lock);
  5711. local_dtmf_helper(myrpt, c);
  5712. } else
  5713. rpt_mutex_unlock(&myrpt->lock);
  5714. if (who == myrpt->rxchannel) { /* if it was a read from rx */
  5715. f = ast_read(myrpt->rxchannel);
  5716. if (!f) {
  5717. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5718. break;
  5719. }
  5720. if (f->frametype == AST_FRAME_VOICE) {
  5721. #ifdef _MDC_DECODE_H_
  5722. unsigned char ubuf[2560];
  5723. short *sp;
  5724. int n;
  5725. #endif
  5726. if (!myrpt->localtx) {
  5727. memset(f->data, 0, f->datalen);
  5728. }
  5729. #ifdef _MDC_DECODE_H_
  5730. sp = (short *) f->data;
  5731. /* convert block to unsigned char */
  5732. for (n = 0; n < f->datalen / 2; n++) {
  5733. ubuf[n] = (*sp++ >> 8) + 128;
  5734. }
  5735. n = mdc_decoder_process_samples(myrpt->mdc, ubuf, f->datalen / 2);
  5736. if (n == 1) {
  5737. unsigned char op, arg;
  5738. unsigned short unitID;
  5739. mdc_decoder_get_packet(myrpt->mdc, &op, &arg, &unitID);
  5740. if (debug > 2) {
  5741. ast_log(LOG_NOTICE, "Got (single-length) packet:\n");
  5742. ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID);
  5743. }
  5744. if ((op == 1) && (arg == 0)) {
  5745. myrpt->lastunit = unitID;
  5746. }
  5747. }
  5748. if ((debug > 2) && (i == 2)) {
  5749. unsigned char op, arg, ex1, ex2, ex3, ex4;
  5750. unsigned short unitID;
  5751. mdc_decoder_get_double_packet(myrpt->mdc, &op, &arg, &unitID, &ex1, &ex2, &ex3, &ex4);
  5752. ast_log(LOG_NOTICE, "Got (double-length) packet:\n");
  5753. ast_log(LOG_NOTICE, "op: %02x, arg: %02x, UnitID: %04x\n", op & 255, arg & 255, unitID);
  5754. ast_log(LOG_NOTICE, "ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
  5755. ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
  5756. }
  5757. #endif
  5758. #ifdef __RPT_NOTCH
  5759. /* apply inbound filters, if any */
  5760. rpt_filter(myrpt, f->data, f->datalen / 2);
  5761. #endif
  5762. ast_write(myrpt->pchannel, f);
  5763. } else if (f->frametype == AST_FRAME_DTMF) {
  5764. c = (char) f->subclass; /* get DTMF char */
  5765. ast_frfree(f);
  5766. if (!myrpt->keyed)
  5767. continue;
  5768. local_dtmf_helper(myrpt, c);
  5769. continue;
  5770. } else if (f->frametype == AST_FRAME_CONTROL) {
  5771. if (f->subclass == AST_CONTROL_HANGUP) {
  5772. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5773. ast_frfree(f);
  5774. break;
  5775. }
  5776. /* if RX key */
  5777. if (f->subclass == AST_CONTROL_RADIO_KEY) {
  5778. if ((!lasttx) || (myrpt->p.duplex > 1)) {
  5779. ast_debug(8, "@@@@ rx key\n");
  5780. myrpt->keyed = 1;
  5781. }
  5782. }
  5783. /* if RX un-key */
  5784. if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
  5785. if ((!lasttx) || (myrpt->p.duplex > 1)) {
  5786. ast_debug(8, "@@@@ rx un-key\n");
  5787. if (myrpt->keyed) {
  5788. rpt_telemetry(myrpt, UNKEY, NULL);
  5789. }
  5790. myrpt->keyed = 0;
  5791. }
  5792. }
  5793. }
  5794. ast_frfree(f);
  5795. continue;
  5796. }
  5797. if (who == myrpt->pchannel) { /* if it was a read from pseudo */
  5798. f = ast_read(myrpt->pchannel);
  5799. if (!f) {
  5800. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5801. break;
  5802. }
  5803. if (f->frametype == AST_FRAME_VOICE) {
  5804. ast_write(myrpt->txpchannel, f);
  5805. }
  5806. if (f->frametype == AST_FRAME_CONTROL) {
  5807. if (f->subclass == AST_CONTROL_HANGUP) {
  5808. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5809. ast_frfree(f);
  5810. break;
  5811. }
  5812. }
  5813. ast_frfree(f);
  5814. continue;
  5815. }
  5816. if (who == myrpt->txchannel) { /* if it was a read from tx */
  5817. f = ast_read(myrpt->txchannel);
  5818. if (!f) {
  5819. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5820. break;
  5821. }
  5822. if (f->frametype == AST_FRAME_CONTROL) {
  5823. if (f->subclass == AST_CONTROL_HANGUP) {
  5824. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5825. ast_frfree(f);
  5826. break;
  5827. }
  5828. }
  5829. ast_frfree(f);
  5830. continue;
  5831. }
  5832. toexit = 0;
  5833. rpt_mutex_lock(&myrpt->lock);
  5834. l = myrpt->links.next;
  5835. while (l != &myrpt->links) {
  5836. if (l->disctime) {
  5837. l = l->next;
  5838. continue;
  5839. }
  5840. if (who == l->chan) { /* if it was a read from rx */
  5841. remrx = 0;
  5842. /* see if any other links are receiving */
  5843. m = myrpt->links.next;
  5844. while (m != &myrpt->links) {
  5845. /* if not us, count it */
  5846. if ((m != l) && (m->lastrx))
  5847. remrx = 1;
  5848. m = m->next;
  5849. }
  5850. rpt_mutex_unlock(&myrpt->lock);
  5851. totx = (((l->isremote) ? myrpt->localtx :
  5852. myrpt->exttx) || remrx) && l->mode;
  5853. if (l->chan && (l->lasttx != totx)) {
  5854. if (totx) {
  5855. ast_indicate(l->chan, AST_CONTROL_RADIO_KEY);
  5856. } else {
  5857. ast_indicate(l->chan, AST_CONTROL_RADIO_UNKEY);
  5858. }
  5859. }
  5860. l->lasttx = totx;
  5861. f = ast_read(l->chan);
  5862. if (!f) {
  5863. if ((!l->disced) && (!l->outbound)) {
  5864. if ((l->name[0] == '0') || l->isremote)
  5865. l->disctime = 1;
  5866. else
  5867. l->disctime = DISC_TIME;
  5868. rpt_mutex_lock(&myrpt->lock);
  5869. ast_hangup(l->chan);
  5870. l->chan = 0;
  5871. break;
  5872. }
  5873. if (l->retrytimer) {
  5874. rpt_mutex_lock(&myrpt->lock);
  5875. break;
  5876. }
  5877. if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
  5878. rpt_mutex_lock(&myrpt->lock);
  5879. ast_hangup(l->chan);
  5880. l->chan = 0;
  5881. rpt_mutex_unlock(&myrpt->lock);
  5882. if (attempt_reconnect(myrpt, l) == -1) {
  5883. l->retrytimer = RETRY_TIMER_MS;
  5884. }
  5885. rpt_mutex_lock(&myrpt->lock);
  5886. break;
  5887. }
  5888. rpt_mutex_lock(&myrpt->lock);
  5889. /* remove from queue */
  5890. remque((struct qelem *) l);
  5891. if (!strcmp(myrpt->cmdnode, l->name))
  5892. myrpt->cmdnode[0] = 0;
  5893. rpt_mutex_unlock(&myrpt->lock);
  5894. if (!l->hasconnected)
  5895. rpt_telemetry(myrpt, CONNFAIL, l);
  5896. else if (l->disced != 2)
  5897. rpt_telemetry(myrpt, REMDISC, l);
  5898. /* hang-up on call to device */
  5899. ast_hangup(l->chan);
  5900. ast_hangup(l->pchan);
  5901. ast_free(l);
  5902. rpt_mutex_lock(&myrpt->lock);
  5903. break;
  5904. }
  5905. if (f->frametype == AST_FRAME_VOICE) {
  5906. if (!l->lastrx) {
  5907. memset(f->data, 0, f->datalen);
  5908. }
  5909. ast_write(l->pchan, f);
  5910. }
  5911. if (f->frametype == AST_FRAME_TEXT) {
  5912. handle_link_data(myrpt, l, f->data);
  5913. }
  5914. if (f->frametype == AST_FRAME_DTMF) {
  5915. handle_link_phone_dtmf(myrpt, l, f->subclass);
  5916. }
  5917. if (f->frametype == AST_FRAME_CONTROL) {
  5918. if (f->subclass == AST_CONTROL_ANSWER) {
  5919. char lconnected = l->connected;
  5920. l->connected = 1;
  5921. l->hasconnected = 1;
  5922. l->elaptime = -1;
  5923. l->retries = 0;
  5924. if (!lconnected)
  5925. rpt_telemetry(myrpt, CONNECTED, l);
  5926. else
  5927. l->reconnects++;
  5928. }
  5929. /* if RX key */
  5930. if (f->subclass == AST_CONTROL_RADIO_KEY) {
  5931. ast_debug(8, "@@@@ rx key\n");
  5932. l->lastrx = 1;
  5933. }
  5934. /* if RX un-key */
  5935. if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
  5936. ast_debug(8, "@@@@ rx un-key\n");
  5937. l->lastrx = 0;
  5938. }
  5939. if (f->subclass == AST_CONTROL_HANGUP) {
  5940. ast_frfree(f);
  5941. if ((!l->outbound) && (!l->disced)) {
  5942. if ((l->name[0] == '0') || l->isremote)
  5943. l->disctime = 1;
  5944. else
  5945. l->disctime = DISC_TIME;
  5946. rpt_mutex_lock(&myrpt->lock);
  5947. ast_hangup(l->chan);
  5948. l->chan = 0;
  5949. break;
  5950. }
  5951. if (l->retrytimer) {
  5952. rpt_mutex_lock(&myrpt->lock);
  5953. break;
  5954. }
  5955. if (l->outbound && (l->retries++ < MAX_RETRIES) && (l->hasconnected)) {
  5956. rpt_mutex_lock(&myrpt->lock);
  5957. ast_hangup(l->chan);
  5958. l->chan = 0;
  5959. rpt_mutex_unlock(&myrpt->lock);
  5960. if (attempt_reconnect(myrpt, l) == -1) {
  5961. l->retrytimer = RETRY_TIMER_MS;
  5962. }
  5963. rpt_mutex_lock(&myrpt->lock);
  5964. break;
  5965. }
  5966. rpt_mutex_lock(&myrpt->lock);
  5967. /* remove from queue */
  5968. remque((struct qelem *) l);
  5969. if (!strcmp(myrpt->cmdnode, l->name))
  5970. myrpt->cmdnode[0] = 0;
  5971. rpt_mutex_unlock(&myrpt->lock);
  5972. if (!l->hasconnected)
  5973. rpt_telemetry(myrpt, CONNFAIL, l);
  5974. else if (l->disced != 2)
  5975. rpt_telemetry(myrpt, REMDISC, l);
  5976. /* hang-up on call to device */
  5977. ast_hangup(l->chan);
  5978. ast_hangup(l->pchan);
  5979. ast_free(l);
  5980. rpt_mutex_lock(&myrpt->lock);
  5981. break;
  5982. }
  5983. }
  5984. ast_frfree(f);
  5985. rpt_mutex_lock(&myrpt->lock);
  5986. break;
  5987. }
  5988. if (who == l->pchan) {
  5989. rpt_mutex_unlock(&myrpt->lock);
  5990. f = ast_read(l->pchan);
  5991. if (!f) {
  5992. ast_debug(1, "@@@@ rpt:Hung Up\n");
  5993. toexit = 1;
  5994. rpt_mutex_lock(&myrpt->lock);
  5995. break;
  5996. }
  5997. if (f->frametype == AST_FRAME_VOICE) {
  5998. if (l->chan)
  5999. ast_write(l->chan, f);
  6000. }
  6001. if (f->frametype == AST_FRAME_CONTROL) {
  6002. if (f->subclass == AST_CONTROL_HANGUP) {
  6003. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6004. ast_frfree(f);
  6005. toexit = 1;
  6006. rpt_mutex_lock(&myrpt->lock);
  6007. break;
  6008. }
  6009. }
  6010. ast_frfree(f);
  6011. rpt_mutex_lock(&myrpt->lock);
  6012. break;
  6013. }
  6014. l = l->next;
  6015. }
  6016. rpt_mutex_unlock(&myrpt->lock);
  6017. if (toexit)
  6018. break;
  6019. if (who == myrpt->txpchannel) { /* if it was a read from remote tx */
  6020. f = ast_read(myrpt->txpchannel);
  6021. if (!f) {
  6022. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6023. break;
  6024. }
  6025. if (f->frametype == AST_FRAME_CONTROL) {
  6026. if (f->subclass == AST_CONTROL_HANGUP) {
  6027. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6028. ast_frfree(f);
  6029. break;
  6030. }
  6031. }
  6032. ast_frfree(f);
  6033. continue;
  6034. }
  6035. }
  6036. usleep(100000);
  6037. ast_hangup(myrpt->pchannel);
  6038. ast_hangup(myrpt->txpchannel);
  6039. if (myrpt->txchannel != myrpt->rxchannel)
  6040. ast_hangup(myrpt->txchannel);
  6041. ast_hangup(myrpt->rxchannel);
  6042. rpt_mutex_lock(&myrpt->lock);
  6043. l = myrpt->links.next;
  6044. while (l != &myrpt->links) {
  6045. struct rpt_link *ll = l;
  6046. /* remove from queue */
  6047. remque((struct qelem *) l);
  6048. /* hang-up on call to device */
  6049. if (l->chan)
  6050. ast_hangup(l->chan);
  6051. ast_hangup(l->pchan);
  6052. l = l->next;
  6053. ast_free(ll);
  6054. }
  6055. rpt_mutex_unlock(&myrpt->lock);
  6056. ast_debug(1, "@@@@ rpt:Hung up channel\n");
  6057. myrpt->rpt_thread = AST_PTHREADT_STOP;
  6058. pthread_exit(NULL);
  6059. return NULL;
  6060. }
  6061. static void *rpt_master(void *config)
  6062. {
  6063. int i, n;
  6064. struct ast_config *cfg;
  6065. char *this;
  6066. const char *val;
  6067. /* go thru all the specified repeaters */
  6068. this = NULL;
  6069. n = 0;
  6070. rpt_vars[n].cfg = config;
  6071. cfg = rpt_vars[n].cfg;
  6072. if (!cfg) {
  6073. ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
  6074. pthread_exit(NULL);
  6075. }
  6076. while ((this = ast_category_browse(cfg, this)) != NULL) {
  6077. for (i = 0; i < strlen(this); i++) {
  6078. if ((this[i] < '0') || (this[i] > '9'))
  6079. break;
  6080. }
  6081. if (i != strlen(this))
  6082. continue; /* Not a node defn */
  6083. memset(&rpt_vars[n], 0, sizeof(rpt_vars[n]));
  6084. rpt_vars[n].name = ast_strdup(this);
  6085. val = ast_variable_retrieve(cfg, this, "rxchannel");
  6086. if (val)
  6087. rpt_vars[n].rxchanname = ast_strdup(val);
  6088. val = ast_variable_retrieve(cfg, this, "txchannel");
  6089. if (val)
  6090. rpt_vars[n].txchanname = ast_strdup(val);
  6091. val = ast_variable_retrieve(cfg, this, "remote");
  6092. if (val)
  6093. rpt_vars[n].remote = ast_strdup(val);
  6094. ast_mutex_init(&rpt_vars[n].lock);
  6095. rpt_vars[n].tele.next = &rpt_vars[n].tele;
  6096. rpt_vars[n].tele.prev = &rpt_vars[n].tele;
  6097. rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
  6098. rpt_vars[n].tailmessagen = 0;
  6099. #ifdef _MDC_DECODE_H_
  6100. rpt_vars[n].mdc = mdc_decoder_new(8000);
  6101. #endif
  6102. n++;
  6103. }
  6104. nrpts = n;
  6105. ast_config_destroy(cfg);
  6106. /* start em all */
  6107. for (i = 0; i < n; i++) {
  6108. load_rpt_vars(i, 1);
  6109. /* if is a remote, dont start one for it */
  6110. if (rpt_vars[i].remote) {
  6111. ast_copy_string(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq));
  6112. ast_copy_string(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl));
  6113. ast_copy_string(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl));
  6114. rpt_vars[i].remmode = REM_MODE_FM;
  6115. rpt_vars[i].offset = REM_SIMPLEX;
  6116. rpt_vars[i].powerlevel = REM_MEDPWR;
  6117. continue;
  6118. }
  6119. if (!rpt_vars[i].p.ident) {
  6120. ast_log(LOG_WARNING, "Did not specify ident for node %s\n", rpt_vars[i].name);
  6121. ast_config_destroy(cfg);
  6122. pthread_exit(NULL);
  6123. }
  6124. ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]);
  6125. }
  6126. usleep(500000);
  6127. for (;;) {
  6128. /* Now monitor each thread, and restart it if necessary */
  6129. for (i = 0; i < n; i++) {
  6130. int rv;
  6131. if (rpt_vars[i].remote)
  6132. continue;
  6133. if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
  6134. rv = -1;
  6135. else
  6136. rv = pthread_kill(rpt_vars[i].rpt_thread, 0);
  6137. if (rv) {
  6138. if (time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15) {
  6139. if (rpt_vars[i].threadrestarts >= 5) {
  6140. ast_log(LOG_ERROR, "Continual RPT thread restarts, killing Asterisk\n");
  6141. ast_cli_command(STDERR_FILENO, "restart now");
  6142. } else {
  6143. ast_log(LOG_NOTICE, "RPT thread restarted on %s\n", rpt_vars[i].name);
  6144. rpt_vars[i].threadrestarts++;
  6145. }
  6146. } else
  6147. rpt_vars[i].threadrestarts = 0;
  6148. rpt_vars[i].lastthreadrestarttime = time(NULL);
  6149. ast_pthread_create_detached(&rpt_vars[i].rpt_thread, NULL, rpt, (void *) &rpt_vars[i]);
  6150. ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
  6151. }
  6152. }
  6153. sleep(2);
  6154. }
  6155. ast_config_destroy(cfg);
  6156. pthread_exit(NULL);
  6157. }
  6158. static int rpt_exec(struct ast_channel *chan, void *data)
  6159. {
  6160. int res = -1, i, rem_totx, n, phone_mode = 0;
  6161. char *tmp, keyed = 0;
  6162. char *options = NULL, *tele, c;
  6163. struct rpt *myrpt;
  6164. struct ast_frame *f;
  6165. struct ast_channel *who;
  6166. struct ast_channel *cs[20];
  6167. struct rpt_link *l;
  6168. struct dahdi_confinfo ci; /* conference info */
  6169. struct dahdi_params par;
  6170. int ms, elap;
  6171. AST_DECLARE_APP_ARGS(args,
  6172. AST_APP_ARG(node);
  6173. AST_APP_ARG(options);
  6174. );
  6175. if (ast_strlen_zero(data)) {
  6176. ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
  6177. return -1;
  6178. }
  6179. tmp = ast_strdupa((char *)data);
  6180. AST_STANDARD_APP_ARGS(args, tmp);
  6181. myrpt = NULL;
  6182. /* see if we can find our specified one */
  6183. for (i = 0; i < nrpts; i++) {
  6184. /* if name matches, assign it and exit loop */
  6185. if (!strcmp(args.node, rpt_vars[i].name)) {
  6186. myrpt = &rpt_vars[i];
  6187. break;
  6188. }
  6189. }
  6190. if (myrpt == NULL) {
  6191. ast_log(LOG_WARNING, "Cannot find specified system node %s\n", args.node);
  6192. return -1;
  6193. }
  6194. /* if not phone access, must be an IAX connection */
  6195. if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R'))) {
  6196. phone_mode = 1;
  6197. if (*options == 'D')
  6198. phone_mode = 2;
  6199. ast_set_callerid(chan, "0", "app_rpt user", "0");
  6200. } else {
  6201. if (strncmp(chan->name, "IAX2", 4)) {
  6202. ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
  6203. return -1;
  6204. }
  6205. }
  6206. if (*args.options == 'R') {
  6207. /* Parts of this section taken from app_parkandannounce */
  6208. int m, lot, timeout = 0;
  6209. char tmp[256];
  6210. char *s;
  6211. AST_DECLARE_APP_ARGS(optionarg,
  6212. AST_APP_ARG(template);
  6213. AST_APP_ARG(timeout);
  6214. AST_APP_ARG(return_context);
  6215. );
  6216. rpt_mutex_lock(&myrpt->lock);
  6217. m = myrpt->callmode;
  6218. rpt_mutex_unlock(&myrpt->lock);
  6219. if ((!myrpt->p.nobusyout) && m) {
  6220. if (chan->_state != AST_STATE_UP) {
  6221. ast_indicate(chan, AST_CONTROL_BUSY);
  6222. }
  6223. while (ast_safe_sleep(chan, 10000) != -1) {
  6224. /* This used to be a busy loop. It's probably better to yield the processor here. */
  6225. usleep(1);
  6226. }
  6227. return -1;
  6228. }
  6229. if (chan->_state != AST_STATE_UP) {
  6230. ast_answer(chan);
  6231. }
  6232. s = ast_strdupa(options);
  6233. AST_STANDARD_APP_ARGS(optionarg, s);
  6234. if (optionarg.argc == 0 || ast_strlen_zero(optionarg.template)) {
  6235. ast_log(LOG_WARNING, "An announce template must be defined\n");
  6236. return -1;
  6237. }
  6238. if (optionarg.argc >= 2) {
  6239. timeout = atoi(optionarg.timeout) * 1000;
  6240. }
  6241. if (!ast_strlen_zero(optionarg.return_context)) {
  6242. if (ast_parseable_goto(chan, optionarg.return_context)) {
  6243. ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
  6244. }
  6245. }
  6246. /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
  6247. before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
  6248. ast_masq_park_call(chan, NULL, timeout, &lot);
  6249. ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, optionarg.return_context);
  6250. snprintf(tmp, sizeof(tmp), "%d,%s", lot, optionarg.template + 1);
  6251. rpt_telemetry(myrpt, REV_PATCH, tmp);
  6252. return 0;
  6253. }
  6254. if (!options) {
  6255. struct ast_hostent ahp;
  6256. struct hostent *hp;
  6257. struct in_addr ia;
  6258. char hisip[100], nodeip[100];
  6259. const char *val;
  6260. char *s, *s1, *s2;
  6261. /* look at callerid to see what node this comes from */
  6262. if (!chan->cid.cid_num) { /* if doesn't have caller id */
  6263. ast_log(LOG_WARNING, "Doesn't have callerid on %s\n", args.node);
  6264. return -1;
  6265. }
  6266. /* get his IP from IAX2 module */
  6267. pbx_substitute_variables_helper(chan, "${IAXPEER(CURRENTCHANNEL)}", hisip, sizeof(hisip) - 1);
  6268. if (ast_strlen_zero(hisip)) {
  6269. ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
  6270. return -1;
  6271. }
  6272. if (!strcmp(myrpt->name, chan->cid.cid_num)) {
  6273. ast_log(LOG_WARNING, "Trying to link to self!!\n");
  6274. return -1;
  6275. }
  6276. if (*(chan->cid.cid_num) < '1') {
  6277. ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n", chan->cid.cid_num);
  6278. return -1;
  6279. }
  6280. /* look for his reported node string */
  6281. val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, chan->cid.cid_num);
  6282. if (!val) {
  6283. ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n", chan->cid.cid_num);
  6284. return -1;
  6285. }
  6286. ast_copy_string(tmp, val, sizeof(tmp));
  6287. s = tmp;
  6288. s1 = strsep(&s, ",");
  6289. s2 = strsep(&s, ",");
  6290. if (!s2) {
  6291. ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n", chan->cid.cid_num);
  6292. return -1;
  6293. }
  6294. if (strcmp(s2, "NONE")) {
  6295. hp = ast_gethostbyname(s2, &ahp);
  6296. if (!hp) {
  6297. ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s2);
  6298. return -1;
  6299. }
  6300. memcpy(&ia, hp->h_addr, sizeof(in_addr_t));
  6301. ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip));
  6302. if (strcmp(hisip, nodeip)) {
  6303. char *s3 = strchr(s1, '@');
  6304. if (s3)
  6305. s1 = s3 + 1;
  6306. s3 = strchr(s1, '/');
  6307. if (s3)
  6308. *s3 = 0;
  6309. hp = ast_gethostbyname(s1, &ahp);
  6310. if (!hp) {
  6311. ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n", chan->cid.cid_num, s1);
  6312. return -1;
  6313. }
  6314. memcpy(&ia, hp->h_addr, sizeof(in_addr_t));
  6315. ast_copy_string(nodeip, ast_inet_ntoa(ia), sizeof(nodeip));
  6316. if (strcmp(hisip, nodeip)) {
  6317. ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n", chan->cid.cid_num, nodeip, hisip);
  6318. return -1;
  6319. }
  6320. }
  6321. }
  6322. }
  6323. /* if is not a remote */
  6324. if (!myrpt->remote) {
  6325. int reconnects = 0;
  6326. /* look at callerid to see what node this comes from */
  6327. if (!chan->cid.cid_num) { /* if doesn't have caller id */
  6328. ast_log(LOG_WARNING, "Doesnt have callerid on %s\n", args.node);
  6329. return -1;
  6330. }
  6331. if (!strcmp(myrpt->name, chan->cid.cid_num)) {
  6332. ast_log(LOG_WARNING, "Trying to link to self!!\n");
  6333. return -1;
  6334. }
  6335. rpt_mutex_lock(&myrpt->lock);
  6336. l = myrpt->links.next;
  6337. /* try to find this one in queue */
  6338. while (l != &myrpt->links) {
  6339. if (l->name[0] == '0') {
  6340. l = l->next;
  6341. continue;
  6342. }
  6343. /* if found matching string */
  6344. if (!strcmp(l->name, chan->cid.cid_num))
  6345. break;
  6346. l = l->next;
  6347. }
  6348. /* if found */
  6349. if (l != &myrpt->links) {
  6350. l->killme = 1;
  6351. l->retries = MAX_RETRIES + 1;
  6352. l->disced = 2;
  6353. reconnects = l->reconnects;
  6354. reconnects++;
  6355. rpt_mutex_unlock(&myrpt->lock);
  6356. usleep(500000);
  6357. } else
  6358. rpt_mutex_unlock(&myrpt->lock);
  6359. /* establish call in tranceive mode */
  6360. l = ast_calloc(1, sizeof(*l));
  6361. if (!l) {
  6362. ast_log(LOG_WARNING, "Unable to malloc\n");
  6363. pthread_exit(NULL);
  6364. }
  6365. l->mode = 1;
  6366. ast_copy_string(l->name, chan->cid.cid_num, sizeof(l->name));
  6367. l->isremote = 0;
  6368. l->chan = chan;
  6369. l->connected = 1;
  6370. l->hasconnected = 1;
  6371. l->reconnects = reconnects;
  6372. l->phonemode = phone_mode;
  6373. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  6374. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  6375. /* allocate a pseudo-channel thru asterisk */
  6376. l->pchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
  6377. if (!l->pchan) {
  6378. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
  6379. pthread_exit(NULL);
  6380. }
  6381. ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
  6382. ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
  6383. /* make a conference for the tx */
  6384. ci.chan = 0;
  6385. ci.confno = myrpt->conf;
  6386. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
  6387. /* first put the channel on the conference in proper mode */
  6388. if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1) {
  6389. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  6390. pthread_exit(NULL);
  6391. }
  6392. rpt_mutex_lock(&myrpt->lock);
  6393. if (phone_mode > 1)
  6394. l->lastrx = 1;
  6395. /* insert at end of queue */
  6396. insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
  6397. rpt_mutex_unlock(&myrpt->lock);
  6398. if (chan->_state != AST_STATE_UP) {
  6399. ast_answer(chan);
  6400. }
  6401. return 0;
  6402. }
  6403. rpt_mutex_lock(&myrpt->lock);
  6404. /* if remote, error if anyone else already linked */
  6405. if (myrpt->remoteon) {
  6406. rpt_mutex_unlock(&myrpt->lock);
  6407. usleep(500000);
  6408. if (myrpt->remoteon) {
  6409. ast_log(LOG_WARNING, "Trying to use busy link on %s\n", args.node);
  6410. return -1;
  6411. }
  6412. rpt_mutex_lock(&myrpt->lock);
  6413. }
  6414. myrpt->remoteon = 1;
  6415. if (ioperm(myrpt->p.iobase, 1, 1) == -1) {
  6416. rpt_mutex_unlock(&myrpt->lock);
  6417. ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n", myrpt->p.iobase);
  6418. return -1;
  6419. }
  6420. rpt_mutex_unlock(&myrpt->lock);
  6421. /* find our index, and load the vars initially */
  6422. for (i = 0; i < nrpts; i++) {
  6423. if (&rpt_vars[i] == myrpt) {
  6424. load_rpt_vars(i, 0);
  6425. break;
  6426. }
  6427. }
  6428. rpt_mutex_lock(&myrpt->lock);
  6429. tele = strchr(myrpt->rxchanname, '/');
  6430. if (!tele) {
  6431. ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
  6432. rpt_mutex_unlock(&myrpt->lock);
  6433. pthread_exit(NULL);
  6434. }
  6435. *tele++ = 0;
  6436. myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, tele, NULL);
  6437. if (myrpt->rxchannel) {
  6438. ast_set_read_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
  6439. ast_set_write_format(myrpt->rxchannel, AST_FORMAT_SLINEAR);
  6440. myrpt->rxchannel->whentohangup = 0;
  6441. myrpt->rxchannel->appl = "Apprpt";
  6442. myrpt->rxchannel->data = "(Link Rx)";
  6443. ast_verb(3, "rpt (Rx) initiating call to %s/%s on %s\n",
  6444. myrpt->rxchanname, tele, myrpt->rxchannel->name);
  6445. rpt_mutex_unlock(&myrpt->lock);
  6446. ast_call(myrpt->rxchannel, tele, 999);
  6447. rpt_mutex_lock(&myrpt->lock);
  6448. } else {
  6449. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Rx channel\n");
  6450. rpt_mutex_unlock(&myrpt->lock);
  6451. pthread_exit(NULL);
  6452. }
  6453. *--tele = '/';
  6454. if (myrpt->txchanname) {
  6455. tele = strchr(myrpt->txchanname, '/');
  6456. if (!tele) {
  6457. ast_log(LOG_ERROR, "rpt:Dial number must be in format tech/number\n");
  6458. rpt_mutex_unlock(&myrpt->lock);
  6459. ast_hangup(myrpt->rxchannel);
  6460. pthread_exit(NULL);
  6461. }
  6462. *tele++ = 0;
  6463. myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, tele, NULL);
  6464. if (myrpt->txchannel) {
  6465. ast_set_read_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
  6466. ast_set_write_format(myrpt->txchannel, AST_FORMAT_SLINEAR);
  6467. myrpt->txchannel->whentohangup = 0;
  6468. myrpt->txchannel->appl = "Apprpt";
  6469. myrpt->txchannel->data = "(Link Tx)";
  6470. ast_verb(3, "rpt (Tx) initiating call to %s/%s on %s\n",
  6471. myrpt->txchanname, tele, myrpt->txchannel->name);
  6472. rpt_mutex_unlock(&myrpt->lock);
  6473. ast_call(myrpt->txchannel, tele, 999);
  6474. rpt_mutex_lock(&myrpt->lock);
  6475. } else {
  6476. ast_log(LOG_ERROR, "rpt:Sorry unable to obtain Tx channel\n");
  6477. rpt_mutex_unlock(&myrpt->lock);
  6478. ast_hangup(myrpt->rxchannel);
  6479. pthread_exit(NULL);
  6480. }
  6481. *--tele = '/';
  6482. } else {
  6483. myrpt->txchannel = myrpt->rxchannel;
  6484. }
  6485. myrpt->remoterx = 0;
  6486. myrpt->remotetx = 0;
  6487. myrpt->retxtimer = 0;
  6488. myrpt->remoteon = 1;
  6489. myrpt->dtmfidx = -1;
  6490. myrpt->dtmfbuf[0] = 0;
  6491. myrpt->dtmf_time_rem = 0;
  6492. myrpt->hfscanmode = 0;
  6493. myrpt->hfscanstatus = 0;
  6494. if (myrpt->p.startupmacro) {
  6495. myrpt->remchannel = chan; /* Save copy of channel */
  6496. snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
  6497. }
  6498. if (myrpt->p.startupgosub) {
  6499. myrpt->remchannel = chan; /* Save copy of channel */
  6500. snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
  6501. }
  6502. myrpt->reload = 0;
  6503. rpt_mutex_unlock(&myrpt->lock);
  6504. setrem(myrpt);
  6505. ast_set_write_format(chan, AST_FORMAT_SLINEAR);
  6506. ast_set_read_format(chan, AST_FORMAT_SLINEAR);
  6507. /* if we are on 2w loop and are a remote, turn EC on */
  6508. if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel)) {
  6509. i = 128;
  6510. ioctl(myrpt->rxchannel->fds[0], DAHDI_ECHOCANCEL, &i);
  6511. }
  6512. if (chan->_state != AST_STATE_UP) {
  6513. ast_answer(chan);
  6514. }
  6515. if (ioctl(myrpt->txchannel->fds[0], DAHDI_GET_PARAMS, &par) != -1) {
  6516. if (par.rxisoffhook) {
  6517. ast_indicate(chan, AST_CONTROL_RADIO_KEY);
  6518. myrpt->remoterx = 1;
  6519. }
  6520. }
  6521. n = 0;
  6522. cs[n++] = chan;
  6523. cs[n++] = myrpt->rxchannel;
  6524. if (myrpt->rxchannel != myrpt->txchannel)
  6525. cs[n++] = myrpt->txchannel;
  6526. for (;;) {
  6527. if (ast_check_hangup(chan))
  6528. break;
  6529. if (ast_check_hangup(myrpt->rxchannel))
  6530. break;
  6531. if (myrpt->reload) {
  6532. myrpt->reload = 0;
  6533. rpt_mutex_unlock(&myrpt->lock);
  6534. /* find our index, and load the vars */
  6535. for (i = 0; i < nrpts; i++) {
  6536. if (&rpt_vars[i] == myrpt) {
  6537. load_rpt_vars(i, 0);
  6538. break;
  6539. }
  6540. }
  6541. rpt_mutex_lock(&myrpt->lock);
  6542. }
  6543. ms = MSWAIT;
  6544. who = ast_waitfor_n(cs, n, &ms);
  6545. if (who == NULL)
  6546. ms = 0;
  6547. elap = MSWAIT - ms;
  6548. if (myrpt->macrotimer)
  6549. myrpt->macrotimer -= elap;
  6550. if (myrpt->macrotimer < 0)
  6551. myrpt->macrotimer = 0;
  6552. if (myrpt->gosubtimer)
  6553. myrpt->gosubtimer -= elap;
  6554. if (myrpt->gosubtimer < 0)
  6555. myrpt->gosubtimer = 0;
  6556. rpt_mutex_unlock(&myrpt->lock);
  6557. if (!ms)
  6558. continue;
  6559. rem_totx = keyed;
  6560. if ((!myrpt->remoterx) && (!myrpt->remotetx)) {
  6561. if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME) {
  6562. myrpt->retxtimer = 0;
  6563. ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
  6564. }
  6565. } else
  6566. myrpt->retxtimer = 0;
  6567. if (rem_totx && (!myrpt->remotetx)) { /* Remote base radio TX key */
  6568. myrpt->remotetx = 1;
  6569. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_KEY);
  6570. }
  6571. if ((!rem_totx) && myrpt->remotetx) { /* Remote base radio TX unkey */
  6572. myrpt->remotetx = 0;
  6573. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  6574. }
  6575. if (myrpt->tunerequest && (!strcmp(myrpt->remote, remote_rig_ft897))) { /* ft-897 specific for now... */
  6576. myrpt->tunerequest = 0;
  6577. set_mode_ft897(myrpt, REM_MODE_AM);
  6578. simple_command_ft897(myrpt, 8);
  6579. myrpt->remotetx = 0;
  6580. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  6581. if (!myrpt->remoterx)
  6582. ast_indicate(chan, AST_CONTROL_RADIO_KEY);
  6583. if (play_tone(chan, 800, 6000, 8192) == -1)
  6584. break;
  6585. rmt_telem_finish(myrpt, chan);
  6586. set_mode_ft897(myrpt, 0x88);
  6587. setrem(myrpt);
  6588. }
  6589. if (myrpt->hfscanmode) {
  6590. myrpt->scantimer -= elap;
  6591. if (myrpt->scantimer <= 0) {
  6592. myrpt->scantimer = REM_SCANTIME;
  6593. service_scan(myrpt);
  6594. }
  6595. }
  6596. if (who == chan) { /* if it was a read from incoming */
  6597. f = ast_read(chan);
  6598. if (!f) {
  6599. ast_debug(1, "@@@@ link:Hung Up\n");
  6600. break;
  6601. }
  6602. if (f->frametype == AST_FRAME_VOICE) {
  6603. /* if not transmitting, zero-out audio */
  6604. if (!myrpt->remotetx)
  6605. memset(f->data, 0, f->datalen);
  6606. ast_write(myrpt->txchannel, f);
  6607. }
  6608. if (f->frametype == AST_FRAME_DTMF) {
  6609. myrpt->remchannel = chan; /* Save copy of channel */
  6610. if (handle_remote_phone_dtmf(myrpt, f->subclass, &keyed, phone_mode) == -1) {
  6611. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6612. ast_frfree(f);
  6613. break;
  6614. }
  6615. }
  6616. if (f->frametype == AST_FRAME_TEXT) {
  6617. myrpt->remchannel = chan; /* Save copy of channel */
  6618. if (handle_remote_data(myrpt, f->data) == -1) {
  6619. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6620. ast_frfree(f);
  6621. break;
  6622. }
  6623. }
  6624. if (f->frametype == AST_FRAME_CONTROL) {
  6625. if (f->subclass == AST_CONTROL_HANGUP) {
  6626. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6627. ast_frfree(f);
  6628. break;
  6629. }
  6630. /* if RX key */
  6631. if (f->subclass == AST_CONTROL_RADIO_KEY) {
  6632. ast_debug(8, "@@@@ rx key\n");
  6633. keyed = 1;
  6634. }
  6635. /* if RX un-key */
  6636. if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
  6637. ast_debug(8, "@@@@ rx un-key\n");
  6638. keyed = 0;
  6639. }
  6640. }
  6641. if (myrpt->hfscanstatus) {
  6642. myrpt->remchannel = chan; /* Save copy of channel */
  6643. myrpt->remotetx = 0;
  6644. ast_indicate(myrpt->txchannel, AST_CONTROL_RADIO_UNKEY);
  6645. if (!myrpt->remoterx) {
  6646. ast_indicate(myrpt->remchannel, AST_CONTROL_RADIO_KEY);
  6647. }
  6648. if (myrpt->hfscanstatus < 0) {
  6649. if (myrpt->hfscanstatus == -1) {
  6650. if (ast_safe_sleep(myrpt->remchannel, 1000) == -1)
  6651. break;
  6652. }
  6653. sayfile(myrpt->remchannel, "rpt/stop");
  6654. } else {
  6655. saynum(myrpt->remchannel, myrpt->hfscanstatus );
  6656. }
  6657. rmt_telem_finish(myrpt, myrpt->remchannel);
  6658. myrpt->hfscanstatus = 0;
  6659. }
  6660. ast_frfree(f);
  6661. rpt_mutex_lock(&myrpt->lock);
  6662. c = myrpt->macrobuf[0];
  6663. if (c && (!myrpt->macrotimer)) {
  6664. myrpt->macrotimer = MACROTIME;
  6665. memmove(myrpt->macrobuf, myrpt->macrobuf + 1, sizeof(myrpt->macrobuf) - 1);
  6666. if ((c == 'p') || (c == 'P'))
  6667. myrpt->macrotimer = MACROPTIME;
  6668. rpt_mutex_unlock(&myrpt->lock);
  6669. if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
  6670. break;
  6671. continue;
  6672. }
  6673. c = myrpt->gosubbuf[0];
  6674. if (c && (!myrpt->gosubtimer)) {
  6675. myrpt->gosubtimer = GOSUBTIME;
  6676. memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
  6677. if ((c == 'p') || (c == 'P'))
  6678. myrpt->gosubtimer = GOSUBPTIME;
  6679. rpt_mutex_unlock(&myrpt->lock);
  6680. if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
  6681. break;
  6682. continue;
  6683. }
  6684. rpt_mutex_unlock(&myrpt->lock);
  6685. continue;
  6686. }
  6687. if (who == myrpt->rxchannel) { /* if it was a read from radio */
  6688. f = ast_read(myrpt->rxchannel);
  6689. if (!f) {
  6690. ast_debug(1, "@@@@ link:Hung Up\n");
  6691. break;
  6692. }
  6693. if (f->frametype == AST_FRAME_VOICE) {
  6694. if ((myrpt->remote) && (myrpt->remotetx))
  6695. memset(f->data, 0, f->datalen);
  6696. ast_write(chan, f);
  6697. } else if (f->frametype == AST_FRAME_CONTROL) {
  6698. if (f->subclass == AST_CONTROL_HANGUP) {
  6699. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6700. ast_frfree(f);
  6701. break;
  6702. }
  6703. /* if RX key */
  6704. if (f->subclass == AST_CONTROL_RADIO_KEY) {
  6705. ast_debug(8, "@@@@ remote rx key\n");
  6706. if (!myrpt->remotetx) {
  6707. ast_indicate(chan, AST_CONTROL_RADIO_KEY);
  6708. myrpt->remoterx = 1;
  6709. }
  6710. }
  6711. /* if RX un-key */
  6712. if (f->subclass == AST_CONTROL_RADIO_UNKEY) {
  6713. ast_debug(8, "@@@@ remote rx un-key\n");
  6714. if (!myrpt->remotetx) {
  6715. ast_indicate(chan, AST_CONTROL_RADIO_UNKEY);
  6716. myrpt->remoterx = 0;
  6717. }
  6718. }
  6719. }
  6720. ast_frfree(f);
  6721. continue;
  6722. }
  6723. if ((myrpt->rxchannel != myrpt->txchannel) && (who == myrpt->txchannel)) {
  6724. /* do this cuz you have to */
  6725. f = ast_read(myrpt->txchannel);
  6726. if (!f) {
  6727. ast_debug(1, "@@@@ link:Hung Up\n");
  6728. break;
  6729. }
  6730. if (f->frametype == AST_FRAME_CONTROL) {
  6731. if (f->subclass == AST_CONTROL_HANGUP) {
  6732. ast_debug(1, "@@@@ rpt:Hung Up\n");
  6733. ast_frfree(f);
  6734. break;
  6735. }
  6736. }
  6737. ast_frfree(f);
  6738. continue;
  6739. }
  6740. }
  6741. rpt_mutex_lock(&myrpt->lock);
  6742. if (myrpt->rxchannel != myrpt->txchannel)
  6743. ast_hangup(myrpt->txchannel);
  6744. ast_hangup(myrpt->rxchannel);
  6745. myrpt->hfscanmode = 0;
  6746. myrpt->hfscanstatus = 0;
  6747. myrpt->remoteon = 0;
  6748. rpt_mutex_unlock(&myrpt->lock);
  6749. closerem(myrpt);
  6750. return res;
  6751. }
  6752. static int unload_module(void)
  6753. {
  6754. int i;
  6755. for (i = 0; i < nrpts; i++) {
  6756. if (!strcmp(rpt_vars[i].name, rpt_vars[i].p.nodes))
  6757. continue;
  6758. ast_mutex_destroy(&rpt_vars[i].lock);
  6759. }
  6760. i = ast_unregister_application(app);
  6761. /* Unregister cli extensions */
  6762. ast_cli_unregister_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
  6763. return i;
  6764. }
  6765. static int load_module(void)
  6766. {
  6767. struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
  6768. struct ast_config *cfg = ast_config_load("rpt.conf", config_flags);
  6769. if (!cfg) {
  6770. ast_log(LOG_WARNING, "No such configuration file rpt.conf\n");
  6771. return AST_MODULE_LOAD_DECLINE;
  6772. }
  6773. ast_pthread_create(&rpt_master_thread, NULL, rpt_master, cfg);
  6774. /* Register cli extensions */
  6775. ast_cli_register_multiple(cli_rpt, sizeof(cli_rpt) / sizeof(struct ast_cli_entry));
  6776. return ast_register_application(app, rpt_exec, synopsis, descrip);
  6777. }
  6778. static int reload(void)
  6779. {
  6780. int n;
  6781. for (n = 0; n < nrpts; n++)
  6782. rpt_vars[n].reload = 1;
  6783. return(0);
  6784. }
  6785. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater / Remote Base",
  6786. .load = load_module,
  6787. .unload = unload_module,
  6788. .reload = reload,
  6789. );