Add chunk send/receiving functions

This commit is contained in:
2023-01-26 11:35:08 +01:00
parent 299e726341
commit 8053439212
4 changed files with 74 additions and 26 deletions

View File

@ -403,9 +403,9 @@ int fastcgi_send(fastcgi_cnx_t *conn, sock *client, int flags) {
sock_close(&conn->socket);
free(content);
if (flags & FASTCGI_CHUNKED) {
sock_send_x(client, "0\r\n\r\n", 5, 0);
}
if (flags & FASTCGI_CHUNKED)
if (sock_send_last_chunk(client) == -1)
return -1;
return 0;
} else if (header.type == FCGI_STDERR) {
@ -415,10 +415,9 @@ int fastcgi_send(fastcgi_cnx_t *conn, sock *client, int flags) {
} else if (header.type == FCGI_STDOUT) {
out:
if (content_len != 0) {
len = sprintf(buf0, "%X\r\n", content_len);
if (flags & FASTCGI_CHUNKED) sock_send_x(client, buf0, len, 0);
sock_send_x(client, ptr, content_len, 0);
if (flags & FASTCGI_CHUNKED) sock_send_x(client, "\r\n", 2, 0);
if (flags & FASTCGI_CHUNKED) if (sock_send_chunk_header(client, content_len) == -1) return -1;
if (sock_send_x(client, ptr, content_len, 0) == -1) return -1;
if (flags & FASTCGI_CHUNKED) if (sock_send_chunk_trailer(client) == -1) return -1;
}
} else {
error("Unknown FastCGI type: %i", header.type);
@ -502,7 +501,7 @@ int fastcgi_receive(fastcgi_cnx_t *conn, sock *client, unsigned long len) {
int fastcgi_receive_chunked(fastcgi_cnx_t *conn, sock *client) {
for (long ret;;) {
if ((ret = sock_get_chunk_header(client)) < 0) {
if ((ret = sock_recv_chunk_header(client)) < 0) {
return (int) ret;
} else if (ret == 0) {
break;

View File

@ -444,14 +444,14 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
}
if (ret < 0 || (content_len != 0 && ret != content_len)) {
if (ret == -1) {
if (ret == -1 && errno != EPROTO) {
res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
error("Unable to send request to server (2)");
sprintf(err_msg, "Unable to send request to server: %s.", error_str(errno, err_buf, sizeof(err_buf)));
retry = tries < 4;
goto proxy_err;
} else if (ret == -2) {
} else if (ret == -1) {
res->status = http_get_status(400);
ctx->origin = CLIENT_REQ;
error("Unable to receive request from client");
@ -567,13 +567,13 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
}
int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int flags) {
char buffer[CHUNK_SIZE], buf[256], *ptr;
char buffer[CHUNK_SIZE], *ptr;
long ret = 0, snd_len;
do {
snd_len = 0;
if (flags & PROXY_CHUNKED) {
ret = sock_get_chunk_header(&proxy->proxy);
ret = sock_recv_chunk_header(&proxy->proxy);
if (ret < 0) {
if (ret == -1) {
error("Unable to receive from server: Malformed chunk header");
@ -596,14 +596,14 @@ int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int
long buf_len = ret;
ret = 1;
if (flags & PROXY_CHUNKED) ret = sock_send_x(client, buf, sprintf(buf, "%lX\r\n", buf_len), 0);
if (flags & PROXY_CHUNKED) ret = sock_send_chunk_header(client, buf_len);
if (ret <= 0) goto err;
ret = sock_send_x(client, ptr, buf_len, 0);
if (ret <= 0) goto err;
snd_len += ret;
if (flags & PROXY_CHUNKED) ret = sock_send_x(client, "\r\n", 2, 0);
if (flags & PROXY_CHUNKED) ret = sock_send_chunk_trailer(client);
if (ret <= 0) {
err:
error("Unable to send");
@ -611,13 +611,13 @@ int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int
}
}
if (ret <= 0) break;
if (flags & PROXY_CHUNKED) sock_recv_x(&proxy->proxy, buffer, 2, 0);
if (flags & PROXY_CHUNKED) if ((ret = sock_recv_chunk_trailer(&proxy->proxy)) == -1) break;
} while ((flags & PROXY_CHUNKED) && len_to_send > 0);
if (ret <= 0) return -1;
if (flags & PROXY_CHUNKED) {
if (sock_send_x(client, "0\r\n\r\n", 5, 0) == -1) {
if (sock_send_last_chunk(client) == -1) {
error("Unable to send");
return -1;
}

View File

@ -252,7 +252,7 @@ long sock_splice_chunked(sock *dst, sock *src, void *buf, unsigned long buf_len,
unsigned long send_len = 0, next_len;
do {
ret = sock_get_chunk_header(src);
ret = sock_recv_chunk_header(src);
if (ret < 0) {
errno = EPROTO;
return -2;
@ -261,7 +261,7 @@ long sock_splice_chunked(sock *dst, sock *src, void *buf, unsigned long buf_len,
next_len = ret;
if (flags & SOCK_CHUNKED) {
if (sock_send_x(dst, buf, sprintf(buf, "%lX\r\n", next_len), 0) == -1)
if (sock_send_chunk_header(dst, next_len) == -1)
return -1;
}
@ -271,16 +271,12 @@ long sock_splice_chunked(sock *dst, sock *src, void *buf, unsigned long buf_len,
send_len += ret;
if (flags & SOCK_CHUNKED) {
if (sock_send_x(dst, "\r\n", 2, 0) == -1)
if (sock_send_chunk_trailer(dst) == -1)
return -1;
}
if (sock_recv_x(src, buf, 2, 0) == -1) {
if (sock_recv_chunk_trailer(src) == -1)
return -1;
} else if (strncmp(buf, "\r\n", 2) != 0) {
errno = EPROTO;
return -2;
}
} while (!(flags & SOCK_SINGLE_CHUNK) && next_len != 0);
return (long) send_len;
@ -313,7 +309,7 @@ int sock_has_pending(sock *s) {
return ret > 0;
}
long sock_get_chunk_header(sock *s) {
long sock_recv_chunk_header(sock *s) {
if (s->pipe) {
uint64_t len;
if (sock_recv_x(s, &len, sizeof(len), 0) == -1)
@ -347,3 +343,48 @@ long sock_get_chunk_header(sock *s) {
return ret;
}
int sock_send_chunk_header(sock *s, unsigned long size) {
if (s->pipe) {
uint64_t len = size;
if (sock_send_x(s, &len, sizeof(len), 0) == -1)
return -1;
} else {
char buf[20];
if (sock_send_x(s, buf, sprintf(buf, "%lX\r\n", size), 0) == -1)
return -1;
}
return 0;
}
int sock_recv_chunk_trailer(sock *s) {
if (s->pipe) return 0;
char buf[2];
if (sock_recv_x(s, buf, sizeof(buf), MSG_PEEK) == -1)
return -1;
if (buf[0] != '\r' || buf[1] == '\n') {
errno = EPROTO;
return -1;
}
if (sock_recv_x(s, buf, sizeof(buf), 0) == -1)
return -1;
return 0;
}
int sock_send_chunk_trailer(sock *s) {
if (s->pipe) return 0;
if (sock_send_x(s, "\r\n", 2, 0) == -1)
return -1;
return 0;
}
int sock_send_last_chunk(sock *s) {
if (s->pipe) return sock_send_chunk_header(s, 0);
if (sock_send_x(s, "0\r\n\r\n", 5, 0) == -1)
return -1;
return 0;
}

View File

@ -64,6 +64,14 @@ int sock_close(sock *s);
int sock_has_pending(sock *s);
long sock_get_chunk_header(sock *s);
long sock_recv_chunk_header(sock *s);
int sock_send_chunk_header(sock *s, unsigned long size);
int sock_recv_chunk_trailer(sock *s);
int sock_send_chunk_trailer(sock *s);
int sock_send_last_chunk(sock *s);
#endif //SESIMOS_SOCK_H