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