Files
LithosAnanake/v4/include/v4/message.h
T
rajamesandClaude Opus 5.5 9efe8aad3a 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>
2026-10-07 19:58:27 -04:00

66 lines
2.8 KiB
C

/* message.h -- a message, as it is written to a port and read from one.
* docs/v4.0.0/MESH.md section 6.
*
* The ports are the transport; the message is what is transported. It is
* v3's Hermes message with what it carries, a word at a time:
*
* word 0 to: the node it is for
* word 1 from: the node that sent it
* word 2 type
* word 3 heat and TTL
* word 4 ACL tag: the sender's identity fingerprint
* word 5 sequence
* word 6 how many characters of text follow, 0 to 1024
* word 7.. the text, four characters to a word, the first lowest
*
* Words 3, 4 and 5 are carried and not yet used: checking them is the
* router's, and awaits rulings (MESH.md section 3).
*
* This is for whatever is on the other end of a node's port and is not a
* node -- a console, a host -- to speak what the nodes speak (v4/capsule/
* core.v4 and quit.v4 are the same thing in the node). Nothing here uses
* the C library.
*/
#ifndef V4_MESSAGE_H
#define V4_MESSAGE_H
#include "v4/cell.h"
#define V4_MSG_HEADER 7u
#define V4_MSG_MAX_CHARS 1024u /* a block */
#define V4_MSG_MAX_WORDS (V4_MSG_HEADER + V4_MSG_MAX_CHARS / 4u)
#define V4_MSG_TEXT 1 /* text to be interpreted */
#define V4_MSG_OUTPUT 2 /* what a node printed */
#define V4_MSG_DONE 3 /* how the text ended: one word, V4_TEXT_* */
#define V4_MSG_NACK 4 /* a message was refused: one word, the node it was for (MESH.md 7b) */
#define V4_MSG_GONE 5 /* a node is gone: one word, its number */
/* how text ended */
#define V4_TEXT_QUIT 0 /* QUIT: nothing is to be said */
#define V4_TEXT_COMPLETED 1 /* a console says " ok" */
#define V4_TEXT_ERROR 2 /* the message is printed; a console says " ERROR" */
typedef struct {
v4_cell word[V4_MSG_MAX_WORDS];
unsigned count; /* words in it */
} v4_message;
/* A message of `len` characters, at most V4_MSG_MAX_CHARS. Returns how many
* words it is, or 0 if `len` is too many. */
unsigned v4_message_text(v4_message *m, v4_cell to, v4_cell from, v4_cell type, const char *chars, unsigned len);
/* A message arriving a word at a time. Start with m->count = 0 and give
* each word as it comes: returns 1 when the message is whole, 0 if there is
* more to come. A length that is not 0 to V4_MSG_MAX_CHARS is taken as 0. */
int v4_message_word(v4_message *m, v4_cell word);
/* Its parts. */
#define v4_message_to(m) ((m)->word[0])
#define v4_message_from(m) ((m)->word[1])
#define v4_message_type(m) ((m)->word[2])
unsigned v4_message_length(const v4_message *m); /* characters of text */
char v4_message_char(const v4_message *m, unsigned i); /* the i-th of them */
#endif /* V4_MESSAGE_H */