diff --git a/src/lib/fastcgi.c b/src/lib/fastcgi.c index 9a73003..01e03a6 100644 --- a/src/lib/fastcgi.c +++ b/src/lib/fastcgi.c @@ -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; diff --git a/src/lib/proxy.c b/src/lib/proxy.c index c4b6815..26c5874 100644 --- a/src/lib/proxy.c +++ b/src/lib/proxy.c @@ -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; } diff --git a/src/lib/sock.c b/src/lib/sock.c index fc0915d..ee72b6e 100644 --- a/src/lib/sock.c +++ b/src/lib/sock.c @@ -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; +} diff --git a/src/lib/sock.h b/src/lib/sock.h index cf831f9..289df1e 100644 --- a/src/lib/sock.h +++ b/src/lib/sock.h @@ -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