feat(v4.0.0): a refused message is told to its sender -- NACK and GONE

A node that has no room for a message, or no way to pass it on, lets it
go and counts it as before, and now notes that it owes its sender a NACK
(type 4: the node the message was for).  It sends what it owes when it
next has nothing else to do.  36 cells of the messages waiting are kept
for NACK and GONE, and nothing is owed for either.

A node sent a NACK counts it in (REFUSED); one waiting for an answer from
that node (AWAIT) stops, with error 19, Message refused.  A GONE (type 5)
from a node's centre makes it forget the way to the node named (NO-ROUTE,
new), and ends a wait on it with error 20, Node gone.  From anyone else
it is ignored.  GONE ( n node -- ) sends one.

test_host_mesh.c, three nodes: text for a node nobody has a way to comes
back to the console, and to a node two away, as a NACK; a waiting sender's
line ends Message refused; a node that is waiting keeps what it has room
for, owes eight refusals, counts the rest, and sends them when its wait is
ended by a GONE from its centre.  70 checks, both widths, sanitizers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 19:58:27 -04:00
co-authored by Claude Opus 5.5
parent 6e1ac157c6
commit 9efe8aad3a
5 changed files with 184 additions and 14 deletions
+7
View File
@@ -64,6 +64,9 @@
#define BLK (BVARS + 7)
#define SRC (BVARS + 8)
#define SRC_HOOK (BVARS + 9)
#define REFUSED (BUF0_W - 7) /* how many of this node's messages it has been told were refused */
#define OWED_COUNT (BUF0_W - 8) /* how many refusals this node owes and has not sent yet, at most 8 */
#define OWED (BUF0_W - 112) /* those: for each, the node it is owed to and the node the refused message was for */
#define ACL_HOOK (BUF0_W - 6) /* the xt of the access control recheck word, or 0 */
#define LINE_STATUS (BUF0_W - 9) /* how the last line ended: 0 QUIT, 1 completed, 2 an error */
#define PORT (BUF0_W - 32) /* the node's ports (node.h): V4_PORTS of them, then "any port" and "which port". Port 0 is where its requests go. */
@@ -192,6 +195,10 @@ static int host_load(v4_text *tx, v4_node *n, const char *const *files, unsigned
v4_text_constant(tx, "(AWAIT-FROM)", AWAIT_FROM);
v4_text_constant(tx, "(MQ)", MQ_W);
v4_text_constant(tx, "(MQ-END)", MQ_W + MQ_CELLS);
v4_text_constant(tx, "-MQ-ORDINARY", -(v4_cell)(MQ_CELLS - 7 - 36)); /* the same for a message that is not a refusal or a GONE: 36 cells are kept for those */
v4_text_constant(tx, "(REFUSED)", REFUSED);
v4_text_constant(tx, "(OWED#)", OWED_COUNT);
v4_text_constant(tx, "(OWED)", OWED);
v4_text_constant(tx, "-MQ-ROOM", -(v4_cell)(MQ_CELLS - 7)); /* cells taken + a text's words + this is below zero while the message fits */
v4_text_constant(tx, "(MQ-HEAD)", MQ_HEAD);
v4_text_constant(tx, "(MQ-TAIL)", MQ_TAIL);