1 #include "iotx_cm_internal.h"
2 
3 #ifdef COAP_COMM_ENABLED
4 #include "iotx_cm.h"
5 #include "iotx_cm_coap.h"
6 #include "linkkit/infra/infra_timer.h"
7 
8 #ifdef COAP_DTLS_SUPPORT /* DTLS */
9 #ifdef ON_DAILY
10 #define IOTX_COAP_SERVER_URI "coaps://11.239.164.238:5684"
11 #else
12 #ifdef ON_PRE
13 #define IOTX_COAP_SERVER_URI \
14     "coaps://pre.coap.cn-shanghai.link.aliyuncs.com:5684"
15 
16 #else /* online */
17 #define IOTX_COAP_SERVER_URI \
18     "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684"
19 #endif
20 #endif
21 
22 #else
23 #ifdef COAP_PSK_SUPPORT /* PSK */
24 #ifdef ON_DAILY
25 #define IOTX_COAP_SERVER_URI "coap-psk://10.101.83.159:5682"
26 #else
27 #ifdef ON_PRE
28 #define IOTX_COAP_SERVER_URI \
29     "coap-psk://pre.coap.cn-shanghai.link.aliyuncs.com:5682"
30 #else /* online */
31 #define IOTX_COAP_SERVER_URI \
32     "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682"
33 #endif
34 #endif
35 #else /* UDP */
36 #ifdef ON_DAILY
37 #define IOTX_COAP_SERVER_URI ""
38 #else
39 #ifdef ON_PRE
40 #define IOTX_COAP_SERVER_URI \
41     "coap://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5683"
42 #else /* online */
43 #define IOTX_COAP_SERVER_URI "coap://%s.coap.cn-shanghai.link.aliyuncs.com:5683"
44 #endif
45 #endif
46 
47 #endif
48 #endif
49 
50 extern uint32_t IOT_CoAP_GetCurToken(iotx_coap_context_t *p_context);
51 int IOT_CoAP_GetMessageToken(void *p_message, unsigned int *token);
52 static struct list_head g_coap_response_list =
53     LIST_HEAD_INIT(g_coap_response_list);
54 
55 static iotx_cm_connection_t *_coap_conncection = NULL;
56 static int iotx_set_devinfo(iotx_coap_device_info_t *p_devinfo);
57 
58 static int _coap_connect(uint32_t timeout);
59 static int _coap_publish(iotx_cm_ext_params_t *params, const char *topic,
60                          const char *payload, unsigned int payload_len);
61 static int _coap_sub(iotx_cm_ext_params_t *params, const char *topic,
62                      iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
63 static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type);
64 static int _coap_unsub(const char *topic);
65 static int _coap_close();
66 static void _set_common_handlers();
67 
iotx_cm_open_coap(iotx_cm_init_param_t * params)68 iotx_cm_connection_t *iotx_cm_open_coap(iotx_cm_init_param_t *params)
69 {
70     iotx_coap_config_t *coap_config = NULL;
71     iotx_coap_device_info_t *deviceinfo = NULL;
72 
73     if (_coap_conncection != NULL) {
74         cm_warning("mqtt connection is opened already,return it");
75         return _coap_conncection;
76     }
77 
78     _coap_conncection =
79         (iotx_cm_connection_t *)cm_malloc(sizeof(iotx_cm_connection_t));
80     if (_coap_conncection == NULL) {
81         cm_err("_coap_conncection malloc failed!");
82         goto failed;
83     }
84 
85     _coap_conncection->list_lock = HAL_MutexCreate();
86     if (_coap_conncection->list_lock == NULL) {
87         cm_err("list_lock create failed!");
88         goto failed;
89     }
90 
91     coap_config = (iotx_coap_config_t *)cm_malloc(sizeof(iotx_coap_config_t));
92     if (coap_config == NULL) {
93         cm_err("coap_config malloc failed!");
94         goto failed;
95     }
96     memset(coap_config, 0, sizeof(iotx_coap_config_t));
97     deviceinfo =
98         (iotx_coap_device_info_t *)cm_malloc(sizeof(iotx_coap_device_info_t));
99     if (deviceinfo == NULL) {
100         cm_err("deviceinfo malloc failed!");
101         goto failed;
102     }
103 
104     _coap_conncection->open_params = coap_config;
105 
106     memset(deviceinfo, 0, sizeof(iotx_coap_device_info_t));
107 
108     iotx_set_devinfo(deviceinfo);
109     coap_config->wait_time_ms = params->request_timeout_ms;
110     coap_config->p_devinfo = deviceinfo;
111     /* coap_config->p_url = IOTX_COAP_SERVER_URI; */
112 
113     _coap_conncection->event_handler = params->handle_event;
114 
115     _set_common_handlers();
116 
117     return _coap_conncection;
118 
119 failed:
120     if (_coap_conncection != NULL) {
121         if (_coap_conncection->list_lock != NULL) {
122             HAL_MutexDestroy(_coap_conncection->list_lock);
123         }
124         cm_free(_coap_conncection);
125         _coap_conncection = NULL;
126     }
127 
128     if (coap_config != NULL) {
129         cm_free(coap_config);
130     }
131     if (deviceinfo != NULL) {
132         cm_free(deviceinfo);
133     }
134 
135     return NULL;
136 }
137 
iotx_set_devinfo(iotx_coap_device_info_t * p_devinfo)138 static int iotx_set_devinfo(iotx_coap_device_info_t *p_devinfo)
139 {
140     if (NULL == p_devinfo) {
141         return IOTX_ERR_INVALID_PARAM;
142     }
143 
144     memset(p_devinfo, 0x00, sizeof(iotx_coap_device_info_t));
145 
146     /**< get device info*/
147     HAL_GetProductKey(p_devinfo->product_key);
148     HAL_GetDeviceName(p_devinfo->device_name);
149     HAL_GetDeviceSecret(p_devinfo->device_secret);
150     HAL_Snprintf(p_devinfo->device_id,
151                  IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2, "%s.%s",
152                  p_devinfo->product_key, p_devinfo->device_name);
153     p_devinfo->device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] =
154         '\0';
155     /**< end*/
156     cm_info("*****The Product Key  : %s *****\r\n", p_devinfo->product_key);
157     cm_info("*****The Device Name  : %s *****\r\n", p_devinfo->device_name);
158     cm_info("*****The Device Secret: %s *****\r\n", p_devinfo->device_secret);
159     cm_info("*****The Device ID    : %s *****\r\n", p_devinfo->device_id);
160     return IOTX_SUCCESS;
161 }
162 
_coap_connect(uint32_t timeout)163 static int _coap_connect(uint32_t timeout)
164 {
165     int ret;
166     char url[100] = { 0 };
167     iotx_time_t timer;
168     iotx_coap_config_t *config = NULL;
169     iotx_coap_context_t *p_ctx = NULL;
170     char product_key[IOTX_PRODUCT_KEY_LEN + 1] = { 0 };
171 
172     if (_coap_conncection == NULL) {
173         return NULL_VALUE_ERROR;
174     }
175 
176     HAL_GetProductKey(product_key);
177     config = _coap_conncection->open_params;
178     if (config == NULL) {
179         return NULL_VALUE_ERROR;
180     }
181 
182     HAL_Snprintf(url, 100, IOTX_COAP_SERVER_URI, product_key);
183     config->p_url = url;
184 
185     iotx_time_init(&timer);
186     utils_time_countdown_ms(&timer, timeout);
187     do {
188         if (p_ctx == NULL) {
189             p_ctx = IOT_CoAP_Init(config);
190             if (NULL == p_ctx) {
191                 continue;
192             }
193         }
194         ret = IOT_CoAP_DeviceNameAuth(p_ctx);
195         if (ret == 0) {
196             iotx_cm_event_msg_t event;
197             event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
198             event.msg = NULL;
199             _coap_conncection->context = p_ctx;
200 
201             if (_coap_conncection->event_handler) {
202                 _coap_conncection->event_handler(_coap_conncection->fd, &event,
203                                                  (void *)_coap_conncection);
204             }
205             return 0;
206         }
207     } while (!utils_time_is_expired(&timer));
208 
209     {
210         iotx_cm_event_msg_t event;
211         event.type = IOTX_CM_EVENT_CLOUD_CONNECT_FAILED;
212         event.msg = NULL;
213 
214         if (_coap_conncection->event_handler) {
215             _coap_conncection->event_handler(_coap_conncection->fd, &event,
216                                              (void *)_coap_conncection);
217         }
218     }
219     cm_err("mqtt connect failed");
220     return -1;
221 }
222 
_coap_response_default(void * p_arg,void * p_message)223 static void _coap_response_default(void *p_arg, void *p_message)
224 {
225     int ret;
226     int len = 0;
227     unsigned char *p_payload = NULL;
228     unsigned int token;
229     iotx_coap_resp_code_t resp_code;
230     coap_response_node_t *node = NULL;
231     coap_response_node_t *next = NULL;
232 
233     if (_coap_conncection == NULL || p_message == NULL) {
234         cm_err("paras err");
235         return;
236     }
237 
238     ret = IOT_CoAP_GetMessageCode(p_message, &resp_code);
239     if (ret < 0) {
240         cm_err("get msg code err");
241         return;
242     }
243 
244     cm_info("resp_code = %d", resp_code);
245 
246     ret = IOT_CoAP_GetMessagePayload(p_message, &p_payload, &len);
247     if (ret < 0) {
248         cm_err("get msg payload err");
249         return;
250     }
251 
252     ret = IOT_CoAP_GetMessageToken(p_message, &token);
253     if (ret < 0) {
254         cm_err("get msg token err");
255         return;
256     }
257 
258     HAL_MutexLock(_coap_conncection->list_lock);
259     list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list,
260                              coap_response_node_t)
261     {
262         if (node->token_num == token) {
263             iotx_cm_data_handle_cb recieve_cb = node->responce_cb;
264             void *context = node->context;
265             unsigned int topic_len = strlen(node->topic) + 1;
266             char *topic = cm_malloc(topic_len);
267             if (topic == NULL) {
268                 cm_err("topic malloc failed");
269                 continue;
270             }
271             memset(topic, 0, topic_len);
272             strncpy(topic, node->topic, topic_len);
273             list_del(&node->linked_list);
274             cm_free(node->topic);
275             cm_free(node);
276             HAL_MutexUnlock(
277                 _coap_conncection->list_lock); /* do not lock while callback */
278 
279             recieve_cb(_coap_conncection->fd, topic, (const char *)p_payload,
280                        len, context);
281             /* recieve_cb(_coap_conncection->fd, &msg, context); */
282             cm_free(topic);
283             HAL_MutexLock(_coap_conncection->list_lock);
284         }
285     }
286     HAL_MutexUnlock(_coap_conncection->list_lock);
287 }
288 
_coap_publish(iotx_cm_ext_params_t * ext,const char * topic,const char * payload,unsigned int payload_len)289 static int _coap_publish(iotx_cm_ext_params_t *ext, const char *topic,
290                          const char *payload, unsigned int payload_len)
291 {
292     iotx_msg_type_t qos = 0;
293     iotx_message_t message;
294     uint32_t token;
295     int topic_len;
296     int ret;
297 
298     if (_coap_conncection == NULL) {
299         return NULL_VALUE_ERROR;
300     }
301 
302     if (ext != NULL) {
303         qos = _get_coap_qos(ext->ack_type);
304     }
305     memset(&message, 0, sizeof(iotx_message_t));
306 
307     message.p_payload = (unsigned char *)payload;
308     message.payload_len = payload_len;
309     message.resp_callback = _coap_response_default;
310     message.msg_type = qos;
311     message.content_type = IOTX_CONTENT_TYPE_JSON;
312 
313     token =
314         IOT_CoAP_GetCurToken((iotx_coap_context_t *)_coap_conncection->context);
315     ret =
316         IOT_CoAP_SendMessage((iotx_coap_context_t *)_coap_conncection->context,
317                              (char *)topic, &message);
318 
319     if (ret < 0) {
320         return -1;
321     }
322 
323     if (ext != NULL && ext->ack_cb != NULL) {
324         coap_response_node_t *node;
325         node = (coap_response_node_t *)cm_malloc(sizeof(coap_response_node_t));
326         if (node == NULL) {
327             return -1;
328         }
329         memset(node, 0, sizeof(coap_response_node_t));
330         topic_len = strlen(topic) + 1;
331         node->topic = (char *)cm_malloc(topic_len);
332         if (node->topic == NULL) {
333             cm_free(node);
334             return -1;
335         }
336 
337         memset(node->topic, 0, topic_len);
338         strncpy(node->topic, topic, topic_len);
339 
340         node->user_data = _coap_conncection;
341         node->responce_cb = ext->ack_cb;
342         node->context = ext->cb_context;
343         node->token_num = token;
344 
345         HAL_MutexLock(_coap_conncection->list_lock);
346         list_add_tail(&node->linked_list, &g_coap_response_list);
347         HAL_MutexUnlock(_coap_conncection->list_lock);
348     }
349     return 0;
350 }
351 
_coap_yield(uint32_t timeout)352 static int _coap_yield(uint32_t timeout)
353 {
354     if (_coap_conncection == NULL) {
355         return NULL_VALUE_ERROR;
356     }
357     return IOT_CoAP_Yield((iotx_coap_context_t *)_coap_conncection->context);
358 }
359 
_coap_sub(iotx_cm_ext_params_t * ext,const char * topic,iotx_cm_data_handle_cb topic_handle_func,void * pcontext)360 static int _coap_sub(iotx_cm_ext_params_t *ext, const char *topic,
361                      iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
362 {
363     return 0;
364 }
365 
_coap_unsub(const char * topic)366 static int _coap_unsub(const char *topic)
367 {
368     return 0;
369 }
370 
_coap_close()371 static int _coap_close()
372 {
373     coap_response_node_t *node = NULL;
374     coap_response_node_t *next = NULL;
375     iotx_coap_config_t *coap_config = NULL;
376 
377     if (_coap_conncection == NULL) {
378         return NULL_VALUE_ERROR;
379     }
380 
381     coap_config = (iotx_coap_config_t *)_coap_conncection->open_params;
382 
383     HAL_MutexLock(_coap_conncection->list_lock);
384     list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list,
385                              coap_response_node_t)
386     {
387         cm_free(node->topic);
388         list_del(&node->linked_list);
389         cm_free(node);
390     }
391     HAL_MutexUnlock(_coap_conncection->list_lock);
392 
393     if (_coap_conncection->list_lock != NULL) {
394         HAL_MutexDestroy(_coap_conncection->list_lock);
395     }
396     cm_free(coap_config->p_devinfo);
397     cm_free(coap_config);
398     IOT_CoAP_Deinit(&_coap_conncection->context);
399 
400     cm_free(_coap_conncection);
401     _coap_conncection = NULL;
402     return 0;
403 }
404 
_get_coap_qos(iotx_cm_ack_types_t ack_type)405 static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type)
406 {
407     switch (ack_type) {
408     case IOTX_CM_MESSAGE_NO_ACK:
409         return IOTX_MESSAGE_NON;
410 
411     case IOTX_CM_MESSAGE_NEED_ACK:
412         return IOTX_MESSAGE_CON;
413 
414     default:
415         return IOTX_MESSAGE_CON;
416     }
417 }
418 
_set_common_handlers()419 static void _set_common_handlers()
420 {
421     if (_coap_conncection != NULL) {
422         _coap_conncection->connect_func = _coap_connect;
423         _coap_conncection->sub_func = _coap_sub;
424         _coap_conncection->unsub_func = _coap_unsub;
425         _coap_conncection->pub_func = _coap_publish;
426         _coap_conncection->yield_func = _coap_yield;
427         _coap_conncection->close_func = _coap_close;
428     }
429 }
430 #endif
431