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