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