1 // Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <esp_tls.h>
19
20 #include "sys/queue.h"
21 #include "esp_log.h"
22
23 #include "esp_transport.h"
24 #include "esp_transport_internal.h"
25 #include "esp_transport_utils.h"
26
27 static const char *TAG = "TRANSPORT";
28
29 /**
30 * Transport layer error structure including
31 * * esp-tls last error storage
32 * * sock-errno
33 */
34 struct esp_transport_error_s {
35 struct esp_tls_last_error esp_tls_err_h_base; /*!< esp-tls last error container */
36 // additional fields
37 int sock_errno; /*!< last socket error captured for this transport */
38 };
39
40 /**
41 * This list will hold all transport available
42 */
43 STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t);
44
45 /**
46 * Internal transport structure holding list of transports and other data common to all transports
47 */
48 typedef struct esp_transport_internal {
49 struct esp_transport_list_t list; /*!< List of transports */
50 struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */
51 } esp_transport_internal_t;
52
esp_transport_get_default_parent(esp_transport_handle_t t)53 static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
54 {
55 /*
56 * By default, the underlying transport layer handle is the handle itself
57 */
58 return t;
59 }
60
esp_transport_list_init(void)61 esp_transport_list_handle_t esp_transport_list_init(void)
62 {
63 esp_transport_list_handle_t transport = calloc(1, sizeof(esp_transport_internal_t));
64 ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
65 STAILQ_INIT(&transport->list);
66 transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s));
67 return transport;
68 }
69
esp_transport_list_add(esp_transport_list_handle_t h,esp_transport_handle_t t,const char * scheme)70 esp_err_t esp_transport_list_add(esp_transport_list_handle_t h, esp_transport_handle_t t, const char *scheme)
71 {
72 if (h == NULL || t == NULL) {
73 return ESP_ERR_INVALID_ARG;
74 }
75 t->scheme = calloc(1, strlen(scheme) + 1);
76 ESP_TRANSPORT_MEM_CHECK(TAG, t->scheme, return ESP_ERR_NO_MEM);
77 strcpy(t->scheme, scheme);
78 STAILQ_INSERT_TAIL(&h->list, t, next);
79 // Each transport in a list to share the same error tracker
80 t->error_handle = h->error_handle;
81 return ESP_OK;
82 }
83
esp_transport_list_get_transport(esp_transport_list_handle_t h,const char * scheme)84 esp_transport_handle_t esp_transport_list_get_transport(esp_transport_list_handle_t h, const char *scheme)
85 {
86 if (!h) {
87 return NULL;
88 }
89 if (scheme == NULL) {
90 return STAILQ_FIRST(&h->list);
91 }
92 esp_transport_handle_t item;
93 STAILQ_FOREACH(item, &h->list, next) {
94 if (strcasecmp(item->scheme, scheme) == 0) {
95 return item;
96 }
97 }
98 return NULL;
99 }
100
esp_transport_list_destroy(esp_transport_list_handle_t h)101 esp_err_t esp_transport_list_destroy(esp_transport_list_handle_t h)
102 {
103 esp_transport_list_clean(h);
104 free(h->error_handle);
105 free(h);
106 return ESP_OK;
107 }
108
esp_transport_list_clean(esp_transport_list_handle_t h)109 esp_err_t esp_transport_list_clean(esp_transport_list_handle_t h)
110 {
111 esp_transport_handle_t item = STAILQ_FIRST(&h->list);
112 esp_transport_handle_t tmp;
113 while (item != NULL) {
114 tmp = STAILQ_NEXT(item, next);
115 esp_transport_destroy(item);
116 item = tmp;
117 }
118 STAILQ_INIT(&h->list);
119 return ESP_OK;
120 }
121
esp_transport_init(void)122 esp_transport_handle_t esp_transport_init(void)
123 {
124 esp_transport_handle_t t = calloc(1, sizeof(struct esp_transport_item_t));
125 ESP_TRANSPORT_MEM_CHECK(TAG, t, return NULL);
126 return t;
127 }
128
esp_transport_get_payload_transport_handle(esp_transport_handle_t t)129 esp_transport_handle_t esp_transport_get_payload_transport_handle(esp_transport_handle_t t)
130 {
131 if (t && t->_read) {
132 return t->_parent_transfer(t);
133 }
134 return NULL;
135 }
136
esp_transport_destroy(esp_transport_handle_t t)137 esp_err_t esp_transport_destroy(esp_transport_handle_t t)
138 {
139 if (t->_destroy) {
140 t->_destroy(t);
141 }
142 if (t->scheme) {
143 free(t->scheme);
144 }
145 free(t);
146 return ESP_OK;
147 }
148
esp_transport_connect(esp_transport_handle_t t,const char * host,int port,int timeout_ms)149 int esp_transport_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
150 {
151 int ret = -1;
152 if (t && t->_connect) {
153 return t->_connect(t, host, port, timeout_ms);
154 }
155 return ret;
156 }
157
esp_transport_connect_async(esp_transport_handle_t t,const char * host,int port,int timeout_ms)158 int esp_transport_connect_async(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
159 {
160 int ret = -1;
161 if (t && t->_connect_async) {
162 return t->_connect_async(t, host, port, timeout_ms);
163 }
164 return ret;
165 }
166
esp_transport_read(esp_transport_handle_t t,char * buffer,int len,int timeout_ms)167 int esp_transport_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
168 {
169 if (t && t->_read) {
170 return t->_read(t, buffer, len, timeout_ms);
171 }
172 return -1;
173 }
174
esp_transport_write(esp_transport_handle_t t,const char * buffer,int len,int timeout_ms)175 int esp_transport_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
176 {
177 if (t && t->_write) {
178 return t->_write(t, buffer, len, timeout_ms);
179 }
180 return -1;
181 }
182
esp_transport_poll_read(esp_transport_handle_t t,int timeout_ms)183 int esp_transport_poll_read(esp_transport_handle_t t, int timeout_ms)
184 {
185 if (t && t->_poll_read) {
186 return t->_poll_read(t, timeout_ms);
187 }
188 return -1;
189 }
190
esp_transport_poll_write(esp_transport_handle_t t,int timeout_ms)191 int esp_transport_poll_write(esp_transport_handle_t t, int timeout_ms)
192 {
193 if (t && t->_poll_write) {
194 return t->_poll_write(t, timeout_ms);
195 }
196 return -1;
197 }
198
esp_transport_close(esp_transport_handle_t t)199 int esp_transport_close(esp_transport_handle_t t)
200 {
201 if (t && t->_close) {
202 return t->_close(t);
203 }
204 return 0;
205 }
206
esp_transport_get_context_data(esp_transport_handle_t t)207 void *esp_transport_get_context_data(esp_transport_handle_t t)
208 {
209 if (t) {
210 return t->data;
211 }
212 return NULL;
213 }
214
esp_transport_set_context_data(esp_transport_handle_t t,void * data)215 esp_err_t esp_transport_set_context_data(esp_transport_handle_t t, void *data)
216 {
217 if (t) {
218 t->data = data;
219 return ESP_OK;
220 }
221 return ESP_FAIL;
222 }
223
esp_transport_set_func(esp_transport_handle_t t,connect_func _connect,io_read_func _read,io_func _write,trans_func _close,poll_func _poll_read,poll_func _poll_write,trans_func _destroy)224 esp_err_t esp_transport_set_func(esp_transport_handle_t t,
225 connect_func _connect,
226 io_read_func _read,
227 io_func _write,
228 trans_func _close,
229 poll_func _poll_read,
230 poll_func _poll_write,
231 trans_func _destroy)
232 {
233 if (t == NULL) {
234 return ESP_FAIL;
235 }
236 t->_connect = _connect;
237 t->_read = _read;
238 t->_write = _write;
239 t->_close = _close;
240 t->_poll_read = _poll_read;
241 t->_poll_write = _poll_write;
242 t->_destroy = _destroy;
243 t->_connect_async = NULL;
244 t->_parent_transfer = esp_transport_get_default_parent;
245 return ESP_OK;
246 }
247
esp_transport_get_default_port(esp_transport_handle_t t)248 int esp_transport_get_default_port(esp_transport_handle_t t)
249 {
250 if (t == NULL) {
251 return -1;
252 }
253 return t->port;
254 }
255
esp_transport_set_default_port(esp_transport_handle_t t,int port)256 esp_err_t esp_transport_set_default_port(esp_transport_handle_t t, int port)
257 {
258 if (t == NULL) {
259 return ESP_FAIL;
260 }
261 t->port = port;
262 return ESP_OK;
263 }
264
esp_transport_set_async_connect_func(esp_transport_handle_t t,connect_async_func _connect_async_func)265 esp_err_t esp_transport_set_async_connect_func(esp_transport_handle_t t, connect_async_func _connect_async_func)
266 {
267 if (t == NULL) {
268 return ESP_FAIL;
269 }
270 t->_connect_async = _connect_async_func;
271 return ESP_OK;
272 }
273
esp_transport_set_parent_transport_func(esp_transport_handle_t t,payload_transfer_func _parent_transport)274 esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payload_transfer_func _parent_transport)
275 {
276 if (t == NULL) {
277 return ESP_FAIL;
278 }
279 t->_parent_transfer = _parent_transport;
280 return ESP_OK;
281 }
282
esp_transport_get_error_handle(esp_transport_handle_t t)283 esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t)
284 {
285 if (t) {
286 return &t->error_handle->esp_tls_err_h_base;
287 }
288 return NULL;
289 }
290
esp_transport_get_errno(esp_transport_handle_t t)291 int esp_transport_get_errno(esp_transport_handle_t t)
292 {
293 if (t && t->error_handle) {
294 int actual_errno = t->error_handle->sock_errno;
295 t->error_handle->sock_errno = 0;
296 return actual_errno;
297 }
298 return -1;
299 }
300
esp_transport_set_errors(esp_transport_handle_t t,const esp_tls_error_handle_t error_handle)301 void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle)
302 {
303 if (t && t->error_handle) {
304 memcpy(&t->error_handle->esp_tls_err_h_base, error_handle, sizeof(esp_tls_last_error_t));
305 int sock_error;
306 if (esp_tls_get_and_clear_error_type(error_handle, ESP_TLS_ERR_TYPE_SYSTEM, &sock_error) == ESP_OK) {
307 t->error_handle->sock_errno = sock_error;
308 }
309 }
310 }
311
esp_transport_capture_errno(esp_transport_handle_t t,int sock_errno)312 void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno)
313 {
314 if (t && t->error_handle) {
315 t->error_handle->sock_errno = sock_errno;
316 }
317 }
318
esp_transport_get_socket(esp_transport_handle_t t)319 int esp_transport_get_socket(esp_transport_handle_t t)
320 {
321 if (t && t->_get_socket) {
322 return t->_get_socket(t);
323 }
324 return -1;
325 }
326