// CopyDiskNet1.bcpl // Copyright Xerox Corporation 1979, 1980, 1981 // Last modified December 11, 1981 7:35 PM by Boggs get "Pup.decl" get "CopyDisk.decl" get "CopyDiskNet.decl" external [ // outgoing procedures NetCompatible; NetPrintDA; NetCompare NetReader; NetWriter; NetPrintBlock; PrintPort GetBlock; PutBlock; PutString // incoming procedures from OS and packages BSPReadBlock; BSPWriteBlock; BSPForceOutput Dequeue; Enqueue; Block; ReadCalendar Allocate; Free; Zero; MoveBlock; Usc Gets; Puts; PutTemplate; CopyString DoubleIncrement; DoubleDifference; Divide32x16 // incoming procedures from CopyDisk GetBuffer; ReleaseBuffer; FatalError; Wss // incoming statics sysZone; CtxRunning; ctxQ debugFlag; dsp; controlLock; seriousErrors userName; userPass; connName; connPass ] //---------------------------------------------------------------------------- let NetCompatible(srcSS, snkSS) = //---------------------------------------------------------------------------- ((srcSS>>SS.compatible eq NetCompatible? snkSS, srcSS)>>SS.compatible)(srcSS, snkSS) //---------------------------------------------------------------------------- and NetPrintDA(stream, ss) be //---------------------------------------------------------------------------- (ss>>SS.otherSS>>SS.printDA)(stream, ss>>SS.otherSS) //---------------------------------------------------------------------------- and NetCompare(ss, buf1, buf2) = //---------------------------------------------------------------------------- (ss>>SS.otherSS>>SS.compare)(ss>>SS.otherSS, buf1, buf2) //---------------------------------------------------------------------------- and PrintPort(stream, port) be //---------------------------------------------------------------------------- [ Puts(stream, $[) if port>>Port.net then PutTemplate(stream, "$UO#", port>>Port.net) PutTemplate(stream, "$UO#", port>>Port.host) if port>>Port.socket↑1 % port>>Port.socket↑2 then PutTemplate(stream, "$EUO", lv port>>Port.socket) Puts(stream, $]) ] //---------------------------------------------------------------------------- and NetReader(ctx) be //a context //---------------------------------------------------------------------------- [ let ss = ctx>>CDCtx.ss test controlLock eq user ifnot PutString(yes, 0, "ready") ifso [ PutBlock(ss>>SS.dp, hereAreDiskParams) PutBlock(ss>>SS.tp, retrieveDisk) unless GetYesNo() eq yes do FatalError() ] let bits = vec 1; Zero(bits, 2) let start = vec 1; ReadCalendar(start) [ let buffer = GetBuffer(false) unless GetBlock(lv buffer>>NetBuffer.length) do FatalError() Enqueue(ss>>SS.outputQ, buffer) if buffer>>NetBuffer.type ne hereIsDiskPage break DoubleIncrement(bits, buffer>>NetBuffer.length lshift 4) ] repeat let stop = vec 1; ReadCalendar(stop) Divide32x16(bits, DoubleDifference(stop, start)) if debugFlag then PutTemplate(dsp, "*N$EUD bits/sec", bits) if controlLock eq user then [ PutBlock(table [ 2; sendErrors ]) if ss>>SS.errors ne 0 then Free(sysZone, ss>>SS.errors) ss>>SS.errors = GetBlock() ] ss>>NetSS.doneFlag = true Block() repeat ] //---------------------------------------------------------------------------- and NetWriter(ctx) be //a context //---------------------------------------------------------------------------- [ let ss = ctx>>CDCtx.ss test controlLock eq user ifnot PutString(yes, 0, "Here it comes") ifso [ PutBlock(ss>>SS.dp, hereAreDiskParams) PutBlock(ss>>SS.tp, storeDisk) unless GetYesNo() eq yes do FatalError() ] let bits = vec 1; Zero(bits, 2) let start = vec 1; ReadCalendar(start) [ Block() repeatwhile (ss>>SS.inputQ)!0 eq 0 let buffer = Dequeue(ss>>SS.inputQ) unless PutBlock(lv buffer>>NetBuffer.length) do FatalError() ReleaseBuffer(buffer) if buffer>>NetBuffer.type ne hereIsDiskPage break DoubleIncrement(bits, buffer>>NetBuffer.length lshift 4) ] repeat BSPForceOutput(ss>>NetSS.soc) let stop = vec 1; ReadCalendar(stop) Divide32x16(bits, DoubleDifference(stop, start)) if debugFlag then PutTemplate(dsp, "*N$EUD bits/sec", bits) if controlLock eq user then [ PutBlock(table [ 2; sendErrors ]) if ss>>SS.errors ne 0 then Free(sysZone, ss>>SS.errors) ss>>SS.errors = GetBlock() ] ss>>NetSS.doneFlag = true Block() repeat ] //---------------------------------------------------------------------------- and GetBlock(cd, complainIfEnd; numargs na) = valof //---------------------------------------------------------------------------- // Eats comments. // Uses 'cd' if it is supplied; it better be big enough! [ if na ls 1 then cd = 0 let callerOwnsCD = cd ne 0 if na ls 2 then complainIfEnd = true let ss = CtxRunning>>CDCtx.ss let stream = ss>>NetSS.stream [ let length = Gets(stream) lshift 8 length = Gets(stream) + length if Usc(length, 1500) gr 0 then //Gets returns -1 if stream has closed [ if complainIfEnd then Wss(dsp, "*N[GetBlock] unreasonable length") resultis 0 ] unless callerOwnsCD do cd = Allocate(sysZone, length) cd>>CD.length = length if BSPReadBlock(stream, cd+1, 0, (length-1) lshift 1) ne (length-1) lshift 1 then [ Wss(dsp, "*N[GetBlock] BSPReadBlock failed") unless callerOwnsCD do Free(sysZone, cd) resultis 0 ] unless cd>>CD.type eq hereIsDiskPage do NetPrintBlock(ss, cd, false) if cd>>CD.type eq comment then [ unless callerOwnsCD do Free(sysZone, cd); loop ] resultis cd ] repeat ] //---------------------------------------------------------------------------- and GetYesNo() = valof //---------------------------------------------------------------------------- // Call only from NetReader and NetWriter because it calls FatalError. [ let cd = GetBlock(); if cd eq 0 then FatalError() let yesNo = cd>>CD.type Free(sysZone, cd) if yesNo ne yes & yesNo ne no then FatalError("*N[GetYesNo] Unexpected block type $D", yesNo) resultis yesNo ] //---------------------------------------------------------------------------- and PutBlock(cd, type; numargs na) = valof //---------------------------------------------------------------------------- [ let ss = CtxRunning>>CDCtx.ss if na gr 1 then cd>>CD.type = type let byteLen = cd>>CD.length lshift 1 if BSPWriteBlock(ss>>NetSS.stream, cd, 0, byteLen) ne byteLen then [ Wss(dsp, "*N[PutBlock] BSPWriteBlock failed") resultis false ] unless cd>>CD.type eq hereIsDiskPage do [ BSPForceOutput(ss>>NetSS.soc) NetPrintBlock(ss, cd, true) ] resultis true ] //---------------------------------------------------------------------------- and PutString(type, code, string) be //---------------------------------------------------------------------------- [ let length = lenCodeString + string>>String.length rshift 1 +1 let cd = Allocate(sysZone, length) cd>>CD.length = length cd>>CD.codeString.code = code CopyString(lv cd>>CD.codeString.string, string) PutBlock(cd, type, true) Free(sysZone, cd) ] //---------------------------------------------------------------------------- and NetPrintBlock(ss, cd, put; numargs na) be //---------------------------------------------------------------------------- [ let type = cd>>CD.type if na gr 2 then [ unless debugFlag % (not put & (type eq version % type eq comment % type eq no)) return Puts(dsp, $*N) if debugFlag then PutTemplate(dsp, "$C: ", (put? (controlLock eq user? $U, $S), (controlLock eq user? $S, $U))) ] if debugFlag % na ls 2 then put = false switchon type into [ case version: case no: [ if debugFlag then PutTemplate(dsp, "[$S] <$D> ", (type eq version? "Version", "No"), cd>>CD.codeString.code) unless put do Wss(dsp, lv cd>>CD.codeString.string) if type eq no then seriousErrors = true endcase ] case yes: [ PutTemplate(dsp, "[Yes] <$D> $S", cd>>CD.codeString.code, lv cd>>CD.codeString.string) endcase ] case sendDiskParamsR: case sendDiskParamsW: [ PutTemplate(dsp, "[SendDiskParams$C] $S", (type eq sendDiskParamsR? $R, $W), lv cd>>CD.string) endcase ] case hereAreDiskParams: [ Wss(dsp, "[HereAreDiskParams] "); docase -1 ] case storeDisk: [ Wss(dsp, "[StoreDisk] "); docase -1 ] case retrieveDisk: [ Wss(dsp, "[RetrieveDisk] "); docase -1 ] case endOfTransfer: [ Wss(dsp, "[EndOfTransfer] "); endcase ] case sendErrors: [ Wss(dsp, "[SendErrors] "); endcase ] case hereAreErrors: [ if debugFlag & na gr 2 then Wss(dsp, "[HereAreErrors] ") docase -1 ] case comment: [ if debugFlag then Wss(dsp, "[Comment] ") unless put do Wss(dsp, lv cd>>CD.string) endcase ] case login: [ Wss(dsp, "[Login] ") let p = lv cd>>CD.string p = PrintNamePass(p, "uNam") p = PrintNamePass(p, "uPsw") p = PrintNamePass(p, "cNam") p = PrintNamePass(p, "cPsw") endcase ] case -1: [ let otherSS = ss>>SS.otherSS if otherSS ne 0 then (otherSS>>SS.printBlock)(otherSS, cd) endcase ] ] ] //---------------------------------------------------------------------------- and PrintNamePass(p, string) = valof //---------------------------------------------------------------------------- [ if p>>String.length ne 0 then PutTemplate(dsp, "$S: $S ", string, p) resultis p + p>>String.length rshift 1 +1 ]