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
CFLAGS= -g3 -Wall -Werror
CFLAGS=-g3
CFILES=proxlib.c
CFILES_PARSLIB=parslib/parslib.final.o
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"
int on = 1;
int debug = 2;
int debug = 3;
int statem;
#define SEGMENT_LEN 512
@ -104,50 +104,143 @@ void do_err(void) {
STATEM_ERR);
}
int do_fwd_clt(void) {
/*int bytes = 0;
int do_fwd_clt(struct conn *conn) {
int bytes = 0;
int ret = 0;
while (bytes < srv_msg_len) {
ret = write(clt_sock, srv_msg+bytes, srv_msg_len-bytes);
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;
}
// 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;
}
srv_msg_len = bytes;
return 0;
}
if (debug == 1)
fprintf(stdout, "[%d] Received server message of size %d bytes\n", statem, srv_msg_len);
*/
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) {
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;
}
// TODO
int do_con_srv(struct conn *conn) {
int ret = 0;
struct httpareq *req = &conn->cltreq;
@ -209,16 +302,16 @@ _exit:
return ret;
}
int do_fwd_srv(void) {
/*int bytes = 0;
int do_fwd_srv(struct conn *conn) {
int bytes = 0;
int ret = 0;
while (bytes < clt_msg_len) {
ret = write(srv_sock, clt_msg+bytes, clt_msg_len-bytes);
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;
}
@ -295,6 +388,9 @@ int do_rcv_clt(struct conn *conn) {
printfpareq(&conn->cltreq);
}
conn->cltbuff = msgbuff;
conn->cltbuff_len = msgbuff_len;
return 0;
}
@ -302,6 +398,8 @@ void do_clear(struct conn *conn) {
statem = STATEM_RCV_CLT;
frepareq(&conn->cltreq);
frepares(&conn->srvres);
free(conn->cltbuff);
free(conn->srvbuff);
}
void do_statem(struct conn *conn) {
@ -315,6 +413,15 @@ void do_statem(struct conn *conn) {
case STATEM_CON_SRV:
ret = do_con_srv(conn);
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)

View File

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