==> src/frame.c <==1/* blobd.rs's blob frames: the bytes it writes (ack, push, get, answer) and how it reads them. */
2#include "mesh/blobs/frame.h"
3#include "mesh/abi/peer_frames.h"
4
5#include <string.h>
6
7static void u32le(msb *o, uint32_t v) {
8 uint8_t b[4];
9 for (int i = 0; i < 4; i++) b[i] = (uint8_t)(v >> 8 * i);
10 msb_put(o, b, 4);
11}
12
13static void u64le(msb *o, uint64_t v) {
14 uint8_t b[8];
15 for (int i = 0; i < 8; i++) b[i] = (uint8_t)(v >> 8 * i);
16 msb_put(o, b, 8);
17}
18
19void mbf_put(msb *o, const mj_hash *h, mj_job_id job, const void *bytes, uint32_t n) {
20 msb_putc(o, (char)MESH_F_BLOB_PUT);
21 u32le(o, 44 + n);
22 msb_put(o, h->b, 32);
23 u64le(o, job);
24 u32le(o, n);
25 msb_put(o, bytes, n);
26}
27
28void mbf_ack(msb *o, const mj_hash *h, bool ok, mj_job_id job) {
29 msb_putc(o, (char)MESH_F_BLOB_ACK);
30 u32le(o, 44);
31 msb_put(o, h->b, 32);
32 u32le(o, ok ? 1 : 0);
33 u64le(o, job);
34}
35
36void mbf_get(msb *o, const mj_hash *h, mj_job_id job) {
37 msb_putc(o, (char)MESH_F_BLOB_GET);
38 u32le(o, 40);
39 msb_put(o, h->b, 32);
40 u64le(o, job);
41}
42
43void mbf_blob(msb *o, const mj_hash *h, const void *bytes, size_t n, bool found) {
44 msb_putc(o, (char)MESH_F_BLOB);
45 u32le(o, (uint32_t)(36 + (found ? n : 0)));
46 msb_put(o, h->b, 32);
47 u32le(o, found ? 1 : 0);
48 if (found) msb_put(o, bytes, n);
49}
50
51static bool u32_at(const uint8_t *b, size_t n, size_t o, uint32_t *v) {
52 if (n < o + 4) return false;
53 *v = (uint32_t)b[o] | (uint32_t)b[o + 1] << 8 | (uint32_t)b[o + 2] << 16 | (uint32_t)b[o + 3] << 24;
54 return true;
55}
56
57static bool u64_at(const uint8_t *b, size_t n, size_t o, uint64_t *v) {
58 if (n < o + 8) return false;
59 uint64_t x = 0;
60 for (int i = 7; i >= 0; i--) x = x << 8 | b[o + (size_t)i];
61 *v = x;
62 return true;
63}
64
65bool mbf_decode(uint8_t ty, const uint8_t *b, size_t n, mbf_body *out) {
66 memset(out, 0, sizeof *out);
67 if (n < 32) return false;
68 memcpy(out->hash.b, b, 32);
69 uint32_t v;
70 switch (ty) {
71 case MESH_F_BLOB_PUT:
72 if (!u64_at(b, n, 32, &out->job) || !u32_at(b, n, 40, &out->len)) return false;
73 out->bytes = b + 44;
74 out->nbytes = n - 44;
75 return true;
76 case MESH_F_BLOB_ACK:
77 if (!u32_at(b, n, 32, &v) || !u64_at(b, n, 36, &out->job)) return false;
78 out->ok = v != 0;
79 return true;
80 case MESH_F_BLOB_GET: return true;
81 case MESH_F_BLOB:
82 out->ok = u32_at(b, n, 32, &v) && v != 0;
83 if (out->ok) {
84 out->bytes = b + 36;
85 out->nbytes = n - 36;
86 }
87 return true;
88 default: return false;
89 }
90}