From 2d3f52a9a5740e469c77b29e1c26ebb481aa9e19 Mon Sep 17 00:00:00 2001 From: Server Ubunto - HOME Date: Tue, 21 Oct 2025 19:00:55 +0100 Subject: [PATCH] Feature: API can now handle write and read to the DB --- .clang-format | 7 ++ API | Bin 0 -> 255272 bytes CMakeLists.txt | 8 +- compile_commands.json | 1 + include/server_structs.h | 244 ++++++++++++++++++++++++++++++++++++ include/stack.cpp | 48 +++++++ include/stack.h | 25 ++++ source/main.cpp | 262 ++++++++++++++++++++++++++++++++++++++- 8 files changed, 587 insertions(+), 8 deletions(-) create mode 100644 .clang-format create mode 100755 API create mode 120000 compile_commands.json create mode 100644 include/server_structs.h create mode 100644 include/stack.cpp create mode 100644 include/stack.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..22eb0c8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +UseTab: ForIndentation +TabWidth: 4 +ColumnLimit: 180 +BreakBeforeBraces: Attach +AllowShortFunctionsOnASingleLine: Empty diff --git a/API b/API new file mode 100755 index 0000000000000000000000000000000000000000..6f7c4ab0be7ccd675f1d4748aaa24c991cdb19dc GIT binary patch literal 255272 zcmeFa3wT^r)&GBbgMvT;0!Bp{ZdwG|+%J{tDQ#e4TZ}*@ikL~0w2h=mNG8y#;6Mm= zh|vI|5e4Vrv;jF5dyrzpj-w-oKP+m6e249t+n@BGiSb?lcrVtKmX?; zkk0JS+55ZKUi)(P-sh69)Gj`8>Xa#t{!DW|=9thumbh|Y)*q&66vuU{oqg%wSB9X<4JW|TkH}2bP8>l)6L+o9{)o> zp7}TP`P)luSU>&gOn&uZ0eqfbW7FxUKOOrfb%{-vx-$1O{R^9J<#qN`)3LiaU1-3@ z4}CZHvrGJ`pXyJxk$6V7o%}%gIhUd8tEYd(6a*&eWIyr_J-$1#@#P1*=iK*j z`u_9pJLt~wg@=5ZxoNDcz^nLG5vB}uEW@ee&sk9-!yf~T4zS#RHtz2 zho(&rUFb}oK0IyavHPF5jN>k$-+KBzg??G})AZXwzn`Js&(ZIh^xH_k&Gg$szx=a; ze%t8xEc!j;8+ToC;Quz?-tf=C7ash1WZOS0kLum?fJ@)~k-BS+`_U(2C&xE_&!K>Q8+jjP4Lvt$^zm~3f=Kk_U+cqug zf9t@mdk$~?QQsc>)-2jK+WNq%XBS_y?Oj!S4$Zph;lx4LC%aa9hiv)dACCU=Tg8_z zx$~iW&L=bS{=7=gIv~%Hrvmul`{s{dzE6IB6KUtuzlth8ALsfD<*{cWRbsyQ{Q>$s z{N{^)R)C#V)KK!pzcHY^9Rd8W0r_4TV1Gk^&Zh$SrU3gN4$%KPy&_^JT=KN%38 z`&x*8@n?(%n|%K44Jg<70qyM+63(YHC!oG=5Aeg50R1BZbfyQ`KO7MM!~i?*4zTBh z06+XTApWTVe9r)TZV8CLE`XmK;Gd@h%H;;++ZLd|*WUT-@gD*DbpiS(2iVyb;LnQ! z>{%ATuMDt<$Mbyc@L1v@`o*8h06Py1$kz*q|K)&kbp+@<8_-Xe1?X=K;NJ_#_nH9x zmjdiLC_sNsK>WUde0iFe&;M@(=pPu+er5#dw^RE(oMsQ3t4WZ4rrHnZFgi~$Z#dq9 zZP<%Oc-?Pd9oPqd()%FjRFq~QL}Ax=7Mfyg+O z@3Qe{9&F=(%|>@_ph*ksPye{(^QfHs^9Fq~zw4uxtDQfkag2Gp7{cQe|1?PaeU7#9 z2P}5pEAiiweEWp+I2)E#YXbQu8ITp!we2+SN&lJ<-nY)@rBmvmH&V^w7$tj+XY;#*WU$?$&5;cZYI+l5&9UolPw) z)6!IbPM$*;-DKN{$}B=~RqLwet~ILC+o45jT+!aStf{?6kDSxm-P1#EM~jAJG^Oa-Gy0y8! zsk>=ak5m7t?$(~(_UNh6rf4q*n>#x?s190|@%Q%Drf&KqYwf}1)arXy5^3%3?(AOD z+SAjtg8Is5PhNCtw2CcTT~bm~x~!>(tmuhSZLO$lJ~diW(!8>%yD{3`)E4cjYpy-D ziT`rQ;LDItaC zrmm*uw&czQBukxogL(g-sWgsJ(c>L(;82$YUJ`#m7Uwv-O|`bExd_Fj>c%y zirvemZS`&&Sj>KECHp#eyO1>`Ayv7XZdzC>ji7|ukZlCZsEe5)f?LP#d49ebVOF-$ z0KcG=+QBJ{PA#J`zj4Lt)s0;=+I4m`wNu?To2%tms&jnV-QBdNv7=SH*MG*XCFIsm8n5n_12dg;H?3JvQcIOu zPL;Y_O{A>xRO*~vYv@$h)ZIfxIklpZ{@*>d8WL;j>1kWhK|-r`bI_rI!B|8RH1h3c zZ{q%F&rY?ctlCYDg(bET?)t!6QbyU+>Hgmw5`y~HZWvU;HN#^8oil4sq1H-1G3QX< zNCUlNHwT33RZXiKd)mI(y4%h(!*N?rS7(oC?8bSuJZr&jq&D?uh9P_Y+|91}pOVQr zf!6MBzoPT7|7^g+mYxlIm+@p?X6a_m+}3dpofujg>EB+O+cf6H=%CqAZ+m-VQ#YNf za}PDOv@~|oGzS{OEm|&&gQQb{FPESA9D-`D>=9- z^UailLnX{tG*h0LP_vD7(t-tzWwVQ&lNQ&Vu%NMYc3FAmYxY|y<+GrnVg3nqjU}_o zDF1B0#%^dJk@DH4HU1zkIHzR(o0|E?Y#RN?pVQ?t8*c`XJ?Lr=AKeo;vzg`yt7X&M zZ&{N4w$~1^FjYP!j+52U6t-k<&>n$a->Co48d{<6=@jf|7uuX^27Tw_F8%)M(r?j@ z%U;fVgdNz%JDk&WwF7VQk|;nYfa z&G@%z$6wO;6S(R}fUABNaE+e; zuJKa=d>e4p3H>C$osj_E1zdF!z%%v)@X)pS^DPFR5`RX3t9}>ogv3t(*ZAv@%Q%uk zF5}NO;9B0${|49(T;oT8t36%7HGTrP#!m(CZNOD0^wa!yMgn*ufUg6d5I?7YtDW0` zr?g-EEWbU)z*Rp2T=lzv;sY`X>ck^|t}n_@SQ%*biLeM}Vt-B7mm?_%`6` zpU^J?>;azAegs_Y=>o3$3E&!k9dIpg3b@7(T^C>{a;e7%atW^n9+Ucw0oQyJz}3F> zz=uS~1FkwL;OdugV;16*|yz_tCY2R^F) z0j@eJ;M%^&fv40z>jL}(JRLh^cc(ERMq3C$P zRVM{p$Ek7PA<=Pe2=EW^h>TO!z>7u41+Ml)kc-Z0;I8PzfU8adxSkKz1Fshy54h^2 zfa`f^9C$=@oEroD13V(Qrdm_k1XEpGc=){1lP6D`|zt;mF5*-h?>ZE|{ z{9qip`sbGc{sA75c|$eub?P7BYEJ~Y=&T0rsegd0P6D{j!`1^IRsR52ofL4L|BVAr zsegVI;2-32KB@-3P5lF0?TG-7$UJg2@a^g!;Hr~AE;{Rh7o1|t;{jKl6mXpni~~PZ zbex+4`~y5C^ZRPxvqi@RuJ%NL>-u3e@Q;a347lnffa|(tJ@Av&KfqNdgSt^T2x=c}uMZ&3dLSDgfK-4|F7{I}{K;Hr}X9+7>4ao|s?f7S>1 z2f64}1Aj^V16=Ki0N4GL)xiIy{sFE!3E;YqvmW@qr`qy(z*Q#&JR4I?k;D z{y{D})xeJv9T<69KOKVyl7A6P*}v)ky%?{kZkOm#BY$t4<1dME2vxfuE`Vxh=py z$VI0bc)R)sxY`o|uKSy-fqzN;16*|yz;$1BJ@8A^KfqNd1w11As^h@FqyG7IfPavS zPBrjr)jz=1o(OQ=k6sP@7WEHs)ky%?eem_bH>-but4<2IuE)oL|4#k$n*jd+kLdgd z_;czX;A&3~1Kp#2*5llJp+%ki;KFe!JCm zHs{wb1Rjz2F7TM>*8@*T{1|X&sm*T)cuL}Xz%{-zl53~tTL@h9b%Co+J#fu823+G0 z0oV8*aE(6-JhValyd~Fujb8{nBJo||8owTRLgL4OYy2VL8T)~2{88X3wf`Ql|I;>H z2t0I$oU^wZ{Xl?O_zSwg>0lT>CYCA#$}Jxca9actrgVT;mS` z*Z3ZAjXw%p>&v+>*M5y(2wda4z%_m>fDZvz9S^wbi~`qkIrj(H2|S_g9JuP&16TbR zaEvxezs4^F z9#TI8*ZB3oHGT}Z#vcNn5`7Q2_ODUk2|e#Tm}|erFGQ~W5xCk@4?Lm$5qRiyo8J&{ zPyG)(BJoFoyBn=e61XGW8O<%1>J$QxNqiT$#*YQ?A>eAyFmScU1FrhcLjiUISN$U3 zs_z0<{a64W0j|W`! zM}ez7&hPTu?*{OC;A&3;aJ44}Tn&sxyjQ?SCe~{s3MNJYzp_&36d6 z#`l10{~ZOMSwB9TYp2F{fk#%@c=f%1riJR;-O5OD8KtK$LJ_@ltJ{X5Tt{i0t8T;sdI)o=B{LsH%taNVyM z0D$$KM%RABb=@I?I{GV=N%Wg=35V3VM#BPYk%)GXz}Yd%!jRC~~#`F9G%gk4bxQfoJ9w$UUnY1Fr3M z2)MRS54gr31+M+Vc{SI5jb8{{-;spoo)cH2d+9X;A;O6aJ^3L0oVAWz}5fG-*WBL z`YHsj@m=6rU-iJXzGA@Do+02Nsb3Gc#vcV9(f06quKk(op1^h9?gEdkwCU@CXY2>A z`@^XK?!J+0kH${~aA!P!{73-z0(j`}`E_CeJQcv*H}mTx0=V;!{P80J+yfpu&883i zGgn7>EP$s1xcjgCI*9=8ypnjq#y#PK6+?8>|*&d(|T=zq|0(dNd4*^&E69L=< zuKghiJke(DP61baeVepCZ|+EcD3Z5KE5AW>LcmqW1+M+S0r)1-i2zrf7;qhThJimK zItk#a;{kVN+(`m|PW=O1b(|^oMTY7JM|6sS|4sb^TyH`Ukk`#DMGk zU>Nur>L1{$;{kVM97qChSN{N49cNmue_WYo6aoLT`Ukk`xWFCJX#hT`{sFE!G2l9H z8wP&0`Ukk`c)(*a&r1ToUi|}Hb)4zoAJHiS?x}x(tBwm?=Q$0)A5#ASSDhGeN9-8} z{*3wuxaxSob$*`&{;K*1xav4Fa{Z(0iX!0C&a&f12)OFFz+G8aGyp$PbRxi2CkEUR zonhcdiB1Bz>Uh9ovhGL%uN0jWaMf}4$n}q|1B-y4sQv-2IxcWse>MO=UHt=Gbz;C> zS$_@#U#b29t~wrYM|6_F*QkGhtB$iL_(#_BMZhmn{{UAV7r5>(Gywmu`Ukk`#DMF* z#xU@otABv2jtAV4awUP^uKoe8I?hb+kL=eJ0e?XK16*}n;JSa*0Q_n74{+6q0oQ%2 zVc^@;KfqPT1MX`70zRc(=7+#l$Jr~_KaTnb`2M030Rr~||e$hz*R~=^`@Q>&e0e@2c16*}n;CdaU0r<=6AKcoJ@ z#;iTVz)ujJ1aQ^yfV-lT1b(Xe2e|4u`+i2;wv z_0D177ps4OtBwcU6`dsTZ>xWRtBz9u{t=xb;Mb~ufUAxRT(3hn0KZlJ16*}tz+-aV zdKmb<>L1{$;{kU?Ckgxy>L1{$Lw_O6yx1_azactBz+Y7V09PFsxZY>b0Q_I-AK#Z(J2C6EIJ|Js^bFJ`$!sq&ljBt zaMg(c*ZWt7fuExO0j@e8aJ|1J3A|bT16*~S19JW2%6%|Jzs0j@d@{{bob(ecNX`_+no|3m!)Ty1|1KLT8JV!-vjz+vDY5S;{Y)$xGq{fJ56vqdKbTy>m-z&~<7ViE9bSu5 zKE?*%_39tssuKh5h&{u=BkCXIazCC2T<;T20zX^*16=KK4$k#YOztZ!0)CwV7+z#mip09TzDa7XMJ2A)>`09PFkxZcm51pasR4{+6SUhBQzWgNcd7_g7t~$` zAK|SN{N4ofvR^j%XP8>*^ois^bCI=ZuoT_dMIShZJztaSj3hJR$7| z_+^(3;9pn&09PI7gWw-2 zR}t{L1{$;{w;`W*dP2Rs928bz;Evx!hskGrH|KkN~ba9&ksV%S{45SaedrRmTbC z`bVEPE&~2x(Fp-p9T&Jh=iC6iT67}7RVN1Aea!k{7Ntnz`o|HSBH-7le}Jow3tZnX&;a}n^$&2>i2>L58Vmy;RsR529S^wsJMjcoKS`z(fmA1FEr;Hu*RcmGfP1ND09TzDaDD&CF!0mWKfqPT1Fr8kNdjM~ z{sFE!&QZDkaUZeeDgwSnbV9&Y#|7?f6#oFfM06s+RVN1A5qpM#Unx2X;Hu*R*Z0vR zf&WZ&QovQm`B1KZ^!+$Rz<(n;A>gXx0(T!4{{a83=tO|4P7JssI>W%9QvU!~9S^v^ zZzu`;74;8r)p0%y{&`5+4{#@Hc?h`bxWM)ON)5pG7o7-j)rkRj#GYZ`hl@@ExaxSo z^?g!F;ANtd0ae=#{(*S&_`Ukk`#DF`ZGYovW`Ukk`c);~N zIZ5E>s(*m1j&pRbf4m39Kfu4L{sFE!E^t@JAK=64AK`Ukk`c)(*) zt|ajF>L1{$<9r1CBhP;o0l!E616*}n;I7!y0Q__VBvr6fnTWp0j@gEak>7{_aqbnzg+zTTy z@qp|5VUxgTo@2|K0L1{$;{n(AGADt5L;V9>b)1r1|LFUmi-0H8KfqPT1@7Ks%hdq<2K5hc)rkRjL}wWI zCiM?+)$xGqbH_>GkEnlutBzBe>mP56^e^ClRQ~{19T#|NgZKydU)4XrRVM~q-#Nw@O{t2mnfUi{l09PFsxV|^P0r+b54{+6q0e44i zI~fKZSN{N49S^u8I!WMHs(*m1j#H8AAN@N7MZkZi{sFE!E^z((2Mxe~qy7P|Ix*m> z+r>Y?f2;lht~wrYceB+=0)ImN16*~S%3S~G^ZrG^UsC@7R~;9)Bla`^|EKx~xa!1^ ztABv+yIRH{;Hu*R*T0{U1b&F&o)$xEk@_c&|_~+C=z*Wbo&h?MJ7oZ6ED)kR=)p3FAdjlGPpRfJ_ zt~xQ~Z%O|GKB)cyt~wrYeLq4H_|@tk;Hu-)NdZ?K=cBp)(f5xO0k0CB5OCFTf$RHC z8i0q@KfqNd23+5tG7S7P>L1{$;{n(Avm}9kLHz?-%LIfPYPNBEVHAhJ0McAK+JsP6D{NxXq{iE;SDFS|n`Ukk` zxWM)OJ`KP})jz;hCk9;KA2ba78TAiv)$xGGUblWu0)JKg16*~SkLCI&(kAT(_{=X_ z9s;g9#mMD+>H-gmegkmTj{sNwF5vopoEY%bN@;JvRX+h-_16K9iTxgMeP3h}_=m+m zDd4K_d_33BF})8Bc(wW&xazpT^*#Fy!0SXO0$g=sz+-Z~dl>jJuJ1D%2kwf#Yo^)qnQ@qp|5%96kb)X%_G$C;n&w@|D24ftj1H{hz{0(YCmKfu4E{sFE!G2~}h zonhb!^$&2>@qmY997qEHiTVe)>NqFl`p5aS_y_oP>L1{$;{wco(X zJ;T6nQ~v;09WQ_@qjzh-;==qrv3r0I!-P4=d;$HBH;fNoe*%El`~g1gOIAMuTy@z-|_VG{o__bGA``LE;%^qCm}hpk8ktwclr3ZkMHB-&ed5z?Caw*eSAM3FZA&O zA20IpLLU$L`2IdV%f}D!@nRo;w~tr*_<=s|`uIUU9`^BreZ1bs-{a#AK3?SG5g&h_ zkFWIc_xpI4k00XWt9|?fJ|6S&5Bm68A3xN`hkQKbEj>q@sy7r$`S@`@KJMeQecX|8 zhR1<9K0edOi+#M%$4h*?$j3{4JmlkLK0eFG%YD4q$18li+Q%z>-1YG)9}oL@wU5{P z_*@@v@bQoOc*Mt#_wkiJKF`OyeEefRzS_q>?&C2ZcYS=VkI(n*KXPzRt%_^zrpR9`Vek^KKN$1@5Pznffi|%nRMIW!W$LY?v3aV~1zMynr1$ARFd|>)6z6m=~;L zufCNjFE3Qbp3R1NfjahZHp~mtu}#@9FG$C3%!YX(I`)HXm=~a9mu17e@Ep4^8|DS) zSa&we3(c`**)VU6jGdAV^MZ5iglw1>nq#HeFfTC24$p=^z~KY3VO~&x8!*)T5z$4y?9nho>9Z|v}Fm=}Cw2V}#%&>NeY4f6tT?A3o} z%FheCv1hYkUeJv_oDK6rZfsLF%nP`&8?#|vxQ+cF8|DSu*k#!;FVw~^%!YY^HrAaD z^TKRwSvJfYU}L9b!@NKnJ0Tn9h1pnXHp~mMvBR_Bc^p0<8|DSr*wk#87hYqp{v%U< zm&4Cy!@STMdpH~B1=iT6Y?v2TV>f2Qyr3HUK{m__sj>d5We7hH;in+{D1;w?@MZ{afbh)_z7E3IK=^71e+$B2hw#M^J|Dv8K)3_K z%OU)E2!9&FCqwu|2!9O1l@Oi{;SWLhgAhI#!uvsZ4+y{Y7}P(6Uxx7W5Pk~6k3#qX z2yce)1_<8_;p-rL4TP_T@V6lRbqHS!;qxJU4um@(yd1)xhw!H%d@_Vjgz(28TnXXX z5dIK^KM3K2A-o@i_ki$Qk3#)J_+lk7aV#K4N^2g8k~3OSEkU%j7#{VW;}WjO`X0@k$CE~*Y;Gw zp)rnkr+iZUCKJEnv;1-NTjBV&@Wz)v9^N=UEj(p&_@TF=2a-Um2+Z7`vg4kn=kYH# zZ$71UdXHHe?wj`!is^*oe~RuC9+-C`1=9DtxqW-Og=Q<8XS|opYi8GG|d8_5kqzuCwUzirYV3QNu{*{8854h;z zD8Z5RwHj$)X(}8iu?dX)oCyE*?;@Nh^VJf^Qv(Ownc>@>zvR60UZ%Ty!Zn+^4-L0@ zziYI`y_e2=;rN}|Oy9G0@ATd5<6?6JymW?$_ox9urFvL%j~8XNcl7!q(K|x*2I~vS zo7?=}Tp@8@(KvlxA$v1E8s30IO$T(R-^X$4n%hi$pYW8XfOK17m?xP{ax zwhx5|&K$qzPHrXKHmGTk(0Suz;5apl@qEqVBa-=ru*p|?zuD5#wSyb!zJx)l-A_ocQloXy8w@StbehZHF-z( ziR^$|*f+kt;G167%h?_{LBpOVS-;=vq{DvmsPD3Qhf173Yn;iO_uT8I)M+v=+?=HH z2Mz;o^3X&+xJ*)zAv<($9?v<>=d*?cckj<=tL1Lkm!1-?xs%*u8)Bvg=by%2;>Jj2 zop_vjTnzln-)xcCkV|RtLQQ_}^*k1j7108ensdtOJ#Yg9a@}*1=r@`uU=aML#QUbk ziw6u^RLN#!TRae&$eS;U-a^&OQ>`<_n}zD}$ye*XB1_d8zq9YoDQCYoJbW83&uxRb zj^z-V1<5krP&iS+Uz6yICXg(Ug1;wQituo_Ey+Xk zVmdt!PJdrG{&=|mp4EqhYestxp`mAS{CTQPZGTUZ_|_RbqCdBI${)l1f5=vNnP}hl z8WkzGEi}lXb$lqE%rl_TI7$xedwx&1`q6@`HXZg*{DIrd`J(TIDdE9=sF~i2r!u$T zijlr&_N;!0pYE%D(tQJ{cQdW;!lWF9LKbVe^1?x@2=)0@% zjQO8CGjk4@ztr|Uo+FSidPm97BzY{E?__Y5)N1dmra%;bBz-QO=(2rp3vC8Xr0`u) zD9b1Wbg;v1L6WwE1zI#9dVl4Kan`sYo3$uU_Texfri5Q@h9i^y)@)TR*2#`8}w zdG<@4v6!str!|vD3#W_vI1@Q=I^|Fozl-wxMJFv7;{m-!$|eXsX@ zZ}5GO_`a|7eed#pU+w!I^L=0I`~FS(PTn_V8TRpOef;Ns{xyz2<25e(&*}SX^uyoR z`M&?k_kF$Z`)_>TJ>U1ceBZao_m=R$^rQI7M>t-)rNpC3anI*Kf08OWJYYYl5&iT9 z3dZ|WmYNTuGw5mtMbcpHm}%~C>rJTBU|<~mr}Bs5&pdK$2LFPV%fN#%``hb{SNhtOxjB=n`v2sKQdb> zBjj{0-ma9UoN6Icnr)QUNXB;TOj`HZ9=q>EUTZEAv&%sA0FC!b9@tDSpwW3G`}4HfD{YD)z-bD@m- z+gYgdo;QWE`HZCBq$_olZRpD2>KR;nk}1`eJi|1t$!Opm>H9OS;~wL68L!G_ay#y) zcE7OT=92lbx2BzQ@ce?CDIT};s}8m8{3fzvVSJk{waNbNEcI9aWJ+!G8A(sKrH)Kc z>KSWI`<+xr`wle}s>QXmMPkcigx}8c-13|$kIiQ!T~60uxkpS?p170;Hi%&%9)IAl zM{lEnVxnG?cOh=lP`w{V^;&RCUz~k$i|M9p)Z6KcpZ(GJ!W5nim_^s7xg$;Fi-G@+ zFAk$tN4^-y_`(?VcKYJ`&l+FYd`8lT&~Ehk}jls8ps!siG1;mN%`Wi%ThSEHl$3UOev_bf0U*# z-0>$W)Q}V^-?a>wF^p34q4Er6%43Az&hotcv?-6xXC!?V-I&6iccStK%(T;|bVu1{cR$m(dBR1h z3rq*T+@y{_6y7*S7dkgOv~DQ4d9RD^u@~d+;0)t72kPsbQJ+WiksW4ac9Js0(Fgj? z{5IaVlB4SsY$W}C)3*ka}O6dbLe07KZ{Y ze(FhMv6+3x`(in%W(B6Y)~0fdC;Qgsq$&Q|mHsS`G}p4MjMqz(tBzQLxx)}{`bv6)s_remq)^?|8-Z0dDV zZb==_N!<{by27SjFXfihi*iy&0#m>72UBiO$}Oq)%}Kp7F!ilA^%g1j_gIV8FQ)ft zxw`^Wf61mEHK}d%ft$>-(5`mB;C#WEe=B#>y7;L1yp3a=EQy^G`Fv!o*9;YD8W`+U}}rR?T!;4P!Eb#&|LNdN!QYS(1iIkEU-Y(ABO18}ZR_+ru{E zz2U)6ObgHBYg^~gP;f6Ntr_h;C>-BnGa8nR>XSJ+42Gvkwsc`{Z@#K`1YgxVLbBkj z;}4Lhzaz<~Jg&RKPfld+#4CpEZ0Iubn!mis@Nxf&&`r)a^L-N+y^nX)24|ev%|7Zc zqUI6k#~QKkf2e|df`e;kupg~sCoW-?C>%--visgtLeogG)KBeVQZ^kS3ImT#U{l`Y5)2x7}lgjSDu~ z_&j>-JJINIrDS`+|K--w+EtV7Uc;i`k-`Ms3+$hG9Qn5=?7yVC@{JZ#X!uFc2s+TU zuht8Ve>>XnAKEND>XB^yQ@i^!JrO|JCU&JcT=fRW1{A;NV1*waE|{5*YY12m{f166NMW{VS?rW_U~8~{$4={^Ous**5BrMZL*WhUrF-sQIRu) zLf(_PnG;W3_1Q`0anzuo4rP)ldm8M^x3db5CwEX+G<8P3`c``MjDnF}slvyfv{kr~ z$`Vk8)3G}TtrMnC)Q{ImMzikEaoS*5rw-Bq~eK2wFJ&Zr7sr!^f_VIofzQtc${#LgVG*KU`;$HY(Ni7(q&w0}kWSexCw zS=Yqdu|?V)sQt*bwD9Dm2knxWsFGr$eXArFV8E;oC{>yb$)uvi_YTt>o7WF)DxSep zs%<%`XoD&sRl7~avu#Q>o|B3erva%dZ7MS>j`ulsCn93bxFhM>gV=$Wo6`1eqHU{y zy|KUCYx10FQzs<#o;j(D15^LfrY^Lpb;!NP^jFP0c;BkmrY^FnLtO0mNO~YAwHugs zl}#Oza!cwZIjMv9t^R(GDfcWXx1=t}NnIb9_pfd0Vw2hybl@glZ_BPrp8XqsoR^DN z%x2sDo3Kq_KIq6fEGm73f=3@=xQA>hgacZX#>_y<~$Csm`Y;xOK`9 zi5ucO4UW?f=Lr)g!KwV%*s!CBv2;hA-~#N3Q+Y6TZO)my_V_q;?ePJ#E7a#rnIGSL z_MtYEb8q;KN$b@YM)*><*)yWz?9NVAHF-a?bMMudj0?UNrMsDYn^uodHuE=3<*Jm+ z22@e8!yKo!|Mlp8^ZVYK+FNLkZ{5#so^9R3ZgNq4z3Nau$@q!yQr@H=nq>Tl#NQU0 zoIN3l?@cnkZVeAjGQMs^M zo57Aal^=)l4+#+-2|+}9v+2yHQ}4r_dcSdcSZ~k1H>XAq**a7DNRjO$TMO?S3ePL>tiub>Ed&RT^3SKF@Eiz~f*q~`sbo9$M7?Pu_B(3z&&r4bfep1p((3P|j zERnR*TMw7C5_~rW7svmY9^1&3U%RCxe2l%pFghdM%PjtM`l?Md`K3ET_p40RE{?ys zfo~jL9DgO<>(Lzhgt|d{8|ba~)Ai2{w!swh1%OTAzD+a3@ou`Kh94Gtc07Fa=#-6p z&y2^nP|J?f!!(c4bFi<4e}?(~i*)(E>A}{dxzT?9=jS)(+_O8;O|RRifi52WF;AiT z=IypJ~Nx!3i;Gx-A1!Xx=+*TL;nX!>5bIG*C3 zI1=OQwtTPaNNl?K=Da!*n@QhZeU&b^#15oyRQNqcVnv3%N=FZ*yEgf*P-1fb=1A<2 z%(qbH+mV@Xvoha~&3r4)d@Gl4{<}caC7u~S&7~iE%kUENU%a0uuzk1lzs{NuQh~nx zIW8{UUwjAMU;HNhV2dKw(@%R(Ze<#`TQ*v(E?4;JQe8i-n+vFrE zUDmpd=DZZ%x6vq@`_ZQx@c|YeF!tTn!ExdbkXc1kI~&u7(ygd$>=(qGsch_$jIl?M zu{Py~8I+Qe-H?;4N0QyQfs!4ZN%o@2x38Y^H5dQFg9rVRwj!jlj->y2d*+^RlY6_! zT*NXD(m&Q!KhDYoE+Q^qcMh1W*x47FBs0!9gNw;m3_oS1?G?l4GR3h~NJZi@9Y;9c zKb@@YyPf}a)*MJFPZy(JA!En(ps|=(pRhmthFCwfbsE3T(!=ESV}D+&*)W;P#q(Dz z+*xxD*-kS!p8Op@zqeAp(rvl2{tpjc!Z+Kp7+;|~*Pq+ol-t-}xpD_*THF^2h|JuG? zAKl)-4x!k`eB8QxUsLHbj{Fu;s;9vj2bcrwvHhsqatmEYISge-S2}X?5{^yxdy{(l z2ixhNb}Cdh%7!Dkp$*Qs_-{7eY${gvX!?^RnEnK%(0HGhco*lyGd&=i41(tQ^LXzz zIyG#|M#?_5LQeyyZzR*GD$C#rpzEnGvH5?#l?uo&4=~Sfm^;{C+LvZ9KjT)J`_RyD zB+0K#l1V+0nYo{?o{CFZqzY~>BGt6-@wsb6_48IWooCE|J6W?^hPPSO^xC2wAI=YD zoD*MapAzfcgDe=|x;*`TYDeUf_fomj;ejRWzH#oI{}O-iQ|rWC}r(7>!#85 z-1N@dX6eI1Z)3Wn$O0+~Jz}rTjq78UKAjyOU0eHvbu62c-ulUOp_o&!Vd)cOj#Py) z=T>^X*4E<+Hk`>x$ZOoj5BiHWX`ap8M2|nk#(#-gJvc(1f1$@*hPXoGw>MC8h~IP? z{Tm)UGgcRWs&C%Aj;EGNr+=4Xq)*~%;L|^y^TUG+BJ{vZcx0NK`G0>BYb@XsKTWx) zV=O4Fi$9U?DHlHXPobwf{O90gi8s*CInxPjZGR_yiQUfsI?=r?e6=hVqkJD`i@%||By1`m69PeLEUx$VYZoYy=2F#Huqw&pkgG)Uc;JKi*lXBZ} zrraaxCn))lNtszNY<9*abtb;)0Qd2>VSMAj71jvOk_Iz+5_l8ck}_0R^HlV3@(IuL z!t4JgKXq|CzY7m6sNT%$v^sjOh37()y+ak9^iLU2xP@#J6EC=nYer^pXYSg28D6-B z4IN1zelzP)Blf>%$4&ea zl}rn|r^eTUW^mzxTF`JUTVq<#)uw`WwFTwW{XjpPp$+7N)LAms&sK8v8~0Q3pQM93 zRzFpOjX09NhlkYBbg`kXoTXE8?~=$Q*$>J^T*&-+y%q&t7g$h-@K+OUpu>si<{HVHfKkw;su#@ zcBxU=rFO>8j1BY~L;8$8`JU&0=_c#;AJZ9j@xU)Q_TqSYN&icE-VZcI{IG`NlCmjV z-|hU7Px;*vdyy|T)#(@MM%udg$ddl;*;h5plBgjzB7VC|ic1F1_h^>HUwx<9k4wZi zZlD-`h2?VKDLO!=aWWcP!~D^AJAe2@z9?~Tq_~t@Jx3a_apQKt?K9AqF4LBKcB8s z(TRC+{MAnkPXEZ__!zwB<8>PMzb=NpPD$-0zUP)q`PbaU!IiO5 z9JDz8f=rlhDx%5aAoX0`*4k;m>6HvtnGCM7wUnf%fb;Yl_1}DsOM5JXWCicTG#P*7 z?!&w!aSr0zuQ4OWZk(rcwsx*$$qVk{fho@xOLm^kbLW7U;_NA<{mOMD#qsjIH{b|~ zv&eXabdAQ9%W2)SVo9x3y`jmpeiGq3KclY~=j?mIg*?0Djk7hLV)yyO7M z_L5(iLXXohogK0&1GSPbA|f!()Hy1Exuvp6iK=_ zC+$0Lz3-6r-&cNaOk2+<%lpiU=gu6Le?ufjY&^<|U*K^jze~mc@{emJT7skTi(j(k z{H+}7w+fV+mQ4J9n0RfPN3+^3#_Bw+{t-#JD3f=5{Z??NS@xM@PS`y?g3CC{dp>-tvKUOQn-+%F59-Qu4(*Io6 z7gK0H#mClAJl-jc?@*w?HQvG0bZZN4KJv(%>e(h4&*F?H_40_!Qna507p^^mQ_%%c z>esm|=W1$KR7dnKpZHQ+L%n-(wT*q4<{s&mZT2DVN4Uw1)TZf!Uf0Tjfu*CSf7AW6 z15468Acy!C?GS}XN_KzNh}lhKwjGqINl3!ML#E~waZuvc{*>!!seSQS9(6KS)W0h! zrsb$-652�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⁢jF^ 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 literal 0 HcmV?d00001 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b40ae0..76b2268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES CXX) +project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES CXX C) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -47,6 +47,10 @@ add_executable(${EXECUTABLE_NAME} ${PROJECT_HEADERS} ) +find_package(PostgreSQL REQUIRED) +include_directories(${PostgreSQL_INCLUDE_DIRS}) +target_link_libraries(${EXECUTABLE_NAME} ${PostgreSQL_LIBRARIES}) + # Set output name property (for consistency) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_NAME}) @@ -72,4 +76,4 @@ endif() # Optionally, enable testing # enable_testing() -# add_subdirectory(tests) \ No newline at end of file +# add_subdirectory(tests) diff --git a/compile_commands.json b/compile_commands.json new file mode 120000 index 0000000..25eb4b2 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1 @@ +build/compile_commands.json \ No newline at end of file diff --git a/include/server_structs.h b/include/server_structs.h new file mode 100644 index 0000000..968da3f --- /dev/null +++ b/include/server_structs.h @@ -0,0 +1,244 @@ +#ifndef SERVER_STRUCTS_H +#define SERVER_STRUCTS_H + +#include +#include + +typedef struct handshake { + // [not used in the current Remote Telemtry version by AC] + // In future versions it will identify the platform type of the client. + // This will be used to adjust a specific behaviour for each platform. (eIPadDevice for now (1)) + int32_t identifier; + + // [not used in the current Remote Telemtry version by AC] + // In future version this field will identify the AC Remote Telemetry version that the device expects to speak with. + int32_t version; + + // This is the type of operation required by the client. + // The following operations are now available: + // ---------------------------------------------------------------- + // HANDSHAKE = 0 : + // This operation identifier must be set when the client wants to start the comunication. + // + // SUBSCRIBE_UPDATE = 1 : + // This operation identifier must be set when the client wants to be updated from the specific ACServer. + // + // SUBSCRIBE_SPOT = 2 : + // This operation identifier must be set when the client wants to be updated from the specific ACServer just for SPOT Events (e.g.: the end of a lap). + // + // DISMISS = 3 : + // This operation identifier must be set when the client wants to leave the comunication with ACServer. + int32_t operationId; +} __attribute__((packed)) handshake; + +typedef struct handshackerResponse { + // is the name of the car that the player is driving on the AC Server + char carName[50]; + + // is the name of the driver running on the AC Server + char driverName[50]; + + // for now is just 4242, this code will identify different status, + // as “NOT AVAILABLE” for connection + int32_t identifier; + + // for now is set to 1, this will identify the version running on the AC Server + int32_t version; + + // is the name of the track on the AC Server + char trackName[50]; + + // is the track configuration on the AC Server + char trackConfig[50]; +} __attribute__((packed)) handshackerResponse; + +typedef struct postion { + float x; + float y; + float z; +} __attribute__((packed)) postion; + +typedef enum flag { + NO_FLAG = 0, + YELLOW_FLAG = 1, + BLUE_FLAG = 2, + BLACK_FLAG = 3, + CHECKERED_FLAG = 4, +} __attribute__((packed)) flag; + +typedef struct carAtributes { + // Related to ACSP_CAR_INFO + u_char isConnected; // 1 = connected, 0 = disconnected + u_char isLoading; // 1 = loading, 0 = not isLoading + + char *car_model; + char *car_skin; + char *driver_name; + char *driver_team; + char *driver_GUID; + + // Related to ACSP_CAR_UPDATE + u_int8_t carID; + postion position; + postion velocity; + u_int8_t carGear; + u_int16_t carRPM; + u_int32_t lap_time; + u_int32_t cuts; + u_int32_t total_cuts; + u_int32_t total_cuts_alltime; + u_int16_t total_laps_completed; + u_int16_t contacts; + u_int16_t total_contacts; + + flag current_flag; // TODO: implement flag status updates + // TAG:3 + + float normalizedSplinePos; +} __attribute__((packed)) carAtributes; + +typedef struct carAtributesAPI { + // Related to ACSP_CAR_INFO + u_char isConnected; // 1 = connected, 0 = disconnected + u_char isLoading; // 1 = loading, 0 = not isLoading + + char car_model[64]; + char car_skin[64]; + char driver_name[64]; + char driver_team[64]; + char driver_GUID[64]; + + // Related to ACSP_CAR_UPDATE + u_int8_t carID; + postion position; + postion velocity; + u_int8_t carGear; + u_int16_t carRPM; + u_int32_t lap_time; + u_int32_t cuts; + u_int32_t total_cuts; + u_int32_t total_cuts_alltime; + u_int16_t total_laps_completed; + u_int16_t contacts; + u_int16_t total_contacts; + + flag current_flag; // TODO: implement flag status updates + // TAG:3 + + float normalizedSplinePos; +} __attribute__((packed)) carAtributesAPI; + + +typedef enum SessionType { + PRACTICE = 0, + RACE = 1, + QUALIFYING = 2, +} __attribute__((packed)) SessionType; + +typedef struct trackAtributes { + u_int8_t protocol_version; + + u_int8_t session_index; + u_int8_t current_session_index; + u_int8_t session_count; + SessionType session_type; + + char *server_name; + char *track; + char *track_config; + char *session_name; + + u_int8_t typ; + u_int16_t time; + u_int16_t laps; + u_int16_t wait_time; + u_int8_t ambient_temp; + u_int8_t road_temp; + + char *weather_graphics; + u_int32_t elapsed_ms; +} __attribute__((packed)) trackAtributes; + +typedef struct trackAtributesAPI { + u_int8_t protocol_version; + + u_int8_t session_index; + u_int8_t current_session_index; + u_int8_t session_count; + SessionType session_type; + + char server_name[128]; + char track[64]; + char track_config[64]; + char session_name[64]; + + u_int8_t typ; + u_int16_t time; + u_int16_t laps; + u_int16_t wait_time; + u_int8_t ambient_temp; + u_int8_t road_temp; + + char weather_graphics[64]; + u_int32_t elapsed_ms; +} __attribute__((packed)) trackAtributesAPI; + +typedef struct api_packet { + u_int8_t tracker_id; + u_int8_t last_updated_carid; + u_int8_t connected_cars; + + carAtributesAPI cars[64]; + trackAtributesAPI track_info; + +} __attribute__((packed)) api_packet; + +enum ACSP_MessageType { + // ============================ + // PROTOCOL VERSION + // ============================ + PROTOCOL_VERSION = 4, + + // ============================ + // SERVER → CLIENT MESSAGES + // ============================ + ACSP_NEW_SESSION = 50, + ACSP_NEW_CONNECTION = 51, + ACSP_CONNECTION_CLOSED = 52, + ACSP_CAR_UPDATE = 53, + ACSP_CAR_INFO = 54, // Response to ACSP_GET_CAR_INFO + ACSP_END_SESSION = 55, + ACSP_VERSION = 56, + ACSP_CHAT = 57, + ACSP_CLIENT_LOADED = 58, + ACSP_SESSION_INFO = 59, + ACSP_ERROR = 60, + ACSP_LAP_COMPLETED = 73, + + // ============================ + // EVENTS + // ============================ + ACSP_CLIENT_EVENT = 130, + + // ============================ + // EVENT TYPES + // ============================ + ACSP_CE_COLLISION_WITH_CAR = 10, + ACSP_CE_COLLISION_WITH_ENV = 11, + + // ============================ + // CLIENT → SERVER COMMANDS + // ============================ + ACSP_REALTIMEPOS_INTERVAL = 200, + ACSP_GET_CAR_INFO = 201, + ACSP_SEND_CHAT = 202, // Sends chat to one car + ACSP_BROADCAST_CHAT = 203, // Sends chat to everybody + ACSP_GET_SESSION_INFO = 204, + ACSP_SET_SESSION_INFO = 205, + ACSP_KICK_USER = 206, + ACSP_NEXT_SESSION = 207, + ACSP_RESTART_SESSION = 208, + ACSP_ADMIN_COMMAND = 209 // Send message plus a string +}; + +#endif // SERVER_STRUCTS_H diff --git a/include/stack.cpp b/include/stack.cpp new file mode 100644 index 0000000..6f417c1 --- /dev/null +++ b/include/stack.cpp @@ -0,0 +1,48 @@ +#include "stack.h" +#include + +Stack::Stack(size_t size) { + capacity = size; + data = new api_packet[capacity]; + top = -1; +} + +Stack::~Stack() { + delete[] data; +} + +bool Stack::isEmpty() { + return top == -1; +} + +bool Stack::isFull() { + return top == capacity - 1; +} + +bool Stack::push(const api_packet &item) { + if (isFull()) { + return false; // Stack overflow + } + data[++top] = item; + return true; +} + +bool Stack::pop(api_packet &item) { + if (isEmpty()) { + return false; // Stack underflow + } + item = data[top--]; + return true; +} + +bool Stack::peek(api_packet &item) { + if (isEmpty()) { + return false; // Stack is empty + } + item = data[top]; + return true; +} + +size_t Stack::size() { + return top + 1; +} diff --git a/include/stack.h b/include/stack.h new file mode 100644 index 0000000..d9236c9 --- /dev/null +++ b/include/stack.h @@ -0,0 +1,25 @@ +#ifndef STACK_H +#define STACK_H // STACK_H + +#include +#include +#include "server_structs.h" + +class Stack { + private: + api_packet *data; + size_t capacity; + int top; + + public: + Stack(size_t size); + ~Stack(); + bool isEmpty(); + bool isFull(); + bool push(const api_packet &item); + bool pop(api_packet &item); + bool peek(api_packet &item); + size_t size(); +}; + +#endif // STACK_H diff --git a/source/main.cpp b/source/main.cpp index df28b27..7dde4bf 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,7 +1,257 @@ -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -int main() -{ - std::cout << "Hello, World!" << std::endl; - return 0; -} \ No newline at end of file +// SERVER STRUCTS +#include "server_structs.h" +#include "stack.h" + +#define SERVER_SOCKET_PATH "/tmp/ACplayer_socket" + +const int STACK_SIZE = 512; + +Stack api_queue(STACK_SIZE); + +void checkConn(PGconn *conn) { + if (PQstatus(conn) != CONNECTION_OK) { + fprintf(stderr, "[!] Connection to database failed: %s", PQerrorMessage(conn)); + PQfinish(conn); + exit(1); + } +} + +void *db_write_thread(void *arg) { + + (void)arg; // Unused parameter + + const char *conninfo = "host=localhost port=5432 dbname=acservers_players user=admin password=123wer789"; + PGconn *conn = PQconnectdb(conninfo); + + checkConn(conn); + if (PQstatus(conn) == CONNECTION_OK) { + printf("[+] Database connection established successfully.\n"); + } + + while (1) { + api_packet packet; + + if (api_queue.pop(packet)) { + + printf("[W] Writing packet for Server with tracker ID: %d to database.\tQueue: %u/%d\n", packet.tracker_id, (unsigned int)api_queue.size(), STACK_SIZE); + + const char *query = "INSERT INTO servers (" + "server_id, server_name, session_type, session_count, server_track, " + "server_config, server_weather_graphics, typ, session_time, session_laps, " + "session_wait_time, session_ambient_temp, session_road_temp, session_elapsed_time, connected_players" + ") " + "VALUES ($1, $2, $4, $3, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) " + "ON CONFLICT (server_id) DO UPDATE SET " + "session_type = EXCLUDED.session_type, " + "session_count = EXCLUDED.session_count, " + "server_track = EXCLUDED.server_track, " + "server_config = EXCLUDED.server_config, " + "server_weather_graphics = EXCLUDED.server_weather_graphics, " + "typ = EXCLUDED.typ, " + "session_time = EXCLUDED.session_time, " + "session_laps = EXCLUDED.session_laps, " + "session_wait_time = EXCLUDED.session_wait_time, " + "session_ambient_temp = EXCLUDED.session_ambient_temp, " + "session_road_temp = EXCLUDED.session_road_temp, " + "session_elapsed_time = EXCLUDED.session_elapsed_time, " + "connected_players = EXCLUDED.connected_players " + "RETURNING server_id;"; + + const char *server_name = packet.track_info.server_name; + const char *server_track = packet.track_info.track; + const char *server_config = packet.track_info.track_config; + const char *server_weather_graphics = packet.track_info.weather_graphics; + + std::string server_id_str = std::to_string(packet.tracker_id); + std::string session_count_s = std::to_string(packet.track_info.session_count); + std::string session_type_s = std::to_string(packet.track_info.session_type); + std::string typ_s = std::to_string(packet.track_info.typ); + std::string session_time_s = std::to_string(packet.track_info.time); + std::string session_laps_s = std::to_string(packet.track_info.laps); + std::string session_wait_s = std::to_string(packet.track_info.wait_time); + std::string ambient_temp_s = std::to_string(packet.track_info.ambient_temp); + std::string road_temp_s = std::to_string(packet.track_info.road_temp); + std::string elapsed_time_s = std::to_string((u_int16_t)packet.track_info.elapsed_ms); + + std::string connected_players_s = std::to_string(packet.connected_cars); + + const char *paramValues[15] = {server_id_str.c_str(), + server_name, + session_count_s.c_str(), + session_type_s.c_str(), + server_track, + server_config, + server_weather_graphics, + typ_s.c_str(), + session_time_s.c_str(), + session_laps_s.c_str(), + session_wait_s.c_str(), + ambient_temp_s.c_str(), + road_temp_s.c_str(), + elapsed_time_s.c_str(), + connected_players_s.c_str()}; + + PGresult *res = PQexecParams(conn, query, 15, nullptr, paramValues, nullptr, nullptr, 0); + + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + printf("[!] Insert failed: %s", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + break; + } + + // Time for users table insert/UPDATE + + if (packet.connected_cars == 0) { + PQclear(res); + continue; // No connected cars to process + } + + for (int i = 0; i < packet.connected_cars; i++) { + + if (packet.cars[i].isConnected == 0) { + continue; // Skip disconnected cars + } + + const char *user_query = "INSERT INTO users (" + "driver_guid, driver_name, driver_team, car_model, car_skin, " + "cuts_alltime, contacts_alltime, laps_completed, is_connect, is_loading, current_server" + ") " + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) " + "ON CONFLICT (driver_guid) DO UPDATE SET " + "driver_name = EXCLUDED.driver_name, " + "driver_team = EXCLUDED.driver_team, " + "car_model = EXCLUDED.car_model, " + "car_skin = EXCLUDED.car_skin, " + "cuts_alltime = EXCLUDED.cuts_alltime, " + "contacts_alltime = EXCLUDED.contacts_alltime, " + "laps_completed = EXCLUDED.laps_completed, " + "is_connect = EXCLUDED.is_connect, " + "is_loading = EXCLUDED.is_loading, " + "current_server = EXCLUDED.current_server;"; + + const char *driver_guid = packet.cars[i].driver_GUID; + const char *driver_name = packet.cars[i].driver_name; + const char *driver_team = packet.cars[i].driver_team; + const char *car_model = packet.cars[i].car_model; + const char *car_skin = packet.cars[i].car_skin; + + std::string cuts_alltime_s = std::to_string(packet.cars[i].total_cuts_alltime); + std::string contacts_alltime_s = std::to_string(packet.cars[i].total_contacts); + std::string laps_completed_s = std::to_string(packet.cars[i].total_laps_completed); + std::string is_connect_s = std::to_string(packet.cars[i].isConnected); + std::string is_loading_s = std::to_string(packet.cars[i].isLoading); + std::string current_server_s = server_id_str; + + const char *user_paramValues[11] = {driver_guid, + driver_name, + driver_team, + car_model, + car_skin, + cuts_alltime_s.c_str(), + contacts_alltime_s.c_str(), + laps_completed_s.c_str(), + is_connect_s.c_str(), + is_loading_s.c_str(), + current_server_s.c_str()}; + PGresult *user_res = PQexecParams(conn, user_query, 11, nullptr, user_paramValues, nullptr, nullptr, 0); + + PQclear(user_res); + } + + PQclear(res); + } else { + usleep(1000); // Sleep for 1ms if no packets are available + } + } + + PQfinish(conn); + return NULL; +} + +int main(void) { + + int server_fd, client_fd; + struct sockaddr_un addr; + socklen_t addr_len; + ssize_t n; + + api_packet api_packet_storage; + + // Create socket + server_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (server_fd < 0) { + perror("socket"); + exit(1); + } + unlink(SERVER_SOCKET_PATH); + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, SERVER_SOCKET_PATH); + if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("bind"); + exit(1); + } + if (listen(server_fd, 5) < 0) { + perror("listen"); + exit(1); + } + + // Start DB write db_write_thread + pthread_t db_thread; + if (pthread_create(&db_thread, NULL, db_write_thread, NULL) != 0) { + perror("pthread create"); + exit(1); + } + // Detach the thread so it cleans up after itself + pthread_detach(db_thread); + + printf("[+] Server listening on %s\n", SERVER_SOCKET_PATH); + + while (1) { + client_fd = accept(server_fd, NULL, NULL); + if (client_fd < 0) { + perror("[!] accept"); + continue; + } + + printf("[+] Client connected\n"); + + while ((n = read(client_fd, &api_packet_storage, sizeof(api_packet))) > 0) { + printf("[+] Received %zd bytes\n", n); + + if (api_packet_storage.tracker_id == 65) { + printf("[+] Handshake Received from server \"%s\" (%d).\n", api_packet_storage.track_info.server_name, api_packet_storage.tracker_id); + continue; + } + + // Print info + printf("[*] Info: Tracker ID: %d (\"%s\")\tQueue: %u/%d\n", api_packet_storage.tracker_id, api_packet_storage.track_info.server_name, (unsigned int)api_queue.size(), + STACK_SIZE); + if (!api_queue.push(api_packet_storage)) { + printf("[!] API Queue full, dropping packet from Tracker ID: %d\n", api_packet_storage.tracker_id); + } + usleep(1500); + } + + if (n < 0) + perror("[!] Error on read"); + else + printf("[+] Client disconnected\n"); + + close(client_fd); + } + + return 0; +}