From ce61e7f36ca746cc190cdaa3286999b267139ebf Mon Sep 17 00:00:00 2001 From: Vance Shipley Date: Wed, 30 Mar 2011 16:26:40 -0400 Subject: [PATCH] added NMS specific SCCP binding --- SCCP/doc/nms_sccp_architecture.pdf | Bin 0 -> 68216 bytes SCCP/ebin/sccp.app | 6 + SCCP/itu/include/sccp.hrl | 85 +++ SCCP/src/ITU/README | 15 + SCCP/src/NMS/Makefile | 50 ++ SCCP/src/NMS/sccp.erl | 863 +++++++++++++++++++++++++++++ 6 files changed, 1019 insertions(+) create mode 100644 SCCP/doc/nms_sccp_architecture.pdf create mode 100644 SCCP/ebin/sccp.app create mode 100644 SCCP/itu/include/sccp.hrl create mode 100644 SCCP/src/ITU/README create mode 100644 SCCP/src/NMS/Makefile create mode 100644 SCCP/src/NMS/sccp.erl diff --git a/SCCP/doc/nms_sccp_architecture.pdf b/SCCP/doc/nms_sccp_architecture.pdf new file mode 100644 index 0000000000000000000000000000000000000000..241159e1a1c5fafda80b5d25e6e515fb815213f8 GIT binary patch literal 68216 zcmdSBWk6m@5-tpc;2H=nF9dgY3GVLh?(VL^3GVLh9s&e+4H6`{y9c?DO=jlKo!u|9 zvwuE*r2F(aefm6IRZmrSbzVYgenCoFDtaiwPaCHjdj)5iW1o7U=m0bTD_v744h{gd zxPhgSy)l6HsYw<CuyNMAp_RZ*;d*1+^BIAH=I*r9Yh{u+YjP%? zH+UeIfMH%)8w6Q5=dqg^mpg;|VW&64(@BNv@h!$mX=l}ng-hykyw=@hisr-DNCZ6I znV32ziWzx4wrK5l4{rm>=*XZpfGh^Hf@%2tPf&2H0sfhXqRJ5j>h#_~FM%C*{fvz6 zSMAZ&vA^&^z7(kAGG~e9Y82s**v>=pUpXV-_+KE~&j;qNOj|6Gf;5!>kJ>K&DO9k&#@!gwRlR_*~vkCyKaZpc*15{ye7K%EBGzN% zmsQD=5q9FVDa07dk6N9dTsi)1-z3v(>$PC_oYBQ zp}D9XU8*du-lm;ui1dxWK#s>1-PWZ@Lv%ERNeVS|i5Y&|l8Nvtwe_kD*5`PU6&A`L zmQ6=or{q@utKhz>`~+g6bY6YjCHml`1oAuxZ=}4-rDNP2X|bZwvDs&+WL!25XsKG4_1>cMOF1%`R)LBk3*0paXV z=o;PC*=)2S7+{`@a*H#U!RWJDf?18*AT8?7RBajtjv>X@D|7@VZI{|xjGE-hZDjamsiVO7gI;qFW`9GYFcw+v_1q`+~;t0uu?92sdC+Y zwTeIT@(O4Jd6x*4i0et5;dSAmqS+uo)r+q~IT~V~$R1t%P922l1X&hoi|j>1E58$6 z66Unx3^%HZq=US_4_jG&rsuW9J(sdhKF2|``=jM;`8vCO;&uWyXP8%^t-$EfZZ`ns z9IfW`K7rkpB742k>&tEWS5Eu-V)w_*nY%CO6f7_ersjMtc_@qOV2>Au4ks^-hc-KmDdF3VabuOM1{}JGrjXgrTKL_c6mXFd|BJU z%eGT}BB7;36~#WrWdRU>SV&X;^Qm=r+oj9;?&YOCK|D{J;q#tko7#7?oyRZxV+@C? zY~6}1^0O{ObOU_%Ro7G&6!J}xB}(kJOaOxe`NVWWEvD0?Q2N4_G`ryI(*;i`MDfoWCWbz4*>!sJsB=7F(!NKp9d2BMiz zM#56he56?-Np0%-+(=DBsQC1gC2x(yKoYjO$Fa^!lnB~P9^3I62J%?X@>x0G0}1)N zIMcdKK3W=GCDw`ezTIbq!*YD|T@vuCeISD3RS`TrIAd<91C|>-w#HsF2>oh!>oqsN zm*u?j zAJ&ZRv57Nv+?{9|Y4O|k&>qh=dMOixNl6`I7q8zA#N}JH0P|ZX_$k5a%;9M>@-y>a zcU@2F-l=~C(u2jM7O4snie32}t6g08m8nrj5z2baZ>=IsviBP0o=ul4@q1ZdQ~MUmto2fiBrx|uI}~a)!sgc+1$J8`;A+9~ zDWB$-E>61>vxt z6x>HOZv@3}JrxH*@kaMiuIo?5UDW(16+3=^7P5s`B0X_~GH-YXG59hn6?M(Xkm~sF z(g4TKnzHN^FIjuVgCzm*ZmslfNzOKX^(!ScUpi>atzg_*`u46Bvh0i!quF%7lyFQh zq~LHM!Q#1Equ{yg0`dsKHyIO9Mqh2SnJtv{1zJGsX3aE=dU|`l{qs8XkFW*xJK6*aIu}P#g-?iaSgdDf|`!5HSw#b(P#f) z&~yVxV+_SY5G=cIt?VbNkOD~ulz@32YrEU)tt;svft$aRJ^ z0^wf)+m0cr%OW=wxY;s@+C~U-AG5sf2ukqOZT7FNsm&hD{$*| zK3=C_rzAG#8YG~B?{Ah2G`R$xL?Vfirw%2fVG(=zo<=3)Ayvk=8?7Mw3-IFPn$C+e zoi|QCCBxYmQVy~{r3@k%4cC&hA_$=_3U1AGIMp>(H7-6LH`9Hl5G534V8CKa)G4_b zpm>5E$E`q2ITiy~c0tFq%Ps= z3)e$rKsc97Kq$%v(!j#9Im~`|VtCcNAbF&{0Sb8_jeR9Va%0F}SMkO&BFSvqrZw+h^l3yMSG6G|lZ zzU~02gdG!RTX7iO7&*x^4i-o@om=#Dyi1O8b+L85+l{tn*mp!X-(_S&2MItOr2cG2 zV*{xcmZw+f>toS(yARgmy60@O%rehVXg7mij8}H?-+!hgw=sE;tf$Wgit#V74|AyuB=4V=NFQZc3@*Q z5VWPXZFRddzF)864T7g>E#7UHlSabCyyhY*%YItf6x&bIB%igcygOfSCi^J-iX96HFL1#Rd7u}=mXq#7 z-*Hc9Q=5pX-)kW_mHKjxp)PSgF|OsDNGNn#DZlgJo(>oKmlhT?^&$_8fMcp;g%58w z`za#Uht0xW68+;sR`KiVf(&8lbko615GB^;7K+Y{Wu&LgKXFK0p`6uzu;^XunDb87 z#qQ~;1R5y1W-EL2q!CR(a)=Vh;;5HcB!Fx$-#A^IO>$nMN3}Kxmt8Ux^5DM zc*Yb1nyJIXyD zUARLVjS7Nd_=L6x@!hCh4V#6Vc~1}Ns;Mls(Fq~9;XU_<#_lfFulnln2MN?&9runp zFBjT@@40c=*;UvgHuhV!w#GwJiSWy zOD#!=a>fI;BR&_;At z8biFTpE}#8Hz!a`{XXf^-_@|U<`u1|?|!GD;<_&Fx2OYU_gm=5V9xJ<7eK&JHBu%@}bLv8RzA6kHO;W}iQtb+ywknTq ztSdiE9z80TaenBjv*|X}b4;#Fi79-;bv)F+X+6Bv&cq`7h*EK5&Nj-m@joafG zWR#ptTN34X9S1b!&9!nVmKhDtJjkEGLNAJ z{&uE?G?8fu{z{Jb-z>2^1*%hvJ*dU3OAXyZl$J+vtq5xSU|blC#PGLGh2D54;rGs5E4uR}whi%oPYwA7~McTx{fZmgor1 zvfUphss=8WjBDK~tzUHC42&o+3cT>O6;D%PEt}P@9v&v{C)T`;rvt-Dml~E`wZlO$ z-$!9uc=sY>V|}2Bd6dsOfF{jIc|inO%tl2~nT4usPQcN-aH?qIywz!U^}vy=>RR5F0lk>MoE)MhErkPVb6(icD)* zDjjPpwAvTh;P;T;l#^aYY{2+0fQo~Iea$D6Adhy@`35Cb23~W z#PEI;)c#=a{-cX|`pYIWCOBc|<=%+~ zD4AB-6lbcOGIn^oyg38k;KSk*^R~r^-uu^7FGh_>Hp2HWBp(=M+M6S86Dq=QE3Vxg zro6g0sJU?}gcK1^Z!GC-<=|r`PV|+Q0m1QXpniKBzSVLLeS5$KQjBfVk(cP?Rjs** zv*5;E!bEtLAXKoKiTwIaMkYH~NF99st)ss3(a0jVl93v;Ga2AH8<{SHFsrIKOqUCYWH3 z578PD!Bar3hc{pBoYT1@I}`f|E-s1&CuC7C>|_&Uu-#Id&ClDSo3Xg8l|T4q-MSQo zx+`&0JD{6Ptxavnz{>hVkxJS4yj8B9)7$mbK~!PwB34yQe{*u3#=WDf@KXKL=oz}y zOJgwF_a-d4({5fu zs|&XD??)BOZAl}SdtS^6BW{)B__H9{a$eo2hW*Rq;zivn8tm*27PmrKm6=Nd>$f3nX?zM7%}!3I zfZT6Xr=(_>JCC0^NEV0v&KLPfmL>dG+xSVoi1`madf=abav<~)$xG8|kF&=w=qE^T zEGLi=tpuJSznPt7X@Ef@!W6ICI5WjT&>!3w9pvWHqM?|K*3)P^4Whf=Bp4*;w&ZYY zZV50{azd6LPLN%ceN!ZdF#u-6dRLYNW>fbucdUr#D!r4PizL<_JlnRd1D3+isSGTd z{S%p#1wK||=`F+&Vf$8Wx0%lLnQ8^^wY#$8Ble;k-*_DzPjl>gIZJs=@_XiP8bDDz zJ#uwk437ulNb0E7jhbQJtCTF^k3EOmF{TzyR-fmOBxQ=bzQSUmnCZ%Rl;Jj110Bd~ z!P$j*mJ|2V@j)#(7cW^}tcPctI^b}a-8&~dZ9kARl5ladPqv=F!>eyLSLJFH*mBKt zGHVb$7Nj-pzR97Zy)d~%4=*Jk$A`#l2Y*pD{y+-!Fm zWEq$C;GW`(wU#$&%*yGT3-~UZ7P;25{YT;qM)6S+0xTpCnX%EG#{0x2XQyj#6(=Jr zq2iq8WPvk6E#u75^)sewx)5uow%8Xer5V@`u$5qgy84EpV^@5lHfHaFTY1hfEWe!1OFSGa)2#8_g``tEY_^R~z<~ zS|%r>9to4jJz1&t*d|BA-962L{j?<4BeA5ColgjAp%x$G?ZmjyFE@O6&SiyVP^i<= z!UZXUxnV!@(NRMOG7CXMJ_?)&t5I<~r>$CWf-X#OYTS>qieo8(vZxNw5}s%G36Em# z%Gkb7095+#azQ6y=pP05r^fH`-zdm$<(5*N5i^L+8o6m;dr=B_s`+q(HiEGhoSd%v zl#}agjGBaT0MqEEy-GaTPLGheAty{GjjcOPJdyA$4&ct++9%`Qw2dCth{qVLwu1~M zPs6Z3LW3X14yR@GnnR*0zLn>yh|&FUxPb0~ z#1Xo1zl%#9(u>vWMkWm0V!(*ME7F}wo}`#WtWHSCxSQq^N5~*{Zu0k?lwj)nG>=@Y z0{w(%bPMwxqa-0jaFPlho(z-ty0hY|h}MBoFw7ggZr5f{38f%D&7GIsJ2WDiR{)vy zh+gt#d9wB<6YDOazKsQ$wkS%!{mCwJ5HO=G_4(KfYPfQacd#4gu~NBJZZ@iNa1OMV zeTC-@kI+Hr(S=Y3mij-kC{MNL3M7@E-nDIvXri=f!@DviCECm1DKz0J@;e+u>7nt z09b!kX_*1E&)@m|5n3qPAGxTft~3DJACR6d7ywVN`tcM!;OX*5{i*klc@VLnd+PD8 z4|y7m5%BcppRc6_(Ec{|Q;qhw(OCgcoqj&W1fctUbUG-y-$thc(ET>}Q(wB@Mt^#q z?ziEeK7{W3@Xugb0CeAnf1Z=yC;YkT=Y;>rz0v*nuzyMX=j>6-Iq2Gd*MaX608lHL z=szXuSQ!D-!UiTr#`aLm%m8XWD|0JbIcps~0|4C*NOBT7c4h$jAE0LTS3nh>;eY=-h9NZmE12H_ zJcFXA`w8=T`u_~`htB*GOj@Qti1w-a??wAV`Tjecz|Yux0gn}y!f$_r`2+1=6{uj* zFaL4|ev%a<%g-73ZpD9|f*;25OH=U6%KgL0{<|6Y@0FYWCtd!o+~3*i&zOJE&M#r6 zeIk~h>do{YE&2yd{CA*%VV{KCnRz8;0S}J+S8{%8vo_X_`Abp%BrOJ}-$eavYk!9Q zgMfYsHuLYw&Pe+ol%3&!!($dOxS4-IZ3#v(`Ikt48ZrHE?DgI0{0S+;-=Qz2C(imo zUkv|=z8L-yef_4?7LZcEA@wc*eiQpwIKKmU2K76AeRrsT#`(AS>&Y+v1o|x9f6HGC z|BSzWL6M(SS=Tt>FM!(rw;W!M#-(js^^-oXI{~l-jcLx0T{L^;;e-iNX z@P8KY-(jj>#`%wk>TlxwNlkxH|^8O!IxdpUsVqhVeJA z`BPMXP))|a!?C~WOBnwV#r{2C@*TkcO*P+FRDYrx#=k?UzZxAptq1-ArT&id*P?^( z5WXY*EjswVT>LZAzeB2j4F70p{!{$N_>XAyH>?MGFu!PNjljw5f2r9&36_cWr(%C! zDF1mH{ubx{AqxJ_)4=qPNcVp^4L^WQEKf#UzlV&LD$ zP~Qid4kpXATK+k%=o^I^=E_`?~`D$y|RB z=+CATL$VIve#7B=|4c^I=3D*yc z2jYSv{O%wk+Wi$3UZMq)J9p7E$0{sK%JKKn6rnWmC-Da?5qr()TOSbHyWcJ}8zFqO z;lzdVd>wv@wFL+4ec!i>zFr&c*j{p*&;P#S&>TBAYFfH>*ob zc0)+eUYL}f5}ae35zeM|-pZmjm+o#()GwCTn-t4Z@9?}N^odi3P!3>;!5U>n$p_8c zyZwNBtAlp?VUJ3}B#Lu5_SHCD_zNfEYn}I`x1KzqM6qC5dqFnSGzeMJ_@gd$_C*FL zLFqL}l`tVQq9>w*+2-?}SOq(x$@w<>Y6$!h_pf<NL<_zePx!MRynW`XjWWvv=5%f}23?+rH|hWr~Lo zgW|qU>UoeoJ^hAA`~gdi#2=dXw_*0?XHz(oJmNKyx@rAL?y|1&&<3^IcwWpLbE zyWmcQ`;L&V+1_fl3kSlgpL-DU*c@k?Eb&`yP7Gw7iVzr2* zup+6``7A>yTV(B7CZc?-jrSXn4mc$CXL+5U#2m8*jMkWWN^s0EA3h54;^3u(cZn-i zKg0Q4KNnydLtt1-NX*(u1I70-;_XEg5oD=ka`Qpp&DvBtrvq~`X*kH~M38G^nMm~~ z7|My-FUiO)w|oJLA1z~&HiMGy*ywp=zR4MFT-WJ(ZO@}zPVpWWhNuUu(jP**?3d;- z8?h_o>qlmPRA7V&lqF!-bURDp9txY=-28Z<62~F-DW)6k4gAAf909HYt}vDOw^3xT zxCd=7aj}5c@Ui@DOgUu{g>sTt*Ru9F}l+@zkA z#;EB@!sfBp1X>}Yirv~6_+A4CqZ ztmC_qBNn#BCRNUJX&ZhkA$25UkM!lxc0{eMdGLPP;dDCSw0#Db&OTc0+2#G;DXZ^x z{%rd!zkB}gYv4cg!H?kNmzJ9UVYU5_3E?358~6PEV=p({o4nxQU}VH-K1o=j-K3^<4SnQv5ZP~O~w2^avv5Nd$ z;@X}b+3WRi#(j_44>oY=hF9_6Nf)eZWc3IX{USC;ppWsixUDTME#UgY4gyo(Mlf$y z>KGbK&m4Ma_i8ybhm#}NQD)l5WfnF-Bf=%l^~ecODiWY;RbBnWnb`@XqpNE&#+Xt{ z3LYM$V-Yse>1E#t1f_mm3!hq+m*YncWTM8{^)<1}vjS-lkU|D>nId3d zG~VTc4weBF9QMux|PVtC`kHH z*Ede>s_E#Ri`2a_aWRq5J3tHNz3AR;e~kdoBoX>FmO%)LvZ@Z88L9PF+uGP!UtE2) zE4J4JUFGh}UFYh=X~+Po0%NwSjfRKE3+Xoq?&gIRNTFr|j0)6biK*!xMshMC zWtpsrkdab@IMLqD&dy5^c+M3SCnckx+Oj%_= zL0-fW5%nk(SIKM~k7Z^{QSBYZ)_*XuEOk>+P|;M6N=b`O9(orJWi(dgNs!$_j^ej3 zmEsk$9qj061MXj|ZAidQo0QOxip-5P6O5_VAk1!X`rw1NktoW^df{lOn3MF`v<^Bn zG_)DoXYXa1qo-s}Qd&}aa;kJVSrFK*TMPTVYBJ`hX>a+c7jKbfOKI3%U+-+L!tCFH zCo*ZLAtJT)1D{v+DZ?>yVgh|YU}R_zZgIT@7wYMmmZLucn$NZrX*Z`SEk_UE+rxaD z61+0q(>!jhuEtnOv6o;UI`8t9Jx?(l4*vYYUUZpZI@Etdz(vI*lEqw+g!AL)(3KE@ z98cskknxyx+&=9p)-N!gJW0~>%U|a4_Aup(fzk~$#JMH`CG< z7Z=;eeT>-I4bOTlVs^S_HUn*jD?zkTH=#U$Ah~q)cM9>0=E@ZE7UT_ z%^mtN4(}}XSv};e>DV3$P@yS5o|)GqNijvgTj$0nnjN6Y>AC)nhod2W^G}Vhgb`>- z!?l!UCXe%ToV4Zd6>~h=Tbn;XUITD)*?o+?9&TQbH?+Usu;_!H#5+;&ky2(T7bTdu^}s7%PiR;8hQ49eW8S8}#uIouyr8xhWhcrw zMeadaPB9=N5eAbL1;J9gb`Z;?U6gjh&+W?3!Q27?aJ(d+u2B`fwsFE`fdDSM8F_eT z8O1wxpBCwDC&HeC6YV7YX%xB|r^C^tu{pEg)^Ye51^)E{dRMa0*kPQfXX-G7kw=iS3!fK!XXNzV) zqX1Ls%r;EQLW?$Ty0VM&rI~)Wi>-TOyWTv__EJ$$Ga>ch^_SU7Agi|~R`=))bwaEy zz&)SNL3H$5co}OT5aA=d-?gV7yGd4ZbK`o<)0S0G42AVC?2?~4p9}#}bM%bwru6lU z0Q+5K(;?AAl_a+W5^Y`V5rLj0zcXsrRB}w$!??h>cq^16{V^0e2SH<85!&+G$Nm6e z$WSTj!uNf#^v%b&b9Nuis#NgPjJsuI*^* zIc+w#z5jk3l#9wb>j-UpeuTQ97rZ5(ad9EKTq&;U3kh34?3%WbodLo8bV`q?r|KMm z+{iBT&^IAsEh-C+7Bh`Q3GL0L`jh)1Yoo53{h+VF{HO)w|w-H~H@?g&# zFh>vh5)9L^yl#!BB;ZBOLMQe3+!tx#P@|YGNl>X(36!K4ixVfx_A0%gcf-f){(PmS9&;l}t#pk=j`Y*GxGD3LZ5Q(oDd2nfZN%zC~eT65gg zJCq*ip$aW7FS@cJI57d=b%+q~OI^A7Z1q+@U1vhr>XVmiBjY<(y0zM#_pYwSnkl$@ zuTVK7vJq_}wxS$KlwPH!Y0eNR?J+q@`+_87ntwr;r7c1B?w4PLcc;@qGb~4eW^&x4?XMR@b|$yZv{IJ4AQasm{X7k~ zBX_^#T89LkZ4@j3^BqI4twRuc#59Meb;W#pXsgoYV5PxCC2~z6t6oLdZx}ohNdY(J zn2j~*c1Rm=BFDXqkUYvb-TnN{*a{krw2V?b9PZT7p}L{z?w|+p1^)XCD6K)_+LC-u z>nGm#^g^qkPlmB0Q;`#Z3xfPGhODa`dwkNRShgsrjWIF!{3pUBNS%k3nJ-H{ zyTN==VWMA^80=vrOkj`Ct!=pzm&@mzK}X=pRWH12%Q@KJ37qw)VcUMxL4+QGr~UFJ zB=8dWBGuCa6AMtjnC8_Y*J%~+N6EtB9W(3Ct9lid@k-#zrh#i}{$osH0kQG^;g8GOTGLrb^M^=?c@D<;dSESzWwKNy-G1HSL zD=d-_huGPiy=u5dc|T2GVX$B$#BJt&^1pUz&aA-h8bSSn=m#E4ORCbXAaQW7XI1CA zhGKoT-GVn*0osbC?LNP_q^_2nAv=&4P92g?AQW(os6h+2EI|{6NS%2O9pRc7t%c_~ z$yt~@zN^G6!Tzn?8O?r=#JH=HftxdbJ9dg|P;9Mo+q!(y*vf4IfU&kK0v8hOl`5w` zJw}Ep-{Y*#Q4o-w;O5HawM>-IAxN9NQhPH{s5yPSYSsf=7rU1d!p& z!Oh=_Q(&$i0PD$TfMy1ZeKh5Dv5UC9xjxoDa_3-WFOs*fV~~&I+OWw+>qEYvHf*!T zIPiBkJIx8|&DVz-D8^J}`zA!RG_rGEvZuCSI7o4OejYD#&YgIc{sIKLgG>#qZE~&a zbcFdr!N3K*-`o&D7x}PP)MQY8!~+GP)6G3FMD8X-9DNC+4mZpVGuQ(n zHQ0Ff?cL4Sj)!uWZ(aH0m9^esLk1SZx;i43g0|}XG?gbu#NW2WB8YD%(4tRB(WOE& zLNV0XT)|_JCNaw3fEhcS*H`ep8d2W5OS#_^6S_9`;aq+d_JS4>sXfZ?i3>@06ycK) zK;))mjd=ZPW$ngE?|u&tawJVSpH{g_q;>zU`V3&i&j=YqbU%=6Gx>hqdqXH2D{%v$ z11D}*?%!(btIsml>L=wU98yzfqOPGbVZvxNt=Dxg9QKCdwSFF#zL3AP$2&`wA$WgX zYolx$Dxeq)ES#8Y2*?9XCed7tQy;`QS64^4DEuTeYlj8%rMZA2v{#|nI5<4mZyx=O zgwg8T!PjWsUIF(X#^WvT*SebX;~kmTfa+)6N)(2k{^HmL{fBBs*s6_i-18V#tC^p zF7{$uNJsRz&BfFL`f#dZOQBnP?q}+XkEM>o&RKPJ3NK)cFT~ggvOSpTVd>|e9Pv{5 zrJ_hqV{>&W4Ra_sWY;#Zz7@!lukp80)fXfTGp`|AcXTKmc~95E_FFrvL&#(n$wf+P zYg!tlXc+h9M6O!q&=Va>h~@PLzVZaLg6A(*V0LGt zzRr8uq_XoR_Zm%+n&Kl#_G*L|E(yqGPjjinXvdZGXoQ&*ivnMy-3~x zb{gugaYE;9H>QZ4oSxrxUZJS6jG{V;b8=e88j;>A zbVMB786HVj55KF6*Eebg7Wl~bUWB(q7hxV9_~P;+XUx|ZeJHrk*wG!Im^I*AVnTd$ zQe0e@S8_^10x`n+))qAA3R%MFXus?Gr05l%{#mWgOc^+C zDd(m`M|g@%DrYBU;5XmojD5}#l&f_G1Zw7NP9Wc<28r~)C6zwLf7c}KMdKja6(hY9@?9;ds2}$a4s#2P?Nr44+qhH7_X%8`U$wQ0RNjII-;*kxUR}M3 z@$e8Pu*yB%iU7BtJsVlp0A4bdW@EuWkTjxz+mQy*b^-yuB*|KN-GN;s+1w1+5E0&T zjxchQ%9}dNrjUIvFkdKXJS!9sF3;b`h;g8AlGV9d8gS?&?@qnj5@6SGg0LNSLhiv{Y77g_{B@C69LD!m;HRtK5zg^PU!Io9Dzm!*4yFIM?Q+Jl({0ng6Z!^Z>@Bev0RQqIHl8Apdjau9g@slo)Wa$@?e zZkz^mtNgP~RLSD-CURxl2?$Tza5u!q=>$6hNm=>R>B1Cfs)6daE5?wANn*(y2r8y` z&Vwn^BulN2N`FPM)yj+Q!zh)j>xhPtzho;4KA3S&Woq%z0ijMqg)y;O;t?+5DUs`9+%d- zm1jM1sdiNyVxfNU_=6dex7Vh6pO5c*$@eOpT9=rE2`Ze7-1IJXhWZvq$!+DtRr44K zu=B%fHWit!!bZ5fZf?V^oSdBCvANqbjv5Z?@`Uu-M$BF^@$?4d=82}UGCn5PIJuA1 zd^mGFa^jy)A8l!BrI|Y_cF2Wvl|*^JY42N>nO|q6>*+GN2QB>Q6QT9i^>a(zQ_wuC zsbtT^CF&sDT-h_t+=LJth=S+v*44qrwKAui<$j1;xGN+UW8!hX5MGR)#{|6~Qp#?s z`L+N>slK(vo9mrS`<$xB-Mw^gLBa%OptUd`#stJfR3Jkx9;^wd$@AsYh41&vrwg7R zcb^&%e?0N#M;E~#orJ$PJYRf&;{W@F-}{9FVE;APU%ux1-RJi{jUV;=#P<&(`O)zF zvH!V0?2d;?nl^c<&4mP2srhXlj|5d4W>h-Pej&MJ1Ah_k#KhIaV2b84PHsPO+uow8 z#+L*xq`db$x9!oEoKawmc;`O$-w-EWPB(l=PrNd3jR|B#w}0zuXJBKRdCXdXUARfczc<~fNwh5Q1dk@W7}>Tc^(uS^?iO9Lq4*b%h{q8E{EI6z_*#L z1p$H^cdNDvEshLqhX(nLf@FtO27=+!sx4bltECUjZ7VKKb!}?``UmFis%o08++U`Z zEv1-DI=4Mc5QhanrM6i&jZCw%oz0#N&fkLJn|T}rZ1ww9eTcYyU&{YxbRyfsL=?v| zxZ$-t<01}LN|IOeI!`X;eeLnuwX~95UDso1p(1FWln9!nndks%k)0!KgyirLS2CYI zXL4E+4tDG0?Oa?asbN}3G-zJ8EE8SN`*^RqrMVp(40LQvA^q_12$%~`hmx#Tn)}jd zB`|JI5UFhSJbFS+l2+Bvvrk)sYmQf!m!9Df3Crc57bh2YOpD2#^ohE6I$zrhs}e+4 zAla-rwBs(KiWZ& zzGlPmk&%;ak}YFQMWKM)dM{TRTpGKc3mU2&G9zFOg?`~V@gVc92t7V@Y#X*mIi?>u zNca@G2Lsks!au|yHz@PP)GO7VO3^qr-z`RraFi!Y#vK(ZR1j69${`HOx+){(u2=7< z)(K{aSLj1W_wYaaP&Zp4F}}^8P2f42lM3HD-fs_;_4KP^AfWQ2;D6y4e;&P{Wup7d zFMdBf{Aa)T;{?GkB`5ylW9R`NR6e3oTL+U{p4_jzVF<9gI|L%cIQE zM+BI5tFeXU9rGzUI>?^>5@iU<;@XQ5%hBT;Vx%k+8eXKeNRK6)tu%}}WFh4OGA1Qy zL39di94`O^<~u4XpGvgwA<6JaXLiaSvZUZauKObdDS`?n*2ONLq^8;3`CBuDna_$D zLY_ER7t4%`^1(7B6}*I^WjAW0ky%X}&boGHnEqwM{CC}VQ+ifvdSxLb#la!X`4LAM zcNn2o`-jAG0D>zg=G9T7UU2pl2h&&VaytI1Ry#NkCYFR%F`~FQKGunn2OsV|JWqKl zrlm;7_gQS-K|00tt1EBA`}pkx&Vc2bQY$^P9abaTP|=@rC+q_RS)W zGm6?bJ)tv)*uy;>w+UCyZ9>oc>pSKk(R7qk6i zddcE=W{$otGSxacDDk>{+770hnVXUnE*j_JL0QD6t45sfN9dc74qq8yywAoLS}7?M zl!`Q}6cU>YV3dT!HARs&RH0D8wsHBYY9;jE*(H;Ta%AYy!*v0{?#WRC`bpwNvL)ml z(k0}vr*yJm8B%?$s6nBtywU!dG3;piO!d$>I zl2~t+{jk373I|k>GZ)gOf9G^{>w6iOLe+G7_hPDLz5XwV>Y0C@If<5rhUWS9bN&0V zrau$a-#J$F?~mL34~XiU(km0RUcE+G7`QMvRGC9xZz7-16v(=t#ayLXvj`8WkSS|x zFRD!m%2Kdl=?8~%TMd#Eg<@sJ`z0UeKj@_>D~53&vVOa{Ng8z-p+Dj{a*|BFj^xXd z&Rhdd58m{WnOVMY=q%BD-|QB13p; zXga$EUInNoBpJ|PNUYOfz^Wv%)$!tsuHqjf(!MliO_a`_FfiE4pj9i~GGAvgs!N1E ztEs6SkO%I$QG^KuvU??PYR{KGr>LoN(70kh^S)!Jb)~SJq9(}>79(jp7%kh!GUoLy zmfgF>o#s``6K7Smh1JRV-IH1d4I9>j_T(A|Tf{&bld-R)Gzj9keSI~GGfe7cN4p1C zOXz6F-A39g5e@APHTSB1H52bk5};im{4mVW#DQP;**9$!t5afoI0XgX!}s=`j&XCW z@9i0vH>la!%W^>xA)e7i$dOjoWOD?JEJ($O2ni37$NC(eK_2sYUwT%5#dJz z*Mx!<3IlR zUk|y|8$=Rn-lpbNL&L~seP%1569}_~1p@-2C!JQ!@`dy2Fvc zJ^Fay%cuKvBB3fCQvM{ZR{2C?FulgvU2KmJ$n*2}l~*S$`yR84P?RqP+tS(8>e-T@ z<=UN9lto=Ni%RYfuf=IvvF}Uo`2$B+w;fqn=sm9tJwz;<(b)GTo<3OX5Y3(AYV+XR zy(4$DLHpM$E2T{wc*n+p(>hYLJ?r*)t5)28Ge|3E1IOi*t8k^%bTwJ8$tzU*PHVD|EXJ*~SlX7=YzvBeO$YE4flN->ZoMuxZf@gg!*$)HUXKn1!?8pm zZOp;%pyC3vck>V3qzwJ`o{~K+q-;9Gbm?SE77NOXay!PS zpI%c_RW0v+F~!h=iK+giYBL~yg3VrSJX+naFc6>#iecnl3pI%HMCyn|l>yDKe=%$9!M1tXr(PDOk z>K4hCO&g^T(M7%4)6dr|Q55ZVr|^Mo&chn^V2B!%h5_%8!jBnzy&g4a@IF=_FCq(& z=D}Ueix3W6!%6}#)@j3~^%jf^w>O3cXF#XR9s~5Arfl+UWuOX#uQkLg&k;}9LW2%* ze8oqCDx}>}FOXiJYiMthbx)0mu6K_&w2wdr^yl+`;TL|METyGqV*br9Jf9i-vtRge zGW3@M*#C6A{GWRUwFTQ88W>m~?XY1&NK#Rx6ETRz`t`j!y6E1lL(n`)r?|Iqf1!MVNJ z+HY*zwr$&5v2EMQifw1bw(Vrawy|Q{Jo$I+?zgK?zo&ZFKKuD}&#GC^w>j=Ht}(9P z7;y^2meGeJfUW=#v@L{m>Q_b2QkV&j;0oSQFIfh-rnzAXhT^tQGkTYV+(<|1-+*hc z&hZ0o^;F(KaOKJ0nioxsO&9}$P9kky_Jzin=M=CUc|OjEkAk-GKDIg?cZWqd8w%FD zQZN!f(+mn*tV=Fg?Y&SqJ1v$T8sa`Kt1z=~1?rWQ-0NfNhbE zevu<>PBQ#l3iv2n<*ecyS|G}K+!)&+e4tlaA76rG7rbgNM4KyPej|i!t16p^WDU7k z`Z!&f6|ya>;q+xZuL(9YO3ppcRncpGiL~N-iB0Yxa z+1cXP!oRHu!fr!2QLCiX0MDc@_ig9Ph6Do(S5{0i(I~B<&=@nF%O_vh>u&5YS*28J-Z zFc#(+w-+@qw5K{yki-HeU=!I{c?!mP_2lK}_x1ez{@nVcbLUFuM5X%_1^Sz&!MogV zZXqKxN!na2CT!^1-na7f5v=g)N&s%*i;w?j$6zh<&yp-=V1T|3LXxOGx#f1#UA_?Wa01ba4-f%^B zTHV{KGcKr}t95D=%{&pAGAC0I0z*;<8Ex63JTbuRnFNl!L9Oa_NW!jts>GGcrvUu{A6}G%7Lo}~4#9i;Nur%VE8>kc1PwFR zoHYah_eDKG1_*9WoVfsVl_Ou$A=PK55;|w35Yly|;Bu+h*Az}sQK>+OU-~h@X&C0Y zNL=b>F%!}2fJ@JmFEV`h3Kth(pv}beJsP;^0pl?tnFV5186|sttzM!4L&dpudS1*W zIbnqg7;*v!gb{cF;kU^`Y>Z4lGX$>cj_7|4_=&1-x^8{WeFDed6;}M4p!-)W{aZ55 z^iLzs|HeJ{&06^XW5)k~9C9a9*5$E0P=?2S!0h$yHIt;ZKovC;1hsw_sb)yDHk!Jy zMmksQVci%YRWQLXC8-112nEO%Ri~zjDz>27NzW<*n(Xy7Gebq7B)=}){T?Sjdc&T2 z$-b)6;+JQXI~_(KOB^+9;KYH;oXq!SmMU7op@Ro_0s83=55z+kssl8xU(ccKPapLA zyC>DD4HQY32e9Lyu2#S@1RP9+5wALy>^w?c1VMvzTO*b(gN012^untmTlLsC0KV3a zwaD9sf|&Y~XR3%~5e^|NPO7L}wZv~>#h58Q0}KDmrHRUfln4nxd488^Rl8P(NTs~- zb%=bLhHdz}F$tG>u$m~=rCO9EH6}pUfg$PO4H2(m@gUaFRMqgNLcbLH(0zJo-H;LO zX_E}|^LbDr19?-m)CH`eYG9E)tOt)2!q6E5|J=!CMGJ{YtK>QLu`7hQFk5i+W zD^mN)@hxrncm(xpn{?}37)A5b9Iju$1A9Le++7Ll8#_BYQ8dzELxJ`NfaQkgJ)?mr zfjK53g+Oa%qS?5$1GB^R-F+PntgMZkoScXsT}&K&sW|>PxN&DFHo>52BS=G{N?x7G zxRzvI2b&Uo{che3*GV98L%yk6u{0*zC*F|DlyuXh0=m;=QvYtVRx+!%gYk5awwYUV z3tr+EDxD~w>gUK<*N7gG`DFj3i_DV?hwwO}JqbajYCKT0b|+$K>BJ+4S2`(x(Gfpc z0L0YO%Z8SPF}k2FEf@N=oG^--MBOBo35^dwC9>ReL27Z%-)_z#>8lkx1v2cAI$5eh z1VncyLkS>RF`M$}OT>Vx5qVVv*RVqAnYIyGBiav`-!l-UDosdGlH7MVz%*%80quvK zp|?qv__9GMX8?Gu4XYkwny@Y8q$<#!Xq}MxYA^k_+V`e0J69 z=J;p4=k0`tF4A=F?WP7gQFmi?Ew>s0P$LdB?1a1<$MfmLPU^&fEQcF3mZB=2a{G+G z5-eHwrpBtV2kRy@bqRSCxoCL!#h5H{V^tmMP2BT*h>H{EPyj*IJUS+Ow)dzg zI!hT)JTYCy(#^?&Yv;rTqbcG_@GCZeJ;ifA)@iS&;2zK(9Y$c3I8>3??a6x|!}{7( z*tc2L56RcFYNWqO>SEAnaOreSbgRQS-r@`))fD$Naw(pQhF zIg95eBn1zb-ACW3{GStx(_$1U1UE)}lHIq3JV%2k7Aj;vpQR+#YH!00rwBo41?a+OzTX zmfw6YkGijpd=4ji$PmD9rZFId4)=2t;u8ada(hCF0fPE_)p7VRIcTB;0Woe&U=-AO z;$?~$69fwq!rf`~`D4i#G2{zp(sA(g;`HL^ckVc3xPrq%`6GoSP{73V4;`O_h3XnB zD?2M?sL;@EIop(x-~xq&O2+aGfLK#A>1mQxmb6PN?959$6n;?B(^BpnDnXWnlX2pN zPmR)3R#e)UtF*W|ySlnIR%l^cQIAXAt~w*Z`5-}Zz-0d#r%q9&(qhTt`q)X1kB_Gg z^wdc$7S*7nJv>ObNkbkX5jVIMbrf}ab9?=R-Et)(D=(jUC9{FCnhpdZUT8dVc>jyjSbQYc; z1Cn1)&)1RQ`BhJ>cz|#0UE6_aPq8YMKElk5K`}$Rig$IH*Zw7P=z0sTB#r~-+>t9! zI#%0?b9I_*2y+{e0tc16Qo(75iN~K?uzrCn{}+3S5MbTqNPIgT)n$oWa}E?DCs7{a zo=Um5k1X-=%SnBfswY5^kSH+r&GFbP7?*|Q17?VHX(0@xiev5hL8~V;)uk_pz;@$S z7APu|Pa~g$)epruE5yj4QGbSX+DgldE`yho#i0%fs#*BZc%p6b7IxpJFZa8-Wff8! zre9$348hb~HSOMBt|v|O7@ORH8HL0fLuPUsDbf99zf;6SkyVzZ`uMKY(a@JQE zsYFjtM%;FrjNEWkSsQKusRl5m$a7z7hd9aek9G?v4sSv|b_2C4O?3 z1lSH2i~>dzVF#7*)CpzDJWP^FJP_Y9Eap^+4X{H&#(KIB8#|P*zYdw9srihW@f2}H zGVi6T9Epk#0$z>KRh!T1w5$m1i6E^`r-32IyKSk_)37^NB@3}p-r*o*jL;;pyGEzw zbl*P@+?;E}YnsvHZQXL9PY`cL-wKg2&L89+9DAPx+krb`yNdyuwSB%(vjOiVW>kugLY z!}?@5uBWTA1?jKbGfEB%2F9+CUK-7t0`nk@Oe&M5Qq#mstJs?LlJ67fhAu%9zyhWw zc!!JHoA)wGRc1xv!}a4BAy8u&6}<(kGQg<>XrV`l_&wiYM2{F71k}x13or!U2zyI} zhB?Kl>4bnKe-vJ>)gBrJZ$rO{{du84f)zQuS7%Prc(HBIZ37=IjILEa=pn#h#ZUIc z*sxP6w8(7j`8-i~`ht5toTWg~2;5vS-EivuIKwhmp!ADYA8&gEfBWi-ihvv!uL z=UDq=@@(Dv?8)x6v!{v+{fKtRAWM^y`cNSjlI)8rP2dRXK+0u$=J|f3e^+|>6#FUT zZL<9AV7Gtc{#hYblM>zW1myYIFId6{uM?@QzG|GovXh_Nu7RGGJ0CFrGZ;@87$L0dZbVR+q@%bKZZTih^#fuh9kk|Dsj z4I&E_AFa?S1|CT7W3IK+ibBy16!0u#&RP*HZarmPo$d0I^OJdOFqqfw zY&lu0507+;99d#Rc{V(MnG87Hyw=Y0=Dar9s#)^|n@QLvm4jU&-7(i+hU&e%jP6L$ zgVYq1$tudr6etlHr%;&o)E+cgkgPl3IkrB|(+GM@@_hven z&i+crZ8UVLsl$7Y8g0&FfRCi?sjfdsm{>85mDYfLSNZXteOjqjAs1CUGPqX zBuJRRaUcQ^%s%&S&>JBi9skYc{P!}7k)8D)+$iS1k1zd`-Io2oW4HZZy`0aqlq}Fg zL+`+hiNpN06k$XaaYz`Wc%sun7@1BLGCVv_n$p51oc6-fV`T84NokSb7}ROdLI?J4IB=eWUqVszAwY;g;spf} z!X>EQ4ooKSlIIb({ka62TOpwvv*R65&bX#i<}fq_@Sf}MgotxM8Flz14<^bC>t z9p1W0L|s_GLdg*%jU(nF%CV`E%iHTaMSL}A_K9h@;&df|Vt^VDe49mdJwHsdn#xAuWXY!X9WWfw6DY*xWe~%lrOR1bv|Ky~_NvKshC;J&C;2Oqp~}K?ei!Np z7&=f4BTJ!-tqr;QsC~s*+`p{cnGMK$;kh)kl#W3;(Gx=EBx2C~gdxAJFC1jY(tOzL ziODE2)zhS@IW#33mIWU2a$}KdQ}<`sBj9=Lj05PS$yU%*a?&!x!O8m7K(~7Si27D< zW8phweY)7Pq=FVsPs&&-qFsp;NUWGHVd^U>yXV&tI_VTSZUuK#Jbv)%G*D-#m4=DU z(zvWP=JbNYmF~|=UijOI&ZkC!)%B4lv%Xu)&Gy3mv6JsAd-&qD_Vw`K_e?=Emx%#e ztZ3kMnmS?hAo6I9mCNRIF}m8Xb-Zm~0u-pfu57pA19vk5`eV@wR(0AS8r;KhM@O?6(rKo|psA}JXBY#We;M_0AmhN0W#t1x)U3S&gV zdQ6eUd_f00>Mn~a4k9)$Win*<^$_mB^*wgzI{E=$w$#8+-sQ1(k*}^-{6ZkQZ(zEB zp*9hJjmZ2gv#rMJ2J|mSd_mD)pIPvBW+AX{UDb=%TkCR|>5+IsffnOW}zvkGjLT|kR`F$4A|om)9cnB&sf{@q_bj?Kf7wLk$L;^H>I#%*Y= zIx5OT7VIAm=K(~2WGOqo7q77nrhq3lGEc}4;n}iO=?Am59Kc34DDDOT76q4}k-Oju zm-cfGIV=v5Zhw2Vb~4(v=|eqX*lb>67S%scpN;=2qkYjlL)WvXDKtUcOnav1tZ`Z% zW~0ZYi-9^Avw?et-?(0(*m~w6YO2e{+T&69PvYdy%NT#Vr)ib5eY+4em(iya91c^h zpQr#yhPC^6_uqb#x2>kVP56+0^I#y~*!8ws&#{F?#hN6@#B^mMHdkJyzUDD{74|dm z;iD8)c5QCFoaw8lw@$pLVxv_q&bg|2Rn&vq)$2B$m_cEEe$&x0RyV&BKfW$~;J1~g z3s*Zk8?Np3RNW88_x&xKMb>ZtorAg>@K@)VRg3(7e3nUgPnpBjVD@optFyB+E7$dW z6U*~5MK@`cUpeW&u21%U_92$t;P}cJw6!am;b5evWi+Vk^)%C|o9ab^cj(!Zih#1{zm?T^ZoKPT5&Av&-WA88)OSVc=MMaS)^$|%#p%jMTwvqazO;#8<03a1FpbPpyXcTUKSQmUv2@z z8DL}ygmfX%NTHCh?TMH=PV_=;AkAS#^gI5c{k>Oys7pU!)~?5>e{)Iy1M$Gl_7AAh z-{3O;QbBY47ro*?s-XWrFgE|=68bMscZLnXkRA(e5eg}hqZDU#IGJfk9oe~&k=(55 z9T%LzN+07mS^db2s^@`%7A0eItlvdf4iurO@fH2mgD~&M{YCp#$5GqW*=bGB=W_Zj z!0iV5{hx9NfV~6IK%KyS*il!|Ko5`AZvVG%1caR(2oR)Tp@LbAD0mVWFztdk2oM}^ z;567vF%kk#Vgw2nu*ktbH@+Z5v)lXt2|fJr64wKJK6UCaSiu7B>nnJ+`fG6#jqqq! z;`ik7l!AQ=aSGoPaA1&~p&<%^lqgK2Ibp*FJ~I*!KAiQ@kl+$}JdFM_c_A~$h>EjO z>SWY(e0|l=9B9lbh~IW%IcUh@xOYf*f3aSAIWQwDBg2~@07nH0brF<6)SR>lImrXZ zd5_L083{}tT`uMHS*oR9=tU#_sOV6Xf_(RdpQ=MO96roui|zLx&#;yO{9? z3j%)pG*~A-lV|Vx*eJn$h@*Why~ZUb#@h$zsVQoZq7SgLRW=t{yVaL?9qk>zaW8CW zWnmwP3`{gE5b<+=)Q~d}S@e+v(1Stp)301EfQ!Sx?6_YC{XjEUd^gF;?; zl+)OOfCY&S6FEB119rt#@{cAjbbM;SLrCY~krQuEVk6R5HAo9rF@tvtyrtM~bg3}$ z+&8IxXYVVkZ@)Fp5)y`Efb&Q(|G@|9fnF+g2@ppK5N65?)$H6xsf8J;OCM$u%$&4W zj)M2bTqPgH3RY>&juaNl2lU0=ck&`b&)Yy{ru$bDGb>>o(UXr2895|?#P?c?=cWc& zVbyp(ccf&z%%qfLJ#9MgEvidwjO4NXh&GR8%>tdJs>-UWGg$Dsv*qO_Rp)WdN%X}| zCBmGzn9hp}>*^Xx>UOWl#1RO1s9qxkvnht$enoYnV6?>Ewq!jeLQ8AE7guL*r9AED z%Gp!ZWf;94Oj&HxhE>DW#&JWy95$IDJFt(na=8ky<5;GXk<4s#*rtO)H)c*q#k`*& zG-Ge~KOe6_fTN&u#cEeDJqA(pi>E#b%g*;U@--{8=KWYRCQ@Y2mX;pfB)DByt6N$s zmt-SXjaiNf?*kk?4XtZy3hJu0TfXEX#(1rxjltaUkK^xkGETFF<>n@uhHKzC(h+{$MgilzqI^7&Mzh5QP-er zLs%T9XP|lHqW= z0p}=W*O8BpTw@Q{w_m^5J{qjtj2rXnI!Reb z(!?+MF|Z9stR!p%ENrA5A}e#`@zeBGzO48z?QVRyfOfVRstZnu#JsYL0W_{K$zh=L zXVz$7!w7)|s~VzrEZ?L!lZr#8GR%5lrU6?!2FHS=|v)BX2}ap@FRy!sl|BygafMc zuX7ur>{UX7rbJm$PW5MyPlO>%ZJ?;KA4)~0n;?qxpuA(O)n%wg^w?v!957UX7Z)BJ zL*2%nN~)vCH?`VLh8xbnF8DAG>^&!Fe|$d{30NPjZ=Dr_^e70hN{2zMT#t+sZoAG$OdD$`JnNkBkfujXjegU~S~ z_#Dk{f8g_d+$|a``K;vdcWc3D7BxP3oLrD_K|=HQ?o!TDdZ13)8AEdwxGYDjcWmNT zICy*xR1DQ~pN|OW1pz|~@AgHE)mY=EDOF`OZ*UB`UdHM$v_aRiPad?f=To$P6rJ~~ zHo*$5*t95JtkCX_1)STA8>y}EUo0`U#A^LIbiFz~TJj*J_iOTXdrNTaO33nSk@mZE zv+9w)!EvLUSJ^CDi`g#v%=D_ifJAXHkJR^_$@EEV>wHyB0xLbO-+%3^^Mdxnb z44yl<+@*R_$}G7m!r>kkd7Dz~Zmne3*sOQjSl#Ay?O5aFx=6Ij^|{@}UnBn#F9~qU z`Z+bt^MpC#unTR5%XyQ&;kiqk#dEWY9ORT`_vHKKt>u3DvJ_8pb1)w2f()8EMI&BeF56W&+dD3MPp9~Z-sXf8B}aP5zjyt3?k^U)CsVHJ>ibM> zTdE^4?or;VWer?>;*>$d!NI}d;laVW+z5Iyu87O(n5#yyL?oG_kRYKfvcj1e1S-}r zq~j^EyM@mb0UngTt?k#=rXJoURp8cw>JTWab!;pbR-1=W+b!LxD`;1j&G*qBB94=< zFVlCaFQ6bx8KnPr3i-Fp@ULu zMT)xxELx6eE_uq-@ZcL@1Ttcm7k3?ju{&qaz;C0Ql%QhLsQHYQ3MUEwmb`8bU<2b% z4mGpfG1^7dOx$0SnkI~?D3%8#Ipb2g_(B{Y>6v!rwOo9z?V9VoP3^y;9~KY9vVM^$ zEr+h8NmMhdaQ(vF%;^B<70%@e1op{kVqMgT!b(SwK1`<|9A(yaX>H#mHbU0jMxn@Y zGjwk4saVz3EhX`=KHfdy48XxPad~tf@`mq$oeY2m#d8<8bJ3|`vMBUUdNIT63yOdr z!)4zz`W(KKrv9U%@F%&bt@qyCFY`m{r}oIt#20Im+0bRLOBr5YtgV%pbN>iyJ02|< z88|mqZQ2P`heVHG%Gec|J*`g>^zHCe?JXTI*0!dNEoJ2r$-^ktfL**XHa{#V8Md~yjg%9wZjoqB?C>)(VEJS5y7@RkU2b2mm#YqT3fE0o zyK?B8++gIVt1dbtvVLU+a&dFUi1o{N2GTZ>mht>1Dr~QB&m8!CdB}k`EIH~4LM z5btl`ldp)L3v&n(JUZdYD!Fsco|^aIlK-!V&z|_NWxnjFMn9Xki<4D*63_d?dzgij z%z>_pI=Qh=X)y8;CUtAwKac$rk;*2%v4m{`q`wXsHHZDQ}FFOQ)Y#m`v$%{Q%@~~r2*Z& z`RkTK?7Y;8u{Vlb^l9O#p|r48j+t}+Q4ZkIQ}j0OxrKu=hO*(VVM+>U-Ho*8aB;UK_Bj@yO=WNwk#;DOVeW5$RDHL@K@FsWkOP^wd(!6rFt*F6|UpW-ygP1f-m$ z3{*jyLirqajk=}vLriQh=c)B#3X@T{5>fBU^OU<>i4%|O;->V z0@Nf#^IH)_DyEk(EqE75saT<`sXYK@|E$rnNc+_l;M3NB+JEOafF1$SxBN*1{!4}m zHBpE!HnWs@ON+l&0WRbYA|MAcVCN48xJlp1!|yrrI$l9_8aC`nkjyOg>0X52t;RJV zAIx+*w6mX=@W39F?*As#{T0Ff3U!POZ2yq7|HdHx*J}AMnfrU6&3{xa|F4>iKIF07 zaE7Vvhx__&c5v5_uXid@Jx;0kq5>#fFT6`Ne}ykhmW3s|DjsPI)?UcuHey&dR&=#b zhMd-Fh^BCDh_SvcyQ(9uyNoUykG=-h@b4tcck_4lTs@Wjz~>PiKI}q*3mxAR91a>j zu;03=!-Eh*AdJW-(pONX5YP`BUW-X{BvPh{A9eUefI@%(5`#Woh(Wa@yb%z|N+=`~ zk{UQCt1a?LYuBcs);LQzU1{klx3D`Oq#^mGPUjlG;xd5gpBt zqpXZ6yQX379F76&V(AqtF@}zq~|_zkpNGc_o#P%`MEb?`NhxPJ;lZr9;Zd zzlLn;&^B>30SUL-Wk-ZcNU;n-SNUW+d}Z0QfDL_IZ}tW)ZyGSqmlOeQeRiM=3SoL2 zdN)|v^I&A_c~AJ)b)v)uk@4`-ri?LRLgAJwwAGhiDs89nzuUi*{N}=#R!a|-*cob) zKXWPH4S-Tp(^~Jr=wa@8r+Hy&0u`WYYKzz3-In!Tb?6iLliw*7^aD)mXomgIAbw(* zS~@NOQ~Jfi(5ceCmVD}FA>r>(ssN_74&IjhSmd70SKc=)f9uECi^-#Lc%TBhP>l+X zawb;Y2QWMy4e5`^qf0!1j*iudB`#!WT{l)#WgPX&nKaz$S%D}Gd6RlCKfv0SCr|Q^ zyZM(Hb@_SDc91|$@^a+G@Y64~5AsoaWs@ts(SyZto9j-gD&7|}-7d-5lk2(Dp`}MS zjP(=rirC9dPjb;!>t(HVaI(vx^xs3KuWA5uCkv4vclNfH*B92}kt*%4{kb$B^DnqKPCz=_dtp=Y#j`3+8ePSpo)b1q{-G*vIHx=cDbjp6_5g6%!G z9^rpjl<<2RY(Kpnn2NJva!g=jYjnPUg!dfwW(T-_8R`_ydD3k&XPq^!3(HXx1cFgh z#jv`dt;$mK^6Yz_SX_LRH0pYZiiksbMU9P>f+VeC*5YgC%*fJb;XYqlb9(*O?ljGP z-gJ~B5)bY*x@O-IDNGZ)%LAy0jq`=jH|<6!$kgJbSc{4TXO#}9>I>B!8wnfC90f$!f-AwDkBF1pU=|}!Ur)Z4C^3JiQYFjJghR#<#Ajadl@FcK|=0` zkGeV{op?S?ynGbiVH1J(!v9Us`g_Zbk%965U|j$1Li*?Y?7u?{_}`ZJ);_R@d*Gy{ z;-x4_^TTOEX&lwzoUE;FqN4}x&6+DG4IFVoM&?9BJ zwt-0K3BdI3T!RpWe+zbV{rv+cbitv)vqImh-gkG;fbr9uq(AuaS(pqa=33aO)*Xm4 zNUA`bAwOTEQp?&^yHnc1+LeYn1amM9qC|0|4@6rZ0IRi|YjrQ^B(@Jx0tG9p&v-LJ zUS_xWdT##e`XxPGLqj7y-P>2p6N^55Trw;&Iy?df9+nW%9zy^uyGFqV;&cz%dpDdA z0Mmy$dq8$_$Lt6V1ybq~Iv5^5oPgJp!dpR!hGJrR^04HtHQa%QjQH0n(SQNF?|eOY ztB5@a)H6(;s7T#zqS74m6&l1PKb4QB;!EctzT{@4XR59QNzzXfc&>Q z$OywlVD$0ff3OX}ohPB6BvK?kIOH_X#NV64Q!d?^jMcMvJVQTnDHbYEF}EmL?=dgv-rq3qv!;IJji!44TH^wyOenUu17 z3wQ*Mu!va`#pbBJmv%}K`K-@vZE`adDwnbDt&LJ{-rr9|>DJ_=r!SopHzH>+Hc6Eo zUtJ`ykLxZ)j0XjDU~W98h0W+|`{Uyre%OU%seS<2_gc`9({@Na7fQ{|kX&8<_~tc| zk(E3+-9>^GjDAmi?#|VZ8f!DrOifQ6H}2&qkNw=5T575JL`+TDzw>}(L{uh1)2356 z@#9p%2f>mq6sza3-~^g&(6lIc_xY-oDp))@0-Wx&tg}|H%4Ex&gc~(o-)PiarnNdm zouAw7)MdXpDafy>c#!pZ_+emxM$ealhZJ-Z_;nj3`18*Q08ctzR$PXUJW0yPmdgWt zY>co(qKD09yT$gJD~GG=)0CCl@Sm0DbvAaI3Tm=}_lZKWqT>tml%*7C=$Fy+%tn12 ztUq^mLfp_%gbJA7Np`%1_LJCFfr3TxeI!|f2`~aKx0lx&cxY&-xcIOc7Z;Ep=St|Y z7TekD>FwNm)MH|OPel=+{~a?2jVA;j0Hkfo@N{W61r23XdRjJlW!%Vqm$2oA8ID5e7;|sPUX%Y-> z6t|=6<5jz5kCKAZCpU?%GR_6I*dB};ISCkrmy`T>)^m)5p}w_RU!8u~Sl+#)whPXw zt%`vd806vM?NrMr0TVuTc)(xnvCdjKi@nU&@^gMqnwdVXugBB5wZ*6<1D5MSAhS^^ zZ6G=i@f{I;97ZY%f*`0)=~jd_dQ7M5qLwT*+He-=ut!Nj?mnRU%y>23#LBUWA zsHaeAspyxs_NMcB*5cFI)i^9zNK4hY6IO6%cPGV#Dn{S-(@?q&ync#6q%19!-y&b3 zj(QVk?vE~}dlVSVkk$sH4_YL}OB*uKBk(&eW-nk&iSE%+L`lt8*1JPl0p7aThcPb3 zZz)cOxq#QMThKc%DtE2s@G!F=;;dotI=thLGNZg23hF(+4ya% z3>2D&rU|^Ao_&3t9tVjTuq?o&}LKS(GVXCAN{C)DB_HLO#{{*#Vn=hv@x$` z*J`tuW3}FwI{60haEM}wbq)RG9|j2wJ-1|DgVJ0E*P+0Sls?G7K?i#sW%Q@JqXAxh zwM}X-)ifknmDT9rH)LX@di-U#sAHMTj?kPM$kRih4zz*a`qHwJo;0vmM||4!?f@sI zN|*B?Pp29UK3C6Jb##}1VipU3G)v;$?)5{OuRx-0lp>I|?5t*X*S$1d1X@woWxl%A-e<;|TtH+TuuH}EnVOtBw z{Tg5CK(FnNTNh%q?*O2?eK724tt+oqE8+}4s@3hra71az6`NsRs>eCrqF?dp#3{lM!p1LEnOQd%ur z#;oBchZnv4+_kygOk@6ngn#k3-!F4BHfXTJ`?k%<0ZR5tiP12GD1pp-2}=$wyEde(&=X};$2+Z zY@+XNFxl-UyMcV#H+5L=+bB-fojR2NN0G1OBDe$|3LR^JnkLmX<~ZtXeYv0a!pilc z0(vj73TajcE-;GIYx_IPVkjI5k}+^Gs?oHox6N@;@{{3RY0`rEF(!AyET~BX+i5%9 z4h>Jw0VN+TH$`1xg*!7*{m%I`?osZbxj3&*J0a!V9CO5_S}IF6w|WwAt7Zc=xp6zR zbg9wf=~CKY)I=j&@s>dvdzWA&bc2pOkRT&XwJR1q`D zI?(tkEWMf7&%(xw5!mWr02Kg6?@hr>`6g&0++irw17eD}3~=9p`D1T9${VzI3QAV;;AiouTJPI;xzF6W`>}obSPVL$OUygzA`j|@ zWT(_i<2Z1)9u7aD`?VZ= zP^sbq0Rxh|hc~~)t3kkk#zy6?qoh%)5HG8pV*ow-j&B=>$))Z3(j?diNLq!S8b95H zL|A@+2mGUt9LVINKQ`LrAM|8Z_Qpr5Vdp!syO0YSq32PauY)%Oyom+VflAe?W7}$U z=)1XHJEcG%Uj~&N$8Z)?AA;?dn==$4#es z*-IfAyGDK1B7ahjzexf z93lM)fn8m=p+57N3o`OiRGtS+qs#_?NeJ-{<{%U6cSo2wbNJ%L;^f5#DM`G3t1DX- z3Kq_tX}14(hq;B;t~h&_$t# z@_qaed4T9(e!`K2FxhTSjdbX#s(guUZPwu6<^&kFqBekz{m~ZOn3|$1%)$*FsOvIm z(WpAJIyBka-Dp%TP`Y<%?o0_2eR5PnHabp9yuU)vD_~xL?M)oWU)kXHAT2TsZ!D|o z@Ka}HV`OD+(Psd9E+4G#HsGBd8frJOL6yRRy?Z?wb!cLC^nR-^-i;?9k47GcfE~*7 z!|T%-ahd%I0+ls-SiFtOFxzU(Kr=CY zV&Ez3qpA zqf{=&Z^44Bd9jaDC|TvI&0LK40Z}x%iCYz2b7qyx!TBU71r#Yr3~n$p1@PgR&I=QB zKa3>Qk5TDv>#6$5Yp~jIl<*qTGFf$zwaNQUu?mD5oVmW9i4$U6`O0f4=_t6+NtAib zZ!Uko3C!2#qYuZ$l_Ul=(AKymT?WmTW8h*4LyQf6){$~p+)^K+_K=WK9>Fy0Bk1cI;-rEg2RX!@x7AaJbHf2>WG`}LNfMLz zYiN3kw$n|Ig33#iu-a2s=LfX%j~_ZJlyrVdP#2<5m!>Ayt>Kr05&%#)UNiH9c#Ymr zzmZ4t{=kq$X2m7_%J@$8MrkQfHmK*1UDp zy@G>6#09)+THWQ4*wa%pQZAJ>so*s|NQWAXjM8AZqNU*A`VFJ0PK6{93PF`|)#h;|$>{F0nz4CleQ*bo9C zuf+@EB#us>HQ9&d8lCiDo#-kNN0N|8O(^Z3D``DrJ8aqW`H<_RpBQf7!M2Kko``p8UW9 z#~8k`KL-M;*d+=XsN7ZD3oy&yMG#zwS^^_o8%a|?`)QaJE`H%&h&Rs?_Iu?91HO_K zbw2ziCIfNuUhm9NMd2;PWG&{-`!nc@VLa2v*XtYF&5jw^2NK_>&+u8t^zE)Ah6u>V z5rB_S!d<12zdU1VKuj9ny8{&>1T#m1diKUk4XiC&NfmBDuuTGpMEtYs4w*}>8x?8D zD2S43ISBzfDdrK7#u2WZEkQy`4ahqxDUvTl)n^pM1Bdi018Oq7Uj&IW{#CS?ikcgI zCNZms?0d=q1=0b7pM*6rSj?a`NrK$z(yEb^i?;|RXc$>uEq@VZzkDvy*qtS3z*IL$ z%pHU7hv}ikJ?f&^{9b#zCqj37`!Jc&!@%6GHe{Oy^G`6s%%j%_|mH#kqjT<-BelIj40nyNB$k1x{1Op2d1K=G91n$~yVp~c= zFH1l+EW>xnWufXlIPvh@n~&-K6P|PN18&#~fiKi(?9vQH~5!;1sZxH zNm)e21nze1n&}~0Y6>Ma0Z+EObmSfL;|-vdQ4^aqWjGuUABMGVB@1iI!onIm8|#tw zw!ICIr#AN4l*h1$pO=q@Z$^}-_p>yycRW$SPF|apyW^$W^3v4hC0?$Ho0*l9jlrp? zn~}<_4(QZVswt88J6u`WXR({%(8(Gf2NxgUJq|wZrFHe^?T@b(v8oIN=nube84&`q zg|&>OpK5n!THxd*wojP30~dTB&d+}?`uB4O3&-VB^hT3SP&9X~t6M0o_oa*1X@zw&lk=x)%kS(DV9^(N(Vr<& zLwUIEtnu!vsUn*FDNx%MBHs=d&x?zt1Fzpd*mF7#MGefP3eI z@3Eh)4I}nA)My+o*;g}$hn||o-M)pBl~xDn%ycB25O@J5yFm{}Uv8!*MScQ)Qkhw=LEnR1-a53VX zGN-xS>`ro?FcU z;k%e3Cxke7_|R~v`yJ{y@MZ|n_T06tVTO(z=&t17iq8;}_AphBpm~A_c(y#12Px># zMb*{V7J=)!@S(1S1l@rESI^Iw^}OE$0JnR>e!J0Qz&s~FwVr$eOo6%bQA05q^R)(tA6RJ14&yq-HVyi@RdEC}@vM7| zge;6G9EqjZ1O$);Co~HLa^egCU@ji+K#Ocj2+`js_-+prhqOY2VJd|15r+dH02XEM zk)}WrF^KpQ4l5vr0L8#JCTjl%$SDx24>D-@*91QzC=&8PJxG~)P#(ktz`!QU#>Agt zsROBG&BW}yMN{L#J>wm7ANu$Z=jg*EE>==Wy6Aycnho4X&OK8Z8fm_=#RJr1Xoq`1 zsDUZO;D#5EZ=-d2;sFxiSio`KIG6xgfFz1VdRuUj3F=V!=_yq~Y&q4tx{jz=X(a{o zulXa>V#-}m9QUt!z_3Yl>V?%;=%I17j7i$6Dq6J2RqMLOo#7=kq<|MOryo8xMS?Xy zsDESh6D+VG97Y(It%@F`W~^80Z1VD*yL!oog$cJ*oh?5uRk$38u39i5LLpyq_|B?# zDpk<4YjAnJe$VRR#>~zl{!)D3Cm@c3frp2Cw>@Lf`+TWX#f+^Z6q?)#Gd|T8&U%@; z5;j7vF8kiSLdic5NCcl)Z6-Iow>5>`RK#h)L$dr<|x&vJz`q4xH0 z@xAeGmRDNVAw?;wACMK+5c>M5qjGkQ{c+>N)yC

xuX0a))0GfwhfICEc_<*X1@- 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 [http://www.motivity.ca] +%%% @end +%%% +%%% Copyright (c) 2004, 2005, Motivity Telecom +%%% +%%% All rights reserved. +%%% +%%% Redistribution and use in source and binary forms, with or without +%%% modification, are permitted provided that the following conditions +%%% are met: +%%% +%%% - Redistributions of source code must retain the above copyright +%%% notice, this list of conditions and the following disclaimer. +%%% - Redistributions in binary form must reproduce the above copyright +%%% notice, this list of conditions and the following disclaimer in +%%% the documentation and/or other materials provided with the +%%% distribution. +%%% - Neither the name of Motivity Telecom nor the names of its +%%% contributors may be used to endorse or promote products derived +%%% from this software without specific prior written permission. +%%% +%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +%%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +%%% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +%%% OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +%%% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +%%% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +%%% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +%%% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +%%% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +%%% +%%%--------------------------------------------------------------------- +%%% +%%% ITU-T recommendation Q.711 Functional Decsription of +%%% the Signalling Connection Control Part describes the +%%% primitives and their parameters used in the N-Service +%%% interface. Each primitive has a record defined here +%%% containing it's parameters. Modules using this service +%%% utilize these records to format messages: +%%% +%%% {'N', 'N-CONNECT', Connect} when is_record(Connect, 'N-CONNECT') +%%% + +%% reference: Table 2/Q.711 - Parameters of the primitive N-CONNECT +-record('N-CONNECT', {calledAddress, callingAddress, respondAddress, + expeditedData, qos, userData, connectionID, importance}). + +%% reference: Table 3/Q.711 - Parameters of the primitive N-DATA +-record('N-DATA', {userData, connectionID, importance}). + +%% reference: Table 4/Q.711 - Parameters of the primitive N-EXPEDITED-DATA +-record('N-EXPEDITED-DATA', {userData, connectionID}). + +%% reference: Table 5/Q.711 - Parameters of the primitive N-RESET +-record('N-RESET', {originator, reason, connectionID}). + +%% reference: Table 6/Q.711 - Parameters of the primitive N-DISCONNECT +-record('N-DISCONNECT', {originator, respondAddress, reason, userData, + connectionID, importance}). + +%% reference: Table 8/Q.711 - Parameters of the primitive N-INFORM +-record('N-INFORM', {reason, connectionID, qos}). + +%% reference: Table 12/Q.711 - Parameters of the primitive N-UNITDATA +-record('N-UNITDATA', {calledAddress, callingAddress, sequenceControl, + returnOption, importance, userData}). + +%% reference: Table 13/Q.711 - Parameters of the primitive N-NOTICE +-record('N-NOTICE', {calledAddress, callingAddress, reason, userData, + importance}). + +%% reference: Table 15/Q.711 - Parameters of the primitive N-COORD +-record('N-COORD', {affectedSubsystem, multiplicity}). + +%% reference: Table 16/Q.711 - Parameters of the primitive N-STATE +-record('N-STATE', {affectedSubsystem, userStatus, multiplicity}). + +%% reference: Table 17/Q.711 - Parameters of the primitive N-PCSTATE +-record('N-PCSTATE', {affectedSignallingPoint, signallingPointStatus, + remoteSCCPStatus, restrictedImportanceLevel}). + diff --git a/SCCP/src/ITU/README b/SCCP/src/ITU/README new file mode 100644 index 0000000..6ec99cc --- /dev/null +++ b/SCCP/src/ITU/README @@ -0,0 +1,15 @@ + +This directory contains the erlang source modules for an implementation +of the ITU-T version of the Signalling Connection Control Part (SCCP). +See ITU-T recommendations Q.711-Q.715 for the specification this +implementation is derived from. + +The basic structure of the SCCP appears in Figure 1/Q.714 - SCCP overview. +It is divided into four functional blocks (ref: Q.714 clause 1.4): + + SCCP connection-oriented control (SCOC) + SCCP connectionless control (SCLC) + SCCP management (SCMG) + SCCP routing control (SCRC) + + diff --git a/SCCP/src/NMS/Makefile b/SCCP/src/NMS/Makefile new file mode 100644 index 0000000..9a19a0c --- /dev/null +++ b/SCCP/src/NMS/Makefile @@ -0,0 +1,50 @@ + +EBIN = ../../ebin +DOC = ../../doc/html + +NMSINC = ../../../nms_erldrv/include + +INCLUDES = $(NMSINC) + +ERLC = erlc +ERL = erl +ERLCFLAGS = -W -v -o $(EBIN) -I $(INCLUDES) +DEBUGFLAGS = +debug_info + +$(EBIN)/%.beam:%.erl + ${ERLC} $(ERLCFLAGS) $< + +$(DOC)/%.html:%.erl + ${ERL} -noshell -run edoc_run file '"$<"' '[{dir, "$(DOC)"}]' -s init stop + +BEAMS = $(EBIN)/sccp.beam + +DOCS = $(DOC)/sccp.html + +$(EBIN)/sccp.app: $(EBIN)/sccp.app.src + sed -e "s;%VERSION%;${VERSION};" $(EBIN)/sccp.app.src > $(EBIN)/sccp.app + +all: $(EBIN)/sccp.app beams docs + +.PHONY: beams +beams: $(BEAMS) + +.PHONY: docs +docs: $(DOCS) + +.PHONY: install +install: all + install -d $(ERL_TOP)/lib/sccp-${VERSION}/ebin + install -f $(ERL_TOP)/lib/sccp-${VERSION}/ebin $(EBIN)/sccp.app + install -f $(ERL_TOP)/lib/sccp-${VERSION}/ebin $(BEAMS) + install -d $(ERL_TOP)/lib/sccp-${VERSION}/doc/html + install -f $(ERL_TOP)/lib/sccp-${VERSION}/doc/html $(DOCS) + +.PHONY: clean +clean: + rm -rf $(EBIN)/sccp.app + rm -rf $(BEAMS) + rm -rf $(DOCS) + +sccp.erl: $(NMSINC)/nms_sccp.hrl + diff --git a/SCCP/src/NMS/sccp.erl b/SCCP/src/NMS/sccp.erl new file mode 100644 index 0000000..39cda97 --- /dev/null +++ b/SCCP/src/NMS/sccp.erl @@ -0,0 +1,863 @@ +%%% $Id: sccp.erl,v 1.26 2007/08/15 11:02:50 vances Exp $ +%%%--------------------------------------------------------------------- +%%% @copyright 2001-2005 Motivity Telecom +%%% @author Vance Shipley [http://www.motivity.ca] +%%% @end +%%% +%%% Copyright (c) 2001-2005, Motivity Telecom +%%% +%%% All rights reserved. +%%% +%%% Redistribution and use in source and binary forms, with or without +%%% modification, are permitted provided that the following conditions +%%% are met: +%%% +%%% - Redistributions of source code must retain the above copyright +%%% notice, this list of conditions and the following disclaimer. +%%% - Redistributions in binary form must reproduce the above copyright +%%% notice, this list of conditions and the following disclaimer in +%%% the documentation and/or other materials provided with the +%%% distribution. +%%% - Neither the name of Motivity Telecom nor the names of its +%%% contributors may be used to endorse or promote products derived +%%% from this software without specific prior written permission. +%%% +%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +%%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +%%% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +%%% OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +%%% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +%%% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +%%% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +%%% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +%%% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +%%% +%%%--------------------------------------------------------------------- +%%% @doc Signaling Connection Control Part (SCCP) application using NMS. +%%%

Implements SCCP service access points (SAP) on top of the +%%% nms application.

+%%% +%%% @see //nms +%%% @reference +%%%
+%%% NMS SCCP Developer's Reference Manual +%%% @reference ITU-T Q.771-Q.774 +%%% @reference ANSI T1.112 + +-module(sccp). +-copyright('Copyright (c) 2001-2007 Motivity Telecom Inc.'). +-author('vances@motivity.ca'). +-vsn('$Revision: 1.26 $'). + +-include("nms_sccp.hrl"). + +-behaviour(gen_server). + +%% call backs needed for gen_server behaviour +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +%% our published API functions +-export([start_link/2, start_link/3, start_link/7, stop/1]). +-export([address/1, address_itu/1, address_ansi/1, bcd_digits/1, btoi/1]). + +-record(state, {user, board, entityid, serviceuserid, sap, ssn, + queue, context, object, port}). + +%% TODO: find a way to have autoconf define these +-define(SW_INT, 1). +-define(SW_ANSI, 2). +-define(ENC_UNKNOWN, 0). +-define(ENC_BCD_ODD, 1). +-define(ENC_BCD_EVEN, 2). + +%%---------------------------------------------------------------------- +%% The sccp exported API (not the service primitives) +%%---------------------------------------------------------------------- + +%% @spec (USAP::pid(), SSN::integer()) -> {ok, NSAP} | {error, Reason} +%% NSAP = pid() +%% Reason = term() +%% +%% @doc Starts an sccp server. +%%

USAP is the pid of the SCCP-User.

+%%

SSN is the SCCP subsystem number for this SAP.

+%%

NSAP is a pid which the SCCP-User will use as the +%% service access point for the SCCP-Service.

+%% +start_link(User, SSN) -> + start_link(User, 0, SSN). +%% +%% @spec (USAP::pid(), SpID::integer(), SSN::integer()) -> {ok, NSAP} | {error, Reason} +%% NSAP = pid() +%% Reason = term() +%% +%% @doc Starts an sccp server. +%%

USAP is the pid of the SCCP-User.

+%%

SpID NMS SCCP service access point ID on which to bind. +%% This is SCCP SAP number which is defined in the TX board SCCP +%% configuration.

+%%

SSN is the SCCP subsystem number for this SAP.

+%%

NSAP is a pid which the SCCP-User will use as the +%% service access point for the SCCP-Service.

+%% +start_link(User, SpID, SSN) -> + start_link(User, 1, 16#20, 0, SpID, SSN, 128). +%% +%% @spec (USAP::pid(), Board::integer(), EntityID::integer(), SuID::integer(), +%% SpID::integer(), SSN::integer(), PoolSize::integer()) -> {ok, NSAP} | {error, Reason} +%% NSAP = pid() +%% Reason = term() +%% +%% @doc Starts an sccp server. +%%

USAP is the pid of the SCCP-User.

+%%

Board is the number of the TX board for this SAP.

+%%

EntityID is the Entity ID which identifies this application +%% to the NMS TX board.

+%%

SuID NMS SCCP calling application service user ID. +%% This is User SAP number which is defined in the TX board SCCP +%% configuration.

+%%

SpID NMS SCCP service access point ID on which to bind. +%% This is SCCP SAP number which is defined in the TX board SCCP +%% configuration.

+%%

SSN is the SCCP subsystem number for this SAP.

+%%

NSAP is a pid which the SCCP-User will use as the +%% service access point for the SCCP-Service.

+%%

PoolSize is the number of messages allowed to +%% be queued to the TX board.

+%% +start_link(User, Board, EntityID, SuID, SpID, SSN, PoolSize) -> + Ourname = list_to_atom("sccp_ssn" ++ integer_to_list(SSN)), + gen_server:start_link({local, Ourname}, ?MODULE, + [User, Board, EntityID, SuID, SpID, SSN, PoolSize], []). + +%% @spec (NSAP) -> ok +%% NSAP = pid() +%% +%% @doc Stop an sccp server. +%%

Closes an SCCP service access point (SAP).

+%%

NSAP is a pid returned from a previous call to +%% start_link/2,3,7.

+%% +stop(NSAP) -> + gen_server:call(NSAP, stop). + +%% @type party(). SCCP called/calling party address. +%%

A binary() or an #'SccpAddr'{} record.

+ +%% @spec (SccpAddress::party()) -> SccpAddress +%% SccpAddress = party() +%% +%% @doc Encodes/decodes SCCP called/calling party addresses. +%%

Naively, but convienently, assumes national addresses +%% are in ANSI format and international addresses are in +%% ITU format when decoding.

+%% @end +%% +% International Indicator +address(<<0:1, _:7, _Rest/binary>> = OrigBin) -> + address_itu(OrigBin); +% National Indicator +address(<<1:1, _:7, _Rest/binary>> = OrigBin) -> + address_ansi(OrigBin); +% encode ANSI address records +address(CP) when is_record(CP, 'SccpAddr'), CP#'SccpAddr'.swtype == ?SW_ANSI -> + address_ansi(CP); +% encode ITU address records +address(CP) when is_record(CP, 'SccpAddr'), CP#'SccpAddr'.swtype == ?SW_INT -> + address_itu(CP). + +%% @spec (SccpAddress::party()) -> SccpAddress +%% SccpAddress = party() +%% +%% @doc Encodes/decodes an ITU-T variant SCCP called/calling party address. +%%

Operates according to ITU-T Q.713 3.4.

+%% @end +%% +%% [note: ANSI reverse the order of the PC & SSN] +%% +address_itu(<>) -> + #'SccpAddr'{presind = 1, swtype = ?SW_INT, natintind = NatIntInd, + routingind = RoutingInd, gltitleind = GlobalTitleInd, + subsystemind = SubsystemInd, pointcodeind = PointCodeInd}; +address_itu(<>) -> + case PointCodeInd of + 1 -> + % ITU-T point codes are 14 bits (Q.713 clause 3.4.2.1) + <> = Addresses, + PointCode = (MSB bsl 8) bor LSB, + AddressWithPC = #'SccpAddr'{presind = 1, swtype = ?SW_INT, + natintind = NatIntInd, pointcodeind = 1, pointcode = PointCode}; + 0 -> + RestAddresses = Addresses, + AddressWithPC = #'SccpAddr'{presind = 1, swtype = ?SW_INT, + natintind = NatIntInd, pointcodeind = 0} + end, + case SubsystemInd of + 1 -> + <> = RestAddresses, + AddressWithSSN = AddressWithPC#'SccpAddr'{subsystemind = 1, + subsystem = SubSystemNumber}; + 0 -> + MoreAddresses = RestAddresses, + AddressWithSSN = AddressWithPC#'SccpAddr'{subsystemind = 0} + end, + case GlobalTitleInd of + % no global title included + 2#0000 -> + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd}; + + % global title includes nature of address indicator only + 2#0001 -> + <> = MoreAddresses, + case OddEven of + 0 -> Encoding = ?ENC_BCD_EVEN; + 1 -> Encoding = ?ENC_BCD_ODD + end, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd, encoding = Encoding, + nataddrind = NatureOfAddressInd, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + + % global title includes translation type only + 2#0010 -> + <> = MoreAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltranstype = TranslationType, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + + % global title includes translation type, numbering plan + % and encoding scheme + 2#0011 -> + <> = MoreAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltranstype = TranslationType, numplan = NumberingPlan, + encoding = EncodingScheme, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + + % global title includes translation type, numbering plan, + % encoding scheme and nature of address indicator + 2#0100 -> + <> = MoreAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd, gltranstype = TranslationType, + numplan = NumberingPlan, encoding = EncodingScheme, + nataddrind = NatureOfAddressInd, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + % GlobalTitleInd 2#0101 to 2#0111 spare international + % 2#1000 to 2#1110 spare national + % 2#1111 reserved for extension + _ -> + <> = MoreAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithSSN#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen} + end, + AddressWithGT#'SccpAddr'{routingind = RoutingInd}; +address_itu(CP) when is_record(CP, 'SccpAddr') -> + Indicators = <<(CP#'SccpAddr'.natintind):1, + (CP#'SccpAddr'.routingind):1, + (CP#'SccpAddr'.gltitleind):4, + (CP#'SccpAddr'.subsystemind):1, + (CP#'SccpAddr'.pointcodeind):1>>, + case CP#'SccpAddr'.pointcodeind of + 0 -> + BinAfterPC = Indicators; + 1 -> + <<_:18, MSB:6, LSB:8>> = CP#'SccpAddr'.pointcode, + BinAfterPC = <> + end, + case CP#'SccpAddr'.subsystemind of + 0 -> + BinAfterSSN = BinAfterPC; + 1 -> + BinAfterSSN = <> + end, + GTLen = CP#'SccpAddr'.gltitlelen, + <> = CP#'SccpAddr'.gltitle, + case CP#'SccpAddr'.gltitleind of + %% no global title included + 2#0000 -> + BinAfterSSN; + %% global title includes nature of address indicator only + 2#0001 -> + case (CP#'SccpAddr'.encoding) of + %% BCD odd number of digits + 16#01 -> + OddEven = 1; + %% BCD even number of digits + 16#02 -> + OddEven = 0 + end, + <>; + %% global title includes translation type only + 2#0010 -> + <>; + %% global title includes translation type, numbering plan + %% and encoding scheme + 2#0011 -> + <>; + %% global title includes translation type, numbering plan, + %% encoding scheme and nature of address indicator + 2#0100 -> + <>; + %% spare/reserved + _ -> + <> + end. + + +%% @spec (SccpAddress::party()) -> SccpAddress +%% SccpAddress = party() +%% +%% @doc Encodes/decodes an ANSI variant SCCP called/calling party address. +%%

Operates according to ANSI T1.112.3.

+%% @end +%% +%% [note: ANSI reverse the order of the PC & SSN] +%% +address_ansi(<>) -> + #'SccpAddr'{presind = 1, swtype = ?SW_ANSI, natintind = NatIntInd, + routingind = RoutingInd, pointcodeind = PointCodeInd, + subsystemind = SubsystemInd, gltitleind = GlobalTitleInd}; +address_ansi(<>) -> + case SubsystemInd of + 1 -> + <> = Addresses, + AddressWithSSN = #'SccpAddr'{presind = 1, swtype = ?SW_ANSI, + natintind = NatIntInd, subsystemind = 1, subsystem = SubSystemNumber}; + 0 -> + MoreAddresses = Addresses, + AddressWithSSN = #'SccpAddr'{presind = 1, swtype = ?SW_ANSI, + natintind = NatIntInd, subsystemind = 0} + end, + case PointCodeInd of + 1 -> + % ANSI point codes are three octets with the first octet + % containing the network cluster member and the last + % containing the network identifier + <> = MoreAddresses, + PointCode = (Network bsl 16) bor (Cluster bsl 8) bor Member, + AddressWithPC = AddressWithSSN#'SccpAddr'{pointcodeind = 1, + pointcode = PointCode}; + 0 -> + RestAddresses = MoreAddresses, + AddressWithPC = AddressWithSSN#'SccpAddr'{pointcodeind = 0} + end, + case GlobalTitleInd of + % no global title included + 2#0000 -> + AddressWithGT = AddressWithPC#'SccpAddr'{ + gltitleind = GlobalTitleInd}; + % global title includes translation type, numbering plan + % and encoding scheme (ITU codes this format as 2#0011) + 2#0001 -> + <> = RestAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithPC#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltranstype = TranslationType, numplan = NumberingPlan, + encoding = EncodingScheme, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + % global title includes translation type only + 2#0010 -> + <> = RestAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithPC#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltranstype = TranslationType, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen}; + % GlobalTitleInd 2#0011 to 2#0100 not assigned for US networks + % GlobalTitleInd 2#0101 to 2#0111 spare international + % 2#1000 to 2#1110 spare national + % 2#1111 reserved for extension + _ -> + <> = RestAddresses, + GlobalTitleLen = size(GlobalTitle), + GlobalTitleRestSize = (?MAX_GLT_SZ - GlobalTitleLen), + AddressWithGT = AddressWithPC#'SccpAddr'{ + gltitleind = GlobalTitleInd, + gltitle = <>/binary>>, + gltitlelen = GlobalTitleLen} + end, + AddressWithGT#'SccpAddr'{routingind = RoutingInd}; +address_ansi(CP) when is_record(CP, 'SccpAddr') -> + Indicators = <<(CP#'SccpAddr'.natintind):1, + (CP#'SccpAddr'.routingind):1, + (CP#'SccpAddr'.gltitleind):4, + (CP#'SccpAddr'.pointcodeind):1, + (CP#'SccpAddr'.subsystemind):1>>, + case CP#'SccpAddr'.subsystemind of + 0 -> + BinAfterSSN = Indicators; + 1 -> + BinAfterSSN = <> + end, + case CP#'SccpAddr'.pointcodeind of + 0 -> + BinAfterPC = BinAfterSSN; + 1 -> + Member = 16#FF band CP#'SccpAddr'.pointcode, + Cluster = 16#FF band (CP#'SccpAddr'.pointcode bsr 8), + Network = 16#FF band (CP#'SccpAddr'.pointcode bsr 16), + BinAfterPC = <> + end, + GTLen = CP#'SccpAddr'.gltitlelen, + <> = CP#'SccpAddr'.gltitle, + case CP#'SccpAddr'.gltitleind of + % no global title + 2#0000 -> + BinAfterPC; + % global title includes translation type, + % numbering plan and encoding scheme + 2#0001 -> + <>; + % global title includes translation type + 2#0010 -> + <>; + % spare/reserved + _ -> + <> + end. + + +%% @type protoclass(). SCCP protocol class. +%%

An #'SccpProtoClass'{} record.

+%% @type importance(). SCCP importance. +%%

An #'SccpImportance'{} record.

+ +%% @spec (ConnectionOriented, QosParams) -> {ProtoClass, Importance} +%% ProtoClass = protoclass() +%% Importance = importance() +%% +%% @doc Creates the records required for the NMS API out of the +%% qos parameter set in the service primitive. +%% +qos_parameters(ConnectionOriented, {SequenceControl, ReturnOption, + MessagePriority}) -> + if + not ConnectionOriented and not SequenceControl -> Class = 0; + not ConnectionOriented and SequenceControl -> Class = 1; + ConnectionOriented and not SequenceControl -> Class = 2; + ConnectionOriented and SequenceControl -> Class = 3 + end, + case ReturnOption of + false -> MessageHandling = 0; + true -> MessageHandling = 8 + end, + ProtoClass = #'SccpProtoClass'{classind = Class, + msghandling = MessageHandling}, + case MessagePriority of + none -> + Importance = #'SccpImportance'{}; + Priority -> + Importance = #'SccpImportance'{presind = 1, impvalue = Priority} + end, + {ProtoClass, Importance}. + +%% @spec (BCDDigits) -> Digits +%% BCDDigits = [integer()] +%% Digits = [char()] +%% +%% @doc Decode BCD encoded digit string. +%%

BCD encoding uses 4 bits for each digit, packing two digits +%% into each octet.

+%%

Returns a character string representation of the digits.

+%% +bcd_digits(BCDDigits) when is_binary(BCDDigits) -> + bcd_digits(BCDDigits, []); +bcd_digits(BCDDigits) when is_list(BCDDigits) -> + bcd_digits(list_to_binary(BCDDigits), []). +bcd_digits(<<>>, Result) -> Result; +bcd_digits(<>, Acc) -> + bcd_digits(Rest, Acc ++ integer_to_list(First) ++ integer_to_list(Second)). + +%% @spec (BCDDigits) -> integer() +%% BCDDigits = [integer()] +%% +%% @doc Decode BCD encoded digit string. +%%

BCD encoding uses 4 bits for each digit, packing two digits +%% into each octet.

+%%

Returns an integer representation of the digits.

+%% +btoi(BCDDigits) when is_list(BCDDigits) -> + list_to_integer(bcd_digits(BCDDigits)). + + +%%---------------------------------------------------------------------- +%% The gen_server call backs +%%---------------------------------------------------------------------- + +%% @private +%% +%% @spec (Args) -> {ok, State} +%% +%% @doc Initialize the sccp server. +%%

This callback is caled by the new process in response to +%% the start_link/2,3,7 functions.

+%% +init([User, Board, EntityID, ServiceUserID, SAP, SSN, Poolsize]) -> + Queue = na:ctaCreateQueue(), + Context = na:ctaCreateContext(Queue, SSN, []), + Service = "sccp", + ServiceManager = "sccpmgr", + ServiceName = {Service, ServiceManager}, + ServiceAddress = 0, + Arg = "", + Args = [Board, 0, EntityID, 0, SAP, ServiceUserID, SSN, 0, Poolsize], + ServiceArgs = {Arg, Args}, + MVIPAddress = {0,0,0,0,0}, + ServiceDecription = {ServiceName, ServiceAddress, ServiceArgs, MVIPAddress}, + Object = na:ctaOpenServices(Queue, Context, [ServiceDecription]), + State = #state{user = User, board = Board, entityid = EntityID, + serviceuserid = ServiceUserID, sap = SAP, ssn = SSN, + queue = Queue, context = Context, object = Object}, + % load the dynamicly linked device driver + PrivDir = code:priv_dir(nms), + LibDir = filename:join([PrivDir, "lib"]), + Name = nms_sccp_drv, + case erl_ddll:try_load(LibDir, Name, [{monitor, pending_driver}]) of + {error, permanent} -> + init1(State); + {error, ErrorDescriptor} -> + {stop, erl_ddll:format_error(ErrorDescriptor)}; + {ok, Loaded} when Loaded == loaded; Loaded == already_loaded -> + init1(State); + {ok, pending_driver, Ref} -> + receive + {'UP', Ref, driver, Name, loaded} -> + init1(State); + {'UP', Ref, driver, Name, permanent} -> + init1(State); + {'DOWN', Ref, driver, Name, load_cancelled} -> + {stop, load_cancelled}; + {'DOWN', Ref, driver, Name, {load_failure, Failure}} -> + {stop, erl_ddll:format_error(Failure)} + after 10 -> + {stop, timeout} + end + end. +init1(State) -> + Port = open_port({spawn, 'nms_sccp_drv'}, [stream, binary]), + process_flag(trap_exit, true), + {ok, State#state{port = Port}}. + +%% @private +%% +%% @spec (Request, From, State) -> {stop, shutdown, State} +%% +%% @doc Handle requests sent with gen_server:call/2,3. +%% @end +%% +% shutdown the sccp server +handle_call(stop, _From, State) -> + {stop, shutdown, State}. + +%% @private +%% +%% @spec (Request, State) -> {noreply, State} +%% +%% @doc Handle requests sent with gen_server:cast/2. +%% @end +% +% service primitives received from the SCCP-Users +% +% Connection-Oriented Primitives +handle_cast({'N', 'CONNECT', request, {_CalledAddress, _CallingAddress, + _RespondingAddress, _ExpeditedDataSelection, + _QualityOfServiceParameterSet, _UserData, _Importance, + _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'CONNECT', response, {_CalledAddress, _CallingAddress, + _RespondingAddress, _ExpeditedDataSelection, + _QualityOfServiceParameterSet, _UserData, _Importance, + _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'DATA', request, {_Importance, _UserData, + _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'EXPEDITEDDATA', request , {_UserData, _ConnectionID}}, + State) -> + {noreply, State}; +handle_cast({'N', 'DISCONNECT', request, {_Originator, _Reason, _UserData, + _RespondingAddress, _Importance, _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'RESET', request, {_Originator, _Reason, + _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'RESET', response, {_Originator, _Reason, + _ConnectionID}}, State) -> + {noreply, State}; +handle_cast({'N', 'INFORM', request, {_Reason, _ConnectionID, + _QualityOfServiceParameterSet}}, State) -> + {noreply, State}; +% Connectionless Primitives +handle_cast({'N', 'UNITDATA', request, {CalledAddress, CallingAddess, + QualityOfServiceParameterSet, UserData}}, State) -> + {ProtoClass, Importance} = qos_parameters(false, + QualityOfServiceParameterSet), + Data = #'SccpData'{presind = 1, + data = UserData, datalen = size(UserData)}, + SCCPUDataRqst = nms_sccp:'SccpUdataRqst'(#'SccpUdataRqst'{ + protoclass = ProtoClass, + calledpty = address(CalledAddress), + callingpty = address(CallingAddess), + % TODO: what about end-of-sequence? (eos = 0) + importance = Importance, + data = Data}), + erlang:port_command(State#state.port, <>), + {noreply, State}; +% Management Primitives +handle_cast({'N', 'COORD', request, {_AffectedSubsystem, + _SubsystemMultiplicityIndicator}}, State) -> + {noreply, State}; +handle_cast({'N', 'COORD', response, {_AffectedSubsystem, + _SubsystemMultiplicityIndicator}}, State) -> + {noreply, State}; +handle_cast({'N', 'STATE', request, {_AffectedSubsystem, _UserStatus, + _SubsystemMultiplicityIndicator}}, State) -> + {noreply, State}. + + +%% @private +%% +%% @spec (Info, State) -> {noreply, State} | {stop, Reason, State} +%% +%% @doc Handle system events and messages. +%% @end +%% +% +% service primitives received from the NMS SCCP service +% +handle_info({{sccpEventData, _Context, _Port, _UserId}, {SccpRcvInfoBlk, SccpAllMsgs}}, State) -> + I = nms_sccp:'SccpRcvInfoBlk'(SccpRcvInfoBlk), + MoreInfo = {I#'SccpRcvInfoBlk'.board, I#'SccpRcvInfoBlk'.evnttype, + I#'SccpRcvInfoBlk'.suid, I#'SccpRcvInfoBlk'.connid, + I#'SccpRcvInfoBlk'.opc}, + forward_primitive(State#state.user, I#'SccpRcvInfoBlk'.indtype, + MoreInfo, SccpAllMsgs), + {noreply, State}; +% trapped exit signals +handle_info({'EXIT', Port, Reason} = R, State) when is_port(Port) -> + error_logger:error_report([Port, Reason, "Port terminated"]), + {stop, R, State}; +handle_info({'EXIT', Pid, Reason} = R, State) when is_pid(Pid) -> + error_logger:error_report([Pid, Reason, "Linked Pid terminated"]), + {stop, R, State}. + +%% @private +%% +%% @spec (Reason, State) -> ok +%% +%% @doc Called when the system is being shutdown. +%% @end +%% +% someone wants us to shutdown and cleanup +terminate(_Reason, _State) -> ok. + +%% @private +%% +%% @spec (OldVsn, State, Extra) -> {ok, NewState} +%% +%% @doc Called during a release upgarde. +%% +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%---------------------------------------------------------------------- +%% internal functions +%%---------------------------------------------------------------------- + +%% @private +%% +%% @spec (User, Name, Params, SccpAllMsgs) -> ok +%% +%% @doc Handles incoming primitives from the NMS driver and sends standardized +%% SCCP-service primitives to the service user. +%% @end +%% +%% TODO: all parameters should be encoded in standardized format +%% +forward_primitive(User, ?SCCPUDATIND, + {_Board, _EvntType, _Suid, _Connid, OPC}, SccpAllMsgs) -> + UD = nms_sccp:'SccpUdataRqst'(SccpAllMsgs), + CL = nms_sccp:'SccpProtoClass'(UD#'SccpUdataRqst'.protoclass), + CD = nms_sccp:'SccpAddr'(UD#'SccpUdataRqst'.calledpty), + CG = nms_sccp:'SccpAddr'(UD#'SccpUdataRqst'.callingpty), + IM = nms_sccp:'SccpImportance'(UD#'SccpUdataRqst'.importance), + SD = nms_sccp:'SccpData'(UD#'SccpUdataRqst'.data), + % if there is no point code in the calling party address we + % insert the originating point code from the routing label + if + (CG#'SccpAddr'.presind == 0) -> + NewCG = #'SccpAddr'{presind = 1, + swtype = CD#'SccpAddr'.swtype, % cheating? + pointcodeind = 1, + pointcode = OPC}; + (CG#'SccpAddr'.presind == 1) + and (CG#'SccpAddr'.pointcodeind == 0) -> + NewCG = CG#'SccpAddr'{pointcodeind = 1, pointcode = OPC}; + (CG#'SccpAddr'.presind == 1) + and (CG#'SccpAddr'.pointcodeind == 1) -> + NewCG = CG + end, + CallingParty = address(NewCG), + CalledParty = address(CD), + case CL#'SccpProtoClass'.classind of + 0 -> SequenceControl = false; + 1 -> SequenceControl = true + end, + case CL#'SccpProtoClass'.msghandling of + 0 -> ReturnOption = false; + 8 -> ReturnOption = true + end, + case IM#'SccpImportance'.presind of + 0 -> Importance = none; + 1 -> Importance = IM#'SccpImportance'.impvalue + end, + PDULen = SD#'SccpData'.datalen, + case SD#'SccpData'.presind of + 1 -> <> = SD#'SccpData'.data; + 0 -> PDU = <<>> + end, + gen_server:cast(User, {'N', 'UNITDATA', indication, {CalledParty, + CallingParty, {SequenceControl, ReturnOption, Importance}, PDU}}); +forward_primitive(User, ?SCCPSTAIND, {_, EventType, _, _, _}, SccpAllMsgs) -> + UD = nms_sccp:'SccpUdataRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'NOTICE', indication, + {UD#'SccpUdataRqst'.calledpty, + UD#'SccpUdataRqst'.callingpty, UD#'SccpUdataRqst'.eos, + EventType, UD#'SccpUdataRqst'.importance, + UD#'SccpUdataRqst'.data}}); +forward_primitive(User, ?SCCPCOORDIND, _MoreInfo, SccpAllMsgs) -> + CO = nms_sccp:'SccpCoordRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'COORD', indication, + {CO#'SccpCoordRqst'.assn, CO#'SccpCoordRqst'.smi}}); +forward_primitive(User, ?SCCPCOORDCFM, _MoreInfo, SccpAllMsgs) -> + CO = nms_sccp:'SccpCoordRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'COORD', confirm, + {CO#'SccpCoordRqst'.assn, CO#'SccpCoordRqst'.smi}}); +forward_primitive(User, ?SCCPSTATEIND, _MoreInfo, SccpAllMsgs) -> + CO = nms_sccp:'SccpCoordRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'STATE', indication, + {CO#'SccpCoordRqst'.assn, CO#'SccpCoordRqst'.status, + CO#'SccpCoordRqst'.smi}}); +forward_primitive(User, ?SCCPPCSTIND, {_, _, _, _, Opc}, SccpAllMsgs) -> + CO = nms_sccp:'SccpCoordRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'PCSTATE', indication, + {Opc, CO#'SccpCoordRqst'.status, none, none}}); +forward_primitive(User, ?SCCPCONNIND, {_, _, _, Connid, _}, SccpAllMsgs) -> + CN = nms_sccp:'SccpConnRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'CONNECT', indication, + {CN#'SccpConnRqst'.calledpty, CN#'SccpConnRqst'.callingpty, + none, CN#'SccpConnRqst'.eds, none, CN#'SccpConnRqst'.data, + CN#'SccpConnRqst'.importance, Connid}}); +%forward_primitive(User, ?SCCPCONNCFM, {_, _, _, Connid, _}, SccpAllMsgs) -> +% CN = nms_sccp:'SccpConnRqst'(SccpAllMsgs), +% gen_server:cast(User, {'N', 'CONNECT', confirm, +% {CN#'SccpConnRqst'.calledpty, CN#'SccpConnRqst'.callingpty, +% none, CN#'SccpConnRqst'.eds, none, CN#'SccpConnRqst'.data, +% CN#'SccpConnRqst'.importance, Connid}}); +forward_primitive(User, ?SCCPDATIND, {_, _, _, Connid, _}, SccpAllMsgs) -> + DA = nms_sccp:'SccpDataRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'DATA', indication, + {none, DA#'SccpDataRqst'.data, Connid}}); +%forward_primitive(User, ?SCCPEDATIND, {_, _, _, Connid, _}, SccpAllMsgs) -> +% DA = nms_sccp:'SccpDataRqst'(SccpAllMsgs), +% gen_server:cast(User, {'N', 'EXPEDITEDDATA', indication, +% {none, DA#'SccpDataRqst'.data, Connid}}); +forward_primitive(User, ?SCCPRESETIND, {_, _, _, Connid, _}, SccpAllMsgs) -> + RS = nms_sccp:'SccpResetRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'RESET', indication, + {RS#'SccpResetRqst'.orig, RS#'SccpResetRqst'.cause, Connid}}); +forward_primitive(User, ?SCCPRESETCFM, {_, _, _, Connid, _}, SccpAllMsgs) -> + RS = nms_sccp:'SccpResetRqst'(SccpAllMsgs), + gen_server:cast(User, {'N', 'RESET', confirm, + {RS#'SccpResetRqst'.orig, RS#'SccpResetRqst'.cause, Connid}}); +forward_primitive(User, ?SCCPRELIND, {_, _, _, Connid, _}, SccpAllMsgs) -> + DC = nms_sccp:'SccpRelease'(SccpAllMsgs), + gen_server:cast(User, {'N', 'DISCONNECT', indication, + {DC#'SccpRelease'.orig, DC#'SccpRelease'.cause, + DC#'SccpRelease'.data, DC#'SccpRelease'.rsppty, + DC#'SccpRelease'.importance, Connid}}); +forward_primitive(_User, ?SCCPDACKIND, _MoreInfo, _SccpAllMsgs) -> + ok; +forward_primitive(_User, ?SCCPCONNAUDCFM, _MoreInfo, _SccpAllMsgs) -> + ok; +forward_primitive(_User, ?SCCPRUNSTATEIND, {_,?SPRS_STANDALONE,SuID,_,OPC}, + _SccpAllMsgs) -> + <<_, N, C, M>> = <>, + error_logger:info_msg("SCCP Point code ~w.~w.~w SuID ~w " + "run state is standalone~n", [N, M, C, SuID]), + ok; +forward_primitive(_User, ?SCCPRUNSTATEIND, {_,?SPRS_PRIMARY,SuID,_,OPC}, + _SccpAllMsgs) -> + <<_, N, C, M>> = <>, + error_logger:info_msg("SCCP Point code ~w.~w.~w SuID ~w " + "run state is primary~n", [N, M, C, SuID]), + ok; +forward_primitive(_User, ?SCCPRUNSTATEIND, {_,?SPRS_BACKUP,SuID,_,OPC}, + _SccpAllMsgs) -> + <<_, N, C, M>> = <>, + error_logger:info_msg("SCCP Point code ~w.~w.~w SuID ~w " + "run state is backup~n", [N, M, C, SuID]), + ok; +forward_primitive(_User, ?SCCPCONGIND, _MoreInfo, _SccpAllMsgs) -> + ok.