1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 
6 #include "alcs_internal.h"
7 #include "alcs_api_internal.h"
8 #include "CoAPPlatform.h"
9 #include "CoAPResource.h"
10 
11 #ifdef ALCS_CLIENT_ENABLED
12 static int default_heart_interval = 30000;
match_key(const char * accesskey,const char * keyprefix)13 char match_key(const char *accesskey, const char *keyprefix)
14 {
15     if (strlen(keyprefix) == KEYPREFIX_LEN &&
16         strstr(accesskey, keyprefix) == accesskey) {
17         return 1;
18     }
19 
20     return 0;
21 }
22 
23 int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item,
24             void *userdata, AuthHandler handler);
res_parse(const char * payload,int len,int * seq,ResponseMsg * res_msg,char ** data,int * datalen)25 bool res_parse(const char *payload, int len, int *seq, ResponseMsg *res_msg,
26                char **data, int *datalen)
27 {
28     if (!payload || !len || !seq || !res_msg || !data) {
29         return 0;
30     }
31 
32     COAP_DEBUG("payload:%.*s", len, payload);
33 
34     int tmplen;
35     char *tmp;
36 
37     tmp = json_get_value_by_name((char *)payload, len, "id", &tmplen, NULL);
38     if (!tmp) {
39         return 0;
40     }
41 
42     char back;
43     backup_json_str_last_char(tmp, tmplen, back);
44     *seq = atoi(tmp);
45     restore_json_str_last_char(tmp, tmplen, back);
46 
47     tmp = json_get_value_by_name((char *)payload, len, "code", &tmplen, NULL);
48     if (!tmp) {
49         return 0;
50     }
51 
52     backup_json_str_last_char(tmp, tmplen, back);
53     res_msg->code = atoi(tmp);
54     restore_json_str_last_char(tmp, tmplen, back);
55 
56     tmp = json_get_value_by_name((char *)payload, len, "msg", &tmplen, NULL);
57     if (tmp && tmplen) {
58         res_msg->msg = (char *)coap_malloc(tmplen);
59         memcpy(res_msg->msg, tmp, tmplen);
60     } else {
61         res_msg->msg = NULL;
62     }
63 
64     *data = json_get_value_by_name((char *)payload, len, "data", datalen, NULL);
65     return 1;
66 }
67 
fillAccessKey(CoAPContext * ctx,char * buf)68 bool fillAccessKey(CoAPContext *ctx, char *buf)
69 {
70     auth_list *lst = get_list(ctx);
71     if (!lst) {
72         return 0;
73     }
74 
75     HAL_MutexLock(lst->list_mutex);
76 
77     if (list_empty(&lst->lst_ctl)) {
78         HAL_MutexUnlock(lst->list_mutex);
79         return 0;
80     }
81     strcpy(buf, ",\"accessKeys\":[");
82     ctl_key_item *node = NULL, *next = NULL;
83     list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item)
84     {
85         char *format;
86         if (lst->ctl_group_count || !list_is_last(&node->lst, &lst->lst_ctl)) {
87             format = "\"%s\",";
88         } else {
89             format = "\"%s\"]";
90         }
91         sprintf(buf + strlen(buf), format, node->accessKey);
92     }
93 
94     ctl_group_item *gnode = NULL, *gnext = NULL;
95     list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst,
96                              ctl_group_item)
97     {
98         char *format;
99         if (!list_is_last(&gnode->lst, &lst->lst_ctl_group)) {
100             format = "\"%s\",";
101         } else {
102             format = "\"%s\"]";
103         }
104         sprintf(buf + strlen(buf), format, gnode->accessKey);
105     }
106 
107     HAL_MutexUnlock(lst->list_mutex);
108     return 1;
109 }
110 
111 #define payload_format                                              \
112     "{\"version\":\"1.0\",\"method\":\"%s\",\"id\":%d,\"params\":{" \
113     "\"prodKey\":\"%s\", \"deviceName\":\"%s\"%s}}"
nego_cb(CoAPContext * ctx,CoAPReqResult result,void * userdata,NetworkAddr * remote,CoAPMessage * message)114 void nego_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata,
115              NetworkAddr *remote, CoAPMessage *message)
116 {
117     COAP_INFO("nego_cb, message addr:%p, networkaddr:%p!", message, remote);
118     AuthParam *auth_param = (AuthParam *)userdata;
119 
120     if (COAP_RECV_RESP_TIMEOUT == result) {
121         ResponseMsg msg = { -1, "response time!" };
122         auth_param->handler(ctx, remote, auth_param->user_data, &msg);
123         coap_free(auth_param->productKey);
124         coap_free(auth_param->deviceName);
125         coap_free(auth_param);
126 
127     } else {
128         COAP_DEBUG("recv response message");
129         int seq, datalen;
130         ResponseMsg msg;
131         char *data;
132 
133         res_parse((const char *)message->payload, message->payloadlen, &seq,
134                   &msg, &data, &datalen);
135         do {
136             if (msg.code != 200) {
137                 break;
138             }
139 
140             int keylen;
141             char *accessKey = json_get_value_by_name(data, datalen, "accessKey",
142                                                      &keylen, NULL);
143             if (!accessKey || !keylen) {
144                 break;
145             }
146             COAP_DEBUG("accesskey:%.*s", keylen, accessKey);
147 
148             auth_list *lst = get_list(ctx);
149             ctl_key_item *node = NULL, *next = NULL;
150             char *accessTokenFound = NULL;
151             HAL_MutexLock(lst->list_mutex);
152 
153             list_for_each_entry_safe(node, next, &lst->lst_ctl, lst,
154                                      ctl_key_item)
155             {
156                 COAP_DEBUG("node:%s", node->accessKey);
157                 if (strncmp(node->accessKey, accessKey, keylen) == 0) {
158                     accessTokenFound = node->accessToken;
159                     break;
160                 }
161             }
162 
163             if (!accessTokenFound) {
164                 ctl_group_item *gnode = NULL, *gnext = NULL;
165                 list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst,
166                                          ctl_group_item)
167                 {
168                     COAP_DEBUG("node:%s", gnode->accessKey);
169                     if (strncmp(gnode->accessKey, accessKey, keylen) == 0) {
170                         accessTokenFound = gnode->accessKey;
171                         break;
172                     }
173                 }
174             }
175 
176             HAL_MutexUnlock(lst->list_mutex);
177 
178             if (accessTokenFound) {
179                 ctl_key_item item;
180                 item.deviceName = auth_param->deviceName;
181                 item.productKey = auth_param->productKey;
182 
183                 item.accessKey = accessKey;
184                 item.accessToken = accessTokenFound;
185                 char back;
186                 backup_json_str_last_char(accessKey, keylen, back);
187                 do_auth(ctx, remote, &item, auth_param->user_data,
188                         auth_param->handler);
189                 restore_json_str_last_char(accessKey, keylen, back);
190 
191                 coap_free(auth_param->productKey);
192                 coap_free(auth_param->deviceName);
193                 coap_free(auth_param);
194                 return;
195             }
196         } while (0);
197 
198         /* todo */
199         ResponseMsg tmp = { -1, "" };
200         auth_param->handler(ctx, remote, auth_param->user_data, &tmp);
201         coap_free(auth_param->productKey);
202         coap_free(auth_param->deviceName);
203         coap_free(auth_param);
204     }
205 }
206 
CoAPServerPath_2_option(char * uri,CoAPMessage * message)207 static int CoAPServerPath_2_option(char *uri, CoAPMessage *message)
208 {
209     char *ptr = NULL;
210     char *pstr = NULL;
211     char path[COAP_MSG_MAX_PATH_LEN] = { 0 };
212 
213     if (NULL == uri || NULL == message) {
214         COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
215         return COAP_ERROR_INVALID_PARAM;
216     }
217     if (256 < strlen(uri)) {
218         COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
219         return COAP_ERROR_INVALID_LENGTH;
220     }
221     COAP_DEBUG("The uri is %s", uri);
222     ptr = pstr = uri;
223     while ('\0' != *ptr) {
224         if ('/' == *ptr) {
225             if (ptr != pstr) {
226                 memset(path, 0x00, sizeof(path));
227                 strncpy(path, pstr, ptr - pstr);
228                 COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
229                 CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
230                                   (unsigned char *)path, (int)strlen(path));
231             }
232             pstr = ptr + 1;
233         }
234         if ('\0' == *(ptr + 1) && '\0' != *pstr) {
235             memset(path, 0x00, sizeof(path));
236             strncpy(path, pstr, sizeof(path) - 1);
237             COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
238             CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
239                               (unsigned char *)path, (int)strlen(path));
240         }
241         ptr++;
242     }
243     return COAP_SUCCESS;
244 }
245 
auth_cb(CoAPContext * ctx,CoAPReqResult result,void * userdata,NetworkAddr * remote,CoAPMessage * message)246 void auth_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata,
247              NetworkAddr *remote, CoAPMessage *message)
248 {
249     AlcsDeviceKey devKey;
250     COAP_DEBUG("recv auth_cb response message");
251 
252     AuthParam *auth_param = (AuthParam *)userdata;
253     memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
254     memcpy(&devKey.addr, remote, sizeof(NetworkAddr));
255     devKey.pk = auth_param->productKey;
256     devKey.dn = auth_param->deviceName;
257     session_item *session = get_ctl_session(ctx, &devKey);
258 
259     if (!session) {
260         COAP_INFO("receive unknown auth_cb response, pk:%s, dn:%s", devKey.pk,
261                   devKey.dn);
262         ResponseMsg msg = { -1, "no session found!" };
263         auth_param->handler(ctx, remote, auth_param->user_data, &msg);
264     } else if (COAP_RECV_RESP_TIMEOUT == result) {
265         COAP_ERR("response time!");
266         ResponseMsg msg = { -1, "response time!" };
267         auth_param->handler(ctx, remote, auth_param->user_data, &msg);
268         remove_session(ctx, session);
269     } else {
270         int seq, datalen;
271         ResponseMsg msg;
272         char *data;
273 
274         res_parse((const char *)message->payload, message->payloadlen, &seq,
275                   &msg, &data, &datalen);
276         if (msg.code == 200) {
277             do {
278                 int tmplen;
279                 char *tmp;
280 
281                 tmp = json_get_value_by_name(data, datalen, "sessionId",
282                                              &tmplen, NULL);
283                 if (!tmp) {
284                     msg.code = -1;
285                     msg.msg = "sessionid = NULL!";
286                     COAP_ERR("sessionid = NULL!");
287                     auth_param->handler(ctx, remote, auth_param->user_data,
288                                         &msg);
289                     break;
290                 }
291                 char back;
292                 backup_json_str_last_char(tmp, tmplen, back);
293                 session->sessionId = atoi(tmp);
294                 restore_json_str_last_char(tmp, tmplen, back);
295                 COAP_INFO("sessionId:%d", session->sessionId);
296 
297                 tmp = json_get_value_by_name(data, datalen, "randomKey",
298                                              &tmplen, NULL);
299                 if (!tmp) {
300                     msg.code = -1;
301                     msg.msg = "randomKey = NULL!";
302                     COAP_ERR("randomKey = NULL!");
303                     auth_param->handler(ctx, remote, auth_param->user_data,
304                                         &msg);
305                     break;
306                 }
307 
308                 char buf[32];
309                 HAL_Snprintf(buf, sizeof(buf), "%s%.*s", session->randomKey,
310                              tmplen, tmp);
311                 utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey,
312                                     auth_param->accessToken,
313                                     strlen(auth_param->accessToken));
314                 session->authed_time = HAL_UptimeMs();
315                 session->heart_time = session->authed_time;
316                 session->interval = default_heart_interval;
317                 COAP_INFO("sessionKey is created");
318             } while (0);
319         } else {
320             remove_session(ctx, session);
321             COAP_ERR("message code :%d", msg.code);
322         }
323         auth_param->handler(ctx, remote, auth_param->user_data, &msg);
324     }
325 
326     coap_free(auth_param->productKey);
327     coap_free(auth_param->deviceName);
328     coap_free(auth_param->accessToken);
329     coap_free(auth_param);
330 }
331 
332 #define auth_payload_format                                               \
333     "{\"version\":\"1.0\",\"method\":\"core/service/"                     \
334     "auth\",\"id\":%d,\"params\":{\"prodKey\":\"%s\", "                   \
335     "\"deviceName\":\"%s\",\"encrypt\":\"payload\",\"randomKey\":\"%s\"," \
336     "\"sign\":\"%s\",\"accessKey\":\"%s\"}}"
337 
do_auth(CoAPContext * ctx,NetworkAddr * addr,ctl_key_item * ctl_item,void * user_data,AuthHandler handler)338 int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item,
339             void *user_data, AuthHandler handler)
340 {
341     int ret = COAP_SUCCESS;
342     AlcsDeviceKey devKey;
343     device_auth_list *dev = get_device(ctx);
344     if (!dev) {
345         return COAP_ERROR_INVALID_PARAM;
346     }
347 
348     memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
349     memcpy(&devKey.addr, addr, sizeof(NetworkAddr));
350     devKey.pk = ctl_item->productKey;
351     devKey.dn = ctl_item->deviceName;
352 
353     session_item *session = get_ctl_session(ctx, &devKey);
354     if (session) {
355         if (session->sessionId) {
356             COAP_INFO("no need to reauth!");
357             ResponseMsg res = { COAP_SUCCESS, NULL };
358             handler(ctx, addr, user_data, &res);
359             return COAP_SUCCESS;
360         } else {
361             COAP_INFO("is authing, no need to reauth!");
362             return ALCS_ERR_AUTH_AUTHING;
363         }
364     }
365 
366     /* create&save session item */
367     {
368         session = (session_item *)coap_malloc(sizeof(session_item));
369         memset(session, 0, sizeof(session_item));
370 
371         char path[100] = { 0 };
372         strncpy(path, ctl_item->productKey, sizeof(path) - 1);
373         strncat(path, ctl_item->deviceName, sizeof(path) - strlen(path) - 1);
374         CoAPPathMD5_sum(path, strlen(path), session->pk_dn, PK_DN_CHECKSUM_LEN);
375         COAP_INFO("pk:%s, dn:%s, checksum:%s", devKey.pk, devKey.dn,
376                   session->pk_dn);
377         memcpy(&session->addr, addr, sizeof(NetworkAddr));
378         gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
379 
380         struct list_head *ctl_head = get_ctl_session_list(ctx);
381         list_add_tail(&session->lst, ctl_head);
382     }
383 
384     char sign[64] = { 0 };
385     int sign_len = sizeof(sign);
386     utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN,
387                            ctl_item->accessToken, strlen(ctl_item->accessToken),
388                            sign, &sign_len);
389     COAP_INFO("calc randomKey:%s,token:%s,sign:%.*s", session->randomKey,
390               ctl_item->accessToken, sign_len, sign);
391 
392     char payloadbuf[512];
393     sprintf(payloadbuf, auth_payload_format, ++dev->seq, ctl_item->productKey,
394             ctl_item->deviceName, session->randomKey, sign,
395             ctl_item->accessKey);
396     COAP_INFO("payload:%s", payloadbuf);
397 
398     CoAPLenString payload;
399     payload.data = (unsigned char *)payloadbuf;
400     payload.len = strlen(payloadbuf);
401     CoAPMessage message;
402     alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0,
403                   &payload, NULL);
404 
405     char path[120];
406     sprintf(path, "/dev/%s/%s/core/service/auth", ctl_item->productKey,
407             ctl_item->deviceName);
408     CoAPServerPath_2_option(path, &message);
409 
410     AuthParam *authParam = (AuthParam *)coap_malloc(sizeof(AuthParam));
411     authParam->handler = handler;
412     authParam->user_data = user_data;
413     authParam->productKey =
414         (char *)coap_malloc(strlen(ctl_item->productKey) + 1);
415     strcpy(authParam->productKey, ctl_item->productKey);
416     authParam->deviceName =
417         (char *)coap_malloc(strlen(ctl_item->deviceName) + 1);
418     strcpy(authParam->deviceName, ctl_item->deviceName);
419     authParam->accessToken =
420         (char *)coap_malloc(strlen(ctl_item->accessToken) + 1);
421     strcpy(authParam->accessToken, ctl_item->accessToken);
422     message.user = authParam;
423     message.handler = auth_cb;
424 
425     ret = CoAPMessage_send(ctx, addr, &message);
426     CoAPMessage_destory(&message);
427 
428     return ret;
429 }
430 
alcs_auth_has_key(CoAPContext * ctx,NetworkAddr * addr,AuthParam * auth_param)431 void alcs_auth_has_key(CoAPContext *ctx, NetworkAddr *addr,
432                        AuthParam *auth_param)
433 {
434     ctl_key_item item;
435     item.accessKey = auth_param->accessKey;
436     item.deviceName = auth_param->deviceName;
437     item.productKey = auth_param->productKey;
438     item.accessToken =
439         auth_param->accessToken; /* (char*) coap_malloc
440                                     (strlen(auth_param->accessToken) + 1); */
441     /* strcpy (item.accessToken, auth_param->accessToken); */
442     do_auth(ctx, addr, &item, auth_param->user_data, auth_param->handler);
443 }
444 
alcs_auth_nego_key(CoAPContext * ctx,AlcsDeviceKey * devKey,AuthHandler handler)445 void alcs_auth_nego_key(CoAPContext *ctx, AlcsDeviceKey *devKey,
446                         AuthHandler handler)
447 {
448     COAP_DEBUG("alcs_auth_nego_key");
449 
450     device_auth_list *dev = get_device(ctx);
451     if (!dev) {
452         COAP_INFO("no device!");
453         return;
454     }
455 
456     char accesskeys[1024] = { 0 };
457     if (!fillAccessKey(ctx, accesskeys)) {
458         COAP_INFO("no ctl key!");
459         return;
460     }
461     COAP_INFO("accesskeys:%s", accesskeys);
462 
463     const char *method = "core/service/auth/select";
464     char payloadbuf[1024];
465     sprintf(payloadbuf, payload_format, method, ++dev->seq, devKey->pk,
466             devKey->dn, accesskeys);
467 
468     CoAPLenString payload;
469     payload.data = (unsigned char *)payloadbuf;
470     payload.len = strlen(payloadbuf);
471     CoAPMessage message;
472     alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0,
473                   &payload, NULL);
474 
475     char path[120];
476     sprintf(path, "/dev/%s/%s/core/service/auth/select", devKey->pk,
477             devKey->dn);
478     CoAPServerPath_2_option(path, &message);
479 
480     AuthParam *authParam = (AuthParam *)coap_malloc(sizeof(AuthParam));
481     memset(authParam, 0, sizeof(AuthParam));
482 
483     authParam->handler = handler;
484     authParam->productKey = (char *)coap_malloc(strlen(devKey->pk) + 1);
485     strcpy(authParam->productKey, devKey->pk);
486     authParam->deviceName = (char *)coap_malloc(strlen(devKey->dn) + 1);
487     strcpy(authParam->deviceName, devKey->dn);
488 
489     message.user = authParam;
490     message.handler = nego_cb;
491     CoAPMessage_send(ctx, &devKey->addr, &message);
492     CoAPMessage_destory(&message);
493 }
494 
alcs_add_client_key(CoAPContext * ctx,const char * accesskey,const char * accesstoken,const char * productKey,const char * deviceName)495 int alcs_add_client_key(CoAPContext *ctx, const char *accesskey,
496                         const char *accesstoken, const char *productKey,
497                         const char *deviceName)
498 {
499     auth_list *lst = get_list(ctx);
500     if (!lst || lst->ctl_count >= KEY_MAXCOUNT) {
501         return COAP_ERROR_INVALID_LENGTH;
502     }
503 
504     ctl_key_item *item = (ctl_key_item *)coap_malloc(sizeof(ctl_key_item));
505     if (!item) {
506         return COAP_ERROR_MALLOC;
507     }
508     item->accessKey = (char *)coap_malloc(strlen(accesskey) + 1);
509     item->accessToken = (char *)coap_malloc(strlen(accesstoken) + 1);
510 
511     if (!item->accessKey || !item->accessToken) {
512         coap_free(item);
513         return COAP_ERROR_MALLOC;
514     }
515     strcpy(item->accessKey, accesskey);
516     strcpy(item->accessToken, accesstoken);
517 
518     if (deviceName) {
519         item->deviceName = (char *)coap_malloc(strlen(deviceName) + 1);
520         strcpy(item->deviceName, deviceName);
521     }
522 
523     HAL_MutexLock(lst->list_mutex);
524     list_add_tail(&item->lst, &lst->lst_ctl);
525     ++lst->ctl_count;
526     HAL_MutexUnlock(lst->list_mutex);
527 
528     return COAP_SUCCESS;
529 }
530 
alcs_remove_client_key(CoAPContext * ctx,const char * key,char isfullkey)531 int alcs_remove_client_key(CoAPContext *ctx, const char *key, char isfullkey)
532 {
533     auth_list *lst = get_list(ctx);
534     if (!lst) {
535         return COAP_ERROR_NULL;
536     }
537 
538     ctl_key_item *node = NULL, *next = NULL;
539     HAL_MutexLock(lst->list_mutex);
540 
541     list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item)
542     {
543         if (match_key(node->accessKey, key)) {
544             coap_free(node->accessKey);
545             coap_free(node->accessToken);
546             list_del(&node->lst);
547             coap_free(node);
548             break;
549         }
550     }
551     HAL_MutexUnlock(lst->list_mutex);
552     return COAP_SUCCESS;
553 }
554 
alcs_device_online(CoAPContext * ctx,AlcsDeviceKey * devKey)555 bool alcs_device_online(CoAPContext *ctx, AlcsDeviceKey *devKey)
556 {
557     session_item *session = get_ctl_session(ctx, devKey);
558     return session && session->sessionId ? 1 : 0;
559 }
560 
heart_beat_cb(CoAPContext * ctx,CoAPReqResult result,void * userdata,NetworkAddr * remote,CoAPMessage * message)561 void heart_beat_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata,
562                    NetworkAddr *remote, CoAPMessage *message)
563 {
564     COAP_DEBUG("heart_beat_cb, message addr:%p, networkaddr:%p!", message,
565                remote);
566 
567     struct list_head *ctl_head = get_ctl_session_list(ctx);
568     if (!ctl_head || list_empty(ctl_head)) {
569         return;
570     }
571 
572     if (result == COAP_RECV_RESP_TIMEOUT) {
573         COAP_ERR("heart beat timeout");
574         session_item *node = NULL, *next = NULL;
575         list_for_each_entry_safe(node, next, ctl_head, lst, session_item)
576         {
577             if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
578                 remove_session(ctx, node);
579             }
580         }
581     } else {
582         session_item *node = NULL, *next = NULL;
583         list_for_each_entry_safe(node, next, ctl_head, lst, session_item)
584         {
585             if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
586                 unsigned int sessionId = 0;
587                 CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
588 
589                 if (node->sessionId != sessionId) {
590                     COAP_INFO("receive stale heart beat response");
591                     remove_session(ctx, node);
592                 } else {
593                     node->heart_time = HAL_UptimeMs();
594                 }
595             }
596         }
597     }
598 }
599 
on_client_auth_timer(CoAPContext * ctx)600 void on_client_auth_timer(CoAPContext *ctx)
601 {
602     struct list_head *ctl_head = get_ctl_session_list(ctx);
603     if (!ctl_head || list_empty(ctl_head)) {
604         return;
605     }
606     COAP_DEBUG("on_client_auth_timer:%d", (int)HAL_UptimeMs());
607 
608     device_auth_list *dev = get_device(ctx);
609     char payloadbuf[64];
610     sprintf(payloadbuf,
611             "{\"id\":%d,\"version\":\"1.0\",\"params\":{\"delayTime\":%d}}",
612             ++dev->seq, 5000);
613 
614     CoAPLenString payload;
615     payload.data = (unsigned char *)payloadbuf;
616     payload.len = strlen(payloadbuf);
617     int tick = HAL_UptimeMs();
618 
619     session_item *node = NULL, *next = NULL;
620     list_for_each_entry_safe(node, next, ctl_head, lst, session_item)
621     {
622         if (!node->sessionId) {
623             continue;
624         }
625 
626         if (node->heart_time + node->interval > tick) {
627             CoAPMessage message;
628             alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET,
629                           COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
630             CoAPServerPath_2_option("/dev/core/service/heartBeat", &message);
631             message.handler = heart_beat_cb;
632             CoAPMessage_send(ctx, &node->addr, &message);
633             COAP_DEBUG("send heartbeat to :%s", node->addr.addr);
634             CoAPMessage_destory(&message);
635         }
636     }
637 }
638 
639 #endif
640