// EFTPFile.bcpl // June 17, 1976 10:57 PM bk, jfs // last modified on June 3, 1979 11:47 AM by Taft // Copyright Xerox Corporation 1979 get "PupEFTP.decl" // that will also get pup-related stuff external [ //incoming procedures InitEFTPPackage; OpenEFTPSoc; CloseEFTPSoc ReceiveEFTPBlock; SendEFTPBlock; SendEFTPEnd; GetEFTPAbort Endofs; ReadBlock; WriteBlock; Puts; FilePos Ws; Wo; Wns; Wl; Zero // incoming statics, for common use, space allocated elsewhere EFTPLclPort; EFTPFrnPort; EFTPSocket; dsp //outgoing procedures EFTPSendFile; EFTPReceiveFile ] static [ // for use in this program, allocated in this module bytecount; totalbytecount packetcount; blockcount ] // These routines will be called from the FrontEnd, and may be // called more than once in the life of a program //----------------------------------------------------------------- let EFTPSendFile(diskstream, foreignport) = valof //----------------------------------------------------------------- [ OpenEFTPSoc(EFTPSocket, 0, foreignport) packetcount = 0 totalbytecount = 0 let maxBufferBytes = 2*256*6 //enough to buffer 6 disk pages let tempvec = vec 256*6 //in words let bytesLeftInBuffer = 0 let nextAddr = tempvec let result = nil // A loop, to read pages and send off blocks [Sendloop //See if we need more input if bytesLeftInBuffer eq 0 then [ //See if time to quit if Endofs(diskstream) then break bytesLeftInBuffer = FillFromDisk(diskstream, tempvec, maxBufferBytes) totalbytecount = totalbytecount + bytesLeftInBuffer nextAddr = tempvec //reset address pointer ] //data remains to be sent, at nextAddr packetcount = packetcount + 1 test bytesLeftInBuffer ls 512 ifso bytecount = bytesLeftInBuffer ifnot bytecount = 512 [dummyLoop result = SendEFTPBlock(EFTPSocket, nextAddr, bytecount, longBlockTimeout) if result eq EFTPTimeout & EFTPSocket>>EFTPSoc.TransferNotStarted then [ Wl("No answer yet, will keep trying...") loop ] break ]dummyLoop repeat //Something happened... if result ge 0 then [ bytesLeftInBuffer = bytesLeftInBuffer - bytecount nextAddr = nextAddr + bytecount/2 loop //it went properly ] //If we get here, had a real failure.... switchon result into [resultCase case EFTPTimeout: [ Ws("EFTPSend timed out while sending....") endcase ] case EFTPAbortSent: [ Ws("EFTPAbort had to be sent....") endcase ] case EFTPAbortReceived: [ Ws("EFTPAbort received while sending....") let temppbi = GetEFTPAbort(EFTPSocket) PrintAbortPBI(temppbi) endcase ] default: [ Ws("Unknown error from EFTPSend....") ] ]resultCase CloseEFTPSoc(EFTPSocket) resultis false //bail out ]Sendloop repeat //keep going, til you break out // All of the data has been sent; now do an end sequence result = SendEFTPEnd(EFTPSocket, longBlockTimeout) CloseEFTPSoc(EFTPSocket) test result ifso [ Wns(dsp, totalbytecount, 0, 10); Ws(" bytes sent. ") ] ifnot Ws("SendEnd sequence failed.....") resultis result ] //--------------------------------------------------------------- and FillFromDisk(diskstream, addr, maxbytes) = valof //--------------------------------------------------------------- [ //Returns the number of bytes read into the buffer // Watch out, Readblock returns a word count let bytecount = ReadBlock(diskstream, addr, maxbytes rshift 1) lshift 1 if bytecount eq 0 then resultis 0 // hit eof, quit early if bytecount < maxbytes then [ // got the last page; we have to do some hacking here let filepos = vec 1 FilePos(diskstream, filepos) //see if the files total byte count is odd if ((filepos!1) & 1) eq 1 then bytecount=bytecount-1 ] resultis bytecount ] //--------------------------------------------------------------- and DumpToDisk(diskstream, addr, bytecount) = valof //--------------------------------------------------------------- [ // Watch out for an odd bytecount WriteBlock(diskstream, addr, bytecount rshift 1) // May have failed to write one byte if (bytecount & 1) eq 1 then Puts(diskstream, addr>>Byte^bytecount) ] //--------------------------------------------------------------- and EFTPReceiveFile(diskstream, foreignport) = valof //--------------------------------------------------------------- [ //use EFTPLclPort, allocated elsewhere Zero(EFTPLclPort, lenPort) EFTPLclPort>>Port.socket^2 = socketEFTPReceive OpenEFTPSoc(EFTPSocket, EFTPLclPort, foreignport) packetcount = 0 totalbytecount = 0 let maxBufferBytes = 2*256*6 //6 disk pages let tempvec = vec 256*6 //in words let bytesLeftInBuffer = 0 let nextAddr = tempvec // a loop to get blocks, and write to the disk [Receiveloop //Make sure there is enough free space if maxBufferBytes-bytesLeftInBuffer ls 512 then [ totalbytecount = totalbytecount + bytesLeftInBuffer DumpToDisk(diskstream, tempvec, bytesLeftInBuffer) nextAddr = tempvec bytesLeftInBuffer = 0 ] let bytecount= ReceiveEFTPBlock(EFTPSocket, nextAddr, longBlockTimeout) if bytecount eq 0 then [ //Received an End.... if bytesLeftInBuffer gr 0 then DumpToDisk(diskstream, tempvec, bytesLeftInBuffer) totalbytecount = totalbytecount + bytesLeftInBuffer break // end has been properly received ] if bytecount gr 0 then [ // odd bytecounts are not legal, except in the last packet bytesLeftInBuffer = bytesLeftInBuffer + bytecount nextAddr = nextAddr + bytecount rshift 1 packetcount = packetcount + 1 loop ] //Some form of error return, figure it out here and punt switchon bytecount into [ReceiveCaseBlock case EFTPTimeout: [ if EFTPSocket>>EFTPSoc.TransferNotStarted then [ Wl("Nothing received yet, will keep listening...") loop ] Ws("Receiver timed out....") endcase ] case EFTPAbortSent: [ Ws("Abort had to be sent from receiver....") endcase ] case EFTPAbortReceived: [ Ws("EFTPAbort received while receiving....") let temppbi = GetEFTPAbort(EFTPSocket) PrintAbortPBI(temppbi) endcase ] case EFTPResetReceived: [ Ws("Asked to reset....[Not implemented here]") endcase ] ]ReceiveCaseBlock CloseEFTPSoc(EFTPSocket) resultis false ]Receiveloop repeat //End has been received, time to clean up and leave CloseEFTPSoc(EFTPSocket) Wns(dsp, totalbytecount, 0, 10); Ws(" bytes received. ") resultis true ] //--------------------------------------------------------------- and PrintAbortPBI(pbi) be //--------------------------------------------------------------- [ Puts(dsp, $*N); Wo(pbi>>PBI.pup.words^1); Ws(" - Abort: ") for i = 3 to (3 + (pbi>>PBI.pup.length-(pupOvBytes+2)) - 1) do Puts(dsp, pbi>>PBI.pup.bytes^i) ]