Commit 8f983ccd authored by Robert Lubos's avatar Robert Lubos Committed by Daniel DeGrasse
Browse files

net: lib: http_client: Fix end of message detection



HTTP 1.1 server has two ways of indicating the message body length -
either by providing the Content Length header, or by closing the
connection when the entire body has been transmitted.

The second method didn't work with Zephyr's HTTP client implementation,
as EOF on a socket was treated as an error condition. Therefore, if no
Content Length was provided by the server, such transfers would always
end up with ECONNRESET error.

In order to fix this, we need to notify the parser about the EOF on a
socket when connection is closed. It is the parser role to determine
whether the EOF was expected in current state (by marking end of message
flag) or not (by setting an error).

Signed-off-by: default avatarRobert Lubos <robert.lubos@nordicsemi.no>
parent b3ccee47
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -520,8 +520,8 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_
		} else if (fds[0].revents & ZSOCK_POLLIN) {
			received = zsock_recv(sock, req->internal.response.recv_buf + offset,
					      req->internal.response.recv_buf_len - offset, 0);
			if (received == 0) {
				/* Connection closed */
			if (received == 0 && total_received == 0) {
				/* Connection closed, no data received */
				goto closed;
			} else if (received < 0) {
				ret = -errno;
@@ -534,9 +534,12 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_
			/* Initialize the data length with the received data length. */
			req->internal.response.data_len = offset;

			/* In case of EOF on a socket, indicate this by passing
			 * 0 length to the parser.
			 */
			processed = http_parser_execute(
				&req->internal.parser, &req->internal.parser_settings,
				req->internal.response.recv_buf, offset);
				req->internal.response.recv_buf, received > 0 ? offset : 0);

			if (processed > offset) {
				LOG_ERR("HTTP parser error, too much data consumed");