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