This is an automated email from the git hooks/post-receive script.
git pushed a commit to reference refs/pull/36/head
in repository terminology.
View the commit online.
commit 2b9002f3a3b8d546f34519fd97b777da09554b57
Author: [email protected] <[email protected]>
AuthorDate: Sun Mar 22 10:14:34 2026 -0600
feat: define tymux shared-memory backlog buffer protocol
Add protocol definitions for exposing the daemon's scrollback history
to clients via memfd-backed shared-memory buffers. Each buffer holds
up to 256 lines at a fixed column width. Extend the NOTIFY and
ATTACHED messages with backlog state fields, and add two new message
types (BACKLOG_BUF_REQ/BACKLOG_BUF) for lazy buffer fetching.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
src/bin/termsrv.c | 6 +++---
src/bin/termsrv.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/src/bin/termsrv.c b/src/bin/termsrv.c
index 6ebc1d80..d0ea6b6c 100644
--- a/src/bin/termsrv.c
+++ b/src/bin/termsrv.c
@@ -153,9 +153,9 @@ termsrv_msg_recv(int fd, void **payload_out, uint32_t *size_out)
}
/* Reject unknown message types before allocating — valid range is
- * ATTACH(1)..EXIT(9). Checking type first prevents a malloc that
- * would otherwise leak on the error path. */
- if (hdr.type == 0 || hdr.type > 9) return -1;
+ * ATTACH(1)..BACKLOG_BUF(11). Checking type first prevents a malloc
+ * that would otherwise leak on the error path. */
+ if (hdr.type == 0 || hdr.type > 11) return -1;
if (hdr.size > TERMSRV_MAX_MSG_PAYLOAD) return -1;
if (hdr.size > 0)
diff --git a/src/bin/termsrv.h b/src/bin/termsrv.h
index f8da7214..761ebc3e 100644
--- a/src/bin/termsrv.h
+++ b/src/bin/termsrv.h
@@ -17,6 +17,10 @@
#define TERMSRV_MAX_COLS 500
#define TERMSRV_MAX_ROWS 200
+#define TERMSRV_BACKLOG_MAGIC 0x544D424Cu /* "TMBL" */
+#define TERMSRV_BACKLOG_VERSION 1u
+#define TERMSRV_BACKLOG_MAX_LINES 256u
+
/*
* Header occupies the first 4096 bytes (one page) of the memfd.
* Cells follow at TERMSRV_SHM_HEADER_SIZE, in display order (row 0 = top).
@@ -34,6 +38,35 @@ typedef struct {
_Atomic uint64_t write_seq;
} TermShmHeader;
+/* ── Backlog buffer shared-memory layout ─────────────────────────── */
+
+typedef struct {
+ uint32_t magic; /* TERMSRV_BACKLOG_MAGIC */
+ uint32_t version; /* TERMSRV_BACKLOG_VERSION */
+ uint32_t cols; /* terminal width when buf created */
+ uint32_t num_lines; /* lines currently stored */
+ uint32_t max_lines; /* capacity (TERMSRV_BACKLOG_MAX_LINES) */
+ uint8_t _pad[3];
+ _Atomic uint64_t write_seq; /* head buffer only: incremented on append */
+ uint32_t line_widths[TERMSRV_BACKLOG_MAX_LINES];
+} TermBacklogBufHeader;
+
+#define TERMSRV_BACKLOG_HEADER_SIZE \
+ ((sizeof(TermBacklogBufHeader) + 4095u) & ~4095u) /* round up to page */
+
+#define TERMSRV_BACKLOG_CELLS_SIZE(cols) \
+ ((size_t)TERMSRV_BACKLOG_MAX_LINES * (size_t)(cols) * sizeof(Termcell))
+
+#define TERMSRV_BACKLOG_TOTAL_SIZE(cols) \
+ (TERMSRV_BACKLOG_HEADER_SIZE + TERMSRV_BACKLOG_CELLS_SIZE(cols))
+
+#define TERMSRV_BACKLOG_CELLS(hdr) \
+ ((Termcell *)((uint8_t *)(hdr) + TERMSRV_BACKLOG_HEADER_SIZE))
+
+/* Line i cell data in a backlog buffer: */
+#define TERMSRV_BACKLOG_LINE(hdr, i) \
+ (TERMSRV_BACKLOG_CELLS(hdr) + (size_t)(i) * (size_t)(hdr)->cols)
+
#define TERMSRV_SHM_HEADER_SIZE 4096u
#define TERMSRV_SHM_CELLS_SIZE \
((size_t)TERMSRV_MAX_COLS * TERMSRV_MAX_ROWS * sizeof(Termcell))
@@ -55,6 +88,8 @@ typedef enum {
TSRV_MSG_TITLE = 7, /* server → client: new window title */
TSRV_MSG_BELL = 8, /* server → client: BEL */
TSRV_MSG_EXIT = 9, /* server → client: tymux ended, exit code */
+ TSRV_MSG_BACKLOG_BUF_REQ = 10, /* client → server: request backlog buffer fd */
+ TSRV_MSG_BACKLOG_BUF = 11, /* server → client: backlog buffer fd response */
} TermSrvMsgType;
/* Every message starts with this 8-byte header */
@@ -65,8 +100,11 @@ typedef struct {
/* ATTACHED payload (memfd via SCM_RIGHTS alongside this) */
typedef struct {
- uint32_t cols;
- uint32_t rows;
+ uint32_t cols; /* screen columns */
+ uint32_t rows; /* screen rows */
+ uint32_t backlog_buf_count; /* backlog buffers available */
+ uint32_t backlog_max_lines; /* lines per buffer */
+ uint32_t oldest_buf_id; /* first valid buffer index */
} TermSrvMsgAttached;
/* RESIZE payload */
@@ -77,7 +115,10 @@ typedef struct {
/* NOTIFY payload */
typedef struct {
- uint64_t write_seq;
+ uint64_t write_seq; /* screen shm sequence */
+ uint32_t backlog_buf_count; /* total backlog buffers available */
+ uint32_t backlog_head_seq; /* write_seq of head buffer (low 32) */
+ uint32_t oldest_buf_id; /* first valid buffer index */
} TermSrvMsgNotify;
/* EXIT payload */
@@ -85,6 +126,19 @@ typedef struct {
int32_t exit_code;
} TermSrvMsgExit;
+/* BACKLOG_BUF_REQ payload */
+typedef struct {
+ uint32_t buf_id; /* buffer index to request */
+} TermSrvMsgBacklogBufReq;
+
+/* BACKLOG_BUF payload */
+typedef struct {
+ uint32_t buf_id; /* which buffer this is */
+ uint32_t cols; /* column width of lines */
+ uint32_t num_lines; /* lines stored */
+ uint32_t max_lines; /* capacity */
+} TermSrvMsgBacklogBuf;
+
/* ── payload size limit ─────────────────────────────────────────── */
/* Sanity cap on incoming message payload size. No tymux message should
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.