==> src/place_wire.c <==1/* place.rs: name16, name_of, PlaceMsg, FrameMsg, encode_input, input_len. */
2#include "mesh/place_wire.h"
3#include "mesh/abi/name.h"
4#include "mesh/abi/peer_frames.h"
5#include "mesh/abi/peer_sizes.h"
6#include "mesh/abi/place_ops.h"
7#include "mesh/rust_fmt.h"
8#include "mesh/mt.h"
9
10#include <stdlib.h>
11#include <string.h>
12
13void mpw_name16(const char *name, uint8_t out[MESH_NAME_BYTES]) {
14 memset(out, 0, MESH_NAME_BYTES);
15 size_t k = strlen(name);
16 if (k > MESH_NAME_MAX) k = MESH_NAME_MAX;
17 memcpy(out, name, k);
18}
19
20bool mpw_name_of(const uint8_t *b, size_t n, char *out, char **err) {
21 size_t k = 0;
22 while (k < n && b[k]) k++;
23 if (!mesh_valid_name(b, k)) {
24 char *raw = mt_strndup((const char *)b, k);
25 char *q = rf_debug_str(raw);
26 *err = mt_fmt("bad program name %s", q);
27 free(q), free(raw);
28 return false;
29 }
30 memcpy(out, b, k);
31 out[k] = 0;
32 return true;
33}
34
35void mpw_put(mpw_bytes *o, const void *p, size_t n) {
36 if (o->n + n > o->cap) {
37 size_t c = o->cap ? o->cap : 64;
38 while (c < o->n + n) c *= 2;
39 o->b = mt_realloc(o->b, c);
40 o->cap = c;
41 }
42 if (n) memcpy(o->b + o->n, p, n);
43 o->n += n;
44}
45
46void mpw_put32(mpw_bytes *o, uint32_t v) {
47 uint8_t b[4] = {(uint8_t)v, (uint8_t)(v >> 8), (uint8_t)(v >> 16), (uint8_t)(v >> 24)};
48 mpw_put(o, b, 4);
49}
50
51void mpw_bytes_free(mpw_bytes *o) {
52 free(o->b);
53 *o = (mpw_bytes){0};
54}
55
56uint32_t mpw_u32_at(const uint8_t *b, size_t at) { return (uint32_t)b[at] | (uint32_t)b[at + 1] << 8 | (uint32_t)b[at + 2] << 16 | (uint32_t)b[at + 3] << 24; }
57uint64_t mpw_u64_at(const uint8_t *b, size_t at) { return (uint64_t)mpw_u32_at(b, at) | (uint64_t)mpw_u32_at(b, at + 4) << 32; }
58
59static uint8_t *dup(const uint8_t *p, size_t n) {
60 uint8_t *d = mt_alloc(n ? n : 1);
61 if (n) memcpy(d, p, n);
62 return d;
63}
64
65mpw_bytes mpw_place_encode(const mpw_place *m) {
66 mpw_bytes o = {0};
67 uint8_t t = MESH_F_PLACE, name[MESH_NAME_BYTES], assign[MESH_PLACE_PARTS_MAX];
68 uint32_t code, sys;
69 mpm_code(&m->mode, &code, &sys);
70 mpw_put(&o, &t, 1);
71 mpw_put32(&o, m->op);
72 mpw_put32(&o, m->id);
73 mpw_name16(m->name, name);
74 mpw_put(&o, name, sizeof name);
75 mpw_put32(&o, code);
76 mpw_put32(&o, sys);
77 mpm_assign_bytes(&m->mode, assign);
78 mpw_put(&o, assign, sizeof assign);
79 mpw_put32(&o, m->aux);
80 mpw_put32(&o, (uint32_t)m->nbytes);
81 mpw_put(&o, m->bytes, m->nbytes);
82 return o;
83}
84
85bool mpw_place_rest_len(const uint8_t *head, size_t *n, char **err) {
86 *n = mpw_u32_at(head, MPW_PLACE_HEAD - 4);
87 if (*n > MESH_F_PLACE_MAX) {
88 *err = mt_fmt("F_PLACE of %zu bytes > F_PLACE_MAX", *n);
89 return false;
90 }
91 return true;
92}
93
94bool mpw_place_decode(const uint8_t *head, const uint8_t *rest, size_t nrest, mpw_place *out, char **err) {
95 uint32_t op = mpw_u32_at(head, 0);
96 if (op > MESH_PL_FAIL) {
97 *err = mt_fmt("F_PLACE: bad op %u", op);
98 return false;
99 }
100 size_t at = 8 + MESH_NAME_BYTES;
101 mpw_place m = {.op = op, .id = mpw_u32_at(head, 4)};
102 if (!mpw_name_of(head + 8, MESH_NAME_BYTES, m.name, err)) return false;
103 if (!mpm_from_code(mpw_u32_at(head, at), mpw_u32_at(head, at + 4), head + at + 8, MESH_PLACE_PARTS_MAX, &m.mode, err)) return false;
104 m.aux = mpw_u32_at(head, at + 8 + MESH_PLACE_PARTS_MAX);
105 m.bytes = dup(rest, nrest);
106 m.nbytes = nrest;
107 *out = m;
108 return true;
109}
110
111void mpw_place_free(mpw_place *m) {
112 free(m->bytes);
113 m->bytes = NULL;
114 m->nbytes = 0;
115}
116
117mpw_bytes mpw_frame_encode(const mpw_frame *m) {
118 mpw_bytes o = {0};
119 uint8_t t = MESH_F_FRAME, name[MESH_NAME_BYTES];
120 mpw_put(&o, &t, 1);
121 mpw_name16(m->name, name);
122 mpw_put(&o, name, sizeof name);
123 mpw_put32(&o, m->frame);
124 mpw_put32(&o, m->parts);
125 mpw_put32(&o, m->sys);
126 mpw_put32(&o, (uint32_t)m->nstate);
127 mpw_put32(&o, (uint32_t)m->ndata);
128 mpw_put(&o, m->state, m->nstate);
129 mpw_put(&o, m->data, m->ndata);
130 return o;
131}
132
133bool mpw_frame_rest_len(const uint8_t *head, size_t *n, char **err) {
134 *n = (size_t)mpw_u32_at(head, MESH_NAME_BYTES + 12) + mpw_u32_at(head, MESH_NAME_BYTES + 16);
135 if (*n > MESH_F_PLACE_MAX) {
136 *err = mt_fmt("F_FRAME of %zu bytes > F_PLACE_MAX", *n);
137 return false;
138 }
139 return true;
140}
141
142bool mpw_frame_decode(const uint8_t *head, const uint8_t *rest, size_t nrest, mpw_frame *out, char **err) {
143 size_t sl = mpw_u32_at(head, MESH_NAME_BYTES + 12);
144 if (sl > nrest) sl = nrest;
145 mpw_frame m = {.frame = mpw_u32_at(head, MESH_NAME_BYTES), .parts = mpw_u32_at(head, MESH_NAME_BYTES + 4), .sys = mpw_u32_at(head, MESH_NAME_BYTES + 8)};
146 if (!mpw_name_of(head, MESH_NAME_BYTES, m.name, err)) return false;
147 m.state = dup(rest, sl);
148 m.nstate = sl;
149 m.data = dup(rest + sl, nrest - sl);
150 m.ndata = nrest - sl;
151 *out = m;
152 return true;
153}
154
155mpw_frame mpw_frame_clone(const mpw_frame *m) {
156 mpw_frame c = *m;
157 c.state = dup(m->state, m->nstate);
158 c.data = dup(m->data, m->ndata);
159 return c;
160}
161
162void mpw_frame_free(mpw_frame *m) {
163 free(m->state);
164 free(m->data);
165 m->state = m->data = NULL;
166 m->nstate = m->ndata = 0;
167}
168
169mpw_bytes mpw_input_encode(const char *name, const uint8_t *bytes, size_t n) {
170 mpw_bytes o = {0};
171 uint8_t t = MESH_F_INPUT, nm[MESH_NAME_BYTES];
172 mpw_put(&o, &t, 1);
173 mpw_name16(name, nm);
174 mpw_put(&o, nm, sizeof nm);
175 mpw_put32(&o, (uint32_t)n);
176 mpw_put(&o, bytes, n);
177 return o;
178}
179
180bool mpw_input_len(const uint8_t *head, size_t *n, char **err) {
181 *n = mpw_u32_at(head, MESH_NAME_BYTES);
182 if (*n > MESH_F_INPUT_MAX) {
183 *err = mt_fmt("F_INPUT of %zu bytes > F_INPUT_MAX", *n);
184 return false;
185 }
186 return true;
187}