cultmesh-ts: count and answer a frame that decodes but is no message the parser takes
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 6m9s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 1m17s
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 6m9s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 1m17s
A map with an unknown schemaVersion was rethrown: unanswered, uncounted toward the session cap. It is now answered message_invalid, reported, and counted like any other unreadable frame, so the cap holds for it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
621e05d552
commit
23c7ce3738
2 changed files with 33 additions and 2 deletions
|
|
@ -5678,9 +5678,13 @@ export class CultMesh {
|
|||
// A frame the server cannot read is judged as the write it looks like (a put when it does not even decode), so
|
||||
// an ungranted peer hears the same refusal for it as for any other write, not a parse error.
|
||||
const write = readableWrite(decoded);
|
||||
if (decoded !== undefined && !write) throw error;
|
||||
record.unreadableInARow += 1;
|
||||
if (!await writeRefused(record, write?.operation ?? "put", write?.schemaId ?? "", write?.recordKey ?? "", null, null)) {
|
||||
if (decoded !== undefined && !write) {
|
||||
// It decodes but is no message the parser takes (an unknown schemaVersion, a non-map) and is no write the
|
||||
// authority could judge: answered and counted like any other unreadable frame.
|
||||
reportError(error);
|
||||
sendSchemaMessage(record, cultNetMessageInvalidError("message", "CultMesh RUDP document server could not read the message."));
|
||||
} else if (!await writeRefused(record, write?.operation ?? "put", write?.schemaId ?? "", write?.recordKey ?? "", null, null)) {
|
||||
reportError(error);
|
||||
sendSchemaMessage(record, cultNetMessageInvalidError("message", "CultMesh RUDP document server could not read the write."));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -563,3 +563,30 @@ test("deletes the authority refuses are answered and the session kept until eigh
|
|||
assert.equal(r.deletes.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test("a frame that decodes but is no message the parser takes is answered, counted, and ended at eight in a row like any unreadable frame", async () => {
|
||||
const r = await rawRig(new Recording(grant));
|
||||
const unknown = () => encodeWireValue({ schemaVersion: "cultnet.not-a-message.v0", messageId: "x" });
|
||||
try {
|
||||
const batch = async (frames: number) => {
|
||||
for (let i = 0; i < frames; i++) r.send(unknown());
|
||||
await sleep(400);
|
||||
};
|
||||
await batch(CAP - 1);
|
||||
assert.equal(r.replies.length, CAP - 1, "each is answered");
|
||||
assert.equal(r.errors.length, CAP - 1, "and reported");
|
||||
r.send(encodeWireValue(put(KEY_A)));
|
||||
await sleep(250);
|
||||
assert.deepEqual(r.puts.map((p) => p.recordKey), [KEY_A], "the session was kept through seven");
|
||||
await batch(CAP - 1);
|
||||
assert.equal(r.replies.length, 2 * (CAP - 1), "the decoded put reset the run");
|
||||
r.send(unknown());
|
||||
await sleep(300);
|
||||
assert.equal(r.replies.length, 2 * (CAP - 1) + 1, "the eighth is answered too");
|
||||
for (const reply of r.replies) {
|
||||
assert.equal((reply as { code?: string }).code, "message_invalid");
|
||||
assert.equal((reply as { details: { field: string } }).details.field, "message");
|
||||
}
|
||||
assert.throws(() => r.send(unknown()), /before the session is connected/, "then the session ended");
|
||||
} finally { r.close(); }
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue