From 2f9357b2a7cd262863459fbce042e17f47563ef8 Mon Sep 17 00:00:00 2001 From: Geovani Ricardo Wiedenhoft Date: Thu, 17 Feb 2011 17:41:56 -0200 Subject: [PATCH] - fxo-busy-disconnection timer for desconnection on FXO - khomp set changes configuration - KR2GotCategory variable - Disconnection forced R2 signaling (collect call) - restricted, omits the number of origin - Option to enable/disable dial with '#' on FXS - Added KR2StrCategory - Added "khomp dump config" command - KISDNOrigTypeOfNumber, KISDNDestTypeOfNumber, KISDNOrigNumberingPlan, KISDNDestNumberingPlan, KISDNOrigPresentation - New version of commons - Updated documentation --- .../mod_khomp/Install/files/khomp.conf.xml | 24 ++ .../mod_khomp/commons/base/config_commons.hpp | 2 +- .../mod_khomp/commons/base/config_options.hpp | 28 +- .../commons/base/configurator/configfile.cpp | 5 +- .../mod_khomp/commons/base/k3lapi.cpp | 9 + .../mod_khomp/commons/base/k3lapi.hpp | 2 + .../mod_khomp/commons/base/logger.hpp | 67 +---- .../mod_khomp/commons/base/simple_lock.hpp | 4 +- .../base/system/freeswitch/simple_lock.hpp | 2 +- .../mod_khomp/commons/base/verbose.cpp | 4 +- src/mod/endpoints/mod_khomp/docs/Manual.html | 12 +- src/mod/endpoints/mod_khomp/docs/Manual.pdf | Bin 470343 -> 470577 bytes src/mod/endpoints/mod_khomp/docs/README.html | 2 +- src/mod/endpoints/mod_khomp/docs/README.pdf | Bin 399119 -> 399111 bytes .../endpoints/mod_khomp/docs/README_en.html | 3 +- .../endpoints/mod_khomp/docs/README_en.pdf | Bin 314413 -> 314423 bytes .../endpoints/mod_khomp/docs/User_Guide.html | 11 +- .../endpoints/mod_khomp/docs/User_Guide.pdf | Bin 509260 -> 464991 bytes src/mod/endpoints/mod_khomp/include/cli.h | 38 +++ src/mod/endpoints/mod_khomp/include/k3l.h | 13 + .../endpoints/mod_khomp/include/khomp_pvt.h | 29 +- .../mod_khomp/include/khomp_pvt_fxo.h | 26 +- .../mod_khomp/include/khomp_pvt_kxe1.h | 150 +++++++--- src/mod/endpoints/mod_khomp/include/opt.h | 5 +- .../endpoints/mod_khomp/include/revision.h | 2 +- src/mod/endpoints/mod_khomp/src/cli.cpp | 99 ++++++- src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp | 48 ++-- .../endpoints/mod_khomp/src/khomp_pvt_fxo.cpp | 32 ++- .../endpoints/mod_khomp/src/khomp_pvt_gsm.cpp | 3 + .../mod_khomp/src/khomp_pvt_kxe1.cpp | 272 ++++++++++++------ src/mod/endpoints/mod_khomp/src/opt.cpp | 5 +- src/mod/endpoints/mod_khomp/src/spec.cpp | 2 - src/mod/endpoints/mod_khomp/src/utils.cpp | 27 +- 33 files changed, 654 insertions(+), 272 deletions(-) diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml index 79c00516b9..069792935c 100644 --- a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml +++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml @@ -272,6 +272,15 @@ a FXS branch. --> + + + + ce6+xNn#ae@d3!6TkUfL=E`)^e zF6fO|SkDuFvkltKHcQjb=_awCuj}avsYn0Mv~=`qGfuVg{byQc`a)QIJIw#rBLn}v z&%o60drq=`XSM(N{SWT+MGeL8iwT_HQ!U{u3V5B0ObXt*7(oghRY=SFnunm)vslX1 z-|C2|_QXVwUcWA$?5dwrSp&B9#e)9g68JCi?=c6q6hZi(u)DMYpGb3=Q*==S1_qzl z@BvU>LWm*zoS3Jv41j3kXR$s&=+sM7p#IO6PqNgTJLV9^pi_{cP;=yQSr+F4$oYlL z8cbTw2^MfH}>ZI@|(wP&|#TDB{`Lyv;sydTPXBXL?IFp$)M4ae{mO+y0#qKf&TkdLjC z;0Q+hoW+3o`iC6=s5!}~k^ST{Z4-1zNo0d176WE=0VpTJs6Q3QQpWrjn1Sxf;wHxA zHE@piOfPj$wX%U5cAtuhpY3_rQP*<;P-UBV_4$VFN;}f1#1pseLJMUgWS^+iRa|g_ z=Tx2FEx&DOE_NCBI@ZuYc1{1dx=2G{LwM#vE02{~G{geLNrsRV|`IhZ1_ ziUh`_q-MP3d9Wx+?no*^+eqy=QQ$VRH9y~F91T)tQ68vJP(E3A++GNN!KaprU)eHM zeYq(|NPW^M>j1LiB%-KO@5D6h!&B5b5u)$ji1`~JRTTdMWwpzZK3+9l(g*SOaB#E( zg|uTWjW7nF`gf+V+M6x3=tcaNhn;8fz@jWGViwoRB$j{8AOKKKxa`TM#d6$BM=Y^* zeBkBv#sSRJZWsbM+KX{D?4goVc(3-z+q=l{DTj^r;J_ao`CVL?AIDNJR+o+R>+p?v zl?c%fC~;Ni-G0!462mnwwzQ>ocn7nF2lYjS{!0PSHpN(B*ooKCG4KwN={w)y&Hkku zFI;-yXan@1?VR=*lPTarV~NA^ky9UWn8I0$m`Zx$FH*Zp1 zLj1ete3%0U$I&-{z2G%PoYy=j{b${E7dzbvMVpLMPBZF$-^!U7S$&##@s;Q?GgTc? zbNe8m;-%dWTC2)ew%m``;z#GE!vnH9EW)=r!ed0o3kk{y_42P(o((v5Q8Qw^t=l&_otx-9(pPmyG>l|>fI9@gl*KjrjDRe zf_a}H$Gv-3p<+v&pJ{=j998-kUiM_&no+RCzGdZ1s(8~3+$kut%we@|qy`Y}YMS#+ z0sm(K_HjO6B*(H-XL|3iL1Sc&UG=h#Y}%<4_UlollU0U^%r!NaOK7VV0Jv^NN3yjV z01483kO=OLuT$NZfw}W3yDxX8dms}Y;d9NZS0Ezb7U*fzyt{t2@9#hkfwDv3HxLN}6Si@Cgd^i@QV0A#KtGdV|0 z1S)l^*X^ebtb~G7BgMSPzWU$08||^qQ{DUa82p~k$Md{-4&t-B132CubDvKySHuq= zj*^C)1l}%v_5j}MUO@4K!)-MB=kuBtbj=8`eetRjw_aWS*oTX>fYs~cp4n!r&V@yT zR)RpWYrtjWDvI|~J>PnvD{C8#OLC=+#H^l4x~x=Dd5mbeiy8g$S9@Aj$-$f56J?t5 zwLy1kFzK&cNleR=F+YLR2xcl{YPL%gDac6%&cYBB-MBm*R6ub=g$gR_L}3K!uH*4; zOg2$=+Ppt(+IT)F;B0;9;FI(OF3zBJQXa$CGK2Y zj!Ju}aE6XJStksQ3KnO=&U)eRoHN19U$7q?2)+)Fyl8=wWY^IyA+lp|0(^*ws#+De z@|=igvQya3+TWG04prtZk^w)0-v!b+>?R9M6JM!-eyw~F5!Za1?-i0O=hxNOg@<@v zB8(IxT5J8b&PDj!Zv{NmIr<^(Q6LO4X$Nl>4|1b3bHw`fIsU$qw{<|*+La_8I@PC5 zn>Y3vUi4?aexkiSebu?8W-{N`Uep3Xq{;|Dl>!F4mjRs$?X;p*u)F%%0)u~zW}82< zuvkXm`ep;t3`b^cW=Fw*mUJ|=30)>mQnW_nX)3(e92|h^MuP5GY_JBY%Z2)YS||dU ztZ9#eV~UtALgh0WmfyMVe@Wj$K^&I@VI&F@P$q{Tisie#C5RiSk=`e8<@})61gX^XR@NSu_6QW@sPaJM?X>C8aH(f>#BO1EU!QAlC$z@=()K*}CZyq&9# zn@<;U>X6@irrg3B;jBr07N5M?%&_^$N|XMnpa{@imRuwxC4ov3$Ddp*bApu#Y8^}` zq*g>lRf(VtwlBz}$(909ROwXu{q&wFzZ_i|(vHxG8uhehA!tKGGdA}8UobZJyg*7= z<#FNk5xrpju=DfdbaTf|=^HVvWgdw|r!BcxGoVQ@=@oF2Uy5b?kk*9PYUHi2l%d(B z*zW*C1TtzNlDJ;zsf<+}t)H$DpTWTP(yX*Q)9lgmq6|2{Con?}eg+C6g#4O=Hevax zsUq3$gI$1@BQU`%{2b-WO13UjUlI2}vCx}3T4F3v&U*NK4!WZ6hHvSQ#jeV4Y1cH( z(+~}vpUFb31+~ED?rMn?FjidrJJmfG(EbHDyoyfF=hVU7SB@<&gdYWx~%Ib9wIJDX@^Z$XA>kS5^1Y@Re_QUceaIpGPD9-$L3 zQa0~d6HR^FpFcwclo-Hih1N)J%;;zl<~k%25r5`=$a=52ArFc|4c=cf-tiSzDP)y{qv2Ty{3jA)FR2%@|_ zWA!*Ox`wSq$<`2Pv#j}Y1))w36soIbNof-EOTmn+;2Hz-xEQsPwEs;LtXOifko2Wm zIHH$itfh)js~%LxM!4UEo{c!(4oVD08nZlV#jrQBXs{ds$a@Ebt%y4SBTf#Gi8m6^ z(ftzHVIO_8AFR;he(AMAo;Eqg)OhM&Xu$M0H7&N(hodj?P@UeDfb$%0cT*~ z{33Bpi?24ba^{(X!Nck>^`roJ{}C%xxOcL!uPG6@^)O}J)(2D7M=--fg~P73@!s$C32_~_Y_%k zhRBk+a{Ik#a<3z^$+J>S9~kqyes2NjneF#0{6k`5Uk!7v;$XvOC0qvU%H(Q8sM|Tz z-#ucC?krou*1(GVHAINB>kMz-yMoYNX%>s`|540Q=-#N~buB#$1ByTJJ4 zdnceJ26W|(tNMd=iBAyF+oZ2Ee+ie$M$yZP0i$&HE`9xXuUmcn0pjdbl$d`oTOgH%IS9R*nv?BGQb-u=!)Ghz<6T zom8s0A`41-7LNCu#lz{&m{_gGnvXOAx{@+A%QzhL+>4SH+HAC>)9T(al_{*$p&K&` zvnM-;^z<#Gl!tc9&+=`d{gO6hYUFv*gxN7Vs!5KP&IJU7-C0Vz9@tzR{Vc@_z>yXy zr`h|7yS)k{WtA0yI|Oj@`H10H+Iz&D$dfP6g}axJK~CjcH_B}(@1%(=i*dKTayTOQ zuz;o6DtKGsSS^-!2MRjo5NmgFuq1{<@vV&Udsy$BV+39FQ+X4~U@wkC=5a+~s;lFyMgZvar`CI3_sK&}y_u6ba;+-2H0U0ki2xdq+)rba~^f*?9YMN_lW zi)vow4;eH8joV3&;LPF8d#wGw-arS&(_o@}uA?~+MSNIs%)tln%1niZm=-OWtV|MY zX|fqo^l5vKkD=0Lu)p#TYGPMqpL&L_FJr!yFx{u5-8_(fHm ztF$G}badLA(_O)bN_R{WFo~LknAI8B;{F}$rfE*BWwE>#bkn;Lnc2wj8G3c$@94?X zm_(DQ|CLuED^x}(nU2OiL}j4Rk`i~zG0h*Ky>FJ|#NLHR4V49sUTbZk+r^F7W7EE% z$UO-bc4L4RQ>`f%rTo_YSgc67XkyjFuC<_XAd^qwU<5BU^!51zV3SKL)+AVPGbpK1 zS(J_HjZ>Y$60HMRGONb9s3crMN4P~HT1S3VO(5Y=bmhb$Ai?qcAm@VqY7Ni6(LAtP z&#*S8WjR6E#5^>uDR_}d;tpV-bIKuHUHKu;{W-xz`JOlM+$3g3rfBZqdKh0k5NbqG zEecT*;L4_7ZK7rdI1?vt#pB*g(xNOk4wHoOHAm+~1Pb|#ni~QigNmefdo=Rk^9!nW zgu}*C**RE(4Ve2mS4`r4skG3E^E~xxbU3atMXLUoZKlaMM>QT@7je#iy~R#4S;?~D zcm~w|8|`yl?#r?F0r%yqxV;tZQ5X1*QDNn7t-hG^4K<`2uy01rFEa-*qlHS8m+6Fe zi;!HW&bV^Rs7;7<9I3=b4fo6;|5c_@b?QUQf)(m8lug``NwvH zdRjX9fO0P%h$M=}6^&v$i~nr}q`!}zp3y=%3B06dt6r2Z5QNNZGkroMQGzreH0se^}r7h1V{xyeC+4=|y)_%O0L z%LoAJ!G=Z#i=EVVKTOU#yFRCdR4$!#O;9%Yjz0w>03r8W(=?X74=U}Jd+9*e?ItVh zm^tM{kv_i&DGF2rlQcyhT$g|!R!<5mN9sDvg5Ofcylzt*^e$7aH&yj}G6k@@aRm-_ z7Q@0#dyG0}LPKe1{;*9;x^~T!qV1Gyg1;keLT9U*L}Ng{sriWO6g2gxzkD85Dt3*= zi7Tr$fN=t_uU2B3tX%Fr&Y^OLZQUdkE~ZRbQ|%qI|mum`ZHXWUrr?`5T2j&O4aVMgaqwg!_e(u7J?$3>xqpM5T&T@4@1FrK6^0viF&L=MhREr z66?@2`L~unmi%BMHfK|ms?{7l=+722&K|-V3;hwfW3$Ecuiv|JV1AuHUVZrkOESqP z01Aj|X6=hv4l#cR4k2H=H1;Ni==$lak_Hh|3ma2!X1CkZolDh*?mOrcHLBydYGC)- zFHM=|?8gFsn;cZ>U?(}wq$iG)=EEvnMvF}5@hlk8`ysYUpIscPy(sNO=reP=Iaa@I z17GUJ8yxuG!c!6kyvE+BIX6Qz7qSk%0S4`L$CnL5CAz1WxVQXP9vSp%G6(Z86c2f_yx0~xnIqmt?I##-&k<(`b?>4q8PEJEs#0T+rRCL^o z3X;85C-8`US!opfPxH9HP*ekvG4x0yX)B_kOT?=}!d3N=&-=*c!5K!HTO<#lJ7+T; zeJp?j6}UyKnAl8>l8f)GKRF=<+A>Q%S@;9c?QnFNoHd#p`hJ3N zg%$|5=j#zlPz4SZ`}m|N(MO*#TAsT7B~nK98vlXDCn(V77$HeL*FSV{*#K)M=jczV4MEaL_-B*#D}I`cMk;BJf0CT}K@0HM4ziSjrE z=3%G0hKGaIZ&(;22~xS8LJ$y>Wq%|R$vnK*HnSFA`!WN`pWMH8sId4VKT@-mGt{w$?rp3WkA2>pnVqiq5K42P=!72lnVZiunO8Sku4LXALN5oou^yQ<;bM-Jm-(OJgZq)_0 ztLB`#{)6(mvmw9s3e-xs1+)Sc{iTS0g4pNndZCiPpBb4Nk;$sB!H`k)4Lq|x#jI)` zG}ToRsu8BO0z1%=qQPpx4;Ydq*R8&i3Z3rz=a4qDku=!w0A>U{z0(+9V-J0*KeXPu zst1}!l}`YPR_(u0n~lEtOFcqkZWtbKe-)N1Fh(lVA=_eb#W;R1jo@=S_MeIjI4&h9 zvIuKiuQqQrPOq}?8rnB67V|W0E>;LM%~lj%^(G^1*5xm`?Z8p#ecJ}L@|1#r4*ztw zB?Z4CT!zqmL8!$HFyo#Ngu4#-PK|hiPrys_^0M1Hc%DdLcj|R5gob(OHC&>Qxj( zd)s$$G)bTR${Q9VJp}`bLGT1hSn9_cbmrjZ$Y!vuFjFa5)qm#9$H!Bf`6vek5}@W3 zn5LR@M&fY?*E3OF`GLkLZ69;C75&KH#?*UY7;6#|I18O6ypU+(#mspWFC;<;cBJAi zR+xnf#f}uoz~869j++`HUY>H&>PdIucl(53wQ0Xgh0gqEQ{&G3-v~1O$I6xo!3oOr zUC(=a_HF6kc3$H|@;k0w8Iu`JfUZ-LfMtgLc=<|qVbynb?f8q3XxLUmQDP?PJk?MWT*=A#L?G3N?SH3YtB;5 zRJc_~8A6WxGA&*B2R}Q(*U~X_toPJv>ES+8?ePTVN{yrLWza7SH5f>c&)7OUYAFr7 zpr$SxTu5BDqOK-c%AML2nm{g`=$ zxD_OX(L?EHqOLw5>Jze&a}8%&hrsUcZ&R4D6mghpNuml!$0TAq3@@o~Z&9i}l|fuu zyNV0Hyu3jb|Bg(f-&W1S@ za&$ThE`>}^*zhQ(*02=Qk_yokE7gscY+b|pB=NWahNRt^^R}m@Ygfnp6S$Zjlrtn@ zez$BL+<^gg5po^BN5v2pUZPvkE-Y52dP<1|15XoKy^X-NkE1r`HUfZ(v2F*nL$?am zXKm{R$zb$)T8pH;3e75r>;1LIj)&$DwtvA{a2ClD<|N3A`4Zr5%l8yc*bJMv1W&jH zVK!U66!T`^B)+DHpkMepem0viK|`sPif~J0Dt2ap5?s8p0{UvE{mr}0uX?RGb!%B?N=?RI2{9dgHdDF}TFx?T-ipDjL^2{+sqK7DTUhmxXzj% z3a)39nnBLk8^eL~D~rc%=?fEs=~D?I5UOSQPOy^_8T)CXG*+sIk`bt`3Tn6*NF;F( z-^@VP`;c?Uh4S(LqV22WqTIShr3R$CmF^w}hLCQM?rsq228mHh>1IT_ySqz55fJGT zkPsxKJMQ2)?|aUX_kK6Nd*>g1zr}u5ueH~+pS{3}erpWbee2 zl7{c1{E&eO8$OTZ(%hmi}4W{%uPZc^0go<%G3b`u%&+ zkk-GCF$KfN!o^ZEg(U^#in1!yV^6=dZ}u*{tfYp1p&w_jG0;;Dzwxp5if3(6e1U+9 z7E%jsf*obD67e)}+8YU0#|nXyOc}N&ZaFD5IF_zQj@l9B+~47{$0TgW`i|-#U=1-v z_S|#0RIV`L^fZAt4QL2dZ^rFggG25vJY5$Y3@D1L;uM$LFj_QD8*(sxalU(D=J7R{ zZ48K9vyNQ_S|jZMs^28_T7`CK!dq8b@k`p$Yd@*)s`lr5DB?k0X;5%9>C=<_MPRU6 zLo%YhW2e32c(*Y^f6?$wvZ-TB&n_ghRphO5r+Z0b*)n20=E`HEW)-WC=*CQKG~mFd z4v}@FdgXrM(x#v^X3@hp;WC(|=p9(puT#l%c0b}<0f!S}0QKFaTeK{LL%p!0puDfo zlg?S#w8YKux$JpnFiVIZGLjMIJJZvyn$hVpucA7%bxrurBGa3r%XP;|WTQf^x>g-p z*54sKW@t3;`oe1YrMwJWG}KY5;l8CMi>m7(?6RmbXroy=sbVspq)OO}l^|+ALr(>KIv#-6VABOLvMqE-){>TD zrjuaH!{1FfkKY~NRW)J`A@F{s*o5%0yzX}3OF$0`veB`rZcJg8z!JkciP8IQIHY~i z>L^`KnS9z{`i?h7DN-4&t5SMJ7U}!4v~?R@)U6HTjmhYSUK{rK9zG%4`25N^&*XPD zoz;1R9lg7HK2)9RA%Dh%EGs2ANNtyN3Z-7DpL;2_sY#@BKv;rRFKz|AZB}K|Z?Kxe z5wJ+Km1>25M7^1;q;qzxE7bBf!#LJUzJhag%_+)llvwaGxMVRKhFg2drYW%$#I2$H zwV%J=ICDJxRloFYgo;iY?-3;SiA9n|MIHt_IrjPolY%OvA&sgJkOW@z%Q427k1Fqu zQ&y`U^YL>^GJXg4TVq5)p2#i`R6Qjg&o*YJl5kUZaQe17Erm0P1&Peokl2TR;r?- zx#nGDYFDEeJeI~%u<)U>2zXV@ZX`7JBi+M_-#x7~xRju)dB5@rLH_^kqW54v>}U@k ztmEvx+>)mWJNV6q-+HP21W~8c@O>EVTv)1*ea(=A%Bo7|f;v0s*rF;?HaPd&*`lYc zuJf!A8$7}dwusf&*5vO6y3$NWB!=H>S!F$H7?^7;9%Za=(H4N@il$5BfUHIf6(q(*E!*a_f4{`PeU7!y=1e_1Eex2y;G$DOhukH6<+* zTd$;yXj#bL-m;Y9wj{}EECRkaWiQ0~_8iG+x2euDxc!vlcZtAKwAvHo-U!PbeV3;# z-J(!EukTUX_T|!RmcoZ#J^l@Pp|w8QoHKz}ZtXx4BZP2+ffYeip|m9E@p~?V9i&S5 z$l2O5{vg{7DZ$E?hhWi;DR}nB)BIK6qu1909)Ir;@o&ru6DrJt)gvC(M$~w5^Y!Ck z=|hSfa$WB)=Bo6%O#xAvM~wz~M>Pg3KUg-y^-asneBj#~vmA0CMAjBO%F&2geKcoH zm;AyuT@%uKlGbQ0nAIB?6ZwUFD-tOhh@3dQ*z7ze$aPC1kR`LkZGiVUdsb&b5N`K9 z8h+5L2#iO9pi(&%Hlu+Y^)7F9aQvzJPRULAkQjm;amT2I8q@Y|-TQ1EdP}WTd*U>i zIe>40ZNY8_6IIY)Q5#_y&GND=S)`G^KdFvFFCS#V1TN^toIX^PhIEhAWdkFWvOk42 zt=0b_ng&X^5P&mq^`WC3{PO{?7O>WNJ`K|g5z6XulJ62v#3z-&obYXAotQ%9IFxG6 zBnc{^ye2Z$u*>bcD7Knu&3oVoUQ18=Jy>G;G#r>xIq{IN*G;-XhLl`;RGQJ6^eHy} zWK=DLMRUq73ya3!rqc;!L%?F&Bzu-!1G^ce;)s~$Oh^f9sz#$O&NO%YxritlI_r|6 zE9!@N{n5x_y^Q`9P-Z*F9FuAt2?xokQjVKH30lNOq%_8Zs^TxFCH!Xy2HSsgLBxpbtu>Ph+99ce&LjB?9lh7@-(?^t@Nw?q;iAZ|m91#}ucN3v`yCXe;HkJK~&L3s}Pc|H8HNiSF_Lsvh$w4T9HEYl=QI6cnmHq|_B|qxr zuzgNvuNeE0-A3yAB7G*DR$VQA96pR%lrr8Yc`%vV`s|oCpYW!4T)A)orlf;Jfb)2r za=b%=3d?iVpV@dAXKUw*1rpjwegfWpo&n(LmK$Z|&8s0KI=1E%6Q7EyzVwzV!&lZe zE7b#vv2ya^=MaNc^TQvzBk_meM`7j-ImzfwiwlkWM#*tu4?`KUfcuqo!5T_y5z$UE zim3Lt{yBN%*Uqk<=VXT8SERCBd^%fnxs1^lgbX2At#%%Gwt6eEi|PV+-t62G=9W%Q z>|+N_HW;K|CN3TkG||ora)8kHeQ26fnD7i}XqG7+zJn;3zt{L?5vg87kTI8SHSZCX z6kO-erB9L=#+usKuFnztxTfEj#YSFp)jButGELd}tk0k|d?P%zR%0zfO?Cf=aVp+^ zr{LFZnZUQ*6Q^<&$|E%9i{N;p@nza^Gxaqr-B{sWz`DZl$cOgCm8AeGrO1y&1h`p6 zh4NQn8>f&b`u2GQ?U552iPR-XeT6o|&OT}ZgVPdUXfIW2Z9o6w$twj zHI3x2bookW*e(?xl=epk#-eAP#MYjss3nLt$YYUqg)WwwF?vOC!L~ujmhrD-I+T4g zLDNHtj4wg=zYyX8`!Jv4_vq`AhJS8-CnB5cDc%d|Caq@@(f8r#xW%zhrFzuT*)p6= z8bd#nxa9wO!XT7aN0iolV{oHRf#JCuJFJv~E^kYNO=Pz~Z}`oV#;`rEL?0NXrvyZ^ z1xoGNR_kaw5T0_JeI;o}dmF8nCU#DB0>;0rjt3P19XQrW+!aXS)->^G2l!R$6^v|KRgl zqIegNBF;)M^x|6BkXFgy(Ih&Tcyp|=Zw-V!lf>iUNsXVKeG21lAaCGP0x`Is2>}FN zB00KeFSJNB9~n~4=vIMFPDDi#wDb@*RJ^d_iad)nbzSh>#|O9HgPI23quS4uuu!b5 zOzS<5g*UNEodWVms%%p_(@`)_5j#k0Qw;ogiqg8t^%G*J&)=d*u=iU;T#ys(IBOuC3$&#G7v4}5Lsa@$b|w# zOD+zTPrFXh@_95RBrY*M*}CgKqAZ9JAvSxuB`OnX?sc4t?gnd1p@KDEsZ005@Y5R^ zq6Wck70=cmAT8VnJ%@(2^DI_@qeEp745aa{7pW(8)^o90o{lmN9MR~}ty!9r+i)ia zeG>UXOI-j5R;w@*{W7tQ64r;TA%!lXVtmCk$oZj9g>o_AwOR5esdL{f2 zZr3f>`*Y^c2P3*#j&gRdcjV?P8y{u&&$$x{7$NR&L=NNg(MNpnc;hzV6eM0rc=1!* zhq;S%6E1w1^fPHYZIkGX)x!bD?XSdaeP*vh&t#K!t)DUK?~c`9(!7;jci$fHm7ozM z-7h!}R$O1_?mG=w6HcwvIX(m$S@Ub|Yp?lh3*~>^C;q=ar1X2A;a`(sY%T24 zv8{3d5yW2kkQe{@tFiNxvRF2i++3}t4}BHf2zDSw-57n@rHNU?e$q6Z2jJ;Q^kSO_ zdKQwsIQ;Va)3sFBk)a;SU_^-8TT9O2tU_cgPUV#%!J&L-fLy9*``h=fFT7lMk~^D1 zTDm+-;DozcI6B_3r5dnPDwx!DZFvj#39{^d?S#}&3#=IE6%mw}(7d%LGmX-MU@EaQ z#N^+6VN5aqND!@+2U1C}vz9_Ic$dv1O>FX-O4PA437#E)(WYpd3zTi9++3tPZq?dgzqNDTGkL6fyMlG@Jszz~ z@e1-XfQf$5=GnSL=?l7U_oA%@F3z=`bZmMmlEVW_<~h z#L;P*1+Mb0$a3au#tFh)f;xUb8*|**0bh)sE#ru1S{Uk9G^7znvprNeZ{VW+35TS? zbtC32;V7BxL0pwKZad73v-wn#Eoy$1t>zFO_=(BWZ0{6mc=T=da0ZryEG2yjMeOAF z$R!&hpDf+8SQ_;|vIWbUBt*5zPLARl7a_8iO?RD^7E^*=C#YQc458$SmqgBIFY!H* z*YB1>)gC;YGkWJPiM*9#-l<=PQyw-*F_I+0#~V}BHjjUO(2$X8Rhi2gjbs0Xjqnyy z%Ied7C8>}}^GYh_?0pC7Vr4hZe9rQiuvDtqsf4#W6d20w ze&KZ`(ZwxZX2<2YY2ug)FB+&d25E|Wk?D@`z*D0w96y;pK{Fy5#-hWi2YA&q2Gl>? zoD6ixHxoXk`T*Bw!@zu0O!Vo}3y~!hqO?3&g!x!u^enTmprbRPxr}dqMU}x?LkfJp z*%~hVuGbYP9b}ib#=YkhGQYbVjv_d}NFB8a?cR-4Jf%O!&6kPYH!oEpq^qQN!gW!B zT@BoTTm`ZGB3@EjdUfWG`6@|Ht7w!R71SA6{spAexAJ)k&@u?=V*RK!M<0d zWx@8N7WOk69{SCMEnPqnAE>7vyhj}z$~tPsBY(dGGhY7P=A6Q-&e zb*iM+uTo~uRXa`}eJ`Dnrj0H240#Rf!)NI!n(#*$woR6$Gc z0@Wkcv%76sTM}8>q)lJrUp<2pUsM^5TsJx_5M?13ZWzGV)!o7+E<_;2OqyLIiJS<{Z~T=4ryBoi0q|d^ zz<(|P{^z~pu*3(3*3|;&iSeb>9LBms*C;vFC^-Y4X!z;GDmd%AXhRQc0aOraPKC^8 z44yH;HwGP%>;8zZC`7B@TtB_$^CReYqFWkT^%m|j-rGH^nCm=xfoY23omUwL>Q?YB zibjkfa!|;lC3}%{%bRS}f0FA1$AA5~=VP0-ADf5J{EnpZ+7I*>aJHy%2ah}6=_9o3 ztIcpLy`VqCNq0=|`9!*>CZetiS(?Q>WZ{7T}6o+5fo-8Z}n*%z2|ArM?Sg3>;< zEIB zdEeHmVq~rvf!!cmg~-tV1QY)f)6TYw>FZ{vE^9TbV*GnCG;{WtQo_{FT`pqZkvO=X z`3Co@#grp5IMrrt9$SB*=oE(}Zoa*qwzx$$LzxL*NgjI>i9omcf&2UO^Q#>Nm2#G7 z2jj(npE*-w6t7ben^zZ*ogK!7TDf1A1yWz}NuE1ryn)+ShZ3)AG-tfm?-j^x`oWk~ zlka4*WiUaH&%@>qt^aaiSfKyB;=RRCJzM>9&pc*u3?Mwp9Pgl0cupLiIrBh%Wx3L_iFO!ZViVWxOW%#w|h-@B^AXR`#J29|KL7A(#cX3(#fJ{5y|ReeYmYi4t%?JagI zQ;iI^)?MXTFMPE!fWK_3+O5boyMxr4$jE8D`!?3^tJAmwLIQ0b8ItKza4b;}^AThE zr7j`aIVt;i31_m6T^Y%<Z&X+fv$|6^qY zYv)J{oo)iSLmu~pz6|dwv3SYwtmUE@%K0Qkj5EaI)w(K3B88S4>?^DGy|5TH3AY#V zbz6f>ByPpSmHvPdJ$#>$IOV|Q8RCG>*_LJevNT$2T-gyI1FnXW>FC~gqZ<Ljw|$ zszhI|_c$0unvu%@RUrbQ2m|q~P&j!h?nA&-1?#Ma4ix7vv=dmScYaHNcC zKOj$rnzMn)1u0IX^2QP=9Mg9&jCZxjHZ!OA%QjyLrPiuYvN;gX3M zz-LNo>m`evc)&$MMiX^3A$BpKo*9S}j3YXZ%BtL?>lf z^Wu!>H?eOqyo5w=>w*+d;aFHyS-KM)xY_Zg=pcAVSo~`XIv+EkmNJ*^bjA;rVn4nU zm&(m087`XBWRSME<=}rH`+92WOS(mP;h1ZVBJcS0{=ZSnO#UVDOYF6Lc>it2X|1~JYnDIXimjac7u3!XLH@Hd7|l$S}QObrr}DCRpRo#4$mPQhuZ@O-qt_7$>d zJ@rKLD$ta;d_F>AK^Q@p9F#h*KQtqj&&AEew0t%L` z@V_&0a`gbfi2SgdZGZLugBr90OdwA}C@@;Lt}A~mKbrSB)3!HlOcf>XVJ^@c(+x<` znis+CVkX;;EJky#x|k+o@81awM4Csl?%F{Fop!BKy6Xy>ybCOPWLS&yc)~ zquufOdmDY)x4}#}y8B%M$-|jV3#R+vK(8Q+y;u1rd$>s_ZEU&UD>{N;dv75}RA7Q< z2s2TeWnPaMM^2@lMl#E92Mge?>c8oR(2kLRG*=?UxNaf4 zsj7FdDW>!JK|w~m+()vbvy+Q-VmBAXQ@>s}?E45biTXYFEBs-#4Xrq{7B!xW@|LHd zdVw$jWKD@-@ax3j&rP zyhM!U9Xu9!y22G(mK$Z0v?5u@cOj2wt8z}o54Dp+Yo1jBR<|FLOeU2=mR(pLkxuEE zz_l5+-x2@=qr9B$w<^aO9w#ND1i9PgPtWU)@|f4FQ&`BhEk~IEen)${$F{mu-T*#kaeYujc}xodc^y?w zno0&!9d7{o`deG%$Vr5!kk|(ky2j*30uIGuC<;vY4Gd~K(?(~lc8FBVXkDNik6E{A zu3#MBv4!`Sxi|1zEbkW|NP-_3s^R7kn|S7HrDmd~RehO6-Sk2&nOlonuQySY_7O!F zoHy(Aj2Bksph{P+LQ-0aUVpf!mOirQklR7Bf-GP$rR^)Q-OSFL4MAPzJ*}};i2Y!o zrho1lQl$4FKXHbSo+oZLQ$be$n|J&r3*9k=J=Pa^x|HgWlO@&+>{)KQxsSQ}hYn}7 ziPZa?`-R?31G;78?wt!8-w!|dhWL6u^;mxL4%{)u9xjaopBmL4IN>v?a)=xoi9k=?v z<2H$9gzu5eAeDTxME0dTNuC^E#?ot5*X|oLuRtfb4t>=w<+@dW@xa|K6TPy&KMj96M%kV;L!$?N zMSADJKdzShPg_9$&lU>oKESpJ!7e?%i+TbGtVfpbRE5rl9N?*Zt}ttX;;VIuy5(F& zGlHGKm)|7Qb8QC%*Q07vZ!U%(%LV60X4@bjR7pHOweqyKIvu0Te&|o#{Klp^la|6a z+Y*2Hdd%x_ALt=NZDVS%f^GBwzU_@~_J;(H zAq@1jO43__F0^6P>Y|UTD-)$~T&OmA7D*TVc&OP-2f770fsOGRk7;+F zCMD;5@%fnd`D`bB0%sPa5=Uti#C`L;00Nu|zm4!GuCPIX_mj1Tf$7>Y|*lNO#XK1uVQi&Z+XKMe39k%r*10`hMItfR@ncV#ZW_E^=fu6JoRO)6_gju-N&+bz*C+YjW2K%9*`^+Y{EU2ke6ag z$LhBtP?a% zoVI!cczzYw?cm_rP)!ff$r$CQljgS9m3%t;ZtD}A^%7CcLKh{-WPgsn|K|_JTe;`x ztFXqIC4in`B*$nh>E7Q%krx$!>e8cY_1Vpa`6W zMSu3Zxzy`L=2o7~l`Ws07|upWLToKQ8{2qdiQ{Y(5&iX5;iIo!S&>R}a*0Y-Ed@LI zjTPMEP(uNg)|dJ7v0d1peA&8VNkzGSYeh_8^?fZh2~sE-GnsGp7Nj7$s_TB!?e%7A|gn}~mB z-WrQAtoKZEsPsV8hAlW}LnhmdUbtG>q{72pTlc~oi-#AE*P9|k!a+>5qENc8kbJ3o;+?d4Ro7X6`Fn}< z#C{JG#r2d=J*6|yb|Xo5&sM8OPa{S2w*|V|^1-!?x|l{i-q-mw)es{L0p^vPNHGP- z1sYs4122ts*OXL^NIKu>UY<5*QUVeCwQbSK=kv8KmY_M=#5u$fZ%UP~L@F%GZ%M6N z^p&8_Ui`+NeTBO~w>7YJh*rG4|w1b2VSix&$z zsN0s`$0ZU*s7^6Q#!PbkHb0CFPPnQk;KA;>c)JnSSF9UAU3*_DbZh8W{v{v&Z*08( zG7MXr$oT+phZ}1k`3NXPKwh-J6l>XXg$@h>C=hd+8L^>pUw+Z)`SRbd=v2mFHY`*rNSeUfz|Gf7^OxHVxp1hK|9Om~;5B+b*?_xO^%DJ578XT0E-P zW?d%L>0O~>Q9KB^H1BD@8h5bq*iDL(tF6h4K~8;?FZfNdmnZ_IP*mY{`OhCJ@P=Q{ zai#}je}b3QI-L39*Sa|Ty>fKV{Xj;bi(}(*G1~jpW&Z=MnDozrx_nU3DF7~a#;_Xx z_Q}ChLdX{*Q5&@CQdCt`OQ{?E3qRb>1f;J&9X<^BmiX_BuRBdY>Le}y5zlFYc!Qew zuroSxqpAFx?UdR$4}?UAPKc%4#i6e0r3Qn&yhEPW^#IzzjH+ZMRNjOF^?gbyTm5K* zvC&*h61Sli@ud!mSK`SwSxH1awd=#I`gu%wdl^WB9|t<((2kZz-?I>(h;nYjmz>fm zMxm^^>Gh2Whs8r!MMePnap@l}W}75R8w=Avs~n2uQJ| z%jat&3Q?nc`W{>tug8LYwcP1|-f`5g-8vQ>`sO5;n!lfB3moQDHrT$!3uxxCMylAF zd&~tn_BQ-v9;{@p31T#)Uf-rkn5>BRt{z zAh!5Xa;p8VXN#$^m&ukI$UZO#4oABz= z@v>jJPl8x>^dR4qSY@EcYvo79(*w zACoV~mJNHGh{w!^ez8dpf0o7^-thE|FK1oMsE6SYV?4RbbusGDq3X-m``E$epTqYM zogpJPr35D;sDX@`;(oW?S8;`aH*i;uDi-+IqPOKiRQP-km!-0dW$cQwZ0Dk%5g-N4 zV1`FA=M5ui%j#CQyi90#G+!f7BI?a?c@`~8*Y3h zo>zo}bCt#))4oY@FChC|NP+rl4vSC~)*u3R@=?IjUa%|~vD#$8&>>1S9xilB8a7vlBTxItrH}}+ zveO^oRv&JB?n5lkTAT9x*d`_j|CA&LUMZq`~(hL&r2kALM4QC+}DR*^#;THm_LMjcL~C0BB}`5 z0(cJU0iL@_0W7V%XDh2zX})P!Xg4PCSlrN#`CsW`Z~m{I$^U%w{9EGiTYx2}|UHKS5+I8>txlQok0 z=|%6Mr3>BEC_6bPA`F_e^{#|VMOjZu)ykT%^+8)%#omewoCy=|BRi(LEsFT++!7la z(8V;!Fl>@zMUm8wf z*s?x%Hnq0WX1;yvwYa$)N-PqKp}m_ky~$Sraf$K;mUj+iMc=Zb1{3xo>?;pm<3muM zP0`ai;#gs$jH)kg=;VYT>q?8*Cw+UG$E102?kVvg1qP8L|zZ4 zyf~EfyyKgA;>Vvjc{Q3tarMQQDB1B#PfjBdiZaM7TRxAV6x0VpmVF!bQ0p{>D6M92 ze6mWPB}Bgo&ick-kZ4W+++(BUsG<*Yy*8B9S01 zaXq?q2l$j^bd^S_#Wm9{oQYICD|Kl)VwaC{X2q2wgX}0&oq|3E@45Fk{UANQzYrBFWeZj#h>pN zIDF-2S}$|Kq$6i84|mGgUaZ8X3G(-#`Rw(zKE3PbmWN$P>`>8B4^Eyk zW=~gY^aQo{FZdq!2vI&k##YK(^HpWFS-z2gy&~l9csRMt)#RoH_%MA6mxQ3JcD5Ef zp|3*RjfY8WCH!jo$V}y9Cf|K^f7&pP@#O=+G(Y^rEi2iAsa&EFYM>Cg)%jC1A6Q6) z8@$qH88U#h=pj7_M^}J@*gB}%%VSh3mg<~b)RQ%AfK4z!#o_gcFhOlI<5epohfuFT zsoV}Po`KA9*TRoFYlUtsNBd`n>MNR(VXn?~@b3wsZ8OYi>xW3JNp@j##$4?@NLMWq zv)350#Z!^YW;gMHn-84i>OMO8pl1*+6QtBInR{QNvag)H z*%n)OjZ}2$TF*G%a5xf4b;N{1%a(tohp)^3(`v%@8vu;J&ku$+EC9qH8dahNEzwFH zN4%8SOVG}@;%`N@Fu$6JOIMvk`)E+R7++eDM$+#rFR+F!iFJ>3b(FxRXYMS^>@4ka zy<{q_f0h=ZAFt`~0Isxpj(FR;2^!F~WrsO91CQ@x+h}&)Fi|1)KmwPzWNsDhY@cIe zpXBIbGtLoL$7@SN7QQW_3M>;kR-1e>{(B0m-=MhEDJ(AO_L(uSz1R@%)X z2XQYWU5YZOIq=+Tijv!T5ow^Y>^*6{iNuB;?OK=`^6iJ@hweMf>|C#()&Eekt9b9u z-vlj=W1iT4P6-Xe+p`?`@S)P*J;EZd3E#?NN--F21l`d;fCJ>YrcUUQsVt8MS1g*0p5%GH3g_orq<<0K}h-odspZLMvf!;3hSHw1T8ZIOq zKEHuqhrh`zs49C;-~dehl!1vvqLutJqfaZz=Sh#)5t`pA1RxYC$fc$V;q>(-(N^J# zH6Qhgu(6wPO0&qcw@FivYIf*d&`j1&CtEusj}`2?-BOn;B@b~Zo9i+)vhW_oqpGTV z9@CiZoV|m;wW)wN_rO7<0TWB|=VOMKJFiE^oWy0+HF!wkRfD3(=bAn(+i(p2pwKa= z>xl*wShBpY6b!`dhikVx)F+KGk=@|r+>y`m0wqhHeYKB%S`+^^0wsC2W65Z}G{hq< ziIt!*MQ-|ZV(I%5q^gr%4@$lIE7sLl|EIBzvIg5(&CLtCzq8ssZb+?^6Fd0yNw4m( zVJ9t#Nx)!<_F#4GM_dZZ7>^JZT5jyx^&Q1;BjWhQI!EWja${-c-Cb9MRRq%s&t9*h ze5j$;l8Sv;8Ie_b@D$+em-fA}vQhbFGE}?ubc=hpvfZLkMa0{)2?LU(C-XAPK|A{s zPP)w4+zCn9L{My$D>&{({Z^S+Z8*C>M@sVNK-=s-$(+ zEaz7ai(}a+K!+z{$23fS-K*mp{?A0E2b+Lw$3iwBhEHQyqZ7d9I@b!*QVEHUH3dRH zqK`~R9xjXeNl$)cK){gCprS`vRqbo(pN4mcF!z^L%C?NIy8H)fKP^c9pb9gVs6+-* zIr=emdFw1mhm|tR?_rF%bo5P>O*GETEjxwCh#(sbrR6WliHy1pUhN*sa}KMqtMvu4 z9#F>vPr=l(zyz-@?%|SC+~I4Xx0w-rq95I?z)0)HY4Z$@h1&3yPoX25ca}=}@!vjd zSpNgS2Nhidc*6BGG_C=55dh>TJ%u9Z(9%uV%k4VoVGdMo@0VA+*!%0#-haJ<38v)c z`{O(RKMTqK{OzA(ANC1@i<|$~c}Eh+X~lFgmfC|@TpPb;n+M=3yd2ptl*|Walzg!= z;rp@u^RXUBKLvecRC%Kzq+XXVRmSTf8nK-s>1A|9n^)SSd?O(Y5LSy5^~j&D zf^>#*$iWhvOHm!M6@^<{7Lz*M>H;{=ld`M{W8!-vxP~OvZHJF0XliScE@MPqi=a-u ztGS{tHxFe;{b2DRE#PChZ~L>cdTO25DQ~n`cGvt`_2MDI1#Aj@Z@{Ltc_xCVYCh)* z*q;@&%av~~Q6L?{)uPfMABdFL-bZ9UEV0Un>p^48boc|(!{UP#6}g-!>vby7o5-KOBBWo*Aw@^DpW=cWK;g|cKQnLgVUL@Vf2(RaY(29 zQx4>h2e}k-J%}#a)H*4U>iTECWpN5Y&(Bhr+g8pt;Nl&Ud7O$eXRntA2ZxZ1RS>NtI?9vh%=N=&1 zZ0LL8qBQi4-|NXke#&Lq?>2S>$ZaNAi0|!)WhOSv6&9ExtnoofCN`28SxEFADnetQ zT#3HCdBny4EHWLHy?QuaIy5~jf3?#?QQ39OpB*M7d2m)6taxvBTbss~UpT5*UTJXh?B3JL56Gg)&wFh({D?u_9cTGT8&pKz`sE-H8H=yr~O zj<58=6a__g8^;84hWnf(!_Fn*g^qt(bfao#+pzmL4NK2Qjq~r9J({xDPU7bFjT#y{ zST4v)!oTwFNh%S!AqO6lgM;00M{>Ned%K=|>*vz?U{%veKpf5f{YtaeD0tLrr6W6S z6eBYSG}P0L?BGF^!F~fb`zGo9_nswC=_3FotXGNk(SKuVLI3-OoKVJN04F>rC)8#i zwu7sHPItIW>K!#BDyZ@T4kXoI$}~z<)VMq4DJPW5i1CG&a|xkIFg0yKcfsf3`!fZT zFUf5ZqN@d$#<8XRvqjCTnj|pkw=eFpK^r3 zyB5z%y;o7am9VyuKrf)AEfRAO<38?W8WV-glAb)Rdn!t^rNnvNez7byMM5iwMU*>O zDavAKN{q84LB_)CH%!hR+e?7A7r=AbWvl0QAPwn%b>tI;q zDg^PtadAo-b;@~&%GqYTp^_ym#Kk28#y%3?C(H@%d~S(`VIzp<0;j?CM10m_SZ~h* zBJw>#(yr`KMUg<{tyq?Cv7lLqbn6;@X-->Nl@^w(S0HVN$F5r3X@mS02q0~-9c zrmlDfP9piTq=O6tLuMwFly~H)zRWbx0kR@`;j}vaOnXjcj}JK>_i)NE5Z~~%YbhGv zZlj4(!3W%W#Qd9-@o{Y77n`g-qO^WWt4JTir>H4rOdgCFDeRlR`II3AKU$e6K9JMC zP10LQIwd+8Jt2tAhS-dptSA)mnbEygNh^B6B)QLl>l_la@#p~_Vi0yOuLDAz z>E$RX%C`9CCFuzEu!pNrozgY^TOOtbu4d1g!fon$A5x<97iKb?xZ334RFoTA-o|IB z;zb%fHcYO(UHg5LUYaxyP@3Fxl=HTE6!v+3TFa7)K+B?*-3ji7jnD@`)(UgB{#qO^0!C{UQwr1)=2f#D}P^aFv}RVk(w&|{xAJ}|ItIgR@@?L}=tyPOEv4za?tsFvMUz)|*W;Ob1K{Dv3=qzW5$=7TX zihHkW+|py?Po$`jdBC&!lTu1?U-ZoddE1THb8{}u5`Buu`D?1;(Ay@ynIxRh zhNkSA)Q&%P)~b(S$w}s9hdkcWPAJR2ScA97yiu@C{`vuv-=d!Jwa2U$>TI!A^I^TV zx!!^-?nn9ENKMARG7F=yTyAlDf-i~miLP+P4X;;`rakQFC^W`#<=NM|hb zWyKXZm&94{w(^5e_Lm8Gol9Lm_W$;F{aCUwB51 z3#QbD)bP&eF)idAw8}Y=&CyaWDB1+EWZ5Fl`?VAqcTiA9L!BlKUgC!^5RoFTlJ#`q zEImP4Ahrr_$)3U()2r7;aQcY=SvsSxo@4YAc7JxV#pU>JT3A*A*|yPbSHz@j)}WJ= z-cdA@5>bb6_tK2R`aMJpy;Fii#s!7Jk7cBqLMPJ??2^zwV{AxynKN@eIXfmg`TE-m z|K{ziEw-o1CgVF*@9+;0*9(2;o*|UWy^87Yh{t-HOAH0PY^#C#&oS_@he7=o(ISPH z2-=!@x%*#J1H?QEgtoB`zBdn4qm2go(C*}62%v<1_R)%9S*e1kwo*;KZ6~OGwVB+T zh5~G3nDiOrs-RpZOg~&rPlZ0}n&=YeT6p%}yrOdp8)5wiCEr)sb_!Y@{jnA7C3?Qq z-0Hx^D%E`Z>hx*WNpAzTN)zq1X9LR8pI3`!sL0HshSgBk_>3a_ChUb*YMjewFSRVTd1(EkkHgK014(F z(fHKV)r}I!!v!rm2T;QSq3dS=5F9U*>>NM>2Z9P*`~vEn1DK$=7XVVEUk^c(F90lb zcOARbI3yh19o#6{xH+V4T<$P&|GI9K;}5jle9*mf02LepFyQ#1#FsFn zJW#_6023aV^A{E!T|L-eULZdury-Q<0zeFny9D6D2K8P5nBl>k(ESS-KfKWOO8^H9 zDtHNCBm3jc>5nIQz%a6g94aoB9xxWb(6FmteCJ;RXrLxn0CLzfepdi8YS0}ySi`X= zPdHReU0~S>Hu@iOa6zN50fcZ|P=PA|BTOB`*8mbE7*~{P(5E*rwh(UskD(1$fOoL} z6~iNwLCtRfc=Z3o0s5CN{@kfDWCx24JB5Vn&Ta$> zVE@Csg_#xfOQCm2DS;r~L|WuKtLoeW9>XsGzBAY#3ghO3sqYVkLHDl#c!`zBxFr7+ z>^!AOAz*xj=U#eur`K-5bXPybGwi z-@ov2^Kf$B=>qZ_5P0XR|AcV?`Cxr?{{iFU=emot-(cMLVEmjQ*nzEoi~|8V`8Z)Z z{_|PLFNtA5e*WJi0Re%W+%W(7bKsxjfG`E#gK_^2;lIX#?hN_cvpm0R1_Xov!NB_i z@0kPygl!$W#~?Qs&u`j-jpOFL4}*b!X9mQ_e@FLD|NpWH2nYu8{4OyF$a_zPuz_5^ z*%Jf;@&SKm5Cr50{^naC5H~0AZ!~_{9|q(C{$@`Y40um7AZ~8p@9GC}!%+Sv9f+HU z8y1rPP(O&9m-}}ufVd&xyZd*38_37~yGcOY{IF{hej5kkyi1(_d=|uYmyLdd0YQJ0 z`0jrom~^0D0>kA0xB6kwdrkv_S>!%pUjBPp0DDu4gNhX z!(e>(Lza(^_dX5&fB6FBZ))Y|`G;zLNz8xW)9;e{@0#J~#>ch0PoP3|RQl|LYV&iQvK0DNDqeD}kXALd>62=l|@<9BBG@B0kQn!iOD1eRww ze=iR1VD}Od4<{Gb@BRUU@%&4Ye+k0F3B2dPFxb5m41@83DSypBf5kQrCv5)wO%fRF zUWVg=`QUGoz?cT{{B9Ch66O3oNx@*Ce+vTnqvX2Fws(c_-S6KK!NbXWZx(~WV0Xs- zJ`Q{@ws|!+)O{F3$VRz)Ht^%y4ntG4o6R ze@P5W%lFjEb$`;~;rjKq^iOTU!u_5gT-^7H7g&7p{^jU@)_**(Qudx&x$aNLuyOb5 zL>^cb_Iv(-!G14BL3fkqJqBSnoZgF1ShWoE%-?Jb1cC247YOF9zmJ2}YxkZ7f&X4| z-66iKDt_U+)Bj)U=lu^}4Vz`}A>;#t?l~(T|GnCPmlJ%?KX|!d)c<1om;FJ!K(2c! zlNa_X@Vmsk+~E7;xcTqHU{mVyVJZX_pN+YjalNChNIE?^q&rWk>e91sm zz85dmuwJUYq2Pp+bMOVMe;PRX#>DvqhUPs6rJJyvkPeKVcmp8Vki~+F{X;_2lC6NU zF!PyB2=iujD4f`|!Srh+3*myD* zWWi3*M>aq7gh2(e#5DtCd2+%({sZLTv)m`h98>TCkjPmfLjiB@jhqjlCv(|;Xt(1> zKU8RfK5u_|bbrJ3({5MVz!(B8!iUez?g~#XUvFP-G<2QoTj#s?C_Q{5c<1}K;4}!r gMqK}|@w#4DU;B30e-HhpiZyzlUaHmV?(x3*1sc6?6951J diff --git a/src/mod/endpoints/mod_khomp/include/cli.h b/src/mod/endpoints/mod_khomp/include/cli.h index bb251bb16b..5df472bb66 100644 --- a/src/mod/endpoints/mod_khomp/include/cli.h +++ b/src/mod/endpoints/mod_khomp/include/cli.h @@ -733,17 +733,21 @@ struct Cli options.push_back("fxs-global-orig"); options.push_back("fxs-co-dialtone"); options.push_back("fxs-bina"); + options.push_back("fxs-sharp-dial"); options.push_back("disconnect-delay"); options.push_back("delay-ringback-co"); options.push_back("delay-ringback-pbx"); options.push_back("ignore-letter-dtmfs"); options.push_back("fxo-send-pre-audio"); + options.push_back("fxo-busy-disconnection"); options.push_back("fxs-digit-timeout"); options.push_back("drop-collect-call"); options.push_back("kommuter-activation"); options.push_back("kommuter-timeout"); options.push_back("user-transfer-digits"); options.push_back("flash-to-digits"); + options.push_back("accountcode"); + options.push_back("audio-packet-length"); brief = "Get configuration options in the Khomp channel."; @@ -821,17 +825,21 @@ struct Cli options.push_back("fxs-global-orig"); options.push_back("fxs-co-dialtone"); options.push_back("fxs-bina"); + options.push_back("fxs-sharp-dial"); options.push_back("disconnect-delay"); options.push_back("delay-ringback-co"); options.push_back("delay-ringback-pbx"); options.push_back("ignore-letter-dtmfs"); options.push_back("fxo-send-pre-audio"); + options.push_back("fxo-busy-disconnection"); options.push_back("fxs-digit-timeout"); options.push_back("drop-collect-call"); options.push_back("kommuter-activation"); options.push_back("kommuter-timeout"); options.push_back("user-transfer-digits"); options.push_back("flash-to-digits"); + options.push_back("accountcode"); + options.push_back("audio-packet-length"); brief = "Ajust configuration options in the Khomp channel."; @@ -933,6 +941,36 @@ struct Cli bool execute(int argc, char *argv[]); } KhompRevision; + /* khomp dump config */ + static struct _KhompDumpConfig : public Command + { + _KhompDumpConfig() + { + complete_name = "dump config"; + brief = "Dump configuration values on screen."; + + usage = \ +"\nUsage: khomp dump config\n\n" \ +"Dump configuration values loaded on memory.\n "; + + _commands.push_back(this); + } + + /* just to hide unavaible options */ + bool removeUnavaible(const std::string &s) + { + if(s == "atxfer" || s == "blindxfer" || s == "callgroup" || + s == "mohclass" || s == "native-bridge" || s == "recording" || + s == "record-prefix" || s == "transferdigittimeout" || + s == "pickupgroup" || s == "has-ctbus" || + s == "user-transfer-digits") + return true; + return false; + } + + bool execute(int argc, char *argv[]); + } KhompDumpConfig; + /* khomp send command */ static struct _KhompSendCommand : public Command { diff --git a/src/mod/endpoints/mod_khomp/include/k3l.h b/src/mod/endpoints/mod_khomp/include/k3l.h index 046bd666b1..51686d0296 100644 --- a/src/mod/endpoints/mod_khomp/include/k3l.h +++ b/src/mod/endpoints/mod_khomp/include/k3l.h @@ -231,6 +231,8 @@ struct KVoIPSeize #define CM_USER_INFORMATION 0x0F +#define CM_USER_INFORMATION_EX 0x2B + #define CM_VOIP_SEIZE 0x23 @@ -369,6 +371,8 @@ struct KVoIPSeize #define EV_USER_INFORMATION 0x0F +#define EV_USER_INFORMATION_EX 0x1D + #define EV_DIALED_DIGIT 0x10 #define EV_SIP_REGISTER_INFO 0x11 @@ -713,6 +717,8 @@ enum KH100CtbusFreq #define CM_START_CADENCE 0xA1 #define CM_STOP_CADENCE 0xA2 + +#define CM_SET_INPUT_MODE 0xA3 #if !defined KR2D_H #define KR2D_H @@ -925,6 +931,7 @@ enum KSignGroupII #ifndef _KISDN_H_ #define _KISDN_H_ #define KMAX_USER_USER_LEN 32 +#define KMAX_USER_USER_EX_LEN 254 #define KMAX_SUBADRESS_INFORMATION_LEN 20 enum KQ931Cause @@ -1845,6 +1852,12 @@ struct KUserInformation int32 UserInfoLength; byte UserInfo[ KMAX_USER_USER_LEN ]; }; +struct KUserInformationEx +{ + int32 ProtocolDescriptor; + int32 UserInfoLength; + byte UserInfo[ KMAX_USER_USER_EX_LEN ]; +}; struct KISDNSubaddressInformation { KQ931TypeOfSubaddress TypeOfSubaddress; diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt.h index d09be88567..b17d163cc6 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt.h @@ -305,8 +305,6 @@ struct KhompPvt { try { - //std::string type((name == "input_volume")?"input":"output"); - int i = Strings::tolong(value); if (i < -10 || i > 10) @@ -614,6 +612,7 @@ public: virtual bool indicateRinging(); virtual bool sendDtmf(std::string digit); + virtual void cleanupIndications(bool force); /* Methods */ @@ -849,7 +848,31 @@ public: if(!name) return NULL; - return switch_core_get_variable(name); +#if SWITCH_LESS_THAN(1,0,6) + const char * tmp = switch_core_get_variable(name); + + if(!tmp) return NULL; + + const char * val = strdup(tmp); + + return val; +#else + return switch_core_get_variable_dup(name); +#endif + } + + void freeFSGlobalVar(const char ** val) + { + if(!val || !*val) return; + +#if SWITCH_LESS_THAN(1,0,6) + free((void *)*val); + *val = NULL; +#else + char * v = (char *)*val; + switch_safe_free(v); + *val=NULL; +#endif } bool mixer(const char *file, const char *func, int line, diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h index d91705b626..6e51af35bd 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h @@ -138,7 +138,7 @@ struct KhompPvtFXO: public KhompPvt TriState _var_fax_adjust; - //ChanTimer::Index _idx_disconnect; + ChanTimer::Index _busy_disconnect; }; /******************************************************************************/ KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target) @@ -240,6 +240,7 @@ struct KhompPvtFXO: public KhompPvt bool autoGainControl(bool enable); void setAnswerInfo(int answer_info); bool indicateBusyUnlocked(int cause, bool sent_signaling = false); + static void busyDisconnect(Board::KhompPvt * pvt); void reportFailToReceive(int fail_code); bool validContexts(MatchExtension::ContextListType & contexts, std::string extra_context = ""); @@ -266,13 +267,20 @@ struct KhompPvtFXO: public KhompPvt virtual bool cleanup(CleanupType type = CLN_HARD) { - //Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect); - //callFXO()->_idx_disconnect.reset(); - + try + { + Board::board(_target.device)->_timers.del(callFXO()->_busy_disconnect); + } + catch (K3LAPITraits::invalid_device & err) + { + LOG(ERROR, PVT_FMT(target(), "Unable to get device: %d!") % err.device); + } + call()->_flags.clear(Kflags::CALL_WAIT_SEIZE); call()->_flags.clear(Kflags::EARLY_RINGBACK); _transfer->clear(); + callFXO()->_busy_disconnect.reset(); switch (type) { @@ -312,6 +320,16 @@ struct KhompPvtFXO: public KhompPvt // static void delayedDisconnect(Board::KhompPvt * pvt); + void cleanupIndications(bool force) + { + if (call()->_indication == INDICA_BUSY && !force) + { + DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXO channel.")); + return; + } + + KhompPvt::cleanupIndications(force); + } }; /******************************************************************************/ /******************************************************************************/ diff --git a/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h b/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h index 0267f33f24..c32071b981 100644 --- a/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h +++ b/src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h @@ -272,24 +272,39 @@ struct KhompPvtISDN: public KhompPvtE1 bool process(std::string name, std::string value = "") { - if (name == "uui") + if ((name == "uui" ) || (name == "uui_ex")) { - Strings::vector_type values; - Strings::tokenize(value, values, "#", 2); - - try + if(value.find("#") != std::string::npos) { - std::string uui_proto_s = values[0]; - std::string uui_data_s = values[1]; + Strings::vector_type values; + Strings::tokenize(value, values, "#", 2); - _uui_descriptor = Strings::toulong(uui_proto_s); - _uui_information.append(uui_data_s); + try + { + std::string uui_proto_s = values[0]; + _uui_extended = (name == "uui_ex"); + _uui_descriptor = Strings::toulong(uui_proto_s); + _uui_information.clear(); - DBG(FUNC, FMT("uui adjusted (%s, '%s')!") % uui_proto_s.c_str() % uui_data_s.c_str()); - } - catch (...) + for (unsigned int i = 0; i < values[1].size(); ++i) + _uui_information += STG(FMT("%02hhx") % ((unsigned char)values[1][i])); + + DBG(FUNC, FMT("uui adjusted (ex=%s, proto=%s, data='%s')!") + % (_uui_extended ? "true" : "false") + % uui_proto_s.c_str() + % _uui_information.c_str()); + } + catch (...) + { + LOG(ERROR, FMT("invalid %s protocol descriptor: '%s' is not a number.") + % (_uui_extended ? "uui_ex" : "uui") + % value.c_str()); + } + } + else { - LOG(ERROR, FMT("invalid uui protocol descriptor: '%s' is not a number.") % value.c_str()); + LOG(ERROR, FMT("invalid %s protocol descriptor, need a '#'.") + % (_uui_extended ? "uui_ex" : "uui")) } } else if (name == "usr_xfer") @@ -306,6 +321,7 @@ struct KhompPvtISDN: public KhompPvtE1 bool clear() { + _uui_extended = false; _uui_descriptor = -1; _uui_information.clear(); _isdn_cause = -1; @@ -322,6 +338,7 @@ struct KhompPvtISDN: public KhompPvtE1 long int _uui_descriptor; std::string _uui_information; long int _isdn_cause; + bool _uui_extended; /* what should we dial to trigger an user-signaled transfer? */ /* used for xfer on user signaling */ @@ -329,6 +346,13 @@ struct KhompPvtISDN: public KhompPvtE1 std::string _user_xfer_buffer; std::string _digits_buffer; std::string _qsig_number; + + /* isdn information */ + std::string _isdn_orig_type_of_number; + std::string _isdn_orig_numbering_plan; + std::string _isdn_dest_type_of_number; + std::string _isdn_dest_numbering_plan; + std::string _isdn_orig_presentation; }; /******************************************************************************/ @@ -429,12 +453,29 @@ struct KhompPvtISDN: public KhompPvtE1 std::string descriptor = STG(FMT("%d") % callISDN()->_uui_descriptor); + setFSChannelVar("KUserInfoExtended", (callISDN()->_uui_extended ? "true" : "false")); setFSChannelVar("KUserInfoDescriptor", descriptor.c_str()); setFSChannelVar("KUserInfoData", callISDN()->_uui_information.c_str()); + callISDN()->_uui_extended = false; callISDN()->_uui_descriptor = -1; callISDN()->_uui_information.clear(); } + + if (!callISDN()->_isdn_orig_type_of_number.empty()) + setFSChannelVar("KISDNOrigTypeOfNumber", callISDN()->_isdn_orig_type_of_number.c_str()); + + if (!callISDN()->_isdn_dest_type_of_number.empty()) + setFSChannelVar("KISDNDestTypeOfNumber", callISDN()->_isdn_dest_type_of_number.c_str()); + + if (!callISDN()->_isdn_orig_numbering_plan.empty()) + setFSChannelVar("KISDNOrigNumberingPlan", callISDN()->_isdn_orig_numbering_plan.c_str()); + + if (!callISDN()->_isdn_dest_numbering_plan.empty()) + setFSChannelVar("KISDNDestNumberingPlan", callISDN()->_isdn_dest_numbering_plan.c_str()); + + if (!callISDN()->_isdn_orig_presentation.empty()) + setFSChannelVar("KISDNOrigPresentation", callISDN()->_isdn_orig_presentation.c_str()); } catch(Board::KhompPvt::InvalidSwitchChannel & err) { @@ -444,8 +485,33 @@ struct KhompPvtISDN: public KhompPvtE1 KhompPvtE1::setSpecialVariables(); } - Transfer * _transfer; + virtual void getSpecialVariables() + { + try + { + const char * isdn_orig_type = getFSChannelVar("KISDNOrigTypeOfNumber"); + const char * isdn_dest_type = getFSChannelVar("KISDNDestTypeOfNumber"); + const char * isdn_orig_numbering = getFSChannelVar("KISDNOrigNumberingPlan"); + const char * isdn_dest_numbering = getFSChannelVar("KISDNDestNumberingPlan"); + const char * isdn_orig_presentation = getFSChannelVar("KISDNOrigPresentation"); + LOG(ERROR, PVT_FMT(_target,"ISDNORIG: %s") % (isdn_orig_type ? isdn_orig_type : "")); + + callISDN()->_isdn_orig_type_of_number = (isdn_orig_type ? isdn_orig_type : ""); + callISDN()->_isdn_dest_type_of_number = (isdn_dest_type ? isdn_dest_type : ""); + callISDN()->_isdn_orig_numbering_plan = (isdn_orig_numbering ? isdn_orig_numbering : ""); + callISDN()->_isdn_dest_numbering_plan = (isdn_dest_numbering ? isdn_dest_numbering : ""); + callISDN()->_isdn_orig_presentation = (isdn_orig_presentation ? isdn_orig_presentation : ""); + } + catch(Board::KhompPvt::InvalidSwitchChannel & err) + { + LOG(ERROR, PVT_FMT(_target, "(ISDN) %s") % err._msg.c_str()); + } + + KhompPvt::getSpecialVariables(); + } + + Transfer * _transfer; }; /******************************************************************************/ /********************************* R2 Channel *********************************/ @@ -472,7 +538,6 @@ struct KhompPvtR2: public KhompPvtE1 { LOG(ERROR, FMT("invalid r2 category: '%s' is not a number.") % value.c_str()); } - } else { @@ -554,7 +619,23 @@ struct KhompPvtR2: public KhompPvtE1 { return (CallR2 *)call(); } - + + bool forceDisconnect(void) + { + char cmd[] = { 0x07, (char)(_target.object + 1) }; + + try + { + Globals::k3lapi.raw_command(_target.device, 0, cmd, sizeof(cmd)); + } + catch(K3LAPI::failed_raw_command &e) + { + return false; + } + + return true; + }; + int makeCall(std::string params = ""); bool doChannelAnswer(CommandRequest &); bool doChannelHangup(CommandRequest &); @@ -609,9 +690,9 @@ struct KhompPvtR2: public KhompPvtE1 /* r2 caller category */ if (callR2()->_r2_category != -1) { - setFSChannelVar("KR2GotCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str()); + setFSChannelVar("KR2GotCategory",STG(FMT("%d") % callR2()->_r2_category).c_str()); + setFSChannelVar("KR2StrCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str()); } - } catch(Board::KhompPvt::InvalidSwitchChannel & err) { @@ -834,9 +915,9 @@ struct KhompPvtFXS: public KhompPvt _ring_off_ext = -1; _incoming_exten.clear(); - _flash_transfer.clear(); + //_flash_transfer.clear(); - _uuid_other_session.clear(); + //_uuid_other_session.clear(); return Call::clear(); } @@ -850,10 +931,10 @@ struct KhompPvtFXS: public KhompPvt std::string _incoming_exten; - ChanTimer::Index _idx_transfer; + //ChanTimer::Index _idx_transfer; - std::string _flash_transfer; - std::string _uuid_other_session; + //std::string _flash_transfer; + //std::string _uuid_other_session; }; @@ -936,9 +1017,9 @@ struct KhompPvtFXS: public KhompPvt std::string extra_context = ""); bool isOK(void); - bool startTransfer(); - bool stopTransfer(); - bool transfer(std::string & context, bool blind = false); + //bool startTransfer(); + //bool stopTransfer(); + //bool transfer(std::string & context, bool blind = false); bool hasNumberDial() { return false; } @@ -996,7 +1077,7 @@ struct KhompPvtFXS: public KhompPvt static OrigToNseqMapType generateNseqMap(); static void dialTimer(KhompPvt * pvt); - static void transferTimer(KhompPvt * pvt); + //static void transferTimer(KhompPvt * pvt); static std::string padOrig(std::string orig_base, unsigned int padding) { @@ -1015,21 +1096,16 @@ struct KhompPvtFXS: public KhompPvt return STG(FMT(STG(FMT("%%0%dd") % orig_size)) % (orig_numb + padding)); } - /* - virtual void getSpecialVariables() + void cleanupIndications(bool force) { - try + if (call()->_indication == INDICA_BUSY && !force) { - } - catch(Board::KhompPvt::InvalidSwitchChannel & err) - { - LOG(ERROR, PVT_FMT(_target, "(FXS) %s") % err._msg.c_str()); + DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXS channel.")); + return; } - KhompPvt::getSpecialVariables(); + KhompPvt::cleanupIndications(force); } - */ - }; /******************************************************************************/ /******************************************************************************/ diff --git a/src/mod/endpoints/mod_khomp/include/opt.h b/src/mod/endpoints/mod_khomp/include/opt.h index 270adc7068..4bc65361a6 100644 --- a/src/mod/endpoints/mod_khomp/include/opt.h +++ b/src/mod/endpoints/mod_khomp/include/opt.h @@ -108,10 +108,13 @@ struct Options Config::Value< bool > _recording; Config::Value< bool > _has_ctbus; Config::Value< bool > _fxs_bina; - Config::Value< bool > _fxo_send_pre_audio; + Config::Value< bool > _fxs_sharp_dial; Config::Value< bool > _drop_collect_call; Config::Value< bool > _ignore_letter_dtmfs; Config::Value< bool > _optimize_audio_path; + + Config::Value< bool > _fxo_send_pre_audio; + Config::Value< unsigned int > _fxo_busy_disconnection; Config::Value< bool > _auto_fax_adjustment; Config::Value< unsigned int > _fax_adjustment_timeout; diff --git a/src/mod/endpoints/mod_khomp/include/revision.h b/src/mod/endpoints/mod_khomp/include/revision.h index b0ace1ad42..717124dda9 100644 --- a/src/mod/endpoints/mod_khomp/include/revision.h +++ b/src/mod/endpoints/mod_khomp/include/revision.h @@ -1 +1 @@ -#define MOD_KHOMP_VERSION "1.0 - (rev: 5891)" +#define MOD_KHOMP_VERSION "1.0 - (rev: 6034)" diff --git a/src/mod/endpoints/mod_khomp/src/cli.cpp b/src/mod/endpoints/mod_khomp/src/cli.cpp index 621afe6a20..b5bcbdd924 100644 --- a/src/mod/endpoints/mod_khomp/src/cli.cpp +++ b/src/mod/endpoints/mod_khomp/src/cli.cpp @@ -75,6 +75,7 @@ void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod " khomp channels unblock {all | all | }\n" \ " khomp clear links [ []]\n" \ " khomp clear statistics [ []]\n" \ +" khomp dump config\n" \ " khomp get