Five units move out of src/ to vendored copies of
fpc-crypto:
bp.sha -> cr.sha
bp.ed25519* -> cr.ed25519*
And -- bigger deal than it looks -- bp.cram's CRAM-MD5
and bp.des's key-check MD5 swap from stock FPC RTL md5 to
cr.md5. The RTL md5.ppu has a sysutils-checksum bug that
corrupts MD5 output on i386-go32v2; consumers building
fpc-binkp for DOS would have hit it the moment CRAM-MD5
auth happened over a live socket. cr.md5 is the go32v2-
safe standalone implementation.
API rename drops MDInit/MDUpdate/MDFinal/MDString/MDBuffer
+ TMDContext/TMDDigest in favour of the MD5-prefixed
names from cr.md5 (TMD5Context, TMD5Digest, MD5Init/etc.).
bp.cram's public surface (BPHmacMd5, BPMd5DigestHex,
BPCramComputeResponse, ...) is unchanged -- callers see no
diff.
bp.des stays in-tree. Single consumer (Argus DES-CBC wire
extension), same discipline that kept X25519/ChaCha20 in
cm.crypto until a second consumer appeared.
Verified:
- 7/7 local test suite PASS (same as baseline)
- RFC 2202 HMAC-MD5 vectors in test_cram still green
(confirms cr.md5 byte-identical to stock RTL md5 on
the exercised inputs)
- 6-target cross-build clean incl. i386-go32v2
Rationale + ecosystem context: MSGS Messages 48-53.
fpc-binkp
A Free Pascal library for the BinkP/1.1 mailer protocol (FTS-1026, FTS-1027) with support for the widely-deployed vendor extensions (NR, ND, MBT, PLZ, CRYPT, DES-CBC, ED25519).
Sibling library to fpc-msgbase (message
storage), fpc-ftn-transport (PKT,
ArcMail, queues), and comet (the mailer daemon
that consumes all three). Same vendoring model: each library
is its own repo with its own tests; consumers cp / rsync
units from units/ into their build; bug fix → commit here →
consumers pull at their own cadence → rebuild → deploy.
Scope
| Concern | Owned by |
|---|---|
| BinkP/1.1 wire protocol (frames, commands, state machine) | fpc-binkp |
| CRAM-MD5, CRYPT, DES-CBC, ED25519 auth | fpc-binkp |
| PLZ (zlib per-frame) compression | fpc-binkp |
| NR (resume), ND (non-destructive), MBT (multi-batch) | fpc-binkp |
| PKT / ArcMail / BSO queue | fpc-ftn-transport |
| Message storage (JAM, Squish, ...) | fpc-msgbase |
| Session dispatch, config, UI, logging backends | consumer |
| Dialup / EMSI / modem framing | out of scope — separate library |
The library handles the wire. Consumers own everything above and below: the socket, the filesystem, the logging sink, the decision of which file to send next, what "secure" means for an inbound directory.
Status
Current: 0.1.0 — initial release. Core library compiles on all five targets (Linux, FreeBSD, Windows, OS/2, DOS go32v2). Reference TCP transport is UNIX-only; DOS has a dedicated Watt-32 transport; Windows / OS/2 consumers plug in their own IBPTransport.
Seven test programs green including a full two-session round-trip self-test. End-to-end smoke-tested on localhost (outbound ↔ inbound, 10 KB binary transferred with identical SHA-256, full CRAM-MD5 + CRYPT + MBT).
Naming
Unit prefix: bp.<category>.<name>.pas — bp = "binkp".
All units use {$mode objfpc}{$H+}{$modeswitch advancedrecords}.
Architecture
Step-based engine (modeled on Argus, not binkd):
Session := TBPSession.Create(bpsOutbound, Transport, Provider, Events);
Session.Config.LocalAddress := FTNAddr('1:218/720');
Session.Config.Advertise := [bpOptNR, bpOptND, bpOptPLZ, bpOptMBT];
Session.Config.OnPostAuth := @MyPostAuthHook;
while Session.NextStep do
begin
// embedder is in control between every tick.
// can cancel, inspect state, swap provider, etc.
end;
writeln('Result: ', Session.Result.Description);
Session.Free;
The embedder drives the loop. Each call to NextStep does a
bounded unit of I/O + state-machine work and returns. This
gives:
- Testability. Replace
Transportwith aTMemoryStream- backed mock; feed in canned bytes; assert on emitted frames. No sockets required. - Cancellation. Stop calling
NextStep; free the session. - Multiplexing. An event loop can drive N sessions on a
single thread if the
Transportimplementation supports non-blocking I/O. - Observability. Inspect
Session.Phase,Session.RemoteInfobetween ticks. Hooks fire at every policy decision.
See docs/architecture.md for the full
design, docs/api.md for the consumer-facing
API reference, and docs/spec.md for the
FTSC / FSP spec cheat sheet and wire-format notes.
Building
Once units land:
./build.sh # all targets
./build.sh x86_64-linux # just one
./run_tests.sh # run test suite
Supported targets (matches fpc-ftn-transport):
x86_64-linux, i386-go32v2, i386-os2, i386-win32,
i386-linux, i386-freebsd.
License
GPL-2.0 — same as comet.
Layout
fpc-binkp/
├── build.sh — multi-target build driver
├── CHANGELOG.md — release notes, tagged vX.Y.Z
├── README.md — this file
├── run_tests.sh — test runner
├── fpc.cfg — FPC search paths
├── docs/
│ ├── architecture.md — engine design, hook taxonomy
│ ├── api.md — public API reference
│ └── spec.md — FTS-1026/1027 + FSP cheat sheet
├── examples/
│ ├── example_outbound.pas — embed as originator
│ ├── example_inbound.pas — embed as answerer
│ ├── example_mock.pas — replay a captured session
│ └── example_multiplex.pas — N sessions one thread
├── src/
│ ├── bp.version.pas — BP_VERSION constant
│ ├── bp.types.pas — enums, records, forward decls
│ ├── bp.frame.pas — TBPFrame, read/write helpers
│ ├── bp.opt.pas — OPT keyword parser / builder
│ ├── bp.cram.pas — CRAM-MD5 (HMAC-MD5 RFC 2104)
│ ├── bp.crypt.pas — FSP-1037 password-derived cipher
│ ├── bp.des.pas — Argus DES-CBC stream
│ ├── bp.plz.pas — zlib per-frame compression
│ ├── bp.transport.pas — IBPTransport interface
│ ├── bp.provider.pas — IBPFileProvider interface
│ ├── bp.events.pas — IBPEventSink, event records
│ ├── bp.config.pas — TBPSessionConfig record
│ └── bp.session.pas — TBPSession engine (NextStep)
├── tests/
│ ├── test_frame.pas
│ ├── test_cram.pas
│ ├── test_crypt.pas
│ ├── test_des.pas
│ ├── test_plz.pas
│ ├── test_opt.pas
│ ├── test_session_outbound.pas
│ ├── test_session_inbound.pas
│ ├── vectors/ — captured traffic, one file per case
│ └── testutil.pas — test harness helpers
└── units/ — compiled output (.ppu/.o), per target