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, 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 
27 #include "net_private.h"
28 
29 #define HTTP_CONTENT_LEN_SIZE 11
30 #define MAX_SEND_BUF_LEN 192
31 
sendall(int sock,const void * buf,size_t len)32 static int sendall(int sock, const void *buf, size_t len)
33 {
34 	while (len) {
35 		ssize_t out_len = zsock_send(sock, buf, len, 0);
36 
37 		if (out_len < 0) {
38 			return -errno;
39 		}
40 
41 		buf = (const char *)buf + out_len;
42 		len -= out_len;
43 	}
44 
45 	return 0;
46 }
47 
http_send_data(int sock,char * send_buf,size_t send_buf_max_len,size_t * send_buf_pos,...)48 static int http_send_data(int sock, char *send_buf,
49 			  size_t send_buf_max_len, size_t *send_buf_pos,
50 			  ...)
51 {
52 	const char *data;
53 	va_list va;
54 	int ret, end_of_send = *send_buf_pos;
55 	int end_of_data, remaining_len;
56 	int sent = 0;
57 
58 	va_start(va, send_buf_pos);
59 
60 	data = va_arg(va, const char *);
61 
62 	while (data) {
63 		end_of_data = 0;
64 
65 		do {
66 			int to_be_copied;
67 
68 			remaining_len = strlen(data + end_of_data);
69 			to_be_copied = send_buf_max_len - end_of_send;
70 
71 			if (remaining_len > to_be_copied) {
72 				strncpy(send_buf + end_of_send,
73 					data + end_of_data,
74 					to_be_copied);
75 
76 				end_of_send += to_be_copied;
77 				end_of_data += to_be_copied;
78 				remaining_len -= to_be_copied;
79 
80 				LOG_HEXDUMP_DBG(send_buf, end_of_send,
81 						"Data to send");
82 
83 				ret = sendall(sock, send_buf, end_of_send);
84 				if (ret < 0) {
85 					NET_DBG("Cannot send %d bytes (%d)",
86 						end_of_send, ret);
87 					goto err;
88 				}
89 				sent += end_of_send;
90 				end_of_send = 0;
91 				continue;
92 			} else {
93 				strncpy(send_buf + end_of_send,
94 					data + end_of_data,
95 					remaining_len);
96 				end_of_send += remaining_len;
97 				remaining_len = 0;
98 			}
99 		} while (remaining_len > 0);
100 
101 		data = va_arg(va, const char *);
102 	}
103 
104 	va_end(va);
105 
106 	if (end_of_send > (int)send_buf_max_len) {
107 		NET_ERR("Sending overflow (%d > %zd)", end_of_send,
108 			send_buf_max_len);
109 		return -EMSGSIZE;
110 	}
111 
112 	*send_buf_pos = end_of_send;
113 
114 	return sent;
115 
116 err:
117 	va_end(va);
118 
119 	return ret;
120 }
121 
http_flush_data(int sock,const char * send_buf,size_t send_buf_len)122 static int http_flush_data(int sock, const char *send_buf, size_t send_buf_len)
123 {
124 	int ret;
125 
126 	LOG_HEXDUMP_DBG(send_buf, send_buf_len, "Data to send");
127 
128 	ret = sendall(sock, send_buf, send_buf_len);
129 	if (ret < 0) {
130 		return ret;
131 	}
132 
133 	return (int)send_buf_len;
134 }
135 
print_header_field(size_t len,const char * str)136 static void print_header_field(size_t len, const char *str)
137 {
138 	if (IS_ENABLED(CONFIG_NET_HTTP_LOG_LEVEL_DBG)) {
139 #define MAX_OUTPUT_LEN 128
140 		char output[MAX_OUTPUT_LEN];
141 
142 		/* The value of len does not count \0 so we need to increase it
143 		 * by one.
144 		 */
145 		if ((len + 1) > sizeof(output)) {
146 			len = sizeof(output) - 1;
147 		}
148 
149 		snprintk(output, len + 1, "%s", str);
150 
151 		NET_DBG("[%zd] %s", len, output);
152 	}
153 }
154 
on_url(struct http_parser * parser,const char * at,size_t length)155 static int on_url(struct http_parser *parser, const char *at, size_t length)
156 {
157 	struct http_request *req = CONTAINER_OF(parser,
158 						struct http_request,
159 						internal.parser);
160 	print_header_field(length, at);
161 
162 	if (req->internal.response.http_cb &&
163 	    req->internal.response.http_cb->on_url) {
164 		req->internal.response.http_cb->on_url(parser, at, length);
165 	}
166 
167 	return 0;
168 }
169 
on_status(struct http_parser * parser,const char * at,size_t length)170 static int on_status(struct http_parser *parser, const char *at, size_t length)
171 {
172 	struct http_request *req = CONTAINER_OF(parser,
173 						struct http_request,
174 						internal.parser);
175 	uint16_t len;
176 
177 	len = MIN(length, sizeof(req->internal.response.http_status) - 1);
178 	memcpy(req->internal.response.http_status, at, len);
179 	req->internal.response.http_status[len] = 0;
180 	req->internal.response.http_status_code =
181 		(uint16_t)parser->status_code;
182 
183 	NET_DBG("HTTP response status %d %s", parser->status_code,
184 		req->internal.response.http_status);
185 
186 	if (req->internal.response.http_cb &&
187 	    req->internal.response.http_cb->on_status) {
188 		req->internal.response.http_cb->on_status(parser, at, length);
189 	}
190 
191 	return 0;
192 }
193 
on_header_field(struct http_parser * parser,const char * at,size_t length)194 static int on_header_field(struct http_parser *parser, const char *at,
195 			   size_t length)
196 {
197 	struct http_request *req = CONTAINER_OF(parser,
198 						struct http_request,
199 						internal.parser);
200 	const char *content_len = "Content-Length";
201 	uint16_t len;
202 
203 	len = strlen(content_len);
204 	if (length >= len && strncasecmp(at, content_len, len) == 0) {
205 		req->internal.response.cl_present = true;
206 	}
207 
208 	print_header_field(length, at);
209 
210 	if (req->internal.response.http_cb &&
211 	    req->internal.response.http_cb->on_header_field) {
212 		req->internal.response.http_cb->on_header_field(parser, at,
213 								length);
214 	}
215 
216 	return 0;
217 }
218 
219 #define MAX_NUM_DIGITS	16
220 
on_header_value(struct http_parser * parser,const char * at,size_t length)221 static int on_header_value(struct http_parser *parser, const char *at,
222 			   size_t length)
223 {
224 	struct http_request *req = CONTAINER_OF(parser,
225 						struct http_request,
226 						internal.parser);
227 	char str[MAX_NUM_DIGITS];
228 
229 	if (req->internal.response.cl_present) {
230 		if (length <= MAX_NUM_DIGITS - 1) {
231 			long int num;
232 
233 			memcpy(str, at, length);
234 			str[length] = 0;
235 
236 			num = strtol(str, NULL, 10);
237 			if (num == LONG_MIN || num == LONG_MAX) {
238 				return -EINVAL;
239 			}
240 
241 			req->internal.response.content_length = num;
242 		}
243 
244 		req->internal.response.cl_present = false;
245 	}
246 
247 	if (req->internal.response.http_cb &&
248 	    req->internal.response.http_cb->on_header_value) {
249 		req->internal.response.http_cb->on_header_value(parser, at,
250 								length);
251 	}
252 
253 	print_header_field(length, at);
254 
255 	return 0;
256 }
257 
on_body(struct http_parser * parser,const char * at,size_t length)258 static int on_body(struct http_parser *parser, const char *at, size_t length)
259 {
260 	struct http_request *req = CONTAINER_OF(parser,
261 						struct http_request,
262 						internal.parser);
263 
264 	req->internal.response.body_found = 1;
265 	req->internal.response.processed += length;
266 
267 	NET_DBG("Processed %zd length %zd", req->internal.response.processed,
268 		length);
269 
270 	if (req->internal.response.http_cb &&
271 	    req->internal.response.http_cb->on_body) {
272 		req->internal.response.http_cb->on_body(parser, at, length);
273 	}
274 
275 	/* Reset the body_frag_start pointer for each fragment. */
276 	if (!req->internal.response.body_frag_start) {
277 		req->internal.response.body_frag_start = (uint8_t *)at;
278 	}
279 
280 	/* Calculate the length of the body contained in the recv_buf */
281 	req->internal.response.body_frag_len = req->internal.response.data_len -
282 		(req->internal.response.body_frag_start - req->internal.response.recv_buf);
283 
284 	return 0;
285 }
286 
on_headers_complete(struct http_parser * parser)287 static int on_headers_complete(struct http_parser *parser)
288 {
289 	struct http_request *req = CONTAINER_OF(parser,
290 						struct http_request,
291 						internal.parser);
292 
293 	if (req->internal.response.http_cb &&
294 	    req->internal.response.http_cb->on_headers_complete) {
295 		req->internal.response.http_cb->on_headers_complete(parser);
296 	}
297 
298 	if (parser->status_code >= 500 && parser->status_code < 600) {
299 		NET_DBG("Status %d, skipping body", parser->status_code);
300 		return 1;
301 	}
302 
303 	if ((req->method == HTTP_HEAD || req->method == HTTP_OPTIONS) &&
304 	    req->internal.response.content_length > 0) {
305 		NET_DBG("No body expected");
306 		return 1;
307 	}
308 
309 	NET_DBG("Headers complete");
310 
311 	return 0;
312 }
313 
on_message_begin(struct http_parser * parser)314 static int on_message_begin(struct http_parser *parser)
315 {
316 	struct http_request *req = CONTAINER_OF(parser,
317 						struct http_request,
318 						internal.parser);
319 
320 	if (req->internal.response.http_cb &&
321 	    req->internal.response.http_cb->on_message_begin) {
322 		req->internal.response.http_cb->on_message_begin(parser);
323 	}
324 
325 	NET_DBG("-- HTTP %s response (headers) --",
326 		http_method_str(req->method));
327 
328 	return 0;
329 }
330 
on_message_complete(struct http_parser * parser)331 static int on_message_complete(struct http_parser *parser)
332 {
333 	struct http_request *req = CONTAINER_OF(parser,
334 						struct http_request,
335 						internal.parser);
336 
337 	if (req->internal.response.http_cb &&
338 	    req->internal.response.http_cb->on_message_complete) {
339 		req->internal.response.http_cb->on_message_complete(parser);
340 	}
341 
342 	NET_DBG("-- HTTP %s response (complete) --",
343 		http_method_str(req->method));
344 
345 	req->internal.response.message_complete = 1;
346 
347 	return 0;
348 }
349 
on_chunk_header(struct http_parser * parser)350 static int on_chunk_header(struct http_parser *parser)
351 {
352 	struct http_request *req = CONTAINER_OF(parser,
353 						struct http_request,
354 						internal.parser);
355 
356 	if (req->internal.response.http_cb &&
357 	    req->internal.response.http_cb->on_chunk_header) {
358 		req->internal.response.http_cb->on_chunk_header(parser);
359 	}
360 
361 	return 0;
362 }
363 
on_chunk_complete(struct http_parser * parser)364 static int on_chunk_complete(struct http_parser *parser)
365 {
366 	struct http_request *req = CONTAINER_OF(parser,
367 						struct http_request,
368 						internal.parser);
369 
370 	if (req->internal.response.http_cb &&
371 	    req->internal.response.http_cb->on_chunk_complete) {
372 		req->internal.response.http_cb->on_chunk_complete(parser);
373 	}
374 
375 	return 0;
376 }
377 
http_client_init_parser(struct http_parser * parser,struct http_parser_settings * settings)378 static void http_client_init_parser(struct http_parser *parser,
379 				    struct http_parser_settings *settings)
380 {
381 	http_parser_init(parser, HTTP_RESPONSE);
382 
383 	settings->on_body = on_body;
384 	settings->on_chunk_complete = on_chunk_complete;
385 	settings->on_chunk_header = on_chunk_header;
386 	settings->on_headers_complete = on_headers_complete;
387 	settings->on_header_field = on_header_field;
388 	settings->on_header_value = on_header_value;
389 	settings->on_message_begin = on_message_begin;
390 	settings->on_message_complete = on_message_complete;
391 	settings->on_status = on_status;
392 	settings->on_url = on_url;
393 }
394 
http_data_final_null_resp(struct http_request * req)395 static void http_data_final_null_resp(struct http_request *req)
396 {
397 	if (req->internal.response.cb) {
398 		NET_DBG("Calling callback for Final Data"
399 			"(NULL HTTP response)");
400 
401 		/* Status code 0 representing a null response */
402 		req->internal.response.http_status_code = 0;
403 
404 		/* Zero out related response metrics */
405 		req->internal.response.processed = 0;
406 		req->internal.response.data_len = 0;
407 		req->internal.response.content_length = 0;
408 		req->internal.response.body_frag_start = NULL;
409 		memset(req->internal.response.http_status, 0, HTTP_STATUS_STR_SIZE);
410 
411 		req->internal.response.cb(&req->internal.response, HTTP_DATA_FINAL,
412 					  req->internal.user_data);
413 	}
414 }
415 
http_wait_data(int sock,struct http_request * req,int32_t timeout)416 static int http_wait_data(int sock, struct http_request *req, int32_t timeout)
417 {
418 	int total_received = 0;
419 	size_t offset = 0;
420 	int received, ret;
421 	struct zsock_pollfd fds[1];
422 	int nfds = 1;
423 	int32_t remaining_time = timeout;
424 	int64_t timestamp = k_uptime_get();
425 
426 	fds[0].fd = sock;
427 	fds[0].events = ZSOCK_POLLIN;
428 
429 	do {
430 		if (timeout > 0) {
431 			remaining_time -= (int32_t)k_uptime_delta(&timestamp);
432 			if (remaining_time < 0) {
433 				/* timeout, make poll return immediately */
434 				remaining_time = 0;
435 			}
436 		}
437 
438 		ret = zsock_poll(fds, nfds, remaining_time);
439 		if (ret == 0) {
440 			LOG_DBG("Timeout");
441 			goto finalize_data;
442 		} else if (ret < 0) {
443 			goto error;
444 		}
445 		if (fds[0].revents & (ZSOCK_POLLERR | ZSOCK_POLLNVAL)) {
446 			goto error;
447 		} else if (fds[0].revents & ZSOCK_POLLHUP) {
448 			/* Connection closed */
449 			LOG_DBG("Connection closed");
450 			goto finalize_data;
451 		} else if (fds[0].revents & ZSOCK_POLLIN) {
452 			received = zsock_recv(sock, req->internal.response.recv_buf + offset,
453 					      req->internal.response.recv_buf_len - offset, 0);
454 			if (received == 0) {
455 				/* Connection closed */
456 				LOG_DBG("Connection closed");
457 				goto finalize_data;
458 			} else if (received < 0) {
459 				goto error;
460 			} else {
461 				req->internal.response.data_len += received;
462 
463 				(void)http_parser_execute(
464 					&req->internal.parser, &req->internal.parser_settings,
465 					req->internal.response.recv_buf + offset, received);
466 			}
467 
468 			total_received += received;
469 			offset += received;
470 
471 			if (offset >= req->internal.response.recv_buf_len) {
472 				offset = 0;
473 			}
474 
475 			if (req->internal.response.cb) {
476 				bool notify = false;
477 				enum http_final_call event;
478 
479 				if (req->internal.response.message_complete) {
480 					NET_DBG("Calling callback for %zd len data",
481 						req->internal.response.data_len);
482 
483 					notify = true;
484 					event = HTTP_DATA_FINAL;
485 				} else if (offset == 0) {
486 					NET_DBG("Calling callback for partitioned %zd len data",
487 						req->internal.response.data_len);
488 
489 					notify = true;
490 					event = HTTP_DATA_MORE;
491 				}
492 
493 				if (notify) {
494 					req->internal.response.cb(&req->internal.response, event,
495 								  req->internal.user_data);
496 
497 					/* Re-use the result buffer and start to fill it again */
498 					req->internal.response.data_len = 0;
499 					req->internal.response.body_frag_start = NULL;
500 					req->internal.response.body_frag_len = 0;
501 				}
502 			}
503 
504 			if (req->internal.response.message_complete) {
505 				ret = total_received;
506 				break;
507 			}
508 		}
509 
510 	} while (true);
511 
512 	return ret;
513 
514 finalize_data:
515 	ret = total_received;
516 
517 	http_data_final_null_resp(req);
518 	return ret;
519 
520 error:
521 	LOG_DBG("Connection error (%d)", errno);
522 	ret = -errno;
523 	return ret;
524 }
525 
http_client_req(int sock,struct http_request * req,int32_t timeout,void * user_data)526 int http_client_req(int sock, struct http_request *req,
527 		    int32_t timeout, void *user_data)
528 {
529 	/* Utilize the network usage by sending data in bigger blocks */
530 	char send_buf[MAX_SEND_BUF_LEN];
531 	const size_t send_buf_max_len = sizeof(send_buf);
532 	size_t send_buf_pos = 0;
533 	int total_sent = 0;
534 	int ret, total_recv, i;
535 	const char *method;
536 
537 	if (sock < 0 || req == NULL || req->response == NULL ||
538 	    req->recv_buf == NULL || req->recv_buf_len == 0) {
539 		return -EINVAL;
540 	}
541 
542 	memset(&req->internal.response, 0, sizeof(req->internal.response));
543 
544 	req->internal.response.http_cb = req->http_cb;
545 	req->internal.response.cb = req->response;
546 	req->internal.response.recv_buf = req->recv_buf;
547 	req->internal.response.recv_buf_len = req->recv_buf_len;
548 	req->internal.user_data = user_data;
549 	req->internal.sock = sock;
550 
551 	method = http_method_str(req->method);
552 
553 	ret = http_send_data(sock, send_buf, send_buf_max_len, &send_buf_pos,
554 			     method, " ", req->url, " ", req->protocol,
555 			     HTTP_CRLF, NULL);
556 	if (ret < 0) {
557 		goto out;
558 	}
559 
560 	total_sent += ret;
561 
562 	if (req->port) {
563 		ret = http_send_data(sock, send_buf, send_buf_max_len,
564 				     &send_buf_pos, "Host", ": ", req->host,
565 				     ":", req->port, HTTP_CRLF, NULL);
566 
567 		if (ret < 0) {
568 			goto out;
569 		}
570 
571 		total_sent += ret;
572 	} else {
573 		ret = http_send_data(sock, send_buf, send_buf_max_len,
574 				     &send_buf_pos, "Host", ": ", req->host,
575 				     HTTP_CRLF, NULL);
576 
577 		if (ret < 0) {
578 			goto out;
579 		}
580 
581 		total_sent += ret;
582 	}
583 
584 	if (req->optional_headers_cb) {
585 		ret = http_flush_data(sock, send_buf, send_buf_pos);
586 		if (ret < 0) {
587 			goto out;
588 		}
589 
590 		send_buf_pos = 0;
591 		total_sent += ret;
592 
593 		ret = req->optional_headers_cb(sock, req, user_data);
594 		if (ret < 0) {
595 			goto out;
596 		}
597 
598 		total_sent += ret;
599 	} else {
600 		for (i = 0; req->optional_headers && req->optional_headers[i];
601 		     i++) {
602 			ret = http_send_data(sock, send_buf, send_buf_max_len,
603 					     &send_buf_pos,
604 					     req->optional_headers[i], NULL);
605 			if (ret < 0) {
606 				goto out;
607 			}
608 
609 			total_sent += ret;
610 		}
611 	}
612 
613 	for (i = 0; req->header_fields && req->header_fields[i]; i++) {
614 		ret = http_send_data(sock, send_buf, send_buf_max_len,
615 				     &send_buf_pos, req->header_fields[i],
616 				     NULL);
617 		if (ret < 0) {
618 			goto out;
619 		}
620 
621 		total_sent += ret;
622 	}
623 
624 	if (req->content_type_value) {
625 		ret = http_send_data(sock, send_buf, send_buf_max_len,
626 				     &send_buf_pos, "Content-Type", ": ",
627 				     req->content_type_value, HTTP_CRLF, NULL);
628 		if (ret < 0) {
629 			goto out;
630 		}
631 
632 		total_sent += ret;
633 	}
634 
635 	if (req->payload || req->payload_cb) {
636 		if (req->payload_len) {
637 			char content_len_str[HTTP_CONTENT_LEN_SIZE];
638 
639 			ret = snprintk(content_len_str, HTTP_CONTENT_LEN_SIZE,
640 				       "%zd", req->payload_len);
641 			if (ret <= 0 || ret >= HTTP_CONTENT_LEN_SIZE) {
642 				ret = -ENOMEM;
643 				goto out;
644 			}
645 
646 			ret = http_send_data(sock, send_buf, send_buf_max_len,
647 					     &send_buf_pos, "Content-Length", ": ",
648 					     content_len_str, HTTP_CRLF,
649 					     HTTP_CRLF, NULL);
650 		} else {
651 			ret = http_send_data(sock, send_buf, send_buf_max_len,
652 				     &send_buf_pos, HTTP_CRLF, NULL);
653 		}
654 
655 		if (ret < 0) {
656 			goto out;
657 		}
658 
659 		total_sent += ret;
660 
661 		ret = http_flush_data(sock, send_buf, send_buf_pos);
662 		if (ret < 0) {
663 			goto out;
664 		}
665 
666 		send_buf_pos = 0;
667 		total_sent += ret;
668 
669 		if (req->payload_cb) {
670 			ret = req->payload_cb(sock, req, user_data);
671 			if (ret < 0) {
672 				goto out;
673 			}
674 
675 			total_sent += ret;
676 		} else {
677 			uint32_t length;
678 
679 			if (req->payload_len == 0) {
680 				length = strlen(req->payload);
681 			} else {
682 				length = req->payload_len;
683 			}
684 
685 			ret = sendall(sock, req->payload, length);
686 			if (ret < 0) {
687 				goto out;
688 			}
689 
690 			total_sent += length;
691 		}
692 	} else {
693 		ret = http_send_data(sock, send_buf, send_buf_max_len,
694 				     &send_buf_pos, HTTP_CRLF, NULL);
695 		if (ret < 0) {
696 			goto out;
697 		}
698 
699 		total_sent += ret;
700 	}
701 
702 	if (send_buf_pos > 0) {
703 		ret = http_flush_data(sock, send_buf, send_buf_pos);
704 		if (ret < 0) {
705 			goto out;
706 		}
707 
708 		total_sent += ret;
709 	}
710 
711 	NET_DBG("Sent %d bytes", total_sent);
712 
713 	http_client_init_parser(&req->internal.parser,
714 				&req->internal.parser_settings);
715 
716 	/* Request is sent, now wait data to be received */
717 	total_recv = http_wait_data(sock, req, timeout);
718 	if (total_recv < 0) {
719 		NET_DBG("Wait data failure (%d)", total_recv);
720 	} else {
721 		NET_DBG("Received %d bytes", total_recv);
722 	}
723 
724 	return total_sent;
725 
726 out:
727 	return ret;
728 }
729