2 Commits

Author SHA1 Message Date
24a2350a51 Live interop fixes against the existing Comet daemon
End-to-end test against the canonical Comet daemon
(comet 1.2.1, both bbsnode2 and a local instance from
build/linux/comet) surfaced three wire-level mismatches.
fpc-comet now talks the existing daemon's protocol exactly:

  1) BOTH sides emit NPKT_INITACK.  My driver only had
     the inbound (answerer) sending INITACK.  The existing
     daemon waits for the originator's INITACK after
     sending its own; without it the answerer hangs in
     its post-INIT wait loop and times out (TimeoutSecs).
     SendOurInitAck now fires on the outbound side too,
     after authentication completes.

  2) Transfer-phase frame routing widened.  The peer can
     race ahead and send transfer frames (FINFO end-of-
     batch, FINFOACK, etc.) before we've fully transitioned
     out of cmpAuth.  Driver now routes transfer-typed
     frames to the xfer engine in any post-auth phase
     (cmpAuth / cmpKeyExchange / cmpTransfer / cmpShutdown)
     instead of dropping them with "unhandled frame in
     phase 3" warnings.

  3) TComFsProvider.NextOutbound now computes SHA-256 of
     each outbound file before returning the TCometSendItem.
     Previously left Item.SHA256 as zeros, which the receiver
     compared against its own freshly-computed hash and
     correctly reported "SHA-256 mismatch" -- the bytes
     transferred fine, the hash advertised in FINFO didn't.
     Added HashFileSHA256 helper.

example_outbound also takes:
  - CM_AKA env var for outbound local AKA (e.g. "1:213/725")
  - CM_PRIVKEY env var for ED25519 private-key seed (hex)
  - CM_LOG=trace for verbose diagnostics
  - CM_REQUEST="*.txt" to FREQ files from peer
  - CM_LIST="*" to LSTREQ a listing
  - File argument now optional (handshake-only is allowed)

Validated against bbsnode2 (1:213/721, FreeBSD x64,
unmodified canonical Comet daemon code at port 26638) AND
against a local Linux build of the same code:

  bbsnode2 dial:   ED25519 verified, 82-byte file accepted
                   + EOF acked, clean cmpDone, byte-identical
                   landing in inbound dir.
  local dial:      NOPWD path, same end-to-end success.

12 unit tests still pass; all 7 cross-targets clean.

That closes the wire-format gap.  fpc-comet v0.1.0 is
interop-validated against the canonical implementation.
2026-04-22 14:58:36 -07:00
f96002ead0 Examples + auth-resolution fixes (NOPWD via capability + OnPostAuth)
examples/example_outbound + example_inbound are working
reference consumers using TComTcpTransport + TComFsProvider.
Verified end-to-end on real TCP sockets with both auth paths:

  NOPWD (no password configured on either side):
    outbound -> auth: NOPWD ; inbound -> authenticated as NOPWD
    (capability) ; HELLO.TXT lands in unsecure dir.

  Plain password (CM_PASSWORD=SecretPwd on outbound,
  same configured on inbound):
    outbound -> auth: plain ; inbound -> authenticated as
    plain-password ; OnPostAuth fires with auth=4 ; routing
    sets InboundOverrideDir -> secure ; HELLO.TXT lands in
    secure dir.  Byte-identical receive both paths.

Three protocol-correctness fixes that came out of the
end-to-end testing:

1) NOPWD signalling.  cm.driver was sending the literal
   string "-" in the INIT Password field for NOPWD -- a
   BinkP convention I borrowed by mistake.  The existing
   Comet daemon has always used the COPT_NOPWD capability
   bit + an empty Password string.  fpc-comet now matches
   that convention exactly; this is an interop bug fix,
   not a protocol change.

2) Outbound credential plumbing.  TCometSessionConfig grows
   a Password field.  cm.driver.BuildOurInit puts that into
   the INIT Password when Direction = cmDirOutbound and
   the field is non-empty; everything else sends empty.

3) OnPostAuth + InboundOverrideDir.  cm.driver now invokes
   OnPostAuth once auth resolves (and before INITACK on the
   inbound side), threads the InboundDir override into a
   per-session FInboundOverrideDir, and exposes it via
   InboundOverrideDir to cm.xfer, which passes it to
   provider.OpenForReceive as the OverrideDir argument.
   This wires the secure / unsecure routing pattern the
   examples demonstrate.

ResolveAuth was rewritten to mirror the existing daemon's
intent:
  - outbound: trusts answerer's INITACK (existing daemon
    pattern), sets AuthMethod for telemetry based on its
    own configured credential + negotiated COPT_NOPWD.
  - inbound: plain password match wins ; otherwise NOPWD
    accepted only if (no per-node password configured)
    AND COPT_NOPWD negotiated ; otherwise auth fails.

All 4 unit tests still pass; all 7 cross-targets clean.
2026-04-22 12:53:07 -07:00