1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include "iotx_coap_internal.h"
7 #include "CoAPSerialize.h"
8 #include "CoAPDeserialize.h"
9
10 #include "CoAPPlatform.h"
11
12 #define COAPAckMsg(header) \
13 ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) && \
14 (header.type == COAP_MESSAGE_TYPE_ACK))
15
16 #define CoAPRespMsg(header) ((header.code >= 0x40) && (header.code < 0xc0))
17
18 #define CoAPPingMsg(header) \
19 ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) && \
20 (header.type == COAP_MESSAGE_TYPE_CON))
21
22 #define CoAPResetMsg(header) (header.type == COAP_MESSAGE_TYPE_RST)
23
24 #define CoAPCONRespMsg(header) \
25 ((header.code == COAP_MSG_CODE_205_CONTENT) && \
26 (header.type == COAP_MESSAGE_TYPE_CON))
27
28 #define CoAPReqMsg(header) ((1 <= header.code) && (32 > header.code))
29
30 #define COAP_CUR_VERSION 1
31 #define COAP_WAIT_TIME_MS 2000
32 #define COAP_MAX_MESSAGE_ID 65535
33 #define COAP_MAX_RETRY_COUNT 4
34 #define COAP_ACK_TIMEOUT 2
35 #define COAP_ACK_RANDOM_FACTOR 1
36 #define COAP_MAX_TRANSMISSION_SPAN 10
37
CoAPStrOption_add(CoAPMessage * message,unsigned short optnum,unsigned char * data,unsigned short datalen)38 int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
39 unsigned char *data, unsigned short datalen)
40 {
41 unsigned char *ptr = NULL;
42 if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
43 return COAP_ERROR_INVALID_PARAM;
44 }
45
46 message->options[message->optcount].num = optnum - message->optdelta;
47 message->options[message->optcount].len = datalen;
48 ptr = (unsigned char *)coap_malloc(datalen);
49 if (NULL == ptr) {
50 return COAP_ERROR_MALLOC;
51 }
52 memset(ptr, 0x00, datalen);
53 memcpy(ptr, data, datalen);
54 message->options[message->optcount].val = ptr;
55 message->optdelta = optnum;
56 message->optcount++;
57
58 return COAP_SUCCESS;
59 }
60
CoAPStrOption_get(CoAPMessage * message,unsigned short optnum,unsigned char * data,unsigned short * datalen)61 int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum,
62 unsigned char *data, unsigned short *datalen)
63 {
64 unsigned char index = 0;
65
66 for (index = 0; index < message->optcount; index++) {
67 if (message->options[index].num == optnum) {
68 if (*datalen >= message->options[index].len) {
69 memcpy(data, message->options[index].val,
70 message->options[index].len);
71 *datalen = message->options[index].len;
72 return COAP_SUCCESS;
73 } else {
74 return COAP_ERROR_INVALID_LENGTH;
75 }
76 }
77 }
78
79 return COAP_ERROR_NOT_FOUND;
80 }
81
CoAPUintOption_add(CoAPMessage * message,unsigned short optnum,unsigned int data)82 int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum,
83 unsigned int data)
84 {
85 unsigned char *ptr = NULL;
86 if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
87 return COAP_ERROR_INVALID_PARAM;
88 }
89 message->options[message->optcount].num = optnum - message->optdelta;
90
91 if (0 == data) {
92 message->options[message->optcount].len = 0;
93 } else if (255 >= data) {
94 message->options[message->optcount].len = 1;
95 ptr = (unsigned char *)coap_malloc(1);
96 if (NULL != ptr) {
97 *ptr = (unsigned char)data;
98 }
99 } else if (65535 >= data) {
100 message->options[message->optcount].len = 2;
101 ptr = (unsigned char *)coap_malloc(2);
102 if (NULL != ptr) {
103 *ptr = (unsigned char)((data & 0xFF00) >> 8);
104 *(ptr + 1) = (unsigned char)(data & 0x00FF);
105 }
106 } else {
107 message->options[message->optcount].len = 4;
108 ptr = (unsigned char *)coap_malloc(4);
109 if (NULL != ptr) {
110 *ptr = (unsigned char)((data & 0xFF000000) >> 24);
111 *(ptr + 1) = (unsigned char)((data & 0x00FF0000) >> 16);
112 *(ptr + 2) = (unsigned char)((data & 0x0000FF00) >> 8);
113 *(ptr + 3) = (unsigned char)(data & 0x000000FF);
114 }
115 }
116 message->options[message->optcount].val = ptr;
117 message->optdelta = optnum;
118 message->optcount += 1;
119
120 return COAP_SUCCESS;
121 }
122
CoAPUintOption_get(CoAPMessage * message,unsigned short optnum,unsigned int * data)123 int CoAPUintOption_get(CoAPMessage *message, unsigned short optnum,
124 unsigned int *data)
125 {
126 unsigned char index = 0;
127
128 for (index = 0; index < message->optcount; index++) {
129 if (message->options[index].num == optnum) {
130 int byte = 0;
131 switch (message->options[index].len) {
132 case 1:
133 *data |= message->options[index].val[byte++];
134 break;
135 case 2:
136 *data |= (message->options[index].val[byte++] << 8);
137 *data |= message->options[index].val[byte++];
138 break;
139 case 3:
140 *data |= (message->options[index].val[byte++] << 16);
141 *data |= (message->options[index].val[byte++] << 8);
142 *data |= message->options[index].val[byte++];
143 break;
144 case 4:
145 *data |= (message->options[index].val[byte++] << 24);
146 *data |= (message->options[index].val[byte++] << 16);
147 *data |= (message->options[index].val[byte++] << 8);
148 *data |= message->options[index].val[byte++];
149 break;
150 default:
151 *data = 0;
152 break;
153 }
154 return COAP_SUCCESS;
155 }
156 }
157
158 return COAP_ERROR_NOT_FOUND;
159 }
160
CoAPOption_present(CoAPMessage * message,unsigned short option)161 int CoAPOption_present(CoAPMessage *message, unsigned short option)
162 {
163 unsigned char index = 0;
164
165 for (index = 0; index < message->optcount; index++) {
166 if (message->options[index].num == option) {
167 return COAP_SUCCESS;
168 }
169 }
170 return COAP_ERROR_NOT_FOUND;
171 }
172
CoAPMessageId_set(CoAPMessage * message,unsigned short msgid)173 int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid)
174 {
175 if (NULL == message) {
176 return COAP_ERROR_NULL;
177 }
178 message->header.msgid = msgid;
179 return COAP_SUCCESS;
180 }
181
CoAPMessageType_set(CoAPMessage * message,unsigned char type)182 int CoAPMessageType_set(CoAPMessage *message, unsigned char type)
183 {
184 if (NULL == message) {
185 return COAP_ERROR_NULL;
186 }
187 if (COAP_MESSAGE_TYPE_CON != type && COAP_MESSAGE_TYPE_NON != type &&
188 COAP_MESSAGE_TYPE_ACK != type && COAP_MESSAGE_TYPE_RST != type) {
189 return COAP_ERROR_INVALID_PARAM;
190 }
191
192 message->header.type = type;
193 return COAP_SUCCESS;
194 }
195
CoAPMessageCode_set(CoAPMessage * message,CoAPMessageCode code)196 int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code)
197 {
198 if (NULL == message) {
199 return COAP_ERROR_NULL;
200 }
201 message->header.code = code;
202 return COAP_SUCCESS;
203 }
204
CoAPMessageCode_get(CoAPMessage * message,CoAPMessageCode * code)205 int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code)
206 {
207 if (NULL == message || NULL == code) {
208 return COAP_ERROR_NULL;
209 }
210 *code = message->header.code;
211 return COAP_SUCCESS;
212 }
213
CoAPMessageToken_set(CoAPMessage * message,unsigned char * token,unsigned char tokenlen)214 int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
215 unsigned char tokenlen)
216 {
217 if (NULL == message || NULL == token) {
218 return COAP_ERROR_NULL;
219 }
220 if (COAP_MSG_MAX_TOKEN_LEN < tokenlen) {
221 return COAP_ERROR_INVALID_LENGTH;
222 }
223 memcpy(message->token, token, tokenlen);
224 message->header.tokenlen = tokenlen;
225
226 return COAP_SUCCESS;
227 }
228
CoAPMessageUserData_set(CoAPMessage * message,void * userdata)229 int CoAPMessageUserData_set(CoAPMessage *message, void *userdata)
230 {
231 if (NULL == message || NULL == userdata) {
232 return COAP_ERROR_NULL;
233 }
234 message->user = userdata;
235 return COAP_SUCCESS;
236 }
237
CoAPMessageKeep_Set(CoAPMessage * message,int keep)238 int CoAPMessageKeep_Set(CoAPMessage *message, int keep)
239 {
240 if (NULL == message || keep < 0) {
241 return COAP_ERROR_NULL;
242 }
243 message->keep = keep;
244 return COAP_SUCCESS;
245 }
246
CoAPMessagePayload_set(CoAPMessage * message,unsigned char * payload,unsigned short payloadlen)247 int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
248 unsigned short payloadlen)
249 {
250 if (NULL == message || (0 < payloadlen && NULL == payload)) {
251 return COAP_ERROR_NULL;
252 }
253 message->payload = payload;
254 message->payloadlen = payloadlen;
255
256 return COAP_SUCCESS;
257 }
258
CoAPMessage_init(CoAPMessage * message)259 int CoAPMessage_init(CoAPMessage *message)
260 {
261 int count = 0;
262
263 if (NULL == message) {
264 return COAP_ERROR_NULL;
265 }
266 memset(message, 0x00, sizeof(CoAPMessage));
267 message->header.version = COAP_CUR_VERSION;
268 message->header.type = COAP_MESSAGE_TYPE_ACK;
269 message->header.tokenlen = 0;
270 message->header.code = COAP_MSG_CODE_EMPTY_MESSAGE;
271 message->header.msgid = 0;
272 message->payload = NULL;
273 message->payloadlen = 0;
274 message->optcount = 0;
275 message->optdelta = 0;
276 message->handler = NULL;
277 message->keep = 0;
278 for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
279 message->options[count].len = 0;
280 message->options[count].num = 0;
281 message->options[count].val = NULL;
282 }
283
284 return COAP_SUCCESS;
285 }
286
CoAPMessage_destory(CoAPMessage * message)287 int CoAPMessage_destory(CoAPMessage *message)
288 {
289 int count = 0;
290 if (NULL == message) {
291 return COAP_ERROR_NULL;
292 }
293
294 for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
295 if (NULL != message->options[count].val) {
296 coap_free(message->options[count].val);
297 message->options[count].val = NULL;
298 }
299 }
300
301 return COAP_SUCCESS;
302 }
303