From d8f7a8bb6c0250ba10332888777ba38b66b398e4 Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Sat, 23 Jan 2021 00:02:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 29 ++++++ LICENSE | 191 +++++++++++++++++++++++++++++++++++++++ README.md | 9 ++ c_src/ePort/ePort.cpp | 170 ++++++++++++++++++++++++++++++++++ c_src/ePort/rebar.config | 7 ++ c_src/erlNpc | Bin 0 -> 26419 bytes c_src/erlNpc.cmd | 4 + rebar.config | 7 ++ src/ePort.app.src | 11 +++ src/ePort.erl | 64 +++++++++++++ src/ePort_app.erl | 18 ++++ src/ePort_sup.erl | 46 ++++++++++ 12 files changed, 556 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 c_src/ePort/ePort.cpp create mode 100644 c_src/ePort/rebar.config create mode 100644 c_src/erlNpc create mode 100644 c_src/erlNpc.cmd create mode 100644 rebar.config create mode 100644 src/ePort.app.src create mode 100644 src/ePort.erl create mode 100644 src/ePort_app.erl create mode 100644 src/ePort_sup.erl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ad44f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +.eunit +*.o +*.beam +*.plt +erl_crash.dump +.concrete/DEV_MODE + +# rebar 2.x +.rebar +rel/example_project +ebin/* +deps + +# rebar 3 +.rebar3 +_build/ +_checkouts/ +rebar.lock + +# idea +.idea +*.iml +cmake-build* +CMakeLists.txt + +# nif compile temp file +*.pdb +*.d +compile_commands.json \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cf05b25 --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2021, SisMaker <1713699517@qq.com>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..60b2713 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +ePort +===== + +An OTP application + +Build +----- + + $ rebar3 compile diff --git a/c_src/ePort/ePort.cpp b/c_src/ePort/ePort.cpp new file mode 100644 index 0000000..4773380 --- /dev/null +++ b/c_src/ePort/ePort.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +# include +#include + +#define BUFF_LEN 256 +std::map reqCache; +bool gIsBigEndian; +char gCmdBuff[BUFF_LEN] = {}; +int gIndex = 0; +u_int64_t gReqId = 0; + + + +void LOG(const char* ms, ... ) { + char wzLog[1024] = {0}; + char buffer[1024] = {0}; + va_list args; + va_start(args, ms); + vsprintf(wzLog, ms, args); + va_end(args); + + time_t now; + time(&now); + struct tm *local; + local = localtime(&now); + printf("%04d-%02d-%02d %02d:%02d:%02d %s\n", local->tm_year + 1900, local->tm_mon, + local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec, + wzLog); + sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d %s\n", local->tm_year + 1900, local->tm_mon, + local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec, + wzLog); + FILE *file = fopen("debug.log", "a+"); + fwrite(buffer, 1, strlen(buffer), file); + fclose(file); + +// syslog(LOG_INFO,wzLog); + return; +} + + +int checkEndian(void) { + union { + uint16_t i; + char c[2]; + } value = {0x0102}; + + return value.c[0] == 1; +} + +uint16_t swapByteOrder(uint16_t ui) { + LOG("IMY***********************swapByteOrder111 %d", ui); + ui = ((ui & 0xff00) >> 8) | ((ui & 0x00ff) << 8); + LOG("IMY***********************swapByteOrder222 %d", ui); + return ui; +} + +uint16_t readLen(std::istream &s) { + uint16_t len; + s.read(reinterpret_cast(&len), sizeof(len)); + if (!gIsBigEndian) + len = swapByteOrder(len); + // std::cerr << 'r' << len << ' '; + // std::cerr.flush(); + return len; +} + +std::ostream &writeLen(std::ostream &s, uint16_t len) { + // std::cerr << 'w' << len << ' '; + // std::cerr.flush(); + + if (!gIsBigEndian) + len = swapByteOrder(len); + s.write(reinterpret_cast(&len), sizeof(len)); + return s; +} + + +int main(void) { + gIsBigEndian = checkEndian(); + + // Helps to detect std::cin closing + std::cin.exceptions(std::istream::failbit | std::istream::badbit); + + // Read buffer's length + while (true) { + // read len, 2 bytes + uint16_t rLen = readLen(std::cin); + + // read data, len bytes + std::cin.read(gCmdBuff, rLen); + gIndex = 0; + int arity = 0; + LOG("IMY*************00000 %d %s", rLen, gCmdBuff); + int version = 0; + ei_decode_version(gCmdBuff, &gIndex, &version); + + ei_decode_tuple_header(gCmdBuff, &gIndex, &arity); + + LOG("IMY*************000111 %d", arity); + char cmdId; + ei_decode_char(gCmdBuff, &gIndex, &cmdId); + LOG("IMY*************11111 %c", cmdId); + switch (cmdId) { + case 'g': + LOG("IMY*************2222222 %s", gCmdBuff); + // get the ip port reqId 先读取 cmdid, cmd + unsigned long sdkCmdId; + unsigned long sdkCmd; + ei_decode_ulong(gCmdBuff, &gIndex, &sdkCmdId); + ei_decode_ulong(gCmdBuff, &gIndex, &sdkCmd); + + LOG("IMY************2222221111* %c %d %d ", cmdId, sdkCmdId, sdkCmd); + // 调用函数 + // SKDAPI(xxxxx) + // 存储 map gReqId => cache + // 获取 reqId + + // 编码结果 + gReqId += 1; + gIndex = 0; + memset(gCmdBuff, 0, BUFF_LEN); + ei_encode_version(gCmdBuff, &gIndex); + ei_encode_tuple_header(gCmdBuff, &gIndex, 3); + ei_encode_char(gCmdBuff, &gIndex, cmdId); + ei_encode_ulong(gCmdBuff, &gIndex, sdkCmdId); + ei_encode_ulong(gCmdBuff, &gIndex, sdkCmd); + //ei_encode_tuple_header(gCmdBuff, &gIndex, 2); + //ei_encode_ulong(gCmdBuff, &gIndex, gReqId); + //ei_encode_ulong(gCmdBuff, &gIndex, 12369); + //ei_encode_string(gCmdBuff, &gIndex, "127.0.0.1"); + + LOG("IMY************222222112222* %d", gIndex); + writeLen(std::cout, uint16_t(gIndex)); + std::cout.write(gCmdBuff, gIndex); + std::cout.flush(); + break; + case 'u': + LOG("IMY*************333333 %c", cmdId); + // 获取消耗时间 reqId + unsigned long useTime; + unsigned long reqId; + ei_decode_ulong(gCmdBuff, &gIndex, &useTime); + ei_decode_ulong(gCmdBuff, &gIndex, &reqId); + // 获取 map gReqId => cache + // 执行上报sdk + break; + case 't': + // 遍历map 删除过期的缓存 + LOG("IMY*************444444 %c", cmdId); + break; + default : + LOG("IMY*************55555 %c", cmdId); + writeLen(std::cout, rLen); + std::cout.write(gCmdBuff, rLen); + std::cout.flush(); + break; + } + } + return 0; +} diff --git a/c_src/ePort/rebar.config b/c_src/ePort/rebar.config new file mode 100644 index 0000000..f41d66d --- /dev/null +++ b/c_src/ePort/rebar.config @@ -0,0 +1,7 @@ +{port_specs, [ + {"../../priv/ePort", ["*.cpp"]} +]}. + + + + diff --git a/c_src/erlNpc b/c_src/erlNpc new file mode 100644 index 0000000000000000000000000000000000000000..37896549b8a82911dce482ae506d5cae1056f5a6 GIT binary patch literal 26419 zcmagF1CX!3)+OAwZQHhO_i5XY;Uyc7&K>kzzFXVp)!TleQ*?$fE-$Ezw%(wk4jBZ;wJ{ssy|cyqE4t zAARkpio`~i3{WFG-W&^CpOBk=w<16|HHoXKg-AK%FUWI{DwafbD7C5|=Mzj!(@tlD zYZcWX;dX2&Z-$H^Uz0f}W)Lf(>k|U?%mKVf(sBB~_A#$4YAUV{Ss8fyWu1M}{y#&_o%!ZVrF&_u zG;zt{HG6x0GISLo%&!X<`LtY26+>mB8+%3Qwep+0C0D1<8>8h|Bh-XPiWYUP3bn|C z`)RG{qRh%)}&YUi$JrgInVqF=HT;) z2?I>rF*6&1kbwCPLFG`vLa-EjMH!UB6zTvM%QfH_ha@px0=^i?}l9W3;9{Ka*7 zl&r!NW}|Lo9o`_r85H$4zGv1xEek(VdqsQ0<~wz-XVS;79Cn#&5V6X6AyIdCKjVA9 zHY*Ln1RTB`A7;<%NFB%&C}ZjHwPMdRTfcEK?ah0*+8$082_3p$AKV8wxPRV{n;n)$ z1?dEdbQsm8zG|AUNQ8Yr(*0-T%Uq} z=d8c1e+SL?8if*m9FhA7uo*yP+ww-*`RS`X^h2UhwJQ(CFQnL_~!nPThVhu%z9}T+iQB|ThXMHAQ zWekTRhn-R$eI=k`5~F8$LS?&r?yD7^$>)R7@PgLt+qmVW-5`7S3+q6O{idx&JHP^t z0Cwz(l~}_9T2<+YAsd1MBllyA{7ZVgT@GCH1vG<){2xMP~3`xBEr6ppn z_dl}?*8iJj{);gFjb@ZV<5no(fq<$||8FvOHZwMIX80G&X!<##9b@lK>pS20j1TB@ zknNM24uXS(kYygB+#4C*FpQJODJBHKIInkZ;z=@ioL=jTDDiSxMkA;rrO)ta)=^Cm z{;CkaC}Y+9tat*2U9xU2fxDVJmxHWcx+`p+?QDgP@AYO?+&T5j+5PC6UH!0k-}K>B zS4H~?X`NoYnh(dJili>4vUVw{05e@gh=5NSN3Al zm@#H~=~G6#zzAAYu5yZmlFT$RW8Iiyw5-VR1p1A#xP? zMeb&yOXEd3V7)^wTpWma2-F!65jerxrZ)F&3z=-)^`+e_C-G88 znsoTl=7bt*@Q+h%DK*b!Ea~vl3+T=K6rw@wdeI}KTHeNL5jNap*uebAaZf{7S~zl+ z6Q9^dY&EpV;?0#X%oV1w12v>PwI4M?h#&=C5y_RAh`pyr^Ih^Mi2C9YXwFr2yU zv#V#2Z1FNBqb}_V2H03-0@W5z@C(St$FWEbsA8@sk3GH9P}?{tf>S@yOr+ccN#6xj zbJ@aJoe43{`MDF$nxy~g9LN^uJ}kKWJ(^%ma2MvfCnNRjh8xB5vE8~vF-hFAaz7@< z1?^hoAC4IDcO0T#*Hs~K07w>4EqstOCeq$LDwD4F&rwDfVz;Mqz5n%u!Q)qF`WzOA ze9;Jh!0}U{G4k}r(LFe?M1lW}Y>_oJ=62-F=A6>l{&$d?+mmGWDxVDJZUlSoB$%T% zklvIJ?j|Vy<+iy8rlqc>J%yew?iRrvn7{(ovI!_jAl89MZ3Y9u5Zs(tQEC&G6@JvP zWwr5Tk2wv0NSaf}b87me)0t|5%c5{idtABC)Y%qVyztX2i>e*V1P26O6oVwm^f20r z>@koOyl&_8)Udn#nWl=K#sZUNM=tUzY&cYjLDPhYp;~LolN|RDED&|7nn}IAZ#i(9 zI)(+w0d*}p8bDG4EfoNG&<`_a0e9!u)UnhJ{aYXoM0#k-&WP=tsB3MyNklT4q<;hQUb&9;+e`XflTv z8U)gW4p0ZulrKy+w5c@!NsCGpi@n^dZwVfK<@ilFYbv~9)ieR-SY&Pqom7JRJ}V@C zKBtj6VWisbT7nCw2Ioe@>?DGtaSg#aM!<~+Fai~arnV-f71?hc!9uIAhq@fwk{*^N+^1o*L`X#E9m=B}f(2M& zmRc>bkqeDfT;Xj|&Be2K1zH0fNpZ?BoW`J)*@FdfiRLolj>0T2h%!>rRkbZjl^C$O zz<5_PR~8voP)RAw=?(A442?7B{s!V85%sO{fU*Z|n+HlF;7Iqe>f?CzouEP5bBZd1q6`jh(cQ~4ImCZj5Y=I{(Q1?8wa3hL zJo+7lMoT#gfL23Nt^}f1H!6sMUFJxjyk;PFaDaLNQADs=W3DTxBDE7 zJr-u@<^#um1le)GoD(suHq8k1NW-2D;LfFPAZud)bqi|$RktO7%`J)Ru;Yen_*6h@ zi&&IQx(x+?bFUbzs3F{r42?&328?BOqYvs92rnqMwc3Yp$L)9f=yKBkwJ4Jl=s$F) zLO-NwooCO~*%pZ3#83{LI;wu@(ikj|5TZ?Gh1k@G@~1HC$^s9!ngalCqzu~`A@N0& zKTmO+D|T#Nr1FvkwQ5bsX5E2A#xOPwgyrTGG&hpkQS^%-Pi$VYuzwvFExzhG@iC}p z$qk?7$lS-v8M5yXn?S`9)wVYYwcS1NW%F~6<*(NPCoY=UHfY2e$uSGW@?gF(&URLc zh_wSTzBvsT7{Ru69`GE}X-mSh(_<%DPl_QCXB{eHAOZ!qvq1GVVNeVW@GA$XU05<` z-wwp^B+9xwj$Jqh#6FQNnx$blHkUm?SXS|gD}+VnrmZ_lQ?&F4Kft^-QAdWOq`wad z3u*vdU!*XOdJQhf5wvnjJL@}N_#vHtHRr%w6mC`tw1Y?LyZ-`Dc0h^{!W~uPSTMxTWGSWVK&}{a6BIwVT=rBdkBU$wYPlKNGeb6!ZL0O@>0z9dSCT7j`-o17l8Z3pc8uD3|}{f z=O{jVz!M16=#}lZehxJDT61+jsx3+;>CzAFZcl zcmIICWCt$;-Vz1Z?@Kk$KG9zeMjHg)){inczui7BVR=`7w_Uv!*Jpd|VIpilnVoa) zI;?FsTwiIB;6{0PY1Ddh|N3dI>8X)a;LXYDc>eZCC;ap@_^m-AcJWrcOq*Hl9qLea zl{XA&Uv{#3j;yrlX?5wu$cAz*{*Q5r? z!+cGeDu5xy*=@)m@6!4*4i*4lk6ZkTQ!fGcCps_#B45JRd6i>1(h6$>fD7gN-1HKo zG9#siDY3=A`~>fYzF$_Ms2#V{F94gMOnOb`uT}e8h}PKBfCHwbO;Q||q%4DFRRO}< zqe)VuR^0opW@TMA@%gC?9h6-})Gvh=X6Mr{fcq<`{LkA70ak5}BM2E0B)eX+s5cQ9 z3X++6I-nXXeSRA2@kSqZ?u4h+i`r-G*H| zit=p8Xg}z`75(8TNYE$h3H$37Y9|KN6YHi=7;m8UpxP6cU{KnZcf}D#aZlP8awqtv z|79QYR^XFJAb@Zrc2D%RbgfVF_V5+^lTIMippWs8^%dP0qc?1~&*7l;miJZfli-`b z=a1k(?m_R~=GCtpfw~QAiRGQ zasM(Bb+9+LviO%MOV-e`#a%_u-Y*<`v5e(EnET*hITtTUiI>tz>avuIEHIl)uw9Qq zr7UUtYr26p?o2g)9z^4$+5{ZbAuqsVr-bd+nkT)_M)jUpVwH_16;)&(&0;>O zUMN;Ka1pKDt-_H>0Xas0LJJ!+|E%rU&j8a6l;=wZ&96A%jCiy_aakmSaUkl zZceXJ!x7D0D17p;+Ewgazi!T915XNMQ)oPeyIg`PENc^2-L7O6lR^uTJ=|;UzhgMk zT%ycA*<3-1^WLRe&c9h4`p5MBGZjOFPH~oyO@@%er>4nvwg^ zxc4HQ;rw~lIcU`1)jejvW?e#RPC1wz1&?Xp>Lw-Txw-WXZ-FEXFFTKZz}01rUYWbi zw#|LMgHqU(YfRJZp=#<{qU;6fp$uTw z^29iGNSBNc#^Cgn)Z_V%gsa(+#vEHR+zIbSF%2mtjUnnwh+9)9^F8VYdl*a775Q4a zD@`q;i$rRYSk2a-A0pCf;S#iZhD+x#PbqV-WK%QaZUuEW8C`vD$%`)=H*WDI&q&L7 zv~-x_vA?U(MxbH9ucAT{4I!chtdRsQKKW6cRh>C|jO=$O6SV=Lacl?YR>K{f`Bn#Z z{FNw|IR-1ktJR8p{Q*@G9)26K!#)_|m7rG{uj7$q4{&PmGg2HyJ^|OwmYo{OBY>9h zC!|0*c6s!2ThRsg80k%V956X0R4XQ$(4+tsB5EVUe0C{ijex?}W9scFVdpdsc^D9} z^AwRv^GFRuT5nz^QGYjc@eL#qd}4Zl+$V0s6lPNgY<$QzL8GrCowUQ5ad zoab?XOgMeVT_ZszUM#%AH8Jl?bWGhm28WhwBW0Qhex^o|T^C`4dEv%%(?|Vq?G9E_ zOB}Hkt+J|^Qo+KnPzOYmB=mUuK&fj|6P*p14^*+D%`74v0MRCW2m1C#q?~(|s#%ZU z8Aq=#E6o*|*0lY-JD}6VTdLnNHcyfFsj6fRmiP0*u4np8q4%?c!Yyu4>|(75Qq4*u zPc-P9LErvQTTI1OQ`Ce9v1?xxW#eW6&4HwnnWuPU)vxm3H6Hkg-X1tao!L9$Su#8T znP*KlxFUX_-A?)#3yEs(3{ z6*Xe7%p#pmIkyi)K_1a!EXd%`{QlTC2TFL|e=GHUTpsULEtO=5{0Aap=ZxfKsKU{y z>!o`c@x4`Wkk0eVlAs_Fh~nKHct6=*^^(-NQU9PgtKp!X1Fbwdmf^EM88M$S+~W`8 zzt?x#b`D)oqm#glE;RC}M7^n_F_n$JnQk0<6S_L}wq(U1r4#14j#0nm>D?Pe5r~*{ z?m3%QS8as%0R>SUXWo}pn1XI=IY``56zZ=@Dx`Pbx(bW}5H` zI=nkl=>K+|m((A?QVlwB3vBipprR;4N+K^_%tjbDx=wASwaQ}Tx<1(puKLFfju3P& zW^b;Eo+aSK$7-oy@DKK=_6j%42^cSvfDhZ)COXU}zN|_#&DpC{RLNc(5N}GHLV@DG zrWy}2f|%RR@gtZu$~p93a664hth@ar%=7U!*Q_-R(wN~kan?R;v9HoT1t>PM1?Z?4 z5pJ+!GEGTtvw6Ct@O(b_73G}zGbgH8A@2WbHiMnThPIq#2CYc^B zmK7roV%oONIu^7aIl1(VM6SyeCK-bb3f%*J+ujw*vLHgVq?dBGTM1n0^v^gz)e{=9%YzQ3Pf8O9(_C{5=^NpT?T)8~)t@798 ztRgu*b+uG8oW!JX-}-~=dMVe= zeJUiK+WXp$6VqlU7mU#PX*Cx&sTc&I_l-ui{~i-~z+jGn=JHm=t2n=nsaNxb+}isr zAkC2pFK~K^Ztu0;D26dzF|A>?&p1op``ih7zo^%fT3GsXS1YL7PEs^l(WvRS+d^6Q zvU(xEbtlL0kwW(2oz9ARa{3TGno6K6Yebz=3-j&Vtf@tXojRVNsSQ&!6CE9UG!v6O zp^Kj6Uu`gH72N(EvVlp+QwBc_fye4Cz@LqqiIv?&Qlqk}&G57kt^9;7YpnRQJ5q za66@j(4yq+^VVeCoN=$ylQa9G8$oCQ!!_rTZKUI!QD|`D=%-k>au3TkIbA1DG4c9k zO75OM-AGee55c-lqGPY@dbwf83(6UByQ7`F&34J zp_@$A=|CzD1 za5w*%w6*Xs|5;z(^{4@B%Ql19eegTw-TiQi33~x-A3fOl*)ZjHQ*U+^&z{2e96r3w zFxagnhK^i&*KnvZY5*ka&gegzL6O^&E7eOU7PA-KSq=EHs5DBg@lk4jSuf%zH!Qja zsWyk{QC;6q{Q`(2bGy5=C^UUs$z;z5+G)N{HY?0cqh;(T@T;d)BX!mtxym-`It3+y zj}p*uYL3_N9+J}$-93|pG*XwT(od}g`q&&>Bk6#>+9>34YqUx;cY4>ER46$C6griu z)k?p{P0RFc*hcI3!G!Bzts6Kf;D+M()oV5s>W=()v&{>2vsZB3yH%(*-UbcNlWdmb zw)N{Js#nO`WwpPttEV|4TNatsE0bt|RhX43H^M$%GMhn>7N7~_JB6Q*5R!Q&o9|@2Sh&=w+44nF{ni*-M2|e4 zJ=UTns*$TXt>^j!FM@MkfMqC_1Vbn$~SMWJ-8vRn;B z0`VMHM(R~9r`(od=N#t>VYrSzY@3zJUAdlQ+OZR|+>2M}GN*#SK?E1@ASy2PSiD%*qCC@mH0O#~d)ygm1e-wnR=W zQ>X(QZCI^LVoavjjMj{}3cHMA4b6KzU^;y5m_ap4PCy`Kp;7%y1GjM*VTmBpbtSN+ z-&$UzAM_coU#4Q%l5+2ASqC;*E7J$-XbMh%_()qX#RtkBPf!X?&y14MO3Hrhftw9_ zBf2Em6b{XXTn7VT*(I)l03m|QMPV@qJ2kuLB*5RQ91yoTUS4#|GFsEOSZ#{mXc0Fm zuS3s{P(c-p9_1d61Gxzn#kqI>EYaF3OuZ=)nhDO;#2p5);AX_#V?~WK_DnOCCUV>d zhJcmPf+S4Fo4zo=wOfV{lTtZ6VLSdS&@3DYtpfFeBgy6wzjB!dIceB-IAw)_d{htY zlG^H9f>oWG;`)5Mjk=k-`H>IdJe5T?%8Da!MDEVLzF_tjV7Yuae>WS%y2l;EnMrt1g+M7Go6EQKg7lE6(?$G80{CxLhM zn8TX~b4r_gVAhKUDTQo?ersh=90}@qBfI%k-BEY43|vE7rK35j7TO;UY?Q5}*Fsl@ zFMFScqhFogV@-9bw$o@Z7xC$oo9`H@j_{+77^EJ zlE-fN-bwF@gUG&p(tD3v)QDfN1Q}k5?kQyQ7ntwo>_F|}#NMcM=B-)B?P&3zWZ{P< zsM_Q}3QzQYG2aMDxkxB{h#CpJUnt224rX9FE`cF@4JE~1BGD8ZNEoRi-yTS3g<%o_ z{io1#zCeFMO!XiDqWCz17piM8sn}4HJRxRgsfwihgHCf*;&8ex40**2=qubrE8x*C zWHaw*)}!O9q&cMmtxH|k8l8TQ6EvyheOJz&#|aEar37*F9eibeG0?7aS-ymP=yo&e74@R zQ;o9ByIm|bzxTX~Vd0GZFoC{RnkgiV#XPR4f!Mi|jJ*D)!%yesGw|}rXnSlzQ$bk> zc?|jckPX>TawW~9izhW3j74%SpyyJ)hBmT7whg2uO^<|HRUh;g4C4HI^UHwUFuce^ zAisRugq~DU$anqyhUmxc1v84NEvACH%6Ctd*^9zqe}6N3)^A+B(TjN@HjcE1WC#}= zJSGYWWeRL$LX_bWB~0Cx@?-s|;RECT$z1)%Sa!@~Rh&0A+1ogofc{-{*gq25rhC_N zLbtVx=8L?D!8OBg@C|=ap{?a$x!mz%?3mxY-J&K|U;f-m_`7+s_evOP*pO1yWubFa z%L!Q2n_1Nh&Brj{EuRz*T@vSGs=f8CQ7Ol0Gsj0np)7F12gM-!FLw>p%)=S@2X^4= zC|oI!VZ>xmeF(VnYYlSKnnXiua)Uivy{025P|>CDYg}OJmPGgI(QJW>z9VCAS9(~b zh3Kdg#EC1|#Z`xU@ghYfO>&T8bW63v>kWwMT{5fXDzPq-s>PInJ5wLeV;m_1MEG}r z9Md&uK^uMrY~noDA4^ri?WP4N^Pj01b|Fuq$C+6_Ea@!y%Bep9f6kV@EAJ0p%d`O` zZZG@8t!%+z+!80j&@NG7F0WX?*|WgTQ%ZsywJ?@wKfDAd@_t0H)4B-ZGhawGGrc-e z4QlJy{u~fRns}E5JHbnHL#0-+co7aaBNkP9LDYBuGQwUjbYAN*4KOIJvjL_BbgXE? zyiyXb1JsFYZm=;6&PT)WTt*ZdNiaXzI#A9@V@q3% z(Ok>V<%Io?d2~#4B(eYEEE|ALofS$|@gkfWEfi0DmUMZK&CvPwjS!4&-8CNWx>!nB zpy<1ks^1r6B@iU;>A90Cd!Nt7Ud4WtA$v#y$^TM-S$#F9qRi!bMr^u!#xXY4X$!~F zB0S<4ro-diIcXmlbV-6wS3{%U+tSgLva9P(>-~k|E0ow)rf*-!Dvi*se4E3+*>~W4 zR0-D732=wnfEVV~rq4AWBhZsDCQRxi8T6=dgk6>npgBf(jNjJR&m(fDwxw*I<3$ct zUJtn$aCFcM1F0tUfONc3Sz}nk4k*ghbw>=@`Fm{d@Lqs2;6v=8ma6KA=Ugjy&u{Hn z3)puZHEv_6uY7--{&O~60Su0$#9yleV6nw8JYCkuWGAz%vw`5!z9%5+?-Nx-(KaHz zUvb7ou1)4_VKc>Gp1i{}M>}T`LXidXr?+buFA2fZG)%XAuWD1k?99qm+O&SzV1?xesbbTldiYaW$DDcvd7@xwe|~Cm0Z&7Cna=c9 z9kgqHyNT{jyMXbJ>Sj+-TeBl@t%clHxC8s}W8ej%@F-;7o}YagcKGw)$B!DcYjy7w zT-d&|uFgpfGY_^gJZHE?X9NX50)HeqVun7uGxP{H<+2Wk*R=D`sZI{gO?oXN*sf#b z5pl~^;1@e^jj`{?behwWSaAe0A%cU(K5No2Xrc5=RC%n-hamC67;a1jE#)`#*gg0x ze7_ZWTg~#~Wu2`qE;Hm|58Kj=@b0`3a_a&HJmK%s@f)SJA#t!K>>b({olbB~Q8V82 z1_(ShU`EVtodzgOS7h-PyYLYN6?$?9dIZ)r2&H7*m7zeC6b_IlL6}VEbvh;vrp3O` z)`90v01=bw*j~fj;ZAqS;@(erosXV7l+NNBk7JgGE2(XPEZhZ-7#_l0@m8jOTFZhO z%@GX7>r|U9g5=AgCHuIIEB}fU>#2c?=5%3MCqO_cDStdwTf_g^Y>V*SQ?#X*%;Rwm z;xk&u7Jq?PAzDbE@TPP!eVA(O<&S7V7x5Un!pO*IK`TKUL~Fy(Pz2JdqjVqsLMsQ2u zH(`J=?rQ_(2@Um$KVqA<5n|Iztf3P;ea}HdZC?qf}a zhe%sjhd}Y3av?I#gg?U9%el4Raon>YRuDeZrSR*Md25$o@XO8^a`f?*xMQ&sVD%XP(+6p-r}#Y2{(`+_m8&zG ztHMfO7+w}S@5v3J?{_bpC`#Io&#^yD8|^L{mIo^UeQoWjV5BJRaUR8yJ99g_1os=l zWF={}-h$WzRXPGCpl2>tNbs=Xl;8}>)`cgdq%zXrX2>ZNKbZMw)k5!?&(}?m=g!6N zQyl$ewhG3KS>@3C!|x45q_;R%5V6s~I`d0~_L2GPv(I-P_8S()hu{P46Ns#fi16<% zME5|BsGR=Pt%c6KA9R;=RBbze-0}{{y?4h9YRmSh@Y5#F2UPE#t_Ao;`egE7>aN$qeWrM@sCtu2L9%k{d9LYLZLMpW>#qZ>>!AdNI@Yl(G?(fI}{S*&aYt!1j z_w#CfaQ^d$j7fdqUPxtv(T`W1>U+=VlO-Gefg?(|?~(xpU8*E3?`~Hd_+t&^KSkq; z31f-Q1l=)Sk6{D)sSYVzB@z^bh;ytR!8xliKBBsC-R03p22+T3Nn_0X_fC9Zi%V6p zw18^3-}1>XrK?Q8@}H&0$eMf48xEB|h=;y(WXpc%^ywH1A;e0m1+lfLXWm}_U|gy{ z`3AIQ38}W>)O@r|>W|*l9=v)S-Elg8O1z_=e)@dFdpouPR{;h;81q2i^lUIp1!kn$WH|kk zuWDpCI9Pi(RDdh-hKDFqM23WHJu;sglJ&!XKIl`jeWPQY5`eXrY!#wIqL;lG2jUl2$@Bt8CzFB}Z39>Y`}Lm&q16$1kss zU5sUn6^Ce};wY{0CQXe+s8&~E)Pz$a=ZwZp++=*R9Uoa89UXpl-=co{g?69HUlLLQ z{2ZQ4LbILLIh{_VLmnahKILp8bLK^%h3Exyq{E#9v=49Lq6b->OTL+0d4J*u{L}U= zELV!9BM1Wt4(UN(wS#6m06IvwXkedhvAK58T(sa>|GSh0nUMh|6zWq%dlnAMB?n$b z9?T8sA>Z>3`hC&hAlkQB_ilmN&DkT$$)ETeZw+OSa1i$JbMRK+8#dGrimW{>PVqK( zkpC3z*~Rhl;Trw44)BuFt10#_8|PnCXJGuhvGoTzMW^d{6m#b@t{XJXpdHXTcZrSl zZS%(W&TuVERkWKIC*ZXHQs)8Z(|dmS+m`zn)yw0p$j##|~}$n)X%utZupc1@q?ms)xrEr zmPffKZZSi`r|PmXr?uN|UBu?D3)8T1kpCK-L(81ruCVMl4M5fETCfv<_O%70^WAmi z@-9yd+o=fIY$EanH%FA`0o|ab2g%Fc)@r22)2gxec0V7A-B zR3yXz1oNH!OL0eW-S%&peg2f->HN?)A`sBePqZd9m)h<}?<)R@emYzsl_{1P14VE- znRE4GwN$Ymai`^2Mw3z!MsasO$yH|Lz5GWBT5=p+GJO-{hFZmL`{5&N@6E$!?&*!! zj?eBx&g@&)jn}MCjf+H#feC3FY-s(_t6N^X^BqwQWG-d$fogFYuVSR)pm)Y%F`WlN zSi9^UHWu4-(ghQRc%ig4Os55PP9yp(cjT$=@S?`uqblDibw}5b&N*`P!mDZgR-*QC%Dg3bPiwSNh+)FHs5+)VwBq>&j?IG%;8J2zAc-sVx|?B0B|}4 zrhCsMpv1%0^-o=fTv#})SYu`gJS?Ry;TWJFEvQJr{3d4ZgW=(ArBAC^^hd!$ApQCN z(QV}}<(Sl<9KF2K@tDORZWF$KDFxP90;t{4@HK7c3_EqUHsigdgTMnSGbe8Oza|)A zRxbT&8N#tRb@`rAA&X;jHR>^^z%$zc58P+mVFz~3zJzrE;1qXW1;~>AV;&Q%sDy)g zklR1N4_l)cha*!_Q9eqM)YMzYz#dl<*F0od93$hf+&#cbEUNxiqh8feTQLujr&En? z$&UK%){fK^raFD~z>ZyNC!Wiw_p)fe>G!(~*LKG4cmwPhH5XcOjN`0S&6)nhm6DF$ z1l?&F&p_IujlAW-u4FtYY)3v24DTxQq_tqd{Z>rBr@{|3#-DIxwuki;2naM`M*E=} zodk9xAROks;>u-$7udx{JyYWQi*k$hQJpn>8lsAYg&-B6PMJMC*w!xs4;VLsDk!GGI|5d_#w>Gv*FZ3ZN`N`_Cm0?pfPd5&s11Dv9(K<#R%t- zir0&1i2#&w@W?eJv_lKz8>v|Ya?hZmeDoFDkqo8wOo$Xf zllqVu3xk|TvoIX+n|7E)j6BPL2qPcn4D^x+tlb-m5C5b?K* zB(zN|gc%sg*%!glSMD#&@|Bn$laj$q+SM*d9Xi#-6k33$@r)cyquE5CTAx}_wG~fp zzw1bgwK_m7z^KRrQVrc+xES8$n)LL5#sEp_V}AgKB>r zf$IJOUvewOXaqBtQmK{YlCty_ES1_QCBcp)w;3i;ueC9x5sv+BJH@?)iknLk>pMza zudI=S_Hqd^YywU_=zLHEyG{c#Z|I=>Clt2@=E(&=Kxj(IGQgz^Q8*=l89Ss*9}{8su@)wxT$ z9)d{XTs_CQ!kBw!>cqfIzz=8&gf`eJy~IWMB0~$!f^s!;^7BC*Q#Rc-@J11KW)w02 z2OC7htfguFXX&@!Yz6eOC+*mZAkm#^j8xee#=sH2P)_i=x7MF2BkFX}Ni4WbJlv~b zqCb)Rgu-Xw%0ibVL<$gh(7ncu)`_Km`a_8A5GJs}KXAK?C()L_LB?dX^Th z{AGwhEJ){XCa!*#oM0?a&MbVsV!An_p0+} zZZ~P}q>@h9;YPT1t$N_h!SE&xC1~~~sfSO1+$4z#_p`A6q8^zZI4NgzRwi86u>FEL zEDijtKJZsH(xNM2Ta`L|$C0k^Lnu4KC~{$~T!#5)nl(7RI;paKZszubwEGDO=n7c~ zLx`_%k|=DRG~bUn&XW8a>yHtjUZ$Q~7>@PDliVOG>D43|5S45!s}gxyTWcniBI-vT zr7Pr%U1$y=SrAvhGz*N8y zFZit#GBzO&(P%kue9x_f(p?ScO)ak*=pdSS*Wi;{OgXAdAnU>4bDRLLVs$Y#Z!QPX z>%IT=`yMakyJNrWd*el9r&VgU^|IEFb4XCqyT=0NG8IHdl z9-I9l@7RRTW%9tWO)(v*!ASV~`;(i9vC7|jIXw|~{pp1ub=1aLu)1AU`3vZaIntVM zTyNUgk8tP?0UB>vkdfU)gT;F~{&$U|W6968SikSpWOg(#U^lhG;@r)(n!N{G?~3rB zS0%Lsc2-|R7bYb!TXac!f>(RZgRB@IQvUih($wDiAJ^iR*Q!_6qZpn1BReCzgbwah z9Xx$Br#bq|J%^3*yVI=NDb4&=`J&|}3c|8a*AMZfAOcP(Lj_g*@D}W>yldk4;MkH9 z>}To&p&d+rpAFu6j)RE>qzXuM2?> zR)wG4E-_t}^yk)$^l+I+4^n%#y7bOJ;p5yoE9O<2>)*3d-zhSOo`^NdSHjVMiwbyF z1HwYLTrk>wS{!9l3+9n)BlUEasA|{k7d~0~B`T{d&;d?IPrl3bigVrM<>jRAE4iJ_ zrM7a;LrrCi+K@TPIc}HF84A@hKU`WJsye06#b&XG_0j9Cq$^&jH!Vk4vXTxS<@(Jr zNes7Bu7b6xt-41{@PbC$My=oSQGPO3pBZ+!!BOyPfa&7*oWz|jw^eTUsj7p6yRpd! z58O_TYZh*%R4Om0wj148Zd+1SfZUhUSBvX@qEYg`GWrazV2MvrMKtFe_cpWNCQSD& zH+pT?N=~irK&EX)AV-T50jkESHFS$c8hIJt=3)ja2My`z^HCM-Y3WykZ|7y~ReExG z48kU7>%OJi$}%+a=jzU3^o`_S`rZx)S>v(IR?wZE$X$W*NxP@cgvru-{S zr~Y~P95$aG`}6TUV+Nc;1&!XgRv;#IZ;_vub^4W{-$q1i#KwfAc5DV`b^InZW6w+n z5%ay-u{}AsH3xS=?jnQ$ThQb+MBPJWwAw5cK*sYBi_(^B;@Ekd$Y1syL)11O80?m)TsG#5&cE|gOXCGj;Aa%Csr)wvO3WoM_11~ zN)I=e#r`6ic187INGDj5oHAO)DhExI?O;AmwLaW0Bl6>&-ioi=ga7{4Xg^;^-F%$D zD}qhmk=f)Pb$-kZ*Q7RCVESe_<9C+w21D*j>AfG_{C$xPFhtElBd*9KGyYh z&+$Wk;$n&YMSmGgBUA$6C40ek+)o+H06_2cxAz=|MlF78bk^}3Q<^|pih$JI>~o`t&E zs^>IWi|n%VuhI>^MlCj8^XZsBa;>}?e3}dz>KJNrS((o5m3@BWtOfJ=H=!TFgX9qU z?VJ^65H+n)TCxsJ{%>s}gwPa^VLS?*6=8f5GwEsJ^jswyX>*S*$wz=9a0|8&ZyWfz zGJ)}Zt3|@++*%IR7MYK?;-*OpDt>jun@20$NOlK~5`FFbWd#L4lg>N8Ki0puB^3L^ zWycU)TO6717mmlDYKVi|1@AMXmQ`A6Z$7PEdnXu+=}m?u?Hmot73l@y@1HF^qEF#! z+1D9MA3h;;m)Y-owkX@^sWeh@Y7ZS8dd@!r@-6WG5-@BppL@p~=JuLIR+#si{i0j~ z<3-@Jqwn-wn41{0XYg67T_A?+tmVUceE#}Cp4Ry8qRv|2v&AA`qG7d_`nXf`07TRG ztfWNU0Wt2fHD@_-+JtkP!5}6n?hvWHe9tMm`a~NvWg^NJs0R4*Wl^i=3Yax|XUaEF zYB=Mg9)AaxfN^!G;RGpy20U3{Du{@Q%FTSiQy5=xmeNM}mW-B*K;NO0~;odEJM(B4FMK6k*XqG&_ zpFO_Qny6S?gY`ce`^um?wyj&-gS*Q{g1fuBJHcIoI|K;swsH61ERNNIG4QR2a#LAW^DOEw58Q)(U=OP(BzW2S^t?V^ zZjlJ;!u#oXyr?`r_+~4>CZInB>2h5M;&UO#anE?yYBn_;HAyUvrM&M`DA1yCQ5Tal z@W1nocX4UFnk1>QqgZG&cT(hRMS85STFdt}Gg$*qtuCa(Y3UNu)bOr+KYk;6MSZQE zyt1h{u^u|=pvZ*&C1&wiiu<|tTYCI}T~nERsqrQ4NcWbSlPRIbo$ATL*f+7V1;L{n z!G_iED^lJ}#CfxBR)OB#A1MpHk>QZcc}ifz7%#Nze-x`)6fOwUoWrkM*eyu;z1=G8eCpKh>`X zQyj=1+mFl-R(DgnJlYBDG7TrsZC>i%M!yYKagbq*v$_iDwP3G6_r`feN zedNPrp}kNp*DsPNnX={c4*X-~&hKcRHTI34 zJH1b~na+E~j+)lBCW!n^TDMo?WDB?VQ)m3{8F;=5-X^ckAiBhAf?{PFxc%KuGjZ#? zshu>%M#hJwZc%f8ej~@Zpu!-TWb+XGMr^j8q5ec_89sh}KX?~i>&tU7^#zCTZ7#jT zH-mkDH=o)gMiPqKAWC^0^H@6$U+C0T7g>XwoxLrdkEZd8!zcQ@bOaHP4YtG1YH6W3 zg#X)6!ni-<5-8^jBMHlB6W>kG#(uD^6Hr^RZPRbUUNFU#`+EHVCRKt1gr9-#XKzg> z`>D4>#$SY zaaT3{bZ23a+kN1Z^nmC#sQo32u+f`mn`dRauj8p@z?{LFi;g~s&H1j*ZBRvyHnWC1 z|6<>7<5aXm>B6RTW93dy&EOCX3AsN3e5^A?)cag*#8P|DrQ(OqE&Cko%SmOqub_q? zFeji5+mj^B+wf8l<{|y*hq0CAL{r!n&&@q(q82vqm1xMX)E_z#c5*WNjdyilbWD!a zCvW4m#^s!`lnXqe&&BQC9A1tMsqQ7WA-owzzYtg={H-b}LB1d25De}lB`MyN0g{=( zjE|5GB#S)bY<~9epv~b4Ts)St<&Ol2t1d<2#;eGaJOv9Cs@Y)ho!mXDD6ztkP_Cf589x|b{<(xK1P zj54RGA=BY_I`f!$T~bLP-B3vFl`Z{X9VNXl-Y^^4KnzPgt*gSu&&VOYYjMHKxb0~1 zJ<43cynTIh4e&EQ7xMw``{y;#XJhS5a~#>Grs?gC%d-2LF`?xEqbnBH5XSH18z;ci zcNgxV8jBAMB!I3A4u8QN+0isYcbZGw?golNlRk2D7I{5}&ls3QM0jTe7%fIU9f$o; z<5J94KQ0&Yi>*fdo8{>;%cdjT>o}4BGbv2$vH8Dh+ zD-#>u!7t41#JGab3(91fo5fFU^rWj;qfpJ{HrAy%lY)%8P z5`zKVy=Zp*%C<(zQ4!Hm$Z!Z!V?k$CU@^AhMf5|oG`ziZwB58+zy7&-hx`p1wUTUi z150be^A7X#Yz24rNqXl-PLsP)sF{a^82h>8u?dd|9J2GE!Md)WO-%|9p!*+T!~=E8 z0JUZT8VQ+i9*p~Ou#)kYHADVy%KIMZ7P*Bh{lcQT%;fUnWWjhWNsi<+y)l=74mc7M z7#84?*e+^ozk!L6Q!uwk7TE-vR(MoD#}2Pk&{vrx)RqX<9b~6e8tQX2tbVZ_78NOe z>XmT!f*?r2#hriiR=J~I3(>% zh9~w77_p1)%#to&l29@H&Wx%xVomZKuxG~E8nz~PPK^>THRSsP;1$WQfDJ4*<9G<~ zklP^3jaM*(eaP~a>7o{j&)%i}LH&?vF^#{A^MhbLmspx$imEYyvlw=EzY&@tUuvq) zD$>0~-x_5lJ4aZl+P$&5H%?3{dd7|NOPNWL8XRvdC$(GykG z1j$$;9NxA!6jw$%+_>M-1d0qGEq?!2$^!L(^555ek^L|FRR7ZE3j2-5feQ}|Or8o1 zjNtFmHC(OjT>kF@FgtB{SAzN0oU7E%rIBIw~|nt=gi@G{avU8uPAqNA!bl)^f4)=Mjk*NWCd;JS(^Ur*W(fHF^iDi&*QY*hO%xG`|ulo z+LJGztaS@9v5wj-kkdAa@$}D6hz!|ThbEqMq~hzO%x3WpBAY7pa%49RX8ZKs6n9YK zyFNTb^01i;ySZgbe?hhxDSlM2SXubEbTRt-%qHmfDTmEriNl)OHi&Lis_Djc;xrHw z*p6tGP*pMDMwb}* zjFDzGE%KhF>@ImS!K?1ajw)e0>UA~L(sI3K?)rv(N=OA6p$;Hgx4|s(F>7urFr!Uq z{3<+?i4?*%x1w50jTzS;t&ZlR;ZL(*nFM%b9qy917YUTIM$bg*{VLDCkV4ELT=q36wTN^nzx6mS3;ePOEX|VI!1C~h#@N>md#SgoGl}ggn2HrtR~5d zjX)4GEsjdebShhfy0c@&pP>VcXByGK=2QVamClM)s@Z_KDemA|!%`z>zmkpoi82 z8q>9GgN(i8?p(38_yOeF3}F~(K}F~hNV5Xoq)CxXQMx0kmWj5}>iEMwy>ty&9Ol8~ zoBdy+a3^H>I3@^jgCxWN64`pJlJUi2#+K~FvL6$G`RbCD_@O$?z}jc+M6-}4{w_}Z zH~`E{bG0}D-u(K@|}_hSG~ysI0>X5;27D}GZ~g7;33j>vl* z+lT9oBZo~kF>c9b>?Tq`qpBWG)R-q5S(tiz-DC-Lx&u87ND2Do+RP0zYb`_mu}I!u zAM`~@@knYI*&Ui2KU0R9iQWliK+-YsLT32Q08$04jsTs5VEJ)oPL_r~^svT8`L-5T zuqj!vg_(w5Eq8j&vCs7UX55{hP+LhkDFRPjveUxg((uwGVVE)u$D?o>O2!TKz+gk3gr^nx~Co=F8$G=cJ(x#t7FLk=B{3pdtPZ?s3zXcLLtj>I~PDC=Yk?Z+M1a?gQ|fLmt~ z0K)2tMEjJnnibxD@jk4b1e(mUV@+sG>&tlnRl3$`WI=7~>;;l1C6I<_(J-tv)m^~dGKdyE4WO;)N~s=^G{<>V@#fhVPEHt}5^>+o4cRuIwF zK-oQ2%d%B~%>QMDaFXd}nEadu7{iAq5)GVux(kQF-n@#sq|;7&ZIXkBu9ec? z*kuEc^S`SP;!1!r)cx=b5C}t;Sj72|2IIyPn&=Fo%2j53?O>||;>?lpVBZZ9v2FlN z^S#N{mGU-_58WvQ88QeRt-w8^N?-`Fz;!&-+vHg%&IPoTsAaE9yjf78Os9ir!-E%GWWy{YUm*==kI;x(w!gKyKr7st>A2~@+l!QL$LlIKTk3}#9JR|tg|3i z0(CN=8B6(b)s&A=nO9-I%jcpTVFm?G{fPk4IUNN4KUY~lm zIBR1j?dBJ%-hfobDAhTob2dkps6*=fd8qh^k)17dB08%{oo;qpq~=!dozqwx2h~-t z62=y5?s*z)n@ziD7WwCK4m)tR$$FlF;PO~ zcg^=sC!sd`tWR3#8fG|8iF0yl1}<_GZbo*(8b4UXAl{Wzyr?}ql6Z#y)7n*VvPmb$ zRydL(>Vqvhp>8agGB4L?o%B3iJc)Upy|7>Om8uXOj(@9P1m~~zSaR!HaSrs5XlTtt^ZXe_RT;*qlEWA!7R|~yf*9R-Qs~+ikFym|*@Puaeb_fLQb|$d z>yzNj$W@KeeipeW&|AD}T7fAVsLJU9I`u`jQbjS?_IQCGVAWQPMp)PDAX-6{8WedS zIb`UtSL$l{aZ>iU>1tpcp*2_JXTF6CgUFfK>1x9wJ0NR`u-fg?V$??x-Clw2z)Gl1 zo3z$?@y`#o@guf9tq4bZNCyW6&!_nM_F_1)^}F34C`9yqx3BaE3gbRIFwegX>bsE6+xdf7(;MgiGxU{yC zMF#ae=Yx`%qb>~yB}AJ9LFdz9i90^#umUl@D1mzo-dnTRQc+bOtb<`uxUNTzVf z@Or{nT#w*0eu?~DuZNo0luVBS+^R31+2CMcW;0=#dcjT z=F@>sD>_Ns}#sU+ko6|4_2N&o&2D3A1K8SS(!dlCcVt`t?H(5bM0#N z+eqJXnw{Ig((`oLxf(9{mQ~&{%7aFoqrx^;0Qbj%Dz3tSmKY0AOC|u)&|Xr#c|33Ria(!E*>V*T`Y~AA zy;hKb6hot;?q)mG*;1ervU+{s!zkYt5wSeeHDn3Nd$)p=^Q7+3Fa*3IgRjWKuZmIL zIJ>p78y^$Ll{=tUyBcCQiaARe4F%R?XwKZN2MmZl_cHW+?A)H}|5Vz*aEc{$UpKa< zRSlB8=a;yTG(#z8Sbe(?7d;(cr#LS!Zr9*P1UrYMQ)}G>=;b@p+3_$35u5o4K;4L( zxJ%R4bFnR~+t*cl7qOmv7aIsvm5S3FZ;d3j#PaOuC@jq&X3P+a!+bbYNg%wN`d$s@ z#85OS?hN2_(gPMQ4+9bi8;XcXY)XJ$Y@N3R$LE~Gq?H}enmJ(Zk-DYRJ`&DxGWL*< znmUgeGP8`S6+TkNh$s|n`ht#KTEVCl$5r)S3fRLk#R95C5EkPE(O$*mgqWPb(C zkycW3wOIxXvwXueVdOqaGKhb7ZB1k1QO3p``DxN5?9^uh;Imatbh-0F`H>s<*Yk}N zcQ18v1Ua+`3t-X>!f0;4%IQMk-ET?@y3XTp z(3H!>8{2&AsaSl3d?>9%x%2OA>ST3hbNAv4HvQ7906^(>ZT>=%w#$6ih;cB0 zvMhu!gyw#kRg6N8)b6J7~bGU{-edUzcegtZ6wa865CPEYU@PSnB zrl`?8pUY!k+6ob(zEs*Sl#v~)Wj)H|5G$oauoDH8d~sW%Yoskw1PG0rh}@Y^-H zm-(a^jd*&9BZUG=9!`ZwSV4e}z;-BZ#enbg-j4`B96&_OD4hJE%>BHHOPRVHs)dTW{eEn6Q0 z5Sf<}$KD*Y!i@(}St6MUeY0N-Ym&Z?GOI^JAjj=`CVXGoq=}v;Stajvs6J)S2=mI%u`^ zlPcPxiwUM>_raKDabQb=aMHIac$R74E92zr0>7cc7CVm+rsG@97!VZso!Yo^G{|A= zhkgH2_g<|RO&r(QHe6^z%RM79n=e;b`edQk>%~C_67f)jfBY;PXg!7c`i{SI^~dGv zwXZX53tOrwPe!MgU`Ny}v!@cVFSF8X5B~-WVVB<4)ei@YR)!Cl^$*?w*8+XUclYd) ze1lAbR^KmK1#tqJ?V2bHqf96gpbu9rZ|&oCKgm8#1<3vE(_8wX9>urGQQzn4 z%bO<$!sr(potTdEt~P~Li#P8zjCU?!IO?5lMYGS&(;Yh=TF@Zwn}>oEt<#gu+exiv zMo%xJo+rjPkPyd3FiRTo+cBuT`jh8wD743uuGYsIogWqhn>BVZoo`--mkmrxFNP-v zps2U2PLS{8kJ!%Z+|!6pb_8iJzglo|44;;y{2#1`!l? z;OVgtaRgG?JJ|sB3A#Pk#GSY3`;&0AJ4zN=uN68(mvFsG z9korl&-+|ZdtCUId0#)=b&g9qpRk?o<2EuBVY?PHY+=u@W0%p;PQFMQYO z59g~~4x6tj6^a>kT#u@WC&E8t-$gNrH@U9yX1MU*Sln&`30_n`fPAvD3`cG)N=Du2`7#Av*{)c3Qki`y@&4Q+dLFkcILg!uXGp~sJo zDqKlQkJPXCJ~`-fJ=xbW-sW zSqrd#GSzTryO2&_eEGJ3J4^`DOXzH!G*M#jFfh_;t36Mp7HwI9v~F_ZfL^_)WQ?fy zKjEkAa2gJVlKfBXZS;caF@*Aw%Of8CxNIcx6G~(2I}l1KA904S1mk)DP}iR1N9Okns}2}&hRt%;wOJkYDiyHM0cZDG9Y=iGmB z3#KW0V6KbUcZh(km{?j7pPJh9#d(Ed-Z3y`0V3`Hs1{N2(4pA{?PMo4ZH`#A^-bc>i%b(}Li1Tb8D>uz zT%(o*xtB{B(ajM8e+x6~bHfyrkSJSL7~&L!RyTxJK2fy@>{`I;6gAsbH90 zX4u6YsY-T8#Ef#*MzGpI{{0HA_LA zOJPixl*rq33EAP)^*B66_$A+2qx-Dn`vKn`KyN7zu>ZYW^S6q7zw0f(DmCB`m|*|i z7~@yD=1=iIHW~jt=?|lf-$D6n_g_i>vd#GanSXDb@jFxLFPXn>H2#V5AF71ELm2$u zul^h3Pxt-*i2T)?;x~xf--G<2A^%TI{?M!c9VNdkFaA6Z|6=kl_4VsJ|%a{1dT1Dx1H9QRZ)m{RQnm$o;j_`5W%z-@*NU5C4hRAFuH5SU33_ aUcZ5UQG$l~<80(#+w?E96&%w)j{Xm;W~r6{ literal 0 HcmV?d00001 diff --git a/c_src/erlNpc.cmd b/c_src/erlNpc.cmd new file mode 100644 index 0000000..6c7a1ca --- /dev/null +++ b/c_src/erlNpc.cmd @@ -0,0 +1,4 @@ +@echo off +setlocal +set rebarscript=%~f0 +escript.exe "%rebarscript:.cmd=%" %* diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..c21c2b2 --- /dev/null +++ b/rebar.config @@ -0,0 +1,7 @@ +{erl_opts, [debug_info]}. +{deps, []}. + +{shell, [ + % {config, "config/sys.config"}, + {apps, [ePort]} +]}. diff --git a/src/ePort.app.src b/src/ePort.app.src new file mode 100644 index 0000000..8d6526d --- /dev/null +++ b/src/ePort.app.src @@ -0,0 +1,11 @@ +{application, ePort, + [{description, "An OTP application"}, + {vsn, "0.1.0"}, + {registered, []}, + {mod, {ePort_app, []}}, + {applications, [kernel, stdlib]}, + {env,[]}, + {modules, []}, + {licenses, ["Apache 2.0"]}, + {links, []} + ]}. diff --git a/src/ePort.erl b/src/ePort.erl new file mode 100644 index 0000000..075ce86 --- /dev/null +++ b/src/ePort.erl @@ -0,0 +1,64 @@ +-module(ePort). + +-behavior(gen_server). + + + +-compile([export_all]). + +-define(PORT_NAME, "./priv/tporti"). + +start_link() -> + gen_server:start_link(). + + +control(Port, Data) -> + Port ! {self(), {command, Data}}, + receive + {Port, {data, AnswerData}} -> + io:format("IMY******************111 ~p", [AnswerData]), + AnswerData; + {Port, {exit_status, _Status}} -> + io:format("IMY******************2222 ~p", [_Status]), + erlang:error(port_exit) + after 1000 -> + io:format("IMY******************333 ~p", [no_receive]), + no_receive + end. + +open() -> + Opts = [{packet, 2}, binary, exit_status, use_stdio], + erlang:open_port({spawn_executable, ?PORT_NAME}, Opts). + + +tt() -> + case get(ppp) of + undefined -> + P = open(), + put(ppp, P); + _ -> + ignore + end, + + control(get(ppp), term_to_binary({$g, 12432, 4324})). + +tt(CmdId) -> + case get(ppp) of + undefined -> + P = open(), + put(ppp, P); + _ -> + ignore + end, + case CmdId of + $g -> + control(get(ppp), term_to_binary({CmdId, 12432, 4324})); + $u -> + control(get(ppp), term_to_binary({CmdId, 12432, 4324})); + $t -> + ignore; + _ -> + control(get(ppp), term_to_binary({CmdId, 12432, 4324})) + end. + + diff --git a/src/ePort_app.erl b/src/ePort_app.erl new file mode 100644 index 0000000..fc812c4 --- /dev/null +++ b/src/ePort_app.erl @@ -0,0 +1,18 @@ +%%%------------------------------------------------------------------- +%% @doc ePort public API +%% @end +%%%------------------------------------------------------------------- + +-module(ePort_app). + +-behaviour(application). + +-export([start/2, stop/1]). + +start(_StartType, _StartArgs) -> + ePort_sup:start_link(). + +stop(_State) -> + ok. + +%% internal functions diff --git a/src/ePort_sup.erl b/src/ePort_sup.erl new file mode 100644 index 0000000..a128819 --- /dev/null +++ b/src/ePort_sup.erl @@ -0,0 +1,46 @@ +-behaviour(supervisor). + +-export([start_link/0]). + +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +% 主管的孩子被定义为孩子规格列表 。当主管启动时,将根据此列表从左到右依次启动子进程。主管终止时,它首先以相反的启动顺序从右到左终止其子进程。 +% sup_flags() = +% #{ +% strategy => strategy(), % optional one_for_one | one_for_all | rest_for_one | simple_one_for_one +% intensity => non_neg_integer(), % optional MaxR 周期时间内最大重启次数 +% period => pos_integer() % optional MaxT 重启时间周期 MaxT里重启次数大于MaxR +% } +% child_spec() = +% #{ +% id => child_id(), % mandatory Id用来内部标识子规范 +% start => mfargs(), % mandatory {M,F,A} +% restart => restart(), % optional permanent(总是重启) | transient(异常关闭会重启即关闭原因非 normal,shutdown,{shutdown,Term}) | temporary(不会重启) +% shutdown => shutdown(), % optional brutal_kill | infinity | integer +% type => worker(), % optional supervisor | worker +% modules => modules() % optional [Module] 假如子进程是supervisor、gen_server 或 gen_fsm,那么Module 是回调模块的名称;假如子进程是gen_event,那么Modules 应该是dynamic +% } +init([]) -> + SupFlags = + #{ + strategy => simple_one_for_one, + intensity => 100, + period => 3600 + }, + + ChildSpecs = [ + #{ + id => ePort, % mandatory Id用来内部标识子规范 + start => {ePort, start_link, []}, % mandatory {M,F,A} + restart => transient, % optional permanent(总是重启) | transient(异常关闭会重启即关闭原因非 normal,shutdown,{shutdown,Term}) | temporary(不会重启) + shutdown => 5000, % optional brutal_kill | infinity | integer + type => worker, % optional supervisor | worker + modules => [ePort] % optional [Module] 假如子进程是supervisor、gen_server 或 gen_fsm,那么Module 是回调模块的名称;假如子进程是gen_event,那么Modules 应该是dynamic + } + ], + {ok, {SupFlags, ChildSpecs}}.