diff --git a/src/lib/fastcgi.c b/src/lib/fastcgi.c index 5bcf687..9dde245 100644 --- a/src/lib/fastcgi.c +++ b/src/lib/fastcgi.c @@ -623,31 +623,9 @@ int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len) { int fastcgi_receive_chunked(fastcgi_conn *conn, sock *client) { long ret; unsigned long next_len; - char tmp[16]; while (1) { - ret = sock_recv(client, tmp, sizeof(tmp), MSG_PEEK); - if (ret <= 0) return -2; - else if (ret < 2) continue; - - int len = 0; - for (int i = 0; i < ret; i++) { - char ch = tmp[i]; - if (ch == '\r') { - continue; - } else if (ch == '\n') { - len = i + 1; - break; - } else if (!((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))) { - return -2; - } - } - if (len == 0) continue; - - next_len = strtol(tmp, NULL, 16); - ret = sock_recv(client, tmp, len, 0); - if (ret <= 0) return -2; - + next_len = sock_get_chunk_header(client); if (next_len <= 0) break; ret = fastcgi_receive(conn, client, next_len); diff --git a/src/lib/rev_proxy.c b/src/lib/rev_proxy.c index 61c837d..9f96478 100644 --- a/src/lib/rev_proxy.c +++ b/src/lib/rev_proxy.c @@ -478,20 +478,17 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) { do { snd_len = 0; if (flags & REV_PROXY_CHUNKED) { - char *pos; - ret = sock_recv(&rev_proxy, buffer, 16, MSG_PEEK); - if (ret <= 0) goto err0; - - len_to_send = strtol(buffer, NULL, 16); - pos = strstr(buffer, "\r\n"); - len = pos - buffer + 2; - sock_recv(&rev_proxy, buffer, len, 0); - if (ret <= 0) { - err0: - print("Unable to receive from server: %s", sock_strerror(&rev_proxy)); + ret = sock_get_chunk_header(&rev_proxy); + if (ret < 0) { + if (ret == -1) { + print("Unable to receive from server: Malformed chunk header"); + } else { + print("Unable to receive from server: %s", sock_strerror(&rev_proxy)); + } break; } + len_to_send = ret; if (len_to_send == 0 && (flags & REV_PROXY_COMPRESS)) { finish_comp = 1; len = 0; @@ -545,7 +542,7 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) { if (flags & REV_PROXY_CHUNKED) sock_recv(&rev_proxy, buffer, 2, 0); } while ((flags & REV_PROXY_CHUNKED) && len_to_send > 0); - if (ret <= 0) return (int) -1; + if (ret <= 0) return -1; if (flags & REV_PROXY_CHUNKED) { ret = sock_send(client, "0\r\n\r\n", 5, 0); diff --git a/src/lib/sock.c b/src/lib/sock.c index 4632ddd..63e3b56 100644 --- a/src/lib/sock.c +++ b/src/lib/sock.c @@ -7,6 +7,7 @@ */ #include "sock.h" +#include "utils.h" #include #include @@ -104,31 +105,12 @@ long sock_splice_chunked(sock *dst, sock *src, void *buf, unsigned long buf_len) long ret; unsigned long send_len = 0; unsigned long next_len; - char tmp[16]; while (1) { - ret = sock_recv(src, tmp, sizeof(tmp), MSG_PEEK); - if (ret <= 0) return -2; - else if (ret < 2) continue; - - int len = 0; - for (int i = 0; i < ret; i++) { - char ch = tmp[i]; - if (ch == '\r') { - continue; - } else if (ch == '\n') { - len = i + 1; - break; - } else if (!((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))) { - return -2; - } - } - if (len == 0) continue; - - next_len = strtol(tmp, NULL, 16); - ret = sock_recv(src, tmp, len, 0); - if (ret <= 0) return -2; + ret = sock_get_chunk_header(src); + if (ret < 0) return -2; + next_len = ret; if (next_len <= 0) break; ret = sock_splice(dst, src, buf, buf_len, next_len); @@ -184,3 +166,39 @@ int sock_poll_read(sock *sockets[], sock *readable[], sock *error[], int n_sock, int sock_poll_write(sock *sockets[], sock *writable[], sock *error[], int n_sock, int *n_writable, int *n_error, int timeout_ms) { return sock_poll(sockets, writable, error, n_sock, n_writable, n_error, POLLOUT, timeout_ms); } + +long sock_parse_chunk_header(const char *buf, long len, long *ret_len) { + for (int i = 0; i < len; i++) { + char ch = buf[i]; + if (ch == '\r') { + continue; + } else if (ch == '\n') { + if (ret_len != NULL) *ret_len = i + 1; + return strtol(buf, NULL, 16); + } else if (!((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))) { + return -2; + } + } + + return -1; +} + +long sock_get_chunk_header(sock *s) { + long ret, len; + char buf[16]; + + do { + print("debug1"); // TODO remove + ret = sock_recv(s, buf, sizeof(buf), MSG_PEEK); + if (ret <= 0) return -2; + else if (ret < 2) continue; + + ret = sock_parse_chunk_header(buf, ret, &len); + if (ret == -2) return -1; + } while (ret < 0); + + if (sock_recv(s, buf, len, 0) != len) + return -2; + + return ret; +} diff --git a/src/lib/sock.h b/src/lib/sock.h index d69f74e..40cb236 100644 --- a/src/lib/sock.h +++ b/src/lib/sock.h @@ -44,4 +44,8 @@ int sock_poll_read(sock *sockets[], sock *readable[], sock *error[], int n_sock, int sock_poll_write(sock *sockets[], sock *writable[], sock *error[], int n_sock, int *n_writable, int *n_error, int timeout_ms); +long sock_parse_chunk_header(const char *buf, long len, long *ret_len); + +long sock_get_chunk_header(sock *s); + #endif //SESIMOS_SOCK_H