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