// PupTestEcho.bcpl
// Copyright Xerox Corporation 1979, 1982
// Last modified February 15, 1982 5:30 PM by Boggs
get "Pup0.decl"
get "Pup1.decl"
get "PupTest.decl"
external
[
//outgoing procedures
EchoServer; EchoUser
//incoming procedures
Puts; Endofs; MoveBlock; Zero
GetPBI; ReleasePBI; ExchangePorts; HLookup
OpenLevel1Socket; CompletePup; CloseLevel1Socket
SetTimer; TimerHasExpired; Enqueue; Dequeue; Block
OtherSpigot; PrintPort; OpenPort
Divide32x16; BlockEq; DoubleIncrement
PutTemplate; Ws
//incoming statics
dsp; keys
pupRT; maxPupDataBytes
Cmmd; checksums; checkdata; sendPort; checkBuffer
]
manifest
[
socketEcho = 5
typeEchoMe = 1
typeImAnEcho = 2
]
structure Byte↑0,0 byte
//----------------------------------------------------------------------------
let EchoServer() be //a context
//----------------------------------------------------------------------------
[
let serverSoc = vec lenPupSoc
OpenLevel1Socket(serverSoc, table [ 0; 0; socketEcho ])
[
Block() repeatuntil serverSoc>>PupSoc.iQ.head ne 0
let pbi = Dequeue(lv serverSoc>>PupSoc.iQ)
test pbi>>PBI.pup.type eq typeEchoMe
ifnot OtherSpigot(pbi)
ifso
[
ExchangePorts(pbi)
//compute checksum on outgoing packet
// if incoming packet computed it.
serverSoc>>PupSoc.doChecksum =
pbi!(lenPBIOverhead+(pbi>>PBI.pup.length-1) rshift 1) ne -1
CompletePup(pbi, typeImAnEcho)
serverSoc>>PupSoc.doChecksum = true
Puts(dsp, $$)
]
] repeat
]
//----------------------------------------------------------------------------
and EchoUser() be
//----------------------------------------------------------------------------
[
let userSoc = vec lenPupSoc
test Cmmd eq 0
ifnot [ Cmmd = 0; OpenLevel1Socket(userSoc, 0, sendPort) ]
ifso unless OpenPort("Echo to: ", userSoc, 0, socketEcho) return
Ws("- Checksums "); Ws(checksums ? "enabled", "disabled")
Ws(", Data checking "); Ws(checkdata? "enabled*N", "disabled*N")
userSoc>>PupSoc.doChecksum = checksums
PrintPort(lv userSoc>>PupSoc.lclPort); Ws(" -> ")
let rte = HLookup(pupRT, userSoc>>PupSoc.frnPort.net)
if rte ne 0 & rte>>RTE.hops ne 0 then
PutTemplate(dsp, "[$UO#$UO#] -> ",
rte>>RTE.ndb>>NDB.localNet, rte>>RTE.host)
PrintPort(lv userSoc>>PupSoc.frnPort)
let out = vec 6; Zero(out, 6)
let in, inTimes100 = out+2, out+4
let numDataBytes, numDataWords, pupid = maxPupDataBytes, 0, 0
while Endofs(keys) & Cmmd eq 0 do
[
let pbi = GetPBI(userSoc)
//packets get longer by 1 byte each time.
numDataBytes = numDataBytes +1
if numDataBytes gr maxPupDataBytes then numDataBytes = 0
numDataWords = (numDataBytes +1)/2
pupid = pupid +1
pbi>>PBI.pup.id↑1 = 0
pbi>>PBI.pup.id↑2 = pupid
MoveBlock(lv pbi>>PBI.pup.bytes, checkBuffer, numDataWords)
CompletePup(pbi, typeEchoMe, numDataBytes+pupOvBytes)
DoubleIncrement(out)
let timeOut = nil; SetTimer(lv timeOut, 150) //1.5 seconds
[
Block() repeatuntil userSoc>>PupSoc.iQ.head %
TimerHasExpired(lv timeOut)
pbi = Dequeue(lv userSoc>>PupSoc.iQ)
if pbi eq 0 then [ Puts(dsp, $?); break ]
if pbi>>PBI.pup.type ne typeImAnEcho then
[ OtherSpigot(pbi); loop ]
DoubleIncrement(in); DoubleIncrement(inTimes100, 100)
//note that if there is a 'garbage' byte at the end of the packet,
// it has a known value and we check it.
if checkdata & numDataBytes gr 0 then
unless BlockEq(checkBuffer, lv pbi>>PBI.pup.bytes, numDataWords) do
Ws("Data compare error*N")
test pbi>>PBI.pup.id↑2 eq pupid
ifnot [ Puts(dsp, $#); ReleasePBI(pbi) ]
ifso [ Puts(dsp, $!); ReleasePBI(pbi); break ]
] repeat
]
CloseLevel1Socket(userSoc)
PutTemplate(dsp, "*nOut: $ED, In: $ED", out, in)
while out!0 ne 0 do //scale so denominator is ls 2↑16
[ Divide32x16(inTimes100, 10); Divide32x16(out, 10) ]
Divide32x16(inTimes100, out!1)
PutTemplate(dsp, ", $UD%", inTimes100!1)
]