19bool emit_option(uint8_t *out,
size_t *o,
size_t cap, uint16_t delta,
const uint8_t *val, uint16_t vlen)
41 dext[0] = (uint8_t)(delta - 13);
47 uint16_t x = (uint16_t)(delta - 269);
48 dext[0] = (uint8_t)(x >> 8);
60 lext[0] = (uint8_t)(vlen - 13);
66 uint16_t x = (uint16_t)(vlen - 269);
67 lext[0] = (uint8_t)(x >> 8);
71 if (start + 1 + dexn + lexn + vlen > cap)
75 out[(*o)++] = (uint8_t)((dn << 4) | ln);
76 for (
int i = 0; i < dexn; i++)
78 out[(*o)++] = dext[i];
80 for (
int i = 0; i < lexn; i++)
82 out[(*o)++] = lext[i];
84 for (uint16_t i = 0; i < vlen; i++)
92size_t pc_wisun_build_coap(uint8_t type, uint8_t code, uint16_t msg_id,
const uint8_t *token, uint8_t tkl,
93 const char *uri_path,
const uint8_t *payload,
size_t plen, uint8_t *out,
size_t cap)
95 if (!out || tkl > 8 || (tkl && !token) || (plen && !payload))
100 if (cap < (
size_t)(4 + tkl))
104 out[o++] = (uint8_t)(0x40 | ((type & 0x03) << 4) | (tkl & 0x0F));
106 out[o++] = (uint8_t)(msg_id >> 8);
107 out[o++] = (uint8_t)msg_id;
108 for (uint8_t i = 0; i < tkl; i++)
115 const char *p = uri_path;
124 while (*p && *p !=
'/')
128 uint16_t seglen = (uint16_t)(p - seg);
129 uint16_t delta = (uint16_t)(11 - last);
130 if (!emit_option(out, &o, cap, delta, (
const uint8_t *)seg, seglen))
139 if (o + 1 + plen > cap)
144 for (
size_t i = 0; i < plen; i++)
146 out[o++] = payload[i];
152void pc_wisun_init(WisunFan *fan,
const pc_ip *border_router, WisunNode *storage,
size_t cap)
160 fan->border_router = *border_router;
164 memset(&fan->border_router, 0,
sizeof(fan->border_router));
166 fan->nodes = storage;
167 fan->cap = storage ? cap : 0;
171int pc_wisun_node_register(WisunFan *fan,
const pc_ip *addr, uint32_t now)
173 if (!fan || !fan->nodes || !addr)
178 if (pc_wisun_node_find(fan, addr, &idx))
180 fan->nodes[idx].joined =
true;
181 fan->nodes[idx].last_seen = now;
184 if (fan->count >= fan->cap)
188 fan->nodes[fan->count].addr = *addr;
189 fan->nodes[fan->count].joined =
true;
190 fan->nodes[fan->count].last_seen = now;
191 return (
int)fan->count++;
194bool pc_wisun_node_find(
const WisunFan *fan,
const pc_ip *addr,
size_t *idx)
196 if (!fan || !fan->nodes || !addr)
200 for (
size_t i = 0; i < fan->count; i++)
214size_t pc_wisun_joined_count(
const WisunFan *fan)
216 if (!fan || !fan->nodes)
221 for (
size_t i = 0; i < fan->count; i++)
223 if (fan->nodes[i].joined)
231size_t pc_wisun_nodes_json(
const WisunFan *fan,
char *out,
size_t cap)
233 if (!fan || !out || cap == 0)
237 pc_sb b = {out, cap, 0,
true};
239 for (
size_t i = 0; i < fan->count; i++)
250 pc_sb_put(&b, fan->nodes[i].joined ?
"true" :
"false");
bool pc_ip_equal(const pc_ip *a, const pc_ip *b)
True if a and b are the same family and address.
size_t pc_ip_format(const pc_ip *ip, char *out, size_t cap)
Format ip into out as its RFC 5952 canonical text.
#define PC_IP_STR_MAX
Longest text an pc_ip_format can produce, including the NUL (RFC 5952 v4-mapped).
Bounded no-heap string builder that fails closed on overflow (one shared copy).
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
A v4 or v6 address in network (big-endian) byte order.
Bump-append target; ok latches false once an append would overflow cap.
Wi-SUN FAN border-router connector (PC_ENABLE_WISUN).