1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 
6 
7 
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 
13 #include "iotx_coap_internal.h"
14 #include "Cloud_CoAPExport.h"
15 #include "Cloud_CoAPNetwork.h"
16 
17 #ifdef COAP_DTLS_SUPPORT
18 
19 static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session);
20 
Cloud_CoAPNetworkDTLS_read(void * p_session,unsigned char * p_data,unsigned int * p_datalen,unsigned int timeout)21 unsigned int Cloud_CoAPNetworkDTLS_read(void *p_session, unsigned char *p_data,
22                                         unsigned int *p_datalen,
23                                         unsigned int timeout)
24 {
25     unsigned int err_code = DTLS_SUCCESS;
26     const unsigned int read_len = *p_datalen;
27     DTLSContext *context = NULL;
28 
29     COAP_TRC("<< secure_datagram_read, read buffer len %d, timeout %d",
30              read_len, timeout);
31     (void)read_len;
32     if (NULL != p_session) {
33         /* read dtls application data*/
34         context = (DTLSContext *)p_session;
35         err_code = HAL_DTLSSession_read(context, p_data, p_datalen, timeout);
36         if (DTLS_PEER_CLOSE_NOTIFY == err_code ||
37             DTLS_FATAL_ALERT_MESSAGE == err_code) {
38             COAP_INFO("dtls session read failed, return (0x%04x)", err_code);
39             Cloud_CoAPNetworkDTLS_freeSession(context);
40         }
41         if (DTLS_SUCCESS == err_code) {
42             return COAP_SUCCESS;
43         } else {
44             return COAP_ERROR_READ_FAILED;
45         }
46     }
47 
48     return COAP_ERROR_INVALID_PARAM;
49 }
50 
Cloud_CoAPNetworkDTLS_write(void * p_session,const unsigned char * p_data,unsigned int * p_datalen)51 unsigned int Cloud_CoAPNetworkDTLS_write(void *p_session,
52                                          const unsigned char *p_data,
53                                          unsigned int *p_datalen)
54 {
55     unsigned int err_code = DTLS_SUCCESS;
56     if (NULL != p_session) {
57         err_code =
58             HAL_DTLSSession_write((DTLSContext *)p_session, p_data, p_datalen);
59         if (DTLS_SUCCESS == err_code) {
60             return COAP_SUCCESS;
61         } else {
62             return COAP_ERROR_WRITE_FAILED;
63         }
64     }
65     return COAP_ERROR_INVALID_PARAM;
66 }
67 
Cloud_CoAPNetworkDTLS_freeSession(void * p_session)68 static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session)
69 {
70     /* Free the session.*/
71     HAL_DTLSSession_free((DTLSContext *)p_session);
72 }
73 
Cloud_CoAPNetworkDTLS_createSession(char * p_host,unsigned short port,unsigned char * p_ca_cert_pem)74 void *Cloud_CoAPNetworkDTLS_createSession(char *p_host, unsigned short port,
75                                           unsigned char *p_ca_cert_pem)
76 {
77     DTLSContext *context = NULL;
78 
79     coap_dtls_options_t dtls_options;
80 
81     memset(&dtls_options, 0x00, sizeof(coap_dtls_options_t));
82     dtls_options.p_ca_cert_pem = p_ca_cert_pem;
83     dtls_options.p_host = p_host;
84     dtls_options.port = port;
85 
86     context = HAL_DTLSSession_create(&dtls_options);
87     return (void *)context;
88 }
89 
90 #endif
91 
Cloud_CoAPNetwork_write(coap_network_t * p_network,const unsigned char * p_data,unsigned int datalen)92 unsigned int Cloud_CoAPNetwork_write(coap_network_t *p_network,
93                                      const unsigned char *p_data,
94                                      unsigned int datalen)
95 {
96     int rc = COAP_ERROR_WRITE_FAILED;
97 
98 #ifdef COAP_DTLS_SUPPORT
99     if (COAP_ENDPOINT_DTLS == p_network->ep_type) {
100         rc = Cloud_CoAPNetworkDTLS_write(p_network->context, p_data, &datalen);
101     } else {
102 #endif
103         rc = HAL_UDP_write((intptr_t)p_network->context, p_data, datalen);
104         COAP_DEBUG("[CoAP-NWK]: Network write return %d", rc);
105 
106         if (-1 == rc) {
107             rc = COAP_ERROR_WRITE_FAILED;
108         } else {
109             rc = COAP_SUCCESS;
110         }
111 #ifdef COAP_DTLS_SUPPORT
112     }
113 #endif
114     return (unsigned int)rc;
115 }
116 
Cloud_CoAPNetwork_read(coap_network_t * network,unsigned char * data,unsigned int datalen,unsigned int timeout)117 int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data,
118                            unsigned int datalen, unsigned int timeout)
119 {
120     int len = 0;
121 
122 #ifdef COAP_DTLS_SUPPORT
123     if (COAP_ENDPOINT_DTLS == network->ep_type) {
124         len = datalen;
125         memset(data, 0x00, datalen);
126         Cloud_CoAPNetworkDTLS_read(network->context, data, (unsigned int *)&len,
127                                    timeout);
128     } else {
129 #endif
130         memset(data, 0x00, datalen);
131         len = HAL_UDP_readTimeout((intptr_t)network->context, data,
132                                   COAP_MSG_MAX_PDU_LEN, timeout);
133 #ifdef COAP_DTLS_SUPPORT
134     }
135 #endif
136     if (len > 0) {
137         COAP_TRC("<< CoAP recv %d bytes data", len);
138     }
139     return len;
140 }
141 
Cloud_CoAPNetwork_init(const coap_network_init_t * p_param,coap_network_t * p_network)142 unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param,
143                                     coap_network_t *p_network)
144 {
145     unsigned int err_code = COAP_SUCCESS;
146 
147     if (NULL == p_param || NULL == p_network) {
148         return COAP_ERROR_INVALID_PARAM;
149     }
150 
151     /* TODO : Parse the url here */
152     p_network->ep_type = p_param->ep_type;
153 
154 #ifdef COAP_DTLS_SUPPORT
155     if (COAP_ENDPOINT_DTLS == p_param->ep_type) {
156         p_network->context = Cloud_CoAPNetworkDTLS_createSession(
157             p_param->p_host, p_param->port, p_param->p_ca_cert_pem);
158         if (NULL == p_network->context) {
159             return COAP_ERROR_NET_INIT_FAILED;
160         }
161     }
162 #endif
163     if (COAP_ENDPOINT_NOSEC == p_param->ep_type ||
164         COAP_ENDPOINT_PSK == p_param->ep_type) {
165         /*Create udp socket*/
166         p_network->context =
167             (void *)HAL_UDP_create(p_param->p_host, p_param->port);
168         if ((void *)-1 == p_network->context) {
169             return COAP_ERROR_NET_INIT_FAILED;
170         }
171     }
172     return err_code;
173 }
174 
Cloud_CoAPNetwork_deinit(coap_network_t * p_network)175 unsigned int Cloud_CoAPNetwork_deinit(coap_network_t *p_network)
176 {
177     unsigned int err_code = COAP_SUCCESS;
178 
179 #ifdef COAP_DTLS_SUPPORT
180     if (COAP_ENDPOINT_DTLS == p_network->ep_type) {
181         Cloud_CoAPNetworkDTLS_freeSession(p_network->context);
182         p_network->context = NULL;
183     }
184 #endif
185     if (COAP_ENDPOINT_NOSEC == p_network->ep_type ||
186         COAP_ENDPOINT_PSK == p_network->ep_type) {
187         HAL_UDP_close_without_connect((intptr_t)p_network->context);
188     }
189 
190     return err_code;
191 }
192