BinkP work

This commit is contained in:
mysticbbs 2013-03-24 05:45:47 -04:00
parent 76e9dcc96e
commit 6f4f9bb2cd
2 changed files with 237 additions and 53 deletions

View File

@ -1,14 +1,19 @@
Program BT;
Program BinkPoll;
{$I M_OPS.PAS}
Uses
cryptoldold,
DOS,
CryptNew,
m_DateTime,
m_FileIO,
m_Strings,
m_IO_Sockets,
m_Protocol_Queue;
m_Protocol_Queue,
bbs_Common;
Var
bbsConfig : RecConfig;
Const
M_NUL = 0;
@ -25,12 +30,8 @@ Const
M_DATA = 255;
BinkPMaxBufferSize = 30 * 1024;
BinkPTimeOut = 3000;
BinkPUseCRAMMD5 = True;
TempFileTime = 1363944820;
InboundPath : String = 'd:\dev\code\mystic\dls\';
Const
BinkCmdStr : Array[0..10] of String[4] = (
'NUL ',
@ -80,9 +81,14 @@ Type
);
TBinkP = Class
SetPassword : String;
SetBlockSize : Word;
SetTimeOut : Word;
Client : TIOSocket;
IsClient : Boolean;
UseMD5 : Boolean;
ForceMD5 : Boolean;
AuthState : TBinkAuthState;
TimeOut : LongInt;
TxState : TBinkTxState;
@ -96,7 +102,7 @@ Type
MD5Challenge : String;
FileList : TProtocolQueue;
Constructor Create (Var C: TIOSocket; Var FL: TProtocolQueue; IsCli, MD5: Boolean);
Constructor Create (Var C: TIOSocket; Var FL: TProtocolQueue; IsCli: Boolean; TOV: Word);
Destructor Destroy; Override;
Function GetDataStr : String;
@ -124,18 +130,20 @@ Begin
End;
End;
Constructor TBinkP.Create (Var C: TIOSocket; Var FL: TProtocolQueue; IsCli, MD5: Boolean);
Constructor TBinkP.Create (Var C: TIOSocket; Var FL: TProtocolQueue; IsCli: Boolean; TOV: Word);
Begin
Inherited Create;
SetTimeOut := TOV;
Client := C;
FileList := FL;
IsClient := IsCli;
UseMD5 := MD5;
UseMD5 := False;
ForceMD5 := False;
RxBufSize := 0;
RxState := RxNone;
TxState := TxNone;
TimeOut := TimerSet(BinkPTimeout);
TimeOut := TimerSet(SetTimeout);
NeedHeader := True;
HaveHeader := False;
MD5Challenge := '';
@ -173,7 +181,8 @@ Begin
Client.BufWriteStr(Char(Hi(DataSize)) + Char(Lo(DataSize)) + Char(CmdType) + CmdData + #0);
Client.BufFlush;
WriteLn ('Put Command Frame (', BinkCmdStr[CmdType], ') Data: ', CmdData);
WriteLn (' S ' + BinkCmdStr[CmdType] + ' ' + CmdData);
//WriteLn ('Put Command Frame (', BinkCmdStr[CmdType], ') Data: ', CmdData);
End;
Procedure TBinkP.SendDataFrame (Var Buf; BufSize: Word);
@ -191,7 +200,7 @@ Begin
Client.WriteBuf (LoChar, 1);
Client.WriteBuf (SendData[1], BufSize);
TimeOut := TimerSet(BinkPTimeOut);
TimeOut := TimerSet(SetTimeOut);
// WriteLn ('Put Data Frame (', BufSize, ')');
End;
@ -223,13 +232,15 @@ Begin
Client.ReadBuf(RxBuffer[InPos], 1);
If Client.Connected Then Begin
TimeOut := TimerSet(BinkPTimeOut);
TimeOut := TimerSet(SetTimeOut);
NeedHeader := False;
HaveHeader := True;
End;
Case RxFrameType of
Command : WriteLn ('Got Command Frame (', BinkCmdStr[RxCommand], ') Data: ', GetDataStr);
// Command : If (RxCommand = M_NUL) or (RxCommand = M_ERR) Then
// WriteLn (' R ', BinkCmdStr[RxCommand], ' ', GetDataStr);
Command : WriteLn (' R ', BinkCmdStr[RxCommand], ' ', GetDataStr);
// Data : WriteLn ('Got Data Frame (Read ', InPos, ' of ', RxBufSize, ')');
End;
End;
@ -240,7 +251,7 @@ Var
Str : String;
Count : LongInt;
Begin
WriteLn ('Begin Authentication');
//WriteLn ('Begin Authentication');
Repeat
DoFrameCheck;
@ -268,10 +279,10 @@ Begin
SendChallenge : Begin // Send MD5 digest
End;
SendWelcome : Begin
SendFrame (M_NUL, 'SYS Sector7');
SendFrame (M_NUL, 'ZYZ g00r00');
SendFrame (M_NUL, 'LOC Philadelphia, PA');
SendFrame (M_NUL, 'VER Mystic/1.10 binkp/1.1');
SendFrame (M_NUL, 'SYS ' + bbsConfig.BBSName);
SendFrame (M_NUL, 'ZYZ ' + bbsConfig.SysopName);
// SendFrame (M_NUL, 'LOC Philadelphia, PA');
SendFrame (M_NUL, 'VER Mystic/1.10 binkp/1.0');
If IsClient Then
AuthState := SendAddress
@ -280,26 +291,42 @@ Begin
End;
SendAddress : Begin
SendFrame (M_ADR, '55:268/212@mysticnet');
Str := '';
For Count := 1 to 30 Do
If strAddr2Str(bbsConfig.NetAddress[Count]) <> '0:0/0' Then Begin
If Str <> '' Then Str := Str + ' ';
Str := Str + strAddr2Str(bbsConfig.NetAddress[Count]);
If bbsConfig.NetDomain[Count] <> '' Then
Str := Str + '@' + bbsConfig.NetDomain[Count];
End;
SendFrame (M_ADR, Str);
AuthState := SendPassword;
End;
SendPassword : If HaveHeader Then Begin // wait for header to see if we support CRAMMD5
If UseMD5 And (MD5Challenge <> '') Then Begin
Str := 'password';
MD5Challenge := StrHex(MD5Challenge);
MD5Challenge := HexStr(HMAC_MD5(Str, MD5Challenge));
MD5Challenge := Digest2String(HMAC_MD5(String2Digest(MD5Challenge), SetPassword));
SendFrame (M_PWD, 'CRAM-MD5-' + MD5Challenge);
End Else
// if forced CRAMMD5 then error and exit otherwise...
SendFrame (M_PWD, 'password');
If ForceMD5 Then Begin
SendFrame (M_ERR, 'Required CRAM-MD5 authentication');
AuthState := AuthFailed;
End Else
SendFrame (M_PWD, SetPassword);
Client.BufFlush;
HaveHeader := False;
NeedHeader := True;
AuthState := WaitPwdOK;
If AuthState <> AuthFailed Then
AuthState := WaitPwdOK;
End;
WaitAddress : Begin
// get address
@ -331,11 +358,11 @@ Var
InTime : Cardinal;
FSize : Cardinal;
Begin
WriteLn ('Begin File Transfers');
//WriteLn ('Begin File Transfers');
RxState := RxWaitFile;
TxState := TxNextFile;
TimeOut := TimerSet(BinkPTimeOut);
TimeOut := TimerSet(SetTimeOut);
NeedHeader := True;
HaveHeader := False;
@ -369,8 +396,8 @@ Begin
InTime := strS2I(strWordGet(3, Str, ' '));
InPos := strS2I(strWordGet(4, Str, ' '));
If FileExist(InBoundPath + InFN) Then Begin
FSize := FileByteSize(InBoundPath + InFN);
If FileExist(bbsConfig.InBoundPath + InFN) Then Begin
FSize := FileByteSize(bbsConfig.InBoundPath + InFN);
// fix timestamp and escape filen
@ -385,7 +412,7 @@ Begin
End;
End;
Assign (InFile, InBoundPath + InFN);
Assign (InFile, bbsConfig.InBoundPath + InFN);
Reset (InFile, 1);
If IoResult <> 0 Then ReWrite (InFile, 1);
@ -477,29 +504,172 @@ Begin
If Client.Connected Then Client.BufFlush;
End;
Procedure PollNode (Var Queue: TProtocolQueue; Var EchoNode: RecEchoMailNode);
Var
BinkP : TBinkP;
Client : TIOSocket;
Queue : TProtocolQueue;
Port : Word;
Begin
Queue := TProtocolQueue.Create;
Client := TIOSocket.Create;
Client.FTelnetClient := False;
Client.FTelnetServer := False;
Queue.Add('d:\s7\echomail\inbound\t\', '0019ff33.mo0');
Queue.Add('d:\s7\echomail\inbound\t\', '0019ff33.mo1');
Queue.Add('d:\s7\echomail\inbound\t\', '0019ff33.mo2');
Write ('- Connecting to ', EchoNode.binkHost, ': ');
BinkP := TBinkP.Create(Client, Queue, True, False);
Port := strS2I(strWordGet(2, EchoNode.binkHost, ':'));
Client.Connect ('localhost', 24554);
If Port = 0 Then Port := 24554;
If Not Client.Connect (strWordGet(1, EchoNode.binkHost, ':'), Port) Then Begin
WriteLn ('UNABLE TO CONNECT');
Client.Free;
Exit;
End;
WriteLn ('CONNECTED!');
BinkP := TBinkP.Create(Client, Queue, True, EchoNode.binkTimeOut * 100);
BinkP.SetPassword := EchoNode.binkPass;
BinkP.SetBlockSize := EchoNode.binkBlock;
BinkP.UseMD5 := EchoNode.binkMD5 > 0;
BinkP.ForceMD5 := EchoNode.binkMD5 = 2;
If BinkP.DoAuthentication Then
BinkP.DoTransfers;
BinkP.DoTransfers
Else
WriteLn ('- Unable to authenticate');
BinkP.Free;
Client.Free;
Queue.Free;
End;
Function GetFTNFlowName (Dest: RecEchoMailAddr) : String;
Begin
Result := strI2H((Dest.Net SHL 16) OR Dest.Node);
End;
Procedure ScanOutbound;
Var
DirInfo : SearchRec;
FLOFile : Text;
EchoFile : File of RecEchoMailNode;
EchoNode : RecEchoMailNode;
Queue : TProtocolQueue;
Str : String;
FN : String;
Path : String;
Matched : Boolean;
Begin
WriteLn ('Scanning configured Echomail nodes...');
WriteLn;
FindFirst (bbsConfig.OutboundPath + '*.?lo', AnyFile, DirInfo);
While DosError = 0 Do Begin
Write ('- Found ', DirInfo.Name, ' -> Send Type: ');
Case UpCase(JustFileExt(DirInfo.Name)[1]) of
'C' : WriteLn ('Crash');
'D' : WriteLn ('Direct');
'H' : Begin
WriteLn ('Hold - SKIPPING');
FindNext (DirInfo);
Continue;
End;
Else
WriteLn ('Normal');
End;
Matched := False;
Assign (EchoFile, bbsConfig.DataPath + 'echonode.dat');
{$I-} Reset (EchoFile); {$I+}
If IoResult <> 0 Then Begin
WriteLn ('- Unable to match .FLO with configured Echomail node');
FindNext (DirInfo);
Continue;
End;
While Not Eof(EchoFile) And Not Matched Do Begin
Read (EchoFile, EchoNode);
Matched := (strUpper(JustFileName(DirInfo.Name)) = strUpper(GetFTNFlowName(EchoNode.Address))) and EchoNode.Active and (EchoNode.ProtType = 0);
End;
Close (EchoFile);
If Not Matched Then Begin
WriteLn ('- Unable to match .FLO with configured Echomail node');
FindNext (DirInfo);
Continue;
End;
Queue := TProtocolQueue.Create;
Assign (FLOFile, bbsConfig.OutboundPath + DirInfo.Name);
Reset (FLOFile);
While Not Eof(FLOFile) Do Begin
ReadLn (FLOFile, Str);
If (Str = '') or (Str[1] = '!') Then Continue;
Str := strStripB(Copy(Str, 2, 255), ' ');
FN := JustFile(Str);
Path := JustPath(Str);
Queue.Add (Path, FN);
End;
Close (FLOFile);
WriteLn('- Queued ', Queue.QSize, ' files (', Queue.QFSize, ' bytes) to ', strAddr2Str(EchoNode.Address));
If Queue.QSize > 0 Then
PollNode(Queue, Echonode);
Queue.Free;
FindNext (DirInfo);
End;
FindClose (DirInfo);
End;
Var
CF : File of RecConfig;
Begin
WriteLn;
WriteLn ('BINKPOLL Version ' + mysVersion);
WriteLn;
Assign (CF, '\s7\mystic.dat');
{$I-} Reset(CF); {$I+}
If IoResult <> 0 Then Begin
WriteLn ('Unable to read MYSTIC.DAT');
Halt(1);
End;
Read (CF, bbsConfig);
Close (CF);
If bbsConfig.DataChanged <> mysDataChanged Then Begin
WriteLn ('Mystic VERSION mismatch');
Halt(1);
End;
ScanOutbound;
End.

View File

@ -25,9 +25,10 @@ Type
End;
TProtocolQueue = Class
QSize : Word;
QPos : Word;
QData : Array[1..QueueMaxSize] of TProtocolQueuePTR;
QFSize : Cardinal;
QSize : Word;
QPos : Word;
QData : Array[1..QueueMaxSize] of TProtocolQueuePTR;
Constructor Create;
Destructor Destroy; Override;
@ -44,8 +45,9 @@ Constructor TProtocolQueue.Create;
Begin
Inherited Create;
QSize := 0;
QPos := 0;
QFSize := 0;
QSize := 0;
QPos := 0;
End;
Destructor TProtocolQueue.Destroy;
@ -57,7 +59,7 @@ Function TProtocolQueue.Add (fPath, fName: String) : Boolean;
Var
F : File;
Begin
Add := False;
Result := False;
If (QSize = QueueMaxSize) Then Exit;
@ -76,11 +78,20 @@ Begin
If IoResult = 0 Then Begin
QData[QSize]^.FileSize := FileSize(F);
QData[QSize]^.Status := QueuePending;
Close(F);
End Else
QData[QSize]^.Status := QueueNoFile;
Add := True;
Inc (QFSize, QData[QSize]^.FileSize);
Close(F);
End Else Begin
Dispose (QData[QSize]);
Dec (QSize);
Exit;
// QData[QSize]^.Status := QueueNoFile;
End;
Result := True;
End;
Procedure TProtocolQueue.Delete (Idx: Word);
@ -88,6 +99,8 @@ Var
Count : Word;
Begin
If QData[Idx] <> NIL Then Begin
Dec (QFSize, QData[QSize]^.FileSize);
Dispose (QData[Idx]);
For Count := Idx To QueueMaxSize - 1 Do
@ -123,8 +136,9 @@ Begin
QData[Count] := NIL;
End;
QSize := 0;
QPos := 0;
QFSize := 0;
QSize := 0;
QPos := 0;
End;
End.