1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "iotx_coap_internal.h"
10 #include "ctype.h"
11 #include "Cloud_CoAPPlatform.h"
12 #include "Cloud_CoAPNetwork.h"
13 #include "Cloud_CoAPExport.h"
14
15 #define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
16 #define COAPS_DEFAULT_PORT \
17 5684 /* CoAP default UDP port for secure transmission */
18
19 #define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
20 #define COAP_DEFAULT_HOST_LEN 128
21 #define COAP_DEFAULT_WAIT_TIME_MS 2000
22
Cloud_CoAPUri_parse(char * p_uri,coap_endpoint_type * p_endpoint_type,char host[COAP_DEFAULT_HOST_LEN],unsigned short * port)23 unsigned int Cloud_CoAPUri_parse(char *p_uri,
24 coap_endpoint_type *p_endpoint_type,
25 char host[COAP_DEFAULT_HOST_LEN],
26 unsigned short *port)
27 {
28 int len = 0;
29 char *p = NULL, *q = NULL;
30 if (NULL == p_uri || NULL == p_endpoint_type) {
31 return COAP_ERROR_INVALID_PARAM;
32 }
33
34 COAP_DEBUG("The uri is %s", p_uri);
35 len = strlen(p_uri);
36 p = p_uri;
37 q = (char *)COAP_DEFAULT_SCHEME;
38 while (len && *q && tolower(*p) == *q) {
39 ++p;
40 ++q;
41 --len;
42 }
43
44 if (*q) {
45 return COAP_ERROR_INVALID_URI;
46 }
47 if (tolower(*p) == 's') {
48 ++p;
49 --len;
50 *p_endpoint_type = COAP_ENDPOINT_DTLS;
51 *port = COAPS_DEFAULT_PORT;
52 } else if (*p == '-') {
53 ++p;
54 --len;
55 q = (char *)"psk";
56 while (len && *q && tolower(*p) == *q) {
57 ++p;
58 ++q;
59 --len;
60 }
61 if (*q) {
62 return COAP_ERROR_INVALID_URI;
63 }
64 *p_endpoint_type = COAP_ENDPOINT_PSK;
65 *port = COAP_DEFAULT_PORT;
66 } else {
67 *p_endpoint_type = COAP_ENDPOINT_NOSEC;
68 *port = COAP_DEFAULT_PORT;
69 }
70 COAP_DEBUG("The endpoint type is: %d", *p_endpoint_type);
71
72 q = (char *)"://";
73 while (len && *q && tolower(*p) == *q) {
74 ++p;
75 ++q;
76 --len;
77 }
78
79 if (*q) {
80 return COAP_ERROR_INVALID_URI;
81 }
82
83 q = p;
84 while (len && *q != ':') {
85 ++q;
86 --len;
87 }
88 if (p == q) {
89 return COAP_ERROR_INVALID_URI;
90 }
91
92 if (COAP_DEFAULT_HOST_LEN - 1 < (q - p)) {
93 return COAP_ERROR_INVALID_URI;
94 } else {
95 memset(host, 0x00, COAP_DEFAULT_HOST_LEN);
96 strncpy(host, p, q - p);
97 }
98 COAP_DEBUG("The host name is: %s", host);
99 if (len && *q == ':') {
100 p = ++q;
101 --len;
102
103 while (len && isdigit(*q)) {
104 ++q;
105 --len;
106 }
107
108 if (p < q) {
109 int uri_port = 0;
110
111 while (p < q) {
112 uri_port = uri_port * 10 + (*p++ - '0');
113 }
114
115 if (uri_port > 65535) {
116 return COAP_ERROR_INVALID_URI;
117 }
118 *port = uri_port;
119 }
120 }
121 COAP_DEBUG("The port is: %d", *port);
122
123 return COAP_SUCCESS;
124 }
125
Cloud_CoAPContext_create(Cloud_CoAPInitParam * param)126 Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param)
127 {
128 unsigned int ret = COAP_SUCCESS;
129 Cloud_CoAPContext *p_ctx = NULL;
130 coap_network_init_t network_param;
131 char host[COAP_DEFAULT_HOST_LEN] = { 0 };
132
133 memset(&network_param, 0x00, sizeof(coap_network_init_t));
134 p_ctx = coap_malloc(sizeof(Cloud_CoAPContext));
135 if (NULL == p_ctx) {
136 COAP_ERR("malloc for coap context failed");
137 goto err;
138 }
139
140 memset(p_ctx, 0, sizeof(Cloud_CoAPContext));
141 p_ctx->message_id = 1;
142 p_ctx->notifier = param->notifier;
143 p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
144 if (NULL == p_ctx->sendbuf) {
145 COAP_ERR("not enough memory");
146 goto err;
147 }
148
149 p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
150 if (NULL == p_ctx->recvbuf) {
151 COAP_ERR("not enough memory");
152 goto err;
153 }
154
155 if (0 == param->waittime) {
156 p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS;
157 } else {
158 p_ctx->waittime = param->waittime;
159 }
160
161 /*CoAP message send list*/
162 INIT_LIST_HEAD(&p_ctx->list.sendlist);
163 p_ctx->list.count = 0;
164 p_ctx->list.maxcount = param->maxcount;
165
166 /*set the endpoint type by uri schema*/
167 if (NULL != param->url) {
168 ret = Cloud_CoAPUri_parse(param->url, &network_param.ep_type, host,
169 &network_param.port);
170 }
171
172 if (COAP_SUCCESS != ret) {
173 goto err;
174 }
175
176 #ifdef COAP_DTLS_SUPPORT
177 if (COAP_ENDPOINT_DTLS == network_param.ep_type) {
178 extern const char *iotx_ca_crt;
179 network_param.p_ca_cert_pem = (unsigned char *)iotx_ca_crt;
180 }
181 #endif
182 if (COAP_ENDPOINT_NOSEC == network_param.ep_type ||
183 COAP_ENDPOINT_PSK == network_param.ep_type) {
184 network_param.p_ca_cert_pem = NULL;
185 }
186 network_param.p_host = host;
187
188 /*CoAP network init*/
189 ret = Cloud_CoAPNetwork_init(&network_param, &p_ctx->network);
190
191 if (COAP_SUCCESS != ret) {
192 goto err;
193 }
194
195 return p_ctx;
196 err:
197 if (NULL == p_ctx) {
198 return p_ctx;
199 }
200
201 if (NULL != p_ctx->recvbuf) {
202 coap_free(p_ctx->recvbuf);
203 p_ctx->recvbuf = NULL;
204 }
205
206 if (NULL != p_ctx->sendbuf) {
207 coap_free(p_ctx->sendbuf);
208 p_ctx->sendbuf = NULL;
209 }
210
211 coap_free(p_ctx);
212 p_ctx = NULL;
213
214 return p_ctx;
215 }
216
Cloud_CoAPContext_free(Cloud_CoAPContext * p_ctx)217 void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx)
218 {
219 Cloud_CoAPSendNode *cur, *next;
220
221 if (NULL == p_ctx) {
222 return;
223 }
224
225 Cloud_CoAPNetwork_deinit(&p_ctx->network);
226
227 list_for_each_entry_safe(cur, next, &p_ctx->list.sendlist, sendlist,
228 Cloud_CoAPSendNode)
229 {
230 if (NULL != cur) {
231 if (NULL != cur->message) {
232 coap_free(cur->message);
233 cur->message = NULL;
234 }
235 coap_free(cur);
236 cur = NULL;
237 }
238 }
239
240 if (NULL != p_ctx->recvbuf) {
241 coap_free(p_ctx->recvbuf);
242 p_ctx->recvbuf = NULL;
243 }
244
245 if (NULL != p_ctx->sendbuf) {
246 coap_free(p_ctx->sendbuf);
247 p_ctx->sendbuf = NULL;
248 }
249
250 if (NULL != p_ctx) {
251 coap_free(p_ctx);
252 p_ctx = NULL;
253 }
254 }
255