skip to content
==> src/host_block.c <==
1/* The host status block under a mutex. */
2#include "mesh/host_block.h"
3#include "mesh/abi/host_status.h"
4#include "mesh/chan.h"
5
6#include <string.h>
7
8void mesh_host_block_init(mesh_host_block *h) {
9    memset(h->block, 0, sizeof h->block);
10    pthread_mutex_init(&h->mu, NULL);
11    h->started_us = mesh_mono_us();
12    mesh_net_counters_init(&h->net);
13}
14
15static void put(mesh_host_block *h, size_t off, const void *b, size_t n) {
16    pthread_mutex_lock(&h->mu);
17    memcpy(h->block + off, b, n);
18    pthread_mutex_unlock(&h->mu);
19}
20
21static void le32(uint8_t b[4], uint32_t v) { for (int i = 0; i < 4; i++) b[i] = (uint8_t)(v >> (8 * i)); }
22
23void mesh_host_block_set_u32(mesh_host_block *h, size_t off, uint32_t v) {
24    uint8_t b[4];
25    le32(b, v);
26    put(h, off, b, 4);
27}
28
29void mesh_host_block_set_f32(mesh_host_block *h, size_t off, float v) {
30    uint32_t u;
31    memcpy(&u, &v, 4);
32    mesh_host_block_set_u32(h, off, u);
33}
34
35void mesh_host_block_set_u64(mesh_host_block *h, size_t off, uint64_t v) {
36    uint8_t b[8];
37    for (int i = 0; i < 8; i++) b[i] = (uint8_t)(v >> (8 * i));
38    put(h, off, b, 8);
39}
40
41void mesh_host_block_set_many(mesh_host_block *h, const mesh_host_field *f, size_t n) {
42    pthread_mutex_lock(&h->mu);
43    for (size_t i = 0; i < n; i++) memcpy(h->block + f[i].off, f[i].bytes, f[i].len);
44    pthread_mutex_unlock(&h->mu);
45}
46
47static uint32_t get32(const uint8_t *b) { return (uint32_t)b[0] | (uint32_t)b[1] << 8 | (uint32_t)b[2] << 16 | (uint32_t)b[3] << 24; }
48
49void mesh_host_block_add_u32(mesh_host_block *h, size_t off, uint32_t n) {
50    pthread_mutex_lock(&h->mu);
51    le32(h->block + off, get32(h->block + off) + n);
52    pthread_mutex_unlock(&h->mu);
53}
54
55void mesh_host_block_set_str(mesh_host_block *h, size_t off, size_t len, const char *s) {
56    uint8_t b[256];
57    size_t k = strlen(s);
58    if (len > sizeof b) len = sizeof b;
59    if (k > len - 1) k = len - 1;
60    memset(b, 0, len);
61    memcpy(b, s, k);
62    put(h, off, b, len);
63}
64
65uint64_t mesh_host_block_uptime_ms(const mesh_host_block *h) { return (uint64_t)((mesh_mono_us() - h->started_us) / 1000); }
66
67uint32_t mesh_host_block_get_u32(mesh_host_block *h, size_t off) {
68    pthread_mutex_lock(&h->mu);
69    uint32_t v = get32(h->block + off);
70    pthread_mutex_unlock(&h->mu);
71    return v;
72}
73
74float mesh_host_block_get_f32(mesh_host_block *h, size_t off) {
75    uint32_t u = mesh_host_block_get_u32(h, off);
76    float f;
77    memcpy(&f, &u, 4);
78    return f;
79}
80
81void mesh_host_block_bytes(mesh_host_block *h, uint8_t out[MESH_SNAP_HOST]) {
82    pthread_mutex_lock(&h->mu);
83    memcpy(out, h->block, MESH_SNAP_HOST);
84    pthread_mutex_unlock(&h->mu);
85    uint64_t up = mesh_host_block_uptime_ms(h);
86    for (int i = 0; i < 8; i++) out[MESH_S_UPTIME_MS + (size_t)i] = (uint8_t)(up >> (8 * i));
87    mesh_net_counters_fill(&h->net, out);
88}