From dbcf0d8ef47a87963f7551bd0e0fe081dc855ab1 Mon Sep 17 00:00:00 2001 From: Kevin Jerebica Date: Tue, 17 Sep 2024 18:40:01 +0200 Subject: [PATCH] proxy: implement a relaying system also remove now defunct functions + rewrite state machine --- .gitignore | 1 + proxlib | Bin 144840 -> 145192 bytes proxlib.c | 362 +++++++++++++++++++++-------------------------------- proxlib.h | 36 +++--- 4 files changed, 161 insertions(+), 238 deletions(-) diff --git a/.gitignore b/.gitignore index 51ac26b..918b7c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o proxy compile_commands.json +.cache diff --git a/proxlib b/proxlib index 7093a678e549ccfbe6157e098464a1239926082f..0f28968b1714fbe4803575333ef5c1fb3d8fa4a4 100755 GIT binary patch delta 46722 zcmcG%2V7N0w>P|JmvauicZ8#Wpok)ZVh0rkML_HoP_cKhB$lIMLu|NJ?6D>GM1zW5 zH1-%{i!pYM1uTh4OkyhEf6d;9VD7!|cklPz_xzr$Hfz?bS!>PA-gAyT=U$k$erHd_vKO`WdJ%5zM(I$!e%arIu`k%49EAq;^p1sEM*Svk<8U7D8_oO1@m^*{RyP~m+522Jo5N5J#{&A*cM*Jq^;tAAK`?1ZSODxQI12Y; zG=W8zp9UuVk}Ngd7%68@9Gs(0H#U?XydHbw6RsI*|=JmAPY4RUT1x{r3K3o zaYd-7%iISKb`YS`Oy~FVc1cLo`EkC3Z3I~E2%bKd^^&koE7DDq-~5;SfmW6lAuLN% zuy(NWasQH=;xxU)f5|;{dD_3^!MeQLzvNN6Jd?{2W$VCkdc&Z9bx6_W6aOX8Y$@>1 zw13H0=<<>bt(^*3Uo>2Bu994~W|>+pS8C7~E$?u%l01-0H1MF3yjmr>wXzh*XvJ7R zCAy;|*O$Ct;fr%b6Tmc#Z=qHQdx1xZGSx{-Bb)Y9)DTC3#RK`RhvZ z;7anhmE5h%r5@&l$svsoJD#;PcFDK@nGJVDkmB(CwxIE+{pi^KR zDB=fETiJthd_qnVPfMxnGUpEwPfMt*g!7*gFA=|+^V^A+iC@q8jl|Q^vXm|6f>k7- zHB~l^^Gk>)Ps>Jeejf3(gvv5GKZAH$I%R2`f1h|-GG%d`A49wy@sXS#LOd;zGBfA< z5|5Q(5z3sopa%(PNt6kkPbc1q_}70!5Ym=-S^{McINySJD*dv{oNq)t?P_HuoR1>j zjriT1uSq;re%X4?S0mno)<@Z5F7PD*m3rAU&bty%C0;g)^R~oOX_sYkUL>9>x-5f2)OHG-i6#`&f~GF;EOCKC4ktEzo8ys~uQY=am6=WX z1E;`gr1zPQq5lwu6BoqXN>PWo`iTzh)jZcK;ddbv#?|YbnA`MuGRVZdCpiv@`Aw@s zUhZ)dqSAiw>Ws2CMZMzsIm=Ynx|vxQ^_bgk_OUwBy(4R+e&(Lcs;JH$4$H*=dY>Z5k97}Z;C;T_&!5iI5SEP2FO?bYy-5w!N^TtLO>6| zW1%z#CKvbSs@TG&CFV_;+dna14#D&>uY|XCOU^3i(UpRyrU%rn`3GfS57=Y0oV1{B z!EjJMfO0rsEr+rN>h=J?@Z(t3c?oNBr>voZ;GO$W`W7UV9Eya2iu6_aMQs=u-qe}L zSJRKd)DBRsV0MW=^QnW4GZ7za4A=CzQ~e{O!9Y#qND`1REJ z3iw2hP-QSsI|B5X-_K;YpGUiFQoj0HK>KR z{S(98d9ZVo($Q#DNBIWWC?6#tH2A0sd~2!+)x5erMQ{PsscUe2SumKu1-t-4rwwYJg=JpRN}Y+~LGnu3fez_l7QedITBLFb!^ z3)+_?=3PQ#FTM|G9vU@^eu(rEg?rna;%Yzg&-U^>)|3K+` zlRM>&VDY4GG>a?<$v;bZS*~X7CN1nY>~dni%TRj2OP^18Ah+8YPSO6!8!&%2t0ix; zM0@ayrs!YM+l2O;h~tVxc0yA2qlF7CzX?M3mx9wU(E^1;TUr!mJXDJ5gt8 z0s`M9%4jlLt7aVTMdl~m;d8`H9=-l&Q?xzsCl$qTBz83V& z|3zQTEGZ4(vxaFC!e@2*HIho5&6?9_MG+u=sCFb3tf!6+fv;wmjGm6N6tL@JC_79>1)_Y8WA zA*o|N)(El$f_9%$jq;yWGS$whIN@>bIg30X562Q$@YcmIbI+0VWrgxMQihcMBZV%P z!URbla}P@KsCbMXA8AIRJQWww^XZD*2P`k)GAB>G6*+eu+;=N-E!1+8)7F+dTFV0& z4;sPb1NIef4JT3|(NwerR)m^G&~$xPN#9@Br=0wwZ$Uw5`rIYx2T`g0#{n<_TEJ=V z=#xJ|y865Jb@h-6cgVamMToY^iKem)EQ!T0*ka8aigQ)n(2)OpX16i2rcAjq|DQ(P zZB-TEvB!7Telj>CxZ_lJrFTK8j@3ggQK*Z&gd^Bd^AbvOr<7>V4m+Ds&Q2V{kzDcI zaT%{cl*jexdH@Tlylf>>i;nRJ=nWuofydLPq;cgCWt=~)K>Np+Wd9$_>AK~bnhu`# z@F2BLH{H6zbaU8130;1-h&^AGmk&6ba9I?zS^UC{UqAlXh$$U>xg^xv@&QyTkM|{f zIz;Vw!bsu6{PTn%L06l}5$#YpMi26Ey5_%(%&TN1_+Lhj!3WLA1QqDD8?{&7c11z6SI6#kwI2%xC?H?e5T6HOW)KmEhrz%gtNw-$FlC|4--ltUjGl4(J zV7_uPxrsJ5y&zb}exPgLfTyLb($vDyV-GsycRq#ae9hJViO#bZYV$A;OD0z+fx^pw zDeQlN8u$y9e9Rd~ulBq(12XJ_=dhFNPmyuxPtk~~1=7VHFhr|QPJn%N1pRp z#S=Z~L!v|rra6~Cqk{q6_qo1xVvl|25hV`|72By3magL~9sNAe(WpsnOS7<_@qJruU*qS*iH%?@_ob;zLf(m_ zytjDONkQ1*Bv&cjR)$dIp2Ci!)Fw^DfL>&+qjuDEOItiwCx^H3Ki`n@@MluqYuKS1 ziV8b{W$OKKU)2~MkvJPl))C|Rh&%CcUZGiBS}|f1()`zmS()1*oI##w5 zQHl|3CR~96oWDQ_dzY9TW18%8H ztU9$;luI>gLn`awJs$S`V$~D1BE%+7)z`IrMe|eDKBB#N<%!xeqG^>SPx$urI`J$< zC2e~Aiu0!46P~F1pcqDqA!?1<4INJ4ty+H!Tl-WUS^E=l@?+Ipr=d7KM(tT=zWCF( zYFVAhV$8Sdz{q$p>RWYtWHZ}lxSb+%&mXBjMrMe4kJOHJ8;NTls*CD&6c0R9AJ=Ut z?u$|bqeh4h5Jt5T<%jCcsBz+g2Wo1)>Eea^>eYH}#1r>bzvw}t*L`(X^ltIPduoH2 zuHwbJ>f)HhfJe1yh!cnC9?Y8krq}^!*ct z%&fku9~SUo#D6p>=-Mmq!eAY>Z-bTr9=cj(qqDJ6X}`k=zd$1lJe18>d07cvEOYqFE&tYaa-LUTTSe9tLRef7MA`4-Y>E7QEvD{d^VZ0 zK1(^xTt!WMGqA%(zX>-hXvAwa-nc25+EeqDZ+M@#FIwk&d{{$0+sND|7iM!ySf27e z2&iK5pV2n`JY89P=q=LBoGo>|sc#G~Jm^@3>9eJOe_d3&aSn6%$tmD>S~vVEtf*>w zs$of7ip$uXteotOkwXOs{Z3Z>AZ~260a=5GW%oBv7@RZ6oIPgD$T8-ABl~BYL;Bka z{RWL2F*Lisy0_&b&tZed=46i;JYt}E093|~>^C$!XRNK-y;VcMtbYBnN9DlAi0ldG ze!~W5kI2y#Y}IA0lFZ>GACot%Ymg^J0SSK_EcE45 z5V*@{%FDZfetoXIJPx?*e0ljaVC7w$9-&LhAp@06F{0cLm6U%~}e2?#Sbyif1J0PyDfFaX^1 z0So|716~gt{tylTUk82wJmV1z;EAB@Tl5ERk2M?z-1r�|#MWoCchU4SO^2T5P-L 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%0Do))Yq#32WmKzr)V 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 #include #include +#include #include "proxlib.h" #include "parslib/parslib.h" @@ -98,21 +99,21 @@ int pull_content_length(int fd, int len, int *msgbuff_len, char **msgbuff) { int line_len = len; char *line = (char *) calloc(1, line_len); if (!line) { - return err_mem; + return ERR_MEM; } int bytes = 0; do { ret = recv(fd, line+bytes, line_len-bytes, MSG_WAITALL); if (ret < 0) { - return err_recv; + return ERR_MEM; } bytes += ret; } while (bytes < line_len); *msgbuff = (char *) realloc(*msgbuff, *msgbuff_len+line_len); if (!*msgbuff) { - return err_mem; + return ERR_MEM; } memcpy(*msgbuff+*msgbuff_len, line, line_len); @@ -166,9 +167,6 @@ int pull_chunked_encoding(int fd, int *msgbuff_len, char **msgbuff) { memcpy(*msgbuff+*msgbuff_len, line, line_len); *msgbuff_len += line_len; - if (debug == 1) { - fprintf(stdout, "debug - [upstream] received chunk:%d\n", line_len); - } free(line); } return 0; @@ -176,137 +174,27 @@ int pull_chunked_encoding(int fd, int *msgbuff_len, char **msgbuff) { } void do_err(void) { - fprintf(stderr, "[%s] failed with error code %d=%s\n", - states_str[statem], err, errs_str[err]); -} - -int do_fwd_clt(struct conn *conn) { - int bytes = 0; - int ret = 0; - while (bytes < conn->srvbuff_len) { - ret = write(conn->cltfd, conn->srvbuff+bytes, conn->srvbuff_len-bytes); - if (ret < 0) - return -1; - bytes += ret; - } - - return 0; -} - -int do_rcv_srv(struct conn *conn) { - int ret = 0; - char *line = NULL; - char *msgbuff = NULL; - int line_len = 0; - int msgbuff_len = 0; - - // response line - ret = read_line(conn->srvfd, &line_len, &line, &msgbuff_len, &msgbuff); - if (ret < 0) { - return err_recv; - } - - if (debug == 1) { - fprintf(stdout, "debug - [upstream] received line: %s\n", line); - } - - ret = parestitl(line, line_len, &(conn->srvres.titl)); - if (ret < 0) { - return err_parstitle; - } - - if (debug == 1) { - fprintf(stdout, "debug - [upstream] parsed response line\n"); - } - - free(line); - - // headers - int next_header = 1; - while (next_header) { - ret = read_line(conn->srvfd, &line_len, &line, &msgbuff_len, &msgbuff); - if (ret < 0) { - return err_recv; - } - - if (line_len == 0) { - if (debug == 1) { - fprintf(stdout, "debug - [upstream] reached end of headers\n"); - } - next_header = 0; - continue; - } - - if (debug == 1) { - fprintf(stdout, "debug - [upstream] received line: %s\n", line); - } - - ret = parshfield(line, line_len, conn->srvres.hentries); - if (ret < 0) { - return err_parsheader; - } - - if (debug == 1) { - fprintf(stdout, "debug - parsed header field\n"); - } - - free(line); - } - - // body - struct httpares *res = &conn->srvres; - struct point *content_length_entry = &res->hentries[header_content_length]; - struct point *transfer_encoding_entry = &res->hentries[header_transfer_encoding]; - if (content_length_entry->er) { - int content_length = 0; - - ret = stoin(content_length_entry->er, content_length_entry->len, &content_length); - if (ret < 0) { - return err_pars; - } - - ret = pull_content_length(conn->srvfd, content_length, &msgbuff_len, &msgbuff); - if (ret < 0) { - return err_recv; - } - fprintf(stdout, "Successfully received normal body from server\n"); - } else if (transfer_encoding_entry->er && strcmp(transfer_encoding_entry->er, "chunked") == 0) { - ret = pull_chunked_encoding(conn->srvfd, &msgbuff_len, &msgbuff); - if (ret < 0) { - return err_recv; - } - fprintf(stdout, "Successfully received chunked body from server\n"); - } else { - return err_support; - } - - fprintf(stdout, "srvbuff:%p+srvbuff_len:%d\n", conn->srvbuff, conn->srvbuff_len); - conn->srvbuff = msgbuff; - conn->srvbuff_len = msgbuff_len; - - return 0; + fprintf(stderr, "failed with error code %d\n", err); } int do_con_srv(struct conn *conn) { + statem = state_con_srv; + int ret = 0; struct httpareq *req = &conn->cltreq; struct point *host = &req->hentries[header_host]; if (host->er == NULL) { - return err_pars; + return ERR_PARS; } struct hostinfo *info = (struct hostinfo *) calloc(1, sizeof(struct hostinfo)); if (!info) { - return err_mem; + return ERR_MEM; } ret = pahostinfo(host->er, host->len, info); if (ret < 0) { - return err_pars; - } - - if (debug <= 2) { - fprintf(stdout, "Establishing connection with upstream: %.*s : %.*s\n", info->hostname_len, info->hostname, info->service_len, info->service); + return ERR_PARS; } struct addrinfo hints; @@ -321,7 +209,7 @@ int do_con_srv(struct conn *conn) { free(info->hostname); free(info->service); free(info); - return err_pars; + return ERR_PARS; } ret = conn->srvfd = socket(res->ai_family, res->ai_socktype, @@ -331,7 +219,7 @@ int do_con_srv(struct conn *conn) { free(info->hostname); free(info->service); free(info); - return err_pars; + return ERR_PARS; } ret = connect(conn->srvfd, res->ai_addr, res->ai_addrlen); @@ -340,26 +228,15 @@ int do_con_srv(struct conn *conn) { free(info->hostname); free(info->service); free(info); - return err_pars; + return ERR_PARS; } return ret; } -int do_fwd_srv(struct conn *conn) { - int bytes = 0; - int ret = 0; - while (bytes < conn->cltbuff_len) { - ret = write(conn->srvfd, conn->cltbuff+bytes, conn->cltbuff_len-bytes); - if (ret < 0) - return -1; - bytes += ret; - } - - return 0; -} - int do_rcv_clt(struct conn *conn) { + statem = state_rcv_clt; + int ret = 0; char *line = NULL; char *msgbuff = NULL; @@ -367,23 +244,14 @@ int do_rcv_clt(struct conn *conn) { int msgbuff_len = 0; // request line - fprintf(stdout, "debug - listening for new lines from client\n"); ret = read_line(conn->cltfd, &line_len, &line, &msgbuff_len, &msgbuff); if (ret < 0) { - return err_recv; - } - - if (debug == 1) { - fprintf(stdout, "debug - received line of %d bytes from client\n", line_len); + return ERR_RECV; } ret = pareqtitl(line, line_len, &(conn->cltreq.titl)); if (ret < 0) { - return err_parstitle; - } - - if (debug == 1) { - fprintf(stdout, "[do_rcv_clt] parsed request line\n"); + return ERR_PARSTITLE; } free(line); @@ -393,28 +261,17 @@ int do_rcv_clt(struct conn *conn) { while (next_header) { ret = read_line(conn->cltfd, &line_len, &line, &msgbuff_len, &msgbuff); if (ret < 0) { - return err_recv; + return ERR_RECV; } if (line_len == 0) { - if (debug == 1) { - fprintf(stdout, "[do_rcv_clt] reached end of headers for the client\n"); - } next_header = 0; continue; } - if (debug == 1) { - fprintf(stdout, "debug - received line: %s\n", line); - } - ret = parshfield(line, line_len, conn->cltreq.hentries); if (ret < 0) { - return err_parsheader; - } - - if (debug == 1) { - fprintf(stdout, "debug - parsed header field\n"); + return ERR_PARSHEADER; } free(line); @@ -429,21 +286,18 @@ int do_rcv_clt(struct conn *conn) { ret = stoin(content_length_entry->er, content_length_entry->len, &content_length); if (ret < 0) { - return err_pars; + return ERR_PARS; } ret = pull_content_length(conn->srvfd, content_length, &msgbuff_len, &msgbuff); if (ret < 0) { - return err_recv; + return ERR_RECV; } - - fprintf(stdout, "Successfully received normal body from server\n"); } else if (transfer_encoding_entry->er && strcmp(transfer_encoding_entry->er, "chunked") == 0) { ret = pull_chunked_encoding(conn->srvfd, &msgbuff_len, &msgbuff); if (ret < 0) { - return err_recv; + return ERR_RECV; } - fprintf(stdout, "Successfully received chunked body from server\n"); } conn->cltbuff = msgbuff; @@ -452,52 +306,125 @@ int do_rcv_clt(struct conn *conn) { return 0; } -void do_clear(struct conn *conn) { - statem = state_rcv_clt; - frepareq(&conn->cltreq); - frepares(&conn->srvres); - free(conn->cltbuff); - free(conn->srvbuff); -} +int read_buffer(int fd, char **buff, int *len) { + char *tmp = (char *) malloc(RELAY_BUFFER_SIZE); + if (!tmp) { + return ERR_MEM; + } + + memset(tmp, 0, RELAY_BUFFER_SIZE); + int bytes = recv(fd, tmp, RELAY_BUFFER_SIZE, 0); + if (bytes <= 0) { + free(tmp); + return ERR_RECV; + } + + *buff = realloc(*buff, *len+bytes); + if (!*buff) { + free(tmp); + return ERR_MEM; + } + + memcpy(*buff+*len, tmp, bytes); + *len += bytes; + + return 0; +} + +int write_buffer(int fd, char **buff, int *len) { + if (*len <= 0) { + *len = 0; + return 0; + } + + int writen = send(fd, *buff, *len, 0); + if (writen < 0) { + return ERR_SEND; + } + + char *trunc = (char *) malloc(*len-writen); + if (!trunc) { + return ERR_MEM; + } + + memcpy(trunc, *buff+writen, *len-writen); + + char *tofree = *buff; // FIXME: any better solution? + *buff = trunc; + *len -= writen; + free(tofree); + + return 0; +} void do_statem(struct conn *conn) { - int ret = 0; + int ret = 0; - for (int counter = 0; counter < MAX_BOUND; counter++) { - switch (statem) { - case state_rcv_clt: - ret = do_rcv_clt(conn); - break; - case state_con_srv: - ret = do_con_srv(conn); - break; - case state_fwd_srv: - ret = do_fwd_srv(conn); - break; - case state_rcv_srv: - ret = do_rcv_srv(conn); - break; - case state_fwd_clt: - ret = do_fwd_clt(conn); - break; - } - - if (ret > 0) { - err = ret; - } - - if (err) { - do_err(); - break; - } - - if (statem == state_fwd_clt) { - do_clear(conn); - continue; - } - - statem++; + ret = do_rcv_clt(conn); + if (ret < 0) { + err = ret; + do_err(); } + + ret = do_con_srv(conn); + if (ret < 0) { + err = ret; + do_err(); + } + + // relay the data between the two sockets until the end of time + ssize_t bytes_received; + struct pollfd fds[2]; + for (;;) { + memset(fds, 0, 2*sizeof(struct pollfd)); + fds[0].fd = conn->cltfd; + fds[1].fd = conn->srvfd; + + if (conn->srvbuff_len > 0) { + fds[0].events |= POLLOUT; + } + if (conn->cltbuff_len > 0) { + fds[1].events |= POLLOUT; + } + if (!conn->srvbuff_len) { + fds[1].events |= POLLIN; + } + if (!conn->cltbuff_len) { + fds[0].events |= POLLIN; + } + + ret = poll(fds, 2, 1000); + + if (fds[1].revents & POLLOUT) { + ret = write_buffer(conn->srvfd, &conn->cltbuff, &conn->cltbuff_len); + } + if (fds[1].revents & POLLIN) { + ret = read_buffer(conn->srvfd, &conn->srvbuff, &conn->srvbuff_len); + } + if (fds[0].revents & POLLIN) { + ret = read_buffer(conn->cltfd, &conn->cltbuff, &conn->cltbuff_len); + } + if (fds[0].revents & POLLOUT) { + ret = write_buffer(conn->cltfd, &conn->srvbuff, &conn->srvbuff_len); + } + if (fds[0].revents & POLLHUP) { + break; + } + if (ret < 0) { + break; + } + } + + if (conn->cltbuff_len > 0) { + write_buffer(conn->srvfd, &conn->cltbuff, &conn->cltbuff_len); + } + if (conn->srvbuff_len > 0) { + write_buffer(conn->cltfd, &conn->srvbuff, &conn->srvbuff_len); + } + + close(conn->cltfd); + close(conn->srvfd); + exit(0); // child die } int do_srv(void) { @@ -535,9 +462,8 @@ int do_srv(void) { return -1; } - fprintf(stdout, "Listening on port %d\n", PROXY_PORT); - for (;;) { + fprintf(stdout, "listening for sockets\n"); struct sockaddr_in new_clt_addr; socklen_t new_clt_addr_len= sizeof(new_clt_addr); int new_clt_sock; @@ -549,6 +475,7 @@ int do_srv(void) { "client\n"); return -1; } + fprintf(stdout, "accepted new client socket\n"); ret = fork(); if (ret < 0) { @@ -558,12 +485,11 @@ int do_srv(void) { } if (ret > 0) { - fprintf(stdout, "[PROGRAM] Successfully forked a new child process" - " with PID %d\n", ret); + fprintf(stdout, "+new request process:%d(pid)\n", ret); continue; } - // child + // request process struct conn *conn = (struct conn *) calloc(1, sizeof(struct conn)); if (!conn) { fprintf(stderr, "Not enough dynamic memory to establish connection\n"); @@ -574,7 +500,6 @@ int do_srv(void) { statem = state_rcv_clt; do_statem(conn); free(conn); - return 0; } @@ -588,7 +513,10 @@ int main(int argc, char *argv[]) { return -1; } - return do_srv(); + ret = do_srv(); + if (ret < 0) { + return -1; + } fretres(); } diff --git a/proxlib.h b/proxlib.h index 88fe106..93864e2 100644 --- a/proxlib.h +++ b/proxlib.h @@ -9,41 +9,35 @@ #define PROXY_PORT 2020 #define PROXY_CONN 20 +#define RELAY_BUFFER_SIZE 1024*2 +#define RELAY_POLL_TIMEOUT 1000 enum states { state_rcv_clt = 0, state_con_srv, state_fwd_srv, state_rcv_srv, - state_fwd_clt + state_fwd_clt, + state_ok }; -enum errs { - err_generic = 1, - err_mem, - err_recv, - err_pars, - err_parstitle, - err_parsheader, - err_support -}; +#define ERR_GENERIC -1 +#define ERR_MEM -2 +#define ERR_RECV -3 +#define ERR_SEND -4 +#define ERR_PARS -5 +#define ERR_PARSTITLE -6 +#define ERR_PARSHEADER -7 +#define ERR_SUPPORT -8 +#define ERR_TIMEOUT -9 char *states_str[] = { "state_rcv_clt", "state_con_srv", "state_fwd_srv", "state_rcv_srv", - "state_fwd_clt" -}; - -char *errs_str[] = { - "err_generic", - "err_mem", - "err_recv", - "err_pars", - "err_parstitle", - "err_parsheader", - "err_support" + "state_fwd_clt", + "state_ok" }; struct conn {