1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "ctype.h"
12 #include "iotx_coap_internal.h"
13 #include "CoAPPlatform.h"
14 #include "CoAPInternal.h"
15 #include "CoAPNetwork.h"
16 #include "CoAPExport.h"
17 #include "CoAPObserve.h"
18 
19 #define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
20 #define COAPS_DEFAULT_PORT \
21     5684 /* CoAP default UDP port for secure transmission */
22 #define COAP_DEFAULT_SENDLIST_MAXCOUNT 8
23 #define COAP_DEFAULT_RES_MAXCOUNT      8
24 #define COAP_DEFAULT_OBS_MAXCOUNT      8
25 
26 #define COAP_DEFAULT_SCHEME            "coap" /* the default scheme for CoAP URIs */
27 #define COAP_DEFAULT_HOST_LEN          128
28 #define COAP_DEFAULT_WAIT_TIME_MS      2000
29 
CoAPContext_create(CoAPInitParam * param)30 CoAPContext *CoAPContext_create(CoAPInitParam *param)
31 {
32     CoAPIntContext *p_ctx = NULL;
33     NetworkInit network_param;
34 
35     memset(&network_param, 0x00, sizeof(NetworkInit));
36     p_ctx = coap_malloc(sizeof(CoAPIntContext));
37     if (NULL == p_ctx) {
38         COAP_ERR("malloc for coap context failed");
39         goto err;
40     }
41     COAP_DEBUG("Send List Max-Count:      %d", param->send_maxcount);
42     COAP_DEBUG("Observe Server Max-Count: %d", param->obs_maxcount);
43     COAP_DEBUG("Observe Client Max-Count: %d", param->obs_maxcount);
44     COAP_DEBUG("Resource Max-Count:       %d", param->res_maxcount);
45     COAP_DEBUG("MultiCast Address:        %s:%d", param->group, param->port);
46     COAP_DEBUG("Send/Recv Wait time:      %dms", param->waittime);
47 
48     memset(p_ctx, 0, sizeof(CoAPIntContext));
49     p_ctx->message_id = 1;
50     p_ctx->notifier = param->notifier;
51     p_ctx->appdata = param->appdata;
52 
53 #ifdef USE_SENDBUFF
54     p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
55     if (NULL == p_ctx->sendbuf) {
56         COAP_ERR("not enough memory");
57         goto err;
58     }
59     memset(p_ctx->sendbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
60 #endif
61 
62     p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
63     if (NULL == p_ctx->recvbuf) {
64         COAP_ERR("not enough memory");
65         goto err;
66     }
67     memset(p_ctx->recvbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
68 
69     if (0 == param->waittime) {
70         p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS;
71     } else {
72         p_ctx->waittime = param->waittime;
73     }
74     p_ctx->mutex = HAL_MutexCreate();
75     if (NULL == p_ctx->mutex) {
76         COAP_ERR("Mutex Create failed");
77         goto err;
78     }
79 
80     /*Init message send list mutex*/
81     p_ctx->sendlist.list_mutex = HAL_MutexCreate();
82     HAL_MutexLock(p_ctx->sendlist.list_mutex);
83     /*CoAP message send list*/
84     INIT_LIST_HEAD(&p_ctx->sendlist.list);
85     p_ctx->sendlist.count = 0;
86     HAL_MutexUnlock(p_ctx->sendlist.list_mutex);
87 
88     if (0 != param->send_maxcount) {
89         p_ctx->sendlist.maxcount = param->send_maxcount;
90     } else {
91         p_ctx->sendlist.maxcount = COAP_DEFAULT_SENDLIST_MAXCOUNT;
92     }
93 
94     if (0 == param->res_maxcount) {
95         param->res_maxcount = COAP_DEFAULT_RES_MAXCOUNT;
96     }
97     CoAPResource_init(p_ctx, param->res_maxcount);
98 
99 #ifndef COAP_OBSERVE_SERVER_DISABLE
100     if (0 == param->obs_maxcount) {
101         param->obs_maxcount = COAP_DEFAULT_OBS_MAXCOUNT;
102     }
103     CoAPObsServer_init(p_ctx, param->obs_maxcount);
104 #endif
105 
106 #ifndef COAP_OBSERVE_CLIENT_DISABLE
107     if (0 == param->obs_maxcount) {
108         param->obs_maxcount = COAP_DEFAULT_OBS_MAXCOUNT;
109     }
110     CoAPObsClient_init(p_ctx, param->obs_maxcount);
111 #endif
112 
113 #ifdef COAP_DTLS_SUPPORT
114     network_param.type = COAP_NETWORK_DTLS;
115     network_param.port = COAPS_DEFAULT_PORT;
116 #else
117     network_param.type = COAP_NETWORK_NOSEC;
118     network_param.port = param->port;
119     network_param.group = param->group;
120 #endif
121 
122     /*CoAP network init*/
123     p_ctx->p_network = CoAPNetwork_init(&network_param);
124 
125     if (NULL == p_ctx->p_network) {
126         COAP_ERR("CoAP Network init failed, exit");
127         goto err;
128     }
129 
130     return p_ctx;
131 err:
132     if (NULL == p_ctx) {
133         return p_ctx;
134     }
135 
136     if (NULL != p_ctx->recvbuf) {
137         coap_free(p_ctx->recvbuf);
138         p_ctx->recvbuf = NULL;
139     }
140 
141 #ifdef USE_SENDBUFF
142     if (NULL != p_ctx->sendbuf) {
143         coap_free(p_ctx->sendbuf);
144         p_ctx->sendbuf = NULL;
145     }
146 #endif
147 
148 #ifndef COAP_OBSERVE_SERVER_DISABLE
149     CoAPObsServer_deinit(p_ctx);
150 #endif
151 
152 #ifndef COAP_OBSERVE_CLIENT_DISABLE
153     CoAPObsClient_deinit(p_ctx);
154 #endif
155 
156     CoAPResource_deinit(p_ctx);
157 
158     if (NULL != p_ctx->sendlist.list_mutex) {
159         HAL_MutexDestroy(p_ctx->sendlist.list_mutex);
160         p_ctx->sendlist.list_mutex = NULL;
161     }
162 
163     if (NULL != p_ctx->mutex) {
164         HAL_MutexDestroy(p_ctx->mutex);
165         p_ctx->mutex = NULL;
166     }
167 
168     coap_free(p_ctx);
169     p_ctx = NULL;
170 
171     /* TODO: release the resource */
172     return (CoAPContext *)p_ctx;
173 }
174 
CoAPContextAppdata_get(CoAPContext * context)175 void *CoAPContextAppdata_get(CoAPContext *context)
176 {
177     CoAPIntContext *p_ctx = (CoAPIntContext *)context;
178     if (NULL == p_ctx) {
179         return NULL;
180     }
181 
182     return (void *)p_ctx->appdata;
183 }
184 
CoAPContext_free(CoAPContext * context)185 void CoAPContext_free(CoAPContext *context)
186 {
187     CoAPIntContext *p_ctx = NULL;
188     CoAPSendNode *cur = NULL, *next = NULL;
189     if (NULL == context) {
190         return;
191     }
192 
193     p_ctx = (CoAPIntContext *)context;
194 
195     CoAPNetwork_deinit(p_ctx->p_network);
196     COAP_DEBUG("CoAP Network Deinit");
197 
198     HAL_MutexLock(p_ctx->sendlist.list_mutex);
199     list_for_each_entry_safe(cur, next, &p_ctx->sendlist.list, sendlist,
200                              CoAPSendNode)
201     {
202         if (NULL != cur) {
203             if (NULL != cur->message) {
204                 coap_free(cur->message);
205                 cur->message = NULL;
206             }
207             coap_free(cur);
208             cur = NULL;
209         }
210     }
211     INIT_LIST_HEAD(&p_ctx->sendlist.list);
212     HAL_MutexUnlock(p_ctx->sendlist.list_mutex);
213     HAL_MutexDestroy(p_ctx->sendlist.list_mutex);
214     p_ctx->sendlist.list_mutex = NULL;
215     HAL_MutexDestroy(p_ctx->mutex);
216     p_ctx->mutex = NULL;
217     COAP_DEBUG("Release Send List and Memory");
218 
219 #ifndef COAP_OBSERVE_SERVER_DISABLE
220     CoAPObsServer_deinit(p_ctx);
221     COAP_DEBUG("CoAP Observe Server Deinit");
222 #endif
223 
224 #ifndef COAP_OBSERVE_CLIENT_DISABLE
225     CoAPObsClient_deinit(p_ctx);
226     COAP_DEBUG("CoAP Observe Client Deinit");
227 #endif
228 
229     CoAPResource_deinit(p_ctx);
230     COAP_DEBUG("CoAP Resource unregister");
231 
232     if (NULL != p_ctx->recvbuf) {
233         coap_free(p_ctx->recvbuf);
234         p_ctx->recvbuf = NULL;
235         COAP_DEBUG("Release The Recv Memory");
236     }
237 #ifdef USE_SENDBUFF
238     if (NULL != p_ctx->sendbuf) {
239         coap_free(p_ctx->sendbuf);
240         p_ctx->sendbuf = NULL;
241         COAP_DEBUG("Release The Send Memory");
242     }
243 #endif
244 
245     if (NULL != p_ctx) {
246         coap_free(p_ctx);
247         p_ctx = NULL;
248         COAP_DEBUG("Release The CoAP Context");
249     }
250 }
251