aboutsummaryrefslogtreecommitdiffstats
path: root/serve/deliver.c
Commit message (Collapse)AuthorAgeFilesLines
* Put the links and the crypto they use in link/, a part of their owneunhhu2026-09-291-1/+1
| | | | | libpure-link.a holds them; pure-serve and the M5 harness link it instead of naming its source files.
* Take a message's rows over HTTPeunhhu2026-09-281-1/+23
| | | | | | | | | | | | | | | | | | | | | | | A rows field's JSON value is an array of objects naming the record's fields (numbers, strings; a field left out takes its default). The connection thread encodes them as the list's stored form, which may be longer than the JSON, grows the request's input by that much (pure_runtime_grow: charged to the payload budget as admission charges an input, 503 payload_budget when it does not fit) and places them after the body, so the owner still applies a message it need not parse. A message whose only variable field is rows takes a body that is not JSON as those rows in their stored form: a bulk insert without JSON. An API's answer (--reply) gives rows the same way. A delivered batch holds no rows. server_rows loads 30,000 stock rows in one JSON request (some 250,000 rows a second, against 6,500 with a request a row) and 20,000 more as bytes, refuses a load with a key already there whole (409 exists), then checks 400 random orders against a model (294 applied, 106 refused with none of their rows applied), texts with escapes and Korean, a walk that removes, and a restart that keeps every state and no rows. The format's document (008) describes walks, rows fields and lists of rows, and OUTER_ROW.
* Seal in one session a wire, authenticated by the sender's key (088)eunhhu2026-09-271-29/+65
| | | | | | | | | | | | | | | | | | | | | | A sealed request cost three X25519 operations (about 0.5 ms), so sealed sends drained at half the plain rate. A wire now keeps one HPKE context, encapsulated at its first seal, and seals each request as the context's next number (a failed seal or a restart starts a new session); the header carries the session's encapsulated key and the number, so a receiver opens a session once per connection thread (16 remembered, the least used replaced) and each seal by its number, also after it restarts, unasked. A sender with a key of its own seals in HPKE auth mode and names that key in the header; a receiver started with --sender NAME=KEY takes deliveries only from the senders it names, each sealed with its key (403 sender otherwise). The body is now the ciphertext and its tag. Sealed sends, sender authenticated, drain at 461-464k a second against 462-470k plain and 207-234k sealed a request at a time (Raspberry Pi 5). The check adds: a wire's requests share one session numbered from 0; a changed number or sender key does not open; a receiver restarted naming its sender opens the same session again; another node claiming that sender's name with its own key is refused and applies nothing.
* Map OpenSSL only in a server that uses iteunhhu2026-09-271-55/+17
| | | | | | | | | | | | | | | | | | Linking OpenSSL cost every pure-serve 2.3 MiB of resident memory, 0.66 MiB of it the process's own (relocated data), though most servers never reach an https receiver or seal a send. The code that uses OpenSSL (TLS to https receivers, sealing) is now built as pure-crypto.so beside pure-serve and exports one table; pure-serve maps it the first time a wire to an https URL opens or a key is read or a seal wired (serve/crypto.c), and a missing library is reported at startup. What needs no OpenSSL, a key's hex and the suite this CPU seals with, stays in pure-serve. An idle server: RSS 4,496 -> 2,320 kB, PSS 1,639 -> 881 kB, private dirty 1,296 -> 864 kB. A static OpenSSL was measured too and is worse (RSS 3.8 MiB, but 2.3 MiB private: all of its tables relocated). The checks, https webhooks and sealed sends included, pass unchanged.
* Seal delivered sends to the receiver's key (086)eunhhu2026-09-271-8/+34
| | | | | | | | | | | | | | | | | | | | --seal OUTPUT=KEY seals each request's body whole to the receiving node's public key with HPKE (RFC 9180, base mode: X25519, HKDF-SHA256, AES-128-GCM where the CPU has AES, else ChaCha20-Poly1305), bound to the request's source, first number and count; X-Pure-Seal names the suite. A receiver's --key is a raw 32-byte file, made 0600 when missing, held in OpenSSL's secure heap; it opens the body where it lies (400 seal when it does not open) and zeroes the plain text when the request's ticket goes. --sealed-only refuses unsealed deliveries (403 unsealed). The check puts a recording relay between two apps: every order applies once, no body shows an item or a field name, a flipped bit is refused, a replayed request applies nothing twice, and a seal to another key does not open. Its hosts choose their own ports (--port 0). Sealed sends drain at 233-235k a second against 469-470k plain (Raspberry Pi 5): three X25519 operations a request, 164 us each. The plain request path measured the same as before.
* Send a delivery's request in one pieceeunhhu2026-09-271-7/+24
| | | | | | | | | | | | A batch went out as a write for its head, then a bracket or comma and the send for each of its sends: two writes a send. Now the head and the whole body are built in one buffer and written once. A receiver stopped while 20,000 sends piled up drained them at 91k sends a second before and at 470k after (three rounds each, Raspberry Pi 5). Writing the head apart from the body measured the same (468k), so the gain is the body's; one buffer is kept as the simpler of the two, and a lone send now leaves in one segment instead of two.
* Lay Pure out as a core with the parts selected around iteunhhu2026-09-271-0/+716
The app model, the tree store and the HTTP host lived in prototypes/connections among the earlier document runtime, the store was known only by its format's name, and Vega compiled six Pure sources by path. Now, as the README's principle has it: core/ runtime, flow and the app model (module*.c), with what the core asks of storage (state.h, store.h) store/ the tree store (PURETRE3, PUREREC1) serve/ pure-serve: HTTP host, outbound delivery, JSON in place cli/ pure-run, pure-edit-module A top-level make builds libpure.a (app model and store, for hosts to link) and the hosts; make check runs the store's and the app model's tests. The earlier runtime still builds from prototypes/connections against core/ and store/ (check, check-tree and check-core pass). Design 009 records the rule: parts by role behind libraries; git repositories split by coupling, so the store stays here while its contract moves with the core, and Vega stays apart.