1 /** @file
2  * @brief HTTP client API
3  *
4  * An API for applications to send HTTP requests
5  */
6 
7 /*
8  * Copyright (c) 2019 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(net_http_client, CONFIG_NET_HTTP_LOG_LEVEL);
15 
16 #include <zephyr/kernel.h>
17 #include <string.h>
18 #include <strings.h>
19 #include <errno.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 
23 #include <zephyr/net/net_ip.h>
24 #include <zephyr/net/socket.h>
25 #include <zephyr/net/http/client.h>
26 #include <zephyr/net/http/status.h>
27 
28 #include "net_private.h"
29 
30 #define HTTP_CONTENT_LEN_SIZE 11
31 #define MAX_SEND_BUF_LEN 192
32 
sendall(int sock,const void * buf,size_t len,const k_timepoint_t req_end_timepoint)33 static int sendall(int sock, const void *buf, size_t len,
34 			const k_timepoint_t req_end_timepoint)
35 {
36 	while (len) {
37 		ssize_t out_len = zsock_send(sock, buf, len, 0);
38 
39 		if ((out_len == 0) || (out_len < 0 && errno == EAGAIN)) {
40 			struct zsock_pollfd pfd;
41 			int pollres;
42 			k_ticks_t req_timeout_ticks =
43 				sys_timepoint_timeout(req_end_timepoint).ticks;
44 			int req_timeout_ms = k_ticks_to_ms_floor32(req_timeout_ticks);
45 
46 			pfd.fd = sock;
47 			pfd.events = ZSOCK_POLLOUT;
48 			pollres = zsock_poll(&pfd, 1, req_timeout_ms);
49 			if (pollres == 0) {
50 				return -ETIMEDOUT;
51 			} else if (pollres > 0) {
52 				continue;
53 			} else {
54 				return -errno;
55 			}
56 		} else if (out_len < 0) {
57 			return -errno;
58 		}
59 
60 		buf = (const char *)buf + out_len;
61 		len -= out_len;
62 	}
63 
64 	return 0;
65 }
66 
http_send_data(int sock,char * send_buf,size_t send_buf_max_len,size_t * send_buf_pos,const k_timepoint_t req_end_timepoint,...)67 static int http_send_data(int sock, char *send_buf,
68 			  size_t send_buf_max_len, size_t *send_buf_pos,
69 			  const k_timepoint_t req_end_timepoint,
70 			  ...)
71 {
72 	const char *data;
73 	va_list va;
74 	int ret, end_of_send = *send_buf_pos;
75 	int end_of_data, remaining_len;
76 	int sent = 0;
77 
78 	va_start(va, req_end_timepoint);
79 
80 	data = va_arg(va, const char *);
81 
82 	while (data) {
83 		end_of_data = 0;
84 
85 		do {
86 			int to_be_copied;
87 
88 			remaining_len = strlen(data + end_of_data);
89 			to_be_copied = send_buf_max_len - end_of_send;
90 
91 			if (remaining_len > to_be_copied) {
92 				strncpy(send_buf + end_of_send,
93 					data + end_of_data,
94 					to_be_copied);
95 
96 				end_of_send += to_be_copied;
97 				end_of_data += to_be_copied;
98 				remaining_len -= to_be_copied;
99 
100 				LOG_HEXDUMP_DBG(send_buf, end_of_send,
101 						"Data to send");
102 
103 				ret = sendall(sock, send_buf, end_of_send, req_end_timepoint);
104 				if (ret < 0) {
105 					NET_DBG("Cannot send %d bytes (%d)",
106 						end_of_send, ret);
107 					goto err;
108 				}
109 				sent += end_of_send;
110 				end_of_send = 0;
111 				continue;
112 			} else {
113 				memcpy(send_buf + end_of_send,
114 				       data + end_of_data,
115 				       remaining_len);
116 				end_of_send += remaining_len;
117 				remaining_len = 0;
118 			}
119 		} while (remaining_len > 0);
120 
121 		data = va_arg(va, const char *);
122 	}
123 
124 	va_end(va);
125 
126 	if (end_of_send > (int)send_buf_max_len) {
127 		NET_ERR("Sending overflow (%d > %zd)", end_of_send,
128 			send_buf_max_len);
129 		return -EMSGSIZE;
130 	}
131 
132 	*send_buf_pos = end_of_send;
133 
134 	return sent;
135 
136 err:
137 	va_end(va);
138 
139 	return ret;
140 }
141 
http_flush_data(int sock,const char * send_buf,size_t send_buf_len,const k_timepoint_t req_end_timepoint)142 static int http_flush_data(int sock, const char *send_buf, size_t send_buf_len,
143 				const k_timepoint_t req_end_timepoint)
144 {
145 	int ret;
146 
147 	LOG_HEXDUMP_DBG(send_buf, send_buf_len, "Data to send");
148 
149 	ret = sendall(sock, send_buf, send_buf_len, req_end_timepoint);
150 	if (ret < 0) {
151 		return ret;
152 	}
153 
154 	return (int)send_buf_len;
155 }
156 
print_header_field(size_t len,const char * str)157 static void print_header_field(size_t len, const char *str)
158 {
159 	if (IS_ENABLED(CONFIG_NET_HTTP_LOG_LEVEL_DBG)) {
160 #define MAX_OUTPUT_LEN 128
161 		char output[MAX_OUTPUT_LEN];
162 
163 		/* The value of len does not count \0 so we need to increase it
164 		 * by one.
165 		 */
166 		if ((len + 1) > sizeof(output)) {
167 			len = sizeof(output) - 1;
168 		}
169 
170 		snprintk(output, len + 1, "%s", str);
171 
172 		NET_DBG("[%zd] %s", len, output);
173 	}
174 }
175 
on_url(struct http_parser * parser,const char * at,size_t length)176 static int on_url(struct http_parser *parser, const char *at, size_t length)
177 {
178 	struct http_request *req = CONTAINER_OF(parser,
179 						struct http_request,
180 						internal.parser);
181 	print_header_field(length, at);
182 
183 	if (req->internal.response.http_cb &&
184 	    req->internal.response.http_cb->on_url) {
185 		req->internal.response.http_cb->on_url(parser, at, length);
186 	}
187 
188 	return 0;
189 }
190 
on_status(struct http_parser * parser,const char * at,size_t length)191 static int on_status(struct http_parser *parser, const char *at, size_t length)
192 {
193 	struct http_request *req = CONTAINER_OF(parser,
194 						struct http_request,
195 						internal.parser);
196 	uint16_t len;
197 
198 	len = MIN(length, sizeof(req->internal.response.http_status) - 1);
199 	memcpy(req->internal.response.http_status, at, len);
200 	req->internal.response.http_status[len] = 0;
201 	req->internal.response.http_status_code =
202 		(uint16_t)parser->status_code;
203 
204 	NET_DBG("HTTP response status %d %s", parser->status_code,
205 		req->internal.response.http_status);
206 
207 	if (req->internal.response.http_cb &&
208 	    req->internal.response.http_cb->on_status) {
209 		req->internal.response.http_cb->on_status(parser, at, length);
210 	}
211 
212 	return 0;
213 }
214 
on_header_field(struct http_parser * parser,const char * at,size_t length)215 static int on_header_field(struct http_parser *parser, const char *at,
216 			   size_t length)
217 {
218 	struct http_request *req = CONTAINER_OF(parser,
219 						struct http_request,
220 						internal.parser);
221 	static const char content_len[] = "Content-Length";
222 	static const char content_range[] = "Content-Range";
223 
224 	uint16_t content_len_len = sizeof(content_len) - 1;
225 	uint16_t content_range_len = sizeof(content_range) - 1;
226 
227 	if (length >= content_len_len && strncasecmp(at, content_len, content_len_len) == 0) {
228 		req->internal.response.cl_present = true;
229 	} else if (length >= content_range_len &&
230 		   strncasecmp(at, content_range, content_range_len) == 0) {
231 		req->internal.response.cr_present = true;
232 	}
233 
234 	print_header_field(length, at);
235 
236 	if (req->internal.response.http_cb &&
237 	    req->internal.response.http_cb->on_header_field) {
238 		req->internal.response.http_cb->on_header_field(parser, at,
239 								length);
240 	}
241 
242 	return 0;
243 }
244 
245 #define MAX_NUM_DIGITS	16
246 
on_header_value(struct http_parser * parser,const char * at,size_t length)247 static int on_header_value(struct http_parser *parser, const char *at,
248 			   size_t length)
249 {
250 	struct http_request *req = CONTAINER_OF(parser,
251 						struct http_request,
252 						internal.parser);
253 	char str[MAX_NUM_DIGITS];
254 
255 	if (req->internal.response.cl_present) {
256 		if (length <= MAX_NUM_DIGITS - 1) {
257 			long int num;
258 
259 			memcpy(str, at, length);
260 			str[length] = 0;
261 
262 			num = strtol(str, NULL, 10);
263 			if (num == LONG_MIN || num == LONG_MAX) {
264 				return -EINVAL;
265 			}
266 
267 			req->internal.response.content_length = num;
268 		}
269 
270 		req->internal.response.cl_present = false;
271 	}
272 
273 	if (req->internal.response.cr_present) {
274 		req->internal.response.content_range.start = parser->content_range.start;
275 		req->internal.response.content_range.end = parser->content_range.end;
276 		req->internal.response.content_range.total = parser->content_range.total;
277 		req->internal.response.cr_present = false;
278 	}
279 
280 	if (req->internal.response.http_cb &&
281 	    req->internal.response.http_cb->on_header_value) {
282 		req->internal.response.http_cb->on_header_value(parser, at,
283 								length);
284 	}
285 
286 	print_header_field(length, at);
287 
288 	return 0;
289 }
290 
on_body(struct http_parser * parser,const char * at,size_t length)291 static int on_body(struct http_parser *parser, const char *at, size_t length)
292 {
293 	struct http_request *req = CONTAINER_OF(parser,
294 						struct http_request,
295 						internal.parser);
296 
297 	req->internal.response.body_found = 1;
298 	req->internal.response.processed += length;
299 
300 	NET_DBG("Processed %zd length %zd", req->internal.response.processed,
301 		length);
302 
303 	if (req->internal.response.http_cb &&
304 	    req->internal.response.http_cb->on_body) {
305 		req->internal.response.http_cb->on_body(parser, at, length);
306 	}
307 
308 	/* Reset the body_frag_start pointer for each fragment. */
309 	if (!req->internal.response.body_frag_start) {
310 		req->internal.response.body_frag_start = (uint8_t *)at;
311 	}
312 
313 	/* Calculate the length of the body contained in the recv_buf */
314 	req->internal.response.body_frag_len = req->internal.response.data_len -
315 		(req->internal.response.body_frag_start - req->internal.response.recv_buf);
316 
317 	return 0;
318 }
319 
on_headers_complete(struct http_parser * parser)320 static int on_headers_complete(struct http_parser *parser)
321 {
322 	struct http_request *req = CONTAINER_OF(parser,
323 						struct http_request,
324 						internal.parser);
325 
326 	if (req->internal.response.http_cb &&
327 	    req->internal.response.http_cb->on_headers_complete) {
328 		req->internal.response.http_cb->on_headers_complete(parser);
329 	}
330 
331 	if (parser->status_code == HTTP_101_SWITCHING_PROTOCOLS) {
332 		NET_DBG("Switching protocols, skipping body");
333 		return 1;
334 	}
335 
336 	if (parser->status_code >= 500 && parser->status_code < 600) {
337 		NET_DBG("Status %d, skipping body", parser->status_code);
338 		return 1;
339 	}
340 
341 	if ((req->method == HTTP_HEAD || req->method == HTTP_OPTIONS) &&
342 	    req->internal.response.content_length > 0) {
343 		NET_DBG("No body expected");
344 		return 1;
345 	}
346 
347 	NET_DBG("Headers complete");
348 
349 	return 0;
350 }
351 
on_message_begin(struct http_parser * parser)352 static int on_message_begin(struct http_parser *parser)
353 {
354 	struct http_request *req = CONTAINER_OF(parser,
355 						struct http_request,
356 						internal.parser);
357 
358 	if (req->internal.response.http_cb &&
359 	    req->internal.response.http_cb->on_message_begin) {
360 		req->internal.response.http_cb->on_message_begin(parser);
361 	}
362 
363 	NET_DBG("-- HTTP %s response (headers) --",
364 		http_method_str(req->method));
365 
366 	return 0;
367 }
368 
on_message_complete(struct http_parser * parser)369 static int on_message_complete(struct http_parser *parser)
370 {
371 	struct http_request *req = CONTAINER_OF(parser,
372 						struct http_request,
373 						internal.parser);
374 
375 	if (req->internal.response.http_cb &&
376 	    req->internal.response.http_cb->on_message_complete) {
377 		req->internal.response.http_cb->on_message_complete(parser);
378 	}
379 
380 	NET_DBG("-- HTTP %s response (complete) --",
381 		http_method_str(req->method));
382 
383 	req->internal.response.message_complete = 1;
384 
385 	return 0;
386 }
387 
on_chunk_header(struct http_parser * parser)388 static int on_chunk_header(struct http_parser *parser)
389 {
390 	struct http_request *req = CONTAINER_OF(parser,
391 						struct http_request,
392 						internal.parser);
393 
394 	if (req->internal.response.http_cb &&
395 	    req->internal.response.http_cb->on_chunk_header) {
396 		req->internal.response.http_cb->on_chunk_header(parser);
397 	}
398 
399 	return 0;
400 }
401 
on_chunk_complete(struct http_parser * parser)402 static int on_chunk_complete(struct http_parser *parser)
403 {
404 	struct http_request *req = CONTAINER_OF(parser,
405 						struct http_request,
406 						internal.parser);
407 
408 	if (req->internal.response.http_cb &&
409 	    req->internal.response.http_cb->on_chunk_complete) {
410 		req->internal.response.http_cb->on_chunk_complete(parser);
411 	}
412 
413 	return 0;
414 }
415 
http_client_init_parser(struct http_parser * parser,struct http_parser_settings * settings)416 static void http_client_init_parser(struct http_parser *parser,
417 				    struct http_parser_settings *settings)
418 {
419 	http_parser_init(parser, HTTP_RESPONSE);
420 
421 	settings->on_body = on_body;
422 	settings->on_chunk_complete = on_chunk_complete;
423 	settings->on_chunk_header = on_chunk_header;
424 	settings->on_headers_complete = on_headers_complete;
425 	settings->on_header_field = on_header_field;
426 	settings->on_header_value = on_header_value;
427 	settings->on_message_begin = on_message_begin;
428 	settings->on_message_complete = on_message_complete;
429 	settings->on_status = on_status;
430 	settings->on_url = on_url;
431 }
432 
433 /* Report a NULL HTTP response to the caller.
434  * A NULL response is when the HTTP server intentionally closes the TLS socket (using FINACK)
435  * without sending any HTTP payload.
436  */
http_report_null(struct http_request * req)437 static void http_report_null(struct http_request *req)
438 {
439 	if (req->internal.response.cb) {
440 		NET_DBG("Calling callback for Final Data"
441 			"(NULL HTTP response)");
442 
443 		/* Status code 0 representing a null response */
444 		req->internal.response.http_status_code = 0;
445 
446 		/* Zero out related response metrics */
447 		req->internal.response.processed = 0;
448 		req->internal.response.data_len = 0;
449 		req->internal.response.content_length = 0;
450 		req->internal.response.body_frag_start = NULL;
451 		memset(req->internal.response.http_status, 0, HTTP_STATUS_STR_SIZE);
452 
453 		req->internal.response.cb(&req->internal.response, HTTP_DATA_FINAL,
454 					  req->internal.user_data);
455 	}
456 }
457 
458 /* Report a completed HTTP transaction (with no error) to the caller */
http_report_complete(struct http_request * req)459 static void http_report_complete(struct http_request *req)
460 {
461 	if (req->internal.response.cb) {
462 		NET_DBG("Calling callback for %zd len data", req->internal.response.data_len);
463 		(void)req->internal.response.cb(&req->internal.response,
464 						HTTP_DATA_FINAL,
465 						req->internal.user_data);
466 	}
467 }
468 
469 /* Report that some data has been received, but the HTTP transaction is still ongoing. */
http_report_progress(struct http_request * req)470 static int http_report_progress(struct http_request *req)
471 {
472 	if (req->internal.response.cb) {
473 		NET_DBG("Calling callback for partitioned %zd len data",
474 			req->internal.response.data_len);
475 
476 		return req->internal.response.cb(&req->internal.response,
477 						 HTTP_DATA_MORE,
478 						 req->internal.user_data);
479 	}
480 
481 	return 0;
482 }
483 
http_wait_data(int sock,struct http_request * req,const k_timepoint_t req_end_timepoint)484 static int http_wait_data(int sock, struct http_request *req, const k_timepoint_t req_end_timepoint)
485 {
486 	int total_received = 0;
487 	size_t offset = 0, processed = 0;
488 	int received, ret;
489 	struct zsock_pollfd fds[1];
490 	int nfds = 1;
491 
492 	fds[0].fd = sock;
493 	fds[0].events = ZSOCK_POLLIN;
494 
495 	do {
496 		k_ticks_t req_timeout_ticks =
497 			sys_timepoint_timeout(req_end_timepoint).ticks;
498 		int req_timeout_ms = k_ticks_to_ms_floor32(req_timeout_ticks);
499 
500 		ret = zsock_poll(fds, nfds, req_timeout_ms);
501 		if (ret == 0) {
502 			LOG_DBG("Timeout");
503 			ret = -ETIMEDOUT;
504 			goto error;
505 		} else if (ret < 0) {
506 			ret = -errno;
507 			goto error;
508 		}
509 
510 		if (fds[0].revents & ZSOCK_POLLERR) {
511 			int sock_err;
512 			net_socklen_t optlen = sizeof(sock_err);
513 
514 			(void)zsock_getsockopt(sock, ZSOCK_SOL_SOCKET, ZSOCK_SO_ERROR,
515 					       &sock_err, &optlen);
516 			ret = -sock_err;
517 			goto error;
518 		} else if (fds[0].revents & ZSOCK_POLLNVAL) {
519 			ret = -EBADF;
520 			goto error;
521 		} else if (fds[0].revents & ZSOCK_POLLIN) {
522 			received = zsock_recv(sock, req->internal.response.recv_buf + offset,
523 					      req->internal.response.recv_buf_len - offset, 0);
524 			if (received == 0 && total_received == 0) {
525 				/* Connection closed, no data received */
526 				goto closed;
527 			} else if (received < 0) {
528 				ret = -errno;
529 				goto error;
530 			}
531 
532 			total_received += received;
533 			offset += received;
534 
535 			/* Initialize the data length with the received data length. */
536 			req->internal.response.data_len = offset;
537 
538 			/* In case of EOF on a socket, indicate this by passing
539 			 * 0 length to the parser.
540 			 */
541 			processed = http_parser_execute(
542 				&req->internal.parser, &req->internal.parser_settings,
543 				req->internal.response.recv_buf, received > 0 ? offset : 0);
544 
545 			if (processed > offset) {
546 				LOG_ERR("HTTP parser error, too much data consumed");
547 				ret = -EBADMSG;
548 				goto error;
549 			}
550 
551 			if (req->internal.parser.http_errno != HPE_OK) {
552 				LOG_ERR("HTTP parsing error, %d",
553 					req->internal.parser.http_errno);
554 				ret = -EBADMSG;
555 				goto error;
556 			}
557 
558 			/* Update the response data length with the actually
559 			 * processed bytes.
560 			 */
561 			req->internal.response.data_len = processed;
562 			offset -= processed;
563 
564 			if (offset >= req->internal.response.recv_buf_len) {
565 				/* This means the parser did not consume any data
566 				 * and we can't fit any more in the buffer.
567 				 */
568 				LOG_ERR("HTTP RX buffer full, cannot proceed");
569 				ret = -ENOMEM;
570 				goto error;
571 			}
572 
573 			if (req->internal.response.message_complete) {
574 				http_report_complete(req);
575 			} else {
576 				ret = http_report_progress(req);
577 				if (ret < 0) {
578 					LOG_DBG("Connection aborted by the application (%d)",
579 						ret);
580 					return -ECONNABORTED;
581 				}
582 
583 				/* Re-use the result buffer and start to fill it again */
584 				req->internal.response.data_len = 0;
585 				req->internal.response.body_frag_start = NULL;
586 				req->internal.response.body_frag_len = 0;
587 			}
588 
589 			if (offset > 0) {
590 				/* In case there are any unprocessed data left,
591 				 * move them to the front of the buffer.
592 				 */
593 				memmove(req->internal.response.recv_buf,
594 					req->internal.response.recv_buf + processed,
595 					offset);
596 			}
597 		} else if (fds[0].revents & ZSOCK_POLLHUP) {
598 			/* Connection closed */
599 			goto closed;
600 		}
601 
602 	} while (!req->internal.response.message_complete);
603 
604 	/* If there's still some data left in the buffer after HTTP processing,
605 	 * reflect this in data_len variable.
606 	 */
607 	req->data_len = offset;
608 
609 	return total_received;
610 
611 closed:
612 	LOG_DBG("Connection closed");
613 
614 	/* If connection was closed with no data sent, this is a NULL response, and is a special
615 	 * case valid response.
616 	 */
617 	if (total_received == 0) {
618 		http_report_null(req);
619 		return total_received;
620 	}
621 
622 	/* Otherwise, connection was closed mid-way through response, and this should be
623 	 * considered an error.
624 	 */
625 	ret = -ECONNRESET;
626 
627 error:
628 	LOG_DBG("Connection error (%d)", ret);
629 	return ret;
630 }
631 
http_client_req(int sock,struct http_request * req,int32_t timeout,void * user_data)632 int http_client_req(int sock, struct http_request *req,
633 		    int32_t timeout, void *user_data)
634 {
635 	/* Utilize the network usage by sending data in bigger blocks */
636 	char send_buf[MAX_SEND_BUF_LEN];
637 	const size_t send_buf_max_len = sizeof(send_buf);
638 	size_t send_buf_pos = 0;
639 	int total_sent = 0;
640 	int ret, total_recv, i;
641 	const char *method;
642 	k_timeout_t req_timeout = (timeout == SYS_FOREVER_MS) ? K_FOREVER : K_MSEC(timeout);
643 	k_timepoint_t req_end_timepoint = sys_timepoint_calc(req_timeout);
644 
645 	if (sock < 0 || req == NULL || req->response == NULL ||
646 	    req->recv_buf == NULL || req->recv_buf_len == 0) {
647 		return -EINVAL;
648 	}
649 
650 	memset(&req->internal.response, 0, sizeof(req->internal.response));
651 
652 	req->internal.response.http_cb = req->http_cb;
653 	req->internal.response.cb = req->response;
654 	req->internal.response.recv_buf = req->recv_buf;
655 	req->internal.response.recv_buf_len = req->recv_buf_len;
656 	req->internal.user_data = user_data;
657 	req->internal.sock = sock;
658 
659 	method = http_method_str(req->method);
660 
661 	ret = http_send_data(sock, send_buf, send_buf_max_len, &send_buf_pos,
662 				req_end_timepoint, method,
663 				" ", req->url, " ", req->protocol,
664 				HTTP_CRLF, NULL);
665 	if (ret < 0) {
666 		goto out;
667 	}
668 
669 	total_sent += ret;
670 
671 	if (req->port) {
672 		ret = http_send_data(sock, send_buf, send_buf_max_len,
673 					&send_buf_pos, req_end_timepoint, "Host", ": ", req->host,
674 					":", req->port, HTTP_CRLF, NULL);
675 
676 		if (ret < 0) {
677 			goto out;
678 		}
679 
680 		total_sent += ret;
681 	} else {
682 		ret = http_send_data(sock, send_buf, send_buf_max_len,
683 				     &send_buf_pos, req_end_timepoint, "Host", ": ", req->host,
684 				     HTTP_CRLF, NULL);
685 
686 		if (ret < 0) {
687 			goto out;
688 		}
689 
690 		total_sent += ret;
691 	}
692 
693 	if (req->optional_headers_cb) {
694 		ret = http_flush_data(sock, send_buf, send_buf_pos, req_end_timepoint);
695 		if (ret < 0) {
696 			goto out;
697 		}
698 
699 		send_buf_pos = 0;
700 		total_sent += ret;
701 
702 		ret = req->optional_headers_cb(sock, req, user_data);
703 		if (ret < 0) {
704 			goto out;
705 		}
706 
707 		total_sent += ret;
708 	} else {
709 		for (i = 0; req->optional_headers && req->optional_headers[i];
710 		     i++) {
711 			ret = http_send_data(sock, send_buf, send_buf_max_len,
712 					     &send_buf_pos, req_end_timepoint,
713 					     req->optional_headers[i], NULL);
714 			if (ret < 0) {
715 				goto out;
716 			}
717 
718 			total_sent += ret;
719 		}
720 	}
721 
722 	for (i = 0; req->header_fields && req->header_fields[i]; i++) {
723 		ret = http_send_data(sock, send_buf, send_buf_max_len,
724 				     &send_buf_pos, req_end_timepoint, req->header_fields[i],
725 				     NULL);
726 		if (ret < 0) {
727 			goto out;
728 		}
729 
730 		total_sent += ret;
731 	}
732 
733 	if (req->content_type_value) {
734 		ret = http_send_data(sock, send_buf, send_buf_max_len,
735 				     &send_buf_pos, req_end_timepoint, "Content-Type", ": ",
736 				     req->content_type_value, HTTP_CRLF, NULL);
737 		if (ret < 0) {
738 			goto out;
739 		}
740 
741 		total_sent += ret;
742 	}
743 
744 	if (req->payload || req->payload_cb) {
745 		if (req->payload_len) {
746 			char content_len_str[HTTP_CONTENT_LEN_SIZE];
747 
748 			ret = snprintk(content_len_str, HTTP_CONTENT_LEN_SIZE,
749 				       "%zd", req->payload_len);
750 			if (ret <= 0 || ret >= HTTP_CONTENT_LEN_SIZE) {
751 				ret = -ENOMEM;
752 				goto out;
753 			}
754 
755 			ret = http_send_data(sock, send_buf, send_buf_max_len,
756 						&send_buf_pos, req_end_timepoint,
757 						"Content-Length", ": ",
758 						content_len_str, HTTP_CRLF,
759 						HTTP_CRLF, NULL);
760 		} else {
761 			ret = http_send_data(sock, send_buf, send_buf_max_len,
762 				     &send_buf_pos, req_end_timepoint, HTTP_CRLF, NULL);
763 		}
764 
765 		if (ret < 0) {
766 			goto out;
767 		}
768 
769 		total_sent += ret;
770 
771 		ret = http_flush_data(sock, send_buf, send_buf_pos, req_end_timepoint);
772 		if (ret < 0) {
773 			goto out;
774 		}
775 
776 		send_buf_pos = 0;
777 		total_sent += ret;
778 
779 		if (req->payload_cb) {
780 			ret = req->payload_cb(sock, req, user_data);
781 			if (ret < 0) {
782 				goto out;
783 			}
784 
785 			total_sent += ret;
786 		} else {
787 			uint32_t length;
788 
789 			if (req->payload_len == 0) {
790 				length = strlen(req->payload);
791 			} else {
792 				length = req->payload_len;
793 			}
794 
795 			ret = sendall(sock, req->payload, length, req_end_timepoint);
796 			if (ret < 0) {
797 				goto out;
798 			}
799 
800 			total_sent += length;
801 		}
802 	} else {
803 		ret = http_send_data(sock, send_buf, send_buf_max_len,
804 				     &send_buf_pos, req_end_timepoint, HTTP_CRLF, NULL);
805 		if (ret < 0) {
806 			goto out;
807 		}
808 
809 		total_sent += ret;
810 	}
811 
812 	if (send_buf_pos > 0) {
813 		ret = http_flush_data(sock, send_buf, send_buf_pos, req_end_timepoint);
814 		if (ret < 0) {
815 			goto out;
816 		}
817 
818 		total_sent += ret;
819 	}
820 
821 	NET_DBG("Sent %d bytes", total_sent);
822 
823 	http_client_init_parser(&req->internal.parser,
824 				&req->internal.parser_settings);
825 
826 	/* Request is sent, now wait data to be received */
827 	total_recv = http_wait_data(sock, req, req_end_timepoint);
828 	if (total_recv < 0) {
829 		NET_DBG("Wait data failure (%d)", total_recv);
830 		ret = total_recv;
831 		goto out;
832 	}
833 
834 	NET_DBG("Received %d bytes", total_recv);
835 
836 	return total_sent;
837 
838 out:
839 	return ret;
840 }
841