1 /*
2  * Copyright (c) 2017 Linaro Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #if !defined(__ZEPHYR__)
11 
12 #include <netinet/in.h>
13 #include <sys/socket.h>
14 #include <arpa/inet.h>
15 #include <unistd.h>
16 #include <netdb.h>
17 
18 #else
19 
20 #include <zephyr/net/socket.h>
21 #include <zephyr/kernel.h>
22 
23 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
24 #include <zephyr/net/tls_credentials.h>
25 #include "ca_certificate.h"
26 #endif
27 
28 #include "net_sample_common.h"
29 
30 #endif
31 
32 /* HTTP server to connect to */
33 #define HTTP_HOST "google.com"
34 /* Port to connect to, as string */
35 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
36 #define HTTP_PORT "443"
37 #else
38 #define HTTP_PORT "80"
39 #endif
40 /* HTTP path to request */
41 #define HTTP_PATH "/"
42 
43 
44 #define SSTRLEN(s) (sizeof(s) - 1)
45 #define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } }
46 
47 #define REQUEST "GET " HTTP_PATH " HTTP/1.0\r\nHost: " HTTP_HOST "\r\n\r\n"
48 
49 static char response[1024];
50 
dump_addrinfo(const struct addrinfo * ai)51 void dump_addrinfo(const struct addrinfo *ai)
52 {
53 	printf("addrinfo @%p: ai_family=%d, ai_socktype=%d, ai_protocol=%d, "
54 	       "sa_family=%d, sin_port=%x\n",
55 	       ai, ai->ai_family, ai->ai_socktype, ai->ai_protocol,
56 	       ai->ai_addr->sa_family,
57 	       ((struct sockaddr_in *)ai->ai_addr)->sin_port);
58 }
59 
main(void)60 int main(void)
61 {
62 	static struct addrinfo hints;
63 	struct addrinfo *res;
64 	int st, sock;
65 
66 	wait_for_network();
67 
68 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
69 	tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
70 			   ca_certificate, sizeof(ca_certificate));
71 #endif
72 
73 	printf("Preparing HTTP GET request for http://" HTTP_HOST
74 	       ":" HTTP_PORT HTTP_PATH "\n");
75 
76 	hints.ai_family = AF_INET;
77 	hints.ai_socktype = SOCK_STREAM;
78 	st = getaddrinfo(HTTP_HOST, HTTP_PORT, &hints, &res);
79 	printf("getaddrinfo status: %d\n", st);
80 
81 	if (st != 0) {
82 		printf("Unable to resolve address, quitting\n");
83 		return 0;
84 	}
85 
86 #if 0
87 	for (; res; res = res->ai_next) {
88 		dump_addrinfo(res);
89 	}
90 #endif
91 
92 	dump_addrinfo(res);
93 
94 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
95 	sock = socket(res->ai_family, res->ai_socktype, IPPROTO_TLS_1_2);
96 #else
97 	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
98 #endif
99 	CHECK(sock);
100 	printf("sock = %d\n", sock);
101 
102 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
103 	sec_tag_t sec_tag_opt[] = {
104 		CA_CERTIFICATE_TAG,
105 	};
106 	CHECK(setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST,
107 			 sec_tag_opt, sizeof(sec_tag_opt)));
108 
109 	CHECK(setsockopt(sock, SOL_TLS, TLS_HOSTNAME,
110 			 HTTP_HOST, sizeof(HTTP_HOST)))
111 #endif
112 
113 	CHECK(connect(sock, res->ai_addr, res->ai_addrlen));
114 	CHECK(send(sock, REQUEST, SSTRLEN(REQUEST), 0));
115 
116 	printf("Response:\n\n");
117 
118 	while (1) {
119 		int len = recv(sock, response, sizeof(response) - 1, 0);
120 
121 		if (len < 0) {
122 			printf("Error reading response\n");
123 			return 0;
124 		}
125 
126 		if (len == 0) {
127 			break;
128 		}
129 
130 		response[len] = 0;
131 		printf("%s", response);
132 	}
133 
134 	printf("\n");
135 
136 	(void)close(sock);
137 	return 0;
138 }
139