From 133d9609195310f1fd43622942b9ced22752e68f Mon Sep 17 00:00:00 2001 From: Serafim Date: Thu, 12 Dec 2024 04:09:30 +0300 Subject: [PATCH] init --- client/client | Bin 0 -> 30896 bytes client/client.cpp | 173 +++++++++++++++++++++ client/run.sh | 2 + compose.yml | 7 + libs.txt | 2 + log/Dockerfile | 5 + log/log | Bin 0 -> 26168 bytes log/log.cpp | 33 ++++ log/run.sh | 2 + log_data/2024-12-12.log | 6 + server1/run.sh | 2 + server1/server | Bin 0 -> 54864 bytes server1/server.cpp | 323 ++++++++++++++++++++++++++++++++++++++++ server2/run.sh | 2 + server2/server | Bin 0 -> 54864 bytes server2/server.cpp | 323 ++++++++++++++++++++++++++++++++++++++++ 16 files changed, 880 insertions(+) create mode 100755 client/client create mode 100644 client/client.cpp create mode 100755 client/run.sh create mode 100644 compose.yml create mode 100644 libs.txt create mode 100644 log/Dockerfile create mode 100755 log/log create mode 100644 log/log.cpp create mode 100755 log/run.sh create mode 100644 log_data/2024-12-12.log create mode 100755 server1/run.sh create mode 100755 server1/server create mode 100644 server1/server.cpp create mode 100755 server2/run.sh create mode 100755 server2/server create mode 100644 server2/server.cpp diff --git a/client/client b/client/client new file mode 100755 index 0000000000000000000000000000000000000000..1fb5a66499770ddf1478fdfc0856bdb0f8a88600 GIT binary patch literal 30896 zcmeHQdwf*YoxhV19ttF=X(L!2L=*+aOvnom8y*)X@-Px&Sqt7wCX-~=$xN8J0|_hJ zxDl7^G`qBQTiV)|e%9{V?ZdRIF0DmFsRp-d!|v9lU0SKDpH2#B%xasu>g@M-9(T^% z%%vrM_MiRaz|HUe9_M#{=XW0Wocs9AC-hD0^IR@XrhM&Ijj)3YIi*H0`a8r4K#f+d z&B9-|c8xX__!LIt{2C6x<>^#jHk>Z#`GAzKgidn6t2kMcP+CZk@;Rk}4{?r!S`o)7 zUjd!E=?{{d{k7mn=5ky@H6JUlM#$TsUsOm!H6Qt=bQ8~4x+5EoiFzL*Axgqdau<<& zBA-v>ldwqmQ$p!avXPEzq1O&e!J{OhJzty1XNT)}Hcdh*gHru#X7fbKs}uRITf_B? zgVaz+*9j=gy94>8tGL94{|a|%TSa+J?Jy+jEukn@yEzIFCCEO&_m-RGdE#KE829qc@hdR=R;Eb!YQKS!IVHTpS| z^iukbL%n_t{hY+oKU9Zu(=UVQ5C}w#`O!FcxeL z#m!)B+vc_5Xe7AJ-xLmVUT)4^TQ=64RfZAh?DTrQWljEgC;*+YP^7gsP;Yv@fi{24 zFk}9Z8LtiK^?v-(s{+yX4u34D*KG`F#$8)3UW0d;QEvpI9bE?LkLz^-sH(3*H7261 z%0SiqrXOl1roiikhJe4r9|)OUdOMUfhwF9|+`?+S&a3a9nC7)SXT4b-j5LRHxm4c@ zH!tIkkHYgoe|zmVV_T`A*H=!^AKo&mPBa2-iGW!P*XsK2ZAN{yQE!%&wnSrl{IO;u zgl^(Dqi9`!D=JrSE(?Sryq49WXxxBF!SdQj$h2x74Wp&jZ>^8k8#?-5pwn+Op}$4o zIy2BlJ+iaY=m^H*(TG0`Pa3;REf)$$Or*P2upY@Uo`I9@xx zljmxYz&5l;g~2;~WDoBeX11SX6)%1`ET{HD%bP)cYddr^*T#ZoTP(U~V*So)vx^?w z7@C`nc+fP$!APsw#zw&+OZsPWCo=PYHEVS-dgS(UNXxqkKK2AX}F*U-`9QG|E7VX$T~!qHYtmBCmn8k_hu zSZ1saqZ&qA2vaxuPhDW^#`2opDM&b}CaD&S^xQ2Hq5QOwp#} zjQ&kUu6!H?*xk%vys0>IF|Cw`a=7r9648H%wT4_5)m`6psfJuX2aWTmX#XVmbs%(| zd=&g?+AD(gZ;#%C6-I&fhQN1?eGV&&DcU;%H*fqjw#fO~jA>F|zBVLyM7bgqnx(<= zV(`g^$3FF0aHne52s|-2G=scylgKak|8n2maXr^tE%x`4USG!PH8y&wke}Yj`BGlu z0|uwV2(}mGn5Laj=rbh|a7dxkzEP%A3Vn_w0-jOmixhfFp)XbFBMRN4(8m4?&)(9zIV>Q?ByXK~g6g^s17l@2O& zDqE&Q3Z2?Oro#$dbOpwGM4`*JBu2kNM+dUf5ruwqlQt0BA9^)1%^bafY zB?`Snp}Q6Ol?r{4LKnCG7`IfR&r{^975Y^Qy+)ybM4|f>`qc`(PN83;(6=jew?c1J z=<^kNn?hIjNgWD(fg<0j(63YI-3oo7LO-C;#ni*N2Nn8_iu@skev?8!tk4%L^hXpr z?ImUESLioOBH$5)UaHV1PbWPv>48ZPOnP9_1Ct(@^uVMCF3to0U3m37zMgZ_eaV8K zeH4$K_YatP=^BW^um<@h1X~#-$tC#;a{cG>4OZXjn?S!Neib9 z*68pt3#X0M=y3QESxq(qr-2$FY8MiA=KZ( zX`_t#TR3fqP=5=jjS%W@;j{rl{Vkj}KB&Ki(}oB2w{Y6%p#Bz48ywW%!f9iJ`dc_{ zXi$F(r;QBiZ{f6oLH#Y9HZG{Yh0}%w^|$bA82;vavi@#{|H{H?V}klyIBiH!e+#FL z2wBb8#c!Le! zY{PXMzRHGI*zlz)?mb`Id-85y?<>BZS4Zl$>D~eFbH2V+S7KUC7cYS1TP>c#Ywky< z$AsOt$`6XKui!2M%g4-OOyyJQ98>v>^qInIx=HT1fROhx`HGte-1xq)cf@z>^^f|F zjph4X&-zZjZ(acfKV8lhOi!O_VdF^Vr}@5n)hY}xEwQ-4*RyIbBsE{}YvxQ}a@7++ zQeE$+)2U`mp3fE(L(a7md9Cs(|L`6#>7)VqeD|H}XBv)f2esLkoU)LHx358jM+s(zw5M3hQU&VJztDfT5B#+rSLuV7Z11*v<$ zdhWPYo1Sx}zTSPO#??bVg-Yn>d`bOOw)sDXfl2)wH<~V_zP^emCU}&pfi(fVsJ+I;l#?isl23)Pq9+d{v!=DGBMKvG=M-J}qL_I0_2K8CwI*k?&_7)zT!_Zh0JA#VAlNu<|R*((}rKfC7fyL zD{jxom`tYd{`sil_et(4s_WCVd`R`YlTP;*Bw$F(px&RSB@6sGFZ|~L*s%e;mR|k4 zFyaToh{r%86T|<5Z2Du#f|XQ-zRmsLr;D|(_eJt2c>4zm9~^*PLF7I6Vd79#DoGd; zvmt@%KZ-leqWZUh@-%g|R36Tf#jk?ZTZG>E2s*+esL}yn?@3=@@lteyry$1EOoK;; zU&1N|s=sO#a*}BsOnsf1dOWr3_pE0RrcU96?C5$j=kA*ho^aonM7t-L34^JnD2=&~ZnoRpcMLMB z`~K@gWF)!ocX$Fs?)wR8Nfvi7l$rP*DBOL=afUGk7IWWWxbJYreXqm0mitanl|P3? zAyhY6g?w5R@~2ct@9|XGm~h|caU$Heg&Xh&o@j{nyBCzETEU@P@6ko#$W;I62qm$vSq5U<(E`+viK93@@7(b|A`I*+utrG zGsr-_t8BBeSWRk_znPQ&-W%xnt8z6tmlK&ea-^%5u zXXO8uE<<4ZjVkzJhO{qP#cym_dUnH@EK?p2LayY$5wT z!s}CI$(IQE5mJQuXXLLY`SX~x#oXS&@-Vj_!X^##>@Hq`XOJ~n{0-z}6*!0r97LXO zZv9i}WR~^+!mJ|JV9LWyAGu7L-p9%wOa-|qQ!}P~29)8Zj43Bs9%jlcW=i4xe@WAG zlKX|6dz(a1(yOFUxk&aEeAX(oL=-ym7Oy{^Kgjl{LeG=hz5>&dPcZ?sKbQAsA_^T5ugl-xy=4y5Z(`uP%)D<^+I?t7k)k?{3j&57{V`D!q*Go_y3#K_$wLVB@lj+uF|ZFM7zcKg1dDf6rot{3N3drhZHY^y$AQ3*KPjbWXBQ7Evym{y!|# zh4{#4viV%~{g&!c=5tbAEmU_Xsvpc!-Ds&kEm~@}qWTe*ui!>Y^*>vxf3cKo8cY>K zZV(f4O_!eHu4$a8j<#D+(3-yzeU$TLb*7&ldQ4^byyy`Ww`bPchqE z=o}s6867?hWRc3}5oHJVX88 zhioU{o&jHP!x8(|Ai47d3I}^I^&&L-dXE7;LVdXRMOu^A!vDUWeFGY8Eir9Dt_!H;@(!lnMz_q2Sy9RocG+TM_FJUe)|0MeH0nv&H509s z)O>*<LPNt^f=Z9@Uqf{dd|63FJPyc`ghv&^`b-eW$m<{Co=0( z*-c}@Q&|eLTIL8!bmsmxi!0j)9#8bER?)VN8UhvWMf3FWCMqP?WByC({hTud&Jgo8 zs{vZ=l;4Ne-qSrfHW=Mhzn(=T|_=WTMushA&Z@1Zvojk2DY$y+= z?nd=#VAEX)p6}hWOcj$9q!0-)iNRDml|&PQEDXEUpQKuO`D&(S=pk<_*Mya4%lRc_ zFg2Bx!khFqWKL20iR(-1^Q;UQG?@A_@vbC1t3OI7vMEgMl-z;v1KdLWotJP98#g{g z1~|v+ZvRT0<;M#j0wa46Jj^V#4T4f?IJG=>ONtlrm#mO+^Tk70h{Fx&O4;+pI_S^z z3UrDK>0V5_Lj&5sd|@SZe)N4D)^s+*p@?7oCaVa#81(EL)3PsEpemOyk`dFYZ?O&z zyI&6Lre~f2(P)}XlOCA#z@!HzJ@Eg{1N3&ini}H%*5HauW{8g;wz!wN#i`qjy3Mwr zJ06Vf4#qB-fsarWp$z73iACG9Bqtd1e>!9cYC$<_`rgbWo0#SQs$VeOv}{S ztF5!V5p34#nTy<^xH}RxrT;+BWGG`Ffq1pe!8kdbTw^j)nZ`Wf)wYpC-2B6lW==#V z)LXJ*!S?8GDCL5ptXLuvf!~;5nbr`wClcKgfd%dDetdI+q<)FGVg-F4CBJ8LM-t&M zGk7;XhiTTlWmTS1{PSwAdHE~d*yJrh{&#B)fJ*?+ z0}cURhOO`jU^ie9_D_caO97t%tOMMO+Yg<9Ujn3WT%QA^UD#aQ$T$U94LAmPCtwL~ zXAcA30(cTPjdlR00q+GY$IZ5f0K0G(@<)Jl$2J9c8*Xk*huz--Tm*QWZgv5l1Z)Gu zja-&od$($?&LY>mnbW2pM16=(uUjm7C7q_%8nkuOaPJ234RDm>ID8uZK)tltMeApm z+*Ww$p6T7%N9V4%Y1wtxg39vm09^EPI_)NcNTk=qQ40ED$}bX?^+_BL!r!+NO`l!# zK;GI}Qxh-r`1h%NoRjU8Tzl&_F)vU1qJN&I&6B<+pVILb@?M79=~L#R z!Dan@J^A^r8LSM_(~mNWVdFxaTQWN`br=GFF8J*#Kd;%!KLUOm`1ERwmH*C6{vxyq z@pJi@Y$PAw4gPV!DGxwc+Nt;C=RKa$L*GZg1Gxo|vt;hd@H@eO5Bw!6Kak-c0)GbX zRotQS^L$Kz{BQ*P72sd3@*6VwPk~?Uz;`3h82FXoe@4wub=aTLaTS{3YmiB)GI=js zHrxV!JH|QgS7z!M%;etz{-1$gq4L9=PrfXH4F|!eZ@Z`5jz5Yo^Q&A;&<(kVq32te zFA}OAvb8l+)(ObG51AdROkO<`Ab+L6UxB$Lkj3W>Lj37dG;JUFcvP6NV{=CTBJktj z&sO<*hVKL45B^-0e+TDNU8kV@>xa|nE~;x%DFgM$zlYbA>^KNLd$1wAQq@z(^$;nY zb``G2qvXA#g~M~SFV6`v((Gj@_v4w`K0`She3XbJzKge4k*^_Y61Ct*3f8YW6-KzXfReqN$Cj$EB zmXgHj8(kHrZ)hpaWRDL&$>pV+r@q{xrKLX0{WNFT$L~9&M zZ@-_8670u(Nr}&9_*NI|0!qRRHlGttuMAVF#A8@W^vW86tF|UZUGMpcv!%G0S5%++CTW;>5W{+jSDpGCLHKLEJ@9X9ufe|LfNNzq~5f{hnSa>~SI&=4{`nB{xv+bD zYXi%k^(U7-Jl@{rnvBOMGgL7>C7OLa*D(5(*8C^s?*v^;agxMf+=0Fybc(}tSopy$ za(&T3{xQ(6g&*Et&IRRlfc5}HKTn%#q&qm!ZUemtSBpiBf*`;hpy#r)*@6Cq1O0i> zsoa4wu6VxCe*+fyZn{b}3W5NaqJQTqm-a}x=w8t05T}MKkn?p7=v40ZDo&SitsZgE z^Na)iawxo3*royx=(+4!&FDqii5s{y?XxMZcaZO6`inGr(UcO~djXzykVmIw{h_;w ziNl9HornCKyt$g3rvzDh$3YM6MdrZ&MU7k%Vl35yJ|BAAjU1QP-5}_>>ieVv{Z$A0 z`$W&1qses)F9mY|797-Gb7&$$TF8O6M9@!){>=7`;N1y&E_>n*^yh@0W1|1F`vK5X zf`vvdJxf3*dm^ITfUxIBg8r*APAC-ga}IiLfdk3US2c1$>F150=PI`ubSigNC6`YL z{f`U!!@@u8z6yAYF^(>Syo^VCy^w#;LH}y>$6V#sJJ2ag3)!=yf-9EmtQlAk=F)Su z1AV0f{SfG+-(IgXf?g@=%kDG5gc(?P<|_AE2YSqb{u2lKZ-}0U)wf$XQh*WAX?!he z%%;EVpyzg|pnB~Ue*28bb`P??ggFfENSHBNjsB5{>x$>SisrZF$evp9q8{0 zJ$C=E!Ty29&qVQJ){U3#$l70;uC0D%3a?nYS-Oqn2=wYGfR-r!$x?8QNIRAnJ z{V~w-e_VRjfj;+gZqM6dUiFBat)S=9qtypurq>fioH2h>h{Y-dA#NsGT08+Q6Y$b7 z+YQ7riv;74Y>pbO;b;>@heLqFxZzK9;yGD+M>uE(n-N+pr-Xs{Y9YfPi}||@JmrdY zX)Q5-d(dc3w6}L5i-H-DL{KwDG!PCUk0;R4!NSCCsy2*Jl%#-`ds&P$6XD{B5~3h( zEOwfKXI%*5hS+Kd(}-AVMrkOd85=g;zGn3%WJxp`wT5w*x3pg0dZ)hCsIBv^sbGOR zVa@ujt2gV0zGWT7{xlGU+0cE0=v%i{GuHjdmereU*IMdsU%$RyM_kF(Yc}bWBRh&) z4GXG<$Y~TLjYWLRqGTCSW*H%)ViN}!XU*66+!T9)tg9IN;L|qT73#iXT{vJm-ENiTq+Zc zU+b+6@7DFL8@CxOzF(F;8I&)JXw=@0hVji&(iV;VmGomnLL58o2`)q`WV6#XNM#%3+{qr11xH0mK>rQ zhvEjkEMRnCDn_*1S_*{QREME7E=p!rp%ZcZxQL``4XG7abIQIG{J?!jy!K()O%u0T zL>bM$Vp>F`)wpSdaQ&;z>XzeXOF8kBV&>7&lW7*s(Aabu-qcj8Z)(ECT8VK8y{HKn z6w|Gakg3$sz3AvHj4=gH&CJ!9?xj_DeFJaU)P^%N^h6x51b?=>oL`g;9`>{hjZP7Z zdEC?Se)D?GHuM)BT6H-Km}($Ya;}C#G-ayc_{&dLg)cU$HYQyq7_123JE0K8svqEd zge%UXSP@yrJ3;hM?=q{ASQB4Fud(+AxM_JXLSe{_P)qIhcnrEQR%mF-GSE+Sy@K@y z9Wko)a<&SPeW=umzRO~AE0-07g{7XQMy1ZGC+l_}tQ9gLc~#BUaQ%wkvDW_a?!1TL=Duo-u`n3&rf0=kcLn=M+f)dexv^X0OE(Dia%JCXUon-zF^ zT=~jW)E>$;xcLQ{% z>hbl%LWkmPs|+?wtSO+sJFcL(B?7ONE?>ZFR z9jv3E*R-_fL9emS#~Xwb>ckYlUGJe651lmLrq&1JA#q7{k=3U2Le5EeVw8jW>b zc+*ogP9BRGwuWIBDG~c!ne0%Y`0}y!Y%XjsL-bEdE5s|Jt%~J*9%Zs!IJt8T}JlAklC@D`63Y z-DUP7h{ni;mp*^cXVy;df2W%7SG|{pP82ed+x{dgO1Mafy8O6Sp z)HF}LtKIZB0h%!m+vFMBUv+36yhk4NV5jEkh(+;BAZC|BYD$FgGi7*Vn@b_M|5Ezt z5hmW|kGE-_=B@~e;Lwb54&LF9)9(y0F@YH1#e!i!We{f_VN>(46@&+;p4KQ(I*A7Z zng>610F>_UK|0EA19^gN;*MS$ewx6-Pz-*PAlMlQc9^)?NWY%LwDOyMT!%bI;r{jz z)N_THo;43G8R!-H51i;dA{UN4p{XRFpGYX*BNA*TE6)ki{d7DEv+`Gq{1TRukdpA2 zDl5_LSv7x~$S>h_S<>|GKz6FN<(KbENa)TMAD91Q;Nz9{sI0$yKT1OJnAUnf%5J|O z`SD1|s((t@FCo1fPl@VCewO*=dsHFND2ps#zK zgfJe5vLwrq@XtY|ccmmQ-4txHuf<{G1{hAvHB{%zvCrjDM-hUnfTg~rwb9o8bw+M;~Jf>ku z!hZm!<{!G2^Cfh1)cPy)N!SmLntw#(m+-K3tk59yN%%cme)(Kj!cSab70pg$K1qGr zmR~-nmk^H~vy$C^&xrh%nKeRO!0Rjqr_1&eQrZhRq54ZP`M!+>iK!%e`Tq%?n%}pU z3rpB<%V016HCz6%4LrYuG(Od2Q>Xn7OnSyChQ0N^ll*;6yT4`m66V8rJX*B!%lE5l zHt|xW9LF;KU(ySapZdNmU%r +#include +#include +#include +#include +#include +#include +#include +#include + +// IP address of the server1 +std::string SERVER_IP1 = "127.0.0.1"; + +// Port of the server1 +int PORT1 = 9001; + +// IP address of the server2 +std::string SERVER_IP2 = "127.0.0.1"; + +// Port of the server2 +int PORT2 = 9002; + +int client_socket1 = -1; +int client_socket2 = -1; + +void* recieve(void* arg) { + int client_socket = *(int*)arg; + delete (int*)arg; + + while (true) { + char buffer[128]; + ssize_t recieved = recv(client_socket, buffer, sizeof(buffer), 0); + if (recieved == 0 || recieved == -1) { + break; + } + std::cout << buffer << std::endl; + } + + return nullptr; +} + +void* timer(void* arg) { + int client_socket = *(int*)arg; + delete (int*)arg; + + while (true) { + send(client_socket, "", 1, 0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + return nullptr; +} + +int main() { + pthread_t t1 = -1, t2 = -1; + + std::cout << "Usage:\n\tconnectN - connect to the server\n\tdisconnectN - disconnect from the server\n\tsendN - send request to the server\n\ttimerN - begin polling of the server\n\tstopN - stop polling of the server\n\tquit - quit" << std::endl; + + while(true) { + std::string command; + + std::cin >> command; + + if(command == "quit") { + break; + } else if (command == "connect1") { + client_socket1 = socket(AF_INET, SOCK_STREAM, 0); + sockaddr_in server_address1; + server_address1.sin_family = AF_INET; + server_address1.sin_port = htons(PORT1); + server_address1.sin_addr.s_addr = inet_addr(SERVER_IP1.c_str()); + if (connect(client_socket1, (struct sockaddr*)&server_address1, sizeof(server_address1)) == 0) { + std::cout << "Connected to the server 1" << std::endl; + pthread_t tid1; + int* client_socket_copy1 = new int(client_socket1); + pthread_create(&tid1, nullptr, &recieve, client_socket_copy1); + } else { + std::cout << "Failed to connect " << std::strerror(errno) << std::endl; + } + } else if (command == "connect2") { + client_socket2 = socket(AF_INET, SOCK_STREAM, 0); + sockaddr_in server_address2; + server_address2.sin_family = AF_INET; + server_address2.sin_port = htons(PORT2); + server_address2.sin_addr.s_addr = inet_addr(SERVER_IP2.c_str()); + if (connect(client_socket2, (struct sockaddr*)&server_address2, sizeof(server_address2)) == 0) { + std::cout << "Connected to the server 2" << std::endl; + pthread_t tid2; + int* client_socket_copy2 = new int(client_socket2); + pthread_create(&tid2, nullptr, &recieve, client_socket_copy2); + } else { + std::cout << "Failed to connect " << std::strerror(errno) << std::endl; + } + } else if (command == "disconnect1") { + if (client_socket1 != -1) { + close(client_socket1); + client_socket1 = -1; + std::cout << "Disconnected" << std::endl; + } else { + std::cout << "Server is not connected" << std::endl; + } + } else if (command == "disconnect2") { + if (client_socket2 != -1) { + close(client_socket1); + client_socket2 = -1; + std::cout << "Disconnected" << std::endl; + } else { + std::cout << "Server is not connected" << std::endl; + } + } else if (command == "send1") { + if (send(client_socket1, "", 1, 0) == -1) { + std::cout << "Server is not connected" << std::endl; + } else { + std::cout << "Message sent" << std::endl; + } + } else if (command == "send2") { + if (send(client_socket2, "", 1, 0) == -1) { + std::cout << "Server is not connected" << std::endl; + } else { + std::cout << "Message sent" << std::endl; + } + } else if (command == "timer1") { + if (client_socket1 != -1) { + int* client_socket_copy1 = new int(client_socket1); + pthread_create(&t1, nullptr, &timer, client_socket_copy1); + pthread_detach(t1); + std::cout << "Timer created" << std::endl; + } else { + std::cout << "Server is not connected" << std::endl; + } + } else if (command == "timer2") { + if (client_socket1 != -1) { + int* client_socket_copy2 = new int(client_socket2); + pthread_create(&t2, nullptr, &timer, client_socket_copy2); + pthread_detach(t2); + std::cout << "Timer created" << std::endl; + } else { + std::cout << "Server is not connected" << std::endl; + } + } else if (command == "stop1") { + if (t1 != -1) { + pthread_cancel(t1); + t1 = -1; + std::cout << "Timer removed" << std::endl; + } else { + std::cout << "Timer is not running" << std::endl; + } + } else if (command == "stop2") { + if (t2 != -1) { + pthread_cancel(t2); + t2 = -1; + std::cout << "Timer removed" << std::endl; + } else { + std::cout << "Timer is not running" << std::endl; + } + } else { + std::cout << "Unknown command" << std::endl; + } + } + + if (t1 != -1) { + pthread_cancel(t1); + } + + if (t2 != -1) { + pthread_cancel(t2); + } + + close(client_socket1); + close(client_socket2); + + return 0; +} \ No newline at end of file diff --git a/client/run.sh b/client/run.sh new file mode 100755 index 0000000..b63712d --- /dev/null +++ b/client/run.sh @@ -0,0 +1,2 @@ +g++ -o client client.cpp +./client \ No newline at end of file diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..dcb4c75 --- /dev/null +++ b/compose.yml @@ -0,0 +1,7 @@ +services: + log: + build: + context: ./log + volumes: + - &log_data ./log_data:/log_data + - &tmp ./tmp:/pipe diff --git a/libs.txt b/libs.txt new file mode 100644 index 0000000..225e3a8 --- /dev/null +++ b/libs.txt @@ -0,0 +1,2 @@ +libncurses5-dev +libncursesw5-dev diff --git a/log/Dockerfile b/log/Dockerfile new file mode 100644 index 0000000..2a7dee2 --- /dev/null +++ b/log/Dockerfile @@ -0,0 +1,5 @@ +FROM frolvlad/alpine-gxx +COPY . /app +WORKDIR /app +RUN g++ -o log log.cpp +CMD ["./log"] diff --git a/log/log b/log/log new file mode 100755 index 0000000000000000000000000000000000000000..07aac05a7847029169e7cbb17dd99972ce55840f GIT binary patch literal 26168 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 H!Lt7a-l(Io literal 0 HcmV?d00001 diff --git a/log/log.cpp b/log/log.cpp new file mode 100644 index 0000000..4144e56 --- /dev/null +++ b/log/log.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +std::string LOG_DIR = "/log_data"; + +void log(std::string msg) { + mkdir(LOG_DIR.c_str(), 0755); + time_t now = time(0); + struct tm tstruct; + tstruct = *localtime(&now); + char filename[12]; + std::strftime(filename, 12, "%Y-%m-%d", &tstruct); + std::ofstream log_file; + log_file.open(LOG_DIR + "/" + filename + ".log", std::ios_base::app); + char timestamp[32]; + std::strftime(timestamp, 32, "%Y/%m/%d %H:%M:%S ", &tstruct); + log_file << timestamp << msg << std::endl; + log_file.close(); +} + +int main() { + log("uwu"); + log("owo"); + log("yay"); + + return 0; +} \ No newline at end of file diff --git a/log/run.sh b/log/run.sh new file mode 100755 index 0000000..84055e5 --- /dev/null +++ b/log/run.sh @@ -0,0 +1,2 @@ +g++ -o log log.cpp +./log \ No newline at end of file diff --git a/log_data/2024-12-12.log b/log_data/2024-12-12.log new file mode 100644 index 0000000..c34ba05 --- /dev/null +++ b/log_data/2024-12-12.log @@ -0,0 +1,6 @@ +2024/12/12 00:24:34 uwu +2024/12/12 00:24:34 owo +2024/12/12 00:24:34 yay +2024/12/12 00:24:50 uwu +2024/12/12 00:24:50 owo +2024/12/12 00:24:50 yay diff --git a/server1/run.sh b/server1/run.sh new file mode 100755 index 0000000..2ce05b3 --- /dev/null +++ b/server1/run.sh @@ -0,0 +1,2 @@ +g++ -o server server.cpp -lncurses +./server \ No newline at end of file diff --git a/server1/server b/server1/server new file mode 100755 index 0000000000000000000000000000000000000000..aa7bfcde292d1ebc0d01fd3bdb1801f6315da787 GIT binary patch literal 54864 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 NiGkxBTLl}+{vQQ-%V_`r literal 0 HcmV?d00001 diff --git a/server1/server.cpp b/server1/server.cpp new file mode 100644 index 0000000..55d3eac --- /dev/null +++ b/server1/server.cpp @@ -0,0 +1,323 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Configuration */ + +// Name of the pipe used to transfer logs to the log server +std::string LOG_FIFO_NAME = "./tmp/log"; + +// Type of the server: server1 - last error & cursor position, server2 - mem % & vmem % +std::string SERVER_TYPE = "server1"; + +// Port to run server +int PORT = 9001; + +// Maximum amount of socket connections +int MAX_CONNECTIONS = 128; + +// Amount of log messages displayed on screen +const int CMD_LOG_BUFFER = 10; + +// Amount of milliseconds between screen rerenders +int CMD_REFRESH_TIME = 500; + + +/* Current status to display */ + +// Buffer with recent log messages +std::string last_log_messages[CMD_LOG_BUFFER]; + +// Amount of active client sessions served by different threads +int active_connections = 0; + +// Total amount of handled requests +int handndled_requests = 0; + +// Amount of active timers for sending messages +int active_timer_threads = 0; + + +// Initializes ncurses lib +void init_ncurses() { + initscr(); + cbreak(); + noecho(); + clear(); +} + +// Returns info about last error +std::string get_last_error() { + const int error_code = errno; + const char* error_description = std::strerror(errno); + return "Last error: " + std::to_string(error_code) + " - " + error_description + "\n"; +} + +// void disable_buffering() { +// struct termios t; +// tcgetattr(STDIN_FILENO, &t); // Get the terminal settings +// t.c_lflag &= ~ICANON; // Disable canonical mode (no buffering) +// t.c_lflag &= ~ECHO; // Disable echo (no terminal output) +// t.c_cc[VMIN] = 1; // Set the minimum number of characters to read (1 char) +// t.c_cc[VTIME] = 0; // Disable timeout +// tcsetattr(STDIN_FILENO, TCSANOW, &t); // Apply the new settings +// } + +// void restore_buffering() { +// struct termios t; +// tcgetattr(STDIN_FILENO, &t); // Get the terminal settings +// t.c_lflag |= ICANON; // Enable canonical mode (buffering) +// t.c_lflag |= ECHO; // Enable echo +// tcsetattr(STDIN_FILENO, TCSANOW, &t); // Apply the restored settings +// } + +// Returns info about current cursor position in console +std::string get_cursor_position() { + int x, y; + + // // Disable buffering + // disable_buffering(); + + // printf("\033[6n"); // Request cursor position + // scanf("\033[%d;%dR", &x, &y); // Read cursor position + + // // Print the cursor position + // printf("Cursor position: (%d, %d)\n", x, y); + + // // Restore the terminal settings + // restore_buffering(); + + getyx(stdscr, y, x); + + return "Cursor position: y: " + std::to_string(y) + " x: " + std::to_string(x) + "\n"; +} + +// Returns info about used physical memory +std::string get_mem_percent() { + std::ifstream meminfo("/proc/meminfo"); + if(!meminfo) { + return "Error: failed to open /proc/meminfo\n"; + } + + std::string line; + long free_mem = -1, total_mem = -1; + + while((std::getline(meminfo, line))) { + if(line.find("MemAvailable:") == 0) { + std::sscanf(line.c_str(), "MemAvailable: %ld kB", &free_mem); + } else if(line.find("MemTotal:") == 0) { + std::sscanf(line.c_str(), "MemTotal: %ld kB", &total_mem); + } + + if(free_mem != -1 && total_mem != -1) { + break; + } + } + + meminfo.close(); + + if(total_mem == -1 || free_mem == -1) { + return "Error: failed to read info from /proc/meminfo\n"; + } + + return "Physical memory: " + std::to_string(100 * (total_mem - free_mem)/total_mem) + "%\n"; +} + +// Returns message to send according to the server type +std::string get_sysinfo() { + if (SERVER_TYPE == "server1") { + return '\t' + get_last_error() + "\t\t\t" + get_cursor_position(); + } + return '\t' + get_mem_percent() + "\t\t\t" + "WIP\n"; // TODO: vmem +} + +// Writes log message on screen and passes it to the logging pipe +void log(std::string msg) { + // Add log message to the screen buffer + for (int i = CMD_LOG_BUFFER - 1; i > 0; i--) { + last_log_messages[i] = last_log_messages[i-1]; + } + time_t now = time(0); + struct tm tstruct; + tstruct = *localtime(&now); + char timestamp[32]; + std::strftime(timestamp, 32, "%H:%M:%S ", &tstruct); + last_log_messages[0] = timestamp + std::string(" ") + msg; + + // Write message to the logging pipe TODO + // int fd = open(LOG_FIFO_NAME.c_str(), O_WRONLY); + // if(fd != -1) { + // write(fd, msg.c_str(), strlen(msg.c_str()) + 1); + // close(fd); + // } +} + +// Opens file descriptor for logging pipe TODO +void init_log_pipe() { + // mkfifo(LOG_FIFO_NAME.c_str(), 0666); +} + +// Returns file descriptor for server socket +int start_socket() { + log("Creating socket..."); + + int server_socket = socket(AF_INET, SOCK_STREAM, 0); + sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_port = htons(PORT); + server_address.sin_addr.s_addr = INADDR_ANY; + + bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)); + + if (errno == 98) { + log("Error: " + std::string(std::strerror(errno))); + return -1; + } + + log("Socket created"); + + int status = listen(server_socket, MAX_CONNECTIONS); + + if (status != 0) { + log("Error: can't listen with socket"); + return -1; + } + + log("Listening for connections..."); + + return server_socket; +} + +// Handles one connection in sepparate thread +void* handle_connection(void* arg) { + // Cast client socket descriptor + int client_socket = *(int*)arg; + delete (int*)arg; + + std::string info = ""; + + log("New thread created for socket " + std::to_string(client_socket)); + + while (true) { + // Recieve message from client + char buffer[5]; + ssize_t bytes_recieved = recv(client_socket, buffer, sizeof(buffer), 0); + + // If connection closed + if (bytes_recieved == 0) { + log("Connection with client " + std::to_string(client_socket) + " closed"); + active_connections--; + break; + } + + if (bytes_recieved == -1) { + log("Error while recieving message: " + std::to_string(errno) + " - " + std::strerror(errno)); + break; + } + + log("Got new message from client " + std::to_string(client_socket) + ": " + buffer); + + std::string new_info = get_sysinfo(); + + if (info != new_info) { + log("Client " + std::to_string(client_socket) + " info is not up to date"); + info = new_info; + time_t now = time(0); + struct tm tstruct; + tstruct = *localtime(&now); + char timestamp[32]; + std::strftime(timestamp, 32, "%Y/%m/%d %H:%M:%S ", &tstruct); + std::string msg = timestamp + info; + send(client_socket, msg.c_str(), strlen(msg.c_str()) + 1, 0); + log("Sent new info to client " + std::to_string(client_socket)); + } else { + log("Actual info already on client " + std::to_string(client_socket)); + } + } + + close(client_socket); + + return nullptr; +} + +// Refreshes console output +void* draw(void* arg) { + while (true) { + // Update info + clear(); + + // Print configuration + printw( + "LOG_FIFO_NAME=%s\nSERVER_TYPE=%s\nPORT=%i\nMAX_CONNECTIONS=%i\nCMD_LOG_BUFFER=%i\nCMD_REFRESH_TIME=%i\n\n", + LOG_FIFO_NAME.c_str(), SERVER_TYPE.c_str(), PORT, MAX_CONNECTIONS, CMD_LOG_BUFFER, CMD_REFRESH_TIME + ); + + // Print statistics + printw("Active connections: %i\nHandled messages: %i\nActive timers: %i\n", active_connections, handndled_requests, active_timer_threads); + + // Print logs + for (int i = CMD_LOG_BUFFER-1; i >= 0; i--) { + printw("\n%s", last_log_messages[i].c_str()); + } + + refresh(); + + // Wait to update again + std::this_thread::sleep_for(std::chrono::milliseconds(CMD_REFRESH_TIME)); + } +} + +int main() { + init_ncurses(); + init_log_pipe(); + + // Create thread to redraw console output + pthread_t tid; + if (pthread_create(&tid, nullptr, &draw, nullptr) != 0) { + std::cout << ("Failed to create drawing thread") << std::endl; + // endwin(); + return 2; + } + pthread_detach(tid); + + int server_socket = start_socket(); + + while (true) { + int client_socket = accept(server_socket, nullptr, nullptr); + + if (client_socket == -1) { + continue; + } + + log("New connection accepted"); + active_connections++; + + // Create thread for each connection + int* client_socket_copy = new int(client_socket); + pthread_t tid; + if (pthread_create(&tid, nullptr, &handle_connection, client_socket_copy) != 0) { + log("Failed to create thread for the connection"); + delete client_socket_copy; + } + pthread_detach(tid); + } + + return 0; +} diff --git a/server2/run.sh b/server2/run.sh new file mode 100755 index 0000000..2ce05b3 --- /dev/null +++ b/server2/run.sh @@ -0,0 +1,2 @@ +g++ -o server server.cpp -lncurses +./server \ No newline at end of file diff --git a/server2/server b/server2/server new file mode 100755 index 0000000000000000000000000000000000000000..93968c30b8cbefb350efbd31d07ff7944d867acc GIT binary patch literal 54864 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Configuration */ + +// Name of the pipe used to transfer logs to the log server +std::string LOG_FIFO_NAME = "./tmp/log"; + +// Type of the server: server1 - last error & cursor position, server2 - mem % & vmem % +std::string SERVER_TYPE = "server2"; + +// Port to run server +int PORT = 9002; + +// Maximum amount of socket connections +int MAX_CONNECTIONS = 128; + +// Amount of log messages displayed on screen +const int CMD_LOG_BUFFER = 10; + +// Amount of milliseconds between screen rerenders +int CMD_REFRESH_TIME = 500; + + +/* Current status to display */ + +// Buffer with recent log messages +std::string last_log_messages[CMD_LOG_BUFFER]; + +// Amount of active client sessions served by different threads +int active_connections = 0; + +// Total amount of handled requests +int handndled_requests = 0; + +// Amount of active timers for sending messages +int active_timer_threads = 0; + + +// Initializes ncurses lib +void init_ncurses() { + initscr(); + cbreak(); + noecho(); + clear(); +} + +// Returns info about last error +std::string get_last_error() { + const int error_code = errno; + const char* error_description = std::strerror(errno); + return "Last error: " + std::to_string(error_code) + " - " + error_description + "\n"; +} + +// void disable_buffering() { +// struct termios t; +// tcgetattr(STDIN_FILENO, &t); // Get the terminal settings +// t.c_lflag &= ~ICANON; // Disable canonical mode (no buffering) +// t.c_lflag &= ~ECHO; // Disable echo (no terminal output) +// t.c_cc[VMIN] = 1; // Set the minimum number of characters to read (1 char) +// t.c_cc[VTIME] = 0; // Disable timeout +// tcsetattr(STDIN_FILENO, TCSANOW, &t); // Apply the new settings +// } + +// void restore_buffering() { +// struct termios t; +// tcgetattr(STDIN_FILENO, &t); // Get the terminal settings +// t.c_lflag |= ICANON; // Enable canonical mode (buffering) +// t.c_lflag |= ECHO; // Enable echo +// tcsetattr(STDIN_FILENO, TCSANOW, &t); // Apply the restored settings +// } + +// Returns info about current cursor position in console +std::string get_cursor_position() { + int x, y; + + // // Disable buffering + // disable_buffering(); + + // printf("\033[6n"); // Request cursor position + // scanf("\033[%d;%dR", &x, &y); // Read cursor position + + // // Print the cursor position + // printf("Cursor position: (%d, %d)\n", x, y); + + // // Restore the terminal settings + // restore_buffering(); + + getyx(stdscr, y, x); + + return "Cursor position: y: " + std::to_string(y) + " x: " + std::to_string(x) + "\n"; +} + +// Returns info about used physical memory +std::string get_mem_percent() { + std::ifstream meminfo("/proc/meminfo"); + if(!meminfo) { + return "Error: failed to open /proc/meminfo\n"; + } + + std::string line; + long free_mem = -1, total_mem = -1; + + while((std::getline(meminfo, line))) { + if(line.find("MemAvailable:") == 0) { + std::sscanf(line.c_str(), "MemAvailable: %ld kB", &free_mem); + } else if(line.find("MemTotal:") == 0) { + std::sscanf(line.c_str(), "MemTotal: %ld kB", &total_mem); + } + + if(free_mem != -1 && total_mem != -1) { + break; + } + } + + meminfo.close(); + + if(total_mem == -1 || free_mem == -1) { + return "Error: failed to read info from /proc/meminfo\n"; + } + + return "Physical memory: " + std::to_string(100 * (total_mem - free_mem)/total_mem) + "%\n"; +} + +// Returns message to send according to the server type +std::string get_sysinfo() { + if (SERVER_TYPE == "server1") { + return '\t' + get_last_error() + "\t\t\t" + get_cursor_position(); + } + return '\t' + get_mem_percent() + "\t\t\t" + "WIP\n"; // TODO: vmem +} + +// Writes log message on screen and passes it to the logging pipe +void log(std::string msg) { + // Add log message to the screen buffer + for (int i = CMD_LOG_BUFFER - 1; i > 0; i--) { + last_log_messages[i] = last_log_messages[i-1]; + } + time_t now = time(0); + struct tm tstruct; + tstruct = *localtime(&now); + char timestamp[32]; + std::strftime(timestamp, 32, "%H:%M:%S ", &tstruct); + last_log_messages[0] = timestamp + std::string(" ") + msg; + + // Write message to the logging pipe TODO + // int fd = open(LOG_FIFO_NAME.c_str(), O_WRONLY); + // if(fd != -1) { + // write(fd, msg.c_str(), strlen(msg.c_str()) + 1); + // close(fd); + // } +} + +// Opens file descriptor for logging pipe TODO +void init_log_pipe() { + // mkfifo(LOG_FIFO_NAME.c_str(), 0666); +} + +// Returns file descriptor for server socket +int start_socket() { + log("Creating socket..."); + + int server_socket = socket(AF_INET, SOCK_STREAM, 0); + sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_port = htons(PORT); + server_address.sin_addr.s_addr = INADDR_ANY; + + bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)); + + if (errno == 98) { + log("Error: " + std::string(std::strerror(errno))); + return -1; + } + + log("Socket created"); + + int status = listen(server_socket, MAX_CONNECTIONS); + + if (status != 0) { + log("Error: can't listen with socket"); + return -1; + } + + log("Listening for connections..."); + + return server_socket; +} + +// Handles one connection in sepparate thread +void* handle_connection(void* arg) { + // Cast client socket descriptor + int client_socket = *(int*)arg; + delete (int*)arg; + + std::string info = ""; + + log("New thread created for socket " + std::to_string(client_socket)); + + while (true) { + // Recieve message from client + char buffer[5]; + ssize_t bytes_recieved = recv(client_socket, buffer, sizeof(buffer), 0); + + // If connection closed + if (bytes_recieved == 0) { + log("Connection with client " + std::to_string(client_socket) + " closed"); + active_connections--; + break; + } + + if (bytes_recieved == -1) { + log("Error while recieving message: " + std::to_string(errno) + " - " + std::strerror(errno)); + break; + } + + log("Got new message from client " + std::to_string(client_socket) + ": " + buffer); + + std::string new_info = get_sysinfo(); + + if (info != new_info) { + log("Client " + std::to_string(client_socket) + " info is not up to date"); + info = new_info; + time_t now = time(0); + struct tm tstruct; + tstruct = *localtime(&now); + char timestamp[32]; + std::strftime(timestamp, 32, "%Y/%m/%d %H:%M:%S ", &tstruct); + std::string msg = timestamp + info; + send(client_socket, msg.c_str(), strlen(msg.c_str()) + 1, 0); + log("Sent new info to client " + std::to_string(client_socket)); + } else { + log("Actual info already on client " + std::to_string(client_socket)); + } + } + + close(client_socket); + + return nullptr; +} + +// Refreshes console output +void* draw(void* arg) { + while (true) { + // Update info + clear(); + + // Print configuration + printw( + "LOG_FIFO_NAME=%s\nSERVER_TYPE=%s\nPORT=%i\nMAX_CONNECTIONS=%i\nCMD_LOG_BUFFER=%i\nCMD_REFRESH_TIME=%i\n\n", + LOG_FIFO_NAME.c_str(), SERVER_TYPE.c_str(), PORT, MAX_CONNECTIONS, CMD_LOG_BUFFER, CMD_REFRESH_TIME + ); + + // Print statistics + printw("Active connections: %i\nHandled messages: %i\nActive timers: %i\n", active_connections, handndled_requests, active_timer_threads); + + // Print logs + for (int i = CMD_LOG_BUFFER-1; i >= 0; i--) { + printw("\n%s", last_log_messages[i].c_str()); + } + + refresh(); + + // Wait to update again + std::this_thread::sleep_for(std::chrono::milliseconds(CMD_REFRESH_TIME)); + } +} + +int main() { + init_ncurses(); + init_log_pipe(); + + // Create thread to redraw console output + pthread_t tid; + if (pthread_create(&tid, nullptr, &draw, nullptr) != 0) { + std::cout << ("Failed to create drawing thread") << std::endl; + // endwin(); + return 2; + } + pthread_detach(tid); + + int server_socket = start_socket(); + + while (true) { + int client_socket = accept(server_socket, nullptr, nullptr); + + if (client_socket == -1) { + continue; + } + + log("New connection accepted"); + active_connections++; + + // Create thread for each connection + int* client_socket_copy = new int(client_socket); + pthread_t tid; + if (pthread_create(&tid, nullptr, &handle_connection, client_socket_copy) != 0) { + log("Failed to create thread for the connection"); + delete client_socket_copy; + } + pthread_detach(tid); + } + + return 0; +}