Files
comet/test_frame.pas
Ken Johnson bade0eb593 Comet 1.00 - Initial commit: complete standalone FidoNet TCP mailer
Standalone FidoNet mailer daemon implementing the Comet protocol
(TCP variant of the Nova protocol family) with BinkP/1.1 fallback.
Written in Free Pascal for DOS/Win/OS2/Linux/FreeBSD.

15 source files, ~10K lines:
- Protocol: length-prefixed frames, SHA-256/384/512, CRC-32,
  bidirectional transfer with sliding window, adaptive block sizing
- Session: own TCP handshake with BinkP auto-detection on port 26638
- Outbound: BSO (Binkley), FrontDoor, D'Bridge format support
- Daemon: multi-session with thread pool, outbound scanner
- Paths: DOS<->Linux bridge with case-insensitive lookup, drive mapping
- Config: INI-style with heavily documented sample (COMET.SAM)

All 17 Nova interop bug fixes baked in from the start.
18/18 tests passing (CRC-32, SHA-256/384/512, frame encode/decode).
2026-03-29 20:02:37 -07:00

160 lines
4.3 KiB
ObjectPascal

{
Frame layer test - verify encode/decode round-trip via loopback TCP.
Creates a listening socket, connects to it, sends frames, receives them.
}
program test_frame;
{$mode objfpc}{$H+}
uses
SysUtils, cometdef, cometcrc, comettcp, cometfrm, cometlog;
var
ListenSock, ClientSock, ServerSock: TCometSocket;
Info: TCometConnInfo;
Rx, ClientRx: TCometFrameRx;
Frame: TCometFrame;
Payload: array[0..255] of Byte;
I: Integer;
Ret: Integer;
Tests, Passed: Integer;
Port: Word;
begin
Tests := 0;
Passed := 0;
Port := 47391; { Arbitrary test port }
CometLogSetConsole(True);
CometLogSetDebug(True);
{ Create listener }
ListenSock := CometTcpListen('127.0.0.1', Port);
if ListenSock = COMET_TCP_INVALID then
begin
WriteLn('FAIL: Cannot create listener on port ', Port);
Halt(1);
end;
WriteLn('Listener on port ', Port);
{ Connect client }
ClientSock := CometTcpConnect('127.0.0.1', Port, 5000);
if ClientSock = COMET_TCP_INVALID then
begin
WriteLn('FAIL: Cannot connect to listener');
CometTcpClose(ListenSock);
Halt(1);
end;
WriteLn('Client connected');
{ Accept on server side }
if not CometTcpAccept(ListenSock, Info) then
begin
WriteLn('FAIL: Accept failed');
CometTcpClose(ClientSock);
CometTcpClose(ListenSock);
Halt(1);
end;
ServerSock := Info.Socket;
WriteLn('Server accepted from ', Info.RemoteIP, ':', Info.RemotePort);
{ Initialize receiver }
CometFrameRxInit(Rx);
{ Test 1: Empty payload (IDLE packet) }
Inc(Tests);
Write('Test 1: IDLE (empty payload)... ');
if CometFrameSend(ClientSock, NPKT_IDLE, 0, nil, 0) then
begin
CometTcpWaitData(ServerSock, 1000);
Ret := CometFrameRecv(ServerSock, Rx, Frame);
if (Ret = NPKT_IDLE) and (Frame.Seq = 0) and (Frame.PayLen = 0) then
begin
WriteLn('OK');
Inc(Passed);
end
else
WriteLn('FAIL: ret=', Ret, ' seq=', Frame.Seq, ' paylen=', Frame.PayLen);
end
else
WriteLn('FAIL: send error');
{ Test 2: Small payload (INIT packet with 10 bytes) }
Inc(Tests);
Write('Test 2: INIT (10 bytes)... ');
for I := 0 to 9 do Payload[I] := Byte(I + $41); { 'A'..'J' }
if CometFrameSend(ClientSock, NPKT_INIT, 1, @Payload[0], 10) then
begin
CometTcpWaitData(ServerSock, 1000);
Ret := CometFrameRecv(ServerSock, Rx, Frame);
if (Ret = NPKT_INIT) and (Frame.Seq = 1) and (Frame.PayLen = 10) and
(Frame.Payload[0] = $41) and (Frame.Payload[9] = $4A) then
begin
WriteLn('OK');
Inc(Passed);
end
else
WriteLn('FAIL: ret=', Ret, ' seq=', Frame.Seq, ' paylen=', Frame.PayLen);
end
else
WriteLn('FAIL: send error');
{ Test 3: 256 byte payload (DATA packet) }
Inc(Tests);
Write('Test 3: DATA (256 bytes)... ');
for I := 0 to 255 do Payload[I] := Byte(I);
if CometFrameSend(ClientSock, NPKT_DATA, 42, @Payload[0], 256) then
begin
{ May need multiple recv calls for larger frames }
CometTcpWaitData(ServerSock, 1000);
Ret := N_NOPKT;
for I := 0 to 9 do
begin
Ret := CometFrameRecv(ServerSock, Rx, Frame);
if Ret <> N_NOPKT then Break;
CometTcpWaitData(ServerSock, 100);
end;
if (Ret = NPKT_DATA) and (Frame.Seq = 42) and (Frame.PayLen = 256) and
(Frame.Payload[0] = 0) and (Frame.Payload[255] = 255) then
begin
WriteLn('OK');
Inc(Passed);
end
else
WriteLn('FAIL: ret=', Ret, ' seq=', Frame.Seq, ' paylen=', Frame.PayLen);
end
else
WriteLn('FAIL: send error');
{ Test 4: Bidirectional - server sends back to client }
Inc(Tests);
Write('Test 4: Bidirectional... ');
if CometFrameSend(ServerSock, NPKT_INITACK, 99, @Payload[0], 5) then
begin
CometFrameRxReset(Rx); { Reset for new direction }
CometTcpWaitData(ClientSock, 1000);
CometFrameRxInit(ClientRx);
Ret := CometFrameRecv(ClientSock, ClientRx, Frame);
if (Ret = NPKT_INITACK) and (Frame.Seq = 99) and (Frame.PayLen = 5) then
begin
WriteLn('OK');
Inc(Passed);
end
else
WriteLn('FAIL: ret=', Ret);
CometFrameRxDone(ClientRx);
end
else
WriteLn('FAIL: send error');
{ Cleanup }
CometFrameRxDone(Rx);
CometTcpClose(ServerSock);
CometTcpClose(ClientSock);
CometTcpClose(ListenSock);
WriteLn;
WriteLn(Passed, '/', Tests, ' frame tests passed.');
if Passed <> Tests then Halt(1);
end.