DIRECTORY BasicTime USING [GMT], IO USING [CreateStream, CreateStreamProcs, EndOf, PutChar, STREAM, StreamProcs, UnsafeBlock, UnsafeGetBlock, UnsafePutBlock], PupStream USING [CloseReason, ConsumeMark, SendMark, StreamClosing], Rope USING [ROPE], STP USING [Access, CredentialsErrors, Error, FileErrors, Type], STPOps USING [ CheckConnection, ErrorIfNextNotEOC, ErrorIfNextNotYes, GenerateProtocolError, GenerateStreamClosingError, GetHereIsAndPList, Handle, LookAtMark, MakeRemoteName, markEOC, markHereIsFile, markHereIsPList, markNewStore, markNo, markRetrieve, markYes, MyGetMark, NameToPList, Object, ResetPList, PList, PutCommand, PutPList, RemoteObject, RemoteStream, SelectError, SetByteSize, SetCreateTime, SetFileType, SmashClosed, UserStateToPList]; STPsC: CEDAR PROGRAM IMPORTS IO, PupStream, STP, STPOps EXPORTS STP = BEGIN OPEN PupStream, STPOps; Object: PUBLIC TYPE = STPOps.Object; remoteStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[ variety: $inputOutput, class: $FTP, endOf: EndOf, unsafeGetBlock: UnsafeGetBlock, putChar: PutChar, unsafePutBlock: UnsafePutBlock, close: DeleteRemoteStream]; CreateRemoteStream: PUBLIC PROCEDURE [ stp: STPOps.Handle, file: Rope.ROPE, access: STP.Access, fileType: STP.Type, creation: BasicTime.GMT] RETURNS [stream: IO.STREAM] = BEGIN rs: STPOps.RemoteStream = NEW[STPOps.RemoteObject _ [access: access, state: initial, stp: stp]]; CheckConnection[stp]; IF stp.remoteStream # NIL THEN ERROR STP.Error[stp, accessError, "Remote Stream Exists"]; ResetPList[stp.plist]; UserStateToPList[stp]; NameToPList[stp.plist, file, alto]; SetFileType[stp, fileType]; IF access = write THEN { STPOps.SetCreateTime[stp, creation]; SetByteSize[stp, fileType]}; IF fileType = text THEN stp.plist[eolConversion] _ "CR"; stp.remoteStream _ rs; RETURN[IO.CreateStream[remoteStreamProcs, rs]] END; NextFileName: PUBLIC PROCEDURE [remoteStream: IO.STREAM] RETURNS [file: Rope.ROPE] = BEGIN rs: RemoteStream _ ConvertHandle[remoteStream]; reason: PupStream.CloseReason; IF rs.access # read THEN ERROR STP.Error[rs.stp, accessError, NIL]; BEGIN ENABLE PupStream.StreamClosing => {reason _ why; GOTO streamClosing}; SELECT rs.state FROM initial => RequestRetrieve[rs]; confirm => BEGIN PutCommand[rs.stp, markNo, 0C, "No Thanks"]; IF LookAtMark[rs.stp] = markEOC THEN {[] _ MyGetMark[rs.stp]; rs.state _ end} ELSE GetHereIsAndPList[rs.stp]; END; data => BEGIN ErrorIfNextNotYes[rs.stp]; IF LookAtMark[rs.stp] = markEOC THEN {[] _ MyGetMark[rs.stp]; rs.state _ end} ELSE {GetHereIsAndPList[rs.stp]; rs.state _ confirm}; END; complete => IF LookAtMark[rs.stp] = markEOC THEN {[] _ MyGetMark[rs.stp]; rs.state _ end} ELSE {GetHereIsAndPList[rs.stp]; rs.state _ confirm}; end => NULL; ENDCASE; EXITS streamClosing => GenerateStreamClosingError[rs.stp, reason]; END; RETURN[IF rs.state = end THEN NIL ELSE MakeRemoteName[rs.stp.plist, alto]] END; ConvertHandle: PROCEDURE [h: IO.STREAM] RETURNS [rs: RemoteStream] = INLINE BEGIN RETURN[NARROW[h.streamData]] END; UnsafeGetBlock: UNSAFE PROC[self: IO.STREAM, block: IO.UnsafeBlock] RETURNS[nBytesRead: INT] = UNCHECKED BEGIN rs: RemoteStream _ ConvertHandle[self]; reason: PupStream.CloseReason; BEGIN ENABLE PupStream.StreamClosing => {reason _ why; GOTO streamClosing}; IF rs.state # data THEN BEGIN StartRemote[rs, read]; IF rs.state = end THEN RETURN[0]; END; nBytesRead _ rs.stp.byteStream.UnsafeGetBlock[block]; IF rs.stp.byteStream.EndOf[] THEN BEGIN rs.stp.mark _ PupStream.ConsumeMark[rs.stp.byteStream]; rs.stp.gotMark _ TRUE; SetupForNextOrEnd[rs.stp]; END; EXITS streamClosing => {rs.state _ end; GenerateStreamClosingError[rs.stp, reason]}; END; END; EndOf: PROC[self: IO.STREAM] RETURNS[BOOL] = BEGIN rs: RemoteStream _ ConvertHandle[self]; RETURN[rs.state # data OR rs.stp.byteStream.EndOf[]] END; PutChar: PROC[self: IO.STREAM, char: CHAR] = BEGIN rs: RemoteStream _ ConvertHandle[self]; reason: PupStream.CloseReason; BEGIN ENABLE PupStream.StreamClosing => {reason _ why; GOTO streamClosing}; IF rs.state # data THEN StartRemote[rs, write]; rs.stp.byteStream.PutChar[char]; EXITS streamClosing => {rs.state _ end; GenerateStreamClosingError[rs.stp, reason]}; END; END; UnsafePutBlock: PROC[self: IO.STREAM, block: IO.UnsafeBlock] = BEGIN rs: RemoteStream _ ConvertHandle[self]; reason: PupStream.CloseReason; BEGIN ENABLE PupStream.StreamClosing => {reason _ why; GOTO streamClosing}; IF rs.state # data THEN StartRemote[rs, write]; rs.stp.byteStream.UnsafePutBlock[block]; EXITS streamClosing => {rs.state _ end; GenerateStreamClosingError[rs.stp, reason]}; END; END; DeleteRemoteStream: PROC[self: IO.STREAM, abort: BOOL _ FALSE] = BEGIN rs: RemoteStream _ ConvertHandle[self]; stp: STPOps.Handle = rs.stp; {ENABLE UNWIND => stp.remoteStream _ NIL; IF rs.access = read THEN {IF rs.state # end THEN SmashClosed[stp]} -- in mid-transfer ELSE SELECT rs.state FROM initial => NULL; data => { PutCommand[rs.stp, markYes, 0C, "Transfer Completed" ! PupStream.StreamClosing => CONTINUE]; -- OK, if closed in advance ErrorIfNextNotYes[rs.stp]; ErrorIfNextNotEOC[rs.stp]}; confirm, complete, end => NULL; -- worry about later ENDCASE; stp.remoteStream _ NIL;}; END; SetupForNextOrEnd: PROCEDURE [stp: STPOps.Handle] = BEGIN ErrorIfNextNotYes[stp]; SELECT LookAtMark[stp] FROM markEOC => {[] _ MyGetMark[stp]; stp.remoteStream.state _ end}; markHereIsPList => stp.remoteStream.state _ complete; ENDCASE => GenerateProtocolError[stp, badMark, MyGetMark[stp]]; END; RequestRetrieve: PROCEDURE [rs: RemoteStream] = BEGIN PutPList[rs.stp, markRetrieve]; GetHereIsAndPList[rs.stp ! STP.Error => SELECT code FROM IN STP.CredentialsErrors, IN STP.FileErrors => rs.state _ end; ENDCASE]; rs.state _ confirm; END; StartRemote: PROCEDURE [rs: RemoteStream, access: STP.Access] = BEGIN reason: PupStream.CloseReason; IF rs.access # access THEN ERROR STP.Error[rs.stp, accessError, "Remote stream access Error"]; BEGIN ENABLE PupStream.StreamClosing => {reason _ why; GOTO streamClosing}; SELECT access FROM read => BEGIN IF rs.state = initial THEN RequestRetrieve[rs]; IF rs.state = complete THEN { IF LookAtMark[rs.stp] = markEOC THEN {rs.state _ end; RETURN} ELSE GetHereIsAndPList[rs.stp]; rs.state _ confirm}; IF rs.state = confirm THEN BEGIN mark: [0..256); PutCommand[rs.stp, markYes, 0C, "Yes, please"]; SELECT (mark _ MyGetMark[rs.stp]) FROM markHereIsFile => NULL; markNo => {rs.state _ complete; SelectError[rs.stp, "He says NO", mark]}; ENDCASE => SelectError[rs.stp, "HereIsFile Expected", mark]; END; END; write => BEGIN PutPList[rs.stp, markNewStore]; GetHereIsAndPList[rs.stp]; PupStream.SendMark[rs.stp.byteStream, markHereIsFile]; END; ENDCASE => ERROR; rs.state _ data; EXITS streamClosing => GenerateStreamClosingError[rs.stp, reason]; END; END; END. of STPsC vfile: STPsC.mesa - Simple/Stream Transfer Protocol Remote Stream stuff in here Edited by: Smokey 16-Jul-81 17:24:59 Sandman 17-Aug-81 11:32:55 Karlton 9-Dec-81 18:36:06 SHayes 11-Sep-81 16:15:34 Bruce 20-Oct-81 11:24:17 Johnsson 16-Dec-81 17:39:42 Daniels 21-Sep-82 13:06:31 Davirro 24-Sep-82 10:45:37 Schmidt January 20, 1983 7:10 pm Andrew Birrell, June 1, 1983 5:39 pm Last Edited by: Schroeder, August 10, 1983 5:56 pm Last Edited by: MBrown, September 12, 1983 8:37 pm Procedures implementing STP interface Procedures for Remote streams Utilities Ê.˜Jšœ3™3Jšœ™Jšœ ™ Jšœ ™ Jšœ!™!Jšœ!™!Jšœ ™ Jšœ'™'Jšœ"™"Jšœ!™!Jšœ!™!Jšœ ™ J™$J™2J™2šÏk ˜ Jšœ œœ˜Jšœœ3œ<˜}Jšœ œ5˜DJšœœœ˜Jšœœ6˜?šœœ˜J˜6J˜MJ˜EJ˜LJ˜DJ˜BJšœ˜—J˜—šœœ˜Jšœœ œ˜"Jšœœ˜ Jšœœ˜J˜Jšœœœ˜$J˜—Jšœ&™&˜šœœœœ˜=J˜#J˜ J˜J˜J˜J˜J˜—šÏnœœ œ˜&Jš œœ œœœ˜eJšœ œœ˜Jš˜JšœœC˜`J˜Jš œœœœœ1˜YJ˜J˜J˜#J˜šœœ˜J˜$J˜—Jšœœ!˜8J˜Jšœœ%˜.Jšœ˜J˜—š ž œœ œœœ˜8Jšœ œ˜Jš˜J˜/J˜Jš œœœœœ˜CJšœœ+œ˜Lšœ ˜J˜˜ Jš˜J˜,Jšœœ*˜NJšœ˜Jšœ˜—˜Jš˜J˜Jšœœ*˜NJšœ1˜5Jšœ˜—˜ Jšœœ*˜NJšœ1˜5—Jšœœ˜ Jšœ˜—š˜J˜<—Jšœ˜Jš œœœœœ$˜JJšœ˜J˜——Jšœ™J˜˜š ž œ œœœœ˜KJšœœœœ˜'J˜—šžœœœœœ œœ œ ˜hJš˜Jšœ'˜'J˜š˜Jšœ+œ˜Ešœ˜Jš˜J˜Jšœœœ˜!Jšœ˜—Jšœ5˜5Jšœ˜šœ˜ Jšœ7˜7Jšœœ˜Jšœ˜Jšœ˜—š˜J˜N——Jšœ˜Jšœ˜J˜—š žœœ œœœ˜,Jš˜Jšœ'˜'Jšœœ˜4Jšœ˜—J˜šžœœ œœ˜,Jš˜Jšœ'˜'J˜Jš˜Jšœ+œ˜EJšœœ˜/J˜ JšœO˜TJšœ˜Jšœ˜—J˜š žœœœœ œ˜>Jš˜Jšœ'˜'J˜Jš˜Jšœ+œ˜EJšœœ˜/Jšœ(˜(JšœO˜TJšœ˜Jšœ˜J˜—š žœœ œ œœ˜@Jš˜Jšœ'˜'J˜Jšœœœœ˜)Jš œœœœÏc˜Ušœœ ˜Jšœ œ˜˜ ˜4JšœœŸ˜C—J˜J˜—JšœœŸ˜4Jšœ˜—Jšœœ˜Jšœ˜J˜J˜——Jšœ ™ ˜šžœ œ˜3Jš˜J˜šœ˜J˜?J˜5Jšœ8˜?—Jšœ˜J˜—šžœ œ˜/Jš˜J˜šœœ ˜'šœ˜Jšœœœœ˜?Jšœ˜ ——J˜Jšœ˜J˜—šž œ œœ ˜?Jš˜J˜šœ˜Jšœœ:˜C—Jš˜Jšœ+œ˜Ešœ˜˜Jš˜Jšœœ˜0šœœ˜Jšœœœ˜=Jšœ0˜4—šœœ˜Jš˜J˜J˜/šœ˜&Jšœœ˜J˜IJšœ5˜<—Jšœ˜—Jšœ˜—˜Jš˜J˜J˜J˜6Jšœ˜—Jšœœ˜—J˜Jšœ=˜BJšœ˜Jšœ˜J˜—Jšœ ˜ J˜J˜J˜——…—†%*