skip to content
==> 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}