11#pragma once
22
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+
39#include < zephyr/net/socket.h>
410
511class ZephyrSocketWrapper {
612protected:
713 int sock_fd;
14+ bool is_ssl = false ;
15+ int ssl_sock_temp_char = -1 ;
816
917public:
1018 ZephyrSocketWrapper () : sock_fd(-1 ) {}
@@ -33,6 +41,8 @@ class ZephyrSocketWrapper {
3341
3442 if (ret == 0 ) {
3543 break ;
44+ } else {
45+ k_sleep (K_MSEC (1 ));
3646 }
3747 }
3848
@@ -77,11 +87,86 @@ class ZephyrSocketWrapper {
7787 return true ;
7888 }
7989
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+
80150 int available () {
81151 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 ) {
84168 delay (1 );
169+ count = 0 ;
85170 }
86171 return count;
87172 }
@@ -90,6 +175,13 @@ class ZephyrSocketWrapper {
90175 if (sock_fd == -1 ) {
91176 return -1 ;
92177 }
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+ }
93185 return ::recv (sock_fd, buffer, size, flags);
94186 }
95187
0 commit comments