char *test_IOBuf_streaming() { // test streaming from /dev/zero to /dev/null Connection *zero = fake_conn("/dev/zero", O_RDONLY); IOBuf *from = zero->iob; Connection *null = fake_conn("/dev/null", O_WRONLY); IOBuf *to = null->iob; int rc = IOBuf_stream(from, to, 500); mu_assert(rc == 500, "Didn't stream the right amount on small test."); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == 10 * 1024, "Didn't stream oversized amount."); fdclose(from->fd); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == -1, "Should fail if send side is closed."); mu_assert(from->avail >= 0, "Avail should never go below 0."); fdclose(to->fd); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == -1, "Should fail if recv side is closed."); fake_conn_close(zero); fake_conn_close(null); return NULL; }
int connection_proxy_reply_parse(Connection *conn) { int rc = 0; int total = 0; Proxy *proxy = Request_get_action(conn->req, proxy); httpclient_parser *client = conn->client; rc = Proxy_read_and_parse(conn); check(rc != -1, "Failed to read from proxy server: %s:%d", bdata(proxy->server), proxy->port); if(client->chunked) { // send the http header we have so far rc = IOBuf_stream(conn->proxy_iob, conn->iob, client->body_start); check_debug(rc != -1, "Failed streaming header to client."); // then just stream out the chunks we've got, as long as // Proxy_stream_chunks return 0 it means we've got more to send do { rc = Proxy_stream_chunks(conn); check(rc != -1, "Failed to stream chunked encoding to client."); } while(rc == 0); } else if(client->content_len >= 0) { total = client->body_start + client->content_len; rc = IOBuf_stream(conn->proxy_iob, conn->iob, total); check(rc != -1, "Failed streaming non-chunked response."); } else if(client->status == 204 || client->status == 304) { // According to the RFC, these MUST NOT incude a body. // Proxy might keep the connection open but not send content-length. rc = IOBuf_stream(conn->proxy_iob, conn->iob, client->body_start); check(rc != -1, "Failed streaming non-chunked response."); } else if(client->close || client->content_len == -1) { debug("Response requested a read until close."); Proxy_stream_to_close(conn); } else { sentinel("Should not reach this code, Tell Zed."); } Log_request(conn, client->status, client->content_len); if(client->close) { return REMOTE_CLOSE; } else { return REQ_RECV; } error: return FAILED; }