1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 
8 #include "CoAPSerialize.h"
9 #include "iotx_coap_internal.h"
10 
CoAPSerialize_Header(CoAPMessage * msg,unsigned char * buf,unsigned short buflen)11 int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf,
12                          unsigned short buflen)
13 {
14     if (4 > buflen) {
15         return 0;
16     }
17     buf[0] =
18         (((msg->header.version & 0x3) << 6) | ((msg->header.type & 0x3) << 4)) |
19         (msg->header.tokenlen & 0x0F);
20 
21     buf[1] = msg->header.code;
22     buf[2] = (msg->header.msgid & 0xFF00) >> 8;
23     buf[3] = (msg->header.msgid & 0x00FF);
24 
25     return 4;
26 }
27 
CoAPSerialize_Token(CoAPMessage * msg,unsigned char * buf,unsigned short buflen)28 int CoAPSerialize_Token(CoAPMessage *msg, unsigned char *buf,
29                         unsigned short buflen)
30 {
31     int i = 0;
32 
33     if (buflen < msg->header.tokenlen) {
34         return 0;
35     }
36     for (i = 0; i < msg->header.tokenlen; i++) {
37         buf[i] = msg->token[i];
38     }
39     return msg->header.tokenlen;
40 }
41 
CoAPSerialize_Option(CoAPMsgOption * option,unsigned char * buf)42 static unsigned short CoAPSerialize_Option(CoAPMsgOption *option,
43                                            unsigned char *buf)
44 {
45     unsigned char *ptr = buf;
46 
47     if (269 <= option->num) {
48         *ptr = ((14 & 0x0F) << 4);
49     } else if (13 <= option->num) {
50         *ptr = ((13 & 0x0F) << 4);
51     } else {
52         *ptr = option->num << 4;
53     }
54 
55     if (269 <= option->len) {
56         *ptr |= (14 & 0x0F);
57     } else if (13 <= option->len) {
58         *ptr |= (13 & 0x0F);
59     } else {
60         *ptr |= (option->len & 0x0F);
61     }
62     ptr++;
63 
64     if (269 <= option->num) {
65         *ptr = (unsigned char)(((option->num - 269) & 0xFF00) >> 8);
66         *(ptr + 1) = (unsigned char)(((option->num - 269) & 0x00FF));
67         ptr += 2;
68     } else if (13 <= option->num) {
69         *ptr = (unsigned char)(option->num - 13);
70         ptr++;
71     }
72 
73     if (269 <= option->len) {
74         *ptr = (unsigned char)(((option->len - 269) & 0xFF00) >> 8);
75         *(ptr + 1) = (unsigned char)(((option->len - 269) & 0x00FF));
76         ptr += 2;
77     } else if (13 <= option->len) {
78         *ptr = (unsigned char)(option->len - 13);
79         ptr++;
80     }
81 
82     memcpy(ptr, option->val, option->len);
83     ptr += option->len;
84 
85     return (int)(ptr - buf);
86 }
87 
CoAPSerialize_Options(CoAPMessage * msg,unsigned char * buf,unsigned short buflen)88 unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char *buf,
89                                      unsigned short buflen)
90 {
91     int i = 0;
92     unsigned short count = 0;
93 
94     for (i = 0; i < msg->optcount; i++) {
95         unsigned short len = 0;
96         len = CoAPSerialize_Option(&msg->options[i], &buf[count]);
97         if (0 < len) {
98             count += len;
99         } else {
100             return 0;
101         }
102     }
103 
104     return count;
105 }
106 
CoAPSerialize_OptionLen(CoAPMsgOption * option)107 static unsigned short CoAPSerialize_OptionLen(CoAPMsgOption *option)
108 {
109     unsigned short len = 1;
110 
111     if (269 <= option->num) {
112         len += 2;
113     } else if (13 <= option->num) {
114         len += 1;
115     } else {
116     }
117 
118     if (269 <= option->len) {
119         len += 2;
120     } else if (13 <= option->len) {
121         len += 1;
122     } else {
123     }
124 
125     len += option->len;
126     return len;
127 }
128 
CoAPSerialize_OptionsLen(CoAPMessage * msg)129 unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg)
130 {
131     int i = 0;
132     unsigned short count = 0;
133 
134     for (i = 0; i < msg->optcount; i++) {
135         unsigned short len = 0;
136         len = CoAPSerialize_OptionLen(&msg->options[i]);
137         if (0 < len) {
138             count += len;
139         } else {
140             return 0;
141         }
142     }
143 
144     return count;
145 }
146 
CoAPSerialize_Payload(CoAPMessage * msg,unsigned char * buf,int buflen)147 int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
148 {
149     if (msg->payloadlen + 1 > buflen) {
150         return 0;
151     }
152     if (msg->payloadlen > 0 && NULL != msg->payload) {
153         *buf = 0xFF;
154         buf++;
155         memcpy(buf, msg->payload, msg->payloadlen);
156         return msg->payloadlen + 1;
157     } else {
158         return 0;
159     }
160 }
161 
CoAPSerialize_MessageLength(CoAPMessage * msg)162 unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg)
163 {
164     unsigned short msglen = 4;
165 
166     msglen += msg->header.tokenlen;
167     msglen += CoAPSerialize_OptionsLen(msg);
168 
169     if (0 < msg->payloadlen) {
170         msglen += msg->payloadlen;
171         msglen += 1; /*CoAP payload marker*/
172     }
173 
174     return msglen;
175 }
176 
CoAPSerialize_Message(CoAPMessage * msg,unsigned char * buf,unsigned short buflen)177 int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf,
178                           unsigned short buflen)
179 {
180     unsigned char *ptr = buf;
181     unsigned short count = 0;
182     unsigned short remlen = buflen;
183 
184     if (NULL == buf || NULL == msg) {
185         return COAP_ERROR_INVALID_PARAM;
186     }
187 
188     count = CoAPSerialize_Header(msg, ptr, remlen);
189     ptr += count;
190     remlen -= count;
191 
192     count = CoAPSerialize_Token(msg, ptr, remlen);
193     ptr += count;
194     remlen -= count;
195 
196     count = CoAPSerialize_Options(msg, ptr, remlen);
197     ptr += count;
198     remlen -= count;
199 
200     count = CoAPSerialize_Payload(msg, ptr, remlen);
201     ptr += count;
202     remlen -= count;
203 
204     return buflen - remlen;
205 }
206