1
1
#pragma once
2
2
3
+ #include " zephyr/sys/printk.h"
4
+ #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
5
+ #include < zephyr/net/tls_credentials.h>
6
+ #define CA_CERTIFICATE_TAG 1
7
+ #endif
8
+
3
9
#include < zephyr/net/socket.h>
4
10
5
11
class ZephyrSocketWrapper {
6
12
protected:
7
13
int sock_fd;
14
+ bool is_ssl = false ;
15
+ int ssl_sock_temp_char = -1 ;
8
16
9
17
public:
10
18
ZephyrSocketWrapper () : sock_fd(-1 ) {}
@@ -33,6 +41,8 @@ class ZephyrSocketWrapper {
33
41
34
42
if (ret == 0 ) {
35
43
break ;
44
+ } else {
45
+ k_sleep (K_MSEC (1 ));
36
46
}
37
47
}
38
48
@@ -77,11 +87,86 @@ class ZephyrSocketWrapper {
77
87
return true ;
78
88
}
79
89
90
+ #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
91
+ bool connectSSL (const char * host, uint16_t port, char * ca_certificate_pem = nullptr ) {
92
+
93
+ // Resolve address
94
+ struct addrinfo hints;
95
+ struct addrinfo *res;
96
+
97
+ hints.ai_family = AF_INET;
98
+ hints.ai_socktype = SOCK_STREAM;
99
+
100
+ int resolve_attempts = 100 ;
101
+ int ret;
102
+
103
+ while (resolve_attempts--) {
104
+ ret = getaddrinfo (host, String (port).c_str (), &hints, &res);
105
+
106
+ if (ret == 0 ) {
107
+ break ;
108
+ } else {
109
+ k_sleep (K_MSEC (1 ));
110
+ }
111
+ }
112
+
113
+ if (ret != 0 ) {
114
+ return false ;
115
+ }
116
+
117
+ if (ca_certificate_pem != nullptr ) {
118
+ ret = tls_credential_add (CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
119
+ ca_certificate_pem, strlen (ca_certificate_pem) + 1 );
120
+ Serial.println (ret);
121
+ }
122
+
123
+ sock_fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
124
+ if (sock_fd < 0 ) {
125
+ return false ;
126
+ }
127
+
128
+ sec_tag_t sec_tag_opt[] = {
129
+ CA_CERTIFICATE_TAG,
130
+ };
131
+ setsockopt (sock_fd, SOL_TLS, TLS_SEC_TAG_LIST,
132
+ sec_tag_opt, sizeof (sec_tag_opt));
133
+
134
+ setsockopt (sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen (host));
135
+
136
+ uint32_t timeo_optval = 100 ;
137
+ setsockopt (sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof (timeo_optval));
138
+
139
+ if (::connect (sock_fd, res->ai_addr , res->ai_addrlen ) < 0 ) {
140
+ ::close (sock_fd);
141
+ sock_fd = -1 ;
142
+ return false ;
143
+ }
144
+ is_ssl = true ;
145
+
146
+ return true ;
147
+ }
148
+ #endif
149
+
80
150
int available () {
81
151
int count = 0 ;
82
- zsock_ioctl (sock_fd, ZFD_IOCTL_FIONREAD, &count);
83
- if (count == 0 ) {
152
+ if (is_ssl) {
153
+ /*
154
+ TODO: HACK:
155
+ The correct colution would be to call
156
+ ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT);
157
+ but it doesn't seem to work. Instead, save a temporary variable
158
+ and use it in read()
159
+ */
160
+ if (ssl_sock_temp_char != -1 ) {
161
+ return 1 ;
162
+ }
163
+ count = ::recv (sock_fd, &ssl_sock_temp_char, 1 , MSG_DONTWAIT);
164
+ } else {
165
+ zsock_ioctl (sock_fd, ZFD_IOCTL_FIONREAD, &count);
166
+ }
167
+ if (count <= 0 ) {
84
168
delay (1 );
169
+ count = 0 ;
85
170
}
86
171
return count;
87
172
}
@@ -90,6 +175,13 @@ class ZephyrSocketWrapper {
90
175
if (sock_fd == -1 ) {
91
176
return -1 ;
92
177
}
178
+ // TODO: see available()
179
+ if (ssl_sock_temp_char != -1 ) {
180
+ int ret = ::recv (sock_fd, &buffer[1 ], size - 1 , flags);
181
+ buffer[0 ] = ssl_sock_temp_char;
182
+ ssl_sock_temp_char = -1 ;
183
+ return ret + 1 ;
184
+ }
93
185
return ::recv (sock_fd, buffer, size, flags);
94
186
}
95
187
0 commit comments