proxy: finish re-writing all proxy states

Also fix some new bugs that showed up. Proxying now works with HTTP websites
but only the ones which serve their content through the content-length HTTP
header field
This commit is contained in:
Kevin J. 2024-09-12 19:31:01 +02:00
parent 403ecb70b3
commit 5dcc4c8bf7
5 changed files with 148 additions and 36 deletions

View File

@ -1,5 +1,5 @@
CC=bear --append -- gcc CC=bear --append -- gcc
CFLAGS= -g3 -Wall -Werror CFLAGS=-g3
CFILES=proxlib.c CFILES=proxlib.c
CFILES_PARSLIB=parslib/parslib.final.o CFILES_PARSLIB=parslib/parslib.final.o
OUT=proxlib OUT=proxlib

@ -1 +1 @@
Subproject commit 678a44228fe0c5b24b2d1b96576da0e44211c364 Subproject commit 55835087d359f77d00030b3dffb1cd43980722ee

BIN
proxlib

Binary file not shown.

183
proxlib.c
View File

@ -11,7 +11,7 @@
#include "parslib/parslib.h" #include "parslib/parslib.h"
int on = 1; int on = 1;
int debug = 2; int debug = 3;
int statem; int statem;
#define SEGMENT_LEN 512 #define SEGMENT_LEN 512
@ -104,50 +104,143 @@ void do_err(void) {
STATEM_ERR); STATEM_ERR);
} }
int do_fwd_clt(void) { int do_fwd_clt(struct conn *conn) {
/*int bytes = 0; int bytes = 0;
int ret = 0; int ret = 0;
while (bytes < srv_msg_len) { while (bytes < conn->srvbuff_len) {
ret = write(clt_sock, srv_msg+bytes, srv_msg_len-bytes); ret = write(conn->cltfd, conn->srvbuff+bytes, conn->srvbuff_len-bytes);
if (ret < 0) if (ret < 0)
return -1; return -1;
bytes += ret;
}*/
return 0;
}
// TODO: add parsing ability
int do_prs_srv(void) {
int ret = 0;
return ret;
}
int do_rcv_srv(void) {
/*int bytes = 0;
int ret = 0;
while (bytes < PROXY_MAX_MSGLEN) {
ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, MSG_PEEK);
if (ret < 0)
return -1;
if (!ret)
break;
ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0);
bytes += ret; bytes += ret;
} }
srv_msg_len = bytes; return 0;
}
if (debug == 1) int do_rcv_srv(struct conn *conn) {
fprintf(stdout, "[%d] Received server message of size %d bytes\n", statem, srv_msg_len); 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) {
fprintf(stderr, "Failed receiving response line from upstream\n");
return -1;
}
if (debug == 1) {
fprintf(stdout, "debug - [upstream] received line: %s\n", line);
}
ret = parestitl(line, line_len, &(conn->srvres.titl));
if (ret < 0) {
fprintf(stderr, "Failed parsing response line\n");
return -1;
}
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) {
fprintf(stderr, "Failed receiving header line\n");
return -1;
}
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) {
fprintf(stderr, "Failed parsing header field\n");
return -1;
}
if (debug == 1) {
fprintf(stdout, "debug - parsed header field\n");
}
free(line);
}
// body
body:
struct httpares *res = &conn->srvres;
struct point *content_length_entry = &res->hentries[header_content_length];
if (content_length_entry->er == NULL) {
fprintf(stderr, "[upstream] no content length header\n");
return -1;
}
int content_length = 0;
ret = stoin(content_length_entry->er, content_length_entry->len, &content_length);
if (ret < 0) {
fprintf(stderr, "[upstream] failed parsing content length header\n");
return -1;
}
line_len = content_length;
line = (char *) calloc(1, line_len);
if (!line) {
fprintf(stderr, "[upstream] not enough dynamic memory\n");
return -1;
}
int bytes = 0;
do {
ret = recv(conn->srvfd, line+bytes, line_len-bytes, MSG_WAITALL);
if (ret < 0) {
fprintf(stderr, "[upstream] failed reading body from response\n");
return -1;
}
bytes += ret;
} while (bytes < line_len);
msgbuff = (char *) realloc(msgbuff, msgbuff_len+line_len);
if (!msgbuff) {
fprintf(stderr, "[upstream] not enough dynamic memory\n");
return -1;
}
memcpy(msgbuff+msgbuff_len, line, line_len);
msgbuff_len += line_len;
if (debug <= 2) {
fprintf(stdout, "------------------------------\n");
fprintf(stdout, "debug - [upstream] received body %d: %.*s\n", line_len, line_len, line);
fprintf(stdout, "------------------------------\n");
}
if (debug <= 2) {
fprintf(stdout, "printing parsed response\n");
printfpares(&conn->srvres);
}
conn->srvbuff = msgbuff;
conn->srvbuff_len = msgbuff_len;
return 0; return 0;
} }
// TODO
int do_con_srv(struct conn *conn) { int do_con_srv(struct conn *conn) {
int ret = 0; int ret = 0;
struct httpareq *req = &conn->cltreq; struct httpareq *req = &conn->cltreq;
@ -209,16 +302,16 @@ _exit:
return ret; return ret;
} }
int do_fwd_srv(void) { int do_fwd_srv(struct conn *conn) {
/*int bytes = 0; int bytes = 0;
int ret = 0; int ret = 0;
while (bytes < clt_msg_len) { while (bytes < conn->cltbuff_len) {
ret = write(srv_sock, clt_msg+bytes, clt_msg_len-bytes); ret = write(conn->srvfd, conn->cltbuff+bytes, conn->cltbuff_len-bytes);
if (ret < 0) if (ret < 0)
return -1; return -1;
bytes += ret; bytes += ret;
}*/ }
return 0; return 0;
} }
@ -295,6 +388,9 @@ int do_rcv_clt(struct conn *conn) {
printfpareq(&conn->cltreq); printfpareq(&conn->cltreq);
} }
conn->cltbuff = msgbuff;
conn->cltbuff_len = msgbuff_len;
return 0; return 0;
} }
@ -302,6 +398,8 @@ void do_clear(struct conn *conn) {
statem = STATEM_RCV_CLT; statem = STATEM_RCV_CLT;
frepareq(&conn->cltreq); frepareq(&conn->cltreq);
frepares(&conn->srvres); frepares(&conn->srvres);
free(conn->cltbuff);
free(conn->srvbuff);
} }
void do_statem(struct conn *conn) { void do_statem(struct conn *conn) {
@ -315,6 +413,15 @@ void do_statem(struct conn *conn) {
case STATEM_CON_SRV: case STATEM_CON_SRV:
ret = do_con_srv(conn); ret = do_con_srv(conn);
break; break;
case STATEM_FWD_SRV:
ret = do_fwd_srv(conn);
break;
case STATEM_RCV_SRV:
ret = do_rcv_srv(conn);
break;
case STATEM_FWD_CLT:
ret = do_fwd_clt(conn);
break;
} }
if (ret < 0) if (ret < 0)

View File

@ -21,6 +21,11 @@ struct conn {
int cltfd; int cltfd;
int srvfd; int srvfd;
char *cltbuff;
int cltbuff_len;
char *srvbuff;
int srvbuff_len;
struct httpareq cltreq; struct httpareq cltreq;
struct httpares srvres; struct httpares srvres;
}; };