// PupServEFTP.bcpl -- Pup Server EFTP routines

// Last modified March 19, 1980  12:20 AM by Boggs

get "Streams.d"
get "PupEFTP.decl"
get "PupServEftp.decl"

external
[
// outgoing procedures
PupServSend; PupServReceive

// incoming procedures
OpenEFTPSoc; CloseEFTPSoc
ReceiveEFTPBlock; SendEFTPBlock; SendEFTPEnd
GetPBI; ReleasePBI; Zero
OpenFile; DeleteFile; RenameFile; FilePos
Closes; Endofs; ReadBlock; WriteBlock; Puts
Dismiss; SetTimer; TimerHasExpired

dsp; Ws
]

//----------------------------------------------------------------------------
let PupServSend(eftp) = valof
//----------------------------------------------------------------------------
[
// Ws("*NSend "); Ws(eftp>>EFTP.realName); Puts(dsp, $*N)

let soc = vec lenEFTPSoc
OpenEFTPSoc(soc, eftp>>EFTP.lclPort, eftp>>EFTP.frnPort)
let tempPBI = GetPBI(soc)
let buffer = lv tempPBI>>PBI.pup
let bcnt, timeout = 0, nil

let stream = OpenFile(eftp>>EFTP.realName, ksTypeReadOnly, charItem,
 0, eftp>>EFTP.fp)
if stream ne 0 then
   [
   until Endofs(stream) % bcnt ls 0 do
      [
      bcnt = ReadBlock(stream, buffer, 256) lshift 1
      if (FilePos(stream) & 1) eq 1 then bcnt = bcnt -1
      if bcnt eq 0 break
      test soc>>EFTPSoc.SeqNum eq 0
         ifso
            [
            timeout = eftp>>EFTP.timeOut1
            soc>>EFTPSoc.currentTimeout = 5
            ]
         ifnot timeout = eftp>>EFTP.timeOut2
      bcnt = SendEFTPBlock(soc, buffer, bcnt, timeout)
      ]
   if bcnt ge 0 then
      bcnt = SendEFTPEnd(soc, eftp>>EFTP.timeOut2)? 0, EFTPTimeout
   Closes(stream)
   ]

ReleasePBI(tempPBI)
CloseEFTPSoc(soc)
resultis stream ne 0 & bcnt eq 0
]

//----------------------------------------------------------------------------
and PupServReceive(eftp) = valof
//----------------------------------------------------------------------------
[
// Ws("*NReceive "); Ws(eftp>>EFTP.realName); Puts(dsp, $*N)

let soc = vec lenEFTPSoc
OpenEFTPSoc(soc, eftp>>EFTP.lclPort, eftp>>EFTP.frnPort)
let tempPBI = GetPBI(soc)
let buffer = lv tempPBI>>PBI.pup
let bcnt, stream = nil, nil

let timer = nil; SetTimer(lv timer, 6000)  // 1 minute
   [
   (eftp>>EFTP.proc1)(soc)
   bcnt = ReceiveEFTPBlock(soc, buffer, eftp>>EFTP.timeOut1)
   ] repeatuntil bcnt gr 0 % TimerHasExpired(lv timer)

if bcnt gr 0 then
   [
   stream = OpenFile(eftp>>EFTP.tempName, ksTypeWriteOnly, charItem)
   if stream ne 0 then
      [
         [
         WriteBlock(stream, buffer, bcnt rshift 1)
         if (bcnt & 1) eq 1 then Puts(stream, buffer!(bcnt rshift 1) rshift 8)
         bcnt = ReceiveEFTPBlock(soc, buffer, eftp>>EFTP.timeOut2)
         ] repeatuntil bcnt le 0
      if bcnt eq 0 then (eftp>>EFTP.proc2)(stream)
      Closes(stream)
      if bcnt eq 0 then
         [
         Dismiss(1)
         DeleteFile(eftp>>EFTP.realName)
         Dismiss(1)
         RenameFile(eftp>>EFTP.tempName, eftp>>EFTP.realName)
         compileif alto then
            [
            Zero(eftp>>EFTP.fp, 5)
            Closes(OpenFile(eftp>>EFTP.realName, ksTypeReadOnly,
             0, 0, eftp>>EFTP.fp))
            ]
         Dismiss(1)
         ]
      ]
   ]

ReleasePBI(tempPBI)
CloseEFTPSoc(soc)
resultis bcnt ge 0 & stream ne 0
]