1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5
6
7
8 #include <string.h>
9 #include "CoAPExport.h"
10 #include "CoAPResource.h"
11 #include "CoAPPlatform.h"
12 #include "CoAPInternal.h"
13 #include "iotx_coap_internal.h"
14
15 #define COAP_PATH_DEFAULT_SUM_LEN (5)
16
CoAPPathMD5_sum(const char * path,int len,char outbuf[],int outlen)17 int CoAPPathMD5_sum(const char *path, int len, char outbuf[], int outlen)
18 {
19 unsigned char md5[16] = { 0 };
20 if (!path || !len || !outbuf || !outlen) {
21 return -1;
22 }
23
24 utils_md5((unsigned char *)path, (size_t)len, md5);
25 memcpy(outbuf, md5, outlen > 16 ? 16 : outlen);
26 return 0;
27 }
28
CoAPResource_init(CoAPContext * context,int res_maxcount)29 int CoAPResource_init(CoAPContext *context, int res_maxcount)
30 {
31 CoAPIntContext *ctx = (CoAPIntContext *)context;
32
33 ctx->resource.list_mutex = HAL_MutexCreate();
34
35 HAL_MutexLock(ctx->resource.list_mutex);
36 INIT_LIST_HEAD(&ctx->resource.list);
37 ctx->resource.count = 0;
38 ctx->resource.maxcount = res_maxcount;
39 HAL_MutexUnlock(ctx->resource.list_mutex);
40
41 return COAP_SUCCESS;
42 }
43
CoAPResource_deinit(CoAPContext * context)44 int CoAPResource_deinit(CoAPContext *context)
45 {
46 CoAPResource *node = NULL, *next = NULL;
47 CoAPIntContext *ctx = (CoAPIntContext *)context;
48 char tmpbuf[2 * COAP_MAX_PATH_CHECKSUM_LEN + 1] = { 0 };
49
50 HAL_MutexLock(ctx->resource.list_mutex);
51 list_for_each_entry_safe(node, next, &ctx->resource.list, reslist,
52 CoAPResource)
53 {
54 if (node->path_type == PATH_FILTER && node->filter_path) {
55 coap_free(node->filter_path);
56 }
57 list_del_init(&node->reslist);
58 infra_hex2str((unsigned char *)node->path, COAP_MAX_PATH_CHECKSUM_LEN,
59 tmpbuf);
60 COAP_DEBUG("Release the resource %s", tmpbuf);
61 coap_free(node);
62 }
63 ctx->resource.count = 0;
64 ctx->resource.maxcount = 0;
65 HAL_MutexUnlock(ctx->resource.list_mutex);
66
67 HAL_MutexDestroy(ctx->resource.list_mutex);
68 ctx->resource.list_mutex = NULL;
69 return COAP_SUCCESS;
70 }
71
CoAPResource_create(const char * path,path_type_t path_type,unsigned short permission,unsigned int ctype,unsigned int maxage,CoAPRecvMsgHandler callback)72 CoAPResource *CoAPResource_create(const char *path, path_type_t path_type,
73 unsigned short permission, unsigned int ctype,
74 unsigned int maxage,
75 CoAPRecvMsgHandler callback)
76 {
77 CoAPResource *resource = NULL;
78
79 if (NULL == path) {
80 return NULL;
81 }
82
83 if (strlen(path) >= COAP_MSG_MAX_PATH_LEN) {
84 return NULL;
85 }
86
87 resource = coap_malloc(sizeof(CoAPResource));
88 if (NULL == resource) {
89 return NULL;
90 }
91
92 memset(resource, 0x00, sizeof(CoAPResource));
93 if (path_type == PATH_NORMAL) {
94 resource->path_type = PATH_NORMAL;
95 CoAPPathMD5_sum(path, strlen(path), resource->path,
96 COAP_PATH_DEFAULT_SUM_LEN);
97 } else {
98 int len = strlen(path) + 1;
99 resource->filter_path = coap_malloc(len);
100 if (NULL == resource->filter_path) {
101 coap_free(resource);
102 return NULL;
103 }
104 resource->path_type = PATH_FILTER;
105 memset(resource->filter_path, 0, len);
106 strncpy(resource->filter_path, path, strlen(path));
107 }
108 resource->callback = callback;
109 resource->ctype = ctype;
110 resource->maxage = maxage;
111 resource->permission = permission;
112
113 return resource;
114 }
115
CoAPResource_register(CoAPContext * context,const char * path,unsigned short permission,unsigned int ctype,unsigned int maxage,CoAPRecvMsgHandler callback)116 int CoAPResource_register(CoAPContext *context, const char *path,
117 unsigned short permission, unsigned int ctype,
118 unsigned int maxage, CoAPRecvMsgHandler callback)
119 {
120 int exist = 0;
121 char path_calc[COAP_PATH_DEFAULT_SUM_LEN] = { 0 };
122 CoAPResource *node = NULL, *newnode = NULL;
123 CoAPIntContext *ctx = (CoAPIntContext *)context;
124 path_type_t type = PATH_NORMAL;
125
126 if (context == NULL) {
127 return FAIL_RETURN;
128 }
129
130 HAL_MutexLock(ctx->resource.list_mutex);
131 if (ctx->resource.count >= ctx->resource.maxcount) {
132 HAL_MutexUnlock(ctx->resource.list_mutex);
133 COAP_INFO("The resource count exceeds limit, cur %d, max %d",
134 ctx->resource.count, ctx->resource.maxcount);
135 return COAP_ERROR_DATA_SIZE;
136 }
137
138 if (strstr(path, "/#") != NULL) {
139 type = PATH_FILTER;
140 } else {
141 CoAPPathMD5_sum(path, strlen(path), path_calc,
142 COAP_PATH_DEFAULT_SUM_LEN);
143 }
144
145 list_for_each_entry(node, &ctx->resource.list, reslist, CoAPResource)
146 {
147 if (type == PATH_NORMAL && node->path_type == PATH_NORMAL) {
148 if (0 == memcmp(path_calc, node->path, COAP_PATH_DEFAULT_SUM_LEN)) {
149 /*Alread exist, re-write it*/
150 COAP_INFO("CoAPResource_register:Alread exist");
151 exist = 1;
152 node->callback = callback;
153 node->ctype = ctype;
154 node->maxage = maxage;
155 node->permission = permission;
156 COAP_INFO("The resource %s already exist, re-write it", path);
157 break;
158 }
159 } else if (type == PATH_FILTER && node->path_type == PATH_FILTER) {
160 if (0 == strncmp((char *)path, node->filter_path, strlen(path))) {
161 /*Alread exist, re-write it*/
162 COAP_INFO("CoAPResource_register:Alread exist");
163 exist = 1;
164 node->callback = callback;
165 node->ctype = ctype;
166 node->maxage = maxage;
167 node->permission = permission;
168 COAP_INFO("The resource %s already exist, re-write it", path);
169 break;
170 }
171 }
172 }
173
174 if (0 == exist) {
175 newnode = CoAPResource_create(path, type, permission, ctype, maxage,
176 callback);
177 if (NULL != newnode) {
178 COAP_DEBUG("CoAPResource_register, context:%p, new node", ctx);
179 list_add_tail(&newnode->reslist, &ctx->resource.list);
180 ctx->resource.count++;
181 COAP_DEBUG("Register new resource %s success, count: %d", path,
182 ctx->resource.count);
183 } else {
184 COAP_ERR("New resource create failed");
185 }
186 }
187
188 HAL_MutexUnlock(ctx->resource.list_mutex);
189
190 return COAP_SUCCESS;
191 }
192
CoAPResource_unregister(CoAPContext * context,const char * path)193 int CoAPResource_unregister(CoAPContext *context, const char *path)
194 {
195 COAP_DEBUG("This feature isn't supported");
196 return COAP_ERROR_UNSUPPORTED;
197 }
198
CoAPResource_topicFilterMatch(const char * filter,const char * topic)199 int CoAPResource_topicFilterMatch(const char *filter, const char *topic)
200 {
201 if (filter == NULL || topic == NULL) {
202 return -1;
203 }
204 if (strncmp(filter, topic, strlen(filter) - 1) == 0) {
205 if (strlen(topic) > strlen(filter) - 1) {
206 const char *more = topic + (strlen(filter) - 1);
207 if (strstr(more, "/") == NULL) {
208 return 0;
209 }
210 }
211 }
212 return -1;
213 }
214
CoAPResourceByPath_get(CoAPContext * context,const char * path)215 CoAPResource *CoAPResourceByPath_get(CoAPContext *context, const char *path)
216 {
217 char path_calc[COAP_PATH_DEFAULT_SUM_LEN] = { 0 };
218 CoAPResource *node = NULL;
219 CoAPIntContext *ctx = (CoAPIntContext *)context;
220
221 if (NULL == context || NULL == path) {
222 COAP_INFO("%s\n", "NULL == context || NULL == path");
223 return NULL;
224 }
225 COAP_FLOW("CoAPResourceByPath_get, context:%p\n", ctx);
226
227 CoAPPathMD5_sum(path, strlen(path), path_calc, COAP_PATH_DEFAULT_SUM_LEN);
228
229 HAL_MutexLock(ctx->resource.list_mutex);
230 list_for_each_entry(node, &ctx->resource.list, reslist, CoAPResource)
231 {
232 if (0 == memcmp(path_calc, node->path, COAP_PATH_DEFAULT_SUM_LEN)) {
233 HAL_MutexUnlock(ctx->resource.list_mutex);
234 COAP_DEBUG("Found the resource: %s", path);
235 return node;
236 }
237 if (node->path_type == PATH_FILTER && strlen(node->filter_path) > 0) {
238 if (CoAPResource_topicFilterMatch(node->filter_path, path) == 0) {
239 HAL_MutexUnlock(ctx->resource.list_mutex);
240 COAP_DEBUG("Found the resource: %s", path);
241 return node;
242 }
243 }
244 }
245 HAL_MutexUnlock(ctx->resource.list_mutex);
246
247 return NULL;
248 }
249