4
4
* The MIT License (MIT)
5
5
*
6
6
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
7
8
*
8
9
* Permission is hereby granted, free of charge, to any person obtaining a copy
9
10
* of this software and associated documentation files (the "Software"), to deal
37
38
#include "components/lwip/lwip/src/include/lwip/sys.h"
38
39
#include "components/lwip/lwip/src/include/lwip/netdb.h"
39
40
41
+ STATIC void _lazy_init_LWIP (socketpool_socket_obj_t * self ) {
42
+ if (self -> num != -1 ) {
43
+ return ; //safe to call on existing socket
44
+ }
45
+ if (self -> tls != NULL ) {
46
+ mp_raise_RuntimeError (translate ("Invalid use of TLS Socket" ));
47
+ }
48
+ int socknum = -1 ;
49
+ socknum = lwip_socket (self -> family , self -> type , self -> ipproto );
50
+ if (socknum < 0 ) {
51
+ mp_raise_RuntimeError (translate ("Out of sockets" ));
52
+ }
53
+ self -> num = socknum ;
54
+ }
55
+
56
+ STATIC void _lazy_init_TLS (socketpool_socket_obj_t * self ) {
57
+ if (self -> type != SOCK_STREAM || self -> num != -1 ) {
58
+ mp_raise_RuntimeError (translate ("Invalid socket for TLS" ));
59
+ }
60
+ esp_tls_t * tls_handle = esp_tls_init ();
61
+ if (tls_handle == NULL ) {
62
+ mp_raise_espidf_MemoryError ();
63
+ }
64
+ self -> tls = tls_handle ;
65
+ }
66
+
40
67
void common_hal_socketpool_socket_settimeout (socketpool_socket_obj_t * self , mp_uint_t timeout_ms ) {
41
68
self -> timeout_ms = timeout_ms ;
42
69
}
43
70
44
- bool common_hal_socketpool_socket_connect (socketpool_socket_obj_t * self , const char * host , mp_uint_t hostlen , mp_int_t port ) {
71
+ bool common_hal_socketpool_socket_bind (socketpool_socket_obj_t * self ,
72
+ const char * host , size_t hostlen , uint8_t port ) {
73
+ _lazy_init_LWIP (self );
74
+
75
+ struct sockaddr_in bind_addr ;
76
+ bind_addr .sin_addr .s_addr = inet_addr (host );
77
+ bind_addr .sin_family = AF_INET ;
78
+ bind_addr .sin_port = htons (port );
79
+
80
+ return lwip_bind (self -> num , (struct sockaddr * )& bind_addr , sizeof (bind_addr )) == 0 ;
81
+ }
82
+
83
+ bool common_hal_socketpool_socket_listen (socketpool_socket_obj_t * self , int backlog ) {
84
+ return lwip_listen (self -> num , backlog ) == 0 ;
85
+ }
86
+
87
+ int common_hal_socketpool_socket_accept (socketpool_socket_obj_t * self ,
88
+ uint8_t * ip , uint * port ) {
89
+ struct sockaddr_in accept_addr ;
90
+ socklen_t socklen = sizeof (accept_addr );
91
+ int newsoc = lwip_accept (self -> num , (struct sockaddr * )& accept_addr , & socklen );
92
+
93
+ memcpy ((void * )ip , (void * )& accept_addr .sin_addr .s_addr , sizeof (accept_addr .sin_addr .s_addr ));
94
+ * port = accept_addr .sin_port ;
95
+
96
+ if (newsoc > 0 ) {
97
+ return newsoc ;
98
+ } else {
99
+ return 0 ;
100
+ }
101
+ }
102
+
103
+ bool common_hal_socketpool_socket_connect (socketpool_socket_obj_t * self ,
104
+ const char * host , mp_uint_t hostlen , mp_int_t port ) {
45
105
// For simplicity we use esp_tls for all TCP connections. If it's not SSL, ssl_context will be
46
106
// NULL and should still work. This makes regular TCP connections more memory expensive but TLS
47
107
// should become more and more common. Therefore, we optimize for the TLS case.
48
108
109
+ // Todo: move to SSL Wrapper and add lwip_connect()
110
+ _lazy_init_TLS (self );
111
+
49
112
esp_tls_cfg_t * tls_config = NULL ;
50
113
if (self -> ssl_context != NULL ) {
51
114
tls_config = & self -> ssl_context -> ssl_config ;
52
115
}
53
- int result = esp_tls_conn_new_sync (host , hostlen , port , tls_config , self -> tcp );
116
+ int result = esp_tls_conn_new_sync (host , hostlen , port , tls_config , self -> tls );
54
117
self -> connected = result >= 0 ;
55
118
if (result < 0 ) {
56
119
int esp_tls_code ;
57
120
int flags ;
58
- esp_err_t err = esp_tls_get_and_clear_last_error (self -> tcp -> error_handle , & esp_tls_code , & flags );
121
+ esp_err_t err = esp_tls_get_and_clear_last_error (self -> tls -> error_handle , & esp_tls_code , & flags );
59
122
60
123
if (err == ESP_ERR_MBEDTLS_SSL_SETUP_FAILED ) {
61
124
mp_raise_espidf_MemoryError ();
@@ -70,7 +133,7 @@ bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const c
70
133
// shouldn't hit this timeout because we try to only read available data. However, there is
71
134
// always a chance that we try to read something that is used internally.
72
135
int fd ;
73
- esp_tls_get_conn_sockfd (self -> tcp , & fd );
136
+ esp_tls_get_conn_sockfd (self -> tls , & fd );
74
137
struct timeval tv ;
75
138
tv .tv_sec = 2 * 60 ; // Two minutes
76
139
tv .tv_usec = 0 ;
@@ -86,7 +149,14 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) {
86
149
}
87
150
88
151
mp_uint_t common_hal_socketpool_socket_send (socketpool_socket_obj_t * self , const uint8_t * buf , mp_uint_t len ) {
89
- size_t sent = esp_tls_conn_write (self -> tcp , buf , len );
152
+ size_t sent = -1 ;
153
+ if (self -> num != -1 ) {
154
+ // LWIP Socket
155
+ sent = lwip_send (self -> num , buf , len , 0 );
156
+ } else if (self -> tls != NULL ) {
157
+ // TLS Socket
158
+ sent = esp_tls_conn_write (self -> tls , buf , len );
159
+ }
90
160
91
161
if (sent < 0 ) {
92
162
mp_raise_OSError (MP_ENOTCONN );
@@ -96,37 +166,44 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const
96
166
97
167
mp_uint_t common_hal_socketpool_socket_recv_into (socketpool_socket_obj_t * self , const uint8_t * buf , mp_uint_t len ) {
98
168
size_t received = 0 ;
99
- int status = 0 ;
100
- uint64_t start_ticks = supervisor_ticks_ms64 ();
101
- int sockfd ;
102
- esp_err_t err = esp_tls_get_conn_sockfd (self -> tcp , & sockfd );
103
- if (err != ESP_OK ) {
104
- mp_raise_OSError (MP_EBADF );
105
- }
106
- while (received == 0 &&
107
- status >= 0 &&
108
- (self -> timeout_ms == 0 || supervisor_ticks_ms64 () - start_ticks <= self -> timeout_ms ) &&
109
- !mp_hal_is_interrupted ()) {
110
- RUN_BACKGROUND_TASKS ;
111
- size_t available = esp_tls_get_bytes_avail (self -> tcp );
112
- if (available == 0 ) {
113
- // This reads the raw socket buffer and is used for non-TLS connections
114
- // and between encrypted TLS blocks.
115
- status = lwip_ioctl (sockfd , FIONREAD , & available );
116
- }
117
- size_t remaining = len - received ;
118
- if (available > remaining ) {
119
- available = remaining ;
169
+
170
+ if (self -> num != -1 ) {
171
+ // LWIP Socket
172
+ received = lwip_recv (self -> num , (void * ) buf , len - 1 , 0 );
173
+ } else if (self -> tls != NULL ) {
174
+ // TLS Socket
175
+ int status = 0 ;
176
+ uint64_t start_ticks = supervisor_ticks_ms64 ();
177
+ int sockfd ;
178
+ esp_err_t err = esp_tls_get_conn_sockfd (self -> tls , & sockfd );
179
+ if (err != ESP_OK ) {
180
+ mp_raise_OSError (MP_EBADF );
120
181
}
121
- if (available > 0 ) {
122
- status = esp_tls_conn_read (self -> tcp , (void * ) buf + received , available );
123
- if (status == 0 ) {
124
- // Reading zero when something is available indicates a closed
125
- // connection. (The available bytes could have been TLS internal.)
126
- break ;
182
+ while (received == 0 &&
183
+ status >= 0 &&
184
+ (self -> timeout_ms == 0 || supervisor_ticks_ms64 () - start_ticks <= self -> timeout_ms ) &&
185
+ !mp_hal_is_interrupted ()) {
186
+ RUN_BACKGROUND_TASKS ;
187
+ size_t available = esp_tls_get_bytes_avail (self -> tls );
188
+ if (available == 0 ) {
189
+ // This reads the raw socket buffer and is used for non-TLS connections
190
+ // and between encrypted TLS blocks.
191
+ status = lwip_ioctl (sockfd , FIONREAD , & available );
127
192
}
128
- if (status > 0 ) {
129
- received += status ;
193
+ size_t remaining = len - received ;
194
+ if (available > remaining ) {
195
+ available = remaining ;
196
+ }
197
+ if (available > 0 ) {
198
+ status = esp_tls_conn_read (self -> tls , (void * ) buf + received , available );
199
+ if (status == 0 ) {
200
+ // Reading zero when something is available indicates a closed
201
+ // connection. (The available bytes could have been TLS internal.)
202
+ break ;
203
+ }
204
+ if (status > 0 ) {
205
+ received += status ;
206
+ }
130
207
}
131
208
}
132
209
}
@@ -141,6 +218,8 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
141
218
mp_uint_t common_hal_socketpool_socket_sendto (socketpool_socket_obj_t * self ,
142
219
const char * host , size_t hostlen , uint8_t port , const uint8_t * buf , mp_uint_t len ) {
143
220
221
+ _lazy_init_LWIP (self );
222
+
144
223
// Get the IP address string
145
224
const struct addrinfo hints = {
146
225
.ai_family = AF_INET ,
@@ -151,17 +230,15 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
151
230
if (error != 0 || result == NULL ) {
152
231
return 0 ;
153
232
}
233
+
234
+ // Set parameters
235
+ struct sockaddr_in dest_addr ;
154
236
#pragma GCC diagnostic push
155
237
#pragma GCC diagnostic ignored "-Wcast-align"
156
- struct in_addr * addr = & ((struct sockaddr_in * )result -> ai_addr )-> sin_addr ;
238
+ dest_addr . sin_addr . s_addr = ((struct sockaddr_in * )result -> ai_addr )-> sin_addr . s_addr ;
157
239
#pragma GCC diagnostic pop
158
- char ip_str [IP4ADDR_STRLEN_MAX ];
159
- inet_ntoa_r (* addr , ip_str , IP4ADDR_STRLEN_MAX );
160
240
freeaddrinfo (result );
161
241
162
- // Set parameters
163
- struct sockaddr_in dest_addr ;
164
- dest_addr .sin_addr .s_addr = inet_addr ((const char * )ip_str );
165
242
dest_addr .sin_family = AF_INET ;
166
243
dest_addr .sin_port = htons (port );
167
244
@@ -176,11 +253,13 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
176
253
mp_uint_t common_hal_socketpool_socket_recvfrom_into (socketpool_socket_obj_t * self ,
177
254
uint8_t * buf , mp_uint_t len , uint8_t * ip , uint * port ) {
178
255
256
+ _lazy_init_LWIP (self );
257
+
179
258
struct sockaddr_in source_addr ;
180
259
socklen_t socklen = sizeof (source_addr );
181
260
int bytes_received = lwip_recvfrom (self -> num , buf , len - 1 , 0 , (struct sockaddr * )& source_addr , & socklen );
182
261
183
- memcpy ((void * )ip , (void * )& source_addr .sin_addr .s_addr , sizeof source_addr .sin_addr .s_addr );
262
+ memcpy ((void * )ip , (void * )& source_addr .sin_addr .s_addr , sizeof ( source_addr .sin_addr .s_addr ) );
184
263
* port = source_addr .sin_port ;
185
264
186
265
if (bytes_received < 0 ) {
@@ -194,9 +273,9 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se
194
273
195
274
void common_hal_socketpool_socket_close (socketpool_socket_obj_t * self ) {
196
275
self -> connected = false;
197
- if (self -> tcp != NULL ) {
198
- esp_tls_conn_destroy (self -> tcp );
199
- self -> tcp = NULL ;
276
+ if (self -> tls != NULL ) {
277
+ esp_tls_conn_destroy (self -> tls );
278
+ self -> tls = NULL ;
200
279
}
201
280
if (self -> num >= 0 ) {
202
281
lwip_shutdown (self -> num , 0 );
@@ -206,7 +285,7 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) {
206
285
}
207
286
208
287
bool common_hal_socketpool_socket_get_closed (socketpool_socket_obj_t * self ) {
209
- return self -> tcp == NULL && self -> num < 0 ;
288
+ return self -> tls == NULL && self -> num < 0 ;
210
289
}
211
290
212
291
0 commit comments