mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-11-01 14:22:12 +01:00
fix: protocol 2 core review findings
From the review of #99: - A sync could stall when a client took a slot the moment another left: loop() used up the new client's sync on the old one. The slots move to ProtoSlots, a pure module with native tests, and loop() takes a slot's wants only for the client it read (takeWants). - Deleting a group sends its shades, whose inGroup changed. Deleting a shade unlinks it from its groups and sends them, so a new shade given its id doesn't join them. - next and sync with an id get an ok reply, and a message in pieces gets one bad request, not one per piece. - Feeds check for loop() before they write the event buffer, and log an event too large, as events do. - editChanges() (ModelEditor, native tests) says what clients get after an edit; the edit result carries the shade a group gained or lost. order() takes a sort_list_t. - The frame writers move to ProtoFrame. Renames: pf to proto_field_t, the X-macro letters to TYPE/FIELD/ERR/FEED, proto_request_t to proto_message_t, REQ_* to WANTS_*, fmt to eventJson. The event bodies share sendItem(), the connection type name lives in ESPNetwork, and the loop() task check in SocketEmitter. - e2e: the heap floor check skips when the low since boot is already under it; tests for replies to next and sync and a long message. - SECURITY_PLAN.md splits step 1 into 1a-1d. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d869bb53d5
commit
dc2f1478b6
29 changed files with 1087 additions and 670 deletions
|
|
@ -13,9 +13,9 @@ static const proto_named_t ERRORS[] = { PROTO_ERRORS(PROTO_NAMED_ROW) };
|
|||
static const proto_named_t FEEDS[] = { PROTO_FEEDS(PROTO_NAMED_ROW) };
|
||||
#undef PROTO_SENDER
|
||||
#undef PROTO_NAMED_ROW
|
||||
static_assert(sizeof(FIELDS) / sizeof(FIELDS[0]) == static_cast<size_t>(pf::count), "a field without a row");
|
||||
static_assert(sizeof(FIELDS) / sizeof(FIELDS[0]) == static_cast<size_t>(proto_field_t::count), "a field without a row");
|
||||
|
||||
const proto_field_info_t &protoField(pf field) { return FIELDS[static_cast<uint8_t>(field)]; }
|
||||
const proto_field_info_t &protoField(proto_field_t field) { return FIELDS[static_cast<uint8_t>(field)]; }
|
||||
const proto_field_info_t *protoFieldByKey(const char *key) {
|
||||
for(const proto_field_info_t &f : FIELDS)
|
||||
if(strcmp(f.key, key) == 0) return &f;
|
||||
|
|
@ -77,30 +77,3 @@ void ProtoWriter::item(int64_t value) {
|
|||
if(value >= INT32_MIN && value <= INT32_MAX) this->json.addElem((int32_t)value);
|
||||
else this->json.addElem((uint32_t)value);
|
||||
}
|
||||
|
||||
void beginFrame(JsonFormatter &json, proto_type_t type, uint32_t id) {
|
||||
json.beginObject();
|
||||
json.addElem("v", (uint8_t)PROTO_VERSION);
|
||||
json.addElem("t", static_cast<uint8_t>(type));
|
||||
if(id) json.addElem("id", id);
|
||||
json.beginObject("d");
|
||||
}
|
||||
void endFrame(JsonFormatter &json) {
|
||||
json.endObject();
|
||||
json.endObject();
|
||||
}
|
||||
void writeErrorReply(JsonFormatter &json, uint32_t id, proto_error_t code, const char *desc) {
|
||||
beginFrame(json, proto_type_t::reply, id);
|
||||
ProtoWriter w(json);
|
||||
w.add(pf::ok, false);
|
||||
w.add(pf::code, static_cast<uint8_t>(code));
|
||||
w.add(pf::desc, desc);
|
||||
endFrame(json);
|
||||
}
|
||||
void writeHello(JsonFormatter &json, const char *fw) {
|
||||
beginFrame(json, proto_type_t::hello);
|
||||
ProtoWriter w(json);
|
||||
w.add(pf::fw, fw);
|
||||
w.add(pf::schemaHash, protoSchemaHash());
|
||||
endFrame(json);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue