SingingCat 0
application
decode.c
1#include <coms/coms.h>
2#include "main-header.h"
3#include <platform-header.h>
4#ifndef CNWDEBUGCOM
5#define CNWDEBUGCOM(a, ...) noop()
6#endif
7//#define CNWDEBUGCOM printf
8
9
10/*
11 * \brief add an encoded arg to com
12 * buf is a pointer to the on-the-wire formatted command (buf[0] == 'b')
13 * bufsize is the total size in bytes of buf
14 * pos is the position at which the argument begins (buf[*pos] == fieldnum).
15 * if result != 0 -> error
16 * pos will contain the position of the next byte after the argument
17 */
18int command_add_encoded_arg_with_pos(struct command *com, byte *buf, int bufsize, int *pos) {
19 if (buf[0] != 'b') {
20 return 13;
21 }
22 if ((*pos) > (bufsize - 3)) {
23 CNWDEBUGCOM("cannot decode out an argument at position %i with bufsize %i\n", *pos, bufsize);
24 return 11;
25 }
26 byte fieldnum = buf[(*pos)];
27 byte fieldtype = buf[(*pos) + 1];
28 byte arraysize = buf[(*pos) + 2];
29 int len = fieldlen(fieldtype, arraysize);
30
31
32 byte *nbuf;
33
34 // find position of new arg:
35 if (com->argctr == 0) {
36 nbuf = (byte *)com->argbuf;
37 } else {
38 int r = get_arg_size_inmem(com, com->argctr - 1); // end of last arg;
39 nbuf = (byte *)get_arg_new(com, com->argctr - 1); // to last arg
40 nbuf = nbuf + r;
41 }
42
43 CNWDEBUGCOM(" Copying bytes from pos %i - %i bytes of argument fieldnum=%i,type=%i, writing to combuf %i\n", *pos, len, fieldnum, fieldtype, (nbuf - (uint8_t *)&com->argbuf));
44 int npos = 0;
45
46 nbuf[npos++] = fieldnum;
47 nbuf[npos++] = fieldtype;
48 int header = 0;
49
50 if (fieldtype & 0x80) {
51 nbuf[npos++] = arraysize;
52 header = 1;
53 }
54 if ((len + (*pos) + 2) > bufsize) {
55 CNWDEBUGCOM("Len: %i, pos: %i, (len+pos+2: %i), bufsize: %i, writing to %i\n", len, *pos, (*pos) + len + 2, bufsize, (nbuf - (uint8_t *)&com->argbuf));
56 return 12;
57 }
58
59 int j;
60
61 for (j = 0; j < len; j++) {
62 nbuf[npos++] = buf[j + (*pos) + 2 + header];
63 }
64 // if array -> add nul terminator
65 if (fieldtype & 0x80) {
66 nbuf[npos++] = 0;
67 *pos = (*pos) + 1;
68 }
69 *pos = (*pos) + len + 2;
70 com->argctr++;
71 return 0;
72}
73
74/************************************** start decoding ******************************/
75
76// 0 == ok
77int get_uint64(byte *buf, int bufsize, int *pos, uint64_t *res) {
78 if (((*pos) + 8) > bufsize) {
79 return 3;
80 }
81 int i;
82 uint64_t r = 0;
83
84 for (i = 0; i < 8; i++) {
85 uint64_t v = ((uint64_t)buf[i + (*pos)]);
86 v = v << ((i) * 8);
87 r = r | v;
88 }
89 *pos = *pos + 8;
90 *res = r;
91 return 0;
92}
93// 0 == ok
94int get_uint32(byte *buf, int bufsize, int *pos, uint32_t *res) {
95 if (((*pos) + 4) > bufsize) {
96 return 4;
97 }
98 int i;
99 uint32_t r = 0;
100
101 for (i = 0; i < 4; i++) {
102 uint32_t v = ((uint32_t)buf[i + (*pos)]);
103 v = v << ((i) * 8);
104 r = r | v;
105 }
106 *pos = *pos + 4;
107 *res = r;
108 return 0;
109}
110// 0 == ok
111int get_uint16(byte *buf, int bufsize, int *pos, uint16_t *res) {
112 if (((*pos) + 2) > bufsize) {
113 return 2;
114 }
115 int i;
116 uint32_t r = 0;
117
118 for (i = 0; i < 2; i++) {
119 uint32_t v = ((uint32_t)buf[i + (*pos)]);
120 v = v << ((i) * 8);
121 r = r | v;
122 }
123 *pos = *pos + 2;
124 *res = r;
125 return 0;
126}
127
128
129// 0 == ok
130int get_uint8(byte *buf, int bufsize, int *pos, uint8_t *res) {
131 if (((*pos)) >= bufsize) {
132 CNWDEBUGCOM("Pos: %i, bufsize: %i\n", *pos, bufsize);
133 return 5;
134 }
135 *res = buf[*pos];
136 *pos = *pos + 1;
137 return 0;
138}
139
140/*
141 * \brief decode buf into com. return 0 - ok, otherwise error. buf must start with '{' and end with '}'
142 */
143int decode(byte *buf, int bufsize, struct command *com) {
144 if (bufsize < 36) {
145 return 1;
146 }
147 if (buf[0] != 'b') {
148 return 2;
149 }
150 CNWDEBUGCOM("-------- Decoding --------\n");
151 uint64_t res;
152 uint32_t res32;
153 uint8_t res8;
154 int pos = 0;
155 int e;
156
157 if ((e = get_uint8(buf, bufsize, &pos, &res8)) != 0) {
158 return e;
159 }
160 if (res8 != 'b') {
161 CNWDEBUGCOM("not a binary encoding 0x%x\n", res8);
162 return 6;
163 }
164 if ((e = get_uint8(buf, bufsize, &pos, &res8)) != 0) {
165 return e;
166 }
167 if (res8 != 1) {
168 CNWDEBUGCOM("Incompatible version 0x%x\n", res8);
169 return 7;
170 }
171
172 pos = pos + 4; // length,checksum
173
174 if ((e = get_uint64(buf, bufsize, &pos, &res)) != 0) {
175 return e;
176 }
177 com->sender = res;
178
179 if ((e = get_uint64(buf, bufsize, &pos, &res)) != 0) {
180 return e;
181 }
182 com->recipient = res;
183
184 if ((e = get_uint64(buf, bufsize, &pos, &res)) != 0) {
185 return e;
186 }
187 com->target = res;
188
189 if ((e = get_uint32(buf, bufsize, &pos, &res32)) != 0) {
190 return e;
191 }
192 com->index = (int)res32;
193 // printf("Res: 0x%x %i, index: 0x%x %i\n",res32,res32,com->index,com->index);
194
195 if ((e = get_uint8(buf, bufsize, &pos, &res8)) != 0) {
196 return e;
197 }
198 com->com = res8;
199
200 if ((e = get_uint8(buf, bufsize, &pos, &res8)) != 0) {
201 return e;
202 }
203 com->flags = res8;
204
205 if ((e = get_uint8(buf, bufsize, &pos, &res8)) != 0) {
206 return e;
207 }
208 com->argctr = 0; // we set com->argctr by adding arguments one by one
209 int args = res8;
210
211 CNWDEBUGCOM("Command type: %i\n", com->com);
212 CNWDEBUGCOM("Sender: %p\n", com->sender);
213 CNWDEBUGCOM("Index: %p\n", com->index);
214 CNWDEBUGCOM("Args: %i\n", args);
215 if (com->sender == 0) {
216 return 8;
217 }
218 if (com->sender > 0xFFFFFFFF) {
219 return 9;
220 }
221
222 //decode args
223 int i;
224
225 for (i = 0; i < args; i++) {
226 /*
227 * uint8_t fieldnum;
228 * uint8_t fieldtype;
229 * uint8_t asize=0;
230 *
231 * if ((e = get_uint8(buf, bufsize, &pos, &fieldnum)) != 0) { // field num
232 * return e;
233 * }
234 * if ((e = get_uint8(buf, bufsize, &pos, &fieldtype)) != 0) { // field type
235 * return e;
236 * }
237 * if (fieldtype & (1<<7)) {
238 * if ((e = get_uint8(buf, bufsize, &pos, &asize)) != 0) { // field type
239 * return e;
240 * }
241 * }
242 * CNWDEBUGCOM("Position %i, arg %i, fieldnum: %i, fieldtype: %i, arraysize: %i\n", pos, i, fieldnum,fieldtype,asize);
243 */
244 e = command_add_encoded_arg_with_pos(com, buf, bufsize, &pos);
245 if (e != 0) {
246 return e;
247 }
248 }
249 // args decoded
250//printf("Decoding: %s\n",buf);
251 return 0;
252}
int get_arg_size_inmem(const struct command *com, int index)
given an argument by index [0..n], will returns the number in bytes this argument takes up in memory....
const byte * get_arg_new(const struct command *com, int index)
given an argument by index[0..n], will returns a pointer to it. This will include the fieldnumber and...
int com
Definition: command.h:22
long target
Definition: command.h:16
long recipient
Definition: command.h:15
int index
Definition: command.h:13
uint8_t flags
Definition: command.h:23
uint8_t argctr
Definition: command.h:24
long sender
Definition: command.h:14