Commit 570f0340f06f49b06ff536463cec8a2e2411b948

Edward Thomson 2020-06-01T19:10:38

httpclient: read_body should return 0 at EOF When users call `git_http_client_read_body`, it should return 0 at the end of a message. When the `on_message_complete` callback is called, this will set `client->state` to `DONE`. In our read loop, we look for this condition and exit. Without this, when there is no data left except the end of message chunk (`0\r\n`) in the http stream, we would block by reading the three bytes off the stream but not making progress in any `on_body` callbacks. Listening to the `on_message_complete` callback allows us to stop trying to read from the socket when we've read the end of message chunk.

diff --git a/src/transports/httpclient.c b/src/transports/httpclient.c
index bde67ca..af90129 100644
--- a/src/transports/httpclient.c
+++ b/src/transports/httpclient.c
@@ -1419,15 +1419,20 @@ int git_http_client_read_body(
 	client->parser.data = &parser_context;
 
 	/*
-	 * Clients expect to get a non-zero amount of data from us.
-	 * With a sufficiently small buffer, one might only read a chunk
-	 * length.  Loop until we actually have data to return.
+	 * Clients expect to get a non-zero amount of data from us,
+	 * so we either block until we have data to return, until we
+	 * hit EOF or there's an error.  Do this in a loop, since we
+	 * may end up reading only some stream metadata (like chunk
+	 * information).
 	 */
 	while (!parser_context.output_written) {
 		error = client_read_and_parse(client);
 
 		if (error <= 0)
 			goto done;
+
+		if (client->state == DONE)
+			break;
 	}
 
 	assert(parser_context.output_written <= INT_MAX);