app_rpt.c 389 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195
  1. #define NEW_ASTERISK
  2. /* #define OLD_ASTERISK */
  3. /*
  4. * Asterisk -- An open source telephony toolkit.
  5. *
  6. * Copyright (C) 2002-2008, Jim Dixon, WB6NIL
  7. *
  8. * Jim Dixon, WB6NIL <jim@lambdatel.com>
  9. * Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
  10. *
  11. * See http://www.asterisk.org for more information about
  12. * the Asterisk project. Please do not directly contact
  13. * any of the maintainers of this project for assistance;
  14. * the project provides a web site, mailing lists and IRC
  15. * channels for your use.
  16. *
  17. * This program is free software, distributed under the terms of
  18. * the GNU General Public License Version 2. See the LICENSE file
  19. * at the top of the source tree.
  20. */
  21. /*! \file
  22. *
  23. * \brief Radio Repeater / Remote Base program
  24. * version 0.115 5/12/08 2055 EDT
  25. *
  26. * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
  27. *
  28. * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
  29. * \note Steven Henke, W9SH, <w9sh@arrl.net> added a few features here and there.
  30. *
  31. * See http://www.zapatatelephony.org/app_rpt.html
  32. *
  33. *
  34. * Repeater / Remote Functions:
  35. * "Simple" Mode: * - autopatch access, # - autopatch hangup
  36. * Normal mode:
  37. * See the function list in rpt.conf (autopatchup, autopatchdn)
  38. * autopatchup can optionally take comma delimited setting=value pairs:
  39. *
  40. *
  41. * context=string : Override default context with "string"
  42. * dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)
  43. * farenddisconnect=1 : Automatically disconnect when called party hangs up
  44. * noct=1 : Don't send repeater courtesy tone during autopatch calls
  45. * quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
  46. *
  47. *
  48. * Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
  49. *
  50. * To send an asterisk (*) while dialing or talking on phone,
  51. * use the autopatch acess code.
  52. *
  53. *
  54. * status cmds:
  55. *
  56. * 1 - Force ID (global)
  57. * 2 - Give Time of Day (global)
  58. * 3 - Give software Version (global)
  59. * 11 - Force ID (local only)
  60. * 12 - Give Time of Day (local only)
  61. *
  62. * cop (control operator) cmds:
  63. *
  64. * 1 - System warm boot
  65. * 2 - System enable
  66. * 3 - System disable
  67. * 4 - Test Tone On/Off
  68. * 5 - Dump System Variables on Console (debug)
  69. * 6 - PTT (phone mode only)
  70. * 7 - Time out timer enable
  71. * 8 - Time out timer disable
  72. * 9 - Autopatch enable
  73. * 10 - Autopatch disable
  74. * 11 - Link enable
  75. * 12 - Link disable
  76. * 13 - Query System State
  77. * 14 - Change System State
  78. * 15 - Scheduler Enable
  79. * 16 - Scheduler Disable
  80. * 17 - User functions (time, id, etc) enable
  81. * 18 - User functions (time, id, etc) disable
  82. * 19 - Select alternate hang timer
  83. * 20 - Select standard hang timer
  84. * 21 - Enable Parrot Mode
  85. * 22 - Disable Parrot Mode
  86. * 23 - Birdbath (Current Parrot Cleanup/Flush)
  87. * 24 - Flush all telemetry
  88. * 25 - Query last node un-keyed
  89. * 26 - Query all nodes keyed/unkeyed
  90. * 30 - Recall Memory Setting in Attached Xcvr
  91. * 31 - Channel Selector for Parallel Programmed Xcvr
  92. * 32 - Touchtone pad test: command + Digit string + # to playback all digits pressed
  93. *
  94. * ilink cmds:
  95. *
  96. * 1 - Disconnect specified link
  97. * 2 - Connect specified link -- monitor only
  98. * 3 - Connect specified link -- tranceive
  99. * 4 - Enter command mode on specified link
  100. * 5 - System status
  101. * 6 - Disconnect all links
  102. * 11 - Disconnect a previously permanently connected link
  103. * 12 - Permanently connect specified link -- monitor only
  104. * 13 - Permanently connect specified link -- tranceive
  105. * 15 - Full system status (all nodes)
  106. * 16 - Reconnect links disconnected with "disconnect all links"
  107. * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
  108. *
  109. * remote cmds:
  110. *
  111. * 1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
  112. * 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
  113. * 3 - Set Rx PL Tone HHH*D*
  114. * 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
  115. * 5 - Link Status (long)
  116. * 6 - Set operating mode M (FM, USB, LSB, AM, etc)
  117. * 100 - RX PL off (Default)
  118. * 101 - RX PL On
  119. * 102 - TX PL Off (Default)
  120. * 103 - TX PL On
  121. * 104 - Low Power
  122. * 105 - Med Power
  123. * 106 - Hi Power
  124. * 107 - Bump Down 20 Hz
  125. * 108 - Bump Down 100 Hz
  126. * 109 - Bump Down 500 Hz
  127. * 110 - Bump Up 20 Hz
  128. * 111 - Bump Up 100 Hz
  129. * 112 - Bump Up 500 Hz
  130. * 113 - Scan Down Slow
  131. * 114 - Scan Down Medium
  132. * 115 - Scan Down Fast
  133. * 116 - Scan Up Slow
  134. * 117 - Scan Up Medium
  135. * 118 - Scan Up Fast
  136. * 119 - Transmit allowing auto-tune
  137. * 140 - Link Status (brief)
  138. * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
  139. *
  140. * playback cmds:
  141. * specify the name of the file to be played (for example, 25=rpt/foo)
  142. *
  143. *
  144. * 'duplex' modes: (defaults to duplex=2)
  145. *
  146. * 0 - Only remote links key Tx and no main repeat audio.
  147. * 1 - Everything other then main Rx keys Tx, no main repeat audio.
  148. * 2 - Normal mode
  149. * 3 - Normal except no main repeat audio.
  150. * 4 - Normal except no main repeat audio during autopatch only
  151. *
  152. */
  153. /*** MODULEINFO
  154. <depend>dahdi</depend>
  155. <depend>tonezone</depend>
  156. <defaultenabled>no</defaultenabled>
  157. <support_level>extended</support_level>
  158. ***/
  159. /* Un-comment the following to include support for MDC-1200 digital tone
  160. signalling protocol (using KA6SQG's GPL'ed implementation) */
  161. /* #include "mdc_decode.c" */
  162. /* Un-comment the following to include support for notch filters in the
  163. rx audio stream (using Tony Fisher's mknotch (mkfilter) implementation) */
  164. /* #include "rpt_notch.c" */
  165. /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
  166. #ifdef OLD_ASTERISK
  167. #define ast_free free
  168. #define ast_malloc malloc
  169. #define ast_strdup strdup
  170. #endif
  171. #define MAXDTMF 32
  172. #define MAXMACRO 2048
  173. #define MAXLINKLIST 512
  174. #define LINKLISTTIME 10000
  175. #define LINKLISTSHORTTIME 200
  176. #define LINKPOSTTIME 30000
  177. #define LINKPOSTSHORTTIME 200
  178. #define KEYPOSTTIME 30000
  179. #define KEYPOSTSHORTTIME 200
  180. #define MACROTIME 100
  181. #define MACROPTIME 500
  182. #define DTMF_TIMEOUT 3
  183. #define KENWOOD_RETRIES 5
  184. #define TOPKEYN 32
  185. #define TOPKEYWAIT 3
  186. #define TOPKEYMAXSTR 30
  187. #define AUTHTELLTIME 7000
  188. #define AUTHTXTIME 1000
  189. #define AUTHLOGOUTTIME 25000
  190. #ifdef __RPT_NOTCH
  191. #define MAXFILTERS 10
  192. #endif
  193. #define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
  194. #define MAX_RETRIES 5
  195. #define MAX_RETRIES_PERM 1000000000
  196. #define REDUNDANT_TX_TIME 2000
  197. #define RETRY_TIMER_MS 5000
  198. #define PATCH_DIALPLAN_TIMEOUT 1500
  199. #ifdef OLD_ASTERISK
  200. #define START_DELAY 10
  201. #else
  202. #define START_DELAY 2
  203. #endif
  204. #define RPT_LOCKOUT_SECS 10
  205. #define MAXPEERSTR 31
  206. #define MAXREMSTR 15
  207. #define DELIMCHR ','
  208. #define QUOTECHR 34
  209. #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
  210. #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
  211. #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
  212. #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
  213. #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
  214. #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
  215. #define NODES "nodes"
  216. #define EXTNODES "extnodes"
  217. #define MEMORY "memory"
  218. #define MACRO "macro"
  219. #define FUNCTIONS "functions"
  220. #define TELEMETRY "telemetry"
  221. #define MORSE "morse"
  222. #define TONEMACRO "tonemacro"
  223. #define FUNCCHAR '*'
  224. #define ENDCHAR '#'
  225. #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
  226. #define NODENAMES "rpt/nodenames"
  227. #define PARROTFILE "/tmp/parrot_%s_%u"
  228. #define PARROTTIME 1000
  229. #define DEFAULT_IOBASE 0x378
  230. #define DEFAULT_CIV_ADDR 0x58
  231. #define MAXCONNECTTIME 5000
  232. #define MAXNODESTR 300
  233. #define MAXNODELEN 16
  234. #define MAXIDENTLEN 32
  235. #define MAXPATCHCONTEXT 100
  236. #define ACTIONSIZE 32
  237. #define TELEPARAMSIZE 256
  238. #define REM_SCANTIME 100
  239. #define DTMF_LOCAL_TIME 250
  240. #define DTMF_LOCAL_STARTTIME 500
  241. #define IC706_PL_MEMORY_OFFSET 50
  242. #define VOX_ON_DEBOUNCE_COUNT 3
  243. #define VOX_OFF_DEBOUNCE_COUNT 20
  244. #define VOX_MAX_THRESHOLD 10000.0
  245. #define VOX_MIN_THRESHOLD 3000.0
  246. #define VOX_TIMEOUT_MS 5000
  247. #define VOX_RECOVER_MS 500
  248. #define SIMPLEX_PATCH_DELAY 25
  249. #define SIMPLEX_PHONE_DELAY 25
  250. #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
  251. #define ALLOW_LOCAL_CHANNELS
  252. enum {REM_OFF,REM_MONITOR,REM_TX};
  253. enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
  254. CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
  255. STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
  256. TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
  257. MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
  258. REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
  259. TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
  260. STATS_TIME_LOCAL};
  261. enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
  262. enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
  263. enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
  264. enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
  265. enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
  266. enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
  267. enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
  268. HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
  269. #include "asterisk.h"
  270. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  271. #include <signal.h>
  272. #include <stdio.h>
  273. #include <stdint.h>
  274. #include <unistd.h>
  275. #include <string.h>
  276. #include <stdlib.h>
  277. #include <search.h>
  278. #include <sys/types.h>
  279. #include <sys/stat.h>
  280. #include <errno.h>
  281. #include <dirent.h>
  282. #include <ctype.h>
  283. #include <sys/stat.h>
  284. #include <sys/time.h>
  285. #include <sys/file.h>
  286. #include <sys/ioctl.h>
  287. #ifdef HAVE_SYS_IO_H
  288. #include <sys/io.h>
  289. #endif
  290. #include <sys/vfs.h>
  291. #include <math.h>
  292. #include <dahdi/user.h>
  293. #include <dahdi/tonezone.h>
  294. #include <netinet/in.h>
  295. #include <arpa/inet.h>
  296. #include "asterisk/utils.h"
  297. #include "asterisk/lock.h"
  298. #include "asterisk/file.h"
  299. #include "asterisk/logger.h"
  300. #include "asterisk/channel.h"
  301. #include "asterisk/callerid.h"
  302. #include "asterisk/pbx.h"
  303. #include "asterisk/module.h"
  304. #include "asterisk/translate.h"
  305. #include "asterisk/features.h"
  306. #include "asterisk/options.h"
  307. #include "asterisk/cli.h"
  308. #include "asterisk/config.h"
  309. #include "asterisk/say.h"
  310. #include "asterisk/localtime.h"
  311. #include "asterisk/cdr.h"
  312. #include "asterisk/options.h"
  313. #include "asterisk/manager.h"
  314. #include "asterisk/app.h"
  315. #include <termios.h>
  316. #ifdef NEW_ASTERISK
  317. struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
  318. #endif
  319. /* Start a tone-list going */
  320. int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
  321. /*! Stop the tones from playing */
  322. void ast_playtones_stop(struct ast_channel *chan);
  323. static char *tdesc = "Radio Repeater / Remote Base version 0.115 5/12/2008";
  324. static char *app = "Rpt";
  325. static char *synopsis = "Radio Repeater/Remote Base Control System";
  326. static char *descrip =
  327. " Rpt(nodename[|options][|M][|*]): \n"
  328. " Radio Remote Link or Remote Base Link Endpoint Process.\n"
  329. "\n"
  330. " Not specifying an option puts it in normal endpoint mode (where source\n"
  331. " IP and nodename are verified).\n"
  332. "\n"
  333. " Options are as follows:\n"
  334. "\n"
  335. " X - Normal endpoint mode WITHOUT security check. Only specify\n"
  336. " this if you have checked security already (like with an IAX2\n"
  337. " user/password or something).\n"
  338. "\n"
  339. " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
  340. " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
  341. " specified by the 'announce-string') is played on radio system.\n"
  342. " Users of radio system can access autopatch, dial specified\n"
  343. " code, and pick up call. Announce-string is list of names of\n"
  344. " recordings, or \"PARKED\" to substitute code for un-parking,\n"
  345. " or \"NODE\" to substitute node number.\n"
  346. "\n"
  347. " P - Phone Control mode. This allows a regular phone user to have\n"
  348. " full control and audio access to the radio system. For the\n"
  349. " user to have DTMF control, the 'phone_functions' parameter\n"
  350. " must be specified for the node in 'rpt.conf'. An additional\n"
  351. " function (cop,6) must be listed so that PTT control is available.\n"
  352. "\n"
  353. " D - Dumb Phone Control mode. This allows a regular phone user to\n"
  354. " have full control and audio access to the radio system. In this\n"
  355. " mode, the PTT is activated for the entire length of the call.\n"
  356. " For the user to have DTMF control (not generally recomended in\n"
  357. " this mode), the 'dphone_functions' parameter must be specified\n"
  358. " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
  359. " available to the phone user.\n"
  360. "\n"
  361. " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
  362. " audio-only access to the radio system. In this mode, the\n"
  363. " transmitter is toggled on and off when the phone user presses the\n"
  364. " funcchar (*) key on the telephone set. In addition, the transmitter\n"
  365. " will turn off if the endchar (#) key is pressed. When a user first\n"
  366. " calls in, the transmitter will be off, and the user can listen for\n"
  367. " radio traffic. When the user wants to transmit, they press the *\n"
  368. " key, start talking, then press the * key again or the # key to turn\n"
  369. " the transmitter off. No other functions can be executed by the\n"
  370. " user on the phone when this mode is selected. Note: If your\n"
  371. " radio system is full-duplex, we recommend using either P or D\n"
  372. " modes as they provide more flexibility.\n"
  373. "\n"
  374. " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
  375. "\n"
  376. " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
  377. "\n"
  378. " * - Alt Macro to execute (e.g. *7 for status)\n"
  379. "\n";
  380. ;
  381. static int debug = 0; /* Set this >0 for extra debug output */
  382. static int nrpts = 0;
  383. static const char remdtmfstr[] = "0123456789*#ABCD";
  384. enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
  385. int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
  386. #define NRPTSTAT 7
  387. struct rpt_chan_stat
  388. {
  389. struct timeval last;
  390. long long total;
  391. unsigned long count;
  392. unsigned long largest;
  393. struct timeval largest_time;
  394. };
  395. char *discstr = "!!DISCONNECT!!";
  396. char *newkeystr = "!NEWKEY!";
  397. static char *remote_rig_ft897="ft897";
  398. static char *remote_rig_rbi="rbi";
  399. static char *remote_rig_kenwood="kenwood";
  400. static char *remote_rig_tm271="tm271";
  401. static char *remote_rig_ic706="ic706";
  402. static char *remote_rig_rtx150="rtx150";
  403. static char *remote_rig_rtx450="rtx450";
  404. static char *remote_rig_ppp16="ppp16"; // parallel port programmable 16 channels
  405. #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
  406. #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
  407. #ifdef OLD_ASTERISK
  408. STANDARD_LOCAL_USER;
  409. LOCAL_USER_DECL;
  410. #endif
  411. #define MSWAIT 200
  412. #define HANGTIME 5000
  413. #define TOTIME 180000
  414. #define IDTIME 300000
  415. #define MAXRPTS 20
  416. #define MAX_STAT_LINKS 32
  417. #define POLITEID 30000
  418. #define FUNCTDELAY 1500
  419. #define MAXXLAT 20
  420. #define MAXXLATTIME 3
  421. #define MAX_SYSSTATES 10
  422. struct vox {
  423. float speech_energy;
  424. float noise_energy;
  425. int enacount;
  426. char voxena;
  427. char lastvox;
  428. int offdebcnt;
  429. int ondebcnt;
  430. } ;
  431. #define mymax(x,y) ((x > y) ? x : y)
  432. #define mymin(x,y) ((x < y) ? x : y)
  433. struct rpt_topkey
  434. {
  435. char node[TOPKEYMAXSTR];
  436. int timesince;
  437. int keyed;
  438. } ;
  439. struct rpt_xlat
  440. {
  441. char funccharseq[MAXXLAT];
  442. char endcharseq[MAXXLAT];
  443. char passchars[MAXXLAT];
  444. int funcindex;
  445. int endindex;
  446. time_t lastone;
  447. } ;
  448. static time_t starttime = 0;
  449. static pthread_t rpt_master_thread;
  450. struct rpt;
  451. struct rpt_link
  452. {
  453. struct rpt_link *next;
  454. struct rpt_link *prev;
  455. char mode; /* 1 if in tx mode */
  456. char isremote;
  457. char phonemode;
  458. char phonevox; /* vox the phone */
  459. char name[MAXNODESTR]; /* identifier (routing) string */
  460. char lasttx;
  461. char lasttx1;
  462. char lastrx;
  463. char lastrealrx;
  464. char lastrx1;
  465. char connected;
  466. char hasconnected;
  467. char perma;
  468. char thisconnected;
  469. char outbound;
  470. char disced;
  471. char killme;
  472. long elaptime;
  473. long disctime;
  474. long retrytimer;
  475. long retxtimer;
  476. long rerxtimer;
  477. int retries;
  478. int max_retries;
  479. int reconnects;
  480. long long connecttime;
  481. struct ast_channel *chan;
  482. struct ast_channel *pchan;
  483. char linklist[MAXLINKLIST];
  484. time_t linklistreceived;
  485. long linklisttimer;
  486. int dtmfed;
  487. int linkunkeytocttimer;
  488. struct timeval lastlinktv;
  489. struct ast_frame *lastf1,*lastf2;
  490. struct rpt_chan_stat chan_stat[NRPTSTAT];
  491. struct vox vox;
  492. char wasvox;
  493. int voxtotimer;
  494. char voxtostate;
  495. char newkey;
  496. #ifdef OLD_ASTERISK
  497. AST_LIST_HEAD(, ast_frame) rxq;
  498. #else
  499. AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
  500. #endif
  501. } ;
  502. struct rpt_lstat
  503. {
  504. struct rpt_lstat *next;
  505. struct rpt_lstat *prev;
  506. char peer[MAXPEERSTR];
  507. char name[MAXNODESTR];
  508. char mode;
  509. char outbound;
  510. char reconnects;
  511. char thisconnected;
  512. long long connecttime;
  513. struct rpt_chan_stat chan_stat[NRPTSTAT];
  514. } ;
  515. struct rpt_tele
  516. {
  517. struct rpt_tele *next;
  518. struct rpt_tele *prev;
  519. struct rpt *rpt;
  520. struct ast_channel *chan;
  521. int mode;
  522. struct rpt_link mylink;
  523. char param[TELEPARAMSIZE];
  524. intptr_t submode;
  525. uintptr_t parrot;
  526. pthread_t threadid;
  527. } ;
  528. struct function_table_tag
  529. {
  530. char action[ACTIONSIZE];
  531. int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
  532. int command_source, struct rpt_link *mylink);
  533. } ;
  534. /* Used to store the morse code patterns */
  535. struct morse_bits
  536. {
  537. int len;
  538. int ddcomb;
  539. } ;
  540. struct telem_defaults
  541. {
  542. char name[20];
  543. char value[80];
  544. } ;
  545. struct sysstate
  546. {
  547. char txdisable;
  548. char totdisable;
  549. char linkfundisable;
  550. char autopatchdisable;
  551. char schedulerdisable;
  552. char userfundisable;
  553. char alternatetail;
  554. };
  555. /* rpt cmd support */
  556. #define CMD_DEPTH 1
  557. #define CMD_STATE_IDLE 0
  558. #define CMD_STATE_BUSY 1
  559. #define CMD_STATE_READY 2
  560. #define CMD_STATE_EXECUTING 3
  561. struct rpt_cmd_struct
  562. {
  563. int state;
  564. int functionNumber;
  565. char param[MAXDTMF];
  566. char digits[MAXDTMF];
  567. int command_source;
  568. };
  569. static struct rpt
  570. {
  571. ast_mutex_t lock;
  572. ast_mutex_t remlock;
  573. ast_mutex_t statpost_lock;
  574. struct ast_config *cfg;
  575. char reload;
  576. char xlink; // cross link state of a share repeater/remote radio
  577. unsigned int statpost_seqno;
  578. char *name;
  579. char *rxchanname;
  580. char *txchanname;
  581. char remote;
  582. char *remoterig;
  583. struct rpt_chan_stat chan_stat[NRPTSTAT];
  584. unsigned int scram;
  585. struct {
  586. char *ourcontext;
  587. char *ourcallerid;
  588. char *acctcode;
  589. char *ident;
  590. char *tonezone;
  591. char simple;
  592. char *functions;
  593. char *link_functions;
  594. char *phone_functions;
  595. char *dphone_functions;
  596. char *alt_functions;
  597. char *nodes;
  598. char *extnodes;
  599. char *extnodefile;
  600. int hangtime;
  601. int althangtime;
  602. int totime;
  603. int idtime;
  604. int tailmessagetime;
  605. int tailsquashedtime;
  606. int duplex;
  607. int politeid;
  608. char *tailmessages[500];
  609. int tailmessagemax;
  610. char *memory;
  611. char *macro;
  612. char *tonemacro;
  613. char *startupmacro;
  614. int iobase;
  615. char *ioport;
  616. char funcchar;
  617. char endchar;
  618. char nobusyout;
  619. char notelemtx;
  620. char propagate_dtmf;
  621. char propagate_phonedtmf;
  622. char linktolink;
  623. unsigned char civaddr;
  624. struct rpt_xlat inxlat;
  625. struct rpt_xlat outxlat;
  626. char *archivedir;
  627. int authlevel;
  628. char *csstanzaname;
  629. char *skedstanzaname;
  630. char *txlimitsstanzaname;
  631. long monminblocks;
  632. int remoteinacttimeout;
  633. int remotetimeout;
  634. int remotetimeoutwarning;
  635. int remotetimeoutwarningfreq;
  636. int sysstate_cur;
  637. struct sysstate s[MAX_SYSSTATES];
  638. char parrotmode;
  639. int parrottime;
  640. char *rptnode;
  641. char remote_mars;
  642. int voxtimeout_ms;
  643. int voxrecover_ms;
  644. int simplexpatchdelay;
  645. int simplexphonedelay;
  646. char *statpost_program;
  647. char *statpost_url;
  648. } p;
  649. struct rpt_link links;
  650. int unkeytocttimer;
  651. time_t lastkeyedtime;
  652. time_t lasttxkeyedtime;
  653. char keyed;
  654. char txkeyed;
  655. char exttx;
  656. char localtx;
  657. char remoterx;
  658. char remotetx;
  659. char remoteon;
  660. char remtxfreqok;
  661. char tounkeyed;
  662. char tonotify;
  663. char dtmfbuf[MAXDTMF];
  664. char macrobuf[MAXMACRO];
  665. char rem_dtmfbuf[MAXDTMF];
  666. char lastdtmfcommand[MAXDTMF];
  667. char cmdnode[50];
  668. char nowchan; // channel now
  669. char waschan; // channel selected initially or by command
  670. char bargechan; // barge in channel
  671. char macropatch; // autopatch via tonemacro state
  672. char parrotstate;
  673. int parrottimer;
  674. unsigned int parrotcnt;
  675. struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
  676. struct ast_channel *pchannel,*txpchannel, *dahdirxchannel, *dahditxchannel;
  677. struct ast_channel *voxchannel;
  678. struct ast_frame *lastf1,*lastf2;
  679. struct rpt_tele tele;
  680. struct timeval lasttv,curtv;
  681. pthread_t rpt_call_thread,rpt_thread;
  682. time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
  683. int calldigittimer;
  684. int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
  685. int mustid,tailid;
  686. int tailevent;
  687. int telemrefcount;
  688. int dtmfidx,rem_dtmfidx;
  689. int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
  690. int totalexecdcommands, dailyexecdcommands;
  691. long retxtimer;
  692. long rerxtimer;
  693. long long totaltxtime;
  694. char mydtmf;
  695. char exten[AST_MAX_EXTENSION];
  696. char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
  697. char offset;
  698. char powerlevel;
  699. char txplon;
  700. char rxplon;
  701. char remmode;
  702. char tunerequest;
  703. char hfscanmode;
  704. int hfscanstatus;
  705. char hfscanstop;
  706. char lastlinknode[MAXNODESTR];
  707. char savednodes[MAXNODESTR];
  708. int stopgen;
  709. char patchfarenddisconnect;
  710. char patchnoct;
  711. char patchquiet;
  712. char patchcontext[MAXPATCHCONTEXT];
  713. int patchdialtime;
  714. int macro_longest;
  715. int phone_longestfunc;
  716. int alt_longestfunc;
  717. int dphone_longestfunc;
  718. int link_longestfunc;
  719. int longestfunc;
  720. int longestnode;
  721. int threadrestarts;
  722. int tailmessagen;
  723. time_t disgorgetime;
  724. time_t lastthreadrestarttime;
  725. long macrotimer;
  726. char lastnodewhichkeyedusup[MAXNODESTR];
  727. int dtmf_local_timer;
  728. char dtmf_local_str[100];
  729. struct ast_filestream *monstream,*parrotstream;
  730. char loginuser[50];
  731. char loginlevel[10];
  732. long authtelltimer;
  733. long authtimer;
  734. int iofd;
  735. time_t start_time,last_activity_time;
  736. char lasttone[32];
  737. struct rpt_tele *active_telem;
  738. struct rpt_topkey topkey[TOPKEYN];
  739. int topkeystate;
  740. time_t topkeytime;
  741. int topkeylong;
  742. struct vox vox;
  743. char wasvox;
  744. int voxtotimer;
  745. char voxtostate;
  746. int linkposttimer;
  747. int keyposttimer;
  748. char newkey;
  749. char inpadtest;
  750. #ifdef OLD_ASTERISK
  751. AST_LIST_HEAD(, ast_frame) txq;
  752. #else
  753. AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
  754. #endif
  755. char txrealkeyed;
  756. #ifdef __RPT_NOTCH
  757. struct rptfilter
  758. {
  759. char desc[100];
  760. float x0;
  761. float x1;
  762. float x2;
  763. float y0;
  764. float y1;
  765. float y2;
  766. float gain;
  767. float const0;
  768. float const1;
  769. float const2;
  770. } filters[MAXFILTERS];
  771. #endif
  772. #ifdef _MDC_DECODE_H_
  773. mdc_decoder_t *mdc;
  774. unsigned short lastunit;
  775. #endif
  776. struct rpt_cmd_struct cmdAction;
  777. } rpt_vars[MAXRPTS];
  778. struct nodelog {
  779. struct nodelog *next;
  780. struct nodelog *prev;
  781. time_t timestamp;
  782. char archivedir[MAXNODESTR];
  783. char str[MAXNODESTR * 2];
  784. } nodelog;
  785. static int service_scan(struct rpt *myrpt);
  786. static int set_mode_ft897(struct rpt *myrpt, char newmode);
  787. static int set_mode_ic706(struct rpt *myrpt, char newmode);
  788. static int simple_command_ft897(struct rpt *myrpt, char command);
  789. static int setrem(struct rpt *myrpt);
  790. static int setrtx_check(struct rpt *myrpt);
  791. static int channel_revert(struct rpt *myrpt);
  792. static int channel_steer(struct rpt *myrpt, char *data);
  793. AST_MUTEX_DEFINE_STATIC(nodeloglock);
  794. AST_MUTEX_DEFINE_STATIC(nodelookuplock);
  795. #ifdef APP_RPT_LOCK_DEBUG
  796. #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
  797. #define MAXLOCKTHREAD 100
  798. #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
  799. #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
  800. struct lockthread
  801. {
  802. pthread_t id;
  803. int lockcount;
  804. int lastlock;
  805. int lastunlock;
  806. } lockthreads[MAXLOCKTHREAD];
  807. struct by_lightning
  808. {
  809. int line;
  810. struct timeval tv;
  811. struct rpt *rpt;
  812. struct lockthread lockthread;
  813. } lock_ring[32];
  814. int lock_ring_index = 0;
  815. AST_MUTEX_DEFINE_STATIC(locklock);
  816. static struct lockthread *get_lockthread(pthread_t id)
  817. {
  818. int i;
  819. for(i = 0; i < MAXLOCKTHREAD; i++)
  820. {
  821. if (lockthreads[i].id == id) return(&lockthreads[i]);
  822. }
  823. return(NULL);
  824. }
  825. static struct lockthread *put_lockthread(pthread_t id)
  826. {
  827. int i;
  828. for(i = 0; i < MAXLOCKTHREAD; i++)
  829. {
  830. if (lockthreads[i].id == id)
  831. return(&lockthreads[i]);
  832. }
  833. for(i = 0; i < MAXLOCKTHREAD; i++)
  834. {
  835. if (!lockthreads[i].id)
  836. {
  837. lockthreads[i].lockcount = 0;
  838. lockthreads[i].lastlock = 0;
  839. lockthreads[i].lastunlock = 0;
  840. lockthreads[i].id = id;
  841. return(&lockthreads[i]);
  842. }
  843. }
  844. return(NULL);
  845. }
  846. static void rpt_mutex_spew(void)
  847. {
  848. struct by_lightning lock_ring_copy[32];
  849. int lock_ring_index_copy;
  850. int i,j;
  851. long long diff;
  852. char a[100];
  853. struct timeval lasttv;
  854. ast_mutex_lock(&locklock);
  855. memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
  856. lock_ring_index_copy = lock_ring_index;
  857. ast_mutex_unlock(&locklock);
  858. lasttv.tv_sec = lasttv.tv_usec = 0;
  859. for(i = 0 ; i < 32 ; i++)
  860. {
  861. j = (i + lock_ring_index_copy) % 32;
  862. strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
  863. localtime(&lock_ring_copy[j].tv.tv_sec));
  864. diff = 0;
  865. if(lasttv.tv_sec)
  866. {
  867. diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
  868. * 1000000;
  869. diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
  870. }
  871. lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
  872. lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
  873. if (!lock_ring_copy[j].tv.tv_sec) continue;
  874. if (lock_ring_copy[j].line < 0)
  875. {
  876. ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
  877. i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
  878. }
  879. else
  880. {
  881. ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
  882. i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
  883. }
  884. }
  885. }
  886. static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
  887. {
  888. struct lockthread *t;
  889. pthread_t id;
  890. id = pthread_self();
  891. ast_mutex_lock(&locklock);
  892. t = put_lockthread(id);
  893. if (!t)
  894. {
  895. ast_mutex_unlock(&locklock);
  896. return;
  897. }
  898. if (t->lockcount)
  899. {
  900. int lastline = t->lastlock;
  901. ast_mutex_unlock(&locklock);
  902. ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
  903. rpt_mutex_spew();
  904. return;
  905. }
  906. t->lastlock = line;
  907. t->lockcount = 1;
  908. gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
  909. lock_ring[lock_ring_index].rpt = myrpt;
  910. memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
  911. lock_ring[lock_ring_index++].line = line;
  912. if(lock_ring_index == 32)
  913. lock_ring_index = 0;
  914. ast_mutex_unlock(&locklock);
  915. ast_mutex_lock(lockp);
  916. }
  917. static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
  918. {
  919. struct lockthread *t;
  920. pthread_t id;
  921. id = pthread_self();
  922. ast_mutex_lock(&locklock);
  923. t = put_lockthread(id);
  924. if (!t)
  925. {
  926. ast_mutex_unlock(&locklock);
  927. return;
  928. }
  929. if (!t->lockcount)
  930. {
  931. int lastline = t->lastunlock;
  932. ast_mutex_unlock(&locklock);
  933. ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
  934. rpt_mutex_spew();
  935. return;
  936. }
  937. t->lastunlock = line;
  938. t->lockcount = 0;
  939. gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
  940. lock_ring[lock_ring_index].rpt = myrpt;
  941. memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
  942. lock_ring[lock_ring_index++].line = -line;
  943. if(lock_ring_index == 32)
  944. lock_ring_index = 0;
  945. ast_mutex_unlock(&locklock);
  946. ast_mutex_unlock(lockp);
  947. }
  948. #else /* APP_RPT_LOCK_DEBUG */
  949. #define rpt_mutex_lock(x) ast_mutex_lock(x)
  950. #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
  951. #endif /* APP_RPT_LOCK_DEBUG */
  952. /*
  953. * Return 1 if rig is multimode capable
  954. */
  955. static int multimode_capable(struct rpt *myrpt)
  956. {
  957. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  958. return 1;
  959. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  960. return 1;
  961. return 0;
  962. }
  963. static void voxinit_rpt(struct rpt *myrpt,char enable)
  964. {
  965. myrpt->vox.speech_energy = 0.0;
  966. myrpt->vox.noise_energy = 0.0;
  967. myrpt->vox.enacount = 0;
  968. myrpt->vox.voxena = 0;
  969. if (!enable) myrpt->vox.voxena = -1;
  970. myrpt->vox.lastvox = 0;
  971. myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
  972. myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
  973. myrpt->wasvox = 0;
  974. myrpt->voxtotimer = 0;
  975. myrpt->voxtostate = 0;
  976. }
  977. static void voxinit_link(struct rpt_link *mylink,char enable)
  978. {
  979. mylink->vox.speech_energy = 0.0;
  980. mylink->vox.noise_energy = 0.0;
  981. mylink->vox.enacount = 0;
  982. mylink->vox.voxena = 0;
  983. if (!enable) mylink->vox.voxena = -1;
  984. mylink->vox.lastvox = 0;
  985. mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
  986. mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
  987. mylink->wasvox = 0;
  988. mylink->voxtotimer = 0;
  989. mylink->voxtostate = 0;
  990. }
  991. static int dovox(struct vox *v,short *buf,int bs)
  992. {
  993. int i;
  994. float esquare = 0.0;
  995. float energy = 0.0;
  996. float threshold = 0.0;
  997. if (v->voxena < 0) return(v->lastvox);
  998. for(i = 0; i < bs; i++)
  999. {
  1000. esquare += (float) buf[i] * (float) buf[i];
  1001. }
  1002. energy = sqrt(esquare);
  1003. if (energy >= v->speech_energy)
  1004. v->speech_energy += (energy - v->speech_energy) / 4;
  1005. else
  1006. v->speech_energy += (energy - v->speech_energy) / 64;
  1007. if (energy >= v->noise_energy)
  1008. v->noise_energy += (energy - v->noise_energy) / 64;
  1009. else
  1010. v->noise_energy += (energy - v->noise_energy) / 4;
  1011. if (v->voxena) threshold = v->speech_energy / 8;
  1012. else
  1013. {
  1014. threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
  1015. threshold = mymin(threshold,VOX_MAX_THRESHOLD);
  1016. }
  1017. threshold = mymax(threshold,VOX_MIN_THRESHOLD);
  1018. if (energy > threshold)
  1019. {
  1020. if (v->voxena) v->noise_energy *= 0.75;
  1021. v->voxena = 1;
  1022. } else v->voxena = 0;
  1023. if (v->lastvox != v->voxena)
  1024. {
  1025. if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
  1026. {
  1027. v->lastvox = v->voxena;
  1028. v->enacount = 0;
  1029. }
  1030. } else v->enacount = 0;
  1031. return(v->lastvox);
  1032. }
  1033. /*
  1034. * CLI extensions
  1035. */
  1036. /* Debug mode */
  1037. static int rpt_do_debug(int fd, int argc, const char * const *argv);
  1038. static int rpt_do_dump(int fd, int argc, const char * const *argv);
  1039. static int rpt_do_stats(int fd, int argc, const char * const *argv);
  1040. static int rpt_do_lstats(int fd, int argc, const char * const *argv);
  1041. static int rpt_do_nodes(int fd, int argc, const char * const *argv);
  1042. static int rpt_do_local_nodes(int fd, int argc, const char * const *argv);
  1043. static int rpt_do_reload(int fd, int argc, const char * const *argv);
  1044. static int rpt_do_restart(int fd, int argc, const char * const *argv);
  1045. static int rpt_do_fun(int fd, int argc, const char * const *argv);
  1046. static int rpt_do_fun1(int fd, int argc, const char * const *argv);
  1047. static int rpt_do_cmd(int fd, int argc, const char * const *argv);
  1048. static char debug_usage[] =
  1049. "Usage: rpt debug level {0-7}\n"
  1050. " Enables debug messages in app_rpt\n";
  1051. static char dump_usage[] =
  1052. "Usage: rpt dump <nodename>\n"
  1053. " Dumps struct debug info to log\n";
  1054. static char dump_stats[] =
  1055. "Usage: rpt stats <nodename>\n"
  1056. " Dumps node statistics to console\n";
  1057. static char dump_lstats[] =
  1058. "Usage: rpt lstats <nodename>\n"
  1059. " Dumps link statistics to console\n";
  1060. static char dump_nodes[] =
  1061. "Usage: rpt nodes <nodename>\n"
  1062. " Dumps a list of directly and indirectly connected nodes to the console\n";
  1063. static char usage_local_nodes[] =
  1064. "Usage: rpt localnodes\n"
  1065. " Dumps a list of the locally configured node numbers to the console.\n";
  1066. static char reload_usage[] =
  1067. "Usage: rpt reload\n"
  1068. " Reloads app_rpt running config parameters\n";
  1069. static char restart_usage[] =
  1070. "Usage: rpt restart\n"
  1071. " Restarts app_rpt\n";
  1072. static char fun_usage[] =
  1073. "Usage: rpt fun <nodename> <command>\n"
  1074. " Send a DTMF function to a node\n";
  1075. static char cmd_usage[] =
  1076. "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
  1077. " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
  1078. #ifndef NEW_ASTERISK
  1079. static struct ast_cli_entry cli_debug =
  1080. { { "rpt", "debug", "level" }, rpt_do_debug,
  1081. "Enable app_rpt debugging", debug_usage };
  1082. static struct ast_cli_entry cli_dump =
  1083. { { "rpt", "dump" }, rpt_do_dump,
  1084. "Dump app_rpt structs for debugging", dump_usage };
  1085. static struct ast_cli_entry cli_stats =
  1086. { { "rpt", "stats" }, rpt_do_stats,
  1087. "Dump node statistics", dump_stats };
  1088. static struct ast_cli_entry cli_nodes =
  1089. { { "rpt", "nodes" }, rpt_do_nodes,
  1090. "Dump node list", dump_nodes };
  1091. static struct ast_cli_entry cli_local_nodes =
  1092. { { "rpt", "localnodes" }, rpt_do_local_nodes,
  1093. "Dump list of local node numbers", usage_local_nodes };
  1094. static struct ast_cli_entry cli_lstats =
  1095. { { "rpt", "lstats" }, rpt_do_lstats,
  1096. "Dump link statistics", dump_lstats };
  1097. static struct ast_cli_entry cli_reload =
  1098. { { "rpt", "reload" }, rpt_do_reload,
  1099. "Reload app_rpt config", reload_usage };
  1100. static struct ast_cli_entry cli_restart =
  1101. { { "rpt", "restart" }, rpt_do_restart,
  1102. "Restart app_rpt", restart_usage };
  1103. static struct ast_cli_entry cli_fun =
  1104. { { "rpt", "fun" }, rpt_do_fun,
  1105. "Execute a DTMF function", fun_usage };
  1106. static struct ast_cli_entry cli_fun1 =
  1107. { { "rpt", "fun1" }, rpt_do_fun1,
  1108. "Execute a DTMF function", fun_usage };
  1109. static struct ast_cli_entry cli_cmd =
  1110. { { "rpt", "cmd" }, rpt_do_cmd,
  1111. "Execute a DTMF function", cmd_usage };
  1112. #endif
  1113. /*
  1114. * Telemetry defaults
  1115. */
  1116. static struct telem_defaults tele_defs[] = {
  1117. {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
  1118. {"ct2","|t(660,880,150,3072)"},
  1119. {"ct3","|t(440,0,150,3072)"},
  1120. {"ct4","|t(550,0,150,3072)"},
  1121. {"ct5","|t(660,0,150,3072)"},
  1122. {"ct6","|t(880,0,150,3072)"},
  1123. {"ct7","|t(660,440,150,3072)"},
  1124. {"ct8","|t(700,1100,150,3072)"},
  1125. {"remotemon","|t(1600,0,75,2048)"},
  1126. {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
  1127. {"cmdmode","|t(900,904,200,2048)"},
  1128. {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
  1129. } ;
  1130. /*
  1131. * Forward decl's - these suppress compiler warnings when funcs coded further down the file than thier invokation
  1132. */
  1133. static int setrbi(struct rpt *myrpt);
  1134. static int set_ft897(struct rpt *myrpt);
  1135. static int set_ic706(struct rpt *myrpt);
  1136. static int setkenwood(struct rpt *myrpt);
  1137. static int set_tm271(struct rpt *myrpt);
  1138. static int setrbi_check(struct rpt *myrpt);
  1139. /*
  1140. * Define function protos for function table here
  1141. */
  1142. static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1143. static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1144. static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1145. static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1146. static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1147. static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1148. static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1149. static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
  1150. /*
  1151. * Function table
  1152. */
  1153. static struct function_table_tag function_table[] = {
  1154. {"cop", function_cop},
  1155. {"autopatchup", function_autopatchup},
  1156. {"autopatchdn", function_autopatchdn},
  1157. {"ilink", function_ilink},
  1158. {"status", function_status},
  1159. {"remote", function_remote},
  1160. {"macro", function_macro},
  1161. {"playback", function_playback}
  1162. } ;
  1163. static long diskavail(struct rpt *myrpt)
  1164. {
  1165. struct statfs statfsbuf;
  1166. if (!myrpt->p.archivedir) return(0);
  1167. if (statfs(myrpt->p.archivedir,&statfsbuf) == -1)
  1168. {
  1169. ast_log(LOG_WARNING,"Cannot get filesystem size for %s node %s\n",
  1170. myrpt->p.archivedir,myrpt->name);
  1171. return(-1);
  1172. }
  1173. return(statfsbuf.f_bavail);
  1174. }
  1175. static void flush_telem(struct rpt *myrpt)
  1176. {
  1177. struct rpt_tele *telem;
  1178. if(debug > 2)
  1179. ast_log(LOG_NOTICE, "flush_telem()!!");
  1180. rpt_mutex_lock(&myrpt->lock);
  1181. telem = myrpt->tele.next;
  1182. while(telem != &myrpt->tele)
  1183. {
  1184. if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
  1185. telem = telem->next;
  1186. }
  1187. rpt_mutex_unlock(&myrpt->lock);
  1188. }
  1189. /*
  1190. return via error priority
  1191. */
  1192. static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
  1193. {
  1194. int res=0;
  1195. // if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
  1196. if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
  1197. res = 0;
  1198. } else {
  1199. res = -1;
  1200. }
  1201. return res;
  1202. }
  1203. /*
  1204. */
  1205. static int linkcount(struct rpt *myrpt)
  1206. {
  1207. struct rpt_link *l;
  1208. int numoflinks;
  1209. numoflinks = 0;
  1210. l = myrpt->links.next;
  1211. while(l && (l != &myrpt->links)){
  1212. if(numoflinks >= MAX_STAT_LINKS){
  1213. ast_log(LOG_WARNING,
  1214. "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
  1215. break;
  1216. }
  1217. numoflinks++;
  1218. l = l->next;
  1219. }
  1220. ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
  1221. return numoflinks;
  1222. }
  1223. /*
  1224. * Retrieve a memory channel
  1225. * Return 0 if sucessful,
  1226. * -1 if channel not found,
  1227. * 1 if parse error
  1228. */
  1229. static int retreive_memory(struct rpt *myrpt, char *memory)
  1230. {
  1231. char tmp[30], *s, *s1, *val;
  1232. if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
  1233. val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
  1234. if (!val){
  1235. return -1;
  1236. }
  1237. strncpy(tmp,val,sizeof(tmp) - 1);
  1238. tmp[sizeof(tmp)-1] = 0;
  1239. s = strchr(tmp,',');
  1240. if (!s)
  1241. return 1;
  1242. *s++ = 0;
  1243. s1 = strchr(s,',');
  1244. if (!s1)
  1245. return 1;
  1246. *s1++ = 0;
  1247. strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
  1248. strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
  1249. strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
  1250. myrpt->remmode = REM_MODE_FM;
  1251. myrpt->offset = REM_SIMPLEX;
  1252. myrpt->powerlevel = REM_MEDPWR;
  1253. myrpt->txplon = myrpt->rxplon = 0;
  1254. while(*s1){
  1255. switch(*s1++){
  1256. case 'A':
  1257. case 'a':
  1258. strcpy(myrpt->rxpl, "100.0");
  1259. strcpy(myrpt->txpl, "100.0");
  1260. myrpt->remmode = REM_MODE_AM;
  1261. break;
  1262. case 'B':
  1263. case 'b':
  1264. strcpy(myrpt->rxpl, "100.0");
  1265. strcpy(myrpt->txpl, "100.0");
  1266. myrpt->remmode = REM_MODE_LSB;
  1267. break;
  1268. case 'F':
  1269. myrpt->remmode = REM_MODE_FM;
  1270. break;
  1271. case 'L':
  1272. case 'l':
  1273. myrpt->powerlevel = REM_LOWPWR;
  1274. break;
  1275. case 'H':
  1276. case 'h':
  1277. myrpt->powerlevel = REM_HIPWR;
  1278. break;
  1279. case 'M':
  1280. case 'm':
  1281. myrpt->powerlevel = REM_MEDPWR;
  1282. break;
  1283. case '-':
  1284. myrpt->offset = REM_MINUS;
  1285. break;
  1286. case '+':
  1287. myrpt->offset = REM_PLUS;
  1288. break;
  1289. case 'S':
  1290. case 's':
  1291. myrpt->offset = REM_SIMPLEX;
  1292. break;
  1293. case 'T':
  1294. case 't':
  1295. myrpt->txplon = 1;
  1296. break;
  1297. case 'R':
  1298. case 'r':
  1299. myrpt->rxplon = 1;
  1300. break;
  1301. case 'U':
  1302. case 'u':
  1303. strcpy(myrpt->rxpl, "100.0");
  1304. strcpy(myrpt->txpl, "100.0");
  1305. myrpt->remmode = REM_MODE_USB;
  1306. break;
  1307. default:
  1308. return 1;
  1309. }
  1310. }
  1311. return 0;
  1312. }
  1313. /*
  1314. */
  1315. static void birdbath(struct rpt *myrpt)
  1316. {
  1317. struct rpt_tele *telem;
  1318. if(debug > 2)
  1319. ast_log(LOG_NOTICE, "birdbath!!");
  1320. rpt_mutex_lock(&myrpt->lock);
  1321. telem = myrpt->tele.next;
  1322. while(telem != &myrpt->tele)
  1323. {
  1324. if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
  1325. telem = telem->next;
  1326. }
  1327. rpt_mutex_unlock(&myrpt->lock);
  1328. }
  1329. static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
  1330. {
  1331. struct rpt_link *l;
  1332. l = myrpt->links.next;
  1333. /* go thru all the links */
  1334. while(l != &myrpt->links)
  1335. {
  1336. if (!l->phonemode)
  1337. {
  1338. l = l->next;
  1339. continue;
  1340. }
  1341. /* don't send to self */
  1342. if (mylink && (l == mylink))
  1343. {
  1344. l = l->next;
  1345. continue;
  1346. }
  1347. #ifdef NEW_ASTERISK
  1348. if (l->chan) ast_senddigit(l->chan,c,0);
  1349. #else
  1350. if (l->chan) ast_senddigit(l->chan,c);
  1351. #endif
  1352. l = l->next;
  1353. }
  1354. return;
  1355. }
  1356. /* node logging function */
  1357. static void donodelog(struct rpt *myrpt,char *str)
  1358. {
  1359. struct nodelog *nodep;
  1360. char datestr[100];
  1361. if (!myrpt->p.archivedir) return;
  1362. nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
  1363. if (nodep == NULL)
  1364. {
  1365. ast_log(LOG_ERROR,"Cannot get memory for node log");
  1366. return;
  1367. }
  1368. time(&nodep->timestamp);
  1369. strncpy(nodep->archivedir,myrpt->p.archivedir,
  1370. sizeof(nodep->archivedir) - 1);
  1371. strftime(datestr,sizeof(datestr) - 1,"%Y%m%d%H%M%S",
  1372. localtime(&nodep->timestamp));
  1373. snprintf(nodep->str,sizeof(nodep->str) - 1,"%s %s,%s\n",
  1374. myrpt->name,datestr,str);
  1375. ast_mutex_lock(&nodeloglock);
  1376. insque((struct qelem *) nodep, (struct qelem *) nodelog.prev);
  1377. ast_mutex_unlock(&nodeloglock);
  1378. }
  1379. /* must be called locked */
  1380. static void do_dtmf_local(struct rpt *myrpt, char c)
  1381. {
  1382. int i;
  1383. char digit;
  1384. static const char* dtmf_tones[] = {
  1385. "!941+1336/200,!0/200", /* 0 */
  1386. "!697+1209/200,!0/200", /* 1 */
  1387. "!697+1336/200,!0/200", /* 2 */
  1388. "!697+1477/200,!0/200", /* 3 */
  1389. "!770+1209/200,!0/200", /* 4 */
  1390. "!770+1336/200,!0/200", /* 5 */
  1391. "!770+1477/200,!0/200", /* 6 */
  1392. "!852+1209/200,!0/200", /* 7 */
  1393. "!852+1336/200,!0/200", /* 8 */
  1394. "!852+1477/200,!0/200", /* 9 */
  1395. "!697+1633/200,!0/200", /* A */
  1396. "!770+1633/200,!0/200", /* B */
  1397. "!852+1633/200,!0/200", /* C */
  1398. "!941+1633/200,!0/200", /* D */
  1399. "!941+1209/200,!0/200", /* * */
  1400. "!941+1477/200,!0/200" }; /* # */
  1401. if (c)
  1402. {
  1403. snprintf(myrpt->dtmf_local_str + strlen(myrpt->dtmf_local_str),sizeof(myrpt->dtmf_local_str) - 1,"%c",c);
  1404. if (!myrpt->dtmf_local_timer)
  1405. myrpt->dtmf_local_timer = DTMF_LOCAL_STARTTIME;
  1406. }
  1407. /* if at timeout */
  1408. if (myrpt->dtmf_local_timer == 1)
  1409. {
  1410. if(debug > 6)
  1411. ast_log(LOG_NOTICE,"time out dtmf_local_timer=%i\n",myrpt->dtmf_local_timer);
  1412. /* if anything in the string */
  1413. if (myrpt->dtmf_local_str[0])
  1414. {
  1415. digit = myrpt->dtmf_local_str[0];
  1416. myrpt->dtmf_local_str[0] = 0;
  1417. for(i = 1; myrpt->dtmf_local_str[i]; i++)
  1418. {
  1419. myrpt->dtmf_local_str[i - 1] =
  1420. myrpt->dtmf_local_str[i];
  1421. }
  1422. myrpt->dtmf_local_str[i - 1] = 0;
  1423. myrpt->dtmf_local_timer = DTMF_LOCAL_TIME;
  1424. rpt_mutex_unlock(&myrpt->lock);
  1425. if (digit >= '0' && digit <='9')
  1426. ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'0'], 0);
  1427. else if (digit >= 'A' && digit <= 'D')
  1428. ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[digit-'A'+10], 0);
  1429. else if (digit == '*')
  1430. ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[14], 0);
  1431. else if (digit == '#')
  1432. ast_playtones_start(myrpt->txchannel, 0, dtmf_tones[15], 0);
  1433. else {
  1434. /* not handled */
  1435. ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, myrpt->txchannel->name);
  1436. }
  1437. rpt_mutex_lock(&myrpt->lock);
  1438. }
  1439. else
  1440. {
  1441. myrpt->dtmf_local_timer = 0;
  1442. }
  1443. }
  1444. }
  1445. static int setdtr(int fd, int enable)
  1446. {
  1447. struct termios mode;
  1448. if (fd < 0) return -1;
  1449. if (tcgetattr(fd, &mode)) {
  1450. ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
  1451. return -1;
  1452. }
  1453. if (enable)
  1454. {
  1455. cfsetspeed(&mode, B9600);
  1456. }
  1457. else
  1458. {
  1459. cfsetspeed(&mode, B0);
  1460. usleep(100000);
  1461. }
  1462. if (tcsetattr(fd, TCSADRAIN, &mode)) {
  1463. ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
  1464. return -1;
  1465. }
  1466. if (enable) usleep(100000);
  1467. return 0;
  1468. }
  1469. static int openserial(struct rpt *myrpt,char *fname)
  1470. {
  1471. struct termios mode;
  1472. int fd;
  1473. fd = open(fname,O_RDWR);
  1474. if (fd == -1)
  1475. {
  1476. ast_log(LOG_WARNING,"Cannot open serial port %s\n",fname);
  1477. return -1;
  1478. }
  1479. memset(&mode, 0, sizeof(mode));
  1480. if (tcgetattr(fd, &mode)) {
  1481. ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
  1482. return -1;
  1483. }
  1484. #ifndef SOLARIS
  1485. cfmakeraw(&mode);
  1486. #else
  1487. mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
  1488. |INLCR|IGNCR|ICRNL|IXON);
  1489. mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
  1490. mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
  1491. mode.c_cflag |= CS8;
  1492. mode.c_cc[VTIME] = 3;
  1493. mode.c_cc[VMIN] = 1;
  1494. #endif
  1495. cfsetispeed(&mode, B9600);
  1496. cfsetospeed(&mode, B9600);
  1497. if (tcsetattr(fd, TCSANOW, &mode))
  1498. ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
  1499. if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
  1500. usleep(100000);
  1501. if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
  1502. return(fd);
  1503. }
  1504. static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
  1505. {
  1506. if (!fromnode)
  1507. {
  1508. ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
  1509. unit,myrpt->name);
  1510. }
  1511. else
  1512. {
  1513. ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
  1514. unit,fromnode,myrpt->name);
  1515. }
  1516. }
  1517. #ifdef _MDC_DECODE_H_
  1518. static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
  1519. {
  1520. struct rpt_link *l;
  1521. struct ast_frame wf;
  1522. char str[200];
  1523. sprintf(str,"I %s %04X",myrpt->name,unit);
  1524. wf.frametype = AST_FRAME_TEXT;
  1525. wf.subclass.integer = 0;
  1526. wf.offset = 0;
  1527. wf.mallocd = 0;
  1528. wf.datalen = strlen(str) + 1;
  1529. wf.samples = 0;
  1530. l = myrpt->links.next;
  1531. /* otherwise, send it to all of em */
  1532. while(l != &myrpt->links)
  1533. {
  1534. if (l->name[0] == '0')
  1535. {
  1536. l = l->next;
  1537. continue;
  1538. }
  1539. wf.data = str;
  1540. if (l->chan) ast_write(l->chan,&wf);
  1541. l = l->next;
  1542. }
  1543. return;
  1544. }
  1545. #endif
  1546. static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
  1547. {
  1548. time_t now;
  1549. int gotone;
  1550. time(&now);
  1551. gotone = 0;
  1552. /* if too much time, reset the skate machine */
  1553. if ((now - xlat->lastone) > MAXXLATTIME)
  1554. {
  1555. xlat->funcindex = xlat->endindex = 0;
  1556. }
  1557. if (xlat->funccharseq[0] && (c == xlat->funccharseq[xlat->funcindex++]))
  1558. {
  1559. time(&xlat->lastone);
  1560. gotone = 1;
  1561. if (!xlat->funccharseq[xlat->funcindex])
  1562. {
  1563. xlat->funcindex = xlat->endindex = 0;
  1564. return(myrpt->p.funcchar);
  1565. }
  1566. } else xlat->funcindex = 0;
  1567. if (xlat->endcharseq[0] && (c == xlat->endcharseq[xlat->endindex++]))
  1568. {
  1569. time(&xlat->lastone);
  1570. gotone = 1;
  1571. if (!xlat->endcharseq[xlat->endindex])
  1572. {
  1573. xlat->funcindex = xlat->endindex = 0;
  1574. return(myrpt->p.endchar);
  1575. }
  1576. } else xlat->endindex = 0;
  1577. /* if in middle of decode seq, send nothing back */
  1578. if (gotone) return(0);
  1579. /* if no pass chars specified, return em all */
  1580. if (!xlat->passchars[0]) return(c);
  1581. /* if a "pass char", pass it */
  1582. if (strchr(xlat->passchars,c)) return(c);
  1583. return(0);
  1584. }
  1585. /*
  1586. * Return a pointer to the first non-whitespace character
  1587. */
  1588. static char *eatwhite(char *s)
  1589. {
  1590. while((*s == ' ') || (*s == 0x09)){ /* get rid of any leading white space */
  1591. if(!*s)
  1592. break;
  1593. s++;
  1594. }
  1595. return s;
  1596. }
  1597. /*
  1598. * Break up a delimited string into a table of substrings
  1599. *
  1600. * str - delimited string ( will be modified )
  1601. * strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
  1602. * limit- maximum number of substrings to process
  1603. */
  1604. static int finddelim(char *str, char *strp[], int limit)
  1605. {
  1606. int i,l,inquo;
  1607. inquo = 0;
  1608. i = 0;
  1609. strp[i++] = str;
  1610. if (!*str)
  1611. {
  1612. strp[0] = 0;
  1613. return(0);
  1614. }
  1615. for(l = 0; *str && (l < limit) ; str++)
  1616. {
  1617. if (*str == QUOTECHR)
  1618. {
  1619. if (inquo)
  1620. {
  1621. *str = 0;
  1622. inquo = 0;
  1623. }
  1624. else
  1625. {
  1626. strp[i - 1] = str + 1;
  1627. inquo = 1;
  1628. }
  1629. }
  1630. if ((*str == DELIMCHR) && (!inquo))
  1631. {
  1632. *str = 0;
  1633. l++;
  1634. strp[i++] = str + 1;
  1635. }
  1636. }
  1637. strp[i] = 0;
  1638. return(i);
  1639. }
  1640. /*
  1641. send asterisk frame text message on the current tx channel
  1642. */
  1643. static int send_usb_txt(struct rpt *myrpt, char *txt)
  1644. {
  1645. struct ast_frame wf;
  1646. if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
  1647. wf.frametype = AST_FRAME_TEXT;
  1648. wf.subclass.integer = 0;
  1649. wf.offset = 0;
  1650. wf.mallocd = 0;
  1651. wf.datalen = strlen(txt) + 1;
  1652. wf.data.ptr = txt;
  1653. wf.samples = 0;
  1654. ast_write(myrpt->txchannel,&wf);
  1655. return 0;
  1656. }
  1657. /* must be called locked */
  1658. static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
  1659. {
  1660. struct rpt_link *l;
  1661. char mode;
  1662. int i,spos;
  1663. buf[0] = 0; /* clear output buffer */
  1664. if (myrpt->remote) return;
  1665. /* go thru all links */
  1666. for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
  1667. {
  1668. /* if is not a real link, ignore it */
  1669. if (l->name[0] == '0') continue;
  1670. /* don't count our stuff */
  1671. if (l == mylink) continue;
  1672. if (mylink && (!strcmp(l->name,mylink->name))) continue;
  1673. /* figure out mode to report */
  1674. mode = 'T'; /* use Tranceive by default */
  1675. if (!l->mode) mode = 'R'; /* indicate RX for our mode */
  1676. if (!l->thisconnected) mode = 'C'; /* indicate connecting */
  1677. spos = strlen(buf); /* current buf size (b4 we add our stuff) */
  1678. if (spos)
  1679. {
  1680. strcat(buf,",");
  1681. spos++;
  1682. }
  1683. /* add nodes into buffer */
  1684. if (l->linklist[0])
  1685. {
  1686. snprintf(buf + spos,MAXLINKLIST - spos,
  1687. "%c%s,%s",mode,l->name,l->linklist);
  1688. }
  1689. else /* if no nodes, add this node into buffer */
  1690. {
  1691. snprintf(buf + spos,MAXLINKLIST - spos,
  1692. "%c%s",mode,l->name);
  1693. }
  1694. /* if we are in tranceive mode, let all modes stand */
  1695. if (mode == 'T') continue;
  1696. /* downgrade everyone on this node if appropriate */
  1697. for(i = spos; buf[i]; i++)
  1698. {
  1699. if (buf[i] == 'T') buf[i] = mode;
  1700. if ((buf[i] == 'R') && (mode == 'C')) buf[i] = mode;
  1701. }
  1702. }
  1703. return;
  1704. }
  1705. /* must be called locked */
  1706. static void __kickshort(struct rpt *myrpt)
  1707. {
  1708. struct rpt_link *l;
  1709. for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
  1710. {
  1711. /* if is not a real link, ignore it */
  1712. if (l->name[0] == '0') continue;
  1713. l->linklisttimer = LINKLISTSHORTTIME;
  1714. }
  1715. myrpt->linkposttimer = LINKPOSTSHORTTIME;
  1716. return;
  1717. }
  1718. static void statpost(struct rpt *myrpt,char *pairs)
  1719. {
  1720. char *str,*astr;
  1721. char *astrs[100];
  1722. int n,pid;
  1723. time_t now;
  1724. unsigned int seq;
  1725. if (!myrpt->p.statpost_url) return;
  1726. str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
  1727. astr = ast_strdup(myrpt->p.statpost_program);
  1728. if ((!str) || (!astr)) {
  1729. ast_free(str);
  1730. ast_free(astr);
  1731. return;
  1732. }
  1733. n = finddelim(astr,astrs,100);
  1734. if (n < 1) {
  1735. ast_free(str);
  1736. ast_free(astr);
  1737. return;
  1738. }
  1739. ast_mutex_lock(&myrpt->statpost_lock);
  1740. seq = ++myrpt->statpost_seqno;
  1741. ast_mutex_unlock(&myrpt->statpost_lock);
  1742. astrs[n++] = str;
  1743. astrs[n] = NULL;
  1744. time(&now);
  1745. sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
  1746. myrpt->name,(unsigned int) now,seq);
  1747. if (pairs) sprintf(str + strlen(str),"&%s",pairs);
  1748. if (!(pid = ast_safe_fork(0)))
  1749. {
  1750. execv(astrs[0],astrs);
  1751. ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
  1752. perror("asterisk");
  1753. exit(0);
  1754. }
  1755. ast_free(astr);
  1756. ast_free(str);
  1757. return;
  1758. }
  1759. static char *node_lookup(struct rpt *myrpt,char *digitbuf)
  1760. {
  1761. char *val;
  1762. int longestnode,j;
  1763. struct stat mystat;
  1764. static time_t last = 0;
  1765. static struct ast_config *ourcfg = NULL;
  1766. struct ast_variable *vp;
  1767. /* try to look it up locally first */
  1768. val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
  1769. if (val) return(val);
  1770. ast_mutex_lock(&nodelookuplock);
  1771. /* if file does not exist */
  1772. if (stat(myrpt->p.extnodefile,&mystat) == -1)
  1773. {
  1774. if (ourcfg) ast_config_destroy(ourcfg);
  1775. ourcfg = NULL;
  1776. ast_mutex_unlock(&nodelookuplock);
  1777. return(NULL);
  1778. }
  1779. /* if we need to reload */
  1780. if (mystat.st_mtime > last)
  1781. {
  1782. if (ourcfg) ast_config_destroy(ourcfg);
  1783. #ifdef NEW_ASTERISK
  1784. ourcfg = ast_config_load(myrpt->p.extnodefile,config_flags);
  1785. #else
  1786. ourcfg = ast_config_load(myrpt->p.extnodefile);
  1787. #endif
  1788. /* if file not there, just bail */
  1789. if (!ourcfg || ourcfg == CONFIG_STATUS_FILEINVALID)
  1790. {
  1791. ast_mutex_unlock(&nodelookuplock);
  1792. return(NULL);
  1793. }
  1794. /* reset "last" time */
  1795. last = mystat.st_mtime;
  1796. /* determine longest node length again */
  1797. longestnode = 0;
  1798. vp = ast_variable_browse(myrpt->cfg, myrpt->p.nodes);
  1799. while(vp){
  1800. j = strlen(vp->name);
  1801. if (j > longestnode)
  1802. longestnode = j;
  1803. vp = vp->next;
  1804. }
  1805. vp = ast_variable_browse(ourcfg, myrpt->p.extnodes);
  1806. while(vp){
  1807. j = strlen(vp->name);
  1808. if (j > longestnode)
  1809. longestnode = j;
  1810. vp = vp->next;
  1811. }
  1812. myrpt->longestnode = longestnode;
  1813. }
  1814. val = NULL;
  1815. if (ourcfg)
  1816. val = (char *) ast_variable_retrieve(ourcfg, myrpt->p.extnodes, digitbuf);
  1817. ast_mutex_unlock(&nodelookuplock);
  1818. return(val);
  1819. }
  1820. /*
  1821. * Match a keyword in a list, and return index of string plus 1 if there was a match,* else return 0.
  1822. * If param is passed in non-null, then it will be set to the first character past the match
  1823. */
  1824. static int matchkeyword(char *string, char **param, char *keywords[])
  1825. {
  1826. int i,ls;
  1827. for( i = 0 ; keywords[i] ; i++){
  1828. ls = strlen(keywords[i]);
  1829. if(!ls){
  1830. *param = NULL;
  1831. return 0;
  1832. }
  1833. if(!strncmp(string, keywords[i], ls)){
  1834. if(param)
  1835. *param = string + ls;
  1836. return i + 1;
  1837. }
  1838. }
  1839. *param = NULL;
  1840. return 0;
  1841. }
  1842. /*
  1843. * Skip characters in string which are in charlist, and return a pointer to the
  1844. * first non-matching character
  1845. */
  1846. static char *skipchars(char *string, char *charlist)
  1847. {
  1848. int i;
  1849. while(*string){
  1850. for(i = 0; charlist[i] ; i++){
  1851. if(*string == charlist[i]){
  1852. string++;
  1853. break;
  1854. }
  1855. }
  1856. if(!charlist[i])
  1857. return string;
  1858. }
  1859. return string;
  1860. }
  1861. static int myatoi(const char *str)
  1862. {
  1863. int ret;
  1864. if (!str) {
  1865. return -1;
  1866. }
  1867. /* leave this %i alone, non-base-10 input is useful here */
  1868. if (sscanf(str, "%30i", &ret) != 1) {
  1869. return -1;
  1870. }
  1871. return ret;
  1872. }
  1873. static int mycompar(const void *a, const void *b)
  1874. {
  1875. char **x = (char **) a;
  1876. char **y = (char **) b;
  1877. int xoff,yoff;
  1878. if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
  1879. if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
  1880. return(strcmp((*x) + xoff,(*y) + yoff));
  1881. }
  1882. static int topcompar(const void *a, const void *b)
  1883. {
  1884. struct rpt_topkey *x = (struct rpt_topkey *) a;
  1885. struct rpt_topkey *y = (struct rpt_topkey *) b;
  1886. return(x->timesince - y->timesince);
  1887. }
  1888. #ifdef __RPT_NOTCH
  1889. /* rpt filter routine */
  1890. static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
  1891. {
  1892. int i,j;
  1893. struct rptfilter *f;
  1894. for(i = 0; i < len; i++)
  1895. {
  1896. for(j = 0; j < MAXFILTERS; j++)
  1897. {
  1898. f = &myrpt->filters[j];
  1899. if (!*f->desc) continue;
  1900. f->x0 = f->x1; f->x1 = f->x2;
  1901. f->x2 = ((float)buf[i]) / f->gain;
  1902. f->y0 = f->y1; f->y1 = f->y2;
  1903. f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
  1904. + (f->const1 * f->y0) + (f->const2 * f->y1);
  1905. buf[i] = (short)f->y2;
  1906. }
  1907. }
  1908. }
  1909. #endif
  1910. /*
  1911. Get the time for the machine's time zone
  1912. Note: Asterisk requires a copy of localtime
  1913. in the /etc directory for this to work properly.
  1914. If /etc/localtime is not present, you will get
  1915. GMT time! This is especially important on systems
  1916. running embedded linux distributions as they don't usually
  1917. have support for locales.
  1918. If OLD_ASTERISK is defined, then the older localtime_r
  1919. function will be used. The /etc/localtime file is not
  1920. required in this case. This provides backward compatibility
  1921. with Asterisk 1.2 systems.
  1922. */
  1923. #ifdef NEW_ASTERISK
  1924. static void rpt_localtime( time_t * t, struct ast_tm *lt)
  1925. {
  1926. struct timeval when;
  1927. when.tv_sec = *t;
  1928. when.tv_usec = 0;
  1929. ast_localtime(&when, lt, NULL);
  1930. }
  1931. #else
  1932. static void rpt_localtime( time_t * t, struct tm *lt)
  1933. {
  1934. #ifdef OLD_ASTERISK
  1935. localtime_r(t, lt);
  1936. #else
  1937. ast_localtime(t, lt, NULL);
  1938. #endif
  1939. }
  1940. #endif
  1941. /* Retrieve an int from a config file */
  1942. static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
  1943. {
  1944. char *var;
  1945. int ret;
  1946. char include_zero = 0;
  1947. if(min < 0){ /* If min is negative, this means include 0 as a valid entry */
  1948. min = -min;
  1949. include_zero = 1;
  1950. }
  1951. var = (char *) ast_variable_retrieve(myrpt->cfg, category, name);
  1952. if(var){
  1953. ret = myatoi(var);
  1954. if(include_zero && !ret)
  1955. return 0;
  1956. if(ret < min)
  1957. ret = min;
  1958. if(ret > max)
  1959. ret = max;
  1960. }
  1961. else
  1962. ret = defl;
  1963. return ret;
  1964. }
  1965. static void load_rpt_vars(int n,int init)
  1966. {
  1967. char *this,*val;
  1968. int i,j,longestnode;
  1969. struct ast_variable *vp;
  1970. struct ast_config *cfg;
  1971. char *strs[100];
  1972. char s1[256];
  1973. static char *cs_keywords[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
  1974. "ufena","ufdis","atena","atdis",NULL};
  1975. if (option_verbose > 2)
  1976. ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
  1977. (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
  1978. ast_mutex_lock(&rpt_vars[n].lock);
  1979. if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
  1980. #ifdef NEW_ASTERISK
  1981. cfg = ast_config_load("rpt.conf",config_flags);
  1982. #else
  1983. cfg = ast_config_load("rpt.conf");
  1984. #endif
  1985. if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
  1986. ast_mutex_unlock(&rpt_vars[n].lock);
  1987. ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
  1988. pthread_exit(NULL);
  1989. }
  1990. rpt_vars[n].cfg = cfg;
  1991. this = rpt_vars[n].name;
  1992. memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
  1993. if (init)
  1994. {
  1995. char *cp;
  1996. int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
  1997. cp = (char *) &rpt_vars[n].p;
  1998. memset(cp + sizeof(rpt_vars[n].p),0,
  1999. sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
  2000. rpt_vars[n].tele.next = &rpt_vars[n].tele;
  2001. rpt_vars[n].tele.prev = &rpt_vars[n].tele;
  2002. rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
  2003. rpt_vars[n].tailmessagen = 0;
  2004. }
  2005. #ifdef __RPT_NOTCH
  2006. /* zot out filters stuff */
  2007. memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
  2008. #endif
  2009. val = (char *) ast_variable_retrieve(cfg,this,"context");
  2010. if (val) rpt_vars[n].p.ourcontext = val;
  2011. else rpt_vars[n].p.ourcontext = this;
  2012. val = (char *) ast_variable_retrieve(cfg,this,"callerid");
  2013. if (val) rpt_vars[n].p.ourcallerid = val;
  2014. val = (char *) ast_variable_retrieve(cfg,this,"accountcode");
  2015. if (val) rpt_vars[n].p.acctcode = val;
  2016. val = (char *) ast_variable_retrieve(cfg,this,"idrecording");
  2017. if (val) rpt_vars[n].p.ident = val;
  2018. val = (char *) ast_variable_retrieve(cfg,this,"hangtime");
  2019. if (val) rpt_vars[n].p.hangtime = atoi(val);
  2020. else rpt_vars[n].p.hangtime = HANGTIME;
  2021. val = (char *) ast_variable_retrieve(cfg,this,"althangtime");
  2022. if (val) rpt_vars[n].p.althangtime = atoi(val);
  2023. else rpt_vars[n].p.althangtime = HANGTIME;
  2024. val = (char *) ast_variable_retrieve(cfg,this,"totime");
  2025. if (val) rpt_vars[n].p.totime = atoi(val);
  2026. else rpt_vars[n].p.totime = TOTIME;
  2027. val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
  2028. if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
  2029. else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
  2030. val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
  2031. if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
  2032. else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
  2033. val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
  2034. if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
  2035. else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
  2036. val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
  2037. if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
  2038. else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
  2039. val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
  2040. if (val) rpt_vars[n].p.statpost_program = val;
  2041. else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
  2042. rpt_vars[n].p.statpost_url =
  2043. (char *) ast_variable_retrieve(cfg,this,"statpost_url");
  2044. rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
  2045. rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
  2046. rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
  2047. rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", -60000, 2400000, IDTIME); /* Enforce a min max including zero */
  2048. rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
  2049. val = (char *) ast_variable_retrieve(cfg,this,"tonezone");
  2050. if (val) rpt_vars[n].p.tonezone = val;
  2051. rpt_vars[n].p.tailmessages[0] = 0;
  2052. rpt_vars[n].p.tailmessagemax = 0;
  2053. val = (char *) ast_variable_retrieve(cfg,this,"tailmessagelist");
  2054. if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
  2055. val = (char *) ast_variable_retrieve(cfg,this,"memory");
  2056. if (!val) val = MEMORY;
  2057. rpt_vars[n].p.memory = val;
  2058. val = (char *) ast_variable_retrieve(cfg,this,"macro");
  2059. if (!val) val = MACRO;
  2060. rpt_vars[n].p.macro = val;
  2061. val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
  2062. if (!val) val = TONEMACRO;
  2063. rpt_vars[n].p.tonemacro = val;
  2064. val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
  2065. if (val) rpt_vars[n].p.startupmacro = val;
  2066. val = (char *) ast_variable_retrieve(cfg,this,"iobase");
  2067. /* do not use atoi() here, we need to be able to have
  2068. the input specified in hex or decimal so we use
  2069. sscanf with a %i */
  2070. if ((!val) || (sscanf(val,"%30i",&rpt_vars[n].p.iobase) != 1))
  2071. rpt_vars[n].p.iobase = DEFAULT_IOBASE;
  2072. val = (char *) ast_variable_retrieve(cfg,this,"ioport");
  2073. rpt_vars[n].p.ioport = val;
  2074. val = (char *) ast_variable_retrieve(cfg,this,"functions");
  2075. if (!val)
  2076. {
  2077. val = FUNCTIONS;
  2078. rpt_vars[n].p.simple = 1;
  2079. }
  2080. rpt_vars[n].p.functions = val;
  2081. val = (char *) ast_variable_retrieve(cfg,this,"link_functions");
  2082. if (val) rpt_vars[n].p.link_functions = val;
  2083. else
  2084. rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
  2085. val = (char *) ast_variable_retrieve(cfg,this,"phone_functions");
  2086. if (val) rpt_vars[n].p.phone_functions = val;
  2087. val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
  2088. if (val) rpt_vars[n].p.dphone_functions = val;
  2089. val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
  2090. if (val) rpt_vars[n].p.alt_functions = val;
  2091. val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
  2092. if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
  2093. rpt_vars[n].p.funcchar = *val;
  2094. val = (char *) ast_variable_retrieve(cfg,this,"endchar");
  2095. if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
  2096. rpt_vars[n].p.endchar = *val;
  2097. val = (char *) ast_variable_retrieve(cfg,this,"nobusyout");
  2098. if (val) rpt_vars[n].p.nobusyout = ast_true(val);
  2099. val = (char *) ast_variable_retrieve(cfg,this,"notelemtx");
  2100. if (val) rpt_vars[n].p.notelemtx = ast_true(val);
  2101. val = (char *) ast_variable_retrieve(cfg,this,"propagate_dtmf");
  2102. if (val) rpt_vars[n].p.propagate_dtmf = ast_true(val);
  2103. val = (char *) ast_variable_retrieve(cfg,this,"propagate_phonedtmf");
  2104. if (val) rpt_vars[n].p.propagate_phonedtmf = ast_true(val);
  2105. val = (char *) ast_variable_retrieve(cfg,this,"linktolink");
  2106. if (val) rpt_vars[n].p.linktolink = ast_true(val);
  2107. val = (char *) ast_variable_retrieve(cfg,this,"nodes");
  2108. if (!val) val = NODES;
  2109. rpt_vars[n].p.nodes = val;
  2110. val = (char *) ast_variable_retrieve(cfg,this,"extnodes");
  2111. if (!val) val = EXTNODES;
  2112. rpt_vars[n].p.extnodes = val;
  2113. val = (char *) ast_variable_retrieve(cfg,this,"extnodefile");
  2114. if (!val) val = EXTNODEFILE;
  2115. rpt_vars[n].p.extnodefile = val;
  2116. val = (char *) ast_variable_retrieve(cfg,this,"archivedir");
  2117. if (val) rpt_vars[n].p.archivedir = val;
  2118. val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
  2119. if (val) rpt_vars[n].p.authlevel = atoi(val);
  2120. else rpt_vars[n].p.authlevel = 0;
  2121. val = (char *) ast_variable_retrieve(cfg,this,"parrot");
  2122. if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
  2123. else rpt_vars[n].p.parrotmode = 0;
  2124. val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
  2125. if (val) rpt_vars[n].p.parrottime = atoi(val);
  2126. else rpt_vars[n].p.parrottime = PARROTTIME;
  2127. val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
  2128. rpt_vars[n].p.rptnode = val;
  2129. val = (char *) ast_variable_retrieve(cfg,this,"mars");
  2130. if (val) rpt_vars[n].p.remote_mars = atoi(val);
  2131. else rpt_vars[n].p.remote_mars = 0;
  2132. val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
  2133. if (val) rpt_vars[n].p.monminblocks = atol(val);
  2134. else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
  2135. val = (char *) ast_variable_retrieve(cfg,this,"remote_inact_timeout");
  2136. if (val) rpt_vars[n].p.remoteinacttimeout = atoi(val);
  2137. else rpt_vars[n].p.remoteinacttimeout = DEFAULT_REMOTE_INACT_TIMEOUT;
  2138. val = (char *) ast_variable_retrieve(cfg,this,"civaddr");
  2139. if (val) rpt_vars[n].p.civaddr = atoi(val);
  2140. else rpt_vars[n].p.civaddr = DEFAULT_CIV_ADDR;
  2141. val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout");
  2142. if (val) rpt_vars[n].p.remotetimeout = atoi(val);
  2143. else rpt_vars[n].p.remotetimeout = DEFAULT_REMOTE_TIMEOUT;
  2144. val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning");
  2145. if (val) rpt_vars[n].p.remotetimeoutwarning = atoi(val);
  2146. else rpt_vars[n].p.remotetimeoutwarning = DEFAULT_REMOTE_TIMEOUT_WARNING;
  2147. val = (char *) ast_variable_retrieve(cfg,this,"remote_timeout_warning_freq");
  2148. if (val) rpt_vars[n].p.remotetimeoutwarningfreq = atoi(val);
  2149. else rpt_vars[n].p.remotetimeoutwarningfreq = DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ;
  2150. #ifdef __RPT_NOTCH
  2151. val = (char *) ast_variable_retrieve(cfg,this,"rxnotch");
  2152. if (val) {
  2153. i = finddelim(val,strs,MAXFILTERS * 2);
  2154. i &= ~1; /* force an even number, rounded down */
  2155. if (i >= 2) for(j = 0; j < i; j += 2)
  2156. {
  2157. rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
  2158. &rpt_vars[n].filters[j >> 1].gain,
  2159. &rpt_vars[n].filters[j >> 1].const0,
  2160. &rpt_vars[n].filters[j >> 1].const1,
  2161. &rpt_vars[n].filters[j >> 1].const2);
  2162. sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
  2163. strs[j],strs[j + 1]);
  2164. }
  2165. }
  2166. #endif
  2167. val = (char *) ast_variable_retrieve(cfg,this,"inxlat");
  2168. if (val) {
  2169. memset(&rpt_vars[n].p.inxlat,0,sizeof(struct rpt_xlat));
  2170. i = finddelim(val,strs,3);
  2171. if (i) strncpy(rpt_vars[n].p.inxlat.funccharseq,strs[0],MAXXLAT - 1);
  2172. if (i > 1) strncpy(rpt_vars[n].p.inxlat.endcharseq,strs[1],MAXXLAT - 1);
  2173. if (i > 2) strncpy(rpt_vars[n].p.inxlat.passchars,strs[2],MAXXLAT - 1);
  2174. }
  2175. val = (char *) ast_variable_retrieve(cfg,this,"outxlat");
  2176. if (val) {
  2177. memset(&rpt_vars[n].p.outxlat,0,sizeof(struct rpt_xlat));
  2178. i = finddelim(val,strs,3);
  2179. if (i) strncpy(rpt_vars[n].p.outxlat.funccharseq,strs[0],MAXXLAT - 1);
  2180. if (i > 1) strncpy(rpt_vars[n].p.outxlat.endcharseq,strs[1],MAXXLAT - 1);
  2181. if (i > 2) strncpy(rpt_vars[n].p.outxlat.passchars,strs[2],MAXXLAT - 1);
  2182. }
  2183. /* retreive the stanza name for the control states if there is one */
  2184. val = (char *) ast_variable_retrieve(cfg,this,"controlstates");
  2185. rpt_vars[n].p.csstanzaname = val;
  2186. /* retreive the stanza name for the scheduler if there is one */
  2187. val = (char *) ast_variable_retrieve(cfg,this,"scheduler");
  2188. rpt_vars[n].p.skedstanzaname = val;
  2189. /* retreive the stanza name for the txlimits */
  2190. val = (char *) ast_variable_retrieve(cfg,this,"txlimits");
  2191. rpt_vars[n].p.txlimitsstanzaname = val;
  2192. longestnode = 0;
  2193. vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
  2194. while(vp){
  2195. j = strlen(vp->name);
  2196. if (j > longestnode)
  2197. longestnode = j;
  2198. vp = vp->next;
  2199. }
  2200. rpt_vars[n].longestnode = longestnode;
  2201. /*
  2202. * For this repeater, Determine the length of the longest function
  2203. */
  2204. rpt_vars[n].longestfunc = 0;
  2205. vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
  2206. while(vp){
  2207. j = strlen(vp->name);
  2208. if (j > rpt_vars[n].longestfunc)
  2209. rpt_vars[n].longestfunc = j;
  2210. vp = vp->next;
  2211. }
  2212. /*
  2213. * For this repeater, Determine the length of the longest function
  2214. */
  2215. rpt_vars[n].link_longestfunc = 0;
  2216. vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
  2217. while(vp){
  2218. j = strlen(vp->name);
  2219. if (j > rpt_vars[n].link_longestfunc)
  2220. rpt_vars[n].link_longestfunc = j;
  2221. vp = vp->next;
  2222. }
  2223. rpt_vars[n].phone_longestfunc = 0;
  2224. if (rpt_vars[n].p.phone_functions)
  2225. {
  2226. vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
  2227. while(vp){
  2228. j = strlen(vp->name);
  2229. if (j > rpt_vars[n].phone_longestfunc)
  2230. rpt_vars[n].phone_longestfunc = j;
  2231. vp = vp->next;
  2232. }
  2233. }
  2234. rpt_vars[n].dphone_longestfunc = 0;
  2235. if (rpt_vars[n].p.dphone_functions)
  2236. {
  2237. vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
  2238. while(vp){
  2239. j = strlen(vp->name);
  2240. if (j > rpt_vars[n].dphone_longestfunc)
  2241. rpt_vars[n].dphone_longestfunc = j;
  2242. vp = vp->next;
  2243. }
  2244. }
  2245. rpt_vars[n].alt_longestfunc = 0;
  2246. if (rpt_vars[n].p.alt_functions)
  2247. {
  2248. vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
  2249. while(vp){
  2250. j = strlen(vp->name);
  2251. if (j > rpt_vars[n].alt_longestfunc)
  2252. rpt_vars[n].alt_longestfunc = j;
  2253. vp = vp->next;
  2254. }
  2255. }
  2256. rpt_vars[n].macro_longest = 1;
  2257. vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
  2258. while(vp){
  2259. j = strlen(vp->name);
  2260. if (j > rpt_vars[n].macro_longest)
  2261. rpt_vars[n].macro_longest = j;
  2262. vp = vp->next;
  2263. }
  2264. /* Browse for control states */
  2265. if(rpt_vars[n].p.csstanzaname)
  2266. vp = ast_variable_browse(cfg, rpt_vars[n].p.csstanzaname);
  2267. else
  2268. vp = NULL;
  2269. for( i = 0 ; vp && (i < MAX_SYSSTATES) ; i++){ /* Iterate over the number of control state lines in the stanza */
  2270. int k,nukw,statenum;
  2271. statenum=atoi(vp->name);
  2272. strncpy(s1, vp->value, 255);
  2273. s1[255] = 0;
  2274. nukw = finddelim(s1,strs,32);
  2275. for (k = 0 ; k < nukw ; k++){ /* for each user specified keyword */
  2276. for(j = 0 ; cs_keywords[j] != NULL ; j++){ /* try to match to one in our internal table */
  2277. if(!strcmp(strs[k],cs_keywords[j])){
  2278. switch(j){
  2279. case 0: /* rptena */
  2280. rpt_vars[n].p.s[statenum].txdisable = 0;
  2281. break;
  2282. case 1: /* rptdis */
  2283. rpt_vars[n].p.s[statenum].txdisable = 1;
  2284. break;
  2285. case 2: /* apena */
  2286. rpt_vars[n].p.s[statenum].autopatchdisable = 0;
  2287. break;
  2288. case 3: /* apdis */
  2289. rpt_vars[n].p.s[statenum].autopatchdisable = 1;
  2290. break;
  2291. case 4: /* lnkena */
  2292. rpt_vars[n].p.s[statenum].linkfundisable = 0;
  2293. break;
  2294. case 5: /* lnkdis */
  2295. rpt_vars[n].p.s[statenum].linkfundisable = 1;
  2296. break;
  2297. case 6: /* totena */
  2298. rpt_vars[n].p.s[statenum].totdisable = 0;
  2299. break;
  2300. case 7: /* totdis */
  2301. rpt_vars[n].p.s[statenum].totdisable = 1;
  2302. break;
  2303. case 8: /* skena */
  2304. rpt_vars[n].p.s[statenum].schedulerdisable = 0;
  2305. break;
  2306. case 9: /* skdis */
  2307. rpt_vars[n].p.s[statenum].schedulerdisable = 1;
  2308. break;
  2309. case 10: /* ufena */
  2310. rpt_vars[n].p.s[statenum].userfundisable = 0;
  2311. break;
  2312. case 11: /* ufdis */
  2313. rpt_vars[n].p.s[statenum].userfundisable = 1;
  2314. break;
  2315. case 12: /* atena */
  2316. rpt_vars[n].p.s[statenum].alternatetail = 1;
  2317. break;
  2318. case 13: /* atdis */
  2319. rpt_vars[n].p.s[statenum].alternatetail = 0;
  2320. break;
  2321. default:
  2322. ast_log(LOG_WARNING,
  2323. "Unhandled control state keyword %s", cs_keywords[i]);
  2324. break;
  2325. }
  2326. }
  2327. }
  2328. }
  2329. vp = vp->next;
  2330. }
  2331. ast_mutex_unlock(&rpt_vars[n].lock);
  2332. }
  2333. /*
  2334. * Enable or disable debug output at a given level at the console
  2335. */
  2336. static int rpt_do_debug(int fd, int argc, const char * const *argv)
  2337. {
  2338. int newlevel;
  2339. if (argc != 4) {
  2340. return RESULT_SHOWUSAGE;
  2341. }
  2342. newlevel = myatoi(argv[3]);
  2343. if (newlevel < 0 || newlevel > 7) {
  2344. return RESULT_SHOWUSAGE;
  2345. }
  2346. if (newlevel) {
  2347. ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
  2348. } else {
  2349. ast_cli(fd, "app_rpt Debugging disabled\n");
  2350. }
  2351. debug = newlevel;
  2352. return RESULT_SUCCESS;
  2353. }
  2354. /*
  2355. * Dump rpt struct debugging onto console
  2356. */
  2357. static int rpt_do_dump(int fd, int argc, const char * const *argv)
  2358. {
  2359. int i;
  2360. if (argc != 3)
  2361. return RESULT_SHOWUSAGE;
  2362. for(i = 0; i < nrpts; i++)
  2363. {
  2364. if (!strcmp(argv[2],rpt_vars[i].name))
  2365. {
  2366. rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
  2367. ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
  2368. return RESULT_SUCCESS;
  2369. }
  2370. }
  2371. return RESULT_FAILURE;
  2372. }
  2373. /*
  2374. * Dump statistics onto console
  2375. */
  2376. static int rpt_do_stats(int fd, int argc, const char * const *argv)
  2377. {
  2378. int i,j,numoflinks;
  2379. int dailytxtime, dailykerchunks;
  2380. time_t now;
  2381. int totalkerchunks, dailykeyups, totalkeyups, timeouts;
  2382. int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
  2383. int uptime;
  2384. long long totaltxtime;
  2385. struct rpt_link *l;
  2386. char *listoflinks[MAX_STAT_LINKS];
  2387. char *lastdtmfcommand,*parrot_ena;
  2388. char *tot_state, *ider_state, *patch_state;
  2389. char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
  2390. char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
  2391. struct rpt *myrpt;
  2392. static char *not_applicable = "N/A";
  2393. if(argc != 3)
  2394. return RESULT_SHOWUSAGE;
  2395. tot_state = ider_state =
  2396. patch_state = reverse_patch_state =
  2397. input_signal = not_applicable;
  2398. called_number = lastdtmfcommand = NULL;
  2399. time(&now);
  2400. for(i = 0; i < nrpts; i++)
  2401. {
  2402. if (!strcmp(argv[2],rpt_vars[i].name)){
  2403. /* Make a copy of all stat variables while locked */
  2404. myrpt = &rpt_vars[i];
  2405. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  2406. uptime = (int)(now - starttime);
  2407. dailytxtime = myrpt->dailytxtime;
  2408. totaltxtime = myrpt->totaltxtime;
  2409. dailykeyups = myrpt->dailykeyups;
  2410. totalkeyups = myrpt->totalkeyups;
  2411. dailykerchunks = myrpt->dailykerchunks;
  2412. totalkerchunks = myrpt->totalkerchunks;
  2413. dailyexecdcommands = myrpt->dailyexecdcommands;
  2414. totalexecdcommands = myrpt->totalexecdcommands;
  2415. timeouts = myrpt->timeouts;
  2416. /* Traverse the list of connected nodes */
  2417. reverse_patch_state = "DOWN";
  2418. numoflinks = 0;
  2419. l = myrpt->links.next;
  2420. while(l && (l != &myrpt->links)){
  2421. if(numoflinks >= MAX_STAT_LINKS){
  2422. ast_log(LOG_NOTICE,
  2423. "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
  2424. break;
  2425. }
  2426. if (l->name[0] == '0'){ /* Skip '0' nodes */
  2427. reverse_patch_state = "UP";
  2428. l = l->next;
  2429. continue;
  2430. }
  2431. listoflinks[numoflinks] = ast_strdup(l->name);
  2432. if(listoflinks[numoflinks] == NULL){
  2433. break;
  2434. }
  2435. else{
  2436. numoflinks++;
  2437. }
  2438. l = l->next;
  2439. }
  2440. if(myrpt->keyed)
  2441. input_signal = "YES";
  2442. else
  2443. input_signal = "NO";
  2444. if(myrpt->p.parrotmode)
  2445. parrot_ena = "ENABLED";
  2446. else
  2447. parrot_ena = "DISABLED";
  2448. if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
  2449. sys_ena = "DISABLED";
  2450. else
  2451. sys_ena = "ENABLED";
  2452. if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
  2453. tot_ena = "DISABLED";
  2454. else
  2455. tot_ena = "ENABLED";
  2456. if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
  2457. link_ena = "DISABLED";
  2458. else
  2459. link_ena = "ENABLED";
  2460. if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
  2461. patch_ena = "DISABLED";
  2462. else
  2463. patch_ena = "ENABLED";
  2464. if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
  2465. sch_ena = "DISABLED";
  2466. else
  2467. sch_ena = "ENABLED";
  2468. if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
  2469. user_funs = "DISABLED";
  2470. else
  2471. user_funs = "ENABLED";
  2472. if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
  2473. tail_type = "ALTERNATE";
  2474. else
  2475. tail_type = "STANDARD";
  2476. if(!myrpt->totimer)
  2477. tot_state = "TIMED OUT!";
  2478. else if(myrpt->totimer != myrpt->p.totime)
  2479. tot_state = "ARMED";
  2480. else
  2481. tot_state = "RESET";
  2482. if(myrpt->tailid)
  2483. ider_state = "QUEUED IN TAIL";
  2484. else if(myrpt->mustid)
  2485. ider_state = "QUEUED FOR CLEANUP";
  2486. else
  2487. ider_state = "CLEAN";
  2488. switch(myrpt->callmode){
  2489. case 1:
  2490. patch_state = "DIALING";
  2491. break;
  2492. case 2:
  2493. patch_state = "CONNECTING";
  2494. break;
  2495. case 3:
  2496. patch_state = "UP";
  2497. break;
  2498. case 4:
  2499. patch_state = "CALL FAILED";
  2500. break;
  2501. default:
  2502. patch_state = "DOWN";
  2503. }
  2504. if(strlen(myrpt->exten)){
  2505. called_number = ast_strdup(myrpt->exten);
  2506. }
  2507. if(strlen(myrpt->lastdtmfcommand)){
  2508. lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
  2509. }
  2510. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  2511. ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
  2512. ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
  2513. ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
  2514. ast_cli(fd, "System...........................................: %s\n", sys_ena);
  2515. ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
  2516. ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
  2517. ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
  2518. ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
  2519. ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
  2520. ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
  2521. ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
  2522. ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
  2523. ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
  2524. ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
  2525. ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
  2526. ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
  2527. ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
  2528. ast_cli(fd, "Last DTMF command executed.......................: %s\n",
  2529. (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
  2530. hours = dailytxtime/3600000;
  2531. dailytxtime %= 3600000;
  2532. minutes = dailytxtime/60000;
  2533. dailytxtime %= 60000;
  2534. seconds = dailytxtime/1000;
  2535. dailytxtime %= 1000;
  2536. ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
  2537. hours, minutes, seconds, dailytxtime);
  2538. hours = (int) totaltxtime/3600000;
  2539. totaltxtime %= 3600000;
  2540. minutes = (int) totaltxtime/60000;
  2541. totaltxtime %= 60000;
  2542. seconds = (int) totaltxtime/1000;
  2543. totaltxtime %= 1000;
  2544. ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
  2545. hours, minutes, seconds, (int) totaltxtime);
  2546. hours = uptime/3600;
  2547. uptime %= 3600;
  2548. minutes = uptime/60;
  2549. uptime %= 60;
  2550. ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
  2551. hours, minutes, uptime);
  2552. ast_cli(fd, "Nodes currently connected to us..................: ");
  2553. if(!numoflinks){
  2554. ast_cli(fd,"<NONE>");
  2555. }
  2556. else{
  2557. for(j = 0 ;j < numoflinks; j++){
  2558. ast_cli(fd, "%s", listoflinks[j]);
  2559. if(j % 4 == 3){
  2560. ast_cli(fd, "\n");
  2561. ast_cli(fd, " : ");
  2562. }
  2563. else{
  2564. if((numoflinks - 1) - j > 0)
  2565. ast_cli(fd, ", ");
  2566. }
  2567. }
  2568. }
  2569. ast_cli(fd,"\n");
  2570. ast_cli(fd, "Autopatch........................................: %s\n", patch_ena);
  2571. ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
  2572. ast_cli(fd, "Autopatch called number..........................: %s\n",
  2573. (called_number && strlen(called_number)) ? called_number : not_applicable);
  2574. ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
  2575. ast_cli(fd, "User linking commands............................: %s\n", link_ena);
  2576. ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
  2577. for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
  2578. ast_free(listoflinks[j]);
  2579. }
  2580. ast_free(called_number);
  2581. ast_free(lastdtmfcommand);
  2582. return RESULT_SUCCESS;
  2583. }
  2584. }
  2585. return RESULT_FAILURE;
  2586. }
  2587. /*
  2588. * Link stats function
  2589. */
  2590. static int rpt_do_lstats(int fd, int argc, const char * const *argv)
  2591. {
  2592. int i;
  2593. char *connstate;
  2594. struct rpt *myrpt;
  2595. struct rpt_link *l;
  2596. struct rpt_lstat *s,*t;
  2597. struct rpt_lstat s_head;
  2598. if(argc != 3)
  2599. return RESULT_SHOWUSAGE;
  2600. s = NULL;
  2601. s_head.next = &s_head;
  2602. s_head.prev = &s_head;
  2603. for(i = 0; i < nrpts; i++)
  2604. {
  2605. if (!strcmp(argv[2],rpt_vars[i].name)){
  2606. /* Make a copy of all stat variables while locked */
  2607. myrpt = &rpt_vars[i];
  2608. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  2609. /* Traverse the list of connected nodes */
  2610. l = myrpt->links.next;
  2611. while(l && (l != &myrpt->links)){
  2612. if (l->name[0] == '0'){ /* Skip '0' nodes */
  2613. l = l->next;
  2614. continue;
  2615. }
  2616. if((s = (struct rpt_lstat *) ast_malloc(sizeof(struct rpt_lstat))) == NULL){
  2617. ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
  2618. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  2619. return RESULT_FAILURE;
  2620. }
  2621. memset(s, 0, sizeof(struct rpt_lstat));
  2622. strncpy(s->name, l->name, MAXREMSTR - 1);
  2623. if (l->chan) pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
  2624. else strcpy(s->peer,"(none)");
  2625. s->mode = l->mode;
  2626. s->outbound = l->outbound;
  2627. s->reconnects = l->reconnects;
  2628. s->connecttime = l->connecttime;
  2629. s->thisconnected = l->thisconnected;
  2630. memcpy(s->chan_stat,l->chan_stat,NRPTSTAT * sizeof(struct rpt_chan_stat));
  2631. insque((struct qelem *) s, (struct qelem *) s_head.next);
  2632. memset(l->chan_stat,0,NRPTSTAT * sizeof(struct rpt_chan_stat));
  2633. l = l->next;
  2634. }
  2635. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  2636. ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
  2637. ast_cli(fd, "---- ---- ---------- --------- ------------ -------------\n");
  2638. for(s = s_head.next; s != &s_head; s = s->next){
  2639. int hours, minutes, seconds;
  2640. long long connecttime = s->connecttime;
  2641. char conntime[21];
  2642. hours = (int) connecttime/3600000;
  2643. connecttime %= 3600000;
  2644. minutes = (int) connecttime/60000;
  2645. connecttime %= 60000;
  2646. seconds = (int) connecttime/1000;
  2647. connecttime %= 1000;
  2648. snprintf(conntime, 20, "%02d:%02d:%02d.%d",
  2649. hours, minutes, seconds, (int) connecttime);
  2650. conntime[20] = 0;
  2651. if(s->thisconnected)
  2652. connstate = "ESTABLISHED";
  2653. else
  2654. connstate = "CONNECTING";
  2655. ast_cli(fd, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
  2656. s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime, connstate);
  2657. }
  2658. /* destroy our local link queue */
  2659. s = s_head.next;
  2660. while(s != &s_head){
  2661. t = s;
  2662. s = s->next;
  2663. remque((struct qelem *)t);
  2664. ast_free(t);
  2665. }
  2666. return RESULT_SUCCESS;
  2667. }
  2668. }
  2669. return RESULT_FAILURE;
  2670. }
  2671. /*
  2672. * List all nodes connected, directly or indirectly
  2673. */
  2674. static int rpt_do_nodes(int fd, int argc, const char * const *argv)
  2675. {
  2676. int i,j;
  2677. char ns;
  2678. char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
  2679. struct rpt *myrpt;
  2680. if(argc != 3)
  2681. return RESULT_SHOWUSAGE;
  2682. for(i = 0; i < nrpts; i++)
  2683. {
  2684. if (!strcmp(argv[2],rpt_vars[i].name)){
  2685. /* Make a copy of all stat variables while locked */
  2686. myrpt = &rpt_vars[i];
  2687. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  2688. __mklinklist(myrpt,NULL,lbuf);
  2689. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  2690. /* parse em */
  2691. ns = finddelim(lbuf,strs,MAXLINKLIST);
  2692. /* sort em */
  2693. if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
  2694. ast_cli(fd,"\n");
  2695. ast_cli(fd, "************************* CONNECTED NODES *************************\n\n");
  2696. for(j = 0 ;; j++){
  2697. if(!strs[j]){
  2698. if(!j){
  2699. ast_cli(fd,"<NONE>");
  2700. }
  2701. break;
  2702. }
  2703. ast_cli(fd, "%s", strs[j]);
  2704. if(j % 8 == 7){
  2705. ast_cli(fd, "\n");
  2706. }
  2707. else{
  2708. if(strs[j + 1])
  2709. ast_cli(fd, ", ");
  2710. }
  2711. }
  2712. ast_cli(fd,"\n\n");
  2713. return RESULT_SUCCESS;
  2714. }
  2715. }
  2716. return RESULT_FAILURE;
  2717. }
  2718. /*
  2719. * List all locally configured nodes
  2720. */
  2721. static int rpt_do_local_nodes(int fd, int argc, const char * const *argv)
  2722. {
  2723. int i;
  2724. ast_cli(fd, "\nNode\n----\n");
  2725. for (i=0; i< nrpts; i++)
  2726. {
  2727. ast_cli(fd, "%s\n", rpt_vars[i].name);
  2728. } /* for i */
  2729. ast_cli(fd,"\n");
  2730. return RESULT_SUCCESS;
  2731. }
  2732. /*
  2733. * reload vars
  2734. */
  2735. static int rpt_do_reload(int fd, int argc, const char * const *argv)
  2736. {
  2737. int n;
  2738. if (argc > 2) return RESULT_SHOWUSAGE;
  2739. for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
  2740. return RESULT_FAILURE;
  2741. }
  2742. /*
  2743. * restart app_rpt
  2744. */
  2745. static int rpt_do_restart(int fd, int argc, const char * const *argv)
  2746. {
  2747. int i;
  2748. if (argc > 2) return RESULT_SHOWUSAGE;
  2749. for(i = 0; i < nrpts; i++)
  2750. {
  2751. if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
  2752. }
  2753. return RESULT_FAILURE;
  2754. }
  2755. /*
  2756. * send an app_rpt DTMF function from the CLI
  2757. */
  2758. static int rpt_do_fun(int fd, int argc, const char * const *argv)
  2759. {
  2760. int i,busy=0;
  2761. if (argc != 4) return RESULT_SHOWUSAGE;
  2762. for(i = 0; i < nrpts; i++){
  2763. if(!strcmp(argv[2], rpt_vars[i].name)){
  2764. struct rpt *myrpt = &rpt_vars[i];
  2765. rpt_mutex_lock(&myrpt->lock);
  2766. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(argv[3])){
  2767. rpt_mutex_unlock(&myrpt->lock);
  2768. busy=1;
  2769. }
  2770. if(!busy){
  2771. myrpt->macrotimer = MACROTIME;
  2772. strncat(myrpt->macrobuf,argv[3],MAXMACRO - 1);
  2773. }
  2774. rpt_mutex_unlock(&myrpt->lock);
  2775. }
  2776. }
  2777. if(busy){
  2778. ast_cli(fd, "Function decoder busy");
  2779. }
  2780. return RESULT_FAILURE;
  2781. }
  2782. /*
  2783. the convention is that macros in the data from the rpt() application
  2784. are all at the end of the data, separated by the | and start with a *
  2785. when put into the macro buffer, the characters have their high bit
  2786. set so the macro processor knows they came from the application data
  2787. and to use the alt-functions table.
  2788. sph:
  2789. */
  2790. static int rpt_push_alt_macro(struct rpt *myrpt, char *sptr)
  2791. {
  2792. int busy=0;
  2793. rpt_mutex_lock(&myrpt->lock);
  2794. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(sptr)){
  2795. rpt_mutex_unlock(&myrpt->lock);
  2796. busy=1;
  2797. }
  2798. if(!busy){
  2799. int x;
  2800. if (debug)ast_log(LOG_NOTICE, "rpt_push_alt_macro %s\n",sptr);
  2801. myrpt->macrotimer = MACROTIME;
  2802. for(x = 0; *(sptr + x); x++)
  2803. myrpt->macrobuf[x] = *(sptr + x) | 0x80;
  2804. *(sptr + x) = 0;
  2805. }
  2806. rpt_mutex_unlock(&myrpt->lock);
  2807. if(busy)ast_log(LOG_WARNING, "Function decoder busy on app_rpt command macro.\n");
  2808. return busy;
  2809. }
  2810. /*
  2811. allows us to test rpt() application data commands
  2812. */
  2813. static int rpt_do_fun1(int fd, int argc, const char * const *argv)
  2814. {
  2815. int i;
  2816. if (argc != 4) return RESULT_SHOWUSAGE;
  2817. for(i = 0; i < nrpts; i++){
  2818. if(!strcmp(argv[2], rpt_vars[i].name)){
  2819. struct rpt *myrpt = &rpt_vars[i];
  2820. rpt_push_alt_macro(myrpt, (char *) argv[3]);
  2821. }
  2822. }
  2823. return RESULT_FAILURE;
  2824. }
  2825. /*
  2826. * send an app_rpt **command** from the CLI
  2827. */
  2828. static int rpt_do_cmd(int fd, int argc, const char * const *argv)
  2829. {
  2830. int i, l;
  2831. int busy=0;
  2832. int maxActions = sizeof(function_table)/sizeof(struct function_table_tag);
  2833. int thisRpt = -1;
  2834. int thisAction = -1;
  2835. struct rpt *myrpt = NULL;
  2836. if (argc != 6) return RESULT_SHOWUSAGE;
  2837. for(i = 0; i < nrpts; i++)
  2838. {
  2839. if(!strcmp(argv[2], rpt_vars[i].name))
  2840. {
  2841. thisRpt = i;
  2842. myrpt = &rpt_vars[i];
  2843. break;
  2844. } /* if !strcmp... */
  2845. } /* for i */
  2846. if (thisRpt < 0)
  2847. {
  2848. ast_cli(fd, "Unknown node number %s.\n", argv[2]);
  2849. return RESULT_FAILURE;
  2850. } /* if thisRpt < 0 */
  2851. /* Look up the action */
  2852. l = strlen(argv[3]);
  2853. for(i = 0 ; i < maxActions; i++)
  2854. {
  2855. if(!strncasecmp(argv[3], function_table[i].action, l))
  2856. {
  2857. thisAction = i;
  2858. break;
  2859. } /* if !strncasecmp... */
  2860. } /* for i */
  2861. if (thisAction < 0)
  2862. {
  2863. ast_cli(fd, "Unknown action name %s.\n", argv[3]);
  2864. return RESULT_FAILURE;
  2865. } /* if thisAction < 0 */
  2866. /* at this point, it looks like all the arguments make sense... */
  2867. rpt_mutex_lock(&myrpt->lock);
  2868. if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE)
  2869. {
  2870. rpt_vars[thisRpt].cmdAction.state = CMD_STATE_BUSY;
  2871. rpt_vars[thisRpt].cmdAction.functionNumber = thisAction;
  2872. strncpy(rpt_vars[thisRpt].cmdAction.param, argv[4], MAXDTMF);
  2873. strncpy(rpt_vars[thisRpt].cmdAction.digits, argv[5], MAXDTMF);
  2874. rpt_vars[thisRpt].cmdAction.command_source = SOURCE_RPT;
  2875. rpt_vars[thisRpt].cmdAction.state = CMD_STATE_READY;
  2876. } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
  2877. else
  2878. {
  2879. busy = 1;
  2880. } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
  2881. rpt_mutex_unlock(&myrpt->lock);
  2882. return (busy ? RESULT_FAILURE : RESULT_SUCCESS);
  2883. } /* rpt_do_cmd() */
  2884. static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
  2885. {
  2886. int res;
  2887. if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
  2888. return res;
  2889. while(chan->generatordata) {
  2890. if (ast_safe_sleep(chan,1)) return -1;
  2891. }
  2892. return 0;
  2893. }
  2894. static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
  2895. {
  2896. return play_tone_pair(chan, freq, 0, duration, amplitude);
  2897. }
  2898. static int play_silence(struct ast_channel *chan, int duration)
  2899. {
  2900. return play_tone_pair(chan, 0, 0, duration, 0);
  2901. }
  2902. #ifdef NEW_ASTERISK
  2903. static char *res2cli(int r)
  2904. {
  2905. switch (r)
  2906. {
  2907. case RESULT_SUCCESS:
  2908. return(CLI_SUCCESS);
  2909. case RESULT_SHOWUSAGE:
  2910. return(CLI_SHOWUSAGE);
  2911. default:
  2912. return(CLI_FAILURE);
  2913. }
  2914. }
  2915. static char *handle_cli_debug(struct ast_cli_entry *e,
  2916. int cmd, struct ast_cli_args *a)
  2917. {
  2918. switch (cmd) {
  2919. case CLI_INIT:
  2920. e->command = "rpt debug level";
  2921. e->usage = debug_usage;
  2922. return NULL;
  2923. case CLI_GENERATE:
  2924. return NULL;
  2925. }
  2926. return res2cli(rpt_do_debug(a->fd, a->argc, a->argv));
  2927. }
  2928. static char *handle_cli_dump(struct ast_cli_entry *e,
  2929. int cmd, struct ast_cli_args *a)
  2930. {
  2931. switch (cmd) {
  2932. case CLI_INIT:
  2933. e->command = "rpt dump level";
  2934. e->usage = dump_usage;
  2935. return NULL;
  2936. case CLI_GENERATE:
  2937. return NULL;
  2938. }
  2939. return res2cli(rpt_do_dump(a->fd,a->argc,a->argv));
  2940. }
  2941. static char *handle_cli_stats(struct ast_cli_entry *e,
  2942. int cmd, struct ast_cli_args *a)
  2943. {
  2944. switch (cmd) {
  2945. case CLI_INIT:
  2946. e->command = "rpt stats";
  2947. e->usage = dump_stats;
  2948. return NULL;
  2949. case CLI_GENERATE:
  2950. return NULL;
  2951. }
  2952. return res2cli(rpt_do_stats(a->fd,a->argc,a->argv));
  2953. }
  2954. static char *handle_cli_nodes(struct ast_cli_entry *e,
  2955. int cmd, struct ast_cli_args *a)
  2956. {
  2957. switch (cmd) {
  2958. case CLI_INIT:
  2959. e->command = "rpt nodes";
  2960. e->usage = dump_nodes;
  2961. return NULL;
  2962. case CLI_GENERATE:
  2963. return NULL;
  2964. }
  2965. return res2cli(rpt_do_nodes(a->fd,a->argc,a->argv));
  2966. }
  2967. static char *handle_cli_local_nodes(struct ast_cli_entry *e,
  2968. int cmd, struct ast_cli_args *a)
  2969. {
  2970. switch (cmd) {
  2971. case CLI_INIT:
  2972. e->command = "rpt localnodes";
  2973. e->usage = usage_local_nodes;
  2974. return NULL;
  2975. case CLI_GENERATE:
  2976. return NULL;
  2977. }
  2978. return res2cli(rpt_do_local_nodes(a->fd,a->argc,a->argv));
  2979. }
  2980. static char *handle_cli_lstats(struct ast_cli_entry *e,
  2981. int cmd, struct ast_cli_args *a)
  2982. {
  2983. switch (cmd) {
  2984. case CLI_INIT:
  2985. e->command = "rpt lstats";
  2986. e->usage = dump_lstats;
  2987. return NULL;
  2988. case CLI_GENERATE:
  2989. return NULL;
  2990. }
  2991. return res2cli(rpt_do_lstats(a->fd,a->argc,a->argv));
  2992. }
  2993. static char *handle_cli_reload(struct ast_cli_entry *e,
  2994. int cmd, struct ast_cli_args *a)
  2995. {
  2996. switch (cmd) {
  2997. case CLI_INIT:
  2998. e->command = "rpt reload";
  2999. e->usage = reload_usage;
  3000. return NULL;
  3001. case CLI_GENERATE:
  3002. return NULL;
  3003. }
  3004. return res2cli(rpt_do_reload(a->fd,a->argc,a->argv));
  3005. }
  3006. static char *handle_cli_restart(struct ast_cli_entry *e,
  3007. int cmd, struct ast_cli_args *a)
  3008. {
  3009. switch (cmd) {
  3010. case CLI_INIT:
  3011. e->command = "rpt restart";
  3012. e->usage = restart_usage;
  3013. return NULL;
  3014. case CLI_GENERATE:
  3015. return NULL;
  3016. }
  3017. return res2cli(rpt_do_restart(a->fd,a->argc,a->argv));
  3018. }
  3019. static char *handle_cli_fun(struct ast_cli_entry *e,
  3020. int cmd, struct ast_cli_args *a)
  3021. {
  3022. switch (cmd) {
  3023. case CLI_INIT:
  3024. e->command = "rpt fun";
  3025. e->usage = fun_usage;
  3026. return NULL;
  3027. case CLI_GENERATE:
  3028. return NULL;
  3029. }
  3030. return res2cli(rpt_do_fun(a->fd,a->argc,a->argv));
  3031. }
  3032. static char *handle_cli_fun1(struct ast_cli_entry *e,
  3033. int cmd, struct ast_cli_args *a)
  3034. {
  3035. switch (cmd) {
  3036. case CLI_INIT:
  3037. e->command = "rpt fun1";
  3038. e->usage = fun_usage;
  3039. return NULL;
  3040. case CLI_GENERATE:
  3041. return NULL;
  3042. }
  3043. return res2cli(rpt_do_fun1(a->fd,a->argc,a->argv));
  3044. }
  3045. static char *handle_cli_cmd(struct ast_cli_entry *e,
  3046. int cmd, struct ast_cli_args *a)
  3047. {
  3048. switch (cmd) {
  3049. case CLI_INIT:
  3050. e->command = "rpt cmd";
  3051. e->usage = cmd_usage;
  3052. return NULL;
  3053. case CLI_GENERATE:
  3054. return NULL;
  3055. }
  3056. return res2cli(rpt_do_cmd(a->fd,a->argc,a->argv));
  3057. }
  3058. static struct ast_cli_entry rpt_cli[] = {
  3059. AST_CLI_DEFINE(handle_cli_debug,"Enable app_rpt debugging"),
  3060. AST_CLI_DEFINE(handle_cli_dump,"Dump app_rpt structs for debugging"),
  3061. AST_CLI_DEFINE(handle_cli_stats,"Dump node statistics"),
  3062. AST_CLI_DEFINE(handle_cli_nodes,"Dump node list"),
  3063. AST_CLI_DEFINE(handle_cli_local_nodes, "Dump list of local node numbers"),
  3064. AST_CLI_DEFINE(handle_cli_lstats,"Dump link statistics"),
  3065. AST_CLI_DEFINE(handle_cli_reload,"Reload app_rpt config"),
  3066. AST_CLI_DEFINE(handle_cli_restart,"Restart app_rpt"),
  3067. AST_CLI_DEFINE(handle_cli_fun,"Execute a DTMF function"),
  3068. AST_CLI_DEFINE(handle_cli_fun1,"Execute a DTMF function"),
  3069. AST_CLI_DEFINE(handle_cli_cmd,"Execute a DTMF function")
  3070. };
  3071. #endif
  3072. static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
  3073. {
  3074. static struct morse_bits mbits[] = {
  3075. {0, 0}, /* SPACE */
  3076. {0, 0},
  3077. {6, 18},/* " */
  3078. {0, 0},
  3079. {7, 72},/* $ */
  3080. {0, 0},
  3081. {0, 0},
  3082. {6, 30},/* ' */
  3083. {5, 13},/* ( */
  3084. {6, 29},/* ) */
  3085. {0, 0},
  3086. {5, 10},/* + */
  3087. {6, 51},/* , */
  3088. {6, 33},/* - */
  3089. {6, 42},/* . */
  3090. {5, 9}, /* / */
  3091. {5, 31},/* 0 */
  3092. {5, 30},/* 1 */
  3093. {5, 28},/* 2 */
  3094. {5, 24},/* 3 */
  3095. {5, 16},/* 4 */
  3096. {5, 0}, /* 5 */
  3097. {5, 1}, /* 6 */
  3098. {5, 3}, /* 7 */
  3099. {5, 7}, /* 8 */
  3100. {5, 15},/* 9 */
  3101. {6, 7}, /* : */
  3102. {6, 21},/* ; */
  3103. {0, 0},
  3104. {5, 33},/* = */
  3105. {0, 0},
  3106. {6, 12},/* ? */
  3107. {0, 0},
  3108. {2, 2}, /* A */
  3109. {4, 1}, /* B */
  3110. {4, 5}, /* C */
  3111. {3, 1}, /* D */
  3112. {1, 0}, /* E */
  3113. {4, 4}, /* F */
  3114. {3, 3}, /* G */
  3115. {4, 0}, /* H */
  3116. {2, 0}, /* I */
  3117. {4, 14},/* J */
  3118. {3, 5}, /* K */
  3119. {4, 2}, /* L */
  3120. {2, 3}, /* M */
  3121. {2, 1}, /* N */
  3122. {3, 7}, /* O */
  3123. {4, 6}, /* P */
  3124. {4, 11},/* Q */
  3125. {3, 2}, /* R */
  3126. {3, 0}, /* S */
  3127. {1, 1}, /* T */
  3128. {3, 4}, /* U */
  3129. {4, 8}, /* V */
  3130. {3, 6}, /* W */
  3131. {4, 9}, /* X */
  3132. {4, 13},/* Y */
  3133. {4, 3} /* Z */
  3134. };
  3135. int dottime;
  3136. int dashtime;
  3137. int intralettertime;
  3138. int interlettertime;
  3139. int interwordtime;
  3140. int len, ddcomb;
  3141. int res;
  3142. int c;
  3143. int i;
  3144. int flags;
  3145. res = 0;
  3146. /* Approximate the dot time from the speed arg. */
  3147. dottime = 900/speed;
  3148. /* Establish timing releationships */
  3149. dashtime = 3 * dottime;
  3150. intralettertime = dottime;
  3151. interlettertime = dottime * 4 ;
  3152. interwordtime = dottime * 7;
  3153. for(;(*string) && (!res); string++){
  3154. c = *string;
  3155. /* Convert lower case to upper case */
  3156. if((c >= 'a') && (c <= 'z'))
  3157. c -= 0x20;
  3158. /* Can't deal with any char code greater than Z, skip it */
  3159. if(c > 'Z')
  3160. continue;
  3161. /* If space char, wait the inter word time */
  3162. if(c == ' '){
  3163. if(!res)
  3164. res = play_silence(chan, interwordtime);
  3165. continue;
  3166. }
  3167. /* Subtract out control char offset to match our table */
  3168. c -= 0x20;
  3169. /* Get the character data */
  3170. len = mbits[c].len;
  3171. ddcomb = mbits[c].ddcomb;
  3172. /* Send the character */
  3173. for(; len ; len--){
  3174. if(!res)
  3175. res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
  3176. if(!res)
  3177. res = play_silence(chan, intralettertime);
  3178. ddcomb >>= 1;
  3179. }
  3180. /* Wait the interletter time */
  3181. if(!res)
  3182. res = play_silence(chan, interlettertime - intralettertime);
  3183. }
  3184. /* Wait for all the frames to be sent */
  3185. if (!res)
  3186. res = ast_waitstream(chan, "");
  3187. ast_stopstream(chan);
  3188. /*
  3189. * Wait for the DAHDI driver to physically write the tone blocks to the hardware
  3190. */
  3191. for(i = 0; i < 20 ; i++){
  3192. flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
  3193. res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
  3194. if(flags & DAHDI_IOMUX_WRITEEMPTY)
  3195. break;
  3196. if( ast_safe_sleep(chan, 50)){
  3197. res = -1;
  3198. break;
  3199. }
  3200. }
  3201. return res;
  3202. }
  3203. static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
  3204. {
  3205. char *p,*stringp;
  3206. char *tonesubset;
  3207. int f1,f2;
  3208. int duration;
  3209. int amplitude;
  3210. int res;
  3211. int i;
  3212. int flags;
  3213. res = 0;
  3214. if(!tonestring)
  3215. return res;
  3216. p = stringp = ast_strdup(tonestring);
  3217. for(;tonestring;){
  3218. tonesubset = strsep(&stringp,")");
  3219. if(!tonesubset)
  3220. break;
  3221. if(sscanf(tonesubset,"(%30d,%30d,%30d,%30d", &f1, &f2, &duration, &amplitude) != 4)
  3222. break;
  3223. res = play_tone_pair(chan, f1, f2, duration, amplitude);
  3224. if(res)
  3225. break;
  3226. }
  3227. ast_free(p);
  3228. if(!res)
  3229. res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
  3230. if (!res)
  3231. res = ast_waitstream(chan, "");
  3232. ast_stopstream(chan);
  3233. /*
  3234. * Wait for the DAHDI driver to physically write the tone blocks to the hardware
  3235. */
  3236. for(i = 0; i < 20 ; i++){
  3237. flags = DAHDI_IOMUX_WRITEEMPTY | DAHDI_IOMUX_NOWAIT;
  3238. res = ioctl(chan->fds[0], DAHDI_IOMUX, &flags);
  3239. if(flags & DAHDI_IOMUX_WRITEEMPTY)
  3240. break;
  3241. if( ast_safe_sleep(chan, 50)){
  3242. res = -1;
  3243. break;
  3244. }
  3245. }
  3246. return res;
  3247. }
  3248. static int sayfile(struct ast_channel *mychannel,char *fname)
  3249. {
  3250. int res;
  3251. res = ast_streamfile(mychannel, fname, mychannel->language);
  3252. if (!res)
  3253. res = ast_waitstream(mychannel, "");
  3254. else
  3255. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  3256. ast_stopstream(mychannel);
  3257. return res;
  3258. }
  3259. static int saycharstr(struct ast_channel *mychannel,char *str)
  3260. {
  3261. int res;
  3262. res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
  3263. if (!res)
  3264. res = ast_waitstream(mychannel, "");
  3265. else
  3266. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  3267. ast_stopstream(mychannel);
  3268. return res;
  3269. }
  3270. static int saynum(struct ast_channel *mychannel, int num)
  3271. {
  3272. int res;
  3273. res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
  3274. if(!res)
  3275. res = ast_waitstream(mychannel, "");
  3276. else
  3277. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  3278. ast_stopstream(mychannel);
  3279. return res;
  3280. }
  3281. /* say a node and nodename. Try to look in dir referred to by nodenames in
  3282. config, and see if there's a custom node file to play, and if so, play it */
  3283. static int saynode(struct rpt *myrpt, struct ast_channel *mychannel, char *name)
  3284. {
  3285. int res;
  3286. char *val,fname[300];
  3287. val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "nodenames");
  3288. if (!val) val = NODENAMES;
  3289. snprintf(fname,sizeof(fname) - 1,"%s/%s",val,name);
  3290. if (ast_fileexists(fname,NULL,mychannel->language) > 0)
  3291. return(sayfile(mychannel,fname));
  3292. res = sayfile(mychannel,"rpt/node");
  3293. if (!res)
  3294. res = ast_say_character_str(mychannel,name,NULL,mychannel->language);
  3295. return res;
  3296. }
  3297. static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
  3298. {
  3299. int res;
  3300. char c;
  3301. static int morsespeed;
  3302. static int morsefreq;
  3303. static int morseampl;
  3304. static int morseidfreq = 0;
  3305. static int morseidampl;
  3306. static char mcat[] = MORSE;
  3307. res = 0;
  3308. if(!morseidfreq){ /* Get the morse parameters if not already loaded */
  3309. morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
  3310. morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
  3311. morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
  3312. morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
  3313. morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
  3314. }
  3315. /* Is it a file, or a tone sequence? */
  3316. if(entry[0] == '|'){
  3317. c = entry[1];
  3318. if((c >= 'a')&&(c <= 'z'))
  3319. c -= 0x20;
  3320. switch(c){
  3321. case 'I': /* Morse ID */
  3322. res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
  3323. break;
  3324. case 'M': /* Morse Message */
  3325. res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
  3326. break;
  3327. case 'T': /* Tone sequence */
  3328. res = send_tone_telemetry(chan, entry + 2);
  3329. break;
  3330. default:
  3331. res = -1;
  3332. }
  3333. }
  3334. else
  3335. res = sayfile(chan, entry); /* File */
  3336. return res;
  3337. }
  3338. /*
  3339. * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
  3340. *
  3341. * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
  3342. */
  3343. static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
  3344. {
  3345. int res;
  3346. int i;
  3347. char *entry;
  3348. char *telemetry;
  3349. char *telemetry_save;
  3350. res = 0;
  3351. telemetry_save = NULL;
  3352. entry = NULL;
  3353. /* Retrieve the section name for telemetry from the node section */
  3354. telemetry = (char *) ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
  3355. if(telemetry ){
  3356. telemetry_save = ast_strdup(telemetry);
  3357. if(!telemetry_save){
  3358. ast_log(LOG_WARNING,"ast_strdup() failed in telem_lookup()\n");
  3359. return res;
  3360. }
  3361. entry = (char *) ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
  3362. }
  3363. /* Try to look up the telemetry name */
  3364. if(!entry){
  3365. /* Telemetry name wasn't found in the config file, use the default */
  3366. for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
  3367. if(!strcasecmp(tele_defs[i].name, name))
  3368. entry = tele_defs[i].value;
  3369. }
  3370. }
  3371. if(entry){
  3372. if(strlen(entry))
  3373. if (chan) telem_any(myrpt,chan, entry);
  3374. }
  3375. else{
  3376. res = -1;
  3377. }
  3378. ast_free(telemetry_save);
  3379. return res;
  3380. }
  3381. /*
  3382. * Retrieve a wait interval
  3383. */
  3384. static int get_wait_interval(struct rpt *myrpt, int type)
  3385. {
  3386. int interval;
  3387. char *wait_times;
  3388. char *wait_times_save;
  3389. wait_times_save = NULL;
  3390. wait_times = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
  3391. if(wait_times){
  3392. wait_times_save = ast_strdup(wait_times);
  3393. if(!wait_times_save)
  3394. return 0;
  3395. }
  3396. switch(type){
  3397. case DLY_TELEM:
  3398. if(wait_times)
  3399. interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
  3400. else
  3401. interval = 1000;
  3402. break;
  3403. case DLY_ID:
  3404. if(wait_times)
  3405. interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
  3406. else
  3407. interval = 500;
  3408. break;
  3409. case DLY_UNKEY:
  3410. if(wait_times)
  3411. interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",50,5000,1000);
  3412. else
  3413. interval = 1000;
  3414. break;
  3415. case DLY_LINKUNKEY:
  3416. if(wait_times)
  3417. interval = retrieve_astcfgint(myrpt,wait_times_save, "linkunkeywait",500,5000,1000);
  3418. else
  3419. interval = 1000;
  3420. break;
  3421. case DLY_CALLTERM:
  3422. if(wait_times)
  3423. interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
  3424. else
  3425. interval = 1500;
  3426. break;
  3427. case DLY_COMP:
  3428. if(wait_times)
  3429. interval = retrieve_astcfgint(myrpt,wait_times_save, "compwait",500,5000,200);
  3430. else
  3431. interval = 200;
  3432. break;
  3433. case DLY_PARROT:
  3434. if(wait_times)
  3435. interval = retrieve_astcfgint(myrpt,wait_times_save, "parrotwait",500,5000,200);
  3436. else
  3437. interval = 200;
  3438. break;
  3439. default:
  3440. interval = 0;
  3441. break;
  3442. }
  3443. ast_free(wait_times_save);
  3444. return interval;
  3445. }
  3446. /*
  3447. * Wait a configurable interval of time
  3448. */
  3449. static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
  3450. {
  3451. int interval;
  3452. interval = get_wait_interval(myrpt, type);
  3453. if(debug)
  3454. ast_log(LOG_NOTICE,"Delay interval = %d\n", interval);
  3455. if(interval)
  3456. ast_safe_sleep(chan,interval);
  3457. if(debug)
  3458. ast_log(LOG_NOTICE,"Delay complete\n");
  3459. return;
  3460. }
  3461. static int split_freq(char *mhz, char *decimals, char *freq);
  3462. static void *rpt_tele_thread(void *this)
  3463. {
  3464. struct dahdi_confinfo ci; /* conference info */
  3465. int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
  3466. struct rpt_tele *mytele = (struct rpt_tele *)this;
  3467. struct rpt_tele *tlist;
  3468. struct rpt *myrpt;
  3469. struct rpt_link *l,*l1,linkbase;
  3470. struct ast_channel *mychannel;
  3471. int vmajor, vminor, m;
  3472. char *p,*ct,*ct_copy,*ident, *nodename;
  3473. time_t t;
  3474. #ifdef NEW_ASTERISK
  3475. struct ast_tm localtm;
  3476. #else
  3477. struct tm localtm;
  3478. #endif
  3479. char lbuf[MAXLINKLIST],*strs[MAXLINKLIST];
  3480. int i,ns,rbimode;
  3481. char mhz[MAXREMSTR];
  3482. char decimals[MAXREMSTR];
  3483. char mystr[200];
  3484. struct dahdi_params par;
  3485. /* get a pointer to myrpt */
  3486. myrpt = mytele->rpt;
  3487. /* Snag copies of a few key myrpt variables */
  3488. rpt_mutex_lock(&myrpt->lock);
  3489. nodename = ast_strdup(myrpt->name);
  3490. if(!nodename)
  3491. {
  3492. fprintf(stderr,"rpt:Sorry unable strdup nodename\n");
  3493. rpt_mutex_lock(&myrpt->lock);
  3494. remque((struct qelem *)mytele);
  3495. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3496. rpt_mutex_unlock(&myrpt->lock);
  3497. ast_free(mytele);
  3498. pthread_exit(NULL);
  3499. }
  3500. if (myrpt->p.ident){
  3501. ident = ast_strdup(myrpt->p.ident);
  3502. if(!ident)
  3503. {
  3504. fprintf(stderr,"rpt:Sorry unable strdup ident\n");
  3505. rpt_mutex_lock(&myrpt->lock);
  3506. remque((struct qelem *)mytele);
  3507. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",
  3508. __LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3509. rpt_mutex_unlock(&myrpt->lock);
  3510. ast_free(nodename);
  3511. ast_free(mytele);
  3512. pthread_exit(NULL);
  3513. }
  3514. }
  3515. else
  3516. {
  3517. ident = "";
  3518. }
  3519. rpt_mutex_unlock(&myrpt->lock);
  3520. /* allocate a pseudo-channel thru asterisk */
  3521. mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  3522. if (!mychannel)
  3523. {
  3524. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  3525. rpt_mutex_lock(&myrpt->lock);
  3526. remque((struct qelem *)mytele);
  3527. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3528. rpt_mutex_unlock(&myrpt->lock);
  3529. ast_free(nodename);
  3530. ast_free(ident);
  3531. ast_free(mytele);
  3532. pthread_exit(NULL);
  3533. }
  3534. #ifdef AST_CDR_FLAG_POST_DISABLED
  3535. if (mychannel->cdr)
  3536. ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  3537. #endif
  3538. rpt_mutex_lock(&myrpt->lock);
  3539. mytele->chan = mychannel;
  3540. rpt_mutex_unlock(&myrpt->lock);
  3541. while((mytele->mode != SETREMOTE) && (mytele->mode != UNKEY) &&
  3542. (mytele->mode != LINKUNKEY))
  3543. {
  3544. rpt_mutex_lock(&myrpt->lock);
  3545. if (!myrpt->active_telem)
  3546. {
  3547. myrpt->active_telem = mytele;
  3548. rpt_mutex_unlock(&myrpt->lock);
  3549. break;
  3550. }
  3551. rpt_mutex_unlock(&myrpt->lock);
  3552. usleep(100000);
  3553. }
  3554. /* make a conference for the tx */
  3555. ci.chan = 0;
  3556. /* If the telemetry is only intended for a local audience, */
  3557. /* only connect the ID audio to the local tx conference so */
  3558. /* linked systems can't hear it */
  3559. ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) ||
  3560. (mytele->mode == TAILMSG) || (mytele->mode == LINKUNKEY) || (mytele->mode == TIMEOUT) ||
  3561. (mytele->mode == PARROT) || (mytele->mode == STATS_TIME_LOCAL)) ?
  3562. myrpt->txconf : myrpt->conf);
  3563. ci.confmode = DAHDI_CONF_CONFANN;
  3564. /* first put the channel on the conference in announce mode */
  3565. if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  3566. {
  3567. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  3568. rpt_mutex_lock(&myrpt->lock);
  3569. myrpt->active_telem = NULL;
  3570. remque((struct qelem *)mytele);
  3571. rpt_mutex_unlock(&myrpt->lock);
  3572. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3573. ast_free(nodename);
  3574. ast_free(ident);
  3575. ast_free(mytele);
  3576. ast_hangup(mychannel);
  3577. pthread_exit(NULL);
  3578. }
  3579. ast_stopstream(mychannel);
  3580. switch(mytele->mode)
  3581. {
  3582. case ID:
  3583. case ID1:
  3584. /* wait a bit */
  3585. wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
  3586. res = telem_any(myrpt,mychannel, ident);
  3587. imdone=1;
  3588. break;
  3589. case TAILMSG:
  3590. res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
  3591. break;
  3592. case IDTALKOVER:
  3593. p = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
  3594. if(p)
  3595. res = telem_any(myrpt,mychannel, p);
  3596. imdone=1;
  3597. break;
  3598. case PROC:
  3599. /* wait a little bit longer */
  3600. wait_interval(myrpt, DLY_TELEM, mychannel);
  3601. res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
  3602. if(res < 0){ /* Then default message */
  3603. res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
  3604. }
  3605. break;
  3606. case TERM:
  3607. /* wait a little bit longer */
  3608. wait_interval(myrpt, DLY_CALLTERM, mychannel);
  3609. res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
  3610. if(res < 0){ /* Then default message */
  3611. res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
  3612. }
  3613. break;
  3614. case COMPLETE:
  3615. /* wait a little bit */
  3616. wait_interval(myrpt, DLY_TELEM, mychannel);
  3617. res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  3618. break;
  3619. case MACRO_NOTFOUND:
  3620. /* wait a little bit */
  3621. wait_interval(myrpt, DLY_TELEM, mychannel);
  3622. res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
  3623. break;
  3624. case MACRO_BUSY:
  3625. /* wait a little bit */
  3626. wait_interval(myrpt, DLY_TELEM, mychannel);
  3627. res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
  3628. break;
  3629. case UNKEY:
  3630. if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
  3631. imdone = 1;
  3632. break;
  3633. }
  3634. /*
  3635. * Reset the Unkey to CT timer
  3636. */
  3637. x = get_wait_interval(myrpt, DLY_UNKEY);
  3638. rpt_mutex_lock(&myrpt->lock);
  3639. myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
  3640. rpt_mutex_unlock(&myrpt->lock);
  3641. /*
  3642. * If there's one already queued, don't do another
  3643. */
  3644. tlist = myrpt->tele.next;
  3645. unkeys_queued = 0;
  3646. if (tlist != &myrpt->tele)
  3647. {
  3648. rpt_mutex_lock(&myrpt->lock);
  3649. while(tlist != &myrpt->tele){
  3650. if (tlist->mode == UNKEY) unkeys_queued++;
  3651. tlist = tlist->next;
  3652. }
  3653. rpt_mutex_unlock(&myrpt->lock);
  3654. }
  3655. if( unkeys_queued > 1){
  3656. imdone = 1;
  3657. break;
  3658. }
  3659. /* Wait for the telemetry timer to expire */
  3660. /* Periodically check the timer since it can be re-initialized above */
  3661. while(myrpt->unkeytocttimer)
  3662. {
  3663. int ctint;
  3664. if(myrpt->unkeytocttimer > 100)
  3665. ctint = 100;
  3666. else
  3667. ctint = myrpt->unkeytocttimer;
  3668. ast_safe_sleep(mychannel, ctint);
  3669. rpt_mutex_lock(&myrpt->lock);
  3670. if(myrpt->unkeytocttimer < ctint)
  3671. myrpt->unkeytocttimer = 0;
  3672. else
  3673. myrpt->unkeytocttimer -= ctint;
  3674. rpt_mutex_unlock(&myrpt->lock);
  3675. }
  3676. /*
  3677. * Now, the carrier on the rptr rx should be gone.
  3678. * If it re-appeared, then forget about sending the CT
  3679. */
  3680. if(myrpt->keyed){
  3681. imdone = 1;
  3682. break;
  3683. }
  3684. rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */
  3685. myrpt->dailykerchunks++;
  3686. myrpt->totalkerchunks++;
  3687. rpt_mutex_unlock(&myrpt->lock);
  3688. haslink = 0;
  3689. hastx = 0;
  3690. hasremote = 0;
  3691. l = myrpt->links.next;
  3692. if (l != &myrpt->links)
  3693. {
  3694. rpt_mutex_lock(&myrpt->lock);
  3695. while(l != &myrpt->links)
  3696. {
  3697. if (l->name[0] == '0')
  3698. {
  3699. l = l->next;
  3700. continue;
  3701. }
  3702. haslink = 1;
  3703. if (l->mode) {
  3704. hastx++;
  3705. if (l->isremote) hasremote++;
  3706. }
  3707. l = l->next;
  3708. }
  3709. rpt_mutex_unlock(&myrpt->lock);
  3710. }
  3711. if (haslink)
  3712. {
  3713. res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
  3714. if(res)
  3715. ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
  3716. /* if in remote cmd mode, indicate it */
  3717. if (myrpt->cmdnode[0])
  3718. {
  3719. ast_safe_sleep(mychannel,200);
  3720. res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
  3721. if(res)
  3722. ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
  3723. ast_stopstream(mychannel);
  3724. }
  3725. }
  3726. else if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
  3727. ct_copy = ast_strdup(ct);
  3728. if(ct_copy)
  3729. {
  3730. res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
  3731. ast_free(ct_copy);
  3732. }
  3733. else
  3734. res = -1;
  3735. if(res)
  3736. ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
  3737. }
  3738. if (hasremote && (!myrpt->cmdnode[0]))
  3739. {
  3740. /* set for all to hear */
  3741. ci.chan = 0;
  3742. ci.confno = myrpt->conf;
  3743. ci.confmode = DAHDI_CONF_CONFANN;
  3744. /* first put the channel on the conference in announce mode */
  3745. if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  3746. {
  3747. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  3748. rpt_mutex_lock(&myrpt->lock);
  3749. myrpt->active_telem = NULL;
  3750. remque((struct qelem *)mytele);
  3751. rpt_mutex_unlock(&myrpt->lock);
  3752. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3753. ast_free(nodename);
  3754. ast_free(ident);
  3755. ast_free(mytele);
  3756. ast_hangup(mychannel);
  3757. pthread_exit(NULL);
  3758. }
  3759. if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
  3760. ast_safe_sleep(mychannel,200);
  3761. ct_copy = ast_strdup(ct);
  3762. if(ct_copy)
  3763. {
  3764. res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
  3765. ast_free(ct_copy);
  3766. }
  3767. else
  3768. res = -1;
  3769. if(res)
  3770. ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
  3771. }
  3772. }
  3773. #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
  3774. if (myrpt->lastunit)
  3775. {
  3776. char mystr[10];
  3777. ast_safe_sleep(mychannel,200);
  3778. /* set for all to hear */
  3779. ci.chan = 0;
  3780. ci.confno = myrpt->txconf;
  3781. ci.confmode = DAHDI_CONF_CONFANN;
  3782. /* first put the channel on the conference in announce mode */
  3783. if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  3784. {
  3785. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  3786. rpt_mutex_lock(&myrpt->lock);
  3787. myrpt->active_telem = NULL;
  3788. remque((struct qelem *)mytele);
  3789. rpt_mutex_unlock(&myrpt->lock);
  3790. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  3791. ast_free(nodename);
  3792. ast_free(ident);
  3793. ast_free(mytele);
  3794. ast_hangup(mychannel);
  3795. pthread_exit(NULL);
  3796. }
  3797. sprintf(mystr,"%04x",myrpt->lastunit);
  3798. myrpt->lastunit = 0;
  3799. ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
  3800. break;
  3801. }
  3802. #endif
  3803. imdone = 1;
  3804. break;
  3805. case LINKUNKEY:
  3806. if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
  3807. imdone = 1;
  3808. break;
  3809. }
  3810. /*
  3811. * Reset the Unkey to CT timer
  3812. */
  3813. x = get_wait_interval(myrpt, DLY_LINKUNKEY);
  3814. mytele->mylink.linkunkeytocttimer = x; /* Must be protected as it is changed below */
  3815. /*
  3816. * If there's one already queued, don't do another
  3817. */
  3818. tlist = myrpt->tele.next;
  3819. unkeys_queued = 0;
  3820. if (tlist != &myrpt->tele)
  3821. {
  3822. rpt_mutex_lock(&myrpt->lock);
  3823. while(tlist != &myrpt->tele){
  3824. if (tlist->mode == LINKUNKEY) unkeys_queued++;
  3825. tlist = tlist->next;
  3826. }
  3827. rpt_mutex_unlock(&myrpt->lock);
  3828. }
  3829. if( unkeys_queued > 1){
  3830. imdone = 1;
  3831. break;
  3832. }
  3833. /* Wait for the telemetry timer to expire */
  3834. /* Periodically check the timer since it can be re-initialized above */
  3835. while(mytele->mylink.linkunkeytocttimer)
  3836. {
  3837. int ctint;
  3838. if(mytele->mylink.linkunkeytocttimer > 100)
  3839. ctint = 100;
  3840. else
  3841. ctint = mytele->mylink.linkunkeytocttimer;
  3842. ast_safe_sleep(mychannel, ctint);
  3843. rpt_mutex_lock(&myrpt->lock);
  3844. if(mytele->mylink.linkunkeytocttimer < ctint)
  3845. mytele->mylink.linkunkeytocttimer = 0;
  3846. else
  3847. mytele->mylink.linkunkeytocttimer -= ctint;
  3848. rpt_mutex_unlock(&myrpt->lock);
  3849. }
  3850. if((ct = (char *) ast_variable_retrieve(myrpt->cfg, nodename, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
  3851. ct_copy = ast_strdup(ct);
  3852. if(ct_copy){
  3853. res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
  3854. ast_free(ct_copy);
  3855. }
  3856. else
  3857. res = -1;
  3858. if(res)
  3859. ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
  3860. }
  3861. imdone = 1;
  3862. break;
  3863. case REMDISC:
  3864. /* wait a little bit */
  3865. wait_interval(myrpt, DLY_TELEM, mychannel);
  3866. l = myrpt->links.next;
  3867. haslink = 0;
  3868. /* don't report if a link for this one still on system */
  3869. if (l != &myrpt->links)
  3870. {
  3871. rpt_mutex_lock(&myrpt->lock);
  3872. while(l != &myrpt->links)
  3873. {
  3874. if (l->name[0] == '0')
  3875. {
  3876. l = l->next;
  3877. continue;
  3878. }
  3879. if (!strcmp(l->name,mytele->mylink.name))
  3880. {
  3881. haslink = 1;
  3882. break;
  3883. }
  3884. l = l->next;
  3885. }
  3886. rpt_mutex_unlock(&myrpt->lock);
  3887. }
  3888. if (haslink)
  3889. {
  3890. imdone = 1;
  3891. break;
  3892. }
  3893. res = saynode(myrpt,mychannel,mytele->mylink.name);
  3894. if (!res)
  3895. res = ast_streamfile(mychannel, ((mytele->mylink.hasconnected) ?
  3896. "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
  3897. break;
  3898. case REMALREADY:
  3899. /* wait a little bit */
  3900. wait_interval(myrpt, DLY_TELEM, mychannel);
  3901. res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
  3902. break;
  3903. case REMNOTFOUND:
  3904. /* wait a little bit */
  3905. wait_interval(myrpt, DLY_TELEM, mychannel);
  3906. res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
  3907. break;
  3908. case REMGO:
  3909. /* wait a little bit */
  3910. wait_interval(myrpt, DLY_TELEM, mychannel);
  3911. res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
  3912. break;
  3913. case CONNECTED:
  3914. /* wait a little bit */
  3915. wait_interval(myrpt, DLY_TELEM, mychannel);
  3916. res = saynode(myrpt,mychannel,mytele->mylink.name);
  3917. if (!res)
  3918. res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
  3919. if (!res)
  3920. res = ast_waitstream(mychannel, "");
  3921. else
  3922. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  3923. ast_stopstream(mychannel);
  3924. res = ast_streamfile(mychannel, "digits/2", mychannel->language);
  3925. if (!res)
  3926. res = ast_waitstream(mychannel, "");
  3927. else
  3928. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  3929. ast_stopstream(mychannel);
  3930. res = saynode(myrpt,mychannel,myrpt->name);
  3931. imdone = 1;
  3932. break;
  3933. case CONNFAIL:
  3934. res = saynode(myrpt,mychannel,mytele->mylink.name);
  3935. if (!res)
  3936. res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
  3937. break;
  3938. case MEMNOTFOUND:
  3939. /* wait a little bit */
  3940. wait_interval(myrpt, DLY_TELEM, mychannel);
  3941. res = ast_streamfile(mychannel, "rpt/memory_notfound", mychannel->language);
  3942. break;
  3943. case PLAYBACK:
  3944. /* wait a little bit */
  3945. wait_interval(myrpt, DLY_TELEM, mychannel);
  3946. res = ast_streamfile(mychannel, mytele->param, mychannel->language);
  3947. break;
  3948. case TOPKEY:
  3949. /* wait a little bit */
  3950. wait_interval(myrpt, DLY_TELEM, mychannel);
  3951. for(i = 0; i < TOPKEYN; i++)
  3952. {
  3953. if (!myrpt->topkey[i].node[0]) continue;
  3954. if ((!myrpt->topkeylong) && (myrpt->topkey[i].keyed)) continue;
  3955. res = saynode(myrpt, mychannel, myrpt->topkey[i].node);
  3956. if (!res) res = sayfile(mychannel,(myrpt->topkey[i].keyed) ?
  3957. "rpt/keyedfor" : "rpt/unkeyedfor");
  3958. if (!res) res = saynum(mychannel,
  3959. myrpt->topkey[i].timesince);
  3960. if (!res) res = sayfile(mychannel,"rpt/seconds");
  3961. if (!myrpt->topkeylong) break;
  3962. }
  3963. imdone = 1;
  3964. break;
  3965. case SETREMOTE:
  3966. ast_mutex_lock(&myrpt->remlock);
  3967. res = 0;
  3968. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  3969. {
  3970. res = set_ft897(myrpt);
  3971. }
  3972. else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
  3973. {
  3974. res = set_tm271(myrpt);
  3975. }
  3976. else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  3977. {
  3978. res = set_ic706(myrpt);
  3979. }
  3980. #ifdef HAVE_IOPERM
  3981. else if(!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16))
  3982. {
  3983. if (ioperm(myrpt->p.iobase,1,1) == -1)
  3984. {
  3985. rpt_mutex_unlock(&myrpt->lock);
  3986. ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
  3987. res = -1;
  3988. }
  3989. else res = setrbi(myrpt);
  3990. }
  3991. #endif
  3992. else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
  3993. {
  3994. if (myrpt->iofd >= 0) setdtr(myrpt->iofd,1);
  3995. res = setkenwood(myrpt);
  3996. if (myrpt->iofd >= 0) setdtr(myrpt->iofd,0);
  3997. if (ast_safe_sleep(mychannel,200) == -1)
  3998. {
  3999. ast_mutex_unlock(&myrpt->remlock);
  4000. res = -1;
  4001. break;
  4002. }
  4003. if (myrpt->iofd < 0)
  4004. {
  4005. i = DAHDI_FLUSH_EVENT;
  4006. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_FLUSH,&i) == -1)
  4007. {
  4008. ast_mutex_unlock(&myrpt->remlock);
  4009. ast_log(LOG_ERROR,"Cant flush events");
  4010. res = -1;
  4011. break;
  4012. }
  4013. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) == -1)
  4014. {
  4015. ast_mutex_unlock(&myrpt->remlock);
  4016. ast_log(LOG_ERROR,"Cant get params");
  4017. res = -1;
  4018. break;
  4019. }
  4020. myrpt->remoterx =
  4021. (par.rxisoffhook || (myrpt->tele.next != &myrpt->tele));
  4022. }
  4023. }
  4024. ast_mutex_unlock(&myrpt->remlock);
  4025. if (!res)
  4026. {
  4027. imdone = 1;
  4028. break;
  4029. }
  4030. /* fall thru to invalid freq */
  4031. case INVFREQ:
  4032. /* wait a little bit */
  4033. wait_interval(myrpt, DLY_TELEM, mychannel);
  4034. res = ast_streamfile(mychannel, "rpt/invalid-freq", mychannel->language);
  4035. break;
  4036. case REMMODE:
  4037. wait_interval(myrpt, DLY_TELEM, mychannel);
  4038. switch(myrpt->remmode)
  4039. {
  4040. case REM_MODE_FM:
  4041. saycharstr(mychannel,"FM");
  4042. break;
  4043. case REM_MODE_USB:
  4044. saycharstr(mychannel,"USB");
  4045. break;
  4046. case REM_MODE_LSB:
  4047. saycharstr(mychannel,"LSB");
  4048. break;
  4049. case REM_MODE_AM:
  4050. saycharstr(mychannel,"AM");
  4051. break;
  4052. }
  4053. wait_interval(myrpt, DLY_COMP, mychannel);
  4054. if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  4055. break;
  4056. case LOGINREQ:
  4057. wait_interval(myrpt, DLY_TELEM, mychannel);
  4058. sayfile(mychannel,"rpt/login");
  4059. saycharstr(mychannel,myrpt->name);
  4060. break;
  4061. case REMLOGIN:
  4062. wait_interval(myrpt, DLY_TELEM, mychannel);
  4063. saycharstr(mychannel,myrpt->loginuser);
  4064. saynode(myrpt,mychannel,myrpt->name);
  4065. wait_interval(myrpt, DLY_COMP, mychannel);
  4066. if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  4067. break;
  4068. case REMXXX:
  4069. wait_interval(myrpt, DLY_TELEM, mychannel);
  4070. res = 0;
  4071. switch(mytele->submode)
  4072. {
  4073. case 100: /* RX PL Off */
  4074. sayfile(mychannel, "rpt/rxpl");
  4075. sayfile(mychannel, "rpt/off");
  4076. break;
  4077. case 101: /* RX PL On */
  4078. sayfile(mychannel, "rpt/rxpl");
  4079. sayfile(mychannel, "rpt/on");
  4080. break;
  4081. case 102: /* TX PL Off */
  4082. sayfile(mychannel, "rpt/txpl");
  4083. sayfile(mychannel, "rpt/off");
  4084. break;
  4085. case 103: /* TX PL On */
  4086. sayfile(mychannel, "rpt/txpl");
  4087. sayfile(mychannel, "rpt/on");
  4088. break;
  4089. case 104: /* Low Power */
  4090. sayfile(mychannel, "rpt/lopwr");
  4091. break;
  4092. case 105: /* Medium Power */
  4093. sayfile(mychannel, "rpt/medpwr");
  4094. break;
  4095. case 106: /* Hi Power */
  4096. sayfile(mychannel, "rpt/hipwr");
  4097. break;
  4098. case 113: /* Scan down slow */
  4099. sayfile(mychannel,"rpt/down");
  4100. sayfile(mychannel, "rpt/slow");
  4101. break;
  4102. case 114: /* Scan down quick */
  4103. sayfile(mychannel,"rpt/down");
  4104. sayfile(mychannel, "rpt/quick");
  4105. break;
  4106. case 115: /* Scan down fast */
  4107. sayfile(mychannel,"rpt/down");
  4108. sayfile(mychannel, "rpt/fast");
  4109. break;
  4110. case 116: /* Scan up slow */
  4111. sayfile(mychannel,"rpt/up");
  4112. sayfile(mychannel, "rpt/slow");
  4113. break;
  4114. case 117: /* Scan up quick */
  4115. sayfile(mychannel,"rpt/up");
  4116. sayfile(mychannel, "rpt/quick");
  4117. break;
  4118. case 118: /* Scan up fast */
  4119. sayfile(mychannel,"rpt/up");
  4120. sayfile(mychannel, "rpt/fast");
  4121. break;
  4122. default:
  4123. res = -1;
  4124. }
  4125. wait_interval(myrpt, DLY_COMP, mychannel);
  4126. if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  4127. break;
  4128. case SCAN:
  4129. ast_mutex_lock(&myrpt->remlock);
  4130. if (myrpt->hfscanstop)
  4131. {
  4132. myrpt->hfscanstatus = 0;
  4133. myrpt->hfscanmode = 0;
  4134. myrpt->hfscanstop = 0;
  4135. mytele->mode = SCANSTAT;
  4136. ast_mutex_unlock(&myrpt->remlock);
  4137. if (ast_safe_sleep(mychannel,1000) == -1) break;
  4138. sayfile(mychannel, "rpt/stop");
  4139. imdone = 1;
  4140. break;
  4141. }
  4142. if (myrpt->hfscanstatus > -2) service_scan(myrpt);
  4143. i = myrpt->hfscanstatus;
  4144. myrpt->hfscanstatus = 0;
  4145. if (i) mytele->mode = SCANSTAT;
  4146. ast_mutex_unlock(&myrpt->remlock);
  4147. if (i < 0) sayfile(mychannel, "rpt/stop");
  4148. else if (i > 0) saynum(mychannel,i);
  4149. imdone = 1;
  4150. break;
  4151. case TUNE:
  4152. ast_mutex_lock(&myrpt->remlock);
  4153. if (!strcmp(myrpt->remoterig,remote_rig_ic706))
  4154. {
  4155. set_mode_ic706(myrpt, REM_MODE_AM);
  4156. if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
  4157. ast_safe_sleep(mychannel,500);
  4158. set_mode_ic706(myrpt, myrpt->remmode);
  4159. myrpt->tunerequest = 0;
  4160. ast_mutex_unlock(&myrpt->remlock);
  4161. imdone = 1;
  4162. break;
  4163. }
  4164. set_mode_ft897(myrpt, REM_MODE_AM);
  4165. simple_command_ft897(myrpt, 8);
  4166. if(play_tone(mychannel, 800, 6000, 8192) == -1) break;
  4167. simple_command_ft897(myrpt, 0x88);
  4168. ast_safe_sleep(mychannel,500);
  4169. set_mode_ft897(myrpt, myrpt->remmode);
  4170. myrpt->tunerequest = 0;
  4171. ast_mutex_unlock(&myrpt->remlock);
  4172. imdone = 1;
  4173. break;
  4174. case REMSHORTSTATUS:
  4175. case REMLONGSTATUS:
  4176. wait_interval(myrpt, DLY_TELEM, mychannel);
  4177. res = saynode(myrpt,mychannel,myrpt->name);
  4178. if(!res)
  4179. res = sayfile(mychannel,"rpt/frequency");
  4180. if(!res)
  4181. res = split_freq(mhz, decimals, myrpt->freq);
  4182. if (!multimode_capable(myrpt)) decimals[3] = 0;
  4183. if(!res){
  4184. m = atoi(mhz);
  4185. if(m < 100)
  4186. res = saynum(mychannel, m);
  4187. else
  4188. res = saycharstr(mychannel, mhz);
  4189. }
  4190. if(!res)
  4191. res = sayfile(mychannel, "letters/dot");
  4192. if(!res)
  4193. res = saycharstr(mychannel, decimals);
  4194. if(res) break;
  4195. if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
  4196. switch(myrpt->offset){
  4197. case REM_MINUS:
  4198. res = sayfile(mychannel,"rpt/minus");
  4199. break;
  4200. case REM_SIMPLEX:
  4201. res = sayfile(mychannel,"rpt/simplex");
  4202. break;
  4203. case REM_PLUS:
  4204. res = sayfile(mychannel,"rpt/plus");
  4205. break;
  4206. default:
  4207. break;
  4208. }
  4209. }
  4210. else{ /* Must be USB, LSB, or AM */
  4211. switch(myrpt->remmode){
  4212. case REM_MODE_USB:
  4213. res = saycharstr(mychannel, "USB");
  4214. break;
  4215. case REM_MODE_LSB:
  4216. res = saycharstr(mychannel, "LSB");
  4217. break;
  4218. case REM_MODE_AM:
  4219. res = saycharstr(mychannel, "AM");
  4220. break;
  4221. default:
  4222. break;
  4223. }
  4224. }
  4225. if (res == -1) break;
  4226. if(mytele->mode == REMSHORTSTATUS){ /* Short status? */
  4227. wait_interval(myrpt, DLY_COMP, mychannel);
  4228. if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  4229. break;
  4230. }
  4231. if (strcmp(myrpt->remoterig,remote_rig_ic706))
  4232. {
  4233. switch(myrpt->powerlevel){
  4234. case REM_LOWPWR:
  4235. res = sayfile(mychannel,"rpt/lopwr") ;
  4236. break;
  4237. case REM_MEDPWR:
  4238. res = sayfile(mychannel,"rpt/medpwr");
  4239. break;
  4240. case REM_HIPWR:
  4241. res = sayfile(mychannel,"rpt/hipwr");
  4242. break;
  4243. }
  4244. }
  4245. rbimode = ((!strncmp(myrpt->remoterig,remote_rig_rbi,3))
  4246. || (!strncmp(myrpt->remoterig,remote_rig_ic706,3)));
  4247. if (res || (sayfile(mychannel,"rpt/rxpl") == -1)) break;
  4248. if (rbimode && (sayfile(mychannel,"rpt/txpl") == -1)) break;
  4249. if ((sayfile(mychannel,"rpt/frequency") == -1) ||
  4250. (saycharstr(mychannel,myrpt->rxpl) == -1)) break;
  4251. if ((!rbimode) && ((sayfile(mychannel,"rpt/txpl") == -1) ||
  4252. (sayfile(mychannel,"rpt/frequency") == -1) ||
  4253. (saycharstr(mychannel,myrpt->txpl) == -1))) break;
  4254. if(myrpt->remmode == REM_MODE_FM){ /* Mode FM? */
  4255. if ((sayfile(mychannel,"rpt/rxpl") == -1) ||
  4256. (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1) ||
  4257. (sayfile(mychannel,"rpt/txpl") == -1) ||
  4258. (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1))
  4259. {
  4260. break;
  4261. }
  4262. }
  4263. wait_interval(myrpt, DLY_COMP, mychannel);
  4264. if (!res) res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
  4265. break;
  4266. case STATUS:
  4267. /* wait a little bit */
  4268. wait_interval(myrpt, DLY_TELEM, mychannel);
  4269. hastx = 0;
  4270. linkbase.next = &linkbase;
  4271. linkbase.prev = &linkbase;
  4272. rpt_mutex_lock(&myrpt->lock);
  4273. /* make our own list of links */
  4274. l = myrpt->links.next;
  4275. while(l != &myrpt->links)
  4276. {
  4277. if (l->name[0] == '0')
  4278. {
  4279. l = l->next;
  4280. continue;
  4281. }
  4282. l1 = ast_malloc(sizeof(struct rpt_link));
  4283. if (!l1)
  4284. {
  4285. ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
  4286. remque((struct qelem *)mytele);
  4287. myrpt->active_telem = NULL;
  4288. rpt_mutex_unlock(&myrpt->lock);
  4289. ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
  4290. ast_free(nodename);
  4291. ast_free(ident);
  4292. ast_free(mytele);
  4293. ast_hangup(mychannel);
  4294. pthread_exit(NULL);
  4295. }
  4296. memcpy(l1,l,sizeof(struct rpt_link));
  4297. l1->next = l1->prev = NULL;
  4298. insque((struct qelem *)l1,(struct qelem *)linkbase.next);
  4299. l = l->next;
  4300. }
  4301. rpt_mutex_unlock(&myrpt->lock);
  4302. res = saynode(myrpt,mychannel,myrpt->name);
  4303. if (myrpt->callmode)
  4304. {
  4305. hastx = 1;
  4306. res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
  4307. if (!res)
  4308. res = ast_waitstream(mychannel, "");
  4309. else
  4310. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4311. ast_stopstream(mychannel);
  4312. }
  4313. l = linkbase.next;
  4314. while(l != &linkbase)
  4315. {
  4316. char *s;
  4317. hastx = 1;
  4318. res = saynode(myrpt,mychannel,l->name);
  4319. s = "rpt/tranceive";
  4320. if (!l->mode) s = "rpt/monitor";
  4321. if (!l->thisconnected) s = "rpt/connecting";
  4322. res = ast_streamfile(mychannel, s, mychannel->language);
  4323. if (!res)
  4324. res = ast_waitstream(mychannel, "");
  4325. else
  4326. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4327. ast_stopstream(mychannel);
  4328. l = l->next;
  4329. }
  4330. if (!hastx)
  4331. {
  4332. res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
  4333. if (!res)
  4334. res = ast_waitstream(mychannel, "");
  4335. else
  4336. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4337. ast_stopstream(mychannel);
  4338. }
  4339. /* destroy our local link queue */
  4340. l = linkbase.next;
  4341. while(l != &linkbase)
  4342. {
  4343. l1 = l;
  4344. l = l->next;
  4345. remque((struct qelem *)l1);
  4346. ast_free(l1);
  4347. }
  4348. imdone = 1;
  4349. break;
  4350. case FULLSTATUS:
  4351. rpt_mutex_lock(&myrpt->lock);
  4352. /* get all the nodes */
  4353. __mklinklist(myrpt,NULL,lbuf);
  4354. rpt_mutex_unlock(&myrpt->lock);
  4355. /* parse em */
  4356. ns = finddelim(lbuf,strs,MAXLINKLIST);
  4357. /* sort em */
  4358. if (ns) qsort((void *)strs,ns,sizeof(char *),mycompar);
  4359. /* wait a little bit */
  4360. wait_interval(myrpt, DLY_TELEM, mychannel);
  4361. hastx = 0;
  4362. res = saynode(myrpt,mychannel,myrpt->name);
  4363. if (myrpt->callmode)
  4364. {
  4365. hastx = 1;
  4366. res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
  4367. if (!res)
  4368. res = ast_waitstream(mychannel, "");
  4369. else
  4370. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4371. ast_stopstream(mychannel);
  4372. }
  4373. /* go thru all the nodes in list */
  4374. for(i = 0; i < ns; i++)
  4375. {
  4376. char *s,mode = 'T';
  4377. /* if a mode spec at first, handle it */
  4378. if ((*strs[i] < '0') || (*strs[i] > '9'))
  4379. {
  4380. mode = *strs[i];
  4381. strs[i]++;
  4382. }
  4383. hastx = 1;
  4384. res = saynode(myrpt,mychannel,strs[i]);
  4385. s = "rpt/tranceive";
  4386. if (mode == 'R') s = "rpt/monitor";
  4387. if (mode == 'C') s = "rpt/connecting";
  4388. res = ast_streamfile(mychannel, s, mychannel->language);
  4389. if (!res)
  4390. res = ast_waitstream(mychannel, "");
  4391. else
  4392. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4393. ast_stopstream(mychannel);
  4394. }
  4395. if (!hastx)
  4396. {
  4397. res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
  4398. if (!res)
  4399. res = ast_waitstream(mychannel, "");
  4400. else
  4401. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4402. ast_stopstream(mychannel);
  4403. }
  4404. imdone = 1;
  4405. break;
  4406. case LASTNODEKEY: /* Identify last node which keyed us up */
  4407. rpt_mutex_lock(&myrpt->lock);
  4408. if(myrpt->lastnodewhichkeyedusup){
  4409. p = ast_strdup(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
  4410. if(!p){
  4411. ast_log(LOG_WARNING, "ast_strdup failed in telemetery LASTNODEKEY");
  4412. imdone = 1;
  4413. break;
  4414. }
  4415. }
  4416. else
  4417. p = NULL;
  4418. rpt_mutex_unlock(&myrpt->lock);
  4419. if(!p){
  4420. imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
  4421. break;
  4422. }
  4423. wait_interval(myrpt, DLY_TELEM, mychannel);
  4424. res = saynode(myrpt,mychannel,p);
  4425. ast_free(p);
  4426. imdone = 1;
  4427. break;
  4428. case UNAUTHTX: /* Say unauthorized transmit frequency */
  4429. wait_interval(myrpt, DLY_TELEM, mychannel);
  4430. res = ast_streamfile(mychannel, "rpt/unauthtx", mychannel->language);
  4431. if (!res)
  4432. res = ast_waitstream(mychannel, "");
  4433. else
  4434. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4435. ast_stopstream(mychannel);
  4436. imdone = 1;
  4437. break;
  4438. case PARROT: /* Repeat stuff */
  4439. sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
  4440. if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
  4441. {
  4442. imdone = 1;
  4443. myrpt->parrotstate = 0;
  4444. break;
  4445. }
  4446. wait_interval(myrpt, DLY_PARROT, mychannel);
  4447. sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
  4448. res = ast_streamfile(mychannel, mystr, mychannel->language);
  4449. if (!res)
  4450. res = ast_waitstream(mychannel, "");
  4451. else
  4452. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4453. ast_stopstream(mychannel);
  4454. sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
  4455. strcat(mystr,".wav");
  4456. unlink(mystr);
  4457. imdone = 1;
  4458. myrpt->parrotstate = 0;
  4459. break;
  4460. case TIMEOUT:
  4461. res = saynode(myrpt,mychannel,myrpt->name);
  4462. if (!res)
  4463. res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
  4464. break;
  4465. case TIMEOUT_WARNING:
  4466. time(&t);
  4467. res = saynode(myrpt,mychannel,myrpt->name);
  4468. if (!res)
  4469. res = ast_streamfile(mychannel, "rpt/timeout-warning", mychannel->language);
  4470. if (!res)
  4471. res = ast_waitstream(mychannel, "");
  4472. else
  4473. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4474. ast_stopstream(mychannel);
  4475. if(!res) /* Say number of seconds */
  4476. ast_say_number(mychannel, myrpt->p.remotetimeout -
  4477. (t - myrpt->last_activity_time),
  4478. "", mychannel->language, (char *) NULL);
  4479. if (!res)
  4480. res = ast_waitstream(mychannel, "");
  4481. ast_stopstream(mychannel);
  4482. res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
  4483. break;
  4484. case ACT_TIMEOUT_WARNING:
  4485. time(&t);
  4486. res = saynode(myrpt,mychannel,myrpt->name);
  4487. if (!res)
  4488. res = ast_streamfile(mychannel, "rpt/act-timeout-warning", mychannel->language);
  4489. if (!res)
  4490. res = ast_waitstream(mychannel, "");
  4491. else
  4492. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4493. ast_stopstream(mychannel);
  4494. if(!res) /* Say number of seconds */
  4495. ast_say_number(mychannel, myrpt->p.remoteinacttimeout -
  4496. (t - myrpt->last_activity_time),
  4497. "", mychannel->language, (char *) NULL);
  4498. if (!res)
  4499. res = ast_waitstream(mychannel, "");
  4500. ast_stopstream(mychannel);
  4501. res = ast_streamfile(mychannel, "queue-seconds", mychannel->language);
  4502. break;
  4503. case STATS_TIME:
  4504. case STATS_TIME_LOCAL:
  4505. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  4506. t = time(NULL);
  4507. rpt_localtime(&t, &localtm);
  4508. /* Say the phase of the day is before the time */
  4509. if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
  4510. p = "rpt/goodmorning";
  4511. else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
  4512. p = "rpt/goodafternoon";
  4513. else
  4514. p = "rpt/goodevening";
  4515. if (sayfile(mychannel,p) == -1)
  4516. {
  4517. imdone = 1;
  4518. break;
  4519. }
  4520. /* Say the time is ... */
  4521. if (sayfile(mychannel,"rpt/thetimeis") == -1)
  4522. {
  4523. imdone = 1;
  4524. break;
  4525. }
  4526. /* Say the time */
  4527. res = ast_say_time(mychannel, t, "", mychannel->language);
  4528. if (!res)
  4529. res = ast_waitstream(mychannel, "");
  4530. ast_stopstream(mychannel);
  4531. imdone = 1;
  4532. break;
  4533. case STATS_VERSION:
  4534. p = strstr(tdesc, "version");
  4535. if(!p)
  4536. break;
  4537. if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) != 2)
  4538. break;
  4539. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  4540. /* Say "version" */
  4541. if (sayfile(mychannel,"rpt/version") == -1)
  4542. {
  4543. imdone = 1;
  4544. break;
  4545. }
  4546. if(!res) /* Say "X" */
  4547. ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
  4548. if (!res)
  4549. res = ast_waitstream(mychannel, "");
  4550. ast_stopstream(mychannel);
  4551. if (saycharstr(mychannel,".") == -1)
  4552. {
  4553. imdone = 1;
  4554. break;
  4555. }
  4556. if(!res) /* Say "Y" */
  4557. ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
  4558. if (!res){
  4559. res = ast_waitstream(mychannel, "");
  4560. ast_stopstream(mychannel);
  4561. }
  4562. else
  4563. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4564. imdone = 1;
  4565. break;
  4566. case ARB_ALPHA:
  4567. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  4568. if(mytele->param)
  4569. saycharstr(mychannel, mytele->param);
  4570. imdone = 1;
  4571. break;
  4572. case REV_PATCH:
  4573. wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
  4574. if(mytele->param) {
  4575. /* Parts of this section taken from app_parkandannounce */
  4576. char *tpl_working, *tpl_current;
  4577. char *tmp[100], *myparm;
  4578. int looptemp=0,idx=0, dres = 0;
  4579. tpl_working = ast_strdup(mytele->param);
  4580. myparm = strsep(&tpl_working,",");
  4581. tpl_current=strsep(&tpl_working, ":");
  4582. while(tpl_current && looptemp < sizeof(tmp)) {
  4583. tmp[looptemp]=tpl_current;
  4584. looptemp++;
  4585. tpl_current=strsep(&tpl_working,":");
  4586. }
  4587. for(idx=0; idx<looptemp; idx++) {
  4588. if(!strcmp(tmp[idx], "PARKED")) {
  4589. ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
  4590. } else if(!strcmp(tmp[idx], "NODE")) {
  4591. ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
  4592. } else {
  4593. dres = ast_streamfile(mychannel, tmp[idx], mychannel->language);
  4594. if(!dres) {
  4595. dres = ast_waitstream(mychannel, "");
  4596. } else {
  4597. ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[idx], mychannel->name);
  4598. dres = 0;
  4599. }
  4600. }
  4601. }
  4602. ast_free(tpl_working);
  4603. }
  4604. imdone = 1;
  4605. break;
  4606. case TEST_TONE:
  4607. imdone = 1;
  4608. if (myrpt->stopgen) break;
  4609. myrpt->stopgen = -1;
  4610. if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
  4611. {
  4612. myrpt->stopgen = 0;
  4613. break;
  4614. }
  4615. while(mychannel->generatordata && (myrpt->stopgen <= 0)) {
  4616. if (ast_safe_sleep(mychannel,1)) break;
  4617. imdone = 1;
  4618. }
  4619. myrpt->stopgen = 0;
  4620. break;
  4621. default:
  4622. break;
  4623. }
  4624. if (!imdone)
  4625. {
  4626. if (!res)
  4627. res = ast_waitstream(mychannel, "");
  4628. else {
  4629. ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
  4630. res = 0;
  4631. }
  4632. }
  4633. ast_stopstream(mychannel);
  4634. rpt_mutex_lock(&myrpt->lock);
  4635. if (mytele->mode == TAILMSG)
  4636. {
  4637. if (!res)
  4638. {
  4639. myrpt->tailmessagen++;
  4640. if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
  4641. }
  4642. else
  4643. {
  4644. myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
  4645. }
  4646. }
  4647. remque((struct qelem *)mytele);
  4648. myrpt->active_telem = NULL;
  4649. rpt_mutex_unlock(&myrpt->lock);
  4650. ast_free(nodename);
  4651. ast_free(ident);
  4652. ast_free(mytele);
  4653. ast_hangup(mychannel);
  4654. #ifdef APP_RPT_LOCK_DEBUG
  4655. {
  4656. struct lockthread *t;
  4657. sleep(5);
  4658. ast_mutex_lock(&locklock);
  4659. t = get_lockthread(pthread_self());
  4660. if (t) memset(t,0,sizeof(struct lockthread));
  4661. ast_mutex_unlock(&locklock);
  4662. }
  4663. #endif
  4664. pthread_exit(NULL);
  4665. }
  4666. static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
  4667. {
  4668. struct rpt_tele *tele;
  4669. struct rpt_link *mylink = NULL;
  4670. int res;
  4671. pthread_attr_t attr;
  4672. char *v1, *v2;
  4673. if(debug > 6)
  4674. ast_log(LOG_NOTICE,"mode=%i data=%s\n",mode, (char *)data);
  4675. switch(mode)
  4676. {
  4677. case UNKEY:
  4678. /* if any of the following are defined, go ahead and do it,
  4679. otherwise, don't bother */
  4680. v1 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
  4681. "unlinkedct");
  4682. v2 = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name,
  4683. "remotect");
  4684. if (telem_lookup(myrpt,NULL, myrpt->name, "remotemon") &&
  4685. telem_lookup(myrpt,NULL, myrpt->name, "remotetx") &&
  4686. telem_lookup(myrpt,NULL, myrpt->name, "cmdmode") &&
  4687. (!(v1 && telem_lookup(myrpt,NULL, myrpt->name, v1))) &&
  4688. (!(v2 && telem_lookup(myrpt,NULL, myrpt->name, v2)))) return;
  4689. break;
  4690. case LINKUNKEY:
  4691. if (!ast_variable_retrieve(myrpt->cfg, myrpt->name, "linkunkeyct"))
  4692. return;
  4693. break;
  4694. default:
  4695. break;
  4696. }
  4697. tele = ast_malloc(sizeof(struct rpt_tele));
  4698. if (!tele)
  4699. {
  4700. ast_log(LOG_WARNING, "Unable to allocate memory\n");
  4701. pthread_exit(NULL);
  4702. return;
  4703. }
  4704. /* zero it out */
  4705. memset((char *)tele,0,sizeof(struct rpt_tele));
  4706. tele->rpt = myrpt;
  4707. tele->mode = mode;
  4708. if (mode == PARROT) tele->parrot = (uintptr_t) data;
  4709. else mylink = (struct rpt_link *) data;
  4710. rpt_mutex_lock(&myrpt->lock);
  4711. if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
  4712. (mode == LINKUNKEY)){
  4713. memset(&tele->mylink,0,sizeof(struct rpt_link));
  4714. if (mylink){
  4715. memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
  4716. }
  4717. }
  4718. else if ((mode == ARB_ALPHA) || (mode == REV_PATCH) || (mode == PLAYBACK)) {
  4719. strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
  4720. tele->param[TELEPARAMSIZE - 1] = 0;
  4721. }
  4722. if (mode == REMXXX) tele->submode = (intptr_t) data;
  4723. insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
  4724. rpt_mutex_unlock(&myrpt->lock);
  4725. pthread_attr_init(&attr);
  4726. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  4727. res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
  4728. if(res < 0){
  4729. rpt_mutex_lock(&myrpt->lock);
  4730. remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
  4731. rpt_mutex_unlock(&myrpt->lock);
  4732. ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
  4733. }
  4734. return;
  4735. }
  4736. static void *rpt_call(void *this)
  4737. {
  4738. struct dahdi_confinfo ci; /* conference info */
  4739. struct rpt *myrpt = (struct rpt *)this;
  4740. int res;
  4741. int stopped,congstarted,dialtimer,lastcidx,aborted;
  4742. struct ast_channel *mychannel,*genchannel;
  4743. myrpt->mydtmf = 0;
  4744. /* allocate a pseudo-channel thru asterisk */
  4745. mychannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  4746. if (!mychannel)
  4747. {
  4748. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  4749. pthread_exit(NULL);
  4750. }
  4751. #ifdef AST_CDR_FLAG_POST_DISABLED
  4752. if (mychannel->cdr)
  4753. ast_set_flag(mychannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  4754. #endif
  4755. ci.chan = 0;
  4756. ci.confno = myrpt->conf; /* use the pseudo conference */
  4757. #if 0
  4758. ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
  4759. | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
  4760. #endif
  4761. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
  4762. /* first put the channel on the conference */
  4763. if (ioctl(mychannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  4764. {
  4765. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  4766. ast_hangup(mychannel);
  4767. myrpt->callmode = 0;
  4768. pthread_exit(NULL);
  4769. }
  4770. /* allocate a pseudo-channel thru asterisk */
  4771. genchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  4772. if (!genchannel)
  4773. {
  4774. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  4775. ast_hangup(mychannel);
  4776. pthread_exit(NULL);
  4777. }
  4778. #ifdef AST_CDR_FLAG_POST_DISABLED
  4779. if (genchannel->cdr)
  4780. ast_set_flag(genchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  4781. #endif
  4782. ci.chan = 0;
  4783. ci.confno = myrpt->conf;
  4784. ci.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER
  4785. | DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
  4786. /* first put the channel on the conference */
  4787. if (ioctl(genchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  4788. {
  4789. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  4790. ast_hangup(mychannel);
  4791. ast_hangup(genchannel);
  4792. myrpt->callmode = 0;
  4793. pthread_exit(NULL);
  4794. }
  4795. if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
  4796. {
  4797. ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
  4798. ast_hangup(mychannel);
  4799. ast_hangup(genchannel);
  4800. myrpt->callmode = 0;
  4801. pthread_exit(NULL);
  4802. }
  4803. if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
  4804. {
  4805. ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
  4806. ast_hangup(mychannel);
  4807. ast_hangup(genchannel);
  4808. myrpt->callmode = 0;
  4809. pthread_exit(NULL);
  4810. }
  4811. /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
  4812. if ((!myrpt->patchquiet) && (tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_DIALTONE) < 0))
  4813. {
  4814. ast_log(LOG_WARNING, "Cannot start dialtone\n");
  4815. ast_hangup(mychannel);
  4816. ast_hangup(genchannel);
  4817. myrpt->callmode = 0;
  4818. pthread_exit(NULL);
  4819. }
  4820. stopped = 0;
  4821. congstarted = 0;
  4822. dialtimer = 0;
  4823. lastcidx = 0;
  4824. myrpt->calldigittimer = 0;
  4825. aborted = 0;
  4826. while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
  4827. {
  4828. if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
  4829. dialtimer = 0;
  4830. lastcidx = myrpt->cidx;
  4831. }
  4832. if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
  4833. if(debug)
  4834. ast_log(LOG_NOTICE, "dialtimer %i > patchdialtime %i\n", dialtimer,myrpt->patchdialtime);
  4835. rpt_mutex_lock(&myrpt->lock);
  4836. aborted = 1;
  4837. myrpt->callmode = 0;
  4838. rpt_mutex_unlock(&myrpt->lock);
  4839. break;
  4840. }
  4841. if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
  4842. {
  4843. stopped = 1;
  4844. /* stop dial tone */
  4845. tone_zone_play_tone(genchannel->fds[0],-1);
  4846. }
  4847. if (myrpt->callmode == 1)
  4848. {
  4849. if(myrpt->calldigittimer > PATCH_DIALPLAN_TIMEOUT)
  4850. {
  4851. myrpt->callmode = 2;
  4852. break;
  4853. }
  4854. /* bump timer if active */
  4855. if (myrpt->calldigittimer)
  4856. myrpt->calldigittimer += MSWAIT;
  4857. }
  4858. if (myrpt->callmode == 4)
  4859. {
  4860. if(!congstarted){
  4861. congstarted = 1;
  4862. /* start congestion tone */
  4863. tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
  4864. }
  4865. }
  4866. res = ast_safe_sleep(mychannel, MSWAIT);
  4867. if (res < 0)
  4868. {
  4869. if(debug)
  4870. ast_log(LOG_NOTICE, "ast_safe_sleep=%i\n", res);
  4871. ast_hangup(mychannel);
  4872. ast_hangup(genchannel);
  4873. rpt_mutex_lock(&myrpt->lock);
  4874. myrpt->callmode = 0;
  4875. rpt_mutex_unlock(&myrpt->lock);
  4876. pthread_exit(NULL);
  4877. }
  4878. dialtimer += MSWAIT;
  4879. }
  4880. /* stop any tone generation */
  4881. tone_zone_play_tone(genchannel->fds[0],-1);
  4882. /* end if done */
  4883. if (!myrpt->callmode)
  4884. {
  4885. if(debug)
  4886. ast_log(LOG_NOTICE, "callmode==0\n");
  4887. ast_hangup(mychannel);
  4888. ast_hangup(genchannel);
  4889. rpt_mutex_lock(&myrpt->lock);
  4890. myrpt->callmode = 0;
  4891. myrpt->macropatch=0;
  4892. channel_revert(myrpt);
  4893. rpt_mutex_unlock(&myrpt->lock);
  4894. if((!myrpt->patchquiet) && aborted)
  4895. rpt_telemetry(myrpt, TERM, NULL);
  4896. pthread_exit(NULL);
  4897. }
  4898. if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
  4899. char *name, *loc, *instr;
  4900. instr = ast_strdup(myrpt->p.ourcallerid);
  4901. if(instr){
  4902. ast_callerid_parse(instr, &name, &loc);
  4903. if(loc){
  4904. mychannel->caller.id.number.valid = 1;
  4905. ast_free(mychannel->caller.id.number.str);
  4906. mychannel->caller.id.number.str = ast_strdup(loc);
  4907. }
  4908. if(name){
  4909. mychannel->caller.id.name.valid = 1;
  4910. ast_free(mychannel->caller.id.name.str);
  4911. mychannel->caller.id.name.str = ast_strdup(name);
  4912. }
  4913. ast_free(instr);
  4914. }
  4915. }
  4916. ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
  4917. ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
  4918. if (myrpt->p.acctcode)
  4919. ast_cdr_setaccount(mychannel,myrpt->p.acctcode);
  4920. mychannel->priority = 1;
  4921. ast_channel_undefer_dtmf(mychannel);
  4922. if (ast_pbx_start(mychannel) < 0)
  4923. {
  4924. ast_log(LOG_WARNING, "Unable to start PBX!!\n");
  4925. ast_hangup(mychannel);
  4926. ast_hangup(genchannel);
  4927. rpt_mutex_lock(&myrpt->lock);
  4928. myrpt->callmode = 0;
  4929. rpt_mutex_unlock(&myrpt->lock);
  4930. pthread_exit(NULL);
  4931. }
  4932. usleep(10000);
  4933. rpt_mutex_lock(&myrpt->lock);
  4934. myrpt->callmode = 3;
  4935. /* set appropriate conference for the pseudo */
  4936. ci.chan = 0;
  4937. ci.confno = myrpt->conf;
  4938. ci.confmode = (myrpt->p.duplex == 2) ? DAHDI_CONF_CONFANNMON :
  4939. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  4940. /* first put the channel on the conference in announce mode */
  4941. if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  4942. {
  4943. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  4944. ast_hangup(mychannel);
  4945. ast_hangup(genchannel);
  4946. myrpt->callmode = 0;
  4947. pthread_exit(NULL);
  4948. }
  4949. /* get its channel number */
  4950. if (ioctl(mychannel->fds[0],DAHDI_CHANNO,&res) == -1)
  4951. {
  4952. ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
  4953. ast_hangup(mychannel);
  4954. myrpt->callmode = 0;
  4955. pthread_exit(NULL);
  4956. }
  4957. ci.chan = 0;
  4958. ci.confno = res;
  4959. ci.confmode = DAHDI_CONF_MONITOR;
  4960. /* put vox channel monitoring on the channel */
  4961. if (ioctl(myrpt->voxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  4962. {
  4963. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  4964. ast_hangup(mychannel);
  4965. myrpt->callmode = 0;
  4966. pthread_exit(NULL);
  4967. }
  4968. while(myrpt->callmode)
  4969. {
  4970. if ((!mychannel->pbx) && (myrpt->callmode != 4))
  4971. {
  4972. /* If patch is setup for far end disconnect */
  4973. if(myrpt->patchfarenddisconnect || (myrpt->p.duplex < 2)){
  4974. if(debug)ast_log(LOG_NOTICE,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
  4975. myrpt->callmode,myrpt->patchfarenddisconnect,myrpt->p.duplex);
  4976. myrpt->callmode = 0;
  4977. myrpt->macropatch=0;
  4978. if(!myrpt->patchquiet){
  4979. rpt_mutex_unlock(&myrpt->lock);
  4980. rpt_telemetry(myrpt, TERM, NULL);
  4981. rpt_mutex_lock(&myrpt->lock);
  4982. }
  4983. }
  4984. else{ /* Send congestion until patch is downed by command */
  4985. myrpt->callmode = 4;
  4986. rpt_mutex_unlock(&myrpt->lock);
  4987. /* start congestion tone */
  4988. tone_zone_play_tone(genchannel->fds[0],DAHDI_TONE_CONGESTION);
  4989. rpt_mutex_lock(&myrpt->lock);
  4990. }
  4991. }
  4992. if (myrpt->mydtmf)
  4993. {
  4994. struct ast_frame wf = {AST_FRAME_DTMF, } ;
  4995. wf.subclass.integer = myrpt->mydtmf;
  4996. rpt_mutex_unlock(&myrpt->lock);
  4997. ast_queue_frame(mychannel,&wf);
  4998. #ifdef NEW_ASTERISK
  4999. ast_senddigit(genchannel,myrpt->mydtmf,0);
  5000. #else
  5001. ast_senddigit(genchannel,myrpt->mydtmf);
  5002. #endif
  5003. rpt_mutex_lock(&myrpt->lock);
  5004. myrpt->mydtmf = 0;
  5005. }
  5006. rpt_mutex_unlock(&myrpt->lock);
  5007. usleep(MSWAIT * 1000);
  5008. rpt_mutex_lock(&myrpt->lock);
  5009. }
  5010. if(debug)
  5011. ast_log(LOG_NOTICE, "exit channel loop\n");
  5012. rpt_mutex_unlock(&myrpt->lock);
  5013. tone_zone_play_tone(genchannel->fds[0],-1);
  5014. if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
  5015. ast_hangup(genchannel);
  5016. rpt_mutex_lock(&myrpt->lock);
  5017. myrpt->callmode = 0;
  5018. myrpt->macropatch=0;
  5019. channel_revert(myrpt);
  5020. rpt_mutex_unlock(&myrpt->lock);
  5021. /* set appropriate conference for the pseudo */
  5022. ci.chan = 0;
  5023. ci.confno = myrpt->conf;
  5024. ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
  5025. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  5026. /* first put the channel on the conference in announce mode */
  5027. if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  5028. {
  5029. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  5030. }
  5031. pthread_exit(NULL);
  5032. }
  5033. static void send_link_dtmf(struct rpt *myrpt,char c)
  5034. {
  5035. char str[300];
  5036. struct ast_frame wf;
  5037. struct rpt_link *l;
  5038. snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
  5039. wf.frametype = AST_FRAME_TEXT;
  5040. wf.subclass.integer = 0;
  5041. wf.offset = 0;
  5042. wf.mallocd = 0;
  5043. wf.datalen = strlen(str) + 1;
  5044. wf.samples = 0;
  5045. l = myrpt->links.next;
  5046. /* first, see if our dude is there */
  5047. while(l != &myrpt->links)
  5048. {
  5049. if (l->name[0] == '0')
  5050. {
  5051. l = l->next;
  5052. continue;
  5053. }
  5054. /* if we found it, write it and were done */
  5055. if (!strcmp(l->name,myrpt->cmdnode))
  5056. {
  5057. wf.data.ptr = str;
  5058. if (l->chan) ast_write(l->chan,&wf);
  5059. return;
  5060. }
  5061. l = l->next;
  5062. }
  5063. l = myrpt->links.next;
  5064. /* if not, give it to everyone */
  5065. while(l != &myrpt->links)
  5066. {
  5067. wf.data.ptr = str;
  5068. if (l->chan) ast_write(l->chan,&wf);
  5069. l = l->next;
  5070. }
  5071. return;
  5072. }
  5073. static void send_link_keyquery(struct rpt *myrpt)
  5074. {
  5075. char str[300];
  5076. struct ast_frame wf;
  5077. struct rpt_link *l;
  5078. rpt_mutex_lock(&myrpt->lock);
  5079. memset(myrpt->topkey,0,sizeof(myrpt->topkey));
  5080. myrpt->topkeystate = 1;
  5081. time(&myrpt->topkeytime);
  5082. rpt_mutex_unlock(&myrpt->lock);
  5083. snprintf(str, sizeof(str), "K? * %s 0 0", myrpt->name);
  5084. wf.frametype = AST_FRAME_TEXT;
  5085. wf.subclass.integer = 0;
  5086. wf.offset = 0;
  5087. wf.mallocd = 0;
  5088. wf.datalen = strlen(str) + 1;
  5089. wf.samples = 0;
  5090. l = myrpt->links.next;
  5091. /* give it to everyone */
  5092. while(l != &myrpt->links)
  5093. {
  5094. wf.data.ptr = str;
  5095. if (l->chan) ast_write(l->chan,&wf);
  5096. l = l->next;
  5097. }
  5098. return;
  5099. }
  5100. /* send newkey request */
  5101. static void send_newkey(struct ast_channel *chan)
  5102. {
  5103. /* ast_safe_sleep(chan,10); */
  5104. ast_sendtext(chan,newkeystr);
  5105. return;
  5106. }
  5107. /*
  5108. * Connect a link
  5109. *
  5110. * Return values:
  5111. * -2: Attempt to connect to self
  5112. * -1: No such node
  5113. * 0: Success
  5114. * 1: No match yet
  5115. * 2: Already connected to this node
  5116. */
  5117. static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
  5118. {
  5119. char *val, *s, *s1, *tele;
  5120. char lstr[MAXLINKLIST],*strs[MAXLINKLIST];
  5121. char tmp[300], deststr[300] = "",modechange = 0;
  5122. char sx[320],*sy;
  5123. struct rpt_link *l;
  5124. int reconnects = 0;
  5125. int i,n;
  5126. struct dahdi_confinfo ci; /* conference info */
  5127. val = node_lookup(myrpt,node);
  5128. if (!val){
  5129. if(strlen(node) >= myrpt->longestnode)
  5130. return -1; /* No such node */
  5131. return 1; /* No match yet */
  5132. }
  5133. if(!strcmp(myrpt->name,node)) /* Do not allow connections to self */
  5134. return -2;
  5135. if(debug > 3){
  5136. ast_log(LOG_NOTICE,"Connect attempt to node %s\n", node);
  5137. ast_log(LOG_NOTICE,"Mode: %s\n",(mode)?"Transceive":"Monitor");
  5138. ast_log(LOG_NOTICE,"Connection type: %s\n",(perma)?"Permalink":"Normal");
  5139. }
  5140. strncpy(tmp,val,sizeof(tmp) - 1);
  5141. s = tmp;
  5142. s1 = strsep(&s,",");
  5143. if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
  5144. {
  5145. sy = strchr(s1,'/');
  5146. *sy = 0;
  5147. sprintf(sx,"%s:4569/%s",s1,sy + 1);
  5148. s1 = sx;
  5149. }
  5150. strsep(&s,",");
  5151. rpt_mutex_lock(&myrpt->lock);
  5152. l = myrpt->links.next;
  5153. /* try to find this one in queue */
  5154. while(l != &myrpt->links){
  5155. if (l->name[0] == '0')
  5156. {
  5157. l = l->next;
  5158. continue;
  5159. }
  5160. /* if found matching string */
  5161. if (!strcmp(l->name, node))
  5162. break;
  5163. l = l->next;
  5164. }
  5165. /* if found */
  5166. if (l != &myrpt->links){
  5167. /* if already in this mode, just ignore */
  5168. if ((l->mode) || (!l->chan)) {
  5169. rpt_mutex_unlock(&myrpt->lock);
  5170. return 2; /* Already linked */
  5171. }
  5172. reconnects = l->reconnects;
  5173. rpt_mutex_unlock(&myrpt->lock);
  5174. if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
  5175. l->retries = l->max_retries + 1;
  5176. l->disced = 2;
  5177. modechange = 1;
  5178. } else
  5179. {
  5180. __mklinklist(myrpt,NULL,lstr);
  5181. rpt_mutex_unlock(&myrpt->lock);
  5182. n = finddelim(lstr,strs,MAXLINKLIST);
  5183. for(i = 0; i < n; i++)
  5184. {
  5185. if ((*strs[i] < '0') ||
  5186. (*strs[i] > '9')) strs[i]++;
  5187. if (!strcmp(strs[i],node))
  5188. {
  5189. return 2; /* Already linked */
  5190. }
  5191. }
  5192. }
  5193. strncpy(myrpt->lastlinknode,node,MAXNODESTR - 1);
  5194. /* establish call */
  5195. l = ast_malloc(sizeof(struct rpt_link));
  5196. if (!l)
  5197. {
  5198. ast_log(LOG_WARNING, "Unable to malloc\n");
  5199. return -1;
  5200. }
  5201. /* zero the silly thing */
  5202. memset((char *)l,0,sizeof(struct rpt_link));
  5203. l->mode = mode;
  5204. l->outbound = 1;
  5205. l->thisconnected = 0;
  5206. voxinit_link(l,1);
  5207. strncpy(l->name, node, MAXNODESTR - 1);
  5208. l->isremote = (s && ast_true(s));
  5209. if (modechange) l->connected = 1;
  5210. l->hasconnected = l->perma = perma;
  5211. #ifdef ALLOW_LOCAL_CHANNELS
  5212. if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
  5213. strncpy(deststr, s1, sizeof(deststr));
  5214. else
  5215. snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
  5216. #else
  5217. snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
  5218. #endif
  5219. tele = strchr(deststr, '/');
  5220. if (!tele){
  5221. ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
  5222. ast_free(l);
  5223. return -1;
  5224. }
  5225. *tele++ = 0;
  5226. l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  5227. if (l->chan){
  5228. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  5229. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  5230. #ifdef AST_CDR_FLAG_POST_DISABLED
  5231. if (l->chan->cdr)
  5232. ast_set_flag(l->chan->cdr,AST_CDR_FLAG_POST_DISABLED);
  5233. #endif
  5234. #ifndef NEW_ASTERISK
  5235. l->chan->whentohangup = 0;
  5236. #endif
  5237. l->chan->appl = "Apprpt";
  5238. l->chan->data = "(Remote Rx)";
  5239. if (debug > 3)
  5240. ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
  5241. deststr, tele, l->chan->name);
  5242. l->chan->caller.id.number.valid = 1;
  5243. ast_free(l->chan->caller.id.number.str);
  5244. l->chan->caller.id.number.str = ast_strdup(myrpt->name);
  5245. ast_call(l->chan,tele,999);
  5246. }
  5247. else {
  5248. if(debug > 3)
  5249. ast_log(LOG_NOTICE, "Unable to place call to %s/%s on %s\n",
  5250. deststr,tele,l->chan->name);
  5251. if (myrpt->p.archivedir)
  5252. {
  5253. char str[100];
  5254. sprintf(str,"LINKFAIL,%s",l->name);
  5255. donodelog(myrpt,str);
  5256. }
  5257. ast_free(l);
  5258. return -1;
  5259. }
  5260. /* allocate a pseudo-channel thru asterisk */
  5261. l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  5262. if (!l->pchan){
  5263. ast_log(LOG_WARNING,"rpt connect: Sorry unable to obtain pseudo channel\n");
  5264. ast_hangup(l->chan);
  5265. ast_free(l);
  5266. return -1;
  5267. }
  5268. ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
  5269. ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
  5270. #ifdef AST_CDR_FLAG_POST_DISABLED
  5271. if (l->pchan->cdr)
  5272. ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
  5273. #endif
  5274. /* make a conference for the tx */
  5275. ci.chan = 0;
  5276. ci.confno = myrpt->conf;
  5277. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
  5278. /* first put the channel on the conference in proper mode */
  5279. if (ioctl(l->pchan->fds[0], DAHDI_SETCONF, &ci) == -1)
  5280. {
  5281. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  5282. ast_hangup(l->chan);
  5283. ast_hangup(l->pchan);
  5284. ast_free(l);
  5285. return -1;
  5286. }
  5287. rpt_mutex_lock(&myrpt->lock);
  5288. l->reconnects = reconnects;
  5289. /* insert at end of queue */
  5290. l->max_retries = MAX_RETRIES;
  5291. if (perma)
  5292. l->max_retries = MAX_RETRIES_PERM;
  5293. if (l->isremote) l->retries = l->max_retries + 1;
  5294. insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
  5295. __kickshort(myrpt);
  5296. rpt_mutex_unlock(&myrpt->lock);
  5297. if (!l->phonemode) send_newkey(l->chan);
  5298. return 0;
  5299. }
  5300. /*
  5301. * Internet linking function
  5302. */
  5303. static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
  5304. {
  5305. char *val, *s, *s1;
  5306. char tmp[300];
  5307. char digitbuf[MAXNODESTR],*strs[MAXLINKLIST];
  5308. char mode,perma;
  5309. char sx[320],*sy;
  5310. struct rpt_link *l;
  5311. int i,r;
  5312. if(!param)
  5313. return DC_ERROR;
  5314. if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable )
  5315. return DC_ERROR;
  5316. strncpy(digitbuf,digits,MAXNODESTR - 1);
  5317. if(debug > 6)
  5318. printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  5319. switch(myatoi(param)){
  5320. case 11: /* Perm Link off */
  5321. case 1: /* Link off */
  5322. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  5323. strcpy(digitbuf,myrpt->lastlinknode);
  5324. val = node_lookup(myrpt,digitbuf);
  5325. if (!val){
  5326. if(strlen(digitbuf) >= myrpt->longestnode)
  5327. return DC_ERROR;
  5328. break;
  5329. }
  5330. strncpy(tmp,val,sizeof(tmp) - 1);
  5331. s = tmp;
  5332. s1 = strsep(&s,",");
  5333. if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
  5334. {
  5335. sy = strchr(s1,'/');
  5336. *sy = 0;
  5337. sprintf(sx,"%s:4569/%s",s1,sy + 1);
  5338. s1 = sx;
  5339. }
  5340. strsep(&s,",");
  5341. rpt_mutex_lock(&myrpt->lock);
  5342. l = myrpt->links.next;
  5343. /* try to find this one in queue */
  5344. while(l != &myrpt->links){
  5345. if (l->name[0] == '0')
  5346. {
  5347. l = l->next;
  5348. continue;
  5349. }
  5350. /* if found matching string */
  5351. if (!strcmp(l->name, digitbuf))
  5352. break;
  5353. l = l->next;
  5354. }
  5355. if (l != &myrpt->links){ /* if found */
  5356. struct ast_frame wf;
  5357. /* must use perm command on perm link */
  5358. if ((myatoi(param) < 10) &&
  5359. (l->max_retries > MAX_RETRIES))
  5360. {
  5361. rpt_mutex_unlock(&myrpt->lock);
  5362. return DC_COMPLETE;
  5363. }
  5364. strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
  5365. l->retries = l->max_retries + 1;
  5366. l->disced = 1;
  5367. rpt_mutex_unlock(&myrpt->lock);
  5368. wf.frametype = AST_FRAME_TEXT;
  5369. wf.subclass.integer = 0;
  5370. wf.offset = 0;
  5371. wf.mallocd = 0;
  5372. wf.datalen = strlen(discstr) + 1;
  5373. wf.samples = 0;
  5374. wf.data.ptr = discstr;
  5375. if (l->chan)
  5376. {
  5377. ast_write(l->chan,&wf);
  5378. if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
  5379. ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
  5380. }
  5381. rpt_telemetry(myrpt, COMPLETE, NULL);
  5382. return DC_COMPLETE;
  5383. }
  5384. rpt_mutex_unlock(&myrpt->lock);
  5385. return DC_COMPLETE;
  5386. case 2: /* Link Monitor */
  5387. case 3: /* Link transceive */
  5388. case 12: /* Link Monitor permanent */
  5389. case 13: /* Link transceive permanent */
  5390. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  5391. strcpy(digitbuf,myrpt->lastlinknode);
  5392. /* Attempt connection */
  5393. perma = (atoi(param) > 10) ? 1 : 0;
  5394. mode = (atoi(param) & 1) ? 1 : 0;
  5395. r = connect_link(myrpt, digitbuf, mode, perma);
  5396. switch(r){
  5397. case -2: /* Attempt to connect to self */
  5398. return DC_COMPLETE; /* Silent error */
  5399. case 0:
  5400. rpt_telemetry(myrpt, COMPLETE, NULL);
  5401. return DC_COMPLETE;
  5402. case 1:
  5403. break;
  5404. case 2:
  5405. rpt_telemetry(myrpt, REMALREADY, NULL);
  5406. return DC_COMPLETE;
  5407. default:
  5408. rpt_telemetry(myrpt, CONNFAIL, NULL);
  5409. return DC_COMPLETE;
  5410. }
  5411. break;
  5412. case 4: /* Enter Command Mode */
  5413. /* if doesnt allow link cmd, or no links active, return */
  5414. if (((command_source != SOURCE_RPT) &&
  5415. (command_source != SOURCE_PHONE) &&
  5416. (command_source != SOURCE_ALT) &&
  5417. (command_source != SOURCE_DPHONE)) ||
  5418. (myrpt->links.next == &myrpt->links))
  5419. return DC_COMPLETE;
  5420. /* if already in cmd mode, or selected self, fughetabahtit */
  5421. if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
  5422. rpt_telemetry(myrpt, REMALREADY, NULL);
  5423. return DC_COMPLETE;
  5424. }
  5425. if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
  5426. strcpy(digitbuf,myrpt->lastlinknode);
  5427. /* node must at least exist in list */
  5428. val = node_lookup(myrpt,digitbuf);
  5429. if (!val){
  5430. if(strlen(digitbuf) >= myrpt->longestnode)
  5431. return DC_ERROR;
  5432. break;
  5433. }
  5434. rpt_mutex_lock(&myrpt->lock);
  5435. strcpy(myrpt->lastlinknode,digitbuf);
  5436. strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
  5437. rpt_mutex_unlock(&myrpt->lock);
  5438. rpt_telemetry(myrpt, REMGO, NULL);
  5439. return DC_COMPLETE;
  5440. case 5: /* Status */
  5441. rpt_telemetry(myrpt, STATUS, NULL);
  5442. return DC_COMPLETE;
  5443. case 15: /* Full Status */
  5444. rpt_telemetry(myrpt, FULLSTATUS, NULL);
  5445. return DC_COMPLETE;
  5446. case 6: /* All Links Off, including permalinks */
  5447. rpt_mutex_lock(&myrpt->lock);
  5448. myrpt->savednodes[0] = 0;
  5449. l = myrpt->links.next;
  5450. /* loop through all links */
  5451. while(l != &myrpt->links){
  5452. struct ast_frame wf;
  5453. if (l->name[0] == '0') /* Skip any IAXRPT monitoring */
  5454. {
  5455. l = l->next;
  5456. continue;
  5457. }
  5458. /* Make a string of disconnected nodes for possible restoration */
  5459. sprintf(tmp,"%c%c%s",(l->mode) ? 'X' : 'M',(l->perma) ? 'P':'T',l->name);
  5460. if(strlen(tmp) + strlen(myrpt->savednodes) + 1 < MAXNODESTR){
  5461. if(myrpt->savednodes[0])
  5462. strcat(myrpt->savednodes, ",");
  5463. strcat(myrpt->savednodes, tmp);
  5464. }
  5465. l->retries = l->max_retries + 1;
  5466. l->disced = 2; /* Silently disconnect */
  5467. rpt_mutex_unlock(&myrpt->lock);
  5468. /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
  5469. wf.frametype = AST_FRAME_TEXT;
  5470. wf.subclass.integer = 0;
  5471. wf.offset = 0;
  5472. wf.mallocd = 0;
  5473. wf.datalen = strlen(discstr) + 1;
  5474. wf.samples = 0;
  5475. wf.data.ptr = discstr;
  5476. if (l->chan)
  5477. {
  5478. ast_write(l->chan,&wf);
  5479. ast_safe_sleep(l->chan,250); /* It's dead already, why check the return value? */
  5480. ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
  5481. }
  5482. rpt_mutex_lock(&myrpt->lock);
  5483. l = l->next;
  5484. }
  5485. rpt_mutex_unlock(&myrpt->lock);
  5486. if(debug > 3)
  5487. ast_log(LOG_NOTICE,"Nodes disconnected: %s\n",myrpt->savednodes);
  5488. rpt_telemetry(myrpt, COMPLETE, NULL);
  5489. return DC_COMPLETE;
  5490. case 7: /* Identify last node which keyed us up */
  5491. rpt_telemetry(myrpt, LASTNODEKEY, NULL);
  5492. break;
  5493. #ifdef _MDC_DECODE_H_
  5494. case 8:
  5495. myrpt->lastunit = 0xd00d;
  5496. mdc1200_notify(myrpt,NULL,myrpt->lastunit);
  5497. mdc1200_send(myrpt,myrpt->lastunit);
  5498. break;
  5499. #endif
  5500. case 16: /* Restore links disconnected with "disconnect all links" command */
  5501. strcpy(tmp, myrpt->savednodes); /* Make a copy */
  5502. finddelim(tmp, strs, MAXLINKLIST); /* convert into substrings */
  5503. for(i = 0; tmp[0] && strs[i] != NULL && i < MAXLINKLIST; i++){
  5504. s1 = strs[i];
  5505. mode = (s1[0] == 'X') ? 1 : 0;
  5506. perma = (s1[1] == 'P') ? 1 : 0;
  5507. connect_link(myrpt, s1 + 2, mode, perma); /* Try to reconnect */
  5508. }
  5509. rpt_telemetry(myrpt, COMPLETE, NULL);
  5510. break;
  5511. case 200:
  5512. case 201:
  5513. case 202:
  5514. case 203:
  5515. case 204:
  5516. case 205:
  5517. case 206:
  5518. case 207:
  5519. case 208:
  5520. case 209:
  5521. case 210:
  5522. case 211:
  5523. case 212:
  5524. case 213:
  5525. case 214:
  5526. case 215:
  5527. if (((myrpt->p.propagate_dtmf) &&
  5528. (command_source == SOURCE_LNK)) ||
  5529. ((myrpt->p.propagate_phonedtmf) &&
  5530. ((command_source == SOURCE_PHONE) ||
  5531. (command_source == SOURCE_ALT) ||
  5532. (command_source == SOURCE_DPHONE))))
  5533. do_dtmf_local(myrpt,
  5534. remdtmfstr[myatoi(param) - 200]);
  5535. default:
  5536. return DC_ERROR;
  5537. }
  5538. return DC_INDETERMINATE;
  5539. }
  5540. /*
  5541. * Autopatch up
  5542. */
  5543. static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5544. {
  5545. pthread_attr_t attr;
  5546. int i, idx, paramlength;
  5547. char *lparam;
  5548. char *value = NULL;
  5549. char *paramlist[20];
  5550. static char *keywords[] = {
  5551. "context",
  5552. "dialtime",
  5553. "farenddisconnect",
  5554. "noct",
  5555. "quiet",
  5556. NULL
  5557. };
  5558. if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
  5559. return DC_ERROR;
  5560. if(debug)
  5561. printf("@@@@ Autopatch up\n");
  5562. if(!myrpt->callmode){
  5563. /* Set defaults */
  5564. myrpt->patchnoct = 0;
  5565. myrpt->patchdialtime = 0;
  5566. myrpt->patchfarenddisconnect = 0;
  5567. myrpt->patchquiet = 0;
  5568. strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
  5569. if(param){
  5570. /* Process parameter list */
  5571. lparam = ast_strdup(param);
  5572. if(!lparam){
  5573. ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
  5574. return DC_ERROR;
  5575. }
  5576. paramlength = finddelim(lparam, paramlist, 20);
  5577. for(i = 0; i < paramlength; i++){
  5578. idx = matchkeyword(paramlist[i], &value, keywords);
  5579. if(value)
  5580. value = skipchars(value, "= ");
  5581. switch(idx){
  5582. case 1: /* context */
  5583. strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
  5584. break;
  5585. case 2: /* dialtime */
  5586. myrpt->patchdialtime = atoi(value);
  5587. break;
  5588. case 3: /* farenddisconnect */
  5589. myrpt->patchfarenddisconnect = atoi(value);
  5590. break;
  5591. case 4: /* noct */
  5592. myrpt->patchnoct = atoi(value);
  5593. break;
  5594. case 5: /* quiet */
  5595. myrpt->patchquiet = atoi(value);
  5596. break;
  5597. default:
  5598. break;
  5599. }
  5600. }
  5601. ast_free(lparam);
  5602. }
  5603. }
  5604. rpt_mutex_lock(&myrpt->lock);
  5605. /* if on call, force * into current audio stream */
  5606. if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
  5607. myrpt->mydtmf = myrpt->p.endchar;
  5608. }
  5609. if (myrpt->callmode){
  5610. rpt_mutex_unlock(&myrpt->lock);
  5611. return DC_COMPLETE;
  5612. }
  5613. myrpt->callmode = 1;
  5614. myrpt->cidx = 0;
  5615. myrpt->exten[myrpt->cidx] = 0;
  5616. rpt_mutex_unlock(&myrpt->lock);
  5617. pthread_attr_init(&attr);
  5618. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  5619. ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
  5620. return DC_COMPLETE;
  5621. }
  5622. /*
  5623. * Autopatch down
  5624. */
  5625. static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5626. {
  5627. if (myrpt->p.s[myrpt->p.sysstate_cur].txdisable || myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
  5628. return DC_ERROR;
  5629. if(debug)
  5630. printf("@@@@ Autopatch down\n");
  5631. rpt_mutex_lock(&myrpt->lock);
  5632. myrpt->macropatch=0;
  5633. if (!myrpt->callmode){
  5634. rpt_mutex_unlock(&myrpt->lock);
  5635. return DC_COMPLETE;
  5636. }
  5637. myrpt->callmode = 0;
  5638. channel_revert(myrpt);
  5639. rpt_mutex_unlock(&myrpt->lock);
  5640. rpt_telemetry(myrpt, TERM, NULL);
  5641. return DC_COMPLETE;
  5642. }
  5643. /*
  5644. * Status
  5645. */
  5646. static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5647. {
  5648. if (!param)
  5649. return DC_ERROR;
  5650. if ((myrpt->p.s[myrpt->p.sysstate_cur].txdisable) || (myrpt->p.s[myrpt->p.sysstate_cur].userfundisable))
  5651. return DC_ERROR;
  5652. if(debug)
  5653. printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  5654. switch(myatoi(param)){
  5655. case 1: /* System ID */
  5656. rpt_telemetry(myrpt, ID1, NULL);
  5657. return DC_COMPLETE;
  5658. case 2: /* System Time */
  5659. rpt_telemetry(myrpt, STATS_TIME, NULL);
  5660. return DC_COMPLETE;
  5661. case 3: /* app_rpt.c version */
  5662. rpt_telemetry(myrpt, STATS_VERSION, NULL);
  5663. return DC_COMPLETE;
  5664. case 11: /* System ID (local only)*/
  5665. rpt_telemetry(myrpt, ID , NULL);
  5666. return DC_COMPLETE;
  5667. case 12: /* System Time (local only)*/
  5668. rpt_telemetry(myrpt, STATS_TIME_LOCAL, NULL);
  5669. return DC_COMPLETE;
  5670. default:
  5671. return DC_ERROR;
  5672. }
  5673. return DC_INDETERMINATE;
  5674. }
  5675. /*
  5676. * Macro-oni (without Salami)
  5677. */
  5678. static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5679. {
  5680. char *val;
  5681. int i;
  5682. if (myrpt->remote)
  5683. return DC_ERROR;
  5684. if(debug)
  5685. printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  5686. if(strlen(digitbuf) < 1) /* needs 1 digit */
  5687. return DC_INDETERMINATE;
  5688. for(i = 0 ; i < digitbuf[i] ; i++) {
  5689. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  5690. return DC_ERROR;
  5691. }
  5692. if (*digitbuf == '0') val = myrpt->p.startupmacro;
  5693. else val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
  5694. /* param was 1 for local buf */
  5695. if (!val){
  5696. if (strlen(digitbuf) < myrpt->macro_longest)
  5697. return DC_INDETERMINATE;
  5698. rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
  5699. return DC_COMPLETE;
  5700. }
  5701. rpt_mutex_lock(&myrpt->lock);
  5702. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
  5703. {
  5704. rpt_mutex_unlock(&myrpt->lock);
  5705. rpt_telemetry(myrpt, MACRO_BUSY, NULL);
  5706. return DC_ERROR;
  5707. }
  5708. myrpt->macrotimer = MACROTIME;
  5709. strncat(myrpt->macrobuf,val,MAXMACRO - 1);
  5710. rpt_mutex_unlock(&myrpt->lock);
  5711. return DC_COMPLETE;
  5712. }
  5713. /*
  5714. * Playback a recording
  5715. */
  5716. static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5717. {
  5718. if (myrpt->remote)
  5719. return DC_ERROR;
  5720. if(debug)
  5721. printf("@@@@ playback param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
  5722. if (ast_fileexists(param,NULL,myrpt->rxchannel->language) <= 0)
  5723. return DC_ERROR;
  5724. rpt_telemetry(myrpt,PLAYBACK,param);
  5725. return DC_COMPLETE;
  5726. }
  5727. /*
  5728. * COP - Control operator
  5729. */
  5730. static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  5731. {
  5732. char string[16];
  5733. int i, r;
  5734. if(!param)
  5735. return DC_ERROR;
  5736. switch(myatoi(param)){
  5737. case 1: /* System reset */
  5738. return system("killall -9 asterisk");
  5739. case 2:
  5740. myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 0;
  5741. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
  5742. return DC_COMPLETE;
  5743. case 3:
  5744. myrpt->p.s[myrpt->p.sysstate_cur].txdisable = 1;
  5745. return DC_COMPLETE;
  5746. case 4: /* test tone on */
  5747. if (myrpt->stopgen < 0)
  5748. {
  5749. myrpt->stopgen = 1;
  5750. }
  5751. else
  5752. {
  5753. myrpt->stopgen = 0;
  5754. rpt_telemetry(myrpt, TEST_TONE, NULL);
  5755. }
  5756. return DC_COMPLETE;
  5757. case 5: /* Disgorge variables to log for debug purposes */
  5758. myrpt->disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
  5759. return DC_COMPLETE;
  5760. case 6: /* Simulate COR being activated (phone only) */
  5761. if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
  5762. return DC_DOKEY;
  5763. case 7: /* Time out timer enable */
  5764. myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 0;
  5765. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTENA");
  5766. return DC_COMPLETE;
  5767. case 8: /* Time out timer disable */
  5768. myrpt->p.s[myrpt->p.sysstate_cur].totdisable = 1;
  5769. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "TOTDIS");
  5770. return DC_COMPLETE;
  5771. case 9: /* Autopatch enable */
  5772. myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 0;
  5773. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APENA");
  5774. return DC_COMPLETE;
  5775. case 10: /* Autopatch disable */
  5776. myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable = 1;
  5777. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "APDIS");
  5778. return DC_COMPLETE;
  5779. case 11: /* Link Enable */
  5780. myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 0;
  5781. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKENA");
  5782. return DC_COMPLETE;
  5783. case 12: /* Link Disable */
  5784. myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable = 1;
  5785. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "LNKDIS");
  5786. return DC_COMPLETE;
  5787. case 13: /* Query System State */
  5788. string[0] = string[1] = 'S';
  5789. string[2] = myrpt->p.sysstate_cur + '0';
  5790. string[3] = '\0';
  5791. rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
  5792. return DC_COMPLETE;
  5793. case 14: /* Change System State */
  5794. if(strlen(digitbuf) == 0)
  5795. break;
  5796. if((digitbuf[0] < '0') || (digitbuf[0] > '9'))
  5797. return DC_ERROR;
  5798. myrpt->p.sysstate_cur = digitbuf[0] - '0';
  5799. string[0] = string[1] = 'S';
  5800. string[2] = myrpt->p.sysstate_cur + '0';
  5801. string[3] = '\0';
  5802. rpt_telemetry(myrpt, ARB_ALPHA, (void *) string);
  5803. return DC_COMPLETE;
  5804. case 15: /* Scheduler Enable */
  5805. myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 0;
  5806. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKENA");
  5807. return DC_COMPLETE;
  5808. case 16: /* Scheduler Disable */
  5809. myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable = 1;
  5810. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "SKDIS");
  5811. return DC_COMPLETE;
  5812. case 17: /* User functions Enable */
  5813. myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 0;
  5814. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFENA");
  5815. return DC_COMPLETE;
  5816. case 18: /* User Functions Disable */
  5817. myrpt->p.s[myrpt->p.sysstate_cur].userfundisable = 1;
  5818. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "UFDIS");
  5819. return DC_COMPLETE;
  5820. case 19: /* Alternate Tail Enable */
  5821. myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 1;
  5822. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATENA");
  5823. return DC_COMPLETE;
  5824. case 20: /* Alternate Tail Disable */
  5825. myrpt->p.s[myrpt->p.sysstate_cur].alternatetail = 0;
  5826. rpt_telemetry(myrpt, ARB_ALPHA, (void *) "ATDIS");
  5827. return DC_COMPLETE;
  5828. case 21: /* Parrot Mode Disable */
  5829. birdbath(myrpt);
  5830. if (myrpt->p.parrotmode < 2)
  5831. {
  5832. myrpt->p.parrotmode = 0;
  5833. rpt_telemetry(myrpt,COMPLETE,NULL);
  5834. return DC_COMPLETE;
  5835. }
  5836. break;
  5837. case 22: /* Parrot Mode Enable */
  5838. birdbath(myrpt);
  5839. if (myrpt->p.parrotmode < 2)
  5840. {
  5841. myrpt->p.parrotmode = 1;
  5842. rpt_telemetry(myrpt,COMPLETE,NULL);
  5843. return DC_COMPLETE;
  5844. }
  5845. break;
  5846. case 23: /* flush parrot in progress */
  5847. birdbath(myrpt);
  5848. rpt_telemetry(myrpt,COMPLETE,NULL);
  5849. return DC_COMPLETE;
  5850. case 24: /* flush all telemetry */
  5851. flush_telem(myrpt);
  5852. rpt_telemetry(myrpt,COMPLETE,NULL);
  5853. return DC_COMPLETE;
  5854. case 25: /* request keying info (brief) */
  5855. send_link_keyquery(myrpt);
  5856. myrpt->topkeylong = 0;
  5857. rpt_telemetry(myrpt,COMPLETE,NULL);
  5858. return DC_COMPLETE;
  5859. case 26: /* request keying info (full) */
  5860. send_link_keyquery(myrpt);
  5861. myrpt->topkeylong = 1;
  5862. rpt_telemetry(myrpt,COMPLETE,NULL);
  5863. return DC_COMPLETE;
  5864. case 30: /* recall memory location on programmable radio */
  5865. if(strlen(digitbuf) < 2) /* needs 2 digits */
  5866. break;
  5867. for(i = 0 ; i < 2 ; i++){
  5868. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  5869. return DC_ERROR;
  5870. }
  5871. r = retreive_memory(myrpt, digitbuf);
  5872. if (r < 0){
  5873. rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
  5874. return DC_COMPLETE;
  5875. }
  5876. if (r > 0){
  5877. return DC_ERROR;
  5878. }
  5879. if (setrem(myrpt) == -1) return DC_ERROR;
  5880. return DC_COMPLETE;
  5881. case 31:
  5882. /* set channel. note that it's going to change channel
  5883. then confirm on the new channel! */
  5884. if(strlen(digitbuf) < 2) /* needs 2 digits */
  5885. break;
  5886. for(i = 0 ; i < 2 ; i++){
  5887. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  5888. return DC_ERROR;
  5889. }
  5890. channel_steer(myrpt,digitbuf);
  5891. return DC_COMPLETE;
  5892. case 32: /* Touch Tone Pad Test */
  5893. i = strlen(digitbuf);
  5894. if(!i){
  5895. if(debug > 3)
  5896. ast_log(LOG_NOTICE,"Padtest entered");
  5897. myrpt->inpadtest = 1;
  5898. }
  5899. else{
  5900. if(debug > 3)
  5901. ast_log(LOG_NOTICE,"Padtest len= %d digits=%s",i,digitbuf);
  5902. if(digitbuf[i-1] != myrpt->p.endchar)
  5903. break;
  5904. rpt_telemetry(myrpt, ARB_ALPHA, digitbuf);
  5905. myrpt->inpadtest = 0;
  5906. if(debug > 3)
  5907. ast_log(LOG_NOTICE,"Padtest exited");
  5908. return DC_COMPLETE;
  5909. }
  5910. }
  5911. return DC_INDETERMINATE;
  5912. }
  5913. /*
  5914. * Collect digits one by one until something matches
  5915. */
  5916. static int collect_function_digits(struct rpt *myrpt, char *digits,
  5917. int command_source, struct rpt_link *mylink)
  5918. {
  5919. int i,rv;
  5920. char *stringp,*action,*param,*functiondigits;
  5921. char function_table_name[30] = "";
  5922. char workstring[200];
  5923. struct ast_variable *vp;
  5924. if (debug > 6) ast_log(LOG_NOTICE,"digits=%s source=%d\n",digits, command_source);
  5925. //if(debug)
  5926. // printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
  5927. if (command_source == SOURCE_DPHONE) {
  5928. if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
  5929. strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
  5930. }
  5931. else if (command_source == SOURCE_ALT) {
  5932. if (!myrpt->p.alt_functions) return DC_INDETERMINATE;
  5933. strncpy(function_table_name, myrpt->p.alt_functions, sizeof(function_table_name) - 1);
  5934. }
  5935. else if (command_source == SOURCE_PHONE) {
  5936. if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
  5937. strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
  5938. }
  5939. else if (command_source == SOURCE_LNK)
  5940. strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
  5941. else
  5942. strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
  5943. /* find context for function table in rpt.conf file */
  5944. vp = ast_variable_browse(myrpt->cfg, function_table_name);
  5945. while(vp) {
  5946. if(!strncasecmp(vp->name, digits, strlen(vp->name)))
  5947. break;
  5948. vp = vp->next;
  5949. }
  5950. /* if function context not found */
  5951. if(!vp) {
  5952. int n;
  5953. n = myrpt->longestfunc;
  5954. if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
  5955. else
  5956. if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
  5957. else
  5958. if (command_source == SOURCE_ALT) n = myrpt->alt_longestfunc;
  5959. else
  5960. if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
  5961. if(strlen(digits) >= n)
  5962. return DC_ERROR;
  5963. else
  5964. return DC_INDETERMINATE;
  5965. }
  5966. /* Found a match, retrieve value part and parse */
  5967. strncpy(workstring, vp->value, sizeof(workstring) - 1 );
  5968. stringp = workstring;
  5969. action = strsep(&stringp, ",");
  5970. param = stringp;
  5971. if(debug)
  5972. printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
  5973. /* Look up the action */
  5974. for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
  5975. if(!strncasecmp(action, function_table[i].action, strlen(action)))
  5976. break;
  5977. }
  5978. if(debug)
  5979. printf("@@@@ table index i = %d\n",i);
  5980. if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
  5981. /* Error, action not in table */
  5982. return DC_ERROR;
  5983. }
  5984. if(function_table[i].function == NULL){
  5985. /* Error, function undefined */
  5986. if(debug)
  5987. printf("@@@@ NULL for action: %s\n",action);
  5988. return DC_ERROR;
  5989. }
  5990. functiondigits = digits + strlen(vp->name);
  5991. rv=(*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
  5992. if (debug > 6) ast_log(LOG_NOTICE,"rv=%i\n",rv);
  5993. return(rv);
  5994. }
  5995. static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
  5996. char *str)
  5997. {
  5998. /* XXX ATTENTION: if you change the size of these arrays you MUST
  5999. * change the limits in corresponding sscanf() calls below. */
  6000. char tmp[512],tmp1[512],cmd[300] = "",dest[300],src[300],c;
  6001. int i,seq, res, ts;
  6002. struct rpt_link *l;
  6003. struct ast_frame wf;
  6004. wf.frametype = AST_FRAME_TEXT;
  6005. wf.subclass.integer = 0;
  6006. wf.offset = 0;
  6007. wf.mallocd = 0;
  6008. wf.datalen = strlen(str) + 1;
  6009. wf.samples = 0;
  6010. /* put string in our buffer */
  6011. strncpy(tmp,str,sizeof(tmp) - 1);
  6012. if (!strcmp(tmp,discstr))
  6013. {
  6014. mylink->disced = 1;
  6015. mylink->retries = mylink->max_retries + 1;
  6016. ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
  6017. return;
  6018. }
  6019. if (!strcmp(tmp,newkeystr))
  6020. {
  6021. mylink->newkey = 1;
  6022. return;
  6023. }
  6024. if (tmp[0] == 'L')
  6025. {
  6026. rpt_mutex_lock(&myrpt->lock);
  6027. strcpy(mylink->linklist,tmp + 2);
  6028. time(&mylink->linklistreceived);
  6029. rpt_mutex_unlock(&myrpt->lock);
  6030. if (debug > 6) ast_log(LOG_NOTICE,"@@@@ node %s received node list %s from node %s\n",
  6031. myrpt->name,tmp,mylink->name);
  6032. return;
  6033. }
  6034. if (tmp[0] == 'K')
  6035. {
  6036. if (sscanf(tmp, "%299s %299s %299s %30d %30d", cmd, dest, src, &seq, &ts) != 5)
  6037. {
  6038. ast_log(LOG_WARNING, "Unable to parse keying string %s\n",str);
  6039. return;
  6040. }
  6041. if (dest[0] == '0')
  6042. {
  6043. strcpy(dest,myrpt->name);
  6044. }
  6045. /* if not for me, redistribute to all links */
  6046. if (strcmp(dest,myrpt->name))
  6047. {
  6048. l = myrpt->links.next;
  6049. /* see if this is one in list */
  6050. while(l != &myrpt->links)
  6051. {
  6052. if (l->name[0] == '0')
  6053. {
  6054. l = l->next;
  6055. continue;
  6056. }
  6057. /* don't send back from where it came */
  6058. if ((l == mylink) || (!strcmp(l->name,mylink->name)))
  6059. {
  6060. l = l->next;
  6061. continue;
  6062. }
  6063. /* if it is, send it and we're done */
  6064. if (!strcmp(l->name,dest))
  6065. {
  6066. /* send, but not to src */
  6067. if (strcmp(l->name,src)) {
  6068. wf.data.ptr = str;
  6069. if (l->chan) ast_write(l->chan,&wf);
  6070. }
  6071. return;
  6072. }
  6073. l = l->next;
  6074. }
  6075. }
  6076. /* if not for me, or is broadcast, redistribute to all links */
  6077. if ((strcmp(dest,myrpt->name)) || (dest[0] == '*'))
  6078. {
  6079. l = myrpt->links.next;
  6080. /* otherwise, send it to all of em */
  6081. while(l != &myrpt->links)
  6082. {
  6083. if (l->name[0] == '0')
  6084. {
  6085. l = l->next;
  6086. continue;
  6087. }
  6088. /* don't send back from where it came */
  6089. if ((l == mylink) || (!strcmp(l->name,mylink->name)))
  6090. {
  6091. l = l->next;
  6092. continue;
  6093. }
  6094. /* send, but not to src */
  6095. if (strcmp(l->name,src)) {
  6096. wf.data.ptr = str;
  6097. if (l->chan) ast_write(l->chan,&wf);
  6098. }
  6099. l = l->next;
  6100. }
  6101. }
  6102. /* if not for me, end here */
  6103. if (strcmp(dest,myrpt->name) && (dest[0] != '*')) return;
  6104. if (cmd[1] == '?')
  6105. {
  6106. time_t now;
  6107. int n = 0;
  6108. time(&now);
  6109. if (myrpt->lastkeyedtime)
  6110. {
  6111. n = (int)(now - myrpt->lastkeyedtime);
  6112. }
  6113. sprintf(tmp1,"K %s %s %d %d",src,myrpt->name,myrpt->keyed,n);
  6114. wf.data.ptr = tmp1;
  6115. wf.datalen = strlen(tmp1) + 1;
  6116. if (mylink->chan) ast_write(mylink->chan,&wf);
  6117. return;
  6118. }
  6119. if (myrpt->topkeystate != 1) return;
  6120. rpt_mutex_lock(&myrpt->lock);
  6121. for(i = 0; i < TOPKEYN; i++)
  6122. {
  6123. if (!strcmp(myrpt->topkey[i].node,src)) break;
  6124. }
  6125. if (i >= TOPKEYN)
  6126. {
  6127. for(i = 0; i < TOPKEYN; i++)
  6128. {
  6129. if (!myrpt->topkey[i].node[0]) break;
  6130. }
  6131. }
  6132. if (i < TOPKEYN)
  6133. {
  6134. strncpy(myrpt->topkey[i].node,src,TOPKEYMAXSTR - 1);
  6135. myrpt->topkey[i].timesince = ts;
  6136. myrpt->topkey[i].keyed = seq;
  6137. }
  6138. rpt_mutex_unlock(&myrpt->lock);
  6139. return;
  6140. }
  6141. if (tmp[0] == 'I')
  6142. {
  6143. /* XXX WARNING: be very careful with the limits on the folowing
  6144. * sscanf() call, make sure they match the values defined above */
  6145. if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
  6146. {
  6147. ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
  6148. return;
  6149. }
  6150. mdc1200_notify(myrpt,src,seq);
  6151. strcpy(dest,"*");
  6152. }
  6153. else
  6154. {
  6155. /* XXX WARNING: be very careful with the limits on the folowing
  6156. * sscanf() call, make sure they match the values defined above */
  6157. if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
  6158. {
  6159. ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
  6160. return;
  6161. }
  6162. if (strcmp(cmd,"D"))
  6163. {
  6164. ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
  6165. return;
  6166. }
  6167. }
  6168. if (dest[0] == '0')
  6169. {
  6170. strcpy(dest,myrpt->name);
  6171. }
  6172. /* if not for me, redistribute to all links */
  6173. if (strcmp(dest,myrpt->name))
  6174. {
  6175. l = myrpt->links.next;
  6176. /* see if this is one in list */
  6177. while(l != &myrpt->links)
  6178. {
  6179. if (l->name[0] == '0')
  6180. {
  6181. l = l->next;
  6182. continue;
  6183. }
  6184. /* don't send back from where it came */
  6185. if ((l == mylink) || (!strcmp(l->name,mylink->name)))
  6186. {
  6187. l = l->next;
  6188. continue;
  6189. }
  6190. /* if it is, send it and we're done */
  6191. if (!strcmp(l->name,dest))
  6192. {
  6193. /* send, but not to src */
  6194. if (strcmp(l->name,src)) {
  6195. wf.data.ptr = str;
  6196. if (l->chan) ast_write(l->chan,&wf);
  6197. }
  6198. return;
  6199. }
  6200. l = l->next;
  6201. }
  6202. l = myrpt->links.next;
  6203. /* otherwise, send it to all of em */
  6204. while(l != &myrpt->links)
  6205. {
  6206. if (l->name[0] == '0')
  6207. {
  6208. l = l->next;
  6209. continue;
  6210. }
  6211. /* don't send back from where it came */
  6212. if ((l == mylink) || (!strcmp(l->name,mylink->name)))
  6213. {
  6214. l = l->next;
  6215. continue;
  6216. }
  6217. /* send, but not to src */
  6218. if (strcmp(l->name,src)) {
  6219. wf.data.ptr = str;
  6220. if (l->chan) ast_write(l->chan,&wf);
  6221. }
  6222. l = l->next;
  6223. }
  6224. return;
  6225. }
  6226. if (myrpt->p.archivedir)
  6227. {
  6228. char dtmfstr[100];
  6229. sprintf(dtmfstr,"DTMF,%s,%c",mylink->name,c);
  6230. donodelog(myrpt,dtmfstr);
  6231. }
  6232. c = func_xlat(myrpt,c,&myrpt->p.outxlat);
  6233. if (!c) return;
  6234. rpt_mutex_lock(&myrpt->lock);
  6235. if (c == myrpt->p.endchar) myrpt->stopgen = 1;
  6236. if (myrpt->callmode == 1)
  6237. {
  6238. myrpt->exten[myrpt->cidx++] = c;
  6239. myrpt->exten[myrpt->cidx] = 0;
  6240. /* if this exists */
  6241. if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  6242. {
  6243. /* if this really it, end now */
  6244. if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
  6245. myrpt->exten,1,NULL))
  6246. {
  6247. myrpt->callmode = 2;
  6248. if(!myrpt->patchquiet)
  6249. {
  6250. rpt_mutex_unlock(&myrpt->lock);
  6251. rpt_telemetry(myrpt,PROC,NULL);
  6252. rpt_mutex_lock(&myrpt->lock);
  6253. }
  6254. }
  6255. else /* othewise, reset timer */
  6256. {
  6257. myrpt->calldigittimer = 1;
  6258. }
  6259. }
  6260. /* if can continue, do so */
  6261. if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  6262. {
  6263. /* call has failed, inform user */
  6264. myrpt->callmode = 4;
  6265. }
  6266. }
  6267. if ((!myrpt->inpadtest) &&(c == myrpt->p.funcchar))
  6268. {
  6269. myrpt->rem_dtmfidx = 0;
  6270. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  6271. time(&myrpt->rem_dtmf_time);
  6272. rpt_mutex_unlock(&myrpt->lock);
  6273. return;
  6274. }
  6275. else if (myrpt->rem_dtmfidx < 0)
  6276. {
  6277. if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
  6278. {
  6279. myrpt->mydtmf = c;
  6280. }
  6281. if (myrpt->p.propagate_dtmf) do_dtmf_local(myrpt,c);
  6282. if (myrpt->p.propagate_phonedtmf) do_dtmf_phone(myrpt,mylink,c);
  6283. rpt_mutex_unlock(&myrpt->lock);
  6284. return;
  6285. }
  6286. else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
  6287. {
  6288. time(&myrpt->rem_dtmf_time);
  6289. if (myrpt->rem_dtmfidx < MAXDTMF)
  6290. {
  6291. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
  6292. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  6293. rpt_mutex_unlock(&myrpt->lock);
  6294. strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
  6295. res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
  6296. rpt_mutex_lock(&myrpt->lock);
  6297. switch(res){
  6298. case DC_INDETERMINATE:
  6299. break;
  6300. case DC_REQ_FLUSH:
  6301. myrpt->rem_dtmfidx = 0;
  6302. myrpt->rem_dtmfbuf[0] = 0;
  6303. break;
  6304. case DC_COMPLETE:
  6305. case DC_COMPLETEQUIET:
  6306. myrpt->totalexecdcommands++;
  6307. myrpt->dailyexecdcommands++;
  6308. strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
  6309. myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
  6310. myrpt->rem_dtmfbuf[0] = 0;
  6311. myrpt->rem_dtmfidx = -1;
  6312. myrpt->rem_dtmf_time = 0;
  6313. break;
  6314. case DC_ERROR:
  6315. default:
  6316. myrpt->rem_dtmfbuf[0] = 0;
  6317. myrpt->rem_dtmfidx = -1;
  6318. myrpt->rem_dtmf_time = 0;
  6319. break;
  6320. }
  6321. }
  6322. }
  6323. rpt_mutex_unlock(&myrpt->lock);
  6324. return;
  6325. }
  6326. static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
  6327. char c)
  6328. {
  6329. char cmd[300];
  6330. int res;
  6331. if (myrpt->p.archivedir)
  6332. {
  6333. char str[100];
  6334. sprintf(str,"DTMF(P),%s,%c",mylink->name,c);
  6335. donodelog(myrpt,str);
  6336. }
  6337. rpt_mutex_lock(&myrpt->lock);
  6338. if (mylink->phonemode == 3) /*If in simplex dumb phone mode */
  6339. {
  6340. if(c == myrpt->p.endchar) /* If end char */
  6341. {
  6342. mylink->lastrealrx = 0; /* Keying state = off */
  6343. rpt_mutex_unlock(&myrpt->lock);
  6344. return;
  6345. }
  6346. if(c == myrpt->p.funcchar) /* If lead-in char */
  6347. {
  6348. mylink->lastrealrx = !mylink->lastrealrx; /* Toggle keying state */
  6349. rpt_mutex_unlock(&myrpt->lock);
  6350. return;
  6351. }
  6352. }
  6353. else
  6354. {
  6355. if (c == myrpt->p.endchar)
  6356. {
  6357. if (mylink->lastrx)
  6358. {
  6359. mylink->lastrealrx = 0;
  6360. rpt_mutex_unlock(&myrpt->lock);
  6361. return;
  6362. }
  6363. myrpt->stopgen = 1;
  6364. if (myrpt->cmdnode[0])
  6365. {
  6366. myrpt->cmdnode[0] = 0;
  6367. myrpt->dtmfidx = -1;
  6368. myrpt->dtmfbuf[0] = 0;
  6369. rpt_mutex_unlock(&myrpt->lock);
  6370. rpt_telemetry(myrpt,COMPLETE,NULL);
  6371. return;
  6372. }
  6373. }
  6374. }
  6375. if (myrpt->cmdnode[0])
  6376. {
  6377. rpt_mutex_unlock(&myrpt->lock);
  6378. send_link_dtmf(myrpt,c);
  6379. return;
  6380. }
  6381. if (myrpt->callmode == 1)
  6382. {
  6383. myrpt->exten[myrpt->cidx++] = c;
  6384. myrpt->exten[myrpt->cidx] = 0;
  6385. /* if this exists */
  6386. if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  6387. {
  6388. /* if this really it, end now */
  6389. if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
  6390. myrpt->exten,1,NULL))
  6391. {
  6392. myrpt->callmode = 2;
  6393. if(!myrpt->patchquiet)
  6394. {
  6395. rpt_mutex_unlock(&myrpt->lock);
  6396. rpt_telemetry(myrpt,PROC,NULL);
  6397. rpt_mutex_lock(&myrpt->lock);
  6398. }
  6399. }
  6400. else /* othewise, reset timer */
  6401. {
  6402. myrpt->calldigittimer = 1;
  6403. }
  6404. }
  6405. /* if can continue, do so */
  6406. if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  6407. {
  6408. /* call has failed, inform user */
  6409. myrpt->callmode = 4;
  6410. }
  6411. }
  6412. if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
  6413. {
  6414. myrpt->mydtmf = c;
  6415. }
  6416. if ((!myrpt->inpadtest) && (c == myrpt->p.funcchar))
  6417. {
  6418. myrpt->rem_dtmfidx = 0;
  6419. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  6420. time(&myrpt->rem_dtmf_time);
  6421. rpt_mutex_unlock(&myrpt->lock);
  6422. return;
  6423. }
  6424. else if (((myrpt->inpadtest) || (c != myrpt->p.endchar)) && (myrpt->rem_dtmfidx >= 0))
  6425. {
  6426. time(&myrpt->rem_dtmf_time);
  6427. if (myrpt->rem_dtmfidx < MAXDTMF)
  6428. {
  6429. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
  6430. myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
  6431. rpt_mutex_unlock(&myrpt->lock);
  6432. strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
  6433. switch(mylink->phonemode)
  6434. {
  6435. case 1:
  6436. res = collect_function_digits(myrpt, cmd,
  6437. SOURCE_PHONE, mylink);
  6438. break;
  6439. case 2:
  6440. res = collect_function_digits(myrpt, cmd,
  6441. SOURCE_DPHONE,mylink);
  6442. break;
  6443. case 4:
  6444. res = collect_function_digits(myrpt, cmd,
  6445. SOURCE_ALT,mylink);
  6446. break;
  6447. default:
  6448. res = collect_function_digits(myrpt, cmd,
  6449. SOURCE_LNK, mylink);
  6450. break;
  6451. }
  6452. rpt_mutex_lock(&myrpt->lock);
  6453. switch(res){
  6454. case DC_INDETERMINATE:
  6455. break;
  6456. case DC_DOKEY:
  6457. mylink->lastrealrx = 1;
  6458. break;
  6459. case DC_REQ_FLUSH:
  6460. myrpt->rem_dtmfidx = 0;
  6461. myrpt->rem_dtmfbuf[0] = 0;
  6462. break;
  6463. case DC_COMPLETE:
  6464. case DC_COMPLETEQUIET:
  6465. myrpt->totalexecdcommands++;
  6466. myrpt->dailyexecdcommands++;
  6467. strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
  6468. myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
  6469. myrpt->rem_dtmfbuf[0] = 0;
  6470. myrpt->rem_dtmfidx = -1;
  6471. myrpt->rem_dtmf_time = 0;
  6472. break;
  6473. case DC_ERROR:
  6474. default:
  6475. myrpt->rem_dtmfbuf[0] = 0;
  6476. myrpt->rem_dtmfidx = -1;
  6477. myrpt->rem_dtmf_time = 0;
  6478. break;
  6479. }
  6480. }
  6481. }
  6482. rpt_mutex_unlock(&myrpt->lock);
  6483. return;
  6484. }
  6485. /* Doug Hall RBI-1 serial data definitions:
  6486. *
  6487. * Byte 0: Expansion external outputs
  6488. * Byte 1:
  6489. * Bits 0-3 are BAND as follows:
  6490. * Bits 4-5 are POWER bits as follows:
  6491. * 00 - Low Power
  6492. * 01 - Hi Power
  6493. * 02 - Med Power
  6494. * Bits 6-7 are always set
  6495. * Byte 2:
  6496. * Bits 0-3 MHZ in BCD format
  6497. * Bits 4-5 are offset as follows:
  6498. * 00 - minus
  6499. * 01 - plus
  6500. * 02 - simplex
  6501. * 03 - minus minus (whatever that is)
  6502. * Bit 6 is the 0/5 KHZ bit
  6503. * Bit 7 is always set
  6504. * Byte 3:
  6505. * Bits 0-3 are 10 KHZ in BCD format
  6506. * Bits 4-7 are 100 KHZ in BCD format
  6507. * Byte 4: PL Tone code and encode/decode enable bits
  6508. * Bits 0-5 are PL tone code (comspec binary codes)
  6509. * Bit 6 is encode enable/disable
  6510. * Bit 7 is decode enable/disable
  6511. */
  6512. /* take the frequency from the 10 mhz digits (and up) and convert it
  6513. to a band number */
  6514. static int rbi_mhztoband(char *str)
  6515. {
  6516. int i;
  6517. i = atoi(str) / 10; /* get the 10's of mhz */
  6518. switch(i)
  6519. {
  6520. case 2:
  6521. return 10;
  6522. case 5:
  6523. return 11;
  6524. case 14:
  6525. return 2;
  6526. case 22:
  6527. return 3;
  6528. case 44:
  6529. return 4;
  6530. case 124:
  6531. return 0;
  6532. case 125:
  6533. return 1;
  6534. case 126:
  6535. return 8;
  6536. case 127:
  6537. return 5;
  6538. case 128:
  6539. return 6;
  6540. case 129:
  6541. return 7;
  6542. default:
  6543. break;
  6544. }
  6545. return -1;
  6546. }
  6547. /* take a PL frequency and turn it into a code */
  6548. static int rbi_pltocode(char *str)
  6549. {
  6550. int i;
  6551. char *s;
  6552. s = strchr(str,'.');
  6553. i = 0;
  6554. if (s) i = atoi(s + 1);
  6555. i += atoi(str) * 10;
  6556. switch(i)
  6557. {
  6558. case 670:
  6559. return 0;
  6560. case 719:
  6561. return 1;
  6562. case 744:
  6563. return 2;
  6564. case 770:
  6565. return 3;
  6566. case 797:
  6567. return 4;
  6568. case 825:
  6569. return 5;
  6570. case 854:
  6571. return 6;
  6572. case 885:
  6573. return 7;
  6574. case 915:
  6575. return 8;
  6576. case 948:
  6577. return 9;
  6578. case 974:
  6579. return 10;
  6580. case 1000:
  6581. return 11;
  6582. case 1035:
  6583. return 12;
  6584. case 1072:
  6585. return 13;
  6586. case 1109:
  6587. return 14;
  6588. case 1148:
  6589. return 15;
  6590. case 1188:
  6591. return 16;
  6592. case 1230:
  6593. return 17;
  6594. case 1273:
  6595. return 18;
  6596. case 1318:
  6597. return 19;
  6598. case 1365:
  6599. return 20;
  6600. case 1413:
  6601. return 21;
  6602. case 1462:
  6603. return 22;
  6604. case 1514:
  6605. return 23;
  6606. case 1567:
  6607. return 24;
  6608. case 1622:
  6609. return 25;
  6610. case 1679:
  6611. return 26;
  6612. case 1738:
  6613. return 27;
  6614. case 1799:
  6615. return 28;
  6616. case 1862:
  6617. return 29;
  6618. case 1928:
  6619. return 30;
  6620. case 2035:
  6621. return 31;
  6622. case 2107:
  6623. return 32;
  6624. case 2181:
  6625. return 33;
  6626. case 2257:
  6627. return 34;
  6628. case 2336:
  6629. return 35;
  6630. case 2418:
  6631. return 36;
  6632. case 2503:
  6633. return 37;
  6634. }
  6635. return -1;
  6636. }
  6637. /*
  6638. * Shift out a formatted serial bit stream
  6639. */
  6640. static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
  6641. {
  6642. #ifdef __i386__
  6643. int i,j;
  6644. unsigned char od,d;
  6645. static volatile long long delayvar;
  6646. for(i = 0 ; i < 5 ; i++){
  6647. od = *data++;
  6648. for(j = 0 ; j < 8 ; j++){
  6649. d = od & 1;
  6650. outb(d,myrpt->p.iobase);
  6651. /* >= 15 us */
  6652. for(delayvar = 1; delayvar < 15000; delayvar++);
  6653. od >>= 1;
  6654. outb(d | 2,myrpt->p.iobase);
  6655. /* >= 30 us */
  6656. for(delayvar = 1; delayvar < 30000; delayvar++);
  6657. outb(d,myrpt->p.iobase);
  6658. /* >= 10 us */
  6659. for(delayvar = 1; delayvar < 10000; delayvar++);
  6660. }
  6661. }
  6662. /* >= 50 us */
  6663. for(delayvar = 1; delayvar < 50000; delayvar++);
  6664. #endif
  6665. }
  6666. static void rbi_out(struct rpt *myrpt,unsigned char *data)
  6667. {
  6668. struct dahdi_radio_param r;
  6669. memset(&r,0,sizeof(struct dahdi_radio_param));
  6670. r.radpar = DAHDI_RADPAR_REMMODE;
  6671. r.data = DAHDI_RADPAR_REM_RBI1;
  6672. /* if setparam ioctl fails, its probably not a pciradio card */
  6673. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
  6674. {
  6675. rbi_out_parallel(myrpt,data);
  6676. return;
  6677. }
  6678. r.radpar = DAHDI_RADPAR_REMCOMMAND;
  6679. memcpy(&r.data,data,5);
  6680. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&r) == -1)
  6681. {
  6682. ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->dahdirxchannel->name);
  6683. return;
  6684. }
  6685. }
  6686. static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes,
  6687. unsigned char *rxbuf, int rxmaxbytes, int asciiflag)
  6688. {
  6689. int i,j,idx,oldmode,olddata;
  6690. struct dahdi_radio_param prm;
  6691. char c;
  6692. if(debug) {
  6693. ast_log(LOG_NOTICE, "ioport=%s iofd=0x%x\n",myrpt->p.ioport,myrpt->iofd);
  6694. printf("String output was:\n");
  6695. for(i = 0; i < txbytes; i++)
  6696. printf("%02X ", (unsigned char ) txbuf[i]);
  6697. printf("\n");
  6698. }
  6699. if (myrpt->iofd >= 0) /* if to do out a serial port */
  6700. {
  6701. if (write(myrpt->iofd,txbuf,txbytes) != txbytes)
  6702. {
  6703. return -1;
  6704. }
  6705. if ((!rxmaxbytes) || (rxbuf == NULL))
  6706. {
  6707. return(0);
  6708. }
  6709. memset(rxbuf,0,rxmaxbytes);
  6710. for(i = 0; i < rxmaxbytes; i++)
  6711. {
  6712. j = read(myrpt->iofd,&c,1);
  6713. if (j < 1)
  6714. {
  6715. return(i);
  6716. }
  6717. rxbuf[i] = c;
  6718. if (asciiflag & 1)
  6719. {
  6720. rxbuf[i + 1] = 0;
  6721. if (c == '\r') break;
  6722. }
  6723. }
  6724. if(debug) {
  6725. printf("String returned was:\n");
  6726. for(j = 0; j < i; j++)
  6727. printf("%02X ", (unsigned char ) rxbuf[j]);
  6728. printf("\n");
  6729. }
  6730. return(i);
  6731. }
  6732. /* if not a DAHDI channel, cant use pciradio stuff */
  6733. if (myrpt->rxchannel != myrpt->dahdirxchannel) return -1;
  6734. prm.radpar = DAHDI_RADPAR_UIOMODE;
  6735. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
  6736. oldmode = prm.data;
  6737. prm.radpar = DAHDI_RADPAR_UIODATA;
  6738. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_GETPARAM,&prm) == -1) return -1;
  6739. olddata = prm.data;
  6740. prm.radpar = DAHDI_RADPAR_REMMODE;
  6741. if (asciiflag & 1) prm.data = DAHDI_RADPAR_REM_SERIAL_ASCII;
  6742. else prm.data = DAHDI_RADPAR_REM_SERIAL;
  6743. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
  6744. if (asciiflag & 2)
  6745. {
  6746. i = DAHDI_ONHOOK;
  6747. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
  6748. usleep(100000);
  6749. }
  6750. prm.radpar = DAHDI_RADPAR_REMCOMMAND;
  6751. prm.data = rxmaxbytes;
  6752. memcpy(prm.buf,txbuf,txbytes);
  6753. prm.index = txbytes;
  6754. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
  6755. if (rxbuf)
  6756. {
  6757. *rxbuf = 0;
  6758. memcpy(rxbuf,prm.buf,prm.index);
  6759. }
  6760. idx = prm.index;
  6761. prm.radpar = DAHDI_RADPAR_REMMODE;
  6762. prm.data = DAHDI_RADPAR_REM_NONE;
  6763. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
  6764. if (asciiflag & 2)
  6765. {
  6766. i = DAHDI_OFFHOOK;
  6767. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_HOOK,&i) == -1) return -1;
  6768. }
  6769. prm.radpar = DAHDI_RADPAR_UIOMODE;
  6770. prm.data = oldmode;
  6771. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
  6772. prm.radpar = DAHDI_RADPAR_UIODATA;
  6773. prm.data = olddata;
  6774. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_RADIO_SETPARAM,&prm) == -1) return -1;
  6775. return(idx);
  6776. }
  6777. static int civ_cmd(struct rpt *myrpt,unsigned char *cmd, int cmdlen)
  6778. {
  6779. unsigned char rxbuf[100];
  6780. int i,rv ;
  6781. rv = serial_remote_io(myrpt,cmd,cmdlen,rxbuf,cmdlen + 6,0);
  6782. if (rv == -1) return(-1);
  6783. if (rv != (cmdlen + 6)) return(1);
  6784. for(i = 0; i < 6; i++)
  6785. if (rxbuf[i] != cmd[i]) return(1);
  6786. if (rxbuf[cmdlen] != 0xfe) return(1);
  6787. if (rxbuf[cmdlen + 1] != 0xfe) return(1);
  6788. if (rxbuf[cmdlen + 4] != 0xfb) return(1);
  6789. if (rxbuf[cmdlen + 5] != 0xfd) return(1);
  6790. return(0);
  6791. }
  6792. static int sendkenwood(struct rpt *myrpt,char *txstr, char *rxstr)
  6793. {
  6794. int i;
  6795. ast_log(LOG_NOTICE,"Sent to kenwood: %s\n",txstr);
  6796. if (debug) printf("Send to kenwood: %s\n",txstr);
  6797. i = serial_remote_io(myrpt, (unsigned char *)txstr, strlen(txstr),
  6798. (unsigned char *)rxstr,RAD_SERIAL_BUFLEN - 1,3);
  6799. if (i < 0) return -1;
  6800. if ((i > 0) && (rxstr[i - 1] == '\r'))
  6801. rxstr[i-- - 1] = 0;
  6802. if (debug) printf("Got from kenwood: %s\n",rxstr);
  6803. ast_log(LOG_NOTICE,"Got from kenwood: %s\n",rxstr);
  6804. return(i);
  6805. }
  6806. /* take a PL frequency and turn it into a code */
  6807. static int kenwood_pltocode(char *str)
  6808. {
  6809. int i;
  6810. char *s;
  6811. s = strchr(str,'.');
  6812. i = 0;
  6813. if (s) i = atoi(s + 1);
  6814. i += atoi(str) * 10;
  6815. switch(i)
  6816. {
  6817. case 670:
  6818. return 1;
  6819. case 719:
  6820. return 3;
  6821. case 744:
  6822. return 4;
  6823. case 770:
  6824. return 5;
  6825. case 797:
  6826. return 6;
  6827. case 825:
  6828. return 7;
  6829. case 854:
  6830. return 8;
  6831. case 885:
  6832. return 9;
  6833. case 915:
  6834. return 10;
  6835. case 948:
  6836. return 11;
  6837. case 974:
  6838. return 12;
  6839. case 1000:
  6840. return 13;
  6841. case 1035:
  6842. return 14;
  6843. case 1072:
  6844. return 15;
  6845. case 1109:
  6846. return 16;
  6847. case 1148:
  6848. return 17;
  6849. case 1188:
  6850. return 18;
  6851. case 1230:
  6852. return 19;
  6853. case 1273:
  6854. return 20;
  6855. case 1318:
  6856. return 21;
  6857. case 1365:
  6858. return 22;
  6859. case 1413:
  6860. return 23;
  6861. case 1462:
  6862. return 24;
  6863. case 1514:
  6864. return 25;
  6865. case 1567:
  6866. return 26;
  6867. case 1622:
  6868. return 27;
  6869. case 1679:
  6870. return 28;
  6871. case 1738:
  6872. return 29;
  6873. case 1799:
  6874. return 30;
  6875. case 1862:
  6876. return 31;
  6877. case 1928:
  6878. return 32;
  6879. case 2035:
  6880. return 33;
  6881. case 2107:
  6882. return 34;
  6883. case 2181:
  6884. return 35;
  6885. case 2257:
  6886. return 36;
  6887. case 2336:
  6888. return 37;
  6889. case 2418:
  6890. return 38;
  6891. case 2503:
  6892. return 39;
  6893. }
  6894. return -1;
  6895. }
  6896. static int sendrxkenwood(struct rpt *myrpt, char *txstr, char *rxstr,
  6897. char *cmpstr)
  6898. {
  6899. int i,j;
  6900. for(i = 0;i < KENWOOD_RETRIES;i++)
  6901. {
  6902. j = sendkenwood(myrpt,txstr,rxstr);
  6903. if (j < 0) return(j);
  6904. if (j == 0) continue;
  6905. if (!strncmp(rxstr,cmpstr,strlen(cmpstr))) return(0);
  6906. }
  6907. return(-1);
  6908. }
  6909. static int setkenwood(struct rpt *myrpt)
  6910. {
  6911. char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
  6912. char mhz[MAXREMSTR],offset[20],band,decimals[MAXREMSTR],band1,band2;
  6913. int myrxpl;
  6914. int offsets[] = {0,2,1};
  6915. int powers[] = {2,1,0};
  6916. if (sendrxkenwood(myrpt,"VMC 0,0\r",rxstr,"VMC") < 0) return -1;
  6917. split_freq(mhz, decimals, myrpt->freq);
  6918. if (atoi(mhz) > 400)
  6919. {
  6920. band = '6';
  6921. band1 = '1';
  6922. band2 = '5';
  6923. strcpy(offset,"005000000");
  6924. }
  6925. else
  6926. {
  6927. band = '2';
  6928. band1 = '0';
  6929. band2 = '2';
  6930. strcpy(offset,"000600000");
  6931. }
  6932. strcpy(freq,"000000");
  6933. strncpy(freq,decimals,strlen(decimals));
  6934. myrxpl = myrpt->rxplon;
  6935. if (IS_XPMR(myrpt)) myrxpl = 0;
  6936. sprintf(txstr,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
  6937. band,atoi(mhz),freq,offsets[(int)myrpt->offset],
  6938. (myrpt->txplon != 0),myrxpl,
  6939. kenwood_pltocode(myrpt->txpl),kenwood_pltocode(myrpt->rxpl),
  6940. offset);
  6941. if (sendrxkenwood(myrpt,txstr,rxstr,"VW") < 0) return -1;
  6942. sprintf(txstr,"RBN %c\r",band2);
  6943. if (sendrxkenwood(myrpt,txstr,rxstr,"RBN") < 0) return -1;
  6944. sprintf(txstr,"PC %c,%d\r",band1,powers[(int)myrpt->powerlevel]);
  6945. if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
  6946. return 0;
  6947. }
  6948. static int set_tm271(struct rpt *myrpt)
  6949. {
  6950. char rxstr[RAD_SERIAL_BUFLEN],txstr[RAD_SERIAL_BUFLEN],freq[20];
  6951. char mhz[MAXREMSTR],decimals[MAXREMSTR];
  6952. int offsets[] = {0,2,1};
  6953. int powers[] = {2,1,0};
  6954. split_freq(mhz, decimals, myrpt->freq);
  6955. strcpy(freq,"000000");
  6956. strncpy(freq,decimals,strlen(decimals));
  6957. sprintf(txstr,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
  6958. atoi(mhz),freq,offsets[(int)myrpt->offset],
  6959. (myrpt->txplon != 0),kenwood_pltocode(myrpt->txpl),
  6960. kenwood_pltocode(myrpt->rxpl));
  6961. if (sendrxkenwood(myrpt,txstr,rxstr,"VF") < 0) return -1;
  6962. if (sendrxkenwood(myrpt,"VM 0\r",rxstr,"VM") < 0) return -1;
  6963. sprintf(txstr,"PC %d\r",powers[(int)myrpt->powerlevel]);
  6964. if (sendrxkenwood(myrpt,txstr,rxstr,"PC") < 0) return -1;
  6965. return 0;
  6966. }
  6967. static int setrbi(struct rpt *myrpt)
  6968. {
  6969. char tmp[MAXREMSTR] = "",*s;
  6970. unsigned char rbicmd[5];
  6971. int band,txoffset = 0,txpower = 0,rxpl;
  6972. /* must be a remote system */
  6973. if (!myrpt->remoterig) return(0);
  6974. if (!myrpt->remoterig[0]) return(0);
  6975. /* must have rbi hardware */
  6976. if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
  6977. if (setrbi_check(myrpt) == -1) return(-1);
  6978. strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
  6979. s = strchr(tmp,'.');
  6980. /* if no decimal, is invalid */
  6981. if (s == NULL){
  6982. if(debug)
  6983. printf("@@@@ Frequency needs a decimal\n");
  6984. return -1;
  6985. }
  6986. *s++ = 0;
  6987. if (strlen(tmp) < 2){
  6988. if(debug)
  6989. printf("@@@@ Bad MHz digits: %s\n", tmp);
  6990. return -1;
  6991. }
  6992. if (strlen(s) < 3){
  6993. if(debug)
  6994. printf("@@@@ Bad KHz digits: %s\n", s);
  6995. return -1;
  6996. }
  6997. if ((s[2] != '0') && (s[2] != '5')){
  6998. if(debug)
  6999. printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
  7000. return -1;
  7001. }
  7002. band = rbi_mhztoband(tmp);
  7003. if (band == -1){
  7004. if(debug)
  7005. printf("@@@@ Bad Band: %s\n", tmp);
  7006. return -1;
  7007. }
  7008. rxpl = rbi_pltocode(myrpt->rxpl);
  7009. if (rxpl == -1){
  7010. if(debug)
  7011. printf("@@@@ Bad TX PL: %s\n", myrpt->rxpl);
  7012. return -1;
  7013. }
  7014. switch(myrpt->offset)
  7015. {
  7016. case REM_MINUS:
  7017. txoffset = 0;
  7018. break;
  7019. case REM_PLUS:
  7020. txoffset = 0x10;
  7021. break;
  7022. case REM_SIMPLEX:
  7023. txoffset = 0x20;
  7024. break;
  7025. }
  7026. switch(myrpt->powerlevel)
  7027. {
  7028. case REM_LOWPWR:
  7029. txpower = 0;
  7030. break;
  7031. case REM_MEDPWR:
  7032. txpower = 0x20;
  7033. break;
  7034. case REM_HIPWR:
  7035. txpower = 0x10;
  7036. break;
  7037. }
  7038. rbicmd[0] = 0;
  7039. rbicmd[1] = band | txpower | 0xc0;
  7040. rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
  7041. if (s[2] == '5') rbicmd[2] |= 0x40;
  7042. rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
  7043. rbicmd[4] = rxpl;
  7044. if (myrpt->txplon) rbicmd[4] |= 0x40;
  7045. if (myrpt->rxplon) rbicmd[4] |= 0x80;
  7046. rbi_out(myrpt,rbicmd);
  7047. return 0;
  7048. }
  7049. static int setrtx(struct rpt *myrpt)
  7050. {
  7051. char tmp[MAXREMSTR] = "",*s,rigstr[200],pwr,res = 0;
  7052. int band,rxpl,txpl;
  7053. float ofac;
  7054. double txfreq;
  7055. /* must be a remote system */
  7056. if (!myrpt->remoterig) return(0);
  7057. if (!myrpt->remoterig[0]) return(0);
  7058. /* must have rtx hardware */
  7059. if (!ISRIG_RTX(myrpt->remoterig)) return(0);
  7060. /* must be a usbradio interface type */
  7061. if (!IS_XPMR(myrpt)) return(0);
  7062. strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
  7063. s = strchr(tmp,'.');
  7064. /* if no decimal, is invalid */
  7065. if(debug)printf("setrtx() %s %s\n",myrpt->name,myrpt->remoterig);
  7066. if (s == NULL){
  7067. if(debug)
  7068. printf("@@@@ Frequency needs a decimal\n");
  7069. return -1;
  7070. }
  7071. *s++ = 0;
  7072. if (strlen(tmp) < 2){
  7073. if(debug)
  7074. printf("@@@@ Bad MHz digits: %s\n", tmp);
  7075. return -1;
  7076. }
  7077. if (strlen(s) < 3){
  7078. if(debug)
  7079. printf("@@@@ Bad KHz digits: %s\n", s);
  7080. return -1;
  7081. }
  7082. if ((s[2] != '0') && (s[2] != '5')){
  7083. if(debug)
  7084. printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
  7085. return -1;
  7086. }
  7087. band = rbi_mhztoband(tmp);
  7088. if (band == -1){
  7089. if(debug)
  7090. printf("@@@@ Bad Band: %s\n", tmp);
  7091. return -1;
  7092. }
  7093. rxpl = rbi_pltocode(myrpt->rxpl);
  7094. if (rxpl == -1){
  7095. if(debug)
  7096. printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
  7097. return -1;
  7098. }
  7099. txpl = rbi_pltocode(myrpt->txpl);
  7100. if (txpl == -1){
  7101. if(debug)
  7102. printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
  7103. return -1;
  7104. }
  7105. res = setrtx_check(myrpt);
  7106. if (res < 0) return res;
  7107. ofac = 0.0;
  7108. if (myrpt->offset == REM_MINUS) ofac = -1.0;
  7109. if (myrpt->offset == REM_PLUS) ofac = 1.0;
  7110. if (!strcmp(myrpt->remoterig,remote_rig_rtx450))
  7111. txfreq = atof(myrpt->freq) + (ofac * 5.0);
  7112. else
  7113. txfreq = atof(myrpt->freq) + (ofac * 0.6);
  7114. pwr = 'L';
  7115. if (myrpt->powerlevel == REM_HIPWR) pwr = 'H';
  7116. if (!res)
  7117. {
  7118. sprintf(rigstr,"SETFREQ %s %f %s %s %c",myrpt->freq,txfreq,
  7119. (myrpt->rxplon) ? myrpt->rxpl : "0.0",
  7120. (myrpt->txplon) ? myrpt->txpl : "0.0",pwr);
  7121. send_usb_txt(myrpt,rigstr);
  7122. rpt_telemetry(myrpt,COMPLETE,NULL);
  7123. res = 0;
  7124. }
  7125. return 0;
  7126. }
  7127. #if 0
  7128. /*
  7129. sets current signaling code for xpmr routines
  7130. under development for new radios.
  7131. */
  7132. static int setxpmr(struct rpt *myrpt)
  7133. {
  7134. char rigstr[200];
  7135. int rxpl,txpl;
  7136. /* must be a remote system */
  7137. if (!myrpt->remoterig) return(0);
  7138. if (!myrpt->remoterig[0]) return(0);
  7139. /* must not have rtx hardware */
  7140. if (ISRIG_RTX(myrpt->remoterig)) return(0);
  7141. /* must be a usbradio interface type */
  7142. if (!IS_XPMR(myrpt)) return(0);
  7143. if(debug)printf("setxpmr() %s %s\n",myrpt->name,myrpt->remoterig );
  7144. rxpl = rbi_pltocode(myrpt->rxpl);
  7145. if (rxpl == -1){
  7146. if(debug)
  7147. printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
  7148. return -1;
  7149. }
  7150. txpl = rbi_pltocode(myrpt->txpl);
  7151. if (txpl == -1){
  7152. if(debug)
  7153. printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
  7154. return -1;
  7155. }
  7156. sprintf(rigstr,"SETFREQ 0.0 0.0 %s %s L",
  7157. (myrpt->rxplon) ? myrpt->rxpl : "0.0",
  7158. (myrpt->txplon) ? myrpt->txpl : "0.0");
  7159. send_usb_txt(myrpt,rigstr);
  7160. return 0;
  7161. }
  7162. #endif
  7163. static int setrbi_check(struct rpt *myrpt)
  7164. {
  7165. char tmp[MAXREMSTR] = "",*s;
  7166. int band,txpl;
  7167. /* must be a remote system */
  7168. if (!myrpt->remote) return(0);
  7169. /* must have rbi hardware */
  7170. if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
  7171. strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
  7172. s = strchr(tmp,'.');
  7173. /* if no decimal, is invalid */
  7174. if (s == NULL){
  7175. if(debug)
  7176. printf("@@@@ Frequency needs a decimal\n");
  7177. return -1;
  7178. }
  7179. *s++ = 0;
  7180. if (strlen(tmp) < 2){
  7181. if(debug)
  7182. printf("@@@@ Bad MHz digits: %s\n", tmp);
  7183. return -1;
  7184. }
  7185. if (strlen(s) < 3){
  7186. if(debug)
  7187. printf("@@@@ Bad KHz digits: %s\n", s);
  7188. return -1;
  7189. }
  7190. if ((s[2] != '0') && (s[2] != '5')){
  7191. if(debug)
  7192. printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
  7193. return -1;
  7194. }
  7195. band = rbi_mhztoband(tmp);
  7196. if (band == -1){
  7197. if(debug)
  7198. printf("@@@@ Bad Band: %s\n", tmp);
  7199. return -1;
  7200. }
  7201. txpl = rbi_pltocode(myrpt->txpl);
  7202. if (txpl == -1){
  7203. if(debug)
  7204. printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
  7205. return -1;
  7206. }
  7207. return 0;
  7208. }
  7209. static int setrtx_check(struct rpt *myrpt)
  7210. {
  7211. char tmp[MAXREMSTR] = "",*s;
  7212. int band,txpl,rxpl;
  7213. /* must be a remote system */
  7214. if (!myrpt->remote) return(0);
  7215. /* must have rbi hardware */
  7216. if (strncmp(myrpt->remoterig,remote_rig_rbi,3)) return(0);
  7217. strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
  7218. s = strchr(tmp,'.');
  7219. /* if no decimal, is invalid */
  7220. if (s == NULL){
  7221. if(debug)
  7222. printf("@@@@ Frequency needs a decimal\n");
  7223. return -1;
  7224. }
  7225. *s++ = 0;
  7226. if (strlen(tmp) < 2){
  7227. if(debug)
  7228. printf("@@@@ Bad MHz digits: %s\n", tmp);
  7229. return -1;
  7230. }
  7231. if (strlen(s) < 3){
  7232. if(debug)
  7233. printf("@@@@ Bad KHz digits: %s\n", s);
  7234. return -1;
  7235. }
  7236. if ((s[2] != '0') && (s[2] != '5')){
  7237. if(debug)
  7238. printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
  7239. return -1;
  7240. }
  7241. band = rbi_mhztoband(tmp);
  7242. if (band == -1){
  7243. if(debug)
  7244. printf("@@@@ Bad Band: %s\n", tmp);
  7245. return -1;
  7246. }
  7247. txpl = rbi_pltocode(myrpt->txpl);
  7248. if (txpl == -1){
  7249. if(debug)
  7250. printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
  7251. return -1;
  7252. }
  7253. rxpl = rbi_pltocode(myrpt->rxpl);
  7254. if (rxpl == -1){
  7255. if(debug)
  7256. printf("@@@@ Bad RX PL: %s\n", myrpt->rxpl);
  7257. return -1;
  7258. }
  7259. return 0;
  7260. }
  7261. static int check_freq_kenwood(int m, int d, int *defmode)
  7262. {
  7263. int dflmd = REM_MODE_FM;
  7264. if (m == 144){ /* 2 meters */
  7265. if(d < 10100)
  7266. return -1;
  7267. }
  7268. else if((m >= 145) && (m < 148)){
  7269. ;
  7270. }
  7271. else if((m >= 430) && (m < 450)){ /* 70 centimeters */
  7272. ;
  7273. }
  7274. else
  7275. return -1;
  7276. if(defmode)
  7277. *defmode = dflmd;
  7278. return 0;
  7279. }
  7280. static int check_freq_tm271(int m, int d, int *defmode)
  7281. {
  7282. int dflmd = REM_MODE_FM;
  7283. if (m == 144){ /* 2 meters */
  7284. if(d < 10100)
  7285. return -1;
  7286. }
  7287. else if((m >= 145) && (m < 148)){
  7288. ;
  7289. }
  7290. return -1;
  7291. if(defmode)
  7292. *defmode = dflmd;
  7293. return 0;
  7294. }
  7295. /* Check for valid rbi frequency */
  7296. /* Hard coded limits now, configurable later, maybe? */
  7297. static int check_freq_rbi(int m, int d, int *defmode)
  7298. {
  7299. int dflmd = REM_MODE_FM;
  7300. if(m == 50){ /* 6 meters */
  7301. if(d < 10100)
  7302. return -1;
  7303. }
  7304. else if((m >= 51) && ( m < 54)){
  7305. ;
  7306. }
  7307. else if(m == 144){ /* 2 meters */
  7308. if(d < 10100)
  7309. return -1;
  7310. }
  7311. else if((m >= 145) && (m < 148)){
  7312. ;
  7313. }
  7314. else if((m >= 222) && (m < 225)){ /* 1.25 meters */
  7315. ;
  7316. }
  7317. else if((m >= 430) && (m < 450)){ /* 70 centimeters */
  7318. ;
  7319. }
  7320. else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */
  7321. ;
  7322. }
  7323. else
  7324. return -1;
  7325. if(defmode)
  7326. *defmode = dflmd;
  7327. return 0;
  7328. }
  7329. /* Check for valid rtx frequency */
  7330. /* Hard coded limits now, configurable later, maybe? */
  7331. static int check_freq_rtx(int m, int d, int *defmode, struct rpt *myrpt)
  7332. {
  7333. int dflmd = REM_MODE_FM;
  7334. if (!strcmp(myrpt->remoterig,remote_rig_rtx150))
  7335. {
  7336. if(m == 144){ /* 2 meters */
  7337. if(d < 10100)
  7338. return -1;
  7339. }
  7340. else if((m >= 145) && (m < 148)){
  7341. ;
  7342. }
  7343. else
  7344. return -1;
  7345. }
  7346. else
  7347. {
  7348. if((m >= 430) && (m < 450)){ /* 70 centimeters */
  7349. ;
  7350. }
  7351. else
  7352. return -1;
  7353. }
  7354. if(defmode)
  7355. *defmode = dflmd;
  7356. return 0;
  7357. }
  7358. /*
  7359. * Convert decimals of frequency to int
  7360. */
  7361. static int decimals2int(char *fraction)
  7362. {
  7363. int i;
  7364. char len = strlen(fraction);
  7365. int multiplier = 100000;
  7366. int res = 0;
  7367. if(!len)
  7368. return 0;
  7369. for( i = 0 ; i < len ; i++, multiplier /= 10)
  7370. res += (fraction[i] - '0') * multiplier;
  7371. return res;
  7372. }
  7373. /*
  7374. * Split frequency into mhz and decimals
  7375. */
  7376. static int split_freq(char *mhz, char *decimals, char *freq)
  7377. {
  7378. char freq_copy[MAXREMSTR];
  7379. char *decp;
  7380. decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
  7381. if(decp){
  7382. *decp++ = 0;
  7383. strncpy(mhz, freq_copy, MAXREMSTR);
  7384. strcpy(decimals, "00000");
  7385. strncpy(decimals, decp, strlen(decp));
  7386. decimals[5] = 0;
  7387. return 0;
  7388. }
  7389. else
  7390. return -1;
  7391. }
  7392. /*
  7393. * Split ctcss frequency into hertz and decimal
  7394. */
  7395. static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
  7396. {
  7397. char freq_copy[MAXREMSTR];
  7398. char *decp;
  7399. decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
  7400. if(decp){
  7401. *decp++ = 0;
  7402. strncpy(hertz, freq_copy, MAXREMSTR);
  7403. strncpy(decimal, decp, strlen(decp));
  7404. decimal[strlen(decp)] = '\0';
  7405. return 0;
  7406. }
  7407. else
  7408. return -1;
  7409. }
  7410. /*
  7411. * FT-897 I/O handlers
  7412. */
  7413. /* Check to see that the frequency is valid */
  7414. /* Hard coded limits now, configurable later, maybe? */
  7415. static int check_freq_ft897(int m, int d, int *defmode)
  7416. {
  7417. int dflmd = REM_MODE_FM;
  7418. if(m == 1){ /* 160 meters */
  7419. dflmd = REM_MODE_LSB;
  7420. if(d < 80000)
  7421. return -1;
  7422. }
  7423. else if(m == 3){ /* 80 meters */
  7424. dflmd = REM_MODE_LSB;
  7425. if(d < 50000)
  7426. return -1;
  7427. }
  7428. else if(m == 7){ /* 40 meters */
  7429. dflmd = REM_MODE_LSB;
  7430. if(d > 30000)
  7431. return -1;
  7432. }
  7433. else if(m == 14){ /* 20 meters */
  7434. dflmd = REM_MODE_USB;
  7435. if(d > 35000)
  7436. return -1;
  7437. }
  7438. else if(m == 18){ /* 17 meters */
  7439. dflmd = REM_MODE_USB;
  7440. if((d < 6800) || (d > 16800))
  7441. return -1;
  7442. }
  7443. else if(m == 21){ /* 15 meters */
  7444. dflmd = REM_MODE_USB;
  7445. if((d < 20000) || (d > 45000))
  7446. return -1;
  7447. }
  7448. else if(m == 24){ /* 12 meters */
  7449. dflmd = REM_MODE_USB;
  7450. if((d < 89000) || (d > 99000))
  7451. return -1;
  7452. }
  7453. else if(m == 28){ /* 10 meters */
  7454. dflmd = REM_MODE_USB;
  7455. }
  7456. else if(m == 29){
  7457. if(d >= 51000)
  7458. dflmd = REM_MODE_FM;
  7459. else
  7460. dflmd = REM_MODE_USB;
  7461. if(d > 70000)
  7462. return -1;
  7463. }
  7464. else if(m == 50){ /* 6 meters */
  7465. if(d >= 30000)
  7466. dflmd = REM_MODE_FM;
  7467. else
  7468. dflmd = REM_MODE_USB;
  7469. }
  7470. else if((m >= 51) && ( m < 54)){
  7471. dflmd = REM_MODE_FM;
  7472. }
  7473. else if(m == 144){ /* 2 meters */
  7474. if(d >= 30000)
  7475. dflmd = REM_MODE_FM;
  7476. else
  7477. dflmd = REM_MODE_USB;
  7478. }
  7479. else if((m >= 145) && (m < 148)){
  7480. dflmd = REM_MODE_FM;
  7481. }
  7482. else if((m >= 430) && (m < 450)){ /* 70 centimeters */
  7483. if(m < 438)
  7484. dflmd = REM_MODE_USB;
  7485. else
  7486. dflmd = REM_MODE_FM;
  7487. ;
  7488. }
  7489. else
  7490. return -1;
  7491. if(defmode)
  7492. *defmode = dflmd;
  7493. return 0;
  7494. }
  7495. /*
  7496. * Set a new frequency for the FT897
  7497. */
  7498. static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
  7499. {
  7500. unsigned char cmdstr[5];
  7501. int m,d;
  7502. char mhz[MAXREMSTR];
  7503. char decimals[MAXREMSTR];
  7504. if(debug)
  7505. printf("New frequency: %s\n",newfreq);
  7506. if(split_freq(mhz, decimals, newfreq))
  7507. return -1;
  7508. m = atoi(mhz);
  7509. d = atoi(decimals);
  7510. /* The FT-897 likes packed BCD frequencies */
  7511. cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10); /* 100MHz 10Mhz */
  7512. cmdstr[1] = ((m % 10) << 4) + (d / 10000); /* 1MHz 100KHz */
  7513. cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100); /* 10KHz 1KHz */
  7514. cmdstr[3] = (((d % 100)/10) << 4) + (d % 10); /* 100Hz 10Hz */
  7515. cmdstr[4] = 0x01; /* command */
  7516. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7517. }
  7518. /* ft-897 simple commands */
  7519. static int simple_command_ft897(struct rpt *myrpt, char command)
  7520. {
  7521. unsigned char cmdstr[5];
  7522. memset(cmdstr, 0, 5);
  7523. cmdstr[4] = command;
  7524. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7525. }
  7526. /* ft-897 offset */
  7527. static int set_offset_ft897(struct rpt *myrpt, char offset)
  7528. {
  7529. unsigned char cmdstr[5];
  7530. memset(cmdstr, 0, 5);
  7531. switch(offset){
  7532. case REM_SIMPLEX:
  7533. cmdstr[0] = 0x89;
  7534. break;
  7535. case REM_MINUS:
  7536. cmdstr[0] = 0x09;
  7537. break;
  7538. case REM_PLUS:
  7539. cmdstr[0] = 0x49;
  7540. break;
  7541. default:
  7542. return -1;
  7543. }
  7544. cmdstr[4] = 0x09;
  7545. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7546. }
  7547. /* ft-897 mode */
  7548. static int set_mode_ft897(struct rpt *myrpt, char newmode)
  7549. {
  7550. unsigned char cmdstr[5];
  7551. memset(cmdstr, 0, 5);
  7552. switch(newmode){
  7553. case REM_MODE_FM:
  7554. cmdstr[0] = 0x08;
  7555. break;
  7556. case REM_MODE_USB:
  7557. cmdstr[0] = 0x01;
  7558. break;
  7559. case REM_MODE_LSB:
  7560. cmdstr[0] = 0x00;
  7561. break;
  7562. case REM_MODE_AM:
  7563. cmdstr[0] = 0x04;
  7564. break;
  7565. default:
  7566. return -1;
  7567. }
  7568. cmdstr[4] = 0x07;
  7569. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7570. }
  7571. /* Set tone encode and decode modes */
  7572. static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
  7573. {
  7574. unsigned char cmdstr[5];
  7575. memset(cmdstr, 0, 5);
  7576. if(rxplon && txplon)
  7577. cmdstr[0] = 0x2A; /* Encode and Decode */
  7578. else if (!rxplon && txplon)
  7579. cmdstr[0] = 0x4A; /* Encode only */
  7580. else if (rxplon && !txplon)
  7581. cmdstr[0] = 0x3A; /* Encode only */
  7582. else
  7583. cmdstr[0] = 0x8A; /* OFF */
  7584. cmdstr[4] = 0x0A;
  7585. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7586. }
  7587. /* Set transmit and receive ctcss tone frequencies */
  7588. static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
  7589. {
  7590. unsigned char cmdstr[5];
  7591. char hertz[MAXREMSTR],decimal[MAXREMSTR];
  7592. int h,d;
  7593. memset(cmdstr, 0, 5);
  7594. if(split_ctcss_freq(hertz, decimal, txtone))
  7595. return -1;
  7596. h = atoi(hertz);
  7597. d = atoi(decimal);
  7598. cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
  7599. cmdstr[1] = ((h % 10) << 4) + (d % 10);
  7600. if(rxtone){
  7601. if(split_ctcss_freq(hertz, decimal, rxtone))
  7602. return -1;
  7603. h = atoi(hertz);
  7604. d = atoi(decimal);
  7605. cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
  7606. cmdstr[3] = ((h % 10) << 4) + (d % 10);
  7607. }
  7608. cmdstr[4] = 0x0B;
  7609. return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
  7610. }
  7611. static int set_ft897(struct rpt *myrpt)
  7612. {
  7613. int res;
  7614. if(debug)
  7615. printf("@@@@ lock on\n");
  7616. res = simple_command_ft897(myrpt, 0x00); /* LOCK on */
  7617. if(debug)
  7618. printf("@@@@ ptt off\n");
  7619. if(!res)
  7620. res = simple_command_ft897(myrpt, 0x88); /* PTT off */
  7621. if(debug)
  7622. printf("Modulation mode\n");
  7623. if(!res)
  7624. res = set_mode_ft897(myrpt, myrpt->remmode); /* Modulation mode */
  7625. if(debug)
  7626. printf("Split off\n");
  7627. if(!res)
  7628. simple_command_ft897(myrpt, 0x82); /* Split off */
  7629. if(debug)
  7630. printf("Frequency\n");
  7631. if(!res)
  7632. res = set_freq_ft897(myrpt, myrpt->freq); /* Frequency */
  7633. if((myrpt->remmode == REM_MODE_FM)){
  7634. if(debug)
  7635. printf("Offset\n");
  7636. if(!res)
  7637. res = set_offset_ft897(myrpt, myrpt->offset); /* Offset if FM */
  7638. if((!res)&&(myrpt->rxplon || myrpt->txplon)){
  7639. if(debug)
  7640. printf("CTCSS tone freqs.\n");
  7641. res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
  7642. }
  7643. if(!res){
  7644. if(debug)
  7645. printf("CTCSS mode\n");
  7646. res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
  7647. }
  7648. }
  7649. if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
  7650. if(debug)
  7651. printf("Clarifier off\n");
  7652. simple_command_ft897(myrpt, 0x85); /* Clarifier off if LSB or USB */
  7653. }
  7654. return res;
  7655. }
  7656. static int closerem_ft897(struct rpt *myrpt)
  7657. {
  7658. simple_command_ft897(myrpt, 0x88); /* PTT off */
  7659. return 0;
  7660. }
  7661. /*
  7662. * Bump frequency up or down by a small amount
  7663. * Return 0 if the new frequnecy is valid, or -1 if invalid
  7664. * Interval is in Hz, resolution is 10Hz
  7665. */
  7666. static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
  7667. {
  7668. int m,d;
  7669. char mhz[MAXREMSTR], decimals[MAXREMSTR];
  7670. if(debug)
  7671. printf("Before bump: %s\n", myrpt->freq);
  7672. if(split_freq(mhz, decimals, myrpt->freq))
  7673. return -1;
  7674. m = atoi(mhz);
  7675. d = atoi(decimals);
  7676. d += (interval / 10); /* 10Hz resolution */
  7677. if(d < 0){
  7678. m--;
  7679. d += 100000;
  7680. }
  7681. else if(d >= 100000){
  7682. m++;
  7683. d -= 100000;
  7684. }
  7685. if(check_freq_ft897(m, d, NULL)){
  7686. if(debug)
  7687. printf("Bump freq invalid\n");
  7688. return -1;
  7689. }
  7690. snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
  7691. if(debug)
  7692. printf("After bump: %s\n", myrpt->freq);
  7693. return set_freq_ft897(myrpt, myrpt->freq);
  7694. }
  7695. /*
  7696. * IC-706 I/O handlers
  7697. */
  7698. /* Check to see that the frequency is valid */
  7699. /* returns 0 if frequency is valid */
  7700. static int check_freq_ic706(int m, int d, int *defmode, char mars)
  7701. {
  7702. int dflmd = REM_MODE_FM;
  7703. int rv=0;
  7704. if(debug > 6)
  7705. ast_log(LOG_NOTICE,"(%i,%i,%i,%i)\n",m,d,*defmode,mars);
  7706. /* first test for standard amateur radio bands */
  7707. if(m == 1){ /* 160 meters */
  7708. dflmd = REM_MODE_LSB;
  7709. if(d < 80000)rv=-1;
  7710. }
  7711. else if(m == 3){ /* 80 meters */
  7712. dflmd = REM_MODE_LSB;
  7713. if(d < 50000)rv=-1;
  7714. }
  7715. else if(m == 7){ /* 40 meters */
  7716. dflmd = REM_MODE_LSB;
  7717. if(d > 30000)rv=-1;
  7718. }
  7719. else if(m == 14){ /* 20 meters */
  7720. dflmd = REM_MODE_USB;
  7721. if(d > 35000)rv=-1;
  7722. }
  7723. else if(m == 18){ /* 17 meters */
  7724. dflmd = REM_MODE_USB;
  7725. if((d < 6800) || (d > 16800))rv=-1;
  7726. }
  7727. else if(m == 21){ /* 15 meters */
  7728. dflmd = REM_MODE_USB;
  7729. if((d < 20000) || (d > 45000))rv=-1;
  7730. }
  7731. else if(m == 24){ /* 12 meters */
  7732. dflmd = REM_MODE_USB;
  7733. if((d < 89000) || (d > 99000))rv=-1;
  7734. }
  7735. else if(m == 28){ /* 10 meters */
  7736. dflmd = REM_MODE_USB;
  7737. }
  7738. else if(m == 29){
  7739. if(d >= 51000)
  7740. dflmd = REM_MODE_FM;
  7741. else
  7742. dflmd = REM_MODE_USB;
  7743. if(d > 70000)rv=-1;
  7744. }
  7745. else if(m == 50){ /* 6 meters */
  7746. if(d >= 30000)
  7747. dflmd = REM_MODE_FM;
  7748. else
  7749. dflmd = REM_MODE_USB;
  7750. }
  7751. else if((m >= 51) && ( m < 54)){
  7752. dflmd = REM_MODE_FM;
  7753. }
  7754. else if(m == 144){ /* 2 meters */
  7755. if(d >= 30000)
  7756. dflmd = REM_MODE_FM;
  7757. else
  7758. dflmd = REM_MODE_USB;
  7759. }
  7760. else if((m >= 145) && (m < 148)){
  7761. dflmd = REM_MODE_FM;
  7762. }
  7763. else if((m >= 430) && (m < 450)){ /* 70 centimeters */
  7764. if(m < 438)
  7765. dflmd = REM_MODE_USB;
  7766. else
  7767. dflmd = REM_MODE_FM;
  7768. }
  7769. /* check expanded coverage */
  7770. if(mars && rv<0){
  7771. if((m >= 450) && (m < 470)){ /* LMR */
  7772. dflmd = REM_MODE_FM;
  7773. rv=0;
  7774. }
  7775. else if((m >= 148) && (m < 174)){ /* LMR */
  7776. dflmd = REM_MODE_FM;
  7777. rv=0;
  7778. }
  7779. else if((m >= 138) && (m < 144)){ /* VHF-AM AIRCRAFT */
  7780. dflmd = REM_MODE_AM;
  7781. rv=0;
  7782. }
  7783. else if((m >= 108) && (m < 138)){ /* VHF-AM AIRCRAFT */
  7784. dflmd = REM_MODE_AM;
  7785. rv=0;
  7786. }
  7787. else if( (m==0 && d>=55000) || (m==1 && d<=75000) ){ /* AM BCB*/
  7788. dflmd = REM_MODE_AM;
  7789. rv=0;
  7790. }
  7791. else if( (m == 1 && d>75000) || (m>1 && m<30) ){ /* HF SWL*/
  7792. dflmd = REM_MODE_AM;
  7793. rv=0;
  7794. }
  7795. }
  7796. if(defmode)
  7797. *defmode = dflmd;
  7798. if(debug > 1)
  7799. ast_log(LOG_NOTICE,"(%i,%i,%i,%i) returning %i\n",m,d,*defmode,mars,rv);
  7800. return rv;
  7801. }
  7802. /* take a PL frequency and turn it into a code */
  7803. static int ic706_pltocode(char *str)
  7804. {
  7805. int i;
  7806. char *s;
  7807. int rv=-1;
  7808. s = strchr(str,'.');
  7809. i = 0;
  7810. if (s) i = atoi(s + 1);
  7811. i += atoi(str) * 10;
  7812. switch(i)
  7813. {
  7814. case 670:
  7815. rv=0;
  7816. case 693:
  7817. rv=1;
  7818. case 719:
  7819. rv=2;
  7820. case 744:
  7821. rv=3;
  7822. case 770:
  7823. rv=4;
  7824. case 797:
  7825. rv=5;
  7826. case 825:
  7827. rv=6;
  7828. case 854:
  7829. rv=7;
  7830. case 885:
  7831. rv=8;
  7832. case 915:
  7833. rv=9;
  7834. case 948:
  7835. rv=10;
  7836. case 974:
  7837. rv=11;
  7838. case 1000:
  7839. rv=12;
  7840. case 1035:
  7841. rv=13;
  7842. case 1072:
  7843. rv=14;
  7844. case 1109:
  7845. rv=15;
  7846. case 1148:
  7847. rv=16;
  7848. case 1188:
  7849. rv=17;
  7850. case 1230:
  7851. rv=18;
  7852. case 1273:
  7853. rv=19;
  7854. case 1318:
  7855. rv=20;
  7856. case 1365:
  7857. rv=21;
  7858. case 1413:
  7859. rv=22;
  7860. case 1462:
  7861. rv=23;
  7862. case 1514:
  7863. rv=24;
  7864. case 1567:
  7865. rv=25;
  7866. case 1598:
  7867. rv=26;
  7868. case 1622:
  7869. rv=27;
  7870. case 1655:
  7871. rv=28;
  7872. case 1679:
  7873. rv=29;
  7874. case 1713:
  7875. rv=30;
  7876. case 1738:
  7877. rv=31;
  7878. case 1773:
  7879. rv=32;
  7880. case 1799:
  7881. rv=33;
  7882. case 1835:
  7883. rv=34;
  7884. case 1862:
  7885. rv=35;
  7886. case 1899:
  7887. rv=36;
  7888. case 1928:
  7889. rv=37;
  7890. case 1966:
  7891. rv=38;
  7892. case 1995:
  7893. rv=39;
  7894. case 2035:
  7895. rv=40;
  7896. case 2065:
  7897. rv=41;
  7898. case 2107:
  7899. rv=42;
  7900. case 2181:
  7901. rv=43;
  7902. case 2257:
  7903. rv=44;
  7904. case 2291:
  7905. rv=45;
  7906. case 2336:
  7907. rv=46;
  7908. case 2418:
  7909. rv=47;
  7910. case 2503:
  7911. rv=48;
  7912. case 2541:
  7913. rv=49;
  7914. }
  7915. if(debug > 1)
  7916. ast_log(LOG_NOTICE,"%i rv=%i\n",i, rv);
  7917. return rv;
  7918. }
  7919. /* ic-706 simple commands */
  7920. static int simple_command_ic706(struct rpt *myrpt, char command, char subcommand)
  7921. {
  7922. unsigned char cmdstr[10];
  7923. cmdstr[0] = cmdstr[1] = 0xfe;
  7924. cmdstr[2] = myrpt->p.civaddr;
  7925. cmdstr[3] = 0xe0;
  7926. cmdstr[4] = command;
  7927. cmdstr[5] = subcommand;
  7928. cmdstr[6] = 0xfd;
  7929. return(civ_cmd(myrpt,cmdstr,7));
  7930. }
  7931. /*
  7932. * Set a new frequency for the ic706
  7933. */
  7934. static int set_freq_ic706(struct rpt *myrpt, char *newfreq)
  7935. {
  7936. unsigned char cmdstr[20];
  7937. char mhz[MAXREMSTR], decimals[MAXREMSTR];
  7938. int m,d;
  7939. if(debug)
  7940. ast_log(LOG_NOTICE,"newfreq:%s\n",newfreq);
  7941. if(split_freq(mhz, decimals, newfreq))
  7942. return -1;
  7943. m = atoi(mhz);
  7944. d = atoi(decimals);
  7945. /* The ic-706 likes packed BCD frequencies */
  7946. cmdstr[0] = cmdstr[1] = 0xfe;
  7947. cmdstr[2] = myrpt->p.civaddr;
  7948. cmdstr[3] = 0xe0;
  7949. cmdstr[4] = 5;
  7950. cmdstr[5] = ((d % 10) << 4);
  7951. cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
  7952. cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
  7953. cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
  7954. cmdstr[9] = (m / 100);
  7955. cmdstr[10] = 0xfd;
  7956. return(civ_cmd(myrpt,cmdstr,11));
  7957. }
  7958. /* ic-706 offset */
  7959. static int set_offset_ic706(struct rpt *myrpt, char offset)
  7960. {
  7961. unsigned char c;
  7962. if(debug > 6)
  7963. ast_log(LOG_NOTICE,"offset=%i\n",offset);
  7964. switch(offset){
  7965. case REM_SIMPLEX:
  7966. c = 0x10;
  7967. break;
  7968. case REM_MINUS:
  7969. c = 0x11;
  7970. break;
  7971. case REM_PLUS:
  7972. c = 0x12;
  7973. break;
  7974. default:
  7975. return -1;
  7976. }
  7977. return simple_command_ic706(myrpt,0x0f,c);
  7978. }
  7979. /* ic-706 mode */
  7980. static int set_mode_ic706(struct rpt *myrpt, char newmode)
  7981. {
  7982. unsigned char c;
  7983. if(debug > 6)
  7984. ast_log(LOG_NOTICE,"newmode=%i\n",newmode);
  7985. switch(newmode){
  7986. case REM_MODE_FM:
  7987. c = 5;
  7988. break;
  7989. case REM_MODE_USB:
  7990. c = 1;
  7991. break;
  7992. case REM_MODE_LSB:
  7993. c = 0;
  7994. break;
  7995. case REM_MODE_AM:
  7996. c = 2;
  7997. break;
  7998. default:
  7999. return -1;
  8000. }
  8001. return simple_command_ic706(myrpt,6,c);
  8002. }
  8003. /* Set tone encode and decode modes */
  8004. static int set_ctcss_mode_ic706(struct rpt *myrpt, char txplon, char rxplon)
  8005. {
  8006. unsigned char cmdstr[10];
  8007. int rv;
  8008. if(debug > 6)
  8009. ast_log(LOG_NOTICE,"txplon=%i rxplon=%i \n",txplon,rxplon);
  8010. cmdstr[0] = cmdstr[1] = 0xfe;
  8011. cmdstr[2] = myrpt->p.civaddr;
  8012. cmdstr[3] = 0xe0;
  8013. cmdstr[4] = 0x16;
  8014. cmdstr[5] = 0x42;
  8015. cmdstr[6] = (txplon != 0);
  8016. cmdstr[7] = 0xfd;
  8017. rv = civ_cmd(myrpt,cmdstr,8);
  8018. if (rv) return(-1);
  8019. cmdstr[0] = cmdstr[1] = 0xfe;
  8020. cmdstr[2] = myrpt->p.civaddr;
  8021. cmdstr[3] = 0xe0;
  8022. cmdstr[4] = 0x16;
  8023. cmdstr[5] = 0x43;
  8024. cmdstr[6] = (rxplon != 0);
  8025. cmdstr[7] = 0xfd;
  8026. return(civ_cmd(myrpt,cmdstr,8));
  8027. }
  8028. #if 0
  8029. /* Set transmit and receive ctcss tone frequencies */
  8030. static int set_ctcss_freq_ic706(struct rpt *myrpt, char *txtone, char *rxtone)
  8031. {
  8032. unsigned char cmdstr[10];
  8033. char hertz[MAXREMSTR],decimal[MAXREMSTR];
  8034. int h,d,rv;
  8035. memset(cmdstr, 0, 5);
  8036. if(debug > 6)
  8037. ast_log(LOG_NOTICE,"txtone=%s rxtone=%s \n",txtone,rxtone);
  8038. if(split_ctcss_freq(hertz, decimal, txtone))
  8039. return -1;
  8040. h = atoi(hertz);
  8041. d = atoi(decimal);
  8042. cmdstr[0] = cmdstr[1] = 0xfe;
  8043. cmdstr[2] = myrpt->p.civaddr;
  8044. cmdstr[3] = 0xe0;
  8045. cmdstr[4] = 0x1b;
  8046. cmdstr[5] = 0;
  8047. cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
  8048. cmdstr[7] = ((h % 10) << 4) + (d % 10);
  8049. cmdstr[8] = 0xfd;
  8050. rv = civ_cmd(myrpt,cmdstr,9);
  8051. if (rv) return(-1);
  8052. if (!rxtone) return(0);
  8053. if(split_ctcss_freq(hertz, decimal, rxtone))
  8054. return -1;
  8055. h = atoi(hertz);
  8056. d = atoi(decimal);
  8057. cmdstr[0] = cmdstr[1] = 0xfe;
  8058. cmdstr[2] = myrpt->p.civaddr;
  8059. cmdstr[3] = 0xe0;
  8060. cmdstr[4] = 0x1b;
  8061. cmdstr[5] = 1;
  8062. cmdstr[6] = ((h / 100) << 4) + (h % 100)/ 10;
  8063. cmdstr[7] = ((h % 10) << 4) + (d % 10);
  8064. cmdstr[8] = 0xfd;
  8065. return(civ_cmd(myrpt,cmdstr,9));
  8066. }
  8067. #endif
  8068. static int vfo_ic706(struct rpt *myrpt)
  8069. {
  8070. unsigned char cmdstr[10];
  8071. cmdstr[0] = cmdstr[1] = 0xfe;
  8072. cmdstr[2] = myrpt->p.civaddr;
  8073. cmdstr[3] = 0xe0;
  8074. cmdstr[4] = 7;
  8075. cmdstr[5] = 0xfd;
  8076. return(civ_cmd(myrpt,cmdstr,6));
  8077. }
  8078. static int mem2vfo_ic706(struct rpt *myrpt)
  8079. {
  8080. unsigned char cmdstr[10];
  8081. cmdstr[0] = cmdstr[1] = 0xfe;
  8082. cmdstr[2] = myrpt->p.civaddr;
  8083. cmdstr[3] = 0xe0;
  8084. cmdstr[4] = 0x0a;
  8085. cmdstr[5] = 0xfd;
  8086. return(civ_cmd(myrpt,cmdstr,6));
  8087. }
  8088. static int select_mem_ic706(struct rpt *myrpt, int slot)
  8089. {
  8090. unsigned char cmdstr[10];
  8091. cmdstr[0] = cmdstr[1] = 0xfe;
  8092. cmdstr[2] = myrpt->p.civaddr;
  8093. cmdstr[3] = 0xe0;
  8094. cmdstr[4] = 8;
  8095. cmdstr[5] = 0;
  8096. cmdstr[6] = ((slot / 10) << 4) + (slot % 10);
  8097. cmdstr[7] = 0xfd;
  8098. return(civ_cmd(myrpt,cmdstr,8));
  8099. }
  8100. static int set_ic706(struct rpt *myrpt)
  8101. {
  8102. int res = 0,i;
  8103. if(debug)ast_log(LOG_NOTICE, "Set to VFO A iobase=%i\n",myrpt->p.iobase);
  8104. if (!res)
  8105. res = simple_command_ic706(myrpt,7,0);
  8106. if((myrpt->remmode == REM_MODE_FM))
  8107. {
  8108. i = ic706_pltocode(myrpt->rxpl);
  8109. if (i == -1) return -1;
  8110. if(debug)
  8111. printf("Select memory number\n");
  8112. if (!res)
  8113. res = select_mem_ic706(myrpt,i + IC706_PL_MEMORY_OFFSET);
  8114. if(debug)
  8115. printf("Transfer memory to VFO\n");
  8116. if (!res)
  8117. res = mem2vfo_ic706(myrpt);
  8118. }
  8119. if(debug)
  8120. printf("Set to VFO\n");
  8121. if (!res)
  8122. res = vfo_ic706(myrpt);
  8123. if(debug)
  8124. printf("Modulation mode\n");
  8125. if (!res)
  8126. res = set_mode_ic706(myrpt, myrpt->remmode); /* Modulation mode */
  8127. if(debug)
  8128. printf("Split off\n");
  8129. if(!res)
  8130. simple_command_ic706(myrpt, 0x82,0); /* Split off */
  8131. if(debug)
  8132. printf("Frequency\n");
  8133. if(!res)
  8134. res = set_freq_ic706(myrpt, myrpt->freq); /* Frequency */
  8135. if((myrpt->remmode == REM_MODE_FM)){
  8136. if(debug)
  8137. printf("Offset\n");
  8138. if(!res)
  8139. res = set_offset_ic706(myrpt, myrpt->offset); /* Offset if FM */
  8140. if(!res){
  8141. if(debug)
  8142. printf("CTCSS mode\n");
  8143. res = set_ctcss_mode_ic706(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
  8144. }
  8145. }
  8146. return res;
  8147. }
  8148. /*
  8149. * Bump frequency up or down by a small amount
  8150. * Return 0 if the new frequnecy is valid, or -1 if invalid
  8151. * Interval is in Hz, resolution is 10Hz
  8152. */
  8153. static int multimode_bump_freq_ic706(struct rpt *myrpt, int interval)
  8154. {
  8155. int m,d;
  8156. char mhz[MAXREMSTR], decimals[MAXREMSTR];
  8157. unsigned char cmdstr[20];
  8158. if(debug)
  8159. printf("Before bump: %s\n", myrpt->freq);
  8160. if(split_freq(mhz, decimals, myrpt->freq))
  8161. return -1;
  8162. m = atoi(mhz);
  8163. d = atoi(decimals);
  8164. d += (interval / 10); /* 10Hz resolution */
  8165. if(d < 0){
  8166. m--;
  8167. d += 100000;
  8168. }
  8169. else if(d >= 100000){
  8170. m++;
  8171. d -= 100000;
  8172. }
  8173. if(check_freq_ic706(m, d, NULL,myrpt->p.remote_mars)){
  8174. if(debug)
  8175. printf("Bump freq invalid\n");
  8176. return -1;
  8177. }
  8178. snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
  8179. if(debug)
  8180. printf("After bump: %s\n", myrpt->freq);
  8181. /* The ic-706 likes packed BCD frequencies */
  8182. cmdstr[0] = cmdstr[1] = 0xfe;
  8183. cmdstr[2] = myrpt->p.civaddr;
  8184. cmdstr[3] = 0xe0;
  8185. cmdstr[4] = 0;
  8186. cmdstr[5] = ((d % 10) << 4);
  8187. cmdstr[6] = (((d % 1000)/ 100) << 4) + ((d % 100)/10);
  8188. cmdstr[7] = ((d / 10000) << 4) + ((d % 10000)/1000);
  8189. cmdstr[8] = (((m % 100)/10) << 4) + (m % 10);
  8190. cmdstr[9] = (m / 100);
  8191. cmdstr[10] = 0xfd;
  8192. return(serial_remote_io(myrpt,cmdstr,11,NULL,0,0));
  8193. }
  8194. /*
  8195. * Dispatch to correct I/O handler
  8196. */
  8197. static int setrem(struct rpt *myrpt)
  8198. {
  8199. char str[300];
  8200. char *offsets[] = {"SIMPLEX","MINUS","PLUS"};
  8201. char *powerlevels[] = {"LOW","MEDIUM","HIGH"};
  8202. char *modes[] = {"FM","USB","LSB","AM"};
  8203. int res = -1;
  8204. #if 0
  8205. printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt->freq,
  8206. modes[(int)myrpt->remmode],
  8207. myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
  8208. powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
  8209. myrpt->rxplon);
  8210. #endif
  8211. if (myrpt->p.archivedir)
  8212. {
  8213. sprintf(str,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt->freq,
  8214. modes[(int)myrpt->remmode],
  8215. myrpt->txpl,myrpt->rxpl,offsets[(int)myrpt->offset],
  8216. powerlevels[(int)myrpt->powerlevel],myrpt->txplon,
  8217. myrpt->rxplon);
  8218. donodelog(myrpt,str);
  8219. }
  8220. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  8221. {
  8222. rpt_telemetry(myrpt,SETREMOTE,NULL);
  8223. res = 0;
  8224. }
  8225. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8226. {
  8227. rpt_telemetry(myrpt,SETREMOTE,NULL);
  8228. res = 0;
  8229. }
  8230. if(!strcmp(myrpt->remoterig, remote_rig_tm271))
  8231. {
  8232. rpt_telemetry(myrpt,SETREMOTE,NULL);
  8233. res = 0;
  8234. }
  8235. else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
  8236. {
  8237. res = setrbi_check(myrpt);
  8238. if (!res)
  8239. {
  8240. rpt_telemetry(myrpt,SETREMOTE,NULL);
  8241. res = 0;
  8242. }
  8243. }
  8244. else if(ISRIG_RTX(myrpt->remoterig))
  8245. {
  8246. setrtx(myrpt);
  8247. res = 0;
  8248. }
  8249. else if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) {
  8250. rpt_telemetry(myrpt,SETREMOTE,NULL);
  8251. res = 0;
  8252. }
  8253. else
  8254. res = 0;
  8255. if (res < 0) ast_log(LOG_ERROR,"Unable to send remote command on node %s\n",myrpt->name);
  8256. return res;
  8257. }
  8258. static int closerem(struct rpt *myrpt)
  8259. {
  8260. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  8261. return closerem_ft897(myrpt);
  8262. else
  8263. return 0;
  8264. }
  8265. /*
  8266. * Dispatch to correct RX frequency checker
  8267. */
  8268. static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
  8269. {
  8270. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  8271. return check_freq_ft897(m, d, defmode);
  8272. else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8273. return check_freq_ic706(m, d, defmode,myrpt->p.remote_mars);
  8274. else if(!strcmp(myrpt->remoterig, remote_rig_rbi))
  8275. return check_freq_rbi(m, d, defmode);
  8276. else if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
  8277. return check_freq_kenwood(m, d, defmode);
  8278. else if(!strcmp(myrpt->remoterig, remote_rig_tm271))
  8279. return check_freq_tm271(m, d, defmode);
  8280. else if(ISRIG_RTX(myrpt->remoterig))
  8281. return check_freq_rtx(m, d, defmode, myrpt);
  8282. else
  8283. return -1;
  8284. }
  8285. /*
  8286. * Check TX frequency before transmitting
  8287. rv=1 if tx frequency in ok.
  8288. */
  8289. static char check_tx_freq(struct rpt *myrpt)
  8290. {
  8291. int i,rv=0;
  8292. int radio_mhz, radio_decimals, ulimit_mhz, ulimit_decimals, llimit_mhz, llimit_decimals;
  8293. char radio_mhz_char[MAXREMSTR];
  8294. char radio_decimals_char[MAXREMSTR];
  8295. char limit_mhz_char[MAXREMSTR];
  8296. char limit_decimals_char[MAXREMSTR];
  8297. char limits[256];
  8298. char *limit_ranges[40];
  8299. struct ast_variable *limitlist;
  8300. if(debug > 3){
  8301. ast_log(LOG_NOTICE, "myrpt->freq = %s\n", myrpt->freq);
  8302. }
  8303. /* Must have user logged in and tx_limits defined */
  8304. if(!myrpt->p.txlimitsstanzaname || !myrpt->loginuser[0] || !myrpt->loginlevel[0]){
  8305. if(debug > 3){
  8306. ast_log(LOG_NOTICE, "No tx band table defined, or no user logged in. rv=1\n");
  8307. }
  8308. rv=1;
  8309. return 1; /* Assume it's ok otherwise */
  8310. }
  8311. /* Retrieve the band table for the loginlevel */
  8312. limitlist = ast_variable_browse(myrpt->cfg, myrpt->p.txlimitsstanzaname);
  8313. if(!limitlist){
  8314. ast_log(LOG_WARNING, "No entries in %s band table stanza. rv=0\n", myrpt->p.txlimitsstanzaname);
  8315. rv=0;
  8316. return 0;
  8317. }
  8318. split_freq(radio_mhz_char, radio_decimals_char, myrpt->freq);
  8319. radio_mhz = atoi(radio_mhz_char);
  8320. radio_decimals = decimals2int(radio_decimals_char);
  8321. if(debug > 3){
  8322. ast_log(LOG_NOTICE, "Login User = %s, login level = %s\n", myrpt->loginuser, myrpt->loginlevel);
  8323. }
  8324. /* Find our entry */
  8325. for(;limitlist; limitlist=limitlist->next){
  8326. if(!strcmp(limitlist->name, myrpt->loginlevel))
  8327. break;
  8328. }
  8329. if(!limitlist){
  8330. ast_log(LOG_WARNING, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt->loginlevel, myrpt->p.txlimitsstanzaname);
  8331. rv=0;
  8332. return 0;
  8333. }
  8334. if(debug > 3){
  8335. ast_log(LOG_NOTICE, "Auth: %s = %s\n", limitlist->name, limitlist->value);
  8336. }
  8337. /* Parse the limits */
  8338. strncpy(limits, limitlist->value, 256);
  8339. limits[255] = 0;
  8340. finddelim(limits, limit_ranges, 40);
  8341. for(i = 0; i < 40 && limit_ranges[i] ; i++){
  8342. char range[40];
  8343. char *r,*s;
  8344. strncpy(range, limit_ranges[i], 40);
  8345. range[39] = 0;
  8346. if(debug > 3)
  8347. ast_log(LOG_NOTICE, "Check %s within %s\n", myrpt->freq, range);
  8348. r = strchr(range, '-');
  8349. if(!r){
  8350. ast_log(LOG_WARNING, "Malformed range in %s tx band table entry. rv=0\n", limitlist->name);
  8351. rv=0;
  8352. break;
  8353. }
  8354. *r++ = 0;
  8355. s = eatwhite(range);
  8356. r = eatwhite(r);
  8357. split_freq(limit_mhz_char, limit_decimals_char, s);
  8358. llimit_mhz = atoi(limit_mhz_char);
  8359. llimit_decimals = decimals2int(limit_decimals_char);
  8360. split_freq(limit_mhz_char, limit_decimals_char, r);
  8361. ulimit_mhz = atoi(limit_mhz_char);
  8362. ulimit_decimals = decimals2int(limit_decimals_char);
  8363. if((radio_mhz >= llimit_mhz) && (radio_mhz <= ulimit_mhz)){
  8364. if(radio_mhz == llimit_mhz){ /* CASE 1: TX freq is in llimit mhz portion of band */
  8365. if(radio_decimals >= llimit_decimals){ /* Cannot be below llimit decimals */
  8366. if(llimit_mhz == ulimit_mhz){ /* If bandwidth < 1Mhz, check ulimit decimals */
  8367. if(radio_decimals <= ulimit_decimals){
  8368. rv=1;
  8369. break;
  8370. }
  8371. else{
  8372. if(debug > 3)
  8373. ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 1\n");
  8374. rv=0;
  8375. break;
  8376. }
  8377. }
  8378. else{
  8379. rv=1;
  8380. break;
  8381. }
  8382. }
  8383. else{ /* Is below llimit decimals */
  8384. if(debug > 3)
  8385. ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 2\n");
  8386. rv=0;
  8387. break;
  8388. }
  8389. }
  8390. else if(radio_mhz == ulimit_mhz){ /* CASE 2: TX freq not in llimit mhz portion of band */
  8391. if(radio_decimals <= ulimit_decimals){
  8392. if(debug > 3)
  8393. ast_log(LOG_NOTICE, "radio_decimals <= ulimit_decimals\n");
  8394. rv=1;
  8395. break;
  8396. }
  8397. else{ /* Is above ulimit decimals */
  8398. if(debug > 3)
  8399. ast_log(LOG_NOTICE, "Invalid TX frequency, debug msg 3\n");
  8400. rv=0;
  8401. break;
  8402. }
  8403. }
  8404. else /* CASE 3: TX freq within a multi-Mhz band and ok */
  8405. if(debug > 3)
  8406. ast_log(LOG_NOTICE, "Valid TX freq within a multi-Mhz band and ok.\n");
  8407. rv=1;
  8408. break;
  8409. }
  8410. }
  8411. if(debug > 3)
  8412. ast_log(LOG_NOTICE, "rv=%i\n",rv);
  8413. return rv;
  8414. }
  8415. /*
  8416. * Dispatch to correct frequency bumping function
  8417. */
  8418. static int multimode_bump_freq(struct rpt *myrpt, int interval)
  8419. {
  8420. if(!strcmp(myrpt->remoterig, remote_rig_ft897))
  8421. return multimode_bump_freq_ft897(myrpt, interval);
  8422. else if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8423. return multimode_bump_freq_ic706(myrpt, interval);
  8424. else
  8425. return -1;
  8426. }
  8427. /*
  8428. * Queue announcment that scan has been stopped
  8429. */
  8430. static void stop_scan(struct rpt *myrpt)
  8431. {
  8432. myrpt->hfscanstop = 1;
  8433. rpt_telemetry(myrpt,SCAN,0);
  8434. }
  8435. /*
  8436. * This is called periodically when in scan mode
  8437. */
  8438. static int service_scan(struct rpt *myrpt)
  8439. {
  8440. int res, interval;
  8441. char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
  8442. switch(myrpt->hfscanmode){
  8443. case HF_SCAN_DOWN_SLOW:
  8444. interval = -10; /* 100Hz /sec */
  8445. break;
  8446. case HF_SCAN_DOWN_QUICK:
  8447. interval = -50; /* 500Hz /sec */
  8448. break;
  8449. case HF_SCAN_DOWN_FAST:
  8450. interval = -200; /* 2KHz /sec */
  8451. break;
  8452. case HF_SCAN_UP_SLOW:
  8453. interval = 10; /* 100Hz /sec */
  8454. break;
  8455. case HF_SCAN_UP_QUICK:
  8456. interval = 50; /* 500 Hz/sec */
  8457. break;
  8458. case HF_SCAN_UP_FAST:
  8459. interval = 200; /* 2KHz /sec */
  8460. break;
  8461. default:
  8462. myrpt->hfscanmode = 0; /* Huh? */
  8463. return -1;
  8464. }
  8465. res = split_freq(mhz, decimals, myrpt->freq);
  8466. if(!res){
  8467. k100 =decimals[0];
  8468. k10 = decimals[1];
  8469. res = multimode_bump_freq(myrpt, interval);
  8470. }
  8471. if(!res)
  8472. res = split_freq(mhz, decimals, myrpt->freq);
  8473. if(res){
  8474. myrpt->hfscanmode = 0;
  8475. myrpt->hfscanstatus = -2;
  8476. return -1;
  8477. }
  8478. /* Announce 10KHz boundaries */
  8479. if(k10 != decimals[1]){
  8480. int myhund = (interval < 0) ? k100 : decimals[0];
  8481. int myten = (interval < 0) ? k10 : decimals[1];
  8482. myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
  8483. } else myrpt->hfscanstatus = 0;
  8484. return res;
  8485. }
  8486. /*
  8487. retrieve memory setting and set radio
  8488. */
  8489. static int get_mem_set(struct rpt *myrpt, char *digitbuf)
  8490. {
  8491. int res=0;
  8492. if(debug)ast_log(LOG_NOTICE," digitbuf=%s\n", digitbuf);
  8493. res = retreive_memory(myrpt, digitbuf);
  8494. if(!res)res=setrem(myrpt);
  8495. if(debug)ast_log(LOG_NOTICE," freq=%s res=%i\n", myrpt->freq, res);
  8496. return res;
  8497. }
  8498. /*
  8499. steer the radio selected channel to either one programmed into the radio
  8500. or if the radio is VFO agile, to an rpt.conf memory location.
  8501. */
  8502. static int channel_steer(struct rpt *myrpt, char *data)
  8503. {
  8504. int res=0;
  8505. if(debug)ast_log(LOG_NOTICE,"remoterig=%s, data=%s\n",myrpt->remoterig,data);
  8506. if (!myrpt->remoterig) return(0);
  8507. if(data<=0)
  8508. {
  8509. res=-1;
  8510. }
  8511. else
  8512. {
  8513. myrpt->nowchan=strtod(data,NULL);
  8514. if(!strcmp(myrpt->remoterig, remote_rig_ppp16))
  8515. {
  8516. char string[16];
  8517. sprintf(string,"SETCHAN %d ",myrpt->nowchan);
  8518. send_usb_txt(myrpt,string);
  8519. }
  8520. else
  8521. {
  8522. if(get_mem_set(myrpt, data))res=-1;
  8523. }
  8524. }
  8525. if(debug)ast_log(LOG_NOTICE,"nowchan=%i res=%i\n",myrpt->nowchan, res);
  8526. return res;
  8527. }
  8528. /*
  8529. */
  8530. static int channel_revert(struct rpt *myrpt)
  8531. {
  8532. int res=0;
  8533. if(debug)ast_log(LOG_NOTICE,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt->remoterig,myrpt->nowchan,myrpt->waschan);
  8534. if (!myrpt->remoterig) return(0);
  8535. if(myrpt->nowchan!=myrpt->waschan)
  8536. {
  8537. char data[8];
  8538. if(debug)ast_log(LOG_NOTICE,"reverting.\n");
  8539. sprintf(data,"%02d",myrpt->waschan);
  8540. myrpt->nowchan=myrpt->waschan;
  8541. channel_steer(myrpt,data);
  8542. res=1;
  8543. }
  8544. return(res);
  8545. }
  8546. /*
  8547. * Remote base function
  8548. */
  8549. static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
  8550. {
  8551. char *s,*s1,*s2;
  8552. int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
  8553. intptr_t p;
  8554. char multimode = 0;
  8555. char oc,*cp,*cp1,*cp2;
  8556. char tmp[20], freq[20] = "", savestr[20] = "";
  8557. char mhz[MAXREMSTR], decimals[MAXREMSTR];
  8558. if(debug > 6) {
  8559. ast_log(LOG_NOTICE,"%s param=%s digitbuf=%s source=%i\n",myrpt->name,param,digitbuf,command_source);
  8560. }
  8561. if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
  8562. return DC_ERROR;
  8563. p = myatoi(param);
  8564. if ((p != 99) && (p != 5) && (p != 140) && myrpt->p.authlevel &&
  8565. (!myrpt->loginlevel[0])) return DC_ERROR;
  8566. multimode = multimode_capable(myrpt);
  8567. switch(p){
  8568. case 1: /* retrieve memory */
  8569. if(strlen(digitbuf) < 2) /* needs 2 digits */
  8570. break;
  8571. for(i = 0 ; i < 2 ; i++){
  8572. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  8573. return DC_ERROR;
  8574. }
  8575. r=get_mem_set(myrpt, digitbuf);
  8576. if (r < 0){
  8577. rpt_telemetry(myrpt,MEMNOTFOUND,NULL);
  8578. return DC_COMPLETE;
  8579. }
  8580. else if (r > 0){
  8581. return DC_ERROR;
  8582. }
  8583. return DC_COMPLETE;
  8584. case 2: /* set freq and offset */
  8585. for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for M+*K+*O or M+*H+* depending on mode */
  8586. if(digitbuf[i] == '*'){
  8587. j++;
  8588. continue;
  8589. }
  8590. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  8591. goto invalid_freq;
  8592. else{
  8593. if(j == 0)
  8594. l++; /* # of digits before first * */
  8595. if(j == 1)
  8596. k++; /* # of digits after first * */
  8597. }
  8598. }
  8599. i = strlen(digitbuf) - 1;
  8600. if(multimode){
  8601. if((j > 2) || (l > 3) || (k > 6))
  8602. goto invalid_freq; /* &^@#! */
  8603. }
  8604. else{
  8605. if((j > 2) || (l > 4) || (k > 3))
  8606. goto invalid_freq; /* &^@#! */
  8607. }
  8608. /* Wait for M+*K+* */
  8609. if(j < 2)
  8610. break; /* Not yet */
  8611. /* We have a frequency */
  8612. strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
  8613. s = tmp;
  8614. s1 = strsep(&s, "*"); /* Pick off MHz */
  8615. s2 = strsep(&s,"*"); /* Pick off KHz and Hz */
  8616. ls2 = strlen(s2);
  8617. switch(ls2){ /* Allow partial entry of khz and hz digits for laziness support */
  8618. case 1:
  8619. ht = 0;
  8620. k = 100 * atoi(s2);
  8621. break;
  8622. case 2:
  8623. ht = 0;
  8624. k = 10 * atoi(s2);
  8625. break;
  8626. case 3:
  8627. if(!multimode){
  8628. if((s2[2] != '0')&&(s2[2] != '5'))
  8629. goto invalid_freq;
  8630. }
  8631. ht = 0;
  8632. k = atoi(s2);
  8633. break;
  8634. case 4:
  8635. k = atoi(s2)/10;
  8636. ht = 10 * (atoi(s2+(ls2-1)));
  8637. break;
  8638. case 5:
  8639. k = atoi(s2)/100;
  8640. ht = (atoi(s2+(ls2-2)));
  8641. break;
  8642. default:
  8643. goto invalid_freq;
  8644. }
  8645. /* Check frequency for validity and establish a default mode */
  8646. snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
  8647. if(debug)
  8648. ast_log(LOG_NOTICE, "New frequency: %s\n", freq);
  8649. split_freq(mhz, decimals, freq);
  8650. m = atoi(mhz);
  8651. d = atoi(decimals);
  8652. if(check_freq(myrpt, m, d, &defmode)) /* Check to see if frequency entered is legit */
  8653. goto invalid_freq;
  8654. if((defmode == REM_MODE_FM) && (digitbuf[i] == '*')) /* If FM, user must enter and additional offset digit */
  8655. break; /* Not yet */
  8656. offset = REM_SIMPLEX; /* Assume simplex */
  8657. if(defmode == REM_MODE_FM){
  8658. oc = *s; /* Pick off offset */
  8659. if (oc){
  8660. switch(oc){
  8661. case '1':
  8662. offset = REM_MINUS;
  8663. break;
  8664. case '2':
  8665. offset = REM_SIMPLEX;
  8666. break;
  8667. case '3':
  8668. offset = REM_PLUS;
  8669. break;
  8670. default:
  8671. goto invalid_freq;
  8672. }
  8673. }
  8674. }
  8675. offsave = myrpt->offset;
  8676. modesave = myrpt->remmode;
  8677. strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
  8678. strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
  8679. myrpt->offset = offset;
  8680. myrpt->remmode = defmode;
  8681. if (setrem(myrpt) == -1){
  8682. myrpt->offset = offsave;
  8683. myrpt->remmode = modesave;
  8684. strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
  8685. goto invalid_freq;
  8686. }
  8687. return DC_COMPLETE;
  8688. invalid_freq:
  8689. rpt_telemetry(myrpt,INVFREQ,NULL);
  8690. return DC_ERROR;
  8691. case 3: /* set rx PL tone */
  8692. for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
  8693. if(digitbuf[i] == '*'){
  8694. j++;
  8695. continue;
  8696. }
  8697. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  8698. return DC_ERROR;
  8699. else{
  8700. if(j)
  8701. l++;
  8702. else
  8703. k++;
  8704. }
  8705. }
  8706. if((j > 1) || (k > 3) || (l > 1))
  8707. return DC_ERROR; /* &$@^! */
  8708. i = strlen(digitbuf) - 1;
  8709. if((j != 1) || (k < 2)|| (l != 1))
  8710. break; /* Not yet */
  8711. if(debug)
  8712. printf("PL digits entered %s\n", digitbuf);
  8713. strncpy(tmp, digitbuf, sizeof(tmp) - 1);
  8714. /* see if we have at least 1 */
  8715. s = strchr(tmp,'*');
  8716. if(s)
  8717. *s = '.';
  8718. strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
  8719. strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
  8720. if(!strcmp(myrpt->remoterig, remote_rig_rbi))
  8721. {
  8722. strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
  8723. }
  8724. if (setrem(myrpt) == -1){
  8725. strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
  8726. return DC_ERROR;
  8727. }
  8728. return DC_COMPLETE;
  8729. case 4: /* set tx PL tone */
  8730. /* cant set tx tone on RBI (rx tone does both) */
  8731. if(!strcmp(myrpt->remoterig, remote_rig_rbi))
  8732. return DC_ERROR;
  8733. /* eventually for the ic706 instead of just throwing the exception
  8734. we can check if we are in encode only mode and allow the tx
  8735. ctcss code to be changed. but at least the warning message is
  8736. issued for now.
  8737. */
  8738. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8739. {
  8740. if(debug)
  8741. ast_log(LOG_WARNING,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
  8742. return DC_ERROR;
  8743. }
  8744. for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){ /* look for N+*N */
  8745. if(digitbuf[i] == '*'){
  8746. j++;
  8747. continue;
  8748. }
  8749. if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
  8750. return DC_ERROR;
  8751. else{
  8752. if(j)
  8753. l++;
  8754. else
  8755. k++;
  8756. }
  8757. }
  8758. if((j > 1) || (k > 3) || (l > 1))
  8759. return DC_ERROR; /* &$@^! */
  8760. i = strlen(digitbuf) - 1;
  8761. if((j != 1) || (k < 2)|| (l != 1))
  8762. break; /* Not yet */
  8763. if(debug)
  8764. printf("PL digits entered %s\n", digitbuf);
  8765. strncpy(tmp, digitbuf, sizeof(tmp) - 1);
  8766. /* see if we have at least 1 */
  8767. s = strchr(tmp,'*');
  8768. if(s)
  8769. *s = '.';
  8770. strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
  8771. strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
  8772. if (setrem(myrpt) == -1){
  8773. strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
  8774. return DC_ERROR;
  8775. }
  8776. return DC_COMPLETE;
  8777. case 6: /* MODE (FM,USB,LSB,AM) */
  8778. if(strlen(digitbuf) < 1)
  8779. break;
  8780. if(!multimode)
  8781. return DC_ERROR; /* Multimode radios only */
  8782. switch(*digitbuf){
  8783. case '1':
  8784. split_freq(mhz, decimals, myrpt->freq);
  8785. m=atoi(mhz);
  8786. if(m < 29) /* No FM allowed below 29MHz! */
  8787. return DC_ERROR;
  8788. myrpt->remmode = REM_MODE_FM;
  8789. rpt_telemetry(myrpt,REMMODE,NULL);
  8790. break;
  8791. case '2':
  8792. myrpt->remmode = REM_MODE_USB;
  8793. rpt_telemetry(myrpt,REMMODE,NULL);
  8794. break;
  8795. case '3':
  8796. myrpt->remmode = REM_MODE_LSB;
  8797. rpt_telemetry(myrpt,REMMODE,NULL);
  8798. break;
  8799. case '4':
  8800. myrpt->remmode = REM_MODE_AM;
  8801. rpt_telemetry(myrpt,REMMODE,NULL);
  8802. break;
  8803. default:
  8804. return DC_ERROR;
  8805. }
  8806. if(setrem(myrpt))
  8807. return DC_ERROR;
  8808. return DC_COMPLETEQUIET;
  8809. case 99:
  8810. /* cant log in when logged in */
  8811. if (myrpt->loginlevel[0])
  8812. return DC_ERROR;
  8813. *myrpt->loginuser = 0;
  8814. myrpt->loginlevel[0] = 0;
  8815. cp = ast_strdup(param);
  8816. cp1 = strchr(cp,',');
  8817. ast_mutex_lock(&myrpt->lock);
  8818. if (cp1)
  8819. {
  8820. *cp1 = 0;
  8821. cp2 = strchr(cp1 + 1,',');
  8822. if (cp2)
  8823. {
  8824. *cp2 = 0;
  8825. strncpy(myrpt->loginlevel,cp2 + 1,
  8826. sizeof(myrpt->loginlevel) - 1);
  8827. }
  8828. strncpy(myrpt->loginuser,cp1 + 1,sizeof(myrpt->loginuser));
  8829. ast_mutex_unlock(&myrpt->lock);
  8830. if (myrpt->p.archivedir)
  8831. {
  8832. char str[100];
  8833. sprintf(str,"LOGIN,%s,%s",
  8834. myrpt->loginuser,myrpt->loginlevel);
  8835. donodelog(myrpt,str);
  8836. }
  8837. if (debug)
  8838. printf("loginuser %s level %s\n",myrpt->loginuser,myrpt->loginlevel);
  8839. rpt_telemetry(myrpt,REMLOGIN,NULL);
  8840. }
  8841. ast_free(cp);
  8842. return DC_COMPLETEQUIET;
  8843. case 100: /* RX PL Off */
  8844. myrpt->rxplon = 0;
  8845. setrem(myrpt);
  8846. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8847. return DC_COMPLETEQUIET;
  8848. case 101: /* RX PL On */
  8849. myrpt->rxplon = 1;
  8850. setrem(myrpt);
  8851. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8852. return DC_COMPLETEQUIET;
  8853. case 102: /* TX PL Off */
  8854. myrpt->txplon = 0;
  8855. setrem(myrpt);
  8856. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8857. return DC_COMPLETEQUIET;
  8858. case 103: /* TX PL On */
  8859. myrpt->txplon = 1;
  8860. setrem(myrpt);
  8861. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8862. return DC_COMPLETEQUIET;
  8863. case 104: /* Low Power */
  8864. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8865. return DC_ERROR;
  8866. myrpt->powerlevel = REM_LOWPWR;
  8867. setrem(myrpt);
  8868. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8869. return DC_COMPLETEQUIET;
  8870. case 105: /* Medium Power */
  8871. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8872. return DC_ERROR;
  8873. if (ISRIG_RTX(myrpt->remoterig)) return DC_ERROR;
  8874. myrpt->powerlevel = REM_MEDPWR;
  8875. setrem(myrpt);
  8876. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8877. return DC_COMPLETEQUIET;
  8878. case 106: /* Hi Power */
  8879. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  8880. return DC_ERROR;
  8881. myrpt->powerlevel = REM_HIPWR;
  8882. setrem(myrpt);
  8883. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8884. return DC_COMPLETEQUIET;
  8885. case 107: /* Bump down 20Hz */
  8886. multimode_bump_freq(myrpt, -20);
  8887. return DC_COMPLETE;
  8888. case 108: /* Bump down 100Hz */
  8889. multimode_bump_freq(myrpt, -100);
  8890. return DC_COMPLETE;
  8891. case 109: /* Bump down 500Hz */
  8892. multimode_bump_freq(myrpt, -500);
  8893. return DC_COMPLETE;
  8894. case 110: /* Bump up 20Hz */
  8895. multimode_bump_freq(myrpt, 20);
  8896. return DC_COMPLETE;
  8897. case 111: /* Bump up 100Hz */
  8898. multimode_bump_freq(myrpt, 100);
  8899. return DC_COMPLETE;
  8900. case 112: /* Bump up 500Hz */
  8901. multimode_bump_freq(myrpt, 500);
  8902. return DC_COMPLETE;
  8903. case 113: /* Scan down slow */
  8904. myrpt->scantimer = REM_SCANTIME;
  8905. myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
  8906. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8907. return DC_COMPLETEQUIET;
  8908. case 114: /* Scan down quick */
  8909. myrpt->scantimer = REM_SCANTIME;
  8910. myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
  8911. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8912. return DC_COMPLETEQUIET;
  8913. case 115: /* Scan down fast */
  8914. myrpt->scantimer = REM_SCANTIME;
  8915. myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
  8916. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8917. return DC_COMPLETEQUIET;
  8918. case 116: /* Scan up slow */
  8919. myrpt->scantimer = REM_SCANTIME;
  8920. myrpt->hfscanmode = HF_SCAN_UP_SLOW;
  8921. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8922. return DC_COMPLETEQUIET;
  8923. case 117: /* Scan up quick */
  8924. myrpt->scantimer = REM_SCANTIME;
  8925. myrpt->hfscanmode = HF_SCAN_UP_QUICK;
  8926. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8927. return DC_COMPLETEQUIET;
  8928. case 118: /* Scan up fast */
  8929. myrpt->scantimer = REM_SCANTIME;
  8930. myrpt->hfscanmode = HF_SCAN_UP_FAST;
  8931. rpt_telemetry(myrpt,REMXXX,(void *)p);
  8932. return DC_COMPLETEQUIET;
  8933. case 119: /* Tune Request */
  8934. if(debug > 3)
  8935. ast_log(LOG_NOTICE,"TUNE REQUEST\n");
  8936. /* if not currently going, and valid to do */
  8937. if((!myrpt->tunerequest) &&
  8938. ((!strcmp(myrpt->remoterig, remote_rig_ft897) ||
  8939. !strcmp(myrpt->remoterig, remote_rig_ic706)) )) {
  8940. myrpt->remotetx = 0;
  8941. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
  8942. myrpt->tunerequest = 1;
  8943. rpt_telemetry(myrpt,TUNE,NULL);
  8944. return DC_COMPLETEQUIET;
  8945. }
  8946. return DC_ERROR;
  8947. case 5: /* Long Status */
  8948. rpt_telemetry(myrpt,REMLONGSTATUS,NULL);
  8949. return DC_COMPLETEQUIET;
  8950. case 140: /* Short Status */
  8951. rpt_telemetry(myrpt,REMSHORTSTATUS,NULL);
  8952. return DC_COMPLETEQUIET;
  8953. case 200:
  8954. case 201:
  8955. case 202:
  8956. case 203:
  8957. case 204:
  8958. case 205:
  8959. case 206:
  8960. case 207:
  8961. case 208:
  8962. case 209:
  8963. case 210:
  8964. case 211:
  8965. case 212:
  8966. case 213:
  8967. case 214:
  8968. case 215:
  8969. do_dtmf_local(myrpt,remdtmfstr[p - 200]);
  8970. return DC_COMPLETEQUIET;
  8971. default:
  8972. break;
  8973. }
  8974. return DC_INDETERMINATE;
  8975. }
  8976. static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
  8977. {
  8978. time_t now;
  8979. int ret,res = 0,src;
  8980. if(debug > 6)
  8981. ast_log(LOG_NOTICE,"c=%c phonemode=%i dtmfidx=%i\n",c,phonemode,myrpt->dtmfidx);
  8982. time(&myrpt->last_activity_time);
  8983. /* Stop scan mode if in scan mode */
  8984. if(myrpt->hfscanmode){
  8985. stop_scan(myrpt);
  8986. return 0;
  8987. }
  8988. time(&now);
  8989. /* if timed-out */
  8990. if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
  8991. {
  8992. myrpt->dtmfidx = -1;
  8993. myrpt->dtmfbuf[0] = 0;
  8994. myrpt->dtmf_time_rem = 0;
  8995. }
  8996. /* if decode not active */
  8997. if (myrpt->dtmfidx == -1)
  8998. {
  8999. /* if not lead-in digit, don't worry */
  9000. if (c != myrpt->p.funcchar)
  9001. {
  9002. if (!myrpt->p.propagate_dtmf)
  9003. {
  9004. rpt_mutex_lock(&myrpt->lock);
  9005. do_dtmf_local(myrpt,c);
  9006. rpt_mutex_unlock(&myrpt->lock);
  9007. }
  9008. return 0;
  9009. }
  9010. myrpt->dtmfidx = 0;
  9011. myrpt->dtmfbuf[0] = 0;
  9012. myrpt->dtmf_time_rem = now;
  9013. return 0;
  9014. }
  9015. /* if too many in buffer, start over */
  9016. if (myrpt->dtmfidx >= MAXDTMF)
  9017. {
  9018. myrpt->dtmfidx = 0;
  9019. myrpt->dtmfbuf[0] = 0;
  9020. myrpt->dtmf_time_rem = now;
  9021. }
  9022. if (c == myrpt->p.funcchar)
  9023. {
  9024. /* if star at beginning, or 2 together, erase buffer */
  9025. if ((myrpt->dtmfidx < 1) ||
  9026. (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
  9027. {
  9028. myrpt->dtmfidx = 0;
  9029. myrpt->dtmfbuf[0] = 0;
  9030. myrpt->dtmf_time_rem = now;
  9031. return 0;
  9032. }
  9033. }
  9034. myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
  9035. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  9036. myrpt->dtmf_time_rem = now;
  9037. src = SOURCE_RMT;
  9038. if (phonemode == 2) src = SOURCE_DPHONE;
  9039. else if (phonemode) src = SOURCE_PHONE;
  9040. else if (phonemode == 4) src = SOURCE_ALT;
  9041. ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
  9042. switch(ret){
  9043. case DC_INDETERMINATE:
  9044. res = 0;
  9045. break;
  9046. case DC_DOKEY:
  9047. if (keyed) *keyed = 1;
  9048. res = 0;
  9049. break;
  9050. case DC_REQ_FLUSH:
  9051. myrpt->dtmfidx = 0;
  9052. myrpt->dtmfbuf[0] = 0;
  9053. res = 0;
  9054. break;
  9055. case DC_COMPLETE:
  9056. res = 1;
  9057. case DC_COMPLETEQUIET:
  9058. myrpt->totalexecdcommands++;
  9059. myrpt->dailyexecdcommands++;
  9060. strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
  9061. myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
  9062. myrpt->dtmfbuf[0] = 0;
  9063. myrpt->dtmfidx = -1;
  9064. myrpt->dtmf_time_rem = 0;
  9065. break;
  9066. case DC_ERROR:
  9067. default:
  9068. myrpt->dtmfbuf[0] = 0;
  9069. myrpt->dtmfidx = -1;
  9070. myrpt->dtmf_time_rem = 0;
  9071. res = 0;
  9072. break;
  9073. }
  9074. return res;
  9075. }
  9076. static int handle_remote_data(struct rpt *myrpt, char *str)
  9077. {
  9078. /* XXX ATTENTION: if you change the size of these arrays you MUST
  9079. * change the limits in corresponding sscanf() calls below. */
  9080. char tmp[300],cmd[300],dest[300],src[300],c;
  9081. int seq,res;
  9082. /* put string in our buffer */
  9083. strncpy(tmp,str,sizeof(tmp) - 1);
  9084. if (!strcmp(tmp,discstr)) return 0;
  9085. if (!strcmp(tmp,newkeystr))
  9086. {
  9087. myrpt->newkey = 1;
  9088. return 0;
  9089. }
  9090. #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
  9091. if (tmp[0] == 'I')
  9092. {
  9093. /* XXX WARNING: be very careful with the limits on the folowing
  9094. * sscanf() call, make sure they match the values defined above */
  9095. if (sscanf(tmp,"%299s %299s %30x",cmd,src,&seq) != 3)
  9096. {
  9097. ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
  9098. return 0;
  9099. }
  9100. mdc1200_notify(myrpt,src,seq);
  9101. return 0;
  9102. }
  9103. #endif
  9104. /* XXX WARNING: be very careful with the limits on the folowing
  9105. * sscanf() call, make sure they match the values defined above */
  9106. if (sscanf(tmp,"%299s %299s %299s %30d %1c",cmd,dest,src,&seq,&c) != 5)
  9107. {
  9108. ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
  9109. return 0;
  9110. }
  9111. if (strcmp(cmd,"D"))
  9112. {
  9113. ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
  9114. return 0;
  9115. }
  9116. /* if not for me, ignore */
  9117. if (strcmp(dest,myrpt->name)) return 0;
  9118. if (myrpt->p.archivedir)
  9119. {
  9120. char dtmfstr[100];
  9121. sprintf(dtmfstr,"DTMF,%c",c);
  9122. donodelog(myrpt,dtmfstr);
  9123. }
  9124. c = func_xlat(myrpt,c,&myrpt->p.outxlat);
  9125. if (!c) return(0);
  9126. res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
  9127. if (res != 1)
  9128. return res;
  9129. rpt_telemetry(myrpt,COMPLETE,NULL);
  9130. return 0;
  9131. }
  9132. static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
  9133. {
  9134. int res;
  9135. if(phonemode == 3) /* simplex phonemode, funcchar key/unkey toggle */
  9136. {
  9137. if (keyed && *keyed && ((c == myrpt->p.funcchar) || (c == myrpt->p.endchar)))
  9138. {
  9139. *keyed = 0; /* UNKEY */
  9140. return 0;
  9141. }
  9142. else if (keyed && !*keyed && (c = myrpt->p.funcchar))
  9143. {
  9144. *keyed = 1; /* KEY */
  9145. return 0;
  9146. }
  9147. }
  9148. else /* endchar unkey */
  9149. {
  9150. if (keyed && *keyed && (c == myrpt->p.endchar))
  9151. {
  9152. *keyed = 0;
  9153. return DC_INDETERMINATE;
  9154. }
  9155. }
  9156. if (myrpt->p.archivedir)
  9157. {
  9158. char str[100];
  9159. sprintf(str,"DTMF(P),%c",c);
  9160. donodelog(myrpt,str);
  9161. }
  9162. res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
  9163. if (res != 1)
  9164. return res;
  9165. rpt_telemetry(myrpt,COMPLETE,NULL);
  9166. return 0;
  9167. }
  9168. static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
  9169. {
  9170. char *val, *s, *s1, *tele;
  9171. char tmp[300], deststr[300] = "";
  9172. char sx[320],*sy;
  9173. val = node_lookup(myrpt,l->name);
  9174. if (!val)
  9175. {
  9176. fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
  9177. return -1;
  9178. }
  9179. rpt_mutex_lock(&myrpt->lock);
  9180. /* remove from queue */
  9181. remque((struct qelem *) l);
  9182. rpt_mutex_unlock(&myrpt->lock);
  9183. strncpy(tmp,val,sizeof(tmp) - 1);
  9184. s = tmp;
  9185. s1 = strsep(&s,",");
  9186. if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
  9187. {
  9188. sy = strchr(s1,'/');
  9189. *sy = 0;
  9190. sprintf(sx,"%s:4569/%s",s1,sy + 1);
  9191. s1 = sx;
  9192. }
  9193. strsep(&s,",");
  9194. snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
  9195. tele = strchr(deststr, '/');
  9196. if (!tele) {
  9197. fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
  9198. return -1;
  9199. }
  9200. *tele++ = 0;
  9201. l->elaptime = 0;
  9202. l->connecttime = 0;
  9203. l->thisconnected = 0;
  9204. l->newkey = 0;
  9205. l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  9206. if (l->chan){
  9207. ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
  9208. ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
  9209. #ifndef NEW_ASTERISK
  9210. l->chan->whentohangup = 0;
  9211. #endif
  9212. l->chan->appl = "Apprpt";
  9213. l->chan->data = "(Remote Rx)";
  9214. if (option_verbose > 2)
  9215. ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
  9216. deststr, tele, l->chan->name);
  9217. l->chan->caller.id.number.valid = 1;
  9218. ast_free(l->chan->caller.id.number.str);
  9219. l->chan->caller.id.number.str = ast_strdup(myrpt->name);
  9220. ast_call(l->chan,tele,999);
  9221. }
  9222. else
  9223. {
  9224. if (option_verbose > 2)
  9225. ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
  9226. deststr,tele,l->chan->name);
  9227. return -1;
  9228. }
  9229. rpt_mutex_lock(&myrpt->lock);
  9230. /* put back in queue */
  9231. insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
  9232. rpt_mutex_unlock(&myrpt->lock);
  9233. ast_log(LOG_WARNING,"Reconnect Attempt to %s in process\n",l->name);
  9234. if (!l->phonemode) send_newkey(l->chan);
  9235. return 0;
  9236. }
  9237. /* 0 return=continue, 1 return = break, -1 return = error */
  9238. static void local_dtmf_helper(struct rpt *myrpt,char c_in)
  9239. {
  9240. int res;
  9241. pthread_attr_t attr;
  9242. char cmd[MAXDTMF+1] = "",c;
  9243. c = c_in & 0x7f;
  9244. if (myrpt->p.archivedir)
  9245. {
  9246. char str[100];
  9247. sprintf(str,"DTMF,MAIN,%c",c);
  9248. donodelog(myrpt,str);
  9249. }
  9250. if (c == myrpt->p.endchar)
  9251. {
  9252. /* if in simple mode, kill autopatch */
  9253. if (myrpt->p.simple && myrpt->callmode)
  9254. {
  9255. if(debug)
  9256. ast_log(LOG_WARNING, "simple mode autopatch kill\n");
  9257. rpt_mutex_lock(&myrpt->lock);
  9258. myrpt->callmode = 0;
  9259. myrpt->macropatch=0;
  9260. channel_revert(myrpt);
  9261. rpt_mutex_unlock(&myrpt->lock);
  9262. rpt_telemetry(myrpt,TERM,NULL);
  9263. return;
  9264. }
  9265. rpt_mutex_lock(&myrpt->lock);
  9266. myrpt->stopgen = 1;
  9267. if (myrpt->cmdnode[0])
  9268. {
  9269. myrpt->cmdnode[0] = 0;
  9270. myrpt->dtmfidx = -1;
  9271. myrpt->dtmfbuf[0] = 0;
  9272. rpt_mutex_unlock(&myrpt->lock);
  9273. rpt_telemetry(myrpt,COMPLETE,NULL);
  9274. return;
  9275. }
  9276. else if(!myrpt->inpadtest)
  9277. {
  9278. rpt_mutex_unlock(&myrpt->lock);
  9279. if (myrpt->p.propagate_phonedtmf)
  9280. do_dtmf_phone(myrpt,NULL,c);
  9281. return;
  9282. }
  9283. else
  9284. rpt_mutex_unlock(&myrpt->lock);
  9285. }
  9286. rpt_mutex_lock(&myrpt->lock);
  9287. if (myrpt->cmdnode[0])
  9288. {
  9289. rpt_mutex_unlock(&myrpt->lock);
  9290. send_link_dtmf(myrpt,c);
  9291. return;
  9292. }
  9293. if (!myrpt->p.simple)
  9294. {
  9295. if ((!myrpt->inpadtest)&&(c == myrpt->p.funcchar))
  9296. {
  9297. myrpt->dtmfidx = 0;
  9298. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  9299. rpt_mutex_unlock(&myrpt->lock);
  9300. time(&myrpt->dtmf_time);
  9301. return;
  9302. }
  9303. else if (((myrpt->inpadtest)||(c != myrpt->p.endchar)) && (myrpt->dtmfidx >= 0))
  9304. {
  9305. time(&myrpt->dtmf_time);
  9306. if (myrpt->dtmfidx < MAXDTMF)
  9307. {
  9308. int src;
  9309. myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
  9310. myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
  9311. strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
  9312. rpt_mutex_unlock(&myrpt->lock);
  9313. src = SOURCE_RPT;
  9314. if (c_in & 0x80) src = SOURCE_ALT;
  9315. res = collect_function_digits(myrpt, cmd, src, NULL);
  9316. rpt_mutex_lock(&myrpt->lock);
  9317. switch(res){
  9318. case DC_INDETERMINATE:
  9319. break;
  9320. case DC_REQ_FLUSH:
  9321. myrpt->dtmfidx = 0;
  9322. myrpt->dtmfbuf[0] = 0;
  9323. break;
  9324. case DC_COMPLETE:
  9325. case DC_COMPLETEQUIET:
  9326. myrpt->totalexecdcommands++;
  9327. myrpt->dailyexecdcommands++;
  9328. strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
  9329. myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
  9330. myrpt->dtmfbuf[0] = 0;
  9331. myrpt->dtmfidx = -1;
  9332. myrpt->dtmf_time = 0;
  9333. break;
  9334. case DC_ERROR:
  9335. default:
  9336. myrpt->dtmfbuf[0] = 0;
  9337. myrpt->dtmfidx = -1;
  9338. myrpt->dtmf_time = 0;
  9339. break;
  9340. }
  9341. if(res != DC_INDETERMINATE) {
  9342. rpt_mutex_unlock(&myrpt->lock);
  9343. return;
  9344. }
  9345. }
  9346. }
  9347. }
  9348. else /* if simple */
  9349. {
  9350. if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
  9351. {
  9352. myrpt->callmode = 1;
  9353. myrpt->patchnoct = 0;
  9354. myrpt->patchquiet = 0;
  9355. myrpt->patchfarenddisconnect = 0;
  9356. myrpt->patchdialtime = 0;
  9357. strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
  9358. myrpt->cidx = 0;
  9359. myrpt->exten[myrpt->cidx] = 0;
  9360. rpt_mutex_unlock(&myrpt->lock);
  9361. pthread_attr_init(&attr);
  9362. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  9363. ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
  9364. return;
  9365. }
  9366. }
  9367. if (myrpt->callmode == 1)
  9368. {
  9369. myrpt->exten[myrpt->cidx++] = c;
  9370. myrpt->exten[myrpt->cidx] = 0;
  9371. /* if this exists */
  9372. if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  9373. {
  9374. /* if this really it, end now */
  9375. if (!ast_matchmore_extension(myrpt->pchannel,myrpt->patchcontext,
  9376. myrpt->exten,1,NULL))
  9377. {
  9378. myrpt->callmode = 2;
  9379. rpt_mutex_unlock(&myrpt->lock);
  9380. if(!myrpt->patchquiet)
  9381. rpt_telemetry(myrpt,PROC,NULL);
  9382. return;
  9383. }
  9384. else /* othewise, reset timer */
  9385. {
  9386. myrpt->calldigittimer = 1;
  9387. }
  9388. }
  9389. /* if can continue, do so */
  9390. if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
  9391. {
  9392. /* call has failed, inform user */
  9393. myrpt->callmode = 4;
  9394. }
  9395. rpt_mutex_unlock(&myrpt->lock);
  9396. return;
  9397. }
  9398. if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
  9399. {
  9400. myrpt->mydtmf = c;
  9401. }
  9402. rpt_mutex_unlock(&myrpt->lock);
  9403. if ((myrpt->dtmfidx < 0) && myrpt->p.propagate_phonedtmf)
  9404. do_dtmf_phone(myrpt,NULL,c);
  9405. return;
  9406. }
  9407. /* place an ID event in the telemetry queue */
  9408. static void queue_id(struct rpt *myrpt)
  9409. {
  9410. if(myrpt->p.idtime){ /* ID time must be non-zero */
  9411. myrpt->mustid = myrpt->tailid = 0;
  9412. myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
  9413. rpt_mutex_unlock(&myrpt->lock);
  9414. rpt_telemetry(myrpt,ID,NULL);
  9415. rpt_mutex_lock(&myrpt->lock);
  9416. }
  9417. }
  9418. /* Scheduler */
  9419. /* must be called locked */
  9420. static void do_scheduler(struct rpt *myrpt)
  9421. {
  9422. int i,res;
  9423. #ifdef NEW_ASTERISK
  9424. struct ast_tm tmnow;
  9425. #else
  9426. struct tm tmnow;
  9427. #endif
  9428. struct ast_variable *skedlist;
  9429. char *strs[5],*vp,*val,value[100];
  9430. memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
  9431. if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
  9432. ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
  9433. /* Try to get close to a 1 second resolution */
  9434. if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
  9435. return;
  9436. rpt_localtime(&myrpt->curtv.tv_sec, &tmnow);
  9437. /* If midnight, then reset all daily statistics */
  9438. if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
  9439. myrpt->dailykeyups = 0;
  9440. myrpt->dailytxtime = 0;
  9441. myrpt->dailykerchunks = 0;
  9442. myrpt->dailyexecdcommands = 0;
  9443. }
  9444. if(tmnow.tm_sec != 0)
  9445. return;
  9446. /* Code below only executes once per minute */
  9447. /* Don't schedule if remote */
  9448. if (myrpt->remote)
  9449. return;
  9450. /* Don't schedule if disabled */
  9451. if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable){
  9452. if(debug > 6)
  9453. ast_log(LOG_NOTICE, "Scheduler disabled\n");
  9454. return;
  9455. }
  9456. if(!myrpt->p.skedstanzaname){ /* No stanza means we do nothing */
  9457. if(debug > 6)
  9458. ast_log(LOG_NOTICE,"No stanza for scheduler in rpt.conf\n");
  9459. return;
  9460. }
  9461. /* get pointer to linked list of scheduler entries */
  9462. skedlist = ast_variable_browse(myrpt->cfg, myrpt->p.skedstanzaname);
  9463. if(debug > 6){
  9464. ast_log(LOG_NOTICE, "Time now: %02d:%02d %02d %02d %02d\n",
  9465. tmnow.tm_hour,tmnow.tm_min,tmnow.tm_mday,tmnow.tm_mon + 1, tmnow.tm_wday);
  9466. }
  9467. /* walk the list */
  9468. for(; skedlist; skedlist = skedlist->next){
  9469. if(debug > 6)
  9470. ast_log(LOG_NOTICE, "Scheduler entry %s = %s being considered\n",skedlist->name, skedlist->value);
  9471. strncpy(value,skedlist->value,99);
  9472. value[99] = 0;
  9473. /* point to the substrings for minute, hour, dom, month, and dow */
  9474. for( i = 0, vp = value ; i < 5; i++){
  9475. if(!*vp)
  9476. break;
  9477. while((*vp == ' ') || (*vp == 0x09)) /* get rid of any leading white space */
  9478. vp++;
  9479. strs[i] = vp; /* save pointer to beginning of substring */
  9480. while((*vp != ' ') && (*vp != 0x09) && (*vp != 0)) /* skip over substring */
  9481. vp++;
  9482. if(*vp)
  9483. *vp++ = 0; /* mark end of substring */
  9484. }
  9485. if(debug > 6)
  9486. ast_log(LOG_NOTICE, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i,
  9487. strs[0], strs[1], strs[2], strs[3], strs[4]);
  9488. if(i == 5){
  9489. if((*strs[0] != '*')&&(atoi(strs[0]) != tmnow.tm_min))
  9490. continue;
  9491. if((*strs[1] != '*')&&(atoi(strs[1]) != tmnow.tm_hour))
  9492. continue;
  9493. if((*strs[2] != '*')&&(atoi(strs[2]) != tmnow.tm_mday))
  9494. continue;
  9495. if((*strs[3] != '*')&&(atoi(strs[3]) != tmnow.tm_mon + 1))
  9496. continue;
  9497. if(atoi(strs[4]) == 7)
  9498. strs[4] = "0";
  9499. if((*strs[4] != '*')&&(atoi(strs[4]) != tmnow.tm_wday))
  9500. continue;
  9501. if(debug)
  9502. ast_log(LOG_NOTICE, "Executing scheduler entry %s = %s\n", skedlist->name, skedlist->value);
  9503. if(atoi(skedlist->name) == 0)
  9504. return; /* Zero is reserved for the startup macro */
  9505. val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, skedlist->name);
  9506. if (!val){
  9507. ast_log(LOG_WARNING,"Scheduler could not find macro %s\n",skedlist->name);
  9508. return; /* Macro not found */
  9509. }
  9510. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val)){
  9511. ast_log(LOG_WARNING, "Scheduler could not execute macro %s: Macro buffer full\n",
  9512. skedlist->name);
  9513. return; /* Macro buffer full */
  9514. }
  9515. myrpt->macrotimer = MACROTIME;
  9516. strncat(myrpt->macrobuf,val,MAXMACRO - 1);
  9517. }
  9518. else{
  9519. ast_log(LOG_WARNING,"Malformed scheduler entry in rpt.conf: %s = %s\n",
  9520. skedlist->name, skedlist->value);
  9521. }
  9522. }
  9523. }
  9524. /* single thread with one file (request) to dial */
  9525. static void *rpt(void *this)
  9526. {
  9527. struct rpt *myrpt = (struct rpt *)this;
  9528. char *tele,*idtalkover,c,myfirst,*p;
  9529. int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued;
  9530. int tailmessagequeued,ctqueued,dtmfed,lastmyrx,localmsgqueued;
  9531. struct ast_channel *who;
  9532. struct dahdi_confinfo ci; /* conference info */
  9533. time_t t;
  9534. struct rpt_link *l,*m;
  9535. struct rpt_tele *telem;
  9536. char tmpstr[300],lstr[MAXLINKLIST];
  9537. if (myrpt->p.archivedir) mkdir(myrpt->p.archivedir,0600);
  9538. sprintf(tmpstr,"%s/%s",myrpt->p.archivedir,myrpt->name);
  9539. mkdir(tmpstr,0600);
  9540. rpt_mutex_lock(&myrpt->lock);
  9541. telem = myrpt->tele.next;
  9542. while(telem != &myrpt->tele)
  9543. {
  9544. ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
  9545. telem = telem->next;
  9546. }
  9547. rpt_mutex_unlock(&myrpt->lock);
  9548. /* find our index, and load the vars initially */
  9549. for(i = 0; i < nrpts; i++)
  9550. {
  9551. if (&rpt_vars[i] == myrpt)
  9552. {
  9553. load_rpt_vars(i,0);
  9554. break;
  9555. }
  9556. }
  9557. rpt_mutex_lock(&myrpt->lock);
  9558. while(myrpt->xlink)
  9559. {
  9560. myrpt->xlink = 3;
  9561. rpt_mutex_unlock(&myrpt->lock);
  9562. usleep(100000);
  9563. rpt_mutex_lock(&myrpt->lock);
  9564. }
  9565. #ifdef HAVE_IOPERM
  9566. if ((!strcmp(myrpt->remoterig, remote_rig_rbi)) &&
  9567. (ioperm(myrpt->p.iobase,1,1) == -1))
  9568. {
  9569. rpt_mutex_unlock(&myrpt->lock);
  9570. ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
  9571. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9572. pthread_exit(NULL);
  9573. }
  9574. #endif
  9575. strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
  9576. tele = strchr(tmpstr,'/');
  9577. if (!tele)
  9578. {
  9579. fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
  9580. rpt_mutex_unlock(&myrpt->lock);
  9581. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9582. pthread_exit(NULL);
  9583. }
  9584. *tele++ = 0;
  9585. myrpt->rxchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  9586. myrpt->dahdirxchannel = NULL;
  9587. if (!strcasecmp(tmpstr,"DAHDI"))
  9588. myrpt->dahdirxchannel = myrpt->rxchannel;
  9589. if (myrpt->rxchannel)
  9590. {
  9591. if (myrpt->rxchannel->_state == AST_STATE_BUSY)
  9592. {
  9593. fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
  9594. rpt_mutex_unlock(&myrpt->lock);
  9595. ast_hangup(myrpt->rxchannel);
  9596. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9597. pthread_exit(NULL);
  9598. }
  9599. ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
  9600. ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
  9601. #ifdef AST_CDR_FLAG_POST_DISABLED
  9602. if (myrpt->rxchannel->cdr)
  9603. ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9604. #endif
  9605. #ifndef NEW_ASTERISK
  9606. myrpt->rxchannel->whentohangup = 0;
  9607. #endif
  9608. myrpt->rxchannel->appl = "Apprpt";
  9609. myrpt->rxchannel->data = "(Repeater Rx)";
  9610. if (option_verbose > 2)
  9611. ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
  9612. tmpstr,tele,myrpt->rxchannel->name);
  9613. ast_call(myrpt->rxchannel,tele,999);
  9614. if (myrpt->rxchannel->_state != AST_STATE_UP)
  9615. {
  9616. rpt_mutex_unlock(&myrpt->lock);
  9617. ast_hangup(myrpt->rxchannel);
  9618. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9619. pthread_exit(NULL);
  9620. }
  9621. }
  9622. else
  9623. {
  9624. fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
  9625. rpt_mutex_unlock(&myrpt->lock);
  9626. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9627. pthread_exit(NULL);
  9628. }
  9629. myrpt->dahditxchannel = NULL;
  9630. if (myrpt->txchanname)
  9631. {
  9632. strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
  9633. tele = strchr(tmpstr,'/');
  9634. if (!tele)
  9635. {
  9636. fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
  9637. rpt_mutex_unlock(&myrpt->lock);
  9638. ast_hangup(myrpt->rxchannel);
  9639. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9640. pthread_exit(NULL);
  9641. }
  9642. *tele++ = 0;
  9643. myrpt->txchannel = ast_request(tmpstr, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  9644. if (!strcasecmp(tmpstr,"DAHDI"))
  9645. myrpt->dahditxchannel = myrpt->txchannel;
  9646. if (myrpt->txchannel)
  9647. {
  9648. if (myrpt->txchannel->_state == AST_STATE_BUSY)
  9649. {
  9650. fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
  9651. rpt_mutex_unlock(&myrpt->lock);
  9652. ast_hangup(myrpt->txchannel);
  9653. ast_hangup(myrpt->rxchannel);
  9654. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9655. pthread_exit(NULL);
  9656. }
  9657. ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
  9658. ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
  9659. #ifdef AST_CDR_FLAG_POST_DISABLED
  9660. if (myrpt->txchannel->cdr)
  9661. ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9662. #endif
  9663. #ifndef NEW_ASTERISK
  9664. myrpt->txchannel->whentohangup = 0;
  9665. #endif
  9666. myrpt->txchannel->appl = "Apprpt";
  9667. myrpt->txchannel->data = "(Repeater Tx)";
  9668. if (option_verbose > 2)
  9669. ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
  9670. tmpstr,tele,myrpt->txchannel->name);
  9671. ast_call(myrpt->txchannel,tele,999);
  9672. if (myrpt->rxchannel->_state != AST_STATE_UP)
  9673. {
  9674. rpt_mutex_unlock(&myrpt->lock);
  9675. ast_hangup(myrpt->rxchannel);
  9676. ast_hangup(myrpt->txchannel);
  9677. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9678. pthread_exit(NULL);
  9679. }
  9680. }
  9681. else
  9682. {
  9683. fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
  9684. rpt_mutex_unlock(&myrpt->lock);
  9685. ast_hangup(myrpt->rxchannel);
  9686. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9687. pthread_exit(NULL);
  9688. }
  9689. }
  9690. else
  9691. {
  9692. myrpt->txchannel = myrpt->rxchannel;
  9693. if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
  9694. myrpt->dahditxchannel = myrpt->txchannel;
  9695. }
  9696. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
  9697. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
  9698. /* allocate a pseudo-channel thru asterisk */
  9699. myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9700. if (!myrpt->pchannel)
  9701. {
  9702. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9703. rpt_mutex_unlock(&myrpt->lock);
  9704. if (myrpt->txchannel != myrpt->rxchannel)
  9705. ast_hangup(myrpt->txchannel);
  9706. ast_hangup(myrpt->rxchannel);
  9707. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9708. pthread_exit(NULL);
  9709. }
  9710. #ifdef AST_CDR_FLAG_POST_DISABLED
  9711. if (myrpt->pchannel->cdr)
  9712. ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9713. #endif
  9714. if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
  9715. if (!myrpt->dahditxchannel)
  9716. {
  9717. /* allocate a pseudo-channel thru asterisk */
  9718. myrpt->dahditxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9719. if (!myrpt->dahditxchannel)
  9720. {
  9721. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9722. rpt_mutex_unlock(&myrpt->lock);
  9723. if (myrpt->txchannel != myrpt->rxchannel)
  9724. ast_hangup(myrpt->txchannel);
  9725. ast_hangup(myrpt->rxchannel);
  9726. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9727. pthread_exit(NULL);
  9728. }
  9729. ast_set_read_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
  9730. ast_set_write_format(myrpt->dahditxchannel,AST_FORMAT_SLINEAR);
  9731. #ifdef AST_CDR_FLAG_POST_DISABLED
  9732. if (myrpt->dahditxchannel->cdr)
  9733. ast_set_flag(myrpt->dahditxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9734. #endif
  9735. }
  9736. /* allocate a pseudo-channel thru asterisk */
  9737. myrpt->monchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9738. if (!myrpt->monchannel)
  9739. {
  9740. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9741. rpt_mutex_unlock(&myrpt->lock);
  9742. if (myrpt->txchannel != myrpt->rxchannel)
  9743. ast_hangup(myrpt->txchannel);
  9744. ast_hangup(myrpt->rxchannel);
  9745. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9746. pthread_exit(NULL);
  9747. }
  9748. ast_set_read_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
  9749. ast_set_write_format(myrpt->monchannel,AST_FORMAT_SLINEAR);
  9750. #ifdef AST_CDR_FLAG_POST_DISABLED
  9751. if (myrpt->monchannel->cdr)
  9752. ast_set_flag(myrpt->monchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9753. #endif
  9754. /* make a conference for the tx */
  9755. ci.chan = 0;
  9756. ci.confno = -1; /* make a new conf */
  9757. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER;
  9758. /* first put the channel on the conference in proper mode */
  9759. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  9760. {
  9761. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  9762. rpt_mutex_unlock(&myrpt->lock);
  9763. ast_hangup(myrpt->pchannel);
  9764. ast_hangup(myrpt->monchannel);
  9765. if (myrpt->txchannel != myrpt->rxchannel)
  9766. ast_hangup(myrpt->txchannel);
  9767. ast_hangup(myrpt->rxchannel);
  9768. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9769. pthread_exit(NULL);
  9770. }
  9771. /* save tx conference number */
  9772. myrpt->txconf = ci.confno;
  9773. /* make a conference for the pseudo */
  9774. ci.chan = 0;
  9775. ci.confno = -1; /* make a new conf */
  9776. ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? DAHDI_CONF_CONFANNMON :
  9777. (DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER);
  9778. /* first put the channel on the conference in announce mode */
  9779. if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  9780. {
  9781. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  9782. rpt_mutex_unlock(&myrpt->lock);
  9783. ast_hangup(myrpt->pchannel);
  9784. ast_hangup(myrpt->monchannel);
  9785. if (myrpt->txchannel != myrpt->rxchannel)
  9786. ast_hangup(myrpt->txchannel);
  9787. ast_hangup(myrpt->rxchannel);
  9788. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9789. pthread_exit(NULL);
  9790. }
  9791. /* save pseudo channel conference number */
  9792. myrpt->conf = ci.confno;
  9793. /* make a conference for the pseudo */
  9794. ci.chan = 0;
  9795. if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
  9796. (myrpt->dahditxchannel == myrpt->txchannel))
  9797. {
  9798. /* get tx channel's port number */
  9799. if (ioctl(myrpt->txchannel->fds[0],DAHDI_CHANNO,&ci.confno) == -1)
  9800. {
  9801. ast_log(LOG_WARNING, "Unable to set tx channel's chan number\n");
  9802. rpt_mutex_unlock(&myrpt->lock);
  9803. ast_hangup(myrpt->pchannel);
  9804. ast_hangup(myrpt->monchannel);
  9805. if (myrpt->txchannel != myrpt->rxchannel)
  9806. ast_hangup(myrpt->txchannel);
  9807. ast_hangup(myrpt->rxchannel);
  9808. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9809. pthread_exit(NULL);
  9810. }
  9811. ci.confmode = DAHDI_CONF_MONITORTX;
  9812. }
  9813. else
  9814. {
  9815. ci.confno = myrpt->txconf;
  9816. ci.confmode = DAHDI_CONF_CONFANNMON;
  9817. }
  9818. /* first put the channel on the conference in announce mode */
  9819. if (ioctl(myrpt->monchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  9820. {
  9821. ast_log(LOG_WARNING, "Unable to set conference mode for monitor\n");
  9822. rpt_mutex_unlock(&myrpt->lock);
  9823. ast_hangup(myrpt->pchannel);
  9824. ast_hangup(myrpt->monchannel);
  9825. if (myrpt->txchannel != myrpt->rxchannel)
  9826. ast_hangup(myrpt->txchannel);
  9827. ast_hangup(myrpt->rxchannel);
  9828. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9829. pthread_exit(NULL);
  9830. }
  9831. /* allocate a pseudo-channel thru asterisk */
  9832. myrpt->parrotchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9833. if (!myrpt->parrotchannel)
  9834. {
  9835. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9836. rpt_mutex_unlock(&myrpt->lock);
  9837. if (myrpt->txchannel != myrpt->rxchannel)
  9838. ast_hangup(myrpt->txchannel);
  9839. ast_hangup(myrpt->rxchannel);
  9840. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9841. pthread_exit(NULL);
  9842. }
  9843. ast_set_read_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
  9844. ast_set_write_format(myrpt->parrotchannel,AST_FORMAT_SLINEAR);
  9845. #ifdef AST_CDR_FLAG_POST_DISABLED
  9846. if (myrpt->parrotchannel->cdr)
  9847. ast_set_flag(myrpt->parrotchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9848. #endif
  9849. /* allocate a pseudo-channel thru asterisk */
  9850. myrpt->voxchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9851. if (!myrpt->voxchannel)
  9852. {
  9853. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9854. rpt_mutex_unlock(&myrpt->lock);
  9855. if (myrpt->txchannel != myrpt->rxchannel)
  9856. ast_hangup(myrpt->txchannel);
  9857. ast_hangup(myrpt->rxchannel);
  9858. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9859. pthread_exit(NULL);
  9860. }
  9861. ast_set_read_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
  9862. ast_set_write_format(myrpt->voxchannel,AST_FORMAT_SLINEAR);
  9863. #ifdef AST_CDR_FLAG_POST_DISABLED
  9864. if (myrpt->voxchannel->cdr)
  9865. ast_set_flag(myrpt->voxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9866. #endif
  9867. /* allocate a pseudo-channel thru asterisk */
  9868. myrpt->txpchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  9869. if (!myrpt->txpchannel)
  9870. {
  9871. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  9872. rpt_mutex_unlock(&myrpt->lock);
  9873. ast_hangup(myrpt->pchannel);
  9874. ast_hangup(myrpt->monchannel);
  9875. if (myrpt->txchannel != myrpt->rxchannel)
  9876. ast_hangup(myrpt->txchannel);
  9877. ast_hangup(myrpt->rxchannel);
  9878. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9879. pthread_exit(NULL);
  9880. }
  9881. #ifdef AST_CDR_FLAG_POST_DISABLED
  9882. if (myrpt->txpchannel->cdr)
  9883. ast_set_flag(myrpt->txpchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  9884. #endif
  9885. /* make a conference for the tx */
  9886. ci.chan = 0;
  9887. ci.confno = myrpt->txconf;
  9888. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER ;
  9889. /* first put the channel on the conference in proper mode */
  9890. if (ioctl(myrpt->txpchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  9891. {
  9892. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  9893. rpt_mutex_unlock(&myrpt->lock);
  9894. ast_hangup(myrpt->txpchannel);
  9895. ast_hangup(myrpt->monchannel);
  9896. if (myrpt->txchannel != myrpt->rxchannel)
  9897. ast_hangup(myrpt->txchannel);
  9898. ast_hangup(myrpt->rxchannel);
  9899. myrpt->rpt_thread = AST_PTHREADT_STOP;
  9900. pthread_exit(NULL);
  9901. }
  9902. /* if serial io port, open it */
  9903. myrpt->iofd = -1;
  9904. if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
  9905. {
  9906. ast_log(LOG_ERROR, "Unable to open %s\n",myrpt->p.ioport);
  9907. rpt_mutex_unlock(&myrpt->lock);
  9908. ast_hangup(myrpt->pchannel);
  9909. if (myrpt->txchannel != myrpt->rxchannel)
  9910. ast_hangup(myrpt->txchannel);
  9911. ast_hangup(myrpt->rxchannel);
  9912. pthread_exit(NULL);
  9913. }
  9914. /* Now, the idea here is to copy from the physical rx channel buffer
  9915. into the pseudo tx buffer, and from the pseudo rx buffer into the
  9916. tx channel buffer */
  9917. myrpt->links.next = &myrpt->links;
  9918. myrpt->links.prev = &myrpt->links;
  9919. myrpt->tailtimer = 0;
  9920. myrpt->totimer = 0;
  9921. myrpt->tmsgtimer = myrpt->p.tailmessagetime;
  9922. myrpt->idtimer = myrpt->p.politeid;
  9923. myrpt->mustid = myrpt->tailid = 0;
  9924. myrpt->callmode = 0;
  9925. myrpt->tounkeyed = 0;
  9926. myrpt->tonotify = 0;
  9927. myrpt->retxtimer = 0;
  9928. myrpt->rerxtimer = 0;
  9929. myrpt->skedtimer = 0;
  9930. myrpt->tailevent = 0;
  9931. lasttx = 0;
  9932. myrpt->keyed = 0;
  9933. myrpt->txkeyed = 0;
  9934. time(&myrpt->lastkeyedtime);
  9935. myrpt->lastkeyedtime -= RPT_LOCKOUT_SECS;
  9936. time(&myrpt->lasttxkeyedtime);
  9937. myrpt->lasttxkeyedtime -= RPT_LOCKOUT_SECS;
  9938. idtalkover = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
  9939. myrpt->dtmfidx = -1;
  9940. myrpt->dtmfbuf[0] = 0;
  9941. myrpt->rem_dtmfidx = -1;
  9942. myrpt->rem_dtmfbuf[0] = 0;
  9943. myrpt->dtmf_time = 0;
  9944. myrpt->rem_dtmf_time = 0;
  9945. myrpt->inpadtest = 0;
  9946. myrpt->disgorgetime = 0;
  9947. myrpt->lastnodewhichkeyedusup[0] = '\0';
  9948. myrpt->dailytxtime = 0;
  9949. myrpt->totaltxtime = 0;
  9950. myrpt->dailykeyups = 0;
  9951. myrpt->totalkeyups = 0;
  9952. myrpt->dailykerchunks = 0;
  9953. myrpt->totalkerchunks = 0;
  9954. myrpt->dailyexecdcommands = 0;
  9955. myrpt->totalexecdcommands = 0;
  9956. myrpt->timeouts = 0;
  9957. myrpt->exten[0] = '\0';
  9958. myrpt->lastdtmfcommand[0] = '\0';
  9959. voxinit_rpt(myrpt,1);
  9960. myrpt->wasvox = 0;
  9961. if (myrpt->p.startupmacro)
  9962. {
  9963. snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
  9964. }
  9965. rpt_mutex_unlock(&myrpt->lock);
  9966. val = 1;
  9967. ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
  9968. val = 1;
  9969. ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
  9970. if (myrpt->p.archivedir) donodelog(myrpt,"STARTUP");
  9971. dtmfed = 0;
  9972. if (myrpt->remoterig && !ISRIG_RTX(myrpt->remoterig)) setrem(myrpt);
  9973. lastmyrx = 0;
  9974. myfirst = 0;
  9975. while (ms >= 0)
  9976. {
  9977. struct ast_frame *f,*f1,*f2;
  9978. struct ast_channel *cs[300],*cs1[300];
  9979. int totx=0,elap=0,n,x,toexit=0;
  9980. /* DEBUG Dump */
  9981. if((myrpt->disgorgetime) && (time(NULL) >= myrpt->disgorgetime)){
  9982. struct rpt_link *dl;
  9983. struct rpt_tele *dt;
  9984. myrpt->disgorgetime = 0;
  9985. ast_log(LOG_NOTICE,"********** Variable Dump Start (app_rpt) **********\n");
  9986. ast_log(LOG_NOTICE,"totx = %d\n",totx);
  9987. ast_log(LOG_NOTICE,"remrx = %d\n",remrx);
  9988. ast_log(LOG_NOTICE,"lasttx = %d\n",lasttx);
  9989. ast_log(LOG_NOTICE,"elap = %d\n",elap);
  9990. ast_log(LOG_NOTICE,"toexit = %d\n",toexit);
  9991. ast_log(LOG_NOTICE,"myrpt->keyed = %d\n",myrpt->keyed);
  9992. ast_log(LOG_NOTICE,"myrpt->localtx = %d\n",myrpt->localtx);
  9993. ast_log(LOG_NOTICE,"myrpt->callmode = %d\n",myrpt->callmode);
  9994. ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
  9995. ast_log(LOG_NOTICE,"myrpt->tounkeyed = %d\n",myrpt->tounkeyed);
  9996. ast_log(LOG_NOTICE,"myrpt->tonotify = %d\n",myrpt->tonotify);
  9997. ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
  9998. ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
  9999. ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
  10000. ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
  10001. dl = myrpt->links.next;
  10002. while(dl != &myrpt->links){
  10003. ast_log(LOG_NOTICE,"*** Link Name: %s ***\n",dl->name);
  10004. ast_log(LOG_NOTICE," link->lasttx %d\n",dl->lasttx);
  10005. ast_log(LOG_NOTICE," link->lastrx %d\n",dl->lastrx);
  10006. ast_log(LOG_NOTICE," link->connected %d\n",dl->connected);
  10007. ast_log(LOG_NOTICE," link->hasconnected %d\n",dl->hasconnected);
  10008. ast_log(LOG_NOTICE," link->outbound %d\n",dl->outbound);
  10009. ast_log(LOG_NOTICE," link->disced %d\n",dl->disced);
  10010. ast_log(LOG_NOTICE," link->killme %d\n",dl->killme);
  10011. ast_log(LOG_NOTICE," link->disctime %ld\n",dl->disctime);
  10012. ast_log(LOG_NOTICE," link->retrytimer %ld\n",dl->retrytimer);
  10013. ast_log(LOG_NOTICE," link->retries = %d\n",dl->retries);
  10014. ast_log(LOG_NOTICE," link->reconnects = %d\n",dl->reconnects);
  10015. ast_log(LOG_NOTICE," link->newkey = %d\n",dl->newkey);
  10016. dl = dl->next;
  10017. }
  10018. dt = myrpt->tele.next;
  10019. if(dt != &myrpt->tele)
  10020. ast_log(LOG_NOTICE,"*** Telemetry Queue ***\n");
  10021. while(dt != &myrpt->tele){
  10022. ast_log(LOG_NOTICE," Telemetry mode: %d\n",dt->mode);
  10023. dt = dt->next;
  10024. }
  10025. ast_log(LOG_NOTICE,"******* Variable Dump End (app_rpt) *******\n");
  10026. }
  10027. if (myrpt->reload)
  10028. {
  10029. struct rpt_tele *inner_telem;
  10030. rpt_mutex_lock(&myrpt->lock);
  10031. inner_telem = myrpt->tele.next;
  10032. while(inner_telem != &myrpt->tele)
  10033. {
  10034. ast_softhangup(inner_telem->chan,AST_SOFTHANGUP_DEV);
  10035. inner_telem = inner_telem->next;
  10036. }
  10037. myrpt->reload = 0;
  10038. rpt_mutex_unlock(&myrpt->lock);
  10039. usleep(10000);
  10040. /* find our index, and load the vars */
  10041. for(i = 0; i < nrpts; i++)
  10042. {
  10043. if (&rpt_vars[i] == myrpt)
  10044. {
  10045. load_rpt_vars(i,0);
  10046. break;
  10047. }
  10048. }
  10049. }
  10050. rpt_mutex_lock(&myrpt->lock);
  10051. if (ast_check_hangup(myrpt->rxchannel)) break;
  10052. if (ast_check_hangup(myrpt->txchannel)) break;
  10053. if (ast_check_hangup(myrpt->pchannel)) break;
  10054. if (ast_check_hangup(myrpt->monchannel)) break;
  10055. if (myrpt->parrotchannel &&
  10056. ast_check_hangup(myrpt->parrotchannel)) break;
  10057. if (myrpt->voxchannel &&
  10058. ast_check_hangup(myrpt->voxchannel)) break;
  10059. if (ast_check_hangup(myrpt->txpchannel)) break;
  10060. if (myrpt->dahditxchannel && ast_check_hangup(myrpt->dahditxchannel)) break;
  10061. /* Set local tx with keyed */
  10062. myrpt->localtx = myrpt->keyed;
  10063. /* If someone's connected, and they're transmitting from their end to us, set remrx true */
  10064. l = myrpt->links.next;
  10065. remrx = 0;
  10066. while(l != &myrpt->links)
  10067. {
  10068. if (l->lastrx){
  10069. remrx = 1;
  10070. if(l->name[0] != '0') /* Ignore '0' nodes */
  10071. strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */
  10072. }
  10073. l = l->next;
  10074. }
  10075. /* Create a "must_id" flag for the cleanup ID */
  10076. if(myrpt->p.idtime) /* ID time must be non-zero */
  10077. myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
  10078. /* Build a fresh totx from myrpt->keyed and autopatch activated */
  10079. /* If full duplex, add local tx to totx */
  10080. if (myrpt->p.duplex > 1)
  10081. {
  10082. totx = myrpt->callmode;
  10083. totx = totx || myrpt->localtx;
  10084. }
  10085. else
  10086. {
  10087. int myrx = myrpt->localtx || remrx || (!myrpt->callmode);
  10088. if (lastmyrx != myrx)
  10089. {
  10090. voxinit_rpt(myrpt,!myrx);
  10091. lastmyrx = myrx;
  10092. }
  10093. totx = 0;
  10094. if (myrpt->callmode && (myrpt->voxtotimer <= 0))
  10095. {
  10096. if (myrpt->voxtostate)
  10097. {
  10098. myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
  10099. myrpt->voxtostate = 0;
  10100. }
  10101. else
  10102. {
  10103. myrpt->voxtotimer = myrpt->p.voxrecover_ms;
  10104. myrpt->voxtostate = 1;
  10105. }
  10106. }
  10107. if (!myrpt->voxtostate)
  10108. totx = myrpt->callmode && myrpt->wasvox;
  10109. }
  10110. /* Traverse the telemetry list to see what's queued */
  10111. identqueued = 0;
  10112. localmsgqueued = 0;
  10113. othertelemqueued = 0;
  10114. tailmessagequeued = 0;
  10115. ctqueued = 0;
  10116. telem = myrpt->tele.next;
  10117. while(telem != &myrpt->tele)
  10118. {
  10119. if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
  10120. identqueued = 1; /* Identification telemetry */
  10121. }
  10122. else if(telem->mode == TAILMSG)
  10123. {
  10124. tailmessagequeued = 1; /* Tail message telemetry */
  10125. }
  10126. else if(telem->mode == STATS_TIME_LOCAL)
  10127. {
  10128. localmsgqueued = 1; /* Local message */
  10129. }
  10130. else
  10131. {
  10132. if ((telem->mode != UNKEY) && (telem->mode != LINKUNKEY))
  10133. othertelemqueued = 1; /* Other telemetry */
  10134. else
  10135. ctqueued = 1; /* Courtesy tone telemetry */
  10136. }
  10137. telem = telem->next;
  10138. }
  10139. /* Add in any "other" telemetry, unless specified otherwise */
  10140. if (!myrpt->p.notelemtx) totx = totx || othertelemqueued;
  10141. /* Update external (to links) transmitter PTT state with everything but */
  10142. /* ID, CT, local messages, and tailmessage telemetry */
  10143. myrpt->exttx = totx;
  10144. totx = totx || myrpt->dtmf_local_timer;
  10145. /* If half or 3/4 duplex, add localtx to external link tx */
  10146. if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
  10147. /* Add in ID telemetry to local transmitter */
  10148. totx = totx || remrx;
  10149. /* If 3/4 or full duplex, add in ident, CT telemetry, and local messages */
  10150. if (myrpt->p.duplex > 0)
  10151. totx = totx || identqueued || ctqueued || localmsgqueued;
  10152. /* If full duplex, add local dtmf stuff active */
  10153. if (myrpt->p.duplex > 1)
  10154. {
  10155. totx = totx || (myrpt->dtmfidx > -1) ||
  10156. myrpt->cmdnode[0];
  10157. }
  10158. /* add in parrot stuff */
  10159. totx = totx || (myrpt->parrotstate > 1);
  10160. /* Reset time out timer variables if there is no activity */
  10161. if (!totx)
  10162. {
  10163. myrpt->totimer = myrpt->p.totime;
  10164. myrpt->tounkeyed = 0;
  10165. myrpt->tonotify = 0;
  10166. }
  10167. else{
  10168. myrpt->tailtimer = myrpt->p.s[myrpt->p.sysstate_cur].alternatetail ?
  10169. myrpt->p.althangtime : /* Initialize tail timer */
  10170. myrpt->p.hangtime;
  10171. }
  10172. /* Disable the local transmitter if we are timed out */
  10173. totx = totx && myrpt->totimer;
  10174. /* if timed-out and not said already, say it */
  10175. if ((!myrpt->totimer) && (!myrpt->tonotify))
  10176. {
  10177. myrpt->tonotify = 1;
  10178. myrpt->timeouts++;
  10179. rpt_mutex_unlock(&myrpt->lock);
  10180. rpt_telemetry(myrpt,TIMEOUT,NULL);
  10181. rpt_mutex_lock(&myrpt->lock);
  10182. }
  10183. /* If unkey and re-key, reset time out timer */
  10184. if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
  10185. {
  10186. myrpt->tounkeyed = 1;
  10187. }
  10188. if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
  10189. {
  10190. myrpt->totimer = myrpt->p.totime;
  10191. myrpt->tounkeyed = 0;
  10192. myrpt->tonotify = 0;
  10193. rpt_mutex_unlock(&myrpt->lock);
  10194. continue;
  10195. }
  10196. /* if timed-out and in circuit busy after call */
  10197. if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
  10198. {
  10199. if(debug)
  10200. ast_log(LOG_NOTICE, "timed-out and in circuit busy after call\n");
  10201. myrpt->callmode = 0;
  10202. myrpt->macropatch=0;
  10203. channel_revert(myrpt);
  10204. }
  10205. /* get rid of tail if timed out */
  10206. if (!myrpt->totimer) myrpt->tailtimer = 0;
  10207. /* if not timed-out, add in tail */
  10208. if (myrpt->totimer) totx = totx || myrpt->tailtimer;
  10209. /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
  10210. /* If tail message, kill the message if someone keys up over it */
  10211. if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) {
  10212. int hasid = 0,hastalkover = 0;
  10213. telem = myrpt->tele.next;
  10214. while(telem != &myrpt->tele){
  10215. if(telem->mode == ID){
  10216. if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
  10217. hasid = 1;
  10218. }
  10219. if(telem->mode == TAILMSG){
  10220. if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
  10221. }
  10222. if (telem->mode == IDTALKOVER) hastalkover = 1;
  10223. telem = telem->next;
  10224. }
  10225. rpt_mutex_unlock(&myrpt->lock);
  10226. if (hasid && (!hastalkover)) rpt_telemetry(myrpt, IDTALKOVER, NULL); /* Start Talkover ID */
  10227. rpt_mutex_lock(&myrpt->lock);
  10228. }
  10229. /* Try to be polite */
  10230. /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
  10231. /* If within 30 seconds of the time to ID, try do it in the tail */
  10232. /* else if at ID time limit, do it right over the top of them */
  10233. /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
  10234. if(myrpt->mustid && (!myrpt->idtimer))
  10235. queue_id(myrpt);
  10236. if ((myrpt->p.idtime && totx && (!myrpt->exttx) &&
  10237. (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer)) /* ID time must be non-zero */
  10238. {
  10239. myrpt->tailid = 1;
  10240. }
  10241. /* If tail timer expires, then check for tail messages */
  10242. if(myrpt->tailevent){
  10243. myrpt->tailevent = 0;
  10244. if(myrpt->tailid){
  10245. totx = 1;
  10246. queue_id(myrpt);
  10247. }
  10248. else if ((myrpt->p.tailmessages[0]) &&
  10249. (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
  10250. totx = 1;
  10251. myrpt->tmsgtimer = myrpt->p.tailmessagetime;
  10252. rpt_mutex_unlock(&myrpt->lock);
  10253. rpt_telemetry(myrpt, TAILMSG, NULL);
  10254. rpt_mutex_lock(&myrpt->lock);
  10255. }
  10256. }
  10257. /* Main TX control */
  10258. /* let telemetry transmit anyway (regardless of timeout) */
  10259. if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
  10260. totx = totx && !myrpt->p.s[myrpt->p.sysstate_cur].txdisable;
  10261. myrpt->txrealkeyed = totx;
  10262. totx = totx || (!AST_LIST_EMPTY(&myrpt->txq));
  10263. if (totx && (!lasttx))
  10264. {
  10265. char mydate[100],myfname[100];
  10266. time_t myt;
  10267. if (myrpt->monstream) ast_closestream(myrpt->monstream);
  10268. if (myrpt->p.archivedir)
  10269. {
  10270. long blocksleft;
  10271. time(&myt);
  10272. strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
  10273. localtime(&myt));
  10274. sprintf(myfname,"%s/%s/%s",myrpt->p.archivedir,
  10275. myrpt->name,mydate);
  10276. myrpt->monstream = ast_writefile(myfname,"wav49",
  10277. "app_rpt Air Archive",O_CREAT | O_APPEND,0,0600);
  10278. if (myrpt->p.monminblocks)
  10279. {
  10280. blocksleft = diskavail(myrpt);
  10281. if (blocksleft >= myrpt->p.monminblocks)
  10282. donodelog(myrpt,"TXKEY,MAIN");
  10283. } else donodelog(myrpt,"TXKEY,MAIN");
  10284. }
  10285. lasttx = 1;
  10286. myrpt->txkeyed = 1;
  10287. time(&myrpt->lasttxkeyedtime);
  10288. myrpt->dailykeyups++;
  10289. myrpt->totalkeyups++;
  10290. rpt_mutex_unlock(&myrpt->lock);
  10291. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
  10292. rpt_mutex_lock(&myrpt->lock);
  10293. }
  10294. if ((!totx) && lasttx)
  10295. {
  10296. if (myrpt->monstream) ast_closestream(myrpt->monstream);
  10297. myrpt->monstream = NULL;
  10298. lasttx = 0;
  10299. myrpt->txkeyed = 0;
  10300. time(&myrpt->lasttxkeyedtime);
  10301. rpt_mutex_unlock(&myrpt->lock);
  10302. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
  10303. rpt_mutex_lock(&myrpt->lock);
  10304. donodelog(myrpt,"TXUNKEY,MAIN");
  10305. }
  10306. time(&t);
  10307. /* if DTMF timeout */
  10308. if ((!myrpt->cmdnode[0]) && (myrpt->dtmfidx >= 0) && ((myrpt->dtmf_time + DTMF_TIMEOUT) < t))
  10309. {
  10310. myrpt->inpadtest = 0;
  10311. myrpt->dtmfidx = -1;
  10312. myrpt->dtmfbuf[0] = 0;
  10313. }
  10314. /* if remote DTMF timeout */
  10315. if ((myrpt->rem_dtmfidx >= 0) && ((myrpt->rem_dtmf_time + DTMF_TIMEOUT) < t))
  10316. {
  10317. myrpt->inpadtest = 0;
  10318. myrpt->rem_dtmfidx = -1;
  10319. myrpt->rem_dtmfbuf[0] = 0;
  10320. }
  10321. if (myrpt->exttx && myrpt->parrotchannel &&
  10322. myrpt->p.parrotmode && (!myrpt->parrotstate))
  10323. {
  10324. char myfname[300];
  10325. ci.confno = myrpt->conf;
  10326. ci.confmode = DAHDI_CONF_CONFANNMON;
  10327. ci.chan = 0;
  10328. /* first put the channel on the conference in announce mode */
  10329. if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  10330. {
  10331. ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
  10332. break;
  10333. }
  10334. sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
  10335. strcat(myfname,".wav");
  10336. unlink(myfname);
  10337. sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
  10338. myrpt->parrotstate = 1;
  10339. myrpt->parrottimer = myrpt->p.parrottime;
  10340. if (myrpt->parrotstream)
  10341. ast_closestream(myrpt->parrotstream);
  10342. myrpt->parrotstream = NULL;
  10343. myrpt->parrotstream = ast_writefile(myfname,"wav",
  10344. "app_rpt Parrot",O_CREAT | O_TRUNC,0,0600);
  10345. }
  10346. /* Reconnect */
  10347. l = myrpt->links.next;
  10348. while(l != &myrpt->links)
  10349. {
  10350. if (l->killme)
  10351. {
  10352. /* remove from queue */
  10353. remque((struct qelem *) l);
  10354. if (!strcmp(myrpt->cmdnode,l->name))
  10355. myrpt->cmdnode[0] = 0;
  10356. rpt_mutex_unlock(&myrpt->lock);
  10357. /* hang-up on call to device */
  10358. if (l->chan) ast_hangup(l->chan);
  10359. ast_hangup(l->pchan);
  10360. ast_free(l);
  10361. rpt_mutex_lock(&myrpt->lock);
  10362. /* re-start link traversal */
  10363. l = myrpt->links.next;
  10364. continue;
  10365. }
  10366. l = l->next;
  10367. }
  10368. n = 0;
  10369. cs[n++] = myrpt->rxchannel;
  10370. cs[n++] = myrpt->pchannel;
  10371. cs[n++] = myrpt->monchannel;
  10372. if (myrpt->parrotchannel) cs[n++] = myrpt->parrotchannel;
  10373. if (myrpt->voxchannel) cs[n++] = myrpt->voxchannel;
  10374. cs[n++] = myrpt->txpchannel;
  10375. if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
  10376. if (myrpt->dahditxchannel != myrpt->txchannel)
  10377. cs[n++] = myrpt->dahditxchannel;
  10378. l = myrpt->links.next;
  10379. while(l != &myrpt->links)
  10380. {
  10381. if ((!l->killme) && (!l->disctime) && l->chan)
  10382. {
  10383. cs[n++] = l->chan;
  10384. cs[n++] = l->pchan;
  10385. }
  10386. l = l->next;
  10387. }
  10388. if ((myrpt->topkeystate == 1) &&
  10389. ((t - myrpt->topkeytime) > TOPKEYWAIT))
  10390. {
  10391. myrpt->topkeystate = 2;
  10392. qsort(myrpt->topkey,TOPKEYN,sizeof(struct rpt_topkey),
  10393. topcompar);
  10394. }
  10395. rpt_mutex_unlock(&myrpt->lock);
  10396. if (myrpt->topkeystate == 2)
  10397. {
  10398. rpt_telemetry(myrpt,TOPKEY,NULL);
  10399. myrpt->topkeystate = 3;
  10400. }
  10401. ms = MSWAIT;
  10402. for(x = 0; x < n; x++)
  10403. {
  10404. int s = -(-x - myrpt->scram - 1) % n;
  10405. cs1[x] = cs[s];
  10406. }
  10407. myrpt->scram++;
  10408. who = ast_waitfor_n(cs1,n,&ms);
  10409. if (who == NULL) ms = 0;
  10410. elap = MSWAIT - ms;
  10411. rpt_mutex_lock(&myrpt->lock);
  10412. l = myrpt->links.next;
  10413. while(l != &myrpt->links)
  10414. {
  10415. int myrx;
  10416. if (l->voxtotimer) l->voxtotimer -= elap;
  10417. if (l->voxtotimer < 0) l->voxtotimer = 0;
  10418. if (l->lasttx != l->lasttx1)
  10419. {
  10420. voxinit_link(l,!l->lasttx);
  10421. l->lasttx1 = l->lasttx;
  10422. }
  10423. myrx = l->lastrealrx;
  10424. if ((l->phonemode) && (l->phonevox))
  10425. {
  10426. myrx = myrx || (!AST_LIST_EMPTY(&l->rxq));
  10427. if (l->voxtotimer <= 0)
  10428. {
  10429. if (l->voxtostate)
  10430. {
  10431. l->voxtotimer = myrpt->p.voxtimeout_ms;
  10432. l->voxtostate = 0;
  10433. }
  10434. else
  10435. {
  10436. l->voxtotimer = myrpt->p.voxrecover_ms;
  10437. l->voxtostate = 1;
  10438. }
  10439. }
  10440. if (!l->voxtostate)
  10441. myrx = myrx || l->wasvox ;
  10442. }
  10443. l->lastrx = myrx;
  10444. if (l->linklisttimer)
  10445. {
  10446. l->linklisttimer -= elap;
  10447. if (l->linklisttimer < 0) l->linklisttimer = 0;
  10448. }
  10449. if ((!l->linklisttimer) && (l->name[0] != '0') && (!l->isremote))
  10450. {
  10451. struct ast_frame lf;
  10452. memset(&lf,0,sizeof(lf));
  10453. lf.frametype = AST_FRAME_TEXT;
  10454. lf.subclass.integer = 0;
  10455. lf.offset = 0;
  10456. lf.mallocd = 0;
  10457. lf.samples = 0;
  10458. l->linklisttimer = LINKLISTTIME;
  10459. strcpy(lstr,"L ");
  10460. __mklinklist(myrpt,l,lstr + 2);
  10461. if (l->chan)
  10462. {
  10463. lf.datalen = strlen(lstr) + 1;
  10464. lf.data.ptr = lstr;
  10465. ast_write(l->chan,&lf);
  10466. if (debug > 6) ast_log(LOG_NOTICE,
  10467. "@@@@ node %s sent node string %s to node %s\n",
  10468. myrpt->name,lstr,l->name);
  10469. }
  10470. }
  10471. if (l->newkey)
  10472. {
  10473. if ((l->retxtimer += elap) >= REDUNDANT_TX_TIME)
  10474. {
  10475. l->retxtimer = 0;
  10476. if (l->chan && l->phonemode == 0)
  10477. {
  10478. if (l->lasttx)
  10479. ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
  10480. else
  10481. ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
  10482. }
  10483. }
  10484. if ((l->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 5))
  10485. {
  10486. if (debug == 7) printf("@@@@ rx un-key\n");
  10487. l->lastrealrx = 0;
  10488. l->rerxtimer = 0;
  10489. if (l->lastrx1)
  10490. {
  10491. if (myrpt->p.archivedir)
  10492. {
  10493. char str[100];
  10494. sprintf(str,"RXUNKEY(T),%s",l->name);
  10495. donodelog(myrpt,str);
  10496. }
  10497. if(myrpt->p.duplex)
  10498. rpt_telemetry(myrpt,LINKUNKEY,l);
  10499. l->lastrx1 = 0;
  10500. }
  10501. }
  10502. }
  10503. if (l->disctime) /* Disconnect timer active on a channel ? */
  10504. {
  10505. l->disctime -= elap;
  10506. if (l->disctime <= 0) /* Disconnect timer expired on inbound channel ? */
  10507. l->disctime = 0; /* Yep */
  10508. }
  10509. if (l->retrytimer)
  10510. {
  10511. l->retrytimer -= elap;
  10512. if (l->retrytimer < 0) l->retrytimer = 0;
  10513. }
  10514. /* Tally connect time */
  10515. l->connecttime += elap;
  10516. /* ignore non-timing channels */
  10517. if (l->elaptime < 0)
  10518. {
  10519. l = l->next;
  10520. continue;
  10521. }
  10522. l->elaptime += elap;
  10523. /* if connection has taken too long */
  10524. if ((l->elaptime > MAXCONNECTTIME) &&
  10525. ((!l->chan) || (l->chan->_state != AST_STATE_UP)))
  10526. {
  10527. l->elaptime = 0;
  10528. rpt_mutex_unlock(&myrpt->lock);
  10529. if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
  10530. rpt_mutex_lock(&myrpt->lock);
  10531. break;
  10532. }
  10533. if ((!l->chan) && (!l->retrytimer) && l->outbound &&
  10534. (l->retries++ < l->max_retries) && (l->hasconnected))
  10535. {
  10536. if (l->chan) ast_hangup(l->chan);
  10537. l->chan = 0;
  10538. rpt_mutex_unlock(&myrpt->lock);
  10539. if ((l->name[0] != '0') && (!l->isremote))
  10540. {
  10541. if (attempt_reconnect(myrpt,l) == -1)
  10542. {
  10543. l->retrytimer = RETRY_TIMER_MS;
  10544. }
  10545. }
  10546. else
  10547. {
  10548. l->retrytimer = l->max_retries + 1;
  10549. }
  10550. rpt_mutex_lock(&myrpt->lock);
  10551. break;
  10552. }
  10553. if ((!l->chan) && (!l->retrytimer) && l->outbound &&
  10554. (l->retries >= l->max_retries))
  10555. {
  10556. /* remove from queue */
  10557. remque((struct qelem *) l);
  10558. if (!strcmp(myrpt->cmdnode,l->name))
  10559. myrpt->cmdnode[0] = 0;
  10560. rpt_mutex_unlock(&myrpt->lock);
  10561. if (l->name[0] != '0')
  10562. {
  10563. if (!l->hasconnected)
  10564. rpt_telemetry(myrpt,CONNFAIL,l);
  10565. else rpt_telemetry(myrpt,REMDISC,l);
  10566. }
  10567. if (myrpt->p.archivedir)
  10568. {
  10569. char str[100];
  10570. if (!l->hasconnected)
  10571. sprintf(str,"LINKFAIL,%s",l->name);
  10572. else
  10573. sprintf(str,"LINKDISC,%s",l->name);
  10574. donodelog(myrpt,str);
  10575. }
  10576. /* hang-up on call to device */
  10577. ast_hangup(l->pchan);
  10578. ast_free(l);
  10579. rpt_mutex_lock(&myrpt->lock);
  10580. break;
  10581. }
  10582. if ((!l->chan) && (!l->disctime) && (!l->outbound))
  10583. {
  10584. if(debug)ast_log(LOG_NOTICE, "LINKDISC AA\n");
  10585. /* remove from queue */
  10586. remque((struct qelem *) l);
  10587. if(myrpt->links.next==&myrpt->links)channel_revert(myrpt);
  10588. if (!strcmp(myrpt->cmdnode,l->name))myrpt->cmdnode[0] = 0;
  10589. rpt_mutex_unlock(&myrpt->lock);
  10590. if (l->name[0] != '0')
  10591. {
  10592. rpt_telemetry(myrpt,REMDISC,l);
  10593. }
  10594. if (myrpt->p.archivedir)
  10595. {
  10596. char str[100];
  10597. sprintf(str,"LINKDISC,%s",l->name);
  10598. donodelog(myrpt,str);
  10599. }
  10600. /* hang-up on call to device */
  10601. ast_hangup(l->pchan);
  10602. ast_free(l);
  10603. rpt_mutex_lock(&myrpt->lock);
  10604. break;
  10605. }
  10606. l = l->next;
  10607. }
  10608. if (myrpt->linkposttimer)
  10609. {
  10610. myrpt->linkposttimer -= elap;
  10611. if (myrpt->linkposttimer < 0) myrpt->linkposttimer = 0;
  10612. }
  10613. if (myrpt->linkposttimer <= 0)
  10614. {
  10615. int nstr;
  10616. char lst,*str;
  10617. time_t now;
  10618. myrpt->linkposttimer = LINKPOSTTIME;
  10619. nstr = 0;
  10620. for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
  10621. {
  10622. /* if is not a real link, ignore it */
  10623. if (l->name[0] == '0') continue;
  10624. nstr += strlen(l->name) + 1;
  10625. }
  10626. str = ast_malloc(nstr + 256);
  10627. if (!str)
  10628. {
  10629. ast_log(LOG_NOTICE,"Cannot ast_malloc()\n");
  10630. break;
  10631. }
  10632. nstr = 0;
  10633. strcpy(str,"nodes=");
  10634. for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
  10635. {
  10636. /* if is not a real link, ignore it */
  10637. if (l->name[0] == '0') continue;
  10638. lst = 'T';
  10639. if (!l->mode) lst = 'R';
  10640. if (!l->thisconnected) lst = 'C';
  10641. if (nstr) strcat(str,",");
  10642. sprintf(str + strlen(str),"%c%s",lst,l->name);
  10643. nstr = 1;
  10644. }
  10645. p = strstr(tdesc, "version");
  10646. if(p){
  10647. int vmajor,vminor;
  10648. if(sscanf(p, "version %30d.%30d", &vmajor, &vminor) == 2)
  10649. sprintf(str + strlen(str),"&apprptvers=%d.%d",vmajor,vminor);
  10650. }
  10651. time(&now);
  10652. sprintf(str + strlen(str),"&apprptuptime=%d",(int)(now-starttime));
  10653. sprintf(str + strlen(str),
  10654. "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
  10655. myrpt->totalkerchunks,myrpt->totalkeyups,(int) myrpt->totaltxtime/1000,
  10656. myrpt->timeouts,myrpt->totalexecdcommands);
  10657. rpt_mutex_unlock(&myrpt->lock);
  10658. statpost(myrpt,str);
  10659. rpt_mutex_lock(&myrpt->lock);
  10660. ast_free(str);
  10661. }
  10662. if (myrpt->keyposttimer)
  10663. {
  10664. myrpt->keyposttimer -= elap;
  10665. if (myrpt->keyposttimer < 0) myrpt->keyposttimer = 0;
  10666. }
  10667. if (myrpt->keyposttimer <= 0)
  10668. {
  10669. char str[100];
  10670. int diff = 0;
  10671. time_t now;
  10672. myrpt->keyposttimer = KEYPOSTTIME;
  10673. time(&now);
  10674. if (myrpt->lastkeyedtime)
  10675. {
  10676. diff = (int)(now - myrpt->lastkeyedtime);
  10677. }
  10678. sprintf(str,"keyed=%d&keytime=%d",myrpt->keyed,diff);
  10679. rpt_mutex_unlock(&myrpt->lock);
  10680. statpost(myrpt,str);
  10681. rpt_mutex_lock(&myrpt->lock);
  10682. }
  10683. if(totx){
  10684. myrpt->dailytxtime += elap;
  10685. myrpt->totaltxtime += elap;
  10686. }
  10687. i = myrpt->tailtimer;
  10688. if (myrpt->tailtimer) myrpt->tailtimer -= elap;
  10689. if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
  10690. if((i) && (myrpt->tailtimer == 0))
  10691. myrpt->tailevent = 1;
  10692. if ((!myrpt->p.s[myrpt->p.sysstate_cur].totdisable) && myrpt->totimer) myrpt->totimer -= elap;
  10693. if (myrpt->totimer < 0) myrpt->totimer = 0;
  10694. if (myrpt->idtimer) myrpt->idtimer -= elap;
  10695. if (myrpt->idtimer < 0) myrpt->idtimer = 0;
  10696. if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap;
  10697. if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0;
  10698. if (myrpt->voxtotimer) myrpt->voxtotimer -= elap;
  10699. if (myrpt->voxtotimer < 0) myrpt->voxtotimer = 0;
  10700. if (myrpt->exttx)
  10701. {
  10702. myrpt->parrottimer = myrpt->p.parrottime;
  10703. }
  10704. else
  10705. {
  10706. if (myrpt->parrottimer) myrpt->parrottimer -= elap;
  10707. if (myrpt->parrottimer < 0) myrpt->parrottimer = 0;
  10708. }
  10709. /* do macro timers */
  10710. if (myrpt->macrotimer) myrpt->macrotimer -= elap;
  10711. if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
  10712. /* do local dtmf timer */
  10713. if (myrpt->dtmf_local_timer)
  10714. {
  10715. if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
  10716. if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
  10717. }
  10718. do_dtmf_local(myrpt,0);
  10719. /* Execute scheduler appx. every 2 tenths of a second */
  10720. if (myrpt->skedtimer <= 0){
  10721. myrpt->skedtimer = 200;
  10722. do_scheduler(myrpt);
  10723. }
  10724. else
  10725. myrpt->skedtimer -=elap;
  10726. if (!ms)
  10727. {
  10728. rpt_mutex_unlock(&myrpt->lock);
  10729. continue;
  10730. }
  10731. if (myrpt->p.parrotmode && (myrpt->parrotstate == 1) &&
  10732. (myrpt->parrottimer <= 0))
  10733. {
  10734. ci.confno = 0;
  10735. ci.confmode = 0;
  10736. ci.chan = 0;
  10737. /* first put the channel on the conference in announce mode */
  10738. if (ioctl(myrpt->parrotchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  10739. {
  10740. ast_log(LOG_WARNING, "Unable to set conference mode for parrot\n");
  10741. break;
  10742. }
  10743. if (myrpt->parrotstream)
  10744. ast_closestream(myrpt->parrotstream);
  10745. myrpt->parrotstream = NULL;
  10746. myrpt->parrotstate = 2;
  10747. rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++));
  10748. }
  10749. if (myrpt->cmdAction.state == CMD_STATE_READY)
  10750. { /* there is a command waiting to be processed */
  10751. myrpt->cmdAction.state = CMD_STATE_EXECUTING;
  10752. // lose the lock
  10753. rpt_mutex_unlock(&myrpt->lock);
  10754. // do the function
  10755. (*function_table[myrpt->cmdAction.functionNumber].function)(myrpt,myrpt->cmdAction.param, myrpt->cmdAction.digits, myrpt->cmdAction.command_source, NULL);
  10756. // get the lock again
  10757. rpt_mutex_lock(&myrpt->lock);
  10758. myrpt->cmdAction.state = CMD_STATE_IDLE;
  10759. } /* if myrpt->cmdAction.state == CMD_STATE_READY */
  10760. c = myrpt->macrobuf[0];
  10761. time(&t);
  10762. if (c && (!myrpt->macrotimer) &&
  10763. starttime && (t > (starttime + START_DELAY)))
  10764. {
  10765. char cin = c & 0x7f;
  10766. myrpt->macrotimer = MACROTIME;
  10767. memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
  10768. if ((cin == 'p') || (cin == 'P'))
  10769. myrpt->macrotimer = MACROPTIME;
  10770. rpt_mutex_unlock(&myrpt->lock);
  10771. if (myrpt->p.archivedir)
  10772. {
  10773. char str[100];
  10774. sprintf(str,"DTMF(M),MAIN,%c",cin);
  10775. donodelog(myrpt,str);
  10776. }
  10777. local_dtmf_helper(myrpt,c);
  10778. } else rpt_mutex_unlock(&myrpt->lock);
  10779. if (who == myrpt->rxchannel) /* if it was a read from rx */
  10780. {
  10781. int ismuted;
  10782. f = ast_read(myrpt->rxchannel);
  10783. if (!f)
  10784. {
  10785. if (debug) printf("@@@@ rpt:Hung Up\n");
  10786. break;
  10787. }
  10788. if (f->frametype == AST_FRAME_VOICE)
  10789. {
  10790. #ifdef _MDC_DECODE_H_
  10791. unsigned char ubuf[2560];
  10792. short *sp;
  10793. int n;
  10794. #endif
  10795. if ((!myrpt->localtx) && (!myrpt->p.linktolink)) {
  10796. memset(f->data.ptr,0,f->datalen);
  10797. }
  10798. #ifdef _MDC_DECODE_H_
  10799. sp = (short *) f->data;
  10800. /* convert block to unsigned char */
  10801. for(n = 0; n < f->datalen / 2; n++)
  10802. {
  10803. ubuf[n] = (*sp++ >> 8) + 128;
  10804. }
  10805. n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
  10806. if (n == 1)
  10807. {
  10808. unsigned char op,arg;
  10809. unsigned short unitID;
  10810. mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
  10811. if (debug > 2)
  10812. {
  10813. ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
  10814. ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
  10815. op & 255,arg & 255,unitID);
  10816. }
  10817. if ((op == 1) && (arg == 0))
  10818. {
  10819. myrpt->lastunit = unitID;
  10820. mdc1200_notify(myrpt,NULL,myrpt->lastunit);
  10821. mdc1200_send(myrpt,myrpt->lastunit);
  10822. }
  10823. }
  10824. if ((debug > 2) && (i == 2))
  10825. {
  10826. unsigned char op,arg,ex1,ex2,ex3,ex4;
  10827. unsigned short unitID;
  10828. mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
  10829. &ex1,&ex2,&ex3,&ex4);
  10830. ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
  10831. ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
  10832. op & 255,arg & 255,unitID);
  10833. ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
  10834. ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
  10835. }
  10836. #endif
  10837. #ifdef __RPT_NOTCH
  10838. /* apply inbound filters, if any */
  10839. rpt_filter(myrpt,f->data,f->datalen / 2);
  10840. #endif
  10841. if (ioctl(myrpt->dahdirxchannel->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
  10842. {
  10843. ismuted = 0;
  10844. }
  10845. if (dtmfed) ismuted = 1;
  10846. dtmfed = 0;
  10847. if (ismuted)
  10848. {
  10849. memset(f->data.ptr,0,f->datalen);
  10850. if (myrpt->lastf1)
  10851. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  10852. if (myrpt->lastf2)
  10853. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  10854. }
  10855. if (f) f2 = ast_frdup(f);
  10856. else f2 = NULL;
  10857. f1 = myrpt->lastf2;
  10858. myrpt->lastf2 = myrpt->lastf1;
  10859. myrpt->lastf1 = f2;
  10860. if (ismuted)
  10861. {
  10862. if (myrpt->lastf1)
  10863. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  10864. if (myrpt->lastf2)
  10865. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  10866. }
  10867. if (f1)
  10868. {
  10869. ast_write(myrpt->pchannel,f1);
  10870. ast_frfree(f1);
  10871. }
  10872. }
  10873. #ifndef OLD_ASTERISK
  10874. else if (f->frametype == AST_FRAME_DTMF_BEGIN)
  10875. {
  10876. if (myrpt->lastf1)
  10877. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  10878. if (myrpt->lastf2)
  10879. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  10880. dtmfed = 1;
  10881. }
  10882. #endif
  10883. else if (f->frametype == AST_FRAME_DTMF)
  10884. {
  10885. c = (char) f->subclass.integer; /* get DTMF char */
  10886. ast_frfree(f);
  10887. if (myrpt->lastf1)
  10888. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  10889. if (myrpt->lastf2)
  10890. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  10891. dtmfed = 1;
  10892. if (!myrpt->keyed) continue;
  10893. c = func_xlat(myrpt,c,&myrpt->p.inxlat);
  10894. if (c) local_dtmf_helper(myrpt,c);
  10895. continue;
  10896. }
  10897. else if (f->frametype == AST_FRAME_CONTROL)
  10898. {
  10899. if (f->subclass.integer == AST_CONTROL_HANGUP)
  10900. {
  10901. if (debug) printf("@@@@ rpt:Hung Up\n");
  10902. ast_frfree(f);
  10903. break;
  10904. }
  10905. /* if RX key */
  10906. if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
  10907. {
  10908. if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
  10909. {
  10910. if (debug == 7) printf("@@@@ rx key\n");
  10911. myrpt->keyed = 1;
  10912. time(&myrpt->lastkeyedtime);
  10913. myrpt->keyposttimer = KEYPOSTSHORTTIME;
  10914. }
  10915. if (myrpt->p.archivedir)
  10916. {
  10917. donodelog(myrpt,"RXKEY,MAIN");
  10918. }
  10919. if (f->datalen && f->data.ptr)
  10920. {
  10921. char busy = 0;
  10922. if (debug) ast_log(LOG_NOTICE,"Got PL %s on node %s\n",(char *)f->data.ptr,myrpt->name);
  10923. // ctcss code autopatch initiate
  10924. if (strstr((char *)f->data.ptr,"/M/")&& !myrpt->macropatch)
  10925. {
  10926. char value[16] = "";
  10927. strcat(value,"*6");
  10928. myrpt->macropatch=1;
  10929. rpt_mutex_lock(&myrpt->lock);
  10930. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
  10931. rpt_mutex_unlock(&myrpt->lock);
  10932. busy=1;
  10933. }
  10934. if(!busy){
  10935. myrpt->macrotimer = MACROTIME;
  10936. strncat(myrpt->macrobuf,value,MAXMACRO - 1);
  10937. if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
  10938. }
  10939. rpt_mutex_unlock(&myrpt->lock);
  10940. }
  10941. else if (strcmp((char *)f->data.ptr,myrpt->lasttone))
  10942. {
  10943. char *value = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.tonemacro, (char *)f->data.ptr);
  10944. if (value)
  10945. {
  10946. if (debug) ast_log(LOG_NOTICE,"Tone %s doing %s on node %s\n",(char *) f->data.ptr,value,myrpt->name);
  10947. rpt_mutex_lock(&myrpt->lock);
  10948. if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(value)){
  10949. rpt_mutex_unlock(&myrpt->lock);
  10950. busy=1;
  10951. }
  10952. if(!busy){
  10953. myrpt->macrotimer = MACROTIME;
  10954. strncat(myrpt->macrobuf,value,MAXMACRO - 1);
  10955. }
  10956. rpt_mutex_unlock(&myrpt->lock);
  10957. }
  10958. if (!busy) strcpy(myrpt->lasttone,(char*)f->data.ptr);
  10959. }
  10960. } else myrpt->lasttone[0] = 0;
  10961. }
  10962. /* if RX un-key */
  10963. if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
  10964. {
  10965. if ((!lasttx) || (myrpt->p.duplex > 1) || (myrpt->p.linktolink))
  10966. {
  10967. if (debug == 7) printf("@@@@ rx un-key\n");
  10968. if(myrpt->p.duplex && myrpt->keyed) {
  10969. rpt_telemetry(myrpt,UNKEY,NULL);
  10970. }
  10971. }
  10972. myrpt->keyed = 0;
  10973. time(&myrpt->lastkeyedtime);
  10974. myrpt->keyposttimer = KEYPOSTSHORTTIME;
  10975. if (myrpt->p.archivedir)
  10976. {
  10977. donodelog(myrpt,"RXUNKEY,MAIN");
  10978. }
  10979. }
  10980. }
  10981. ast_frfree(f);
  10982. continue;
  10983. }
  10984. if (who == myrpt->pchannel) /* if it was a read from pseudo */
  10985. {
  10986. f = ast_read(myrpt->pchannel);
  10987. if (!f)
  10988. {
  10989. if (debug) printf("@@@@ rpt:Hung Up\n");
  10990. break;
  10991. }
  10992. if (f->frametype == AST_FRAME_VOICE)
  10993. {
  10994. ast_write(myrpt->txpchannel,f);
  10995. }
  10996. if (f->frametype == AST_FRAME_CONTROL)
  10997. {
  10998. if (f->subclass.integer == AST_CONTROL_HANGUP)
  10999. {
  11000. if (debug) printf("@@@@ rpt:Hung Up\n");
  11001. ast_frfree(f);
  11002. break;
  11003. }
  11004. }
  11005. ast_frfree(f);
  11006. continue;
  11007. }
  11008. if (who == myrpt->txchannel) /* if it was a read from tx */
  11009. {
  11010. f = ast_read(myrpt->txchannel);
  11011. if (!f)
  11012. {
  11013. if (debug) printf("@@@@ rpt:Hung Up\n");
  11014. break;
  11015. }
  11016. if (f->frametype == AST_FRAME_CONTROL)
  11017. {
  11018. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11019. {
  11020. if (debug) printf("@@@@ rpt:Hung Up\n");
  11021. ast_frfree(f);
  11022. break;
  11023. }
  11024. }
  11025. ast_frfree(f);
  11026. continue;
  11027. }
  11028. if (who == myrpt->dahditxchannel) /* if it was a read from pseudo-tx */
  11029. {
  11030. f = ast_read(myrpt->dahditxchannel);
  11031. if (!f)
  11032. {
  11033. if (debug) printf("@@@@ rpt:Hung Up\n");
  11034. break;
  11035. }
  11036. if (f->frametype == AST_FRAME_VOICE)
  11037. {
  11038. struct ast_frame *vframe;
  11039. if (myrpt->p.duplex < 2)
  11040. {
  11041. if (myrpt->txrealkeyed)
  11042. {
  11043. if ((!myfirst) && myrpt->callmode)
  11044. {
  11045. x = 0;
  11046. AST_LIST_TRAVERSE(&myrpt->txq, vframe,
  11047. frame_list) x++;
  11048. for(;x < myrpt->p.simplexpatchdelay; x++)
  11049. {
  11050. vframe = ast_frdup(f);
  11051. memset(vframe->data.ptr,0,vframe->datalen);
  11052. AST_LIST_INSERT_TAIL(&myrpt->txq,vframe,frame_list);
  11053. }
  11054. myfirst = 1;
  11055. }
  11056. vframe = ast_frdup(f);
  11057. AST_LIST_INSERT_TAIL(&myrpt->txq,
  11058. vframe,frame_list);
  11059. } else myfirst = 0;
  11060. x = 0;
  11061. AST_LIST_TRAVERSE(&myrpt->txq, vframe,
  11062. frame_list) x++;
  11063. if (!x)
  11064. {
  11065. memset(f->data.ptr,0,f->datalen);
  11066. }
  11067. else
  11068. {
  11069. ast_frfree(f);
  11070. f = AST_LIST_REMOVE_HEAD(&myrpt->txq,
  11071. frame_list);
  11072. }
  11073. }
  11074. else
  11075. {
  11076. while((vframe = AST_LIST_REMOVE_HEAD(&myrpt->txq,
  11077. frame_list))) ast_frfree(vframe);
  11078. }
  11079. ast_write(myrpt->txchannel,f);
  11080. }
  11081. if (f->frametype == AST_FRAME_CONTROL)
  11082. {
  11083. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11084. {
  11085. if (debug) printf("@@@@ rpt:Hung Up\n");
  11086. ast_frfree(f);
  11087. break;
  11088. }
  11089. }
  11090. ast_frfree(f);
  11091. continue;
  11092. }
  11093. toexit = 0;
  11094. rpt_mutex_lock(&myrpt->lock);
  11095. l = myrpt->links.next;
  11096. while(l != &myrpt->links)
  11097. {
  11098. int remnomute;
  11099. struct timeval now;
  11100. if (l->disctime)
  11101. {
  11102. l = l->next;
  11103. continue;
  11104. }
  11105. remrx = 0;
  11106. /* see if any other links are receiving */
  11107. m = myrpt->links.next;
  11108. while(m != &myrpt->links)
  11109. {
  11110. /* if not us, count it */
  11111. if ((m != l) && (m->lastrx)) remrx = 1;
  11112. m = m->next;
  11113. }
  11114. rpt_mutex_unlock(&myrpt->lock);
  11115. now = ast_tvnow();
  11116. if ((who == l->chan) || (!l->lastlinktv.tv_sec) ||
  11117. (ast_tvdiff_ms(now,l->lastlinktv) >= 19))
  11118. {
  11119. l->lastlinktv = now;
  11120. remnomute = myrpt->localtx &&
  11121. (!(myrpt->cmdnode[0] ||
  11122. (myrpt->dtmfidx > -1)));
  11123. totx = (((l->isremote) ? (remnomute) :
  11124. myrpt->exttx) || remrx) && l->mode;
  11125. if (l->phonemode == 0 && l->chan && (l->lasttx != totx))
  11126. {
  11127. if (totx)
  11128. {
  11129. ast_indicate(l->chan,AST_CONTROL_RADIO_KEY);
  11130. }
  11131. else
  11132. {
  11133. ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
  11134. }
  11135. if (myrpt->p.archivedir)
  11136. {
  11137. char str[100];
  11138. if (totx)
  11139. sprintf(str,"TXKEY,%s",l->name);
  11140. else
  11141. sprintf(str,"TXUNKEY,%s",l->name);
  11142. donodelog(myrpt,str);
  11143. }
  11144. }
  11145. l->lasttx = totx;
  11146. }
  11147. rpt_mutex_lock(&myrpt->lock);
  11148. if (who == l->chan) /* if it was a read from rx */
  11149. {
  11150. rpt_mutex_unlock(&myrpt->lock);
  11151. f = ast_read(l->chan);
  11152. if (!f)
  11153. {
  11154. rpt_mutex_lock(&myrpt->lock);
  11155. __kickshort(myrpt);
  11156. rpt_mutex_unlock(&myrpt->lock);
  11157. if ((!l->disced) && (!l->outbound))
  11158. {
  11159. if ((l->name[0] == '0') || l->isremote)
  11160. l->disctime = 1;
  11161. else
  11162. l->disctime = DISC_TIME;
  11163. rpt_mutex_lock(&myrpt->lock);
  11164. ast_hangup(l->chan);
  11165. l->chan = 0;
  11166. break;
  11167. }
  11168. if (l->retrytimer)
  11169. {
  11170. ast_hangup(l->chan);
  11171. l->chan = 0;
  11172. rpt_mutex_lock(&myrpt->lock);
  11173. break;
  11174. }
  11175. if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
  11176. {
  11177. rpt_mutex_lock(&myrpt->lock);
  11178. if (l->chan) ast_hangup(l->chan);
  11179. l->chan = 0;
  11180. l->hasconnected = 1;
  11181. l->retrytimer = RETRY_TIMER_MS;
  11182. l->elaptime = 0;
  11183. l->connecttime = 0;
  11184. l->thisconnected = 0;
  11185. break;
  11186. }
  11187. rpt_mutex_lock(&myrpt->lock);
  11188. /* remove from queue */
  11189. remque((struct qelem *) l);
  11190. if (!strcmp(myrpt->cmdnode,l->name))
  11191. myrpt->cmdnode[0] = 0;
  11192. __kickshort(myrpt);
  11193. rpt_mutex_unlock(&myrpt->lock);
  11194. if (!l->hasconnected)
  11195. rpt_telemetry(myrpt,CONNFAIL,l);
  11196. else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
  11197. if (myrpt->p.archivedir)
  11198. {
  11199. char str[100];
  11200. if (!l->hasconnected)
  11201. sprintf(str,"LINKFAIL,%s",l->name);
  11202. else
  11203. sprintf(str,"LINKDISC,%s",l->name);
  11204. donodelog(myrpt,str);
  11205. }
  11206. if (l->lastf1) ast_frfree(l->lastf1);
  11207. l->lastf1 = NULL;
  11208. if (l->lastf2) ast_frfree(l->lastf2);
  11209. l->lastf2 = NULL;
  11210. /* hang-up on call to device */
  11211. ast_hangup(l->chan);
  11212. ast_hangup(l->pchan);
  11213. ast_free(l);
  11214. rpt_mutex_lock(&myrpt->lock);
  11215. break;
  11216. }
  11217. if (f->frametype == AST_FRAME_VOICE)
  11218. {
  11219. int ismuted,n1;
  11220. if ((l->phonemode) && (l->phonevox))
  11221. {
  11222. n1 = dovox(&l->vox,
  11223. f->data.ptr,f->datalen / 2);
  11224. if (n1 != l->wasvox)
  11225. {
  11226. if (debug)ast_log(LOG_DEBUG,"Link Node %s, vox %d\n",l->name,n1);
  11227. l->wasvox = n1;
  11228. l->voxtostate = 0;
  11229. if (n1) l->voxtotimer = myrpt->p.voxtimeout_ms;
  11230. else l->voxtotimer = 0;
  11231. }
  11232. if (l->lastrealrx || n1)
  11233. {
  11234. if (!myfirst)
  11235. {
  11236. x = 0;
  11237. AST_LIST_TRAVERSE(&l->rxq, f1,
  11238. frame_list) x++;
  11239. for(;x < myrpt->p.simplexphonedelay; x++)
  11240. {
  11241. f1 = ast_frdup(f);
  11242. memset(f1->data.ptr,0,f1->datalen);
  11243. AST_LIST_INSERT_TAIL(&l->rxq,
  11244. f1,frame_list);
  11245. }
  11246. myfirst = 1;
  11247. }
  11248. f1 = ast_frdup(f);
  11249. AST_LIST_INSERT_TAIL(&l->rxq,f1,frame_list);
  11250. } else myfirst = 0;
  11251. x = 0;
  11252. AST_LIST_TRAVERSE(&l->rxq, f1,frame_list) x++;
  11253. if (!x)
  11254. {
  11255. memset(f->data.ptr,0,f->datalen);
  11256. }
  11257. else
  11258. {
  11259. ast_frfree(f);
  11260. f = AST_LIST_REMOVE_HEAD(&l->rxq,frame_list);
  11261. }
  11262. if (ioctl(l->chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
  11263. {
  11264. ismuted = 0;
  11265. }
  11266. /* if not receiving, zero-out audio */
  11267. ismuted |= (!l->lastrx);
  11268. if (l->dtmfed && l->phonemode) ismuted = 1;
  11269. l->dtmfed = 0;
  11270. if (ismuted)
  11271. {
  11272. memset(f->data.ptr,0,f->datalen);
  11273. if (l->lastf1)
  11274. memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
  11275. if (l->lastf2)
  11276. memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
  11277. }
  11278. if (f) f2 = ast_frdup(f);
  11279. else f2 = NULL;
  11280. f1 = l->lastf2;
  11281. l->lastf2 = l->lastf1;
  11282. l->lastf1 = f2;
  11283. if (ismuted)
  11284. {
  11285. if (l->lastf1)
  11286. memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
  11287. if (l->lastf2)
  11288. memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
  11289. }
  11290. if (f1)
  11291. {
  11292. ast_write(l->pchan,f1);
  11293. ast_frfree(f1);
  11294. }
  11295. }
  11296. else
  11297. {
  11298. if (!l->lastrx)
  11299. memset(f->data.ptr,0,f->datalen);
  11300. ast_write(l->pchan,f);
  11301. }
  11302. }
  11303. #ifndef OLD_ASTERISK
  11304. else if (f->frametype == AST_FRAME_DTMF_BEGIN)
  11305. {
  11306. if (l->lastf1)
  11307. memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
  11308. if (l->lastf2)
  11309. memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
  11310. l->dtmfed = 1;
  11311. }
  11312. #endif
  11313. if (f->frametype == AST_FRAME_TEXT)
  11314. {
  11315. handle_link_data(myrpt,l,f->data.ptr);
  11316. }
  11317. if (f->frametype == AST_FRAME_DTMF)
  11318. {
  11319. if (l->lastf1)
  11320. memset(l->lastf1->data.ptr,0,l->lastf1->datalen);
  11321. if (l->lastf2)
  11322. memset(l->lastf2->data.ptr,0,l->lastf2->datalen);
  11323. l->dtmfed = 1;
  11324. handle_link_phone_dtmf(myrpt,l,f->subclass.integer);
  11325. }
  11326. if (f->frametype == AST_FRAME_CONTROL)
  11327. {
  11328. if (f->subclass.integer == AST_CONTROL_ANSWER)
  11329. {
  11330. char lconnected = l->connected;
  11331. __kickshort(myrpt);
  11332. l->connected = 1;
  11333. l->hasconnected = 1;
  11334. l->thisconnected = 1;
  11335. l->elaptime = -1;
  11336. if (!l->phonemode) send_newkey(l->chan);
  11337. if (!l->isremote) l->retries = 0;
  11338. if (!lconnected)
  11339. {
  11340. rpt_telemetry(myrpt,CONNECTED,l);
  11341. if (myrpt->p.archivedir)
  11342. {
  11343. char str[100];
  11344. if (l->mode)
  11345. sprintf(str,"LINKTRX,%s",l->name);
  11346. else
  11347. sprintf(str,"LINKMONITOR,%s",l->name);
  11348. donodelog(myrpt,str);
  11349. }
  11350. }
  11351. else
  11352. l->reconnects++;
  11353. }
  11354. /* if RX key */
  11355. if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
  11356. {
  11357. if (debug == 7 ) printf("@@@@ rx key\n");
  11358. l->lastrealrx = 1;
  11359. l->rerxtimer = 0;
  11360. if (!l->lastrx1)
  11361. {
  11362. if (myrpt->p.archivedir)
  11363. {
  11364. char str[100];
  11365. sprintf(str,"RXKEY,%s",l->name);
  11366. donodelog(myrpt,str);
  11367. }
  11368. l->lastrx1 = 1;
  11369. }
  11370. }
  11371. /* if RX un-key */
  11372. if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
  11373. {
  11374. if (debug == 7) printf("@@@@ rx un-key\n");
  11375. l->lastrealrx = 0;
  11376. l->rerxtimer = 0;
  11377. if (l->lastrx1)
  11378. {
  11379. if (myrpt->p.archivedir)
  11380. {
  11381. char str[100];
  11382. sprintf(str,"RXUNKEY,%s",l->name);
  11383. donodelog(myrpt,str);
  11384. }
  11385. l->lastrx1 = 0;
  11386. if(myrpt->p.duplex)
  11387. rpt_telemetry(myrpt,LINKUNKEY,l);
  11388. }
  11389. }
  11390. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11391. {
  11392. ast_frfree(f);
  11393. rpt_mutex_lock(&myrpt->lock);
  11394. __kickshort(myrpt);
  11395. rpt_mutex_unlock(&myrpt->lock);
  11396. if ((!l->outbound) && (!l->disced))
  11397. {
  11398. if ((l->name[0] == '0') || l->isremote)
  11399. l->disctime = 1;
  11400. else
  11401. l->disctime = DISC_TIME;
  11402. rpt_mutex_lock(&myrpt->lock);
  11403. ast_hangup(l->chan);
  11404. l->chan = 0;
  11405. break;
  11406. }
  11407. if (l->retrytimer)
  11408. {
  11409. if (l->chan) ast_hangup(l->chan);
  11410. l->chan = 0;
  11411. rpt_mutex_lock(&myrpt->lock);
  11412. break;
  11413. }
  11414. if (l->outbound && (l->retries++ < l->max_retries) && (l->hasconnected))
  11415. {
  11416. rpt_mutex_lock(&myrpt->lock);
  11417. if (l->chan) ast_hangup(l->chan);
  11418. l->chan = 0;
  11419. l->hasconnected = 1;
  11420. l->elaptime = 0;
  11421. l->retrytimer = RETRY_TIMER_MS;
  11422. l->connecttime = 0;
  11423. l->thisconnected = 0;
  11424. break;
  11425. }
  11426. rpt_mutex_lock(&myrpt->lock);
  11427. /* remove from queue */
  11428. remque((struct qelem *) l);
  11429. if (!strcmp(myrpt->cmdnode,l->name))
  11430. myrpt->cmdnode[0] = 0;
  11431. __kickshort(myrpt);
  11432. rpt_mutex_unlock(&myrpt->lock);
  11433. if (!l->hasconnected)
  11434. rpt_telemetry(myrpt,CONNFAIL,l);
  11435. else if (l->disced != 2) rpt_telemetry(myrpt,REMDISC,l);
  11436. if (myrpt->p.archivedir)
  11437. {
  11438. char str[100];
  11439. if (!l->hasconnected)
  11440. sprintf(str,"LINKFAIL,%s",l->name);
  11441. else
  11442. sprintf(str,"LINKDISC,%s",l->name);
  11443. donodelog(myrpt,str);
  11444. }
  11445. if (l->lastf1) ast_frfree(l->lastf1);
  11446. l->lastf1 = NULL;
  11447. if (l->lastf2) ast_frfree(l->lastf2);
  11448. l->lastf2 = NULL;
  11449. /* hang-up on call to device */
  11450. ast_hangup(l->chan);
  11451. ast_hangup(l->pchan);
  11452. ast_free(l);
  11453. rpt_mutex_lock(&myrpt->lock);
  11454. break;
  11455. }
  11456. }
  11457. ast_frfree(f);
  11458. rpt_mutex_lock(&myrpt->lock);
  11459. break;
  11460. }
  11461. if (who == l->pchan)
  11462. {
  11463. rpt_mutex_unlock(&myrpt->lock);
  11464. f = ast_read(l->pchan);
  11465. if (!f)
  11466. {
  11467. if (debug) printf("@@@@ rpt:Hung Up\n");
  11468. toexit = 1;
  11469. rpt_mutex_lock(&myrpt->lock);
  11470. break;
  11471. }
  11472. if (f->frametype == AST_FRAME_VOICE)
  11473. {
  11474. if (l->chan) ast_write(l->chan,f);
  11475. }
  11476. if (f->frametype == AST_FRAME_CONTROL)
  11477. {
  11478. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11479. {
  11480. if (debug) printf("@@@@ rpt:Hung Up\n");
  11481. ast_frfree(f);
  11482. toexit = 1;
  11483. rpt_mutex_lock(&myrpt->lock);
  11484. break;
  11485. }
  11486. }
  11487. ast_frfree(f);
  11488. rpt_mutex_lock(&myrpt->lock);
  11489. break;
  11490. }
  11491. l = l->next;
  11492. }
  11493. rpt_mutex_unlock(&myrpt->lock);
  11494. if (toexit) break;
  11495. if (who == myrpt->monchannel)
  11496. {
  11497. f = ast_read(myrpt->monchannel);
  11498. if (!f)
  11499. {
  11500. if (debug) printf("@@@@ rpt:Hung Up\n");
  11501. break;
  11502. }
  11503. if (f->frametype == AST_FRAME_VOICE)
  11504. {
  11505. if (myrpt->monstream)
  11506. ast_writestream(myrpt->monstream,f);
  11507. }
  11508. if (f->frametype == AST_FRAME_CONTROL)
  11509. {
  11510. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11511. {
  11512. if (debug) printf("@@@@ rpt:Hung Up\n");
  11513. ast_frfree(f);
  11514. break;
  11515. }
  11516. }
  11517. ast_frfree(f);
  11518. continue;
  11519. }
  11520. if (myrpt->parrotchannel && (who == myrpt->parrotchannel))
  11521. {
  11522. f = ast_read(myrpt->parrotchannel);
  11523. if (!f)
  11524. {
  11525. if (debug) printf("@@@@ rpt:Hung Up\n");
  11526. break;
  11527. }
  11528. if (!myrpt->p.parrotmode)
  11529. {
  11530. char myfname[300];
  11531. if (myrpt->parrotstream)
  11532. {
  11533. ast_closestream(myrpt->parrotstream);
  11534. myrpt->parrotstream = 0;
  11535. }
  11536. sprintf(myfname,PARROTFILE,myrpt->name,myrpt->parrotcnt);
  11537. strcat(myfname,".wav");
  11538. unlink(myfname);
  11539. } else if (f->frametype == AST_FRAME_VOICE)
  11540. {
  11541. if (myrpt->parrotstream)
  11542. ast_writestream(myrpt->parrotstream,f);
  11543. }
  11544. if (f->frametype == AST_FRAME_CONTROL)
  11545. {
  11546. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11547. {
  11548. if (debug) printf("@@@@ rpt:Hung Up\n");
  11549. ast_frfree(f);
  11550. break;
  11551. }
  11552. }
  11553. ast_frfree(f);
  11554. continue;
  11555. }
  11556. if (myrpt->voxchannel && (who == myrpt->voxchannel))
  11557. {
  11558. f = ast_read(myrpt->voxchannel);
  11559. if (!f)
  11560. {
  11561. if (debug) printf("@@@@ rpt:Hung Up\n");
  11562. break;
  11563. }
  11564. if (f->frametype == AST_FRAME_VOICE)
  11565. {
  11566. n = dovox(&myrpt->vox,f->data.ptr,f->datalen / 2);
  11567. if (n != myrpt->wasvox)
  11568. {
  11569. if (debug) ast_log(LOG_DEBUG,"Node %s, vox %d\n",myrpt->name,n);
  11570. myrpt->wasvox = n;
  11571. myrpt->voxtostate = 0;
  11572. if (n) myrpt->voxtotimer = myrpt->p.voxtimeout_ms;
  11573. else myrpt->voxtotimer = 0;
  11574. }
  11575. }
  11576. if (f->frametype == AST_FRAME_CONTROL)
  11577. {
  11578. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11579. {
  11580. if (debug) printf("@@@@ rpt:Hung Up\n");
  11581. ast_frfree(f);
  11582. break;
  11583. }
  11584. }
  11585. ast_frfree(f);
  11586. continue;
  11587. }
  11588. if (who == myrpt->txpchannel) /* if it was a read from remote tx */
  11589. {
  11590. f = ast_read(myrpt->txpchannel);
  11591. if (!f)
  11592. {
  11593. if (debug) printf("@@@@ rpt:Hung Up\n");
  11594. break;
  11595. }
  11596. if (f->frametype == AST_FRAME_CONTROL)
  11597. {
  11598. if (f->subclass.integer == AST_CONTROL_HANGUP)
  11599. {
  11600. if (debug) printf("@@@@ rpt:Hung Up\n");
  11601. ast_frfree(f);
  11602. break;
  11603. }
  11604. }
  11605. ast_frfree(f);
  11606. continue;
  11607. }
  11608. }
  11609. usleep(100000);
  11610. ast_hangup(myrpt->pchannel);
  11611. ast_hangup(myrpt->monchannel);
  11612. if (myrpt->parrotchannel) ast_hangup(myrpt->parrotchannel);
  11613. myrpt->parrotstate = 0;
  11614. if (myrpt->voxchannel) ast_hangup(myrpt->voxchannel);
  11615. ast_hangup(myrpt->txpchannel);
  11616. if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
  11617. if (myrpt->dahditxchannel != myrpt->txchannel) ast_hangup(myrpt->dahditxchannel);
  11618. if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
  11619. myrpt->lastf1 = NULL;
  11620. if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
  11621. myrpt->lastf2 = NULL;
  11622. ast_hangup(myrpt->rxchannel);
  11623. rpt_mutex_lock(&myrpt->lock);
  11624. l = myrpt->links.next;
  11625. while(l != &myrpt->links)
  11626. {
  11627. struct rpt_link *ll = l;
  11628. /* remove from queue */
  11629. remque((struct qelem *) l);
  11630. /* hang-up on call to device */
  11631. if (l->chan) ast_hangup(l->chan);
  11632. ast_hangup(l->pchan);
  11633. l = l->next;
  11634. ast_free(ll);
  11635. }
  11636. if (myrpt->xlink == 1) myrpt->xlink = 2;
  11637. rpt_mutex_unlock(&myrpt->lock);
  11638. if (debug) printf("@@@@ rpt:Hung up channel\n");
  11639. myrpt->rpt_thread = AST_PTHREADT_STOP;
  11640. pthread_exit(NULL);
  11641. return NULL;
  11642. }
  11643. static void *rpt_master(void *ignore)
  11644. {
  11645. int i,n;
  11646. pthread_attr_t attr;
  11647. struct ast_config *cfg;
  11648. char *this,*val;
  11649. /* init nodelog queue */
  11650. nodelog.next = nodelog.prev = &nodelog;
  11651. /* go thru all the specified repeaters */
  11652. this = NULL;
  11653. n = 0;
  11654. #ifndef OLD_ASTERISK
  11655. /* wait until asterisk starts */
  11656. while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
  11657. usleep(250000);
  11658. #endif
  11659. #ifdef NEW_ASTERISK
  11660. rpt_vars[n].cfg = ast_config_load("rpt.conf",config_flags);
  11661. #else
  11662. rpt_vars[n].cfg = ast_config_load("rpt.conf");
  11663. #endif
  11664. cfg = rpt_vars[n].cfg;
  11665. if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
  11666. ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
  11667. pthread_exit(NULL);
  11668. }
  11669. while((this = ast_category_browse(cfg,this)) != NULL)
  11670. {
  11671. for(i = 0 ; i < strlen(this) ; i++){
  11672. if((this[i] < '0') || (this[i] > '9'))
  11673. break;
  11674. }
  11675. if(i != strlen(this)) continue; /* Not a node defn */
  11676. memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
  11677. rpt_vars[n].name = ast_strdup(this);
  11678. val = (char *) ast_variable_retrieve(cfg,this,"rxchannel");
  11679. if (val) rpt_vars[n].rxchanname = ast_strdup(val);
  11680. val = (char *) ast_variable_retrieve(cfg,this,"txchannel");
  11681. if (val) rpt_vars[n].txchanname = ast_strdup(val);
  11682. rpt_vars[n].remote = 0;
  11683. rpt_vars[n].remoterig = "";
  11684. val = (char *) ast_variable_retrieve(cfg,this,"remote");
  11685. if (val)
  11686. {
  11687. rpt_vars[n].remoterig = ast_strdup(val);
  11688. rpt_vars[n].remote = 1;
  11689. }
  11690. val = (char *) ast_variable_retrieve(cfg,this,"radiotype");
  11691. if (val) rpt_vars[n].remoterig = ast_strdup(val);
  11692. ast_mutex_init(&rpt_vars[n].lock);
  11693. ast_mutex_init(&rpt_vars[n].remlock);
  11694. ast_mutex_init(&rpt_vars[n].statpost_lock);
  11695. rpt_vars[n].tele.next = &rpt_vars[n].tele;
  11696. rpt_vars[n].tele.prev = &rpt_vars[n].tele;
  11697. rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
  11698. rpt_vars[n].tailmessagen = 0;
  11699. #ifdef _MDC_DECODE_H_
  11700. rpt_vars[n].mdc = mdc_decoder_new(8000);
  11701. #endif
  11702. n++;
  11703. }
  11704. nrpts = n;
  11705. ast_config_destroy(cfg);
  11706. /* start em all */
  11707. for(i = 0; i < n; i++)
  11708. {
  11709. load_rpt_vars(i,1);
  11710. /* if is a remote, don't start one for it */
  11711. if (rpt_vars[i].remote)
  11712. {
  11713. if(retreive_memory(&rpt_vars[i],"init")){ /* Try to retreive initial memory channel */
  11714. if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
  11715. strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
  11716. else
  11717. strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
  11718. strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
  11719. strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
  11720. rpt_vars[i].remmode = REM_MODE_FM;
  11721. rpt_vars[i].offset = REM_SIMPLEX;
  11722. rpt_vars[i].powerlevel = REM_LOWPWR;
  11723. }
  11724. continue;
  11725. }
  11726. else /* is a normal repeater */
  11727. {
  11728. rpt_vars[i].p.memory = rpt_vars[i].name;
  11729. if(retreive_memory(&rpt_vars[i],"radiofreq")){ /* Try to retreive initial memory channel */
  11730. if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx450))
  11731. strncpy(rpt_vars[i].freq, "446.500", sizeof(rpt_vars[i].freq) - 1);
  11732. else if (!strcmp(rpt_vars[i].remoterig,remote_rig_rtx150))
  11733. strncpy(rpt_vars[i].freq, "146.580", sizeof(rpt_vars[i].freq) - 1);
  11734. strncpy(rpt_vars[i].rxpl, "100.0", sizeof(rpt_vars[i].rxpl) - 1);
  11735. strncpy(rpt_vars[i].txpl, "100.0", sizeof(rpt_vars[i].txpl) - 1);
  11736. rpt_vars[i].remmode = REM_MODE_FM;
  11737. rpt_vars[i].offset = REM_SIMPLEX;
  11738. rpt_vars[i].powerlevel = REM_LOWPWR;
  11739. }
  11740. ast_log(LOG_NOTICE,"Normal Repeater Init %s %s %s\n",rpt_vars[i].name, rpt_vars[i].remoterig, rpt_vars[i].freq);
  11741. }
  11742. if (!rpt_vars[i].p.ident)
  11743. {
  11744. ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
  11745. ast_config_destroy(cfg);
  11746. pthread_exit(NULL);
  11747. }
  11748. pthread_attr_init(&attr);
  11749. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  11750. ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
  11751. }
  11752. usleep(500000);
  11753. time(&starttime);
  11754. for(;;)
  11755. {
  11756. /* Now monitor each thread, and restart it if necessary */
  11757. for(i = 0; i < n; i++)
  11758. {
  11759. int rv;
  11760. if (rpt_vars[i].remote) continue;
  11761. if (rpt_vars[i].rpt_thread == AST_PTHREADT_STOP)
  11762. rv = -1;
  11763. else
  11764. rv = pthread_kill(rpt_vars[i].rpt_thread,0);
  11765. if (rv)
  11766. {
  11767. if(time(NULL) - rpt_vars[i].lastthreadrestarttime <= 15)
  11768. {
  11769. if(rpt_vars[i].threadrestarts >= 5)
  11770. {
  11771. ast_log(LOG_ERROR,"Continual RPT thread restarts, killing Asterisk\n");
  11772. exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
  11773. }
  11774. else
  11775. {
  11776. ast_log(LOG_NOTICE,"RPT thread restarted on %s\n",rpt_vars[i].name);
  11777. rpt_vars[i].threadrestarts++;
  11778. }
  11779. }
  11780. else
  11781. rpt_vars[i].threadrestarts = 0;
  11782. rpt_vars[i].lastthreadrestarttime = time(NULL);
  11783. pthread_attr_init(&attr);
  11784. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  11785. ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
  11786. /* if (!rpt_vars[i].xlink) */
  11787. ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
  11788. }
  11789. }
  11790. for(;;)
  11791. {
  11792. struct nodelog *nodep;
  11793. char *space,datestr[100],fname[300];
  11794. int fd;
  11795. ast_mutex_lock(&nodeloglock);
  11796. nodep = nodelog.next;
  11797. if(nodep == &nodelog) /* if nothing in queue */
  11798. {
  11799. ast_mutex_unlock(&nodeloglock);
  11800. break;
  11801. }
  11802. remque((struct qelem *)nodep);
  11803. ast_mutex_unlock(&nodeloglock);
  11804. space = strchr(nodep->str,' ');
  11805. if (!space)
  11806. {
  11807. ast_free(nodep);
  11808. continue;
  11809. }
  11810. *space = 0;
  11811. strftime(datestr,sizeof(datestr) - 1,"%Y%m%d",
  11812. localtime(&nodep->timestamp));
  11813. sprintf(fname,"%s/%s/%s.txt",nodep->archivedir,
  11814. nodep->str,datestr);
  11815. fd = open(fname,O_WRONLY | O_CREAT | O_APPEND,0600);
  11816. if (fd == -1)
  11817. {
  11818. ast_log(LOG_ERROR,"Cannot open node log file %s for write",space + 1);
  11819. ast_free(nodep);
  11820. continue;
  11821. }
  11822. if (write(fd,space + 1,strlen(space + 1)) !=
  11823. strlen(space + 1))
  11824. {
  11825. ast_log(LOG_ERROR,"Cannot write node log file %s for write",space + 1);
  11826. ast_free(nodep);
  11827. continue;
  11828. }
  11829. close(fd);
  11830. ast_free(nodep);
  11831. }
  11832. sleep(2);
  11833. }
  11834. ast_config_destroy(cfg);
  11835. pthread_exit(NULL);
  11836. }
  11837. static int rpt_exec(struct ast_channel *chan, const char *data)
  11838. {
  11839. int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
  11840. int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
  11841. int ismuted,dtmfed,phone_vox = 0;
  11842. #ifdef OLD_ASTERISK
  11843. struct localuser *u;
  11844. #endif
  11845. char tmp[256], keyed = 0,keyed1 = 0;
  11846. char *options,*stringp,*tele,c,*altp,*memp;
  11847. char sx[320],*sy;
  11848. struct rpt *myrpt;
  11849. struct ast_frame *f,*f1,*f2;
  11850. struct ast_channel *who;
  11851. struct ast_channel *cs[20];
  11852. struct rpt_link *l;
  11853. struct dahdi_confinfo ci; /* conference info */
  11854. struct dahdi_params par;
  11855. int ms,elap,nullfd;
  11856. time_t t,last_timeout_warning;
  11857. struct dahdi_radio_param z;
  11858. struct rpt_tele *telem;
  11859. int numlinks;
  11860. nullfd = open("/dev/null",O_RDWR);
  11861. if (ast_strlen_zero(data)) {
  11862. ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
  11863. return -1;
  11864. }
  11865. strncpy(tmp, (char *)data, sizeof(tmp)-1);
  11866. time(&t);
  11867. /* if time has externally shifted negative, screw it */
  11868. if (t < starttime) t = starttime + START_DELAY;
  11869. if ((!starttime) || (t < (starttime + START_DELAY)))
  11870. {
  11871. ast_log(LOG_NOTICE,"Node %s rejecting call: too soon!\n",tmp);
  11872. ast_safe_sleep(chan,3000);
  11873. return -1;
  11874. }
  11875. ast_log(LOG_NOTICE,"parsing argument=%s \n",tmp);
  11876. altp=strstr(tmp, "|*");
  11877. if(altp){
  11878. altp[0]=0;
  11879. altp++;
  11880. }
  11881. memp=strstr(tmp, "|M");
  11882. if(memp){
  11883. memp[0]=0;
  11884. memp+=2;
  11885. }
  11886. stringp=tmp;
  11887. strsep(&stringp, "|");
  11888. options = stringp;
  11889. ast_log(LOG_NOTICE,"options=%s \n",options);
  11890. if(memp>0)ast_log(LOG_NOTICE,"memp=%s \n",memp);
  11891. if(altp>0)ast_log(LOG_NOTICE,"altp=%s \n",altp);
  11892. myrpt = NULL;
  11893. /* see if we can find our specified one */
  11894. for(i = 0; i < nrpts; i++)
  11895. {
  11896. /* if name matches, assign it and exit loop */
  11897. if (!strcmp(tmp,rpt_vars[i].name))
  11898. {
  11899. myrpt = &rpt_vars[i];
  11900. break;
  11901. }
  11902. }
  11903. pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "");
  11904. if (myrpt == NULL)
  11905. {
  11906. pbx_builtin_setvar_helper(chan, "RPT_STAT_ERR", "NODE_NOT_FOUND");
  11907. ast_log(LOG_WARNING, "Cannot find specified system node %s\n",tmp);
  11908. return (priority_jump(NULL,chan));
  11909. }
  11910. numlinks=linkcount(myrpt);
  11911. if(options && *options == 'q')
  11912. {
  11913. char buf2[128];
  11914. if(myrpt->keyed)
  11915. pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "1");
  11916. else
  11917. pbx_builtin_setvar_helper(chan, "RPT_STAT_RXKEYED", "0");
  11918. if(myrpt->txkeyed)
  11919. pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "1");
  11920. else
  11921. pbx_builtin_setvar_helper(chan, "RPT_STAT_TXKEYED", "0");
  11922. snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_XLINK", myrpt->xlink);
  11923. pbx_builtin_setvar(chan, buf2);
  11924. snprintf(buf2,sizeof(buf2),"%s=%i", "RPT_STAT_LINKS", numlinks);
  11925. pbx_builtin_setvar(chan, buf2);
  11926. snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_WASCHAN", myrpt->waschan);
  11927. pbx_builtin_setvar(chan, buf2);
  11928. snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_NOWCHAN", myrpt->nowchan);
  11929. pbx_builtin_setvar(chan, buf2);
  11930. snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_DUPLEX", myrpt->p.duplex);
  11931. pbx_builtin_setvar(chan, buf2);
  11932. snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PARROT", myrpt->p.parrotmode);
  11933. pbx_builtin_setvar(chan, buf2);
  11934. //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PHONEVOX", myrpt->phonevox);
  11935. //pbx_builtin_setvar(chan, buf2);
  11936. //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CONNECTED", myrpt->connected);
  11937. //pbx_builtin_setvar(chan, buf2);
  11938. snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CALLMODE", myrpt->callmode);
  11939. pbx_builtin_setvar(chan, buf2);
  11940. snprintf(buf2,sizeof(buf2),"%s=%s", "RPT_STAT_LASTTONE", myrpt->lasttone);
  11941. pbx_builtin_setvar(chan, buf2);
  11942. return priority_jump(myrpt,chan);
  11943. }
  11944. if(options && *options == 'o')
  11945. {
  11946. return(channel_revert(myrpt));
  11947. }
  11948. #if 0
  11949. if((altp)&&(*options == 'Z'))
  11950. {
  11951. rpt_push_alt_macro(myrpt,altp);
  11952. return 0;
  11953. }
  11954. #endif
  11955. /* if not phone access, must be an IAX connection */
  11956. if (options && ((*options == 'P') || (*options == 'D') || (*options == 'R') || (*options == 'S')))
  11957. {
  11958. int val;
  11959. pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "0");
  11960. myrpt->bargechan=0;
  11961. if(options && strstr(options, "f")>0)
  11962. {
  11963. myrpt->bargechan=1;
  11964. }
  11965. if(memp>0)
  11966. {
  11967. char radiochan;
  11968. radiochan=strtod(data,NULL);
  11969. // if(myrpt->nowchan!=0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
  11970. if(numlinks>0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
  11971. {
  11972. pbx_builtin_setvar_helper(chan, "RPT_STAT_BUSY", "1");
  11973. ast_log(LOG_NOTICE, "Radio Channel Busy.\n");
  11974. return (priority_jump(myrpt,chan));
  11975. }
  11976. else if(radiochan!=myrpt->nowchan || myrpt->bargechan)
  11977. {
  11978. channel_steer(myrpt,memp);
  11979. }
  11980. }
  11981. if(altp)rpt_push_alt_macro(myrpt,altp);
  11982. phone_mode = 1;
  11983. if (*options == 'D') phone_mode = 2;
  11984. if (*options == 'S') phone_mode = 3;
  11985. ast_set_callerid(chan,"0","app_rpt user","0");
  11986. val = 1;
  11987. ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
  11988. if ((*(options + 1) == 'V') || (*(options + 1) == 'v')) phone_vox = 1;
  11989. }
  11990. else
  11991. {
  11992. #ifdef ALLOW_LOCAL_CHANNELS
  11993. /* Check to insure the connection is IAX2 or Local*/
  11994. if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
  11995. ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
  11996. return -1;
  11997. }
  11998. #else
  11999. if (strncmp(chan->name,"IAX2",4))
  12000. {
  12001. ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
  12002. return -1;
  12003. }
  12004. #endif
  12005. if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable){ /* Do not allow incoming radio connections if disabled */
  12006. ast_log(LOG_NOTICE, "Connect attempt to node %s with tx disabled", myrpt->name);
  12007. return -1;
  12008. }
  12009. }
  12010. if (options && (*options == 'R'))
  12011. {
  12012. /* Parts of this section taken from app_parkandannounce */
  12013. char *return_context;
  12014. int length, m, lot, timeout = 0;
  12015. char buffer[256],*template;
  12016. char *working, *context, *exten, *priority;
  12017. char *s,*orig_s;
  12018. rpt_mutex_lock(&myrpt->lock);
  12019. m = myrpt->callmode;
  12020. rpt_mutex_unlock(&myrpt->lock);
  12021. if ((!myrpt->p.nobusyout) && m)
  12022. {
  12023. if (chan->_state != AST_STATE_UP)
  12024. {
  12025. ast_indicate(chan,AST_CONTROL_BUSY);
  12026. }
  12027. while(ast_safe_sleep(chan,10000) != -1);
  12028. return -1;
  12029. }
  12030. if (chan->_state != AST_STATE_UP)
  12031. {
  12032. ast_answer(chan);
  12033. if (!phone_mode) send_newkey(chan);
  12034. }
  12035. length=strlen(options)+2;
  12036. orig_s=ast_malloc(length);
  12037. if(!orig_s) {
  12038. ast_log(LOG_WARNING, "Out of memory\n");
  12039. return -1;
  12040. }
  12041. s=orig_s;
  12042. strncpy(s,options,length);
  12043. template=strsep(&s,"|");
  12044. if(!template) {
  12045. ast_log(LOG_WARNING, "An announce template must be defined\n");
  12046. ast_free(orig_s);
  12047. return -1;
  12048. }
  12049. if(s) {
  12050. timeout = atoi(strsep(&s, "|"));
  12051. timeout *= 1000;
  12052. }
  12053. return_context = s;
  12054. if(return_context != NULL) {
  12055. /* set the return context. Code borrowed from the Goto builtin */
  12056. working = return_context;
  12057. context = strsep(&working, "|");
  12058. exten = strsep(&working, "|");
  12059. if(!exten) {
  12060. /* Only a priority in this one */
  12061. priority = context;
  12062. exten = NULL;
  12063. context = NULL;
  12064. } else {
  12065. priority = strsep(&working, "|");
  12066. if(!priority) {
  12067. /* Only an extension and priority in this one */
  12068. priority = exten;
  12069. exten = context;
  12070. context = NULL;
  12071. }
  12072. }
  12073. if(atoi(priority) < 0) {
  12074. ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
  12075. ast_free(orig_s);
  12076. return -1;
  12077. }
  12078. /* At this point we have a priority and maybe an extension and a context */
  12079. chan->priority = atoi(priority);
  12080. #ifdef OLD_ASTERISK
  12081. if(exten && strcasecmp(exten, "BYEXTENSION"))
  12082. #else
  12083. if(exten)
  12084. #endif
  12085. strncpy(chan->exten, exten, sizeof(chan->exten)-1);
  12086. if(context)
  12087. strncpy(chan->context, context, sizeof(chan->context)-1);
  12088. } else { /* increment the priority by default*/
  12089. chan->priority++;
  12090. }
  12091. if(option_verbose > 2) {
  12092. ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n",
  12093. chan->context, chan->exten, chan->priority,
  12094. S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
  12095. if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
  12096. S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
  12097. ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
  12098. }
  12099. }
  12100. /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
  12101. before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
  12102. ast_masq_park_call(chan, NULL, timeout, &lot);
  12103. if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
  12104. snprintf(buffer, sizeof(buffer) - 1, "%d,%s", lot, template + 1);
  12105. rpt_telemetry(myrpt,REV_PATCH,buffer);
  12106. ast_free(orig_s);
  12107. return 0;
  12108. }
  12109. if (!options)
  12110. {
  12111. struct ast_hostent ahp;
  12112. struct hostent *hp;
  12113. struct in_addr ia;
  12114. char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
  12115. /* look at callerid to see what node this comes from */
  12116. b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
  12117. if (!b) /* if doesn't have caller id */
  12118. {
  12119. ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
  12120. return -1;
  12121. }
  12122. /* get his IP from IAX2 module */
  12123. memset(hisip,0,sizeof(hisip));
  12124. #ifdef ALLOW_LOCAL_CHANNELS
  12125. /* set IP address if this is a local connection*/
  12126. if (strncmp(chan->name,"Local",5)==0) {
  12127. strcpy(hisip,"127.0.0.1");
  12128. } else {
  12129. pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
  12130. }
  12131. #else
  12132. pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
  12133. #endif
  12134. if (!hisip[0])
  12135. {
  12136. ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
  12137. return -1;
  12138. }
  12139. b1 = ast_strdupa(b);
  12140. ast_shrink_phone_number(b1);
  12141. if (!strcmp(myrpt->name,b1))
  12142. {
  12143. ast_log(LOG_WARNING, "Trying to link to self!!\n");
  12144. return -1;
  12145. }
  12146. if (*b1 < '1')
  12147. {
  12148. ast_log(LOG_WARNING, "Node %s Invalid for connection here!!\n",b1);
  12149. return -1;
  12150. }
  12151. /* look for his reported node string */
  12152. val = node_lookup(myrpt,b1);
  12153. if (!val)
  12154. {
  12155. ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
  12156. return -1;
  12157. }
  12158. strncpy(tmp,val,sizeof(tmp) - 1);
  12159. s = tmp;
  12160. s1 = strsep(&s,",");
  12161. if (!strchr(s1,':') && strchr(s1,'/') && strncasecmp(s1, "local/", 6))
  12162. {
  12163. sy = strchr(s1,'/');
  12164. *sy = 0;
  12165. sprintf(sx,"%s:4569/%s",s1,sy + 1);
  12166. s1 = sx;
  12167. }
  12168. s2 = strsep(&s,",");
  12169. if (!s2)
  12170. {
  12171. ast_log(LOG_WARNING, "Reported node %s not in correct format!!\n",b1);
  12172. return -1;
  12173. }
  12174. if (strcmp(s2,"NONE")) {
  12175. hp = ast_gethostbyname(s2, &ahp);
  12176. if (!hp)
  12177. {
  12178. ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s2);
  12179. return -1;
  12180. }
  12181. memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
  12182. #ifdef OLD_ASTERISK
  12183. ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
  12184. #else
  12185. strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
  12186. #endif
  12187. s3 = strchr(hisip,':');
  12188. if (s3) *s3 = 0;
  12189. if (strcmp(hisip,nodeip))
  12190. {
  12191. s3 = strchr(s1,'@');
  12192. if (s3) s1 = s3 + 1;
  12193. s3 = strchr(s1,'/');
  12194. if (s3) *s3 = 0;
  12195. s3 = strchr(s1,':');
  12196. if (s3) *s3 = 0;
  12197. hp = ast_gethostbyname(s1, &ahp);
  12198. if (!hp)
  12199. {
  12200. ast_log(LOG_WARNING, "Reported node %s, name %s cannot be found!!\n",b1,s1);
  12201. return -1;
  12202. }
  12203. memcpy(&ia,hp->h_addr,sizeof(in_addr_t));
  12204. #ifdef OLD_ASTERISK
  12205. ast_inet_ntoa(nodeip,sizeof(nodeip) - 1,ia);
  12206. #else
  12207. strncpy(nodeip,ast_inet_ntoa(ia),sizeof(nodeip) - 1);
  12208. #endif
  12209. if (strcmp(hisip,nodeip))
  12210. {
  12211. ast_log(LOG_WARNING, "Node %s IP %s does not match link IP %s!!\n",b1,nodeip,hisip);
  12212. return -1;
  12213. }
  12214. }
  12215. }
  12216. }
  12217. /* if is not a remote */
  12218. if (!myrpt->remote)
  12219. {
  12220. char *b,*b1;
  12221. int reconnects = 0;
  12222. rpt_mutex_lock(&myrpt->lock);
  12223. i = myrpt->xlink;
  12224. rpt_mutex_unlock(&myrpt->lock);
  12225. if (i)
  12226. {
  12227. ast_log(LOG_WARNING, "Cannot connect to node %s, system busy\n",myrpt->name);
  12228. return -1;
  12229. }
  12230. /* look at callerid to see what node this comes from */
  12231. b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
  12232. if (!b) /* if doesn't have caller id */
  12233. {
  12234. ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
  12235. return -1;
  12236. }
  12237. b1 = ast_strdupa(b);
  12238. ast_shrink_phone_number(b1);
  12239. if (!strcmp(myrpt->name,b1))
  12240. {
  12241. ast_log(LOG_WARNING, "Trying to link to self!!\n");
  12242. return -1;
  12243. }
  12244. rpt_mutex_lock(&myrpt->lock);
  12245. l = myrpt->links.next;
  12246. /* try to find this one in queue */
  12247. while(l != &myrpt->links)
  12248. {
  12249. if (l->name[0] == '0')
  12250. {
  12251. l = l->next;
  12252. continue;
  12253. }
  12254. /* if found matching string */
  12255. if (!strcmp(l->name,b1)) break;
  12256. l = l->next;
  12257. }
  12258. /* if found */
  12259. if (l != &myrpt->links)
  12260. {
  12261. l->killme = 1;
  12262. l->retries = l->max_retries + 1;
  12263. l->disced = 2;
  12264. reconnects = l->reconnects;
  12265. reconnects++;
  12266. rpt_mutex_unlock(&myrpt->lock);
  12267. usleep(500000);
  12268. } else
  12269. rpt_mutex_unlock(&myrpt->lock);
  12270. /* establish call in tranceive mode */
  12271. l = ast_malloc(sizeof(struct rpt_link));
  12272. if (!l)
  12273. {
  12274. ast_log(LOG_WARNING, "Unable to malloc\n");
  12275. pthread_exit(NULL);
  12276. }
  12277. /* zero the silly thing */
  12278. memset((char *)l,0,sizeof(struct rpt_link));
  12279. l->mode = 1;
  12280. strncpy(l->name,b1,MAXNODESTR - 1);
  12281. l->isremote = 0;
  12282. l->chan = chan;
  12283. l->connected = 1;
  12284. l->thisconnected = 1;
  12285. l->hasconnected = 1;
  12286. l->reconnects = reconnects;
  12287. l->phonemode = phone_mode;
  12288. l->phonevox = phone_vox;
  12289. l->lastf1 = NULL;
  12290. l->lastf2 = NULL;
  12291. l->dtmfed = 0;
  12292. voxinit_link(l,1);
  12293. ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
  12294. ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
  12295. /* allocate a pseudo-channel thru asterisk */
  12296. l->pchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  12297. if (!l->pchan)
  12298. {
  12299. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  12300. pthread_exit(NULL);
  12301. }
  12302. ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
  12303. ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
  12304. #ifdef AST_CDR_FLAG_POST_DISABLED
  12305. if (l->pchan->cdr)
  12306. ast_set_flag(l->pchan->cdr,AST_CDR_FLAG_POST_DISABLED);
  12307. #endif
  12308. /* make a conference for the tx */
  12309. ci.chan = 0;
  12310. ci.confno = myrpt->conf;
  12311. ci.confmode = DAHDI_CONF_CONF | DAHDI_CONF_LISTENER | DAHDI_CONF_TALKER;
  12312. /* first put the channel on the conference in proper mode */
  12313. if (ioctl(l->pchan->fds[0],DAHDI_SETCONF,&ci) == -1)
  12314. {
  12315. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  12316. pthread_exit(NULL);
  12317. }
  12318. rpt_mutex_lock(&myrpt->lock);
  12319. if ((phone_mode == 2) && (!phone_vox)) l->lastrealrx = 1;
  12320. l->max_retries = MAX_RETRIES;
  12321. /* insert at end of queue */
  12322. insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
  12323. __kickshort(myrpt);
  12324. rpt_mutex_unlock(&myrpt->lock);
  12325. if (chan->_state != AST_STATE_UP) {
  12326. ast_answer(chan);
  12327. if (!phone_mode) send_newkey(chan);
  12328. }
  12329. if (myrpt->p.archivedir)
  12330. {
  12331. char str[100];
  12332. if (l->phonemode)
  12333. sprintf(str,"LINK(P),%s",l->name);
  12334. else
  12335. sprintf(str,"LINK,%s",l->name);
  12336. donodelog(myrpt,str);
  12337. }
  12338. if (!phone_mode) send_newkey(chan);
  12339. return 0;
  12340. }
  12341. /* well, then it is a remote */
  12342. rpt_mutex_lock(&myrpt->lock);
  12343. /* if remote, error if anyone else already linked */
  12344. if (myrpt->remoteon)
  12345. {
  12346. rpt_mutex_unlock(&myrpt->lock);
  12347. usleep(500000);
  12348. if (myrpt->remoteon)
  12349. {
  12350. ast_log(LOG_WARNING, "Trying to use busy link on %s\n",tmp);
  12351. #ifdef AST_CDR_FLAG_POST_DISABLED
  12352. if (chan->cdr)
  12353. ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
  12354. #endif
  12355. return -1;
  12356. }
  12357. rpt_mutex_lock(&myrpt->lock);
  12358. }
  12359. if (myrpt->p.rptnode)
  12360. {
  12361. char killedit = 0;
  12362. time_t now;
  12363. time(&now);
  12364. for(i = 0; i < nrpts; i++)
  12365. {
  12366. if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
  12367. {
  12368. if ((rpt_vars[i].links.next != &rpt_vars[i].links) ||
  12369. rpt_vars[i].keyed ||
  12370. ((rpt_vars[i].lastkeyedtime + RPT_LOCKOUT_SECS) > now) ||
  12371. rpt_vars[i].txkeyed ||
  12372. ((rpt_vars[i].lasttxkeyedtime + RPT_LOCKOUT_SECS) > now))
  12373. {
  12374. rpt_mutex_unlock(&myrpt->lock);
  12375. ast_log(LOG_WARNING, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars[i].name,tmp);
  12376. #ifdef AST_CDR_FLAG_POST_DISABLED
  12377. if (chan->cdr)
  12378. ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
  12379. #endif
  12380. return -1;
  12381. }
  12382. while(rpt_vars[i].xlink != 3)
  12383. {
  12384. if (!killedit)
  12385. {
  12386. ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
  12387. rpt_vars[i].xlink = 1;
  12388. killedit = 1;
  12389. }
  12390. rpt_mutex_unlock(&myrpt->lock);
  12391. if (ast_safe_sleep(chan,500) == -1)
  12392. {
  12393. #ifdef AST_CDR_FLAG_POST_DISABLED
  12394. if (chan->cdr)
  12395. ast_set_flag(chan->cdr,AST_CDR_FLAG_POST_DISABLED);
  12396. #endif
  12397. return -1;
  12398. }
  12399. rpt_mutex_lock(&myrpt->lock);
  12400. }
  12401. break;
  12402. }
  12403. }
  12404. }
  12405. #ifdef HAVE_IOPERM
  12406. if ( (!strcmp(myrpt->remoterig, remote_rig_rbi)||!strcmp(myrpt->remoterig, remote_rig_ppp16)) &&
  12407. (ioperm(myrpt->p.iobase,1,1) == -1))
  12408. {
  12409. rpt_mutex_unlock(&myrpt->lock);
  12410. ast_log(LOG_WARNING, "Can't get io permission on IO port %x hex\n",myrpt->p.iobase);
  12411. return -1;
  12412. }
  12413. #endif
  12414. myrpt->remoteon = 1;
  12415. #ifdef OLD_ASTERISK
  12416. LOCAL_USER_ADD(u);
  12417. #endif
  12418. rpt_mutex_unlock(&myrpt->lock);
  12419. /* find our index, and load the vars initially */
  12420. for(i = 0; i < nrpts; i++)
  12421. {
  12422. if (&rpt_vars[i] == myrpt)
  12423. {
  12424. load_rpt_vars(i,0);
  12425. break;
  12426. }
  12427. }
  12428. rpt_mutex_lock(&myrpt->lock);
  12429. tele = strchr(myrpt->rxchanname,'/');
  12430. if (!tele)
  12431. {
  12432. fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
  12433. rpt_mutex_unlock(&myrpt->lock);
  12434. pthread_exit(NULL);
  12435. }
  12436. *tele++ = 0;
  12437. myrpt->rxchannel = ast_request(myrpt->rxchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  12438. myrpt->dahdirxchannel = NULL;
  12439. if (!strcasecmp(myrpt->rxchanname,"DAHDI"))
  12440. myrpt->dahdirxchannel = myrpt->rxchannel;
  12441. if (myrpt->rxchannel)
  12442. {
  12443. ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
  12444. ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
  12445. #ifdef AST_CDR_FLAG_POST_DISABLED
  12446. if (myrpt->rxchannel->cdr)
  12447. ast_set_flag(myrpt->rxchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  12448. #endif
  12449. #ifndef NEW_ASTERISK
  12450. myrpt->rxchannel->whentohangup = 0;
  12451. #endif
  12452. myrpt->rxchannel->appl = "Apprpt";
  12453. myrpt->rxchannel->data = "(Link Rx)";
  12454. if (option_verbose > 2)
  12455. ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
  12456. myrpt->rxchanname,tele,myrpt->rxchannel->name);
  12457. rpt_mutex_unlock(&myrpt->lock);
  12458. ast_call(myrpt->rxchannel,tele,999);
  12459. rpt_mutex_lock(&myrpt->lock);
  12460. }
  12461. else
  12462. {
  12463. fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
  12464. rpt_mutex_unlock(&myrpt->lock);
  12465. pthread_exit(NULL);
  12466. }
  12467. *--tele = '/';
  12468. myrpt->dahditxchannel = NULL;
  12469. if (myrpt->txchanname)
  12470. {
  12471. tele = strchr(myrpt->txchanname,'/');
  12472. if (!tele)
  12473. {
  12474. fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
  12475. rpt_mutex_unlock(&myrpt->lock);
  12476. ast_hangup(myrpt->rxchannel);
  12477. pthread_exit(NULL);
  12478. }
  12479. *tele++ = 0;
  12480. myrpt->txchannel = ast_request(myrpt->txchanname, AST_FORMAT_SLINEAR, NULL, tele, NULL);
  12481. if (!strncasecmp(myrpt->txchanname,"DAHDI",3))
  12482. myrpt->dahditxchannel = myrpt->txchannel;
  12483. if (myrpt->txchannel)
  12484. {
  12485. ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
  12486. ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
  12487. #ifdef AST_CDR_FLAG_POST_DISABLED
  12488. if (myrpt->txchannel->cdr)
  12489. ast_set_flag(myrpt->txchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  12490. #endif
  12491. #ifndef NEW_ASTERISK
  12492. myrpt->txchannel->whentohangup = 0;
  12493. #endif
  12494. myrpt->txchannel->appl = "Apprpt";
  12495. myrpt->txchannel->data = "(Link Tx)";
  12496. if (option_verbose > 2)
  12497. ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
  12498. myrpt->txchanname,tele,myrpt->txchannel->name);
  12499. rpt_mutex_unlock(&myrpt->lock);
  12500. ast_call(myrpt->txchannel,tele,999);
  12501. rpt_mutex_lock(&myrpt->lock);
  12502. }
  12503. else
  12504. {
  12505. fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
  12506. rpt_mutex_unlock(&myrpt->lock);
  12507. ast_hangup(myrpt->rxchannel);
  12508. pthread_exit(NULL);
  12509. }
  12510. *--tele = '/';
  12511. }
  12512. else
  12513. {
  12514. myrpt->txchannel = myrpt->rxchannel;
  12515. if (!strncasecmp(myrpt->rxchanname,"DAHDI",3))
  12516. myrpt->dahditxchannel = myrpt->rxchannel;
  12517. }
  12518. /* allocate a pseudo-channel thru asterisk */
  12519. myrpt->pchannel = ast_request("DAHDI", AST_FORMAT_SLINEAR, NULL, "pseudo", NULL);
  12520. if (!myrpt->pchannel)
  12521. {
  12522. fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
  12523. rpt_mutex_unlock(&myrpt->lock);
  12524. if (myrpt->txchannel != myrpt->rxchannel)
  12525. ast_hangup(myrpt->txchannel);
  12526. ast_hangup(myrpt->rxchannel);
  12527. pthread_exit(NULL);
  12528. }
  12529. ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
  12530. ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
  12531. #ifdef AST_CDR_FLAG_POST_DISABLED
  12532. if (myrpt->pchannel->cdr)
  12533. ast_set_flag(myrpt->pchannel->cdr,AST_CDR_FLAG_POST_DISABLED);
  12534. #endif
  12535. if (!myrpt->dahdirxchannel) myrpt->dahdirxchannel = myrpt->pchannel;
  12536. if (!myrpt->dahditxchannel) myrpt->dahditxchannel = myrpt->pchannel;
  12537. /* make a conference for the pseudo */
  12538. ci.chan = 0;
  12539. ci.confno = -1; /* make a new conf */
  12540. ci.confmode = DAHDI_CONF_CONFANNMON ;
  12541. /* first put the channel on the conference in announce/monitor mode */
  12542. if (ioctl(myrpt->pchannel->fds[0],DAHDI_SETCONF,&ci) == -1)
  12543. {
  12544. ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
  12545. rpt_mutex_unlock(&myrpt->lock);
  12546. ast_hangup(myrpt->pchannel);
  12547. if (myrpt->txchannel != myrpt->rxchannel)
  12548. ast_hangup(myrpt->txchannel);
  12549. ast_hangup(myrpt->rxchannel);
  12550. pthread_exit(NULL);
  12551. }
  12552. /* save pseudo channel conference number */
  12553. myrpt->conf = myrpt->txconf = ci.confno;
  12554. /* if serial io port, open it */
  12555. myrpt->iofd = -1;
  12556. if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt,myrpt->p.ioport)) == -1))
  12557. {
  12558. rpt_mutex_unlock(&myrpt->lock);
  12559. ast_hangup(myrpt->pchannel);
  12560. if (myrpt->txchannel != myrpt->rxchannel)
  12561. ast_hangup(myrpt->txchannel);
  12562. ast_hangup(myrpt->rxchannel);
  12563. pthread_exit(NULL);
  12564. }
  12565. iskenwood_pci4 = 0;
  12566. memset(&z,0,sizeof(z));
  12567. if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->dahditxchannel))
  12568. {
  12569. z.radpar = DAHDI_RADPAR_REMMODE;
  12570. z.data = DAHDI_RADPAR_REM_NONE;
  12571. res = ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z);
  12572. /* if PCIRADIO and kenwood selected */
  12573. if ((!res) && (!strcmp(myrpt->remoterig,remote_rig_kenwood)))
  12574. {
  12575. z.radpar = DAHDI_RADPAR_UIOMODE;
  12576. z.data = 1;
  12577. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12578. {
  12579. ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
  12580. return -1;
  12581. }
  12582. z.radpar = DAHDI_RADPAR_UIODATA;
  12583. z.data = 3;
  12584. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12585. {
  12586. ast_log(LOG_ERROR,"Cannot set UIODATA\n");
  12587. return -1;
  12588. }
  12589. i = DAHDI_OFFHOOK;
  12590. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
  12591. {
  12592. ast_log(LOG_ERROR,"Cannot set hook\n");
  12593. return -1;
  12594. }
  12595. iskenwood_pci4 = 1;
  12596. }
  12597. }
  12598. if (myrpt->txchannel == myrpt->dahditxchannel)
  12599. {
  12600. i = DAHDI_ONHOOK;
  12601. ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i);
  12602. /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
  12603. if ((myrpt->iofd < 1) && (!res) &&
  12604. ((!strcmp(myrpt->remoterig,remote_rig_ft897)) ||
  12605. (!strcmp(myrpt->remoterig,remote_rig_ic706)) ||
  12606. (!strcmp(myrpt->remoterig,remote_rig_tm271))))
  12607. {
  12608. z.radpar = DAHDI_RADPAR_UIOMODE;
  12609. z.data = 1;
  12610. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12611. {
  12612. ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
  12613. return -1;
  12614. }
  12615. z.radpar = DAHDI_RADPAR_UIODATA;
  12616. z.data = 3;
  12617. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12618. {
  12619. ast_log(LOG_ERROR,"Cannot set UIODATA\n");
  12620. return -1;
  12621. }
  12622. }
  12623. }
  12624. myrpt->remoterx = 0;
  12625. myrpt->remotetx = 0;
  12626. myrpt->retxtimer = 0;
  12627. myrpt->rerxtimer = 0;
  12628. myrpt->remoteon = 1;
  12629. myrpt->dtmfidx = -1;
  12630. myrpt->dtmfbuf[0] = 0;
  12631. myrpt->dtmf_time_rem = 0;
  12632. myrpt->hfscanmode = 0;
  12633. myrpt->hfscanstatus = 0;
  12634. if (myrpt->p.startupmacro)
  12635. {
  12636. snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
  12637. }
  12638. time(&myrpt->start_time);
  12639. myrpt->last_activity_time = myrpt->start_time;
  12640. last_timeout_warning = 0;
  12641. myrpt->reload = 0;
  12642. myrpt->tele.next = &myrpt->tele;
  12643. myrpt->tele.prev = &myrpt->tele;
  12644. myrpt->newkey = 0;
  12645. rpt_mutex_unlock(&myrpt->lock);
  12646. ast_set_write_format(chan, AST_FORMAT_SLINEAR);
  12647. ast_set_read_format(chan, AST_FORMAT_SLINEAR);
  12648. rem_rx = 0;
  12649. remkeyed = 0;
  12650. /* if we are on 2w loop and are a remote, turn EC on */
  12651. if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
  12652. {
  12653. i = 128;
  12654. ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_ECHOCANCEL,&i);
  12655. }
  12656. if (chan->_state != AST_STATE_UP) {
  12657. ast_answer(chan);
  12658. if (!phone_mode) send_newkey(chan);
  12659. }
  12660. if (myrpt->rxchannel == myrpt->dahdirxchannel)
  12661. {
  12662. if (ioctl(myrpt->dahdirxchannel->fds[0],DAHDI_GET_PARAMS,&par) != -1)
  12663. {
  12664. if (par.rxisoffhook)
  12665. {
  12666. ast_indicate(chan,AST_CONTROL_RADIO_KEY);
  12667. myrpt->remoterx = 1;
  12668. remkeyed = 1;
  12669. }
  12670. }
  12671. }
  12672. if (myrpt->p.archivedir)
  12673. {
  12674. char mycmd[100],mydate[100],*b,*b1;
  12675. time_t myt;
  12676. long blocksleft;
  12677. mkdir(myrpt->p.archivedir,0600);
  12678. sprintf(mycmd,"%s/%s",myrpt->p.archivedir,myrpt->name);
  12679. mkdir(mycmd,0600);
  12680. time(&myt);
  12681. strftime(mydate,sizeof(mydate) - 1,"%Y%m%d%H%M%S",
  12682. localtime(&myt));
  12683. sprintf(mycmd,"mixmonitor start %s %s/%s/%s.wav49 a",chan->name,
  12684. myrpt->p.archivedir,myrpt->name,mydate);
  12685. if (myrpt->p.monminblocks)
  12686. {
  12687. blocksleft = diskavail(myrpt);
  12688. if (myrpt->p.remotetimeout)
  12689. {
  12690. blocksleft -= (myrpt->p.remotetimeout *
  12691. MONITOR_DISK_BLOCKS_PER_MINUTE) / 60;
  12692. }
  12693. if (blocksleft >= myrpt->p.monminblocks)
  12694. ast_cli_command(nullfd,mycmd);
  12695. } else ast_cli_command(nullfd,mycmd);
  12696. /* look at callerid to see what node this comes from */
  12697. b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
  12698. if (!b) /* if doesn't have caller id */
  12699. {
  12700. b1 = "0";
  12701. } else {
  12702. b1 = ast_strdupa(b);
  12703. ast_shrink_phone_number(b1);
  12704. }
  12705. sprintf(mycmd,"CONNECT,%s",b1);
  12706. donodelog(myrpt,mycmd);
  12707. }
  12708. myrpt->loginuser[0] = 0;
  12709. myrpt->loginlevel[0] = 0;
  12710. myrpt->authtelltimer = 0;
  12711. myrpt->authtimer = 0;
  12712. authtold = 0;
  12713. authreq = 0;
  12714. if (myrpt->p.authlevel > 1) authreq = 1;
  12715. setrem(myrpt);
  12716. n = 0;
  12717. dtmfed = 0;
  12718. cs[n++] = chan;
  12719. cs[n++] = myrpt->rxchannel;
  12720. cs[n++] = myrpt->pchannel;
  12721. if (myrpt->rxchannel != myrpt->txchannel)
  12722. cs[n++] = myrpt->txchannel;
  12723. if (!phone_mode) send_newkey(chan);
  12724. /* start un-locked */
  12725. for(;;)
  12726. {
  12727. if (ast_check_hangup(chan)) break;
  12728. if (ast_check_hangup(myrpt->rxchannel)) break;
  12729. notremming = 0;
  12730. setting = 0;
  12731. reming = 0;
  12732. telem = myrpt->tele.next;
  12733. while(telem != &myrpt->tele)
  12734. {
  12735. if (telem->mode == SETREMOTE) setting = 1;
  12736. if ((telem->mode == SETREMOTE) ||
  12737. (telem->mode == SCAN) ||
  12738. (telem->mode == TUNE)) reming = 1;
  12739. else notremming = 1;
  12740. telem = telem->next;
  12741. }
  12742. if (myrpt->reload)
  12743. {
  12744. myrpt->reload = 0;
  12745. /* find our index, and load the vars */
  12746. for(i = 0; i < nrpts; i++)
  12747. {
  12748. if (&rpt_vars[i] == myrpt)
  12749. {
  12750. load_rpt_vars(i,0);
  12751. break;
  12752. }
  12753. }
  12754. }
  12755. time(&t);
  12756. if (myrpt->p.remotetimeout)
  12757. {
  12758. time_t r;
  12759. r = (t - myrpt->start_time);
  12760. if (r >= myrpt->p.remotetimeout)
  12761. {
  12762. saynode(myrpt,chan,myrpt->name);
  12763. sayfile(chan,"rpt/timeout");
  12764. ast_safe_sleep(chan,1000);
  12765. break;
  12766. }
  12767. if ((myrpt->p.remotetimeoutwarning) &&
  12768. (r >= (myrpt->p.remotetimeout -
  12769. myrpt->p.remotetimeoutwarning)) &&
  12770. (r <= (myrpt->p.remotetimeout -
  12771. myrpt->p.remotetimeoutwarningfreq)))
  12772. {
  12773. if (myrpt->p.remotetimeoutwarningfreq)
  12774. {
  12775. if ((t - last_timeout_warning) >=
  12776. myrpt->p.remotetimeoutwarningfreq)
  12777. {
  12778. time(&last_timeout_warning);
  12779. rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
  12780. }
  12781. }
  12782. else
  12783. {
  12784. if (!last_timeout_warning)
  12785. {
  12786. time(&last_timeout_warning);
  12787. rpt_telemetry(myrpt,TIMEOUT_WARNING,0);
  12788. }
  12789. }
  12790. }
  12791. }
  12792. if (myrpt->p.remoteinacttimeout && myrpt->last_activity_time)
  12793. {
  12794. time_t r;
  12795. r = (t - myrpt->last_activity_time);
  12796. if (r >= myrpt->p.remoteinacttimeout)
  12797. {
  12798. saynode(myrpt,chan,myrpt->name);
  12799. ast_safe_sleep(chan,1000);
  12800. break;
  12801. }
  12802. if ((myrpt->p.remotetimeoutwarning) &&
  12803. (r >= (myrpt->p.remoteinacttimeout -
  12804. myrpt->p.remotetimeoutwarning)) &&
  12805. (r <= (myrpt->p.remoteinacttimeout -
  12806. myrpt->p.remotetimeoutwarningfreq)))
  12807. {
  12808. if (myrpt->p.remotetimeoutwarningfreq)
  12809. {
  12810. if ((t - last_timeout_warning) >=
  12811. myrpt->p.remotetimeoutwarningfreq)
  12812. {
  12813. time(&last_timeout_warning);
  12814. rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
  12815. }
  12816. }
  12817. else
  12818. {
  12819. if (!last_timeout_warning)
  12820. {
  12821. time(&last_timeout_warning);
  12822. rpt_telemetry(myrpt,ACT_TIMEOUT_WARNING,0);
  12823. }
  12824. }
  12825. }
  12826. }
  12827. ms = MSWAIT;
  12828. who = ast_waitfor_n(cs,n,&ms);
  12829. if (who == NULL) ms = 0;
  12830. elap = MSWAIT - ms;
  12831. if (myrpt->macrotimer) myrpt->macrotimer -= elap;
  12832. if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
  12833. if (!ms) continue;
  12834. /* do local dtmf timer */
  12835. if (myrpt->dtmf_local_timer)
  12836. {
  12837. if (myrpt->dtmf_local_timer > 1) myrpt->dtmf_local_timer -= elap;
  12838. if (myrpt->dtmf_local_timer < 1) myrpt->dtmf_local_timer = 1;
  12839. }
  12840. rpt_mutex_lock(&myrpt->lock);
  12841. do_dtmf_local(myrpt,0);
  12842. rpt_mutex_unlock(&myrpt->lock);
  12843. //
  12844. rem_totx = myrpt->dtmf_local_timer && (!phone_mode);
  12845. rem_totx |= keyed && (!myrpt->tunerequest);
  12846. rem_rx = (remkeyed && (!setting)) || (myrpt->tele.next != &myrpt->tele);
  12847. if(!strcmp(myrpt->remoterig, remote_rig_ic706))
  12848. rem_totx |= myrpt->tunerequest;
  12849. //
  12850. if((debug > 6) && rem_totx) {
  12851. ast_log(LOG_NOTICE,"Set rem_totx=%i. dtmf_local_timer=%i phone_mode=%i keyed=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,phone_mode,keyed,myrpt->tunerequest);
  12852. }
  12853. if (keyed && (!keyed1))
  12854. {
  12855. keyed1 = 1;
  12856. }
  12857. if (!keyed && (keyed1))
  12858. {
  12859. time_t myt;
  12860. keyed1 = 0;
  12861. time(&myt);
  12862. /* if login necessary, and not too soon */
  12863. if ((myrpt->p.authlevel) &&
  12864. (!myrpt->loginlevel[0]) &&
  12865. (myt > (t + 3)))
  12866. {
  12867. authreq = 1;
  12868. authtold = 0;
  12869. myrpt->authtelltimer = AUTHTELLTIME - AUTHTXTIME;
  12870. }
  12871. }
  12872. if (rem_rx && (!myrpt->remoterx))
  12873. {
  12874. myrpt->remoterx = 1;
  12875. ast_indicate(chan,AST_CONTROL_RADIO_KEY);
  12876. }
  12877. if ((!rem_rx) && (myrpt->remoterx))
  12878. {
  12879. myrpt->remoterx = 0;
  12880. ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
  12881. }
  12882. /* if auth requested, and not authed yet */
  12883. if (authreq && (!myrpt->loginlevel[0]))
  12884. {
  12885. if ((!authtold) && ((myrpt->authtelltimer += elap)
  12886. >= AUTHTELLTIME))
  12887. {
  12888. authtold = 1;
  12889. rpt_telemetry(myrpt,LOGINREQ,NULL);
  12890. }
  12891. if ((myrpt->authtimer += elap) >= AUTHLOGOUTTIME)
  12892. {
  12893. break; /* if not logged in, hang up after a time */
  12894. }
  12895. }
  12896. if (myrpt->newkey)
  12897. {
  12898. if ((myrpt->retxtimer += elap) >= REDUNDANT_TX_TIME)
  12899. {
  12900. myrpt->retxtimer = 0;
  12901. if ((myrpt->remoterx) && (!myrpt->remotetx))
  12902. ast_indicate(chan,AST_CONTROL_RADIO_KEY);
  12903. else
  12904. ast_indicate(chan,AST_CONTROL_RADIO_UNKEY);
  12905. }
  12906. if ((myrpt->rerxtimer += elap) >= (REDUNDANT_TX_TIME * 2))
  12907. {
  12908. keyed = 0;
  12909. myrpt->rerxtimer = 0;
  12910. }
  12911. }
  12912. if (rem_totx && (!myrpt->remotetx))
  12913. {
  12914. /* if not authed, and needed, do not transmit */
  12915. if ((!myrpt->p.authlevel) || myrpt->loginlevel[0])
  12916. {
  12917. if(debug > 6)
  12918. ast_log(LOG_NOTICE,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx,myrpt->dtmf_local_timer,myrpt->tunerequest);
  12919. myrpt->remotetx = 1;
  12920. /* asdf maw ??? is this really what you want? Doesn't it always get executed? */
  12921. if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
  12922. {
  12923. time(&myrpt->last_activity_time);
  12924. if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
  12925. {
  12926. z.radpar = DAHDI_RADPAR_UIODATA;
  12927. z.data = 1;
  12928. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12929. {
  12930. ast_log(LOG_ERROR,"Cannot set UIODATA\n");
  12931. return -1;
  12932. }
  12933. }
  12934. else
  12935. {
  12936. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
  12937. }
  12938. if (myrpt->p.archivedir) donodelog(myrpt,"TXKEY");
  12939. }
  12940. }
  12941. }
  12942. if ((!rem_totx) && myrpt->remotetx) /* Remote base radio TX unkey */
  12943. {
  12944. myrpt->remotetx = 0;
  12945. if(!myrpt->remtxfreqok){
  12946. rpt_telemetry(myrpt,UNAUTHTX,NULL);
  12947. }
  12948. if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
  12949. {
  12950. z.radpar = DAHDI_RADPAR_UIODATA;
  12951. z.data = 3;
  12952. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  12953. {
  12954. ast_log(LOG_ERROR,"Cannot set UIODATA\n");
  12955. return -1;
  12956. }
  12957. }
  12958. else
  12959. {
  12960. ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
  12961. }
  12962. if (myrpt->p.archivedir) donodelog(myrpt,"TXUNKEY");
  12963. }
  12964. if (myrpt->hfscanmode){
  12965. myrpt->scantimer -= elap;
  12966. if(myrpt->scantimer <= 0){
  12967. if (!reming)
  12968. {
  12969. myrpt->scantimer = REM_SCANTIME;
  12970. rpt_telemetry(myrpt,SCAN,0);
  12971. } else myrpt->scantimer = 1;
  12972. }
  12973. }
  12974. rpt_mutex_lock(&myrpt->lock);
  12975. c = myrpt->macrobuf[0];
  12976. if (c && (!myrpt->macrotimer))
  12977. {
  12978. myrpt->macrotimer = MACROTIME;
  12979. memmove(myrpt->macrobuf,myrpt->macrobuf + 1,MAXMACRO - 1);
  12980. if ((c == 'p') || (c == 'P'))
  12981. myrpt->macrotimer = MACROPTIME;
  12982. rpt_mutex_unlock(&myrpt->lock);
  12983. if (myrpt->p.archivedir)
  12984. {
  12985. char str[100];
  12986. sprintf(str,"DTMF(M),%c",c);
  12987. donodelog(myrpt,str);
  12988. }
  12989. if (handle_remote_dtmf_digit(myrpt,c,&keyed,0) == -1) break;
  12990. continue;
  12991. } else rpt_mutex_unlock(&myrpt->lock);
  12992. if (who == chan) /* if it was a read from incoming */
  12993. {
  12994. f = ast_read(chan);
  12995. if (!f)
  12996. {
  12997. if (debug) printf("@@@@ link:Hung Up\n");
  12998. break;
  12999. }
  13000. if (f->frametype == AST_FRAME_VOICE)
  13001. {
  13002. if (ioctl(chan->fds[0], DAHDI_GETCONFMUTE, &ismuted) == -1)
  13003. {
  13004. ismuted = 0;
  13005. }
  13006. /* if not transmitting, zero-out audio */
  13007. ismuted |= (!myrpt->remotetx);
  13008. if (dtmfed && phone_mode) ismuted = 1;
  13009. dtmfed = 0;
  13010. if (ismuted)
  13011. {
  13012. memset(f->data.ptr,0,f->datalen);
  13013. if (myrpt->lastf1)
  13014. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  13015. if (myrpt->lastf2)
  13016. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  13017. }
  13018. if (f) f2 = ast_frdup(f);
  13019. else f2 = NULL;
  13020. f1 = myrpt->lastf2;
  13021. myrpt->lastf2 = myrpt->lastf1;
  13022. myrpt->lastf1 = f2;
  13023. if (ismuted)
  13024. {
  13025. if (myrpt->lastf1)
  13026. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  13027. if (myrpt->lastf2)
  13028. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  13029. }
  13030. if (f1)
  13031. {
  13032. if (phone_mode)
  13033. ast_write(myrpt->txchannel,f1);
  13034. else
  13035. ast_write(myrpt->txchannel,f);
  13036. ast_frfree(f1);
  13037. }
  13038. }
  13039. #ifndef OLD_ASTERISK
  13040. else if (f->frametype == AST_FRAME_DTMF_BEGIN)
  13041. {
  13042. if (myrpt->lastf1)
  13043. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  13044. if (myrpt->lastf2)
  13045. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  13046. dtmfed = 1;
  13047. }
  13048. #endif
  13049. if (f->frametype == AST_FRAME_DTMF)
  13050. {
  13051. if (myrpt->lastf1)
  13052. memset(myrpt->lastf1->data.ptr,0,myrpt->lastf1->datalen);
  13053. if (myrpt->lastf2)
  13054. memset(myrpt->lastf2->data.ptr,0,myrpt->lastf2->datalen);
  13055. dtmfed = 1;
  13056. if (handle_remote_phone_dtmf(myrpt,f->subclass.integer,&keyed,phone_mode) == -1)
  13057. {
  13058. if (debug) printf("@@@@ rpt:Hung Up\n");
  13059. ast_frfree(f);
  13060. break;
  13061. }
  13062. }
  13063. if (f->frametype == AST_FRAME_TEXT)
  13064. {
  13065. if (handle_remote_data(myrpt,f->data.ptr) == -1)
  13066. {
  13067. if (debug) printf("@@@@ rpt:Hung Up\n");
  13068. ast_frfree(f);
  13069. break;
  13070. }
  13071. }
  13072. if (f->frametype == AST_FRAME_CONTROL)
  13073. {
  13074. if (f->subclass.integer == AST_CONTROL_HANGUP)
  13075. {
  13076. if (debug) printf("@@@@ rpt:Hung Up\n");
  13077. ast_frfree(f);
  13078. break;
  13079. }
  13080. /* if RX key */
  13081. if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
  13082. {
  13083. if (debug == 7) printf("@@@@ rx key\n");
  13084. keyed = 1;
  13085. myrpt->rerxtimer = 0;
  13086. }
  13087. /* if RX un-key */
  13088. if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
  13089. {
  13090. myrpt->rerxtimer = 0;
  13091. if (debug == 7) printf("@@@@ rx un-key\n");
  13092. keyed = 0;
  13093. }
  13094. }
  13095. ast_frfree(f);
  13096. continue;
  13097. }
  13098. if (who == myrpt->rxchannel) /* if it was a read from radio */
  13099. {
  13100. f = ast_read(myrpt->rxchannel);
  13101. if (!f)
  13102. {
  13103. if (debug) printf("@@@@ link:Hung Up\n");
  13104. break;
  13105. }
  13106. if (f->frametype == AST_FRAME_VOICE)
  13107. {
  13108. int myreming = 0;
  13109. if(!strcmp(myrpt->remoterig, remote_rig_kenwood))
  13110. myreming = reming;
  13111. if (myreming || (!remkeyed) ||
  13112. ((myrpt->remote) && (myrpt->remotetx)) ||
  13113. ((myrpt->remmode != REM_MODE_FM) &&
  13114. notremming))
  13115. memset(f->data.ptr,0,f->datalen);
  13116. ast_write(myrpt->pchannel,f);
  13117. }
  13118. else if (f->frametype == AST_FRAME_CONTROL)
  13119. {
  13120. if (f->subclass.integer == AST_CONTROL_HANGUP)
  13121. {
  13122. if (debug) printf("@@@@ rpt:Hung Up\n");
  13123. ast_frfree(f);
  13124. break;
  13125. }
  13126. /* if RX key */
  13127. if (f->subclass.integer == AST_CONTROL_RADIO_KEY)
  13128. {
  13129. if (debug == 7) printf("@@@@ remote rx key\n");
  13130. if (!myrpt->remotetx)
  13131. {
  13132. remkeyed = 1;
  13133. }
  13134. }
  13135. /* if RX un-key */
  13136. if (f->subclass.integer == AST_CONTROL_RADIO_UNKEY)
  13137. {
  13138. if (debug == 7) printf("@@@@ remote rx un-key\n");
  13139. if (!myrpt->remotetx)
  13140. {
  13141. remkeyed = 0;
  13142. }
  13143. }
  13144. }
  13145. ast_frfree(f);
  13146. continue;
  13147. }
  13148. if (who == myrpt->pchannel) /* if is remote mix output */
  13149. {
  13150. f = ast_read(myrpt->pchannel);
  13151. if (!f)
  13152. {
  13153. if (debug) printf("@@@@ link:Hung Up\n");
  13154. break;
  13155. }
  13156. if (f->frametype == AST_FRAME_VOICE)
  13157. {
  13158. ast_write(chan,f);
  13159. }
  13160. if (f->frametype == AST_FRAME_CONTROL)
  13161. {
  13162. if (f->subclass.integer == AST_CONTROL_HANGUP)
  13163. {
  13164. if (debug) printf("@@@@ rpt:Hung Up\n");
  13165. ast_frfree(f);
  13166. break;
  13167. }
  13168. }
  13169. ast_frfree(f);
  13170. continue;
  13171. }
  13172. if ((myrpt->rxchannel != myrpt->txchannel) &&
  13173. (who == myrpt->txchannel)) /* do this cuz you have to */
  13174. {
  13175. f = ast_read(myrpt->txchannel);
  13176. if (!f)
  13177. {
  13178. if (debug) printf("@@@@ link:Hung Up\n");
  13179. break;
  13180. }
  13181. if (f->frametype == AST_FRAME_CONTROL)
  13182. {
  13183. if (f->subclass.integer == AST_CONTROL_HANGUP)
  13184. {
  13185. if (debug) printf("@@@@ rpt:Hung Up\n");
  13186. ast_frfree(f);
  13187. break;
  13188. }
  13189. }
  13190. ast_frfree(f);
  13191. continue;
  13192. }
  13193. }
  13194. if (myrpt->p.archivedir)
  13195. {
  13196. char mycmd[100],*b,*b1;
  13197. /* look at callerid to see what node this comes from */
  13198. b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
  13199. if (!b) /* if doesn't have caller id */
  13200. {
  13201. b1 = "0";
  13202. } else {
  13203. b1 = ast_strdupa(b);
  13204. ast_shrink_phone_number(b1);
  13205. }
  13206. sprintf(mycmd,"DISCONNECT,%s",b1);
  13207. donodelog(myrpt,mycmd);
  13208. }
  13209. /* wait for telem to be done */
  13210. while(myrpt->tele.next != &myrpt->tele) usleep(100000);
  13211. sprintf(tmp,"mixmonitor stop %s",chan->name);
  13212. ast_cli_command(nullfd,tmp);
  13213. close(nullfd);
  13214. rpt_mutex_lock(&myrpt->lock);
  13215. myrpt->hfscanmode = 0;
  13216. myrpt->hfscanstatus = 0;
  13217. myrpt->remoteon = 0;
  13218. rpt_mutex_unlock(&myrpt->lock);
  13219. if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
  13220. myrpt->lastf1 = NULL;
  13221. if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
  13222. myrpt->lastf2 = NULL;
  13223. if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->dahditxchannel))
  13224. {
  13225. z.radpar = DAHDI_RADPAR_UIOMODE;
  13226. z.data = 3;
  13227. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  13228. {
  13229. ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
  13230. return -1;
  13231. }
  13232. z.radpar = DAHDI_RADPAR_UIODATA;
  13233. z.data = 3;
  13234. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_RADIO_SETPARAM,&z) == -1)
  13235. {
  13236. ast_log(LOG_ERROR,"Cannot set UIODATA\n");
  13237. return -1;
  13238. }
  13239. i = DAHDI_OFFHOOK;
  13240. if (ioctl(myrpt->dahditxchannel->fds[0],DAHDI_HOOK,&i) == -1)
  13241. {
  13242. ast_log(LOG_ERROR,"Cannot set hook\n");
  13243. return -1;
  13244. }
  13245. }
  13246. if (myrpt->iofd) close(myrpt->iofd);
  13247. myrpt->iofd = -1;
  13248. ast_hangup(myrpt->pchannel);
  13249. if (myrpt->rxchannel != myrpt->txchannel) ast_hangup(myrpt->txchannel);
  13250. ast_hangup(myrpt->rxchannel);
  13251. closerem(myrpt);
  13252. if (myrpt->p.rptnode)
  13253. {
  13254. rpt_mutex_lock(&myrpt->lock);
  13255. for(i = 0; i < nrpts; i++)
  13256. {
  13257. if (!strcasecmp(rpt_vars[i].name,myrpt->p.rptnode))
  13258. {
  13259. rpt_vars[i].xlink = 0;
  13260. break;
  13261. }
  13262. }
  13263. rpt_mutex_unlock(&myrpt->lock);
  13264. }
  13265. #ifdef OLD_ASTERISK
  13266. LOCAL_USER_REMOVE(u);
  13267. #endif
  13268. return res;
  13269. }
  13270. #ifndef OLD_ASTERISK
  13271. /*!\brief callback to display list of locally configured nodes
  13272. \addtogroup Group_AMI
  13273. */
  13274. static int manager_rpt_local_nodes(struct mansession *s, const struct message *m)
  13275. {
  13276. int i;
  13277. astman_append(s, "<?xml version=\"1.0\"?>\r\n");
  13278. astman_append(s, "<nodes>\r\n");
  13279. for (i=0; i< nrpts; i++)
  13280. {
  13281. astman_append(s, " <node>%s</node>\r\n", rpt_vars[i].name);
  13282. } /* for i */
  13283. astman_append(s, "</nodes>\r\n");
  13284. astman_append(s, "\r\n"); /* Properly terminate Manager output */
  13285. return RESULT_SUCCESS;
  13286. } /* manager_rpt_local_nodes() */
  13287. /*
  13288. * Append Success and ActionID to manager response message
  13289. */
  13290. static void rpt_manager_success(struct mansession *s, const struct message *m)
  13291. {
  13292. const char *id = astman_get_header(m, "ActionID");
  13293. if (!ast_strlen_zero(id))
  13294. astman_append(s, "ActionID: %s\r\n", id);
  13295. astman_append(s, "Response: Success\r\n");
  13296. }
  13297. /*
  13298. * Dump statistics to manager session
  13299. */
  13300. static int rpt_manager_do_stats(struct mansession *s, const struct message *m, char *str)
  13301. {
  13302. int i,j,numoflinks;
  13303. int dailytxtime, dailykerchunks;
  13304. time_t now;
  13305. int totalkerchunks, dailykeyups, totalkeyups, timeouts;
  13306. int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
  13307. long long totaltxtime;
  13308. struct rpt_link *l;
  13309. char *listoflinks[MAX_STAT_LINKS];
  13310. char *lastdtmfcommand,*parrot_ena;
  13311. char *tot_state, *ider_state, *patch_state;
  13312. char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
  13313. char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
  13314. char *transmitterkeyed;
  13315. const char *node = astman_get_header(m, "Node");
  13316. struct rpt *myrpt;
  13317. static char *not_applicable = "N/A";
  13318. tot_state = ider_state =
  13319. patch_state = reverse_patch_state =
  13320. input_signal = not_applicable;
  13321. called_number = lastdtmfcommand = transmitterkeyed = NULL;
  13322. time(&now);
  13323. for(i = 0; i < nrpts; i++)
  13324. {
  13325. if ((node)&&(!strcmp(node,rpt_vars[i].name))){
  13326. rpt_manager_success(s,m);
  13327. myrpt = &rpt_vars[i];
  13328. if(myrpt->remote){ /* Remote base ? */
  13329. char *loginuser, *loginlevel, *freq, *rxpl, *txpl, *modestr;
  13330. char offset = 0, powerlevel = 0, rxplon = 0, txplon = 0, remoteon, remmode = 0, reportfmstuff;
  13331. char offsetc,powerlevelc;
  13332. loginuser = loginlevel = freq = rxpl = txpl = NULL;
  13333. /* Make a copy of all stat variables while locked */
  13334. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  13335. if((remoteon = myrpt->remoteon)){
  13336. if(!ast_strlen_zero(myrpt->loginuser))
  13337. loginuser = ast_strdup(myrpt->loginuser);
  13338. if(!ast_strlen_zero(myrpt->loginlevel))
  13339. loginlevel = ast_strdup(myrpt->loginlevel);
  13340. if(!ast_strlen_zero(myrpt->freq))
  13341. freq = ast_strdup(myrpt->freq);
  13342. if(!ast_strlen_zero(myrpt->rxpl))
  13343. rxpl = ast_strdup(myrpt->rxpl);
  13344. if(!ast_strlen_zero(myrpt->txpl))
  13345. txpl = ast_strdup(myrpt->txpl);
  13346. remmode = myrpt->remmode;
  13347. offset = myrpt->offset;
  13348. powerlevel = myrpt->powerlevel;
  13349. rxplon = myrpt->rxplon;
  13350. txplon = myrpt->txplon;
  13351. }
  13352. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  13353. astman_append(s, "IsRemoteBase: YES\r\n");
  13354. astman_append(s, "RemoteOn: %s\r\n",(remoteon) ? "YES": "NO");
  13355. if(remoteon){
  13356. if(loginuser){
  13357. astman_append(s, "LogInUser: %s\r\n", loginuser);
  13358. ast_free(loginuser);
  13359. }
  13360. if(loginlevel){
  13361. astman_append(s, "LogInLevel: %s\r\n", loginlevel);
  13362. ast_free(loginlevel);
  13363. }
  13364. if(freq){
  13365. astman_append(s, "Freq: %s\r\n", freq);
  13366. ast_free(freq);
  13367. }
  13368. reportfmstuff = 0;
  13369. switch(remmode){
  13370. case REM_MODE_FM:
  13371. modestr = "FM";
  13372. reportfmstuff = 1;
  13373. break;
  13374. case REM_MODE_AM:
  13375. modestr = "AM";
  13376. break;
  13377. case REM_MODE_USB:
  13378. modestr = "USB";
  13379. break;
  13380. default:
  13381. modestr = "LSB";
  13382. break;
  13383. }
  13384. astman_append(s, "RemMode: %s\r\n", modestr);
  13385. if(reportfmstuff){
  13386. switch(offset){
  13387. case REM_SIMPLEX:
  13388. offsetc = 'S';
  13389. break;
  13390. case REM_MINUS:
  13391. offsetc = '-';
  13392. break;
  13393. default:
  13394. offsetc = '+';
  13395. break;
  13396. }
  13397. astman_append(s, "RemOffset: %c\r\n", offsetc);
  13398. if(rxplon && rxpl){
  13399. astman_append(s, "RxPl: %s\r\n",rxpl);
  13400. ast_free(rxpl);
  13401. }
  13402. if(txplon && txpl){
  13403. astman_append(s, "TxPl: %s\r\n",txpl);
  13404. ast_free(txpl);
  13405. }
  13406. }
  13407. switch(powerlevel){
  13408. case REM_LOWPWR:
  13409. powerlevelc = 'L';
  13410. break;
  13411. case REM_MEDPWR:
  13412. powerlevelc = 'M';
  13413. break;
  13414. default:
  13415. powerlevelc = 'H';
  13416. break;
  13417. }
  13418. astman_append(s,"PowerLevel: %c\r\n", powerlevelc);
  13419. }
  13420. astman_append(s, "\r\n");
  13421. return 0; /* End of remote base status reporting */
  13422. }
  13423. /* ELSE Process as a repeater node */
  13424. /* Make a copy of all stat variables while locked */
  13425. rpt_mutex_lock(&myrpt->lock); /* LOCK */
  13426. dailytxtime = myrpt->dailytxtime;
  13427. totaltxtime = myrpt->totaltxtime;
  13428. dailykeyups = myrpt->dailykeyups;
  13429. totalkeyups = myrpt->totalkeyups;
  13430. dailykerchunks = myrpt->dailykerchunks;
  13431. totalkerchunks = myrpt->totalkerchunks;
  13432. dailyexecdcommands = myrpt->dailyexecdcommands;
  13433. totalexecdcommands = myrpt->totalexecdcommands;
  13434. timeouts = myrpt->timeouts;
  13435. /* Traverse the list of connected nodes */
  13436. reverse_patch_state = "DOWN";
  13437. numoflinks = 0;
  13438. l = myrpt->links.next;
  13439. while(l && (l != &myrpt->links)){
  13440. if(numoflinks >= MAX_STAT_LINKS){
  13441. ast_log(LOG_NOTICE,
  13442. "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
  13443. break;
  13444. }
  13445. if (l->name[0] == '0'){ /* Skip '0' nodes */
  13446. reverse_patch_state = "UP";
  13447. l = l->next;
  13448. continue;
  13449. }
  13450. listoflinks[numoflinks] = ast_strdup(l->name);
  13451. if(listoflinks[numoflinks] == NULL){
  13452. break;
  13453. }
  13454. else{
  13455. numoflinks++;
  13456. }
  13457. l = l->next;
  13458. }
  13459. if(myrpt->keyed)
  13460. input_signal = "YES";
  13461. else
  13462. input_signal = "NO";
  13463. if(myrpt->txkeyed)
  13464. transmitterkeyed = "YES";
  13465. else
  13466. transmitterkeyed = "NO";
  13467. if(myrpt->p.parrotmode)
  13468. parrot_ena = "ENABLED";
  13469. else
  13470. parrot_ena = "DISABLED";
  13471. if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
  13472. sys_ena = "DISABLED";
  13473. else
  13474. sys_ena = "ENABLED";
  13475. if(myrpt->p.s[myrpt->p.sysstate_cur].totdisable)
  13476. tot_ena = "DISABLED";
  13477. else
  13478. tot_ena = "ENABLED";
  13479. if(myrpt->p.s[myrpt->p.sysstate_cur].linkfundisable)
  13480. link_ena = "DISABLED";
  13481. else
  13482. link_ena = "ENABLED";
  13483. if(myrpt->p.s[myrpt->p.sysstate_cur].autopatchdisable)
  13484. patch_ena = "DISABLED";
  13485. else
  13486. patch_ena = "ENABLED";
  13487. if(myrpt->p.s[myrpt->p.sysstate_cur].schedulerdisable)
  13488. sch_ena = "DISABLED";
  13489. else
  13490. sch_ena = "ENABLED";
  13491. if(myrpt->p.s[myrpt->p.sysstate_cur].userfundisable)
  13492. user_funs = "DISABLED";
  13493. else
  13494. user_funs = "ENABLED";
  13495. if(myrpt->p.s[myrpt->p.sysstate_cur].alternatetail)
  13496. tail_type = "ALTERNATE";
  13497. else
  13498. tail_type = "STANDARD";
  13499. if(!myrpt->totimer)
  13500. tot_state = "TIMED OUT!";
  13501. else if(myrpt->totimer != myrpt->p.totime)
  13502. tot_state = "ARMED";
  13503. else
  13504. tot_state = "RESET";
  13505. if(myrpt->tailid)
  13506. ider_state = "QUEUED IN TAIL";
  13507. else if(myrpt->mustid)
  13508. ider_state = "QUEUED FOR CLEANUP";
  13509. else
  13510. ider_state = "CLEAN";
  13511. switch(myrpt->callmode){
  13512. case 1:
  13513. patch_state = "DIALING";
  13514. break;
  13515. case 2:
  13516. patch_state = "CONNECTING";
  13517. break;
  13518. case 3:
  13519. patch_state = "UP";
  13520. break;
  13521. case 4:
  13522. patch_state = "CALL FAILED";
  13523. break;
  13524. default:
  13525. patch_state = "DOWN";
  13526. }
  13527. if(strlen(myrpt->exten)){
  13528. called_number = ast_strdup(myrpt->exten);
  13529. }
  13530. if(strlen(myrpt->lastdtmfcommand)){
  13531. lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
  13532. }
  13533. rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
  13534. astman_append(s, "IsRemoteBase: NO\r\n");
  13535. astman_append(s, "NodeState: %d\r\n", myrpt->p.sysstate_cur);
  13536. astman_append(s, "SignalOnInput: %s\r\n", input_signal);
  13537. astman_append(s, "TransmitterKeyed: %s\r\n", transmitterkeyed);
  13538. astman_append(s, "Transmitter: %s\r\n", sys_ena);
  13539. astman_append(s, "Parrot: %s\r\n", parrot_ena);
  13540. astman_append(s, "Scheduler: %s\r\n", sch_ena);
  13541. astman_append(s, "TailLength: %s\r\n", tail_type);
  13542. astman_append(s, "TimeOutTimer: %s\r\n", tot_ena);
  13543. astman_append(s, "TimeOutTimerState: %s\r\n", tot_state);
  13544. astman_append(s, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts);
  13545. astman_append(s, "IdentifierState: %s\r\n", ider_state);
  13546. astman_append(s, "KerchunksToday: %d\r\n", dailykerchunks);
  13547. astman_append(s, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks);
  13548. astman_append(s, "KeyupsToday: %d\r\n", dailykeyups);
  13549. astman_append(s, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups);
  13550. astman_append(s, "DtmfCommandsToday: %d\r\n", dailyexecdcommands);
  13551. astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
  13552. astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
  13553. (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
  13554. hours = dailytxtime/3600000;
  13555. dailytxtime %= 3600000;
  13556. minutes = dailytxtime/60000;
  13557. dailytxtime %= 60000;
  13558. seconds = dailytxtime/1000;
  13559. dailytxtime %= 1000;
  13560. astman_append(s, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
  13561. hours, minutes, seconds, dailytxtime);
  13562. hours = (int) totaltxtime/3600000;
  13563. totaltxtime %= 3600000;
  13564. minutes = (int) totaltxtime/60000;
  13565. totaltxtime %= 60000;
  13566. seconds = (int) totaltxtime/1000;
  13567. totaltxtime %= 1000;
  13568. astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
  13569. hours, minutes, seconds, (int) totaltxtime);
  13570. sprintf(str, "NodesCurrentlyConnectedToUs: ");
  13571. if(!numoflinks){
  13572. strcat(str,"<NONE>");
  13573. }
  13574. else{
  13575. for(j = 0 ;j < numoflinks; j++){
  13576. sprintf(str+strlen(str), "%s", listoflinks[j]);
  13577. if(j < numoflinks - 1)
  13578. strcat(str,",");
  13579. }
  13580. }
  13581. astman_append(s,"%s\r\n", str);
  13582. astman_append(s, "Autopatch: %s\r\n", patch_ena);
  13583. astman_append(s, "AutopatchState: %s\r\n", patch_state);
  13584. astman_append(s, "AutopatchCalledNumber: %s\r\n",
  13585. (called_number && strlen(called_number)) ? called_number : not_applicable);
  13586. astman_append(s, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state);
  13587. astman_append(s, "UserLinkingCommands: %s\r\n", link_ena);
  13588. astman_append(s, "UserFunctions: %s\r\n", user_funs);
  13589. for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
  13590. ast_free(listoflinks[j]);
  13591. }
  13592. if(called_number){
  13593. ast_free(called_number);
  13594. }
  13595. if(lastdtmfcommand){
  13596. ast_free(lastdtmfcommand);
  13597. }
  13598. astman_append(s, "\r\n"); /* We're Done! */
  13599. return 0;
  13600. }
  13601. }
  13602. astman_send_error(s, m, "RptStatus unknown or missing node");
  13603. return -1;
  13604. }
  13605. /*
  13606. * Implement the RptStatus Manager Interface
  13607. */
  13608. static int manager_rpt_status(struct mansession *s, const struct message *m)
  13609. {
  13610. int i,res,len,idx;
  13611. int uptime,hours,minutes;
  13612. time_t now;
  13613. const char *cmd = astman_get_header(m, "Command");
  13614. char *str;
  13615. enum {MGRCMD_RPTSTAT,MGRCMD_NODESTAT};
  13616. struct mgrcmdtbl{
  13617. const char *cmd;
  13618. int index;
  13619. };
  13620. static struct mgrcmdtbl mct[] = {
  13621. {"RptStat",MGRCMD_RPTSTAT},
  13622. {"NodeStat",MGRCMD_NODESTAT},
  13623. {NULL,0} /* NULL marks end of command table */
  13624. };
  13625. time(&now);
  13626. len = 1024; /* Allocate a working buffer */
  13627. if(!(str = ast_malloc(len)))
  13628. return -1;
  13629. /* Check for Command */
  13630. if(ast_strlen_zero(cmd)){
  13631. astman_send_error(s, m, "RptStatus missing command");
  13632. ast_free(str);
  13633. return 0;
  13634. }
  13635. /* Try to find the command in the table */
  13636. for(i = 0 ; mct[i].cmd ; i++){
  13637. if(!strcmp(mct[i].cmd, cmd))
  13638. break;
  13639. }
  13640. if(!mct[i].cmd){ /* Found or not found ? */
  13641. astman_send_error(s, m, "RptStatus unknown command");
  13642. ast_free(str);
  13643. return 0;
  13644. }
  13645. else
  13646. idx = mct[i].index;
  13647. switch(idx){ /* Use the index to go to the correct command */
  13648. case MGRCMD_RPTSTAT:
  13649. /* Return Nodes: and a comma separated list of nodes */
  13650. if((res = snprintf(str, len, "Nodes: ")) > -1)
  13651. len -= res;
  13652. else{
  13653. ast_free(str);
  13654. return 0;
  13655. }
  13656. for(i = 0; i < nrpts; i++){
  13657. if(i < nrpts - 1){
  13658. if((res = snprintf(str+strlen(str), len, "%s,",rpt_vars[i].name)) < 0){
  13659. ast_free(str);
  13660. return 0;
  13661. }
  13662. }
  13663. else{
  13664. if((res = snprintf(str+strlen(str), len, "%s",rpt_vars[i].name)) < 0){
  13665. ast_free(str);
  13666. return 0;
  13667. }
  13668. }
  13669. len -= res;
  13670. }
  13671. rpt_manager_success(s,m);
  13672. if(!nrpts)
  13673. astman_append(s, "<NONE>\r\n");
  13674. else
  13675. astman_append(s, "%s\r\n", str);
  13676. uptime = (int)(now - starttime);
  13677. hours = uptime/3600;
  13678. uptime %= 3600;
  13679. minutes = uptime/60;
  13680. uptime %= 60;
  13681. astman_append(s, "RptUptime: %02d:%02d:%02d\r\n",
  13682. hours, minutes, uptime);
  13683. astman_append(s, "\r\n");
  13684. break;
  13685. case MGRCMD_NODESTAT:
  13686. res = rpt_manager_do_stats(s,m,str);
  13687. ast_free(str);
  13688. return res;
  13689. default:
  13690. astman_send_error(s, m, "RptStatus invalid command");
  13691. break;
  13692. }
  13693. ast_free(str);
  13694. return 0;
  13695. }
  13696. #endif
  13697. #ifdef OLD_ASTERISK
  13698. int unload_module()
  13699. #else
  13700. static int unload_module(void)
  13701. #endif
  13702. {
  13703. int i, res;
  13704. #ifdef OLD_ASTERISK
  13705. STANDARD_HANGUP_LOCALUSERS;
  13706. #endif
  13707. for(i = 0; i < nrpts; i++) {
  13708. if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
  13709. ast_mutex_destroy(&rpt_vars[i].lock);
  13710. ast_mutex_destroy(&rpt_vars[i].remlock);
  13711. }
  13712. res = ast_unregister_application(app);
  13713. #ifdef NEW_ASTERISK
  13714. ast_cli_unregister_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
  13715. #else
  13716. /* Unregister cli extensions */
  13717. ast_cli_unregister(&cli_debug);
  13718. ast_cli_unregister(&cli_dump);
  13719. ast_cli_unregister(&cli_stats);
  13720. ast_cli_unregister(&cli_lstats);
  13721. ast_cli_unregister(&cli_nodes);
  13722. ast_cli_unregister(&cli_local_nodes);
  13723. ast_cli_unregister(&cli_reload);
  13724. ast_cli_unregister(&cli_restart);
  13725. ast_cli_unregister(&cli_fun);
  13726. ast_cli_unregister(&cli_fun1);
  13727. res |= ast_cli_unregister(&cli_cmd);
  13728. #endif
  13729. #ifndef OLD_ASTERISK
  13730. res |= ast_manager_unregister("RptLocalNodes");
  13731. res |= ast_manager_unregister("RptStatus");
  13732. #endif
  13733. return res;
  13734. }
  13735. #ifdef OLD_ASTERISK
  13736. int load_module()
  13737. #else
  13738. static int load_module(void)
  13739. #endif
  13740. {
  13741. int res;
  13742. ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
  13743. #ifdef NEW_ASTERISK
  13744. ast_cli_register_multiple(rpt_cli, ARRAY_LEN(rpt_cli));
  13745. res = 0;
  13746. #else
  13747. /* Register cli extensions */
  13748. ast_cli_register(&cli_debug);
  13749. ast_cli_register(&cli_dump);
  13750. ast_cli_register(&cli_stats);
  13751. ast_cli_register(&cli_lstats);
  13752. ast_cli_register(&cli_nodes);
  13753. ast_cli_register(&cli_local_nodes);
  13754. ast_cli_register(&cli_reload);
  13755. ast_cli_register(&cli_restart);
  13756. ast_cli_register(&cli_fun);
  13757. ast_cli_register(&cli_fun1);
  13758. res = ast_cli_register(&cli_cmd);
  13759. #endif
  13760. #ifndef OLD_ASTERISK
  13761. res |= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes, "List local node numbers");
  13762. res |= ast_manager_register("RptStatus", 0, manager_rpt_status, "Return Rpt Status for CGI");
  13763. #endif
  13764. res |= ast_register_application(app, rpt_exec, synopsis, descrip);
  13765. return res;
  13766. }
  13767. #ifdef OLD_ASTERISK
  13768. char *description()
  13769. {
  13770. return tdesc;
  13771. }
  13772. int usecount(void)
  13773. {
  13774. int res;
  13775. STANDARD_USECOUNT(res);
  13776. return res;
  13777. }
  13778. char *key()
  13779. {
  13780. return ASTERISK_GPL_KEY;
  13781. }
  13782. #endif
  13783. #ifdef OLD_ASTERISK
  13784. int reload()
  13785. #else
  13786. static int reload(void)
  13787. #endif
  13788. {
  13789. int n;
  13790. for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
  13791. return(0);
  13792. }
  13793. #ifndef OLD_ASTERISK
  13794. /* STD_MOD(MOD_1, reload, NULL, NULL); */
  13795. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Radio Repeater/Remote Base Application",
  13796. .load = load_module,
  13797. .unload = unload_module,
  13798. .reload = reload,
  13799. );
  13800. #endif