-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- RetrieveInit.mesa, Transport Mechanism: User: initial stages of mail retrieval/polling -- -- HGM: 15-Sep-85 8:03:07 -- Andrew Birrell 28-Apr-81 14:20:56 -- DIRECTORY BodyDefs USING [Connect, maxConnectLength, RName, Timestamp], Heap USING [systemZone], NameInfoDefs USING [Close, Enumerate, Expand, ExpandInfo, GetConnect, NameType], Process USING [DisableTimeout, InitializeCondition, InitializeMonitor], ProtocolDefs USING [Init, mailServerOutputSocket, MakeKey], PupDefs, PupTypes, RetrieveDefs USING [MBXState, ServerState], RetrieveXDefs USING [ GVClose, Handle, HandleObject, MBXData, MBXPtr, noMBX, NoteChangedMBX, SendPollProcess, SetMBXState], String USING [AppendString]; RetrieveInit: MONITOR LOCKS handle USING handle: RetrieveXDefs.Handle IMPORTS Heap, NameInfoDefs, Process, ProtocolDefs, PupDefs, RetrieveXDefs, String EXPORTS RetrieveDefs, RetrieveXDefs = BEGIN Handle: PUBLIC TYPE = RetrieveXDefs.Handle; HandleObject: PUBLIC TYPE = RetrieveXDefs.HandleObject; -- low-level utilities: -- KeepString: PROC [keep: LONG POINTER TO LONG STRING, str: LONG STRING] = BEGIN Heap.systemZone.FREE[keep]; IF str # NIL THEN BEGIN keep­ ¬ Heap.systemZone.NEW[StringBody[str.length]]; String.AppendString[keep­, str]; END; END; -- Global state control by the client: -- Create: PUBLIC PROCEDURE [ pollingInterval: CARDINAL, reportChanges: PROCEDURE [RetrieveDefs.MBXState] ¬ NIL] RETURNS [handle: Handle] = BEGIN handle ¬ Heap.systemZone.NEW[HandleObject]; BEGIN handle.MBXChain ¬ RetrieveXDefs.noMBX; handle.mbxKnown ¬ FALSE; handle.notEmptyMBXCount ¬ 0; handle.unknownMBXCount ¬ 0; -- handle.state ¬ ; handle.spareByte ¬ FALSE; -- handle.spareByteValue ¬; -- handle.header ¬ ; handle.currentMBX ¬ RetrieveXDefs.noMBX; handle.messages ¬ 0; handle.currentStr ¬ NIL; handle.ftpUser ¬ NIL; handle.mbxState ¬ badName; handle.polling ¬ FALSE; handle.pollWanted ¬ FALSE; handle.newPollWanted ¬ FALSE; handle.pollReplying ¬ FALSE; -- handle.mbxStateChange ¬; -- handle.pollCond ¬ ; handle.pollID ¬ [0, 1]; -- handle.sendPoll ¬ ; handle.pollStarted ¬ 0; handle.interval ¬ pollingInterval; handle.changes ¬ reportChanges; handle.userName ¬ NIL; handle.userPwd ¬ NIL; handle.userKey ¬ [0, 0, 0, 0]; END; Process.InitializeMonitor[@(handle.LOCK)]; Process.InitializeCondition[@(handle.pollCond), 0]; -- the polling process adjusts the timeout on handle.pollCond -- Process.InitializeCondition[@(handle.mbxStateChange), 0]; Process.DisableTimeout[@(handle.mbxStateChange)]; END; NewUser: PUBLIC ENTRY PROCEDURE [handle: Handle, user, password: LONG STRING] = BEGIN UnsetMailboxes[handle]; IF user = NIL OR user.length = 0 THEN RetrieveXDefs.SetMBXState[handle, badName] ELSE IF password = NIL OR password.length = 0 THEN RetrieveXDefs.SetMBXState[handle, badPwd] ELSE BEGIN KeepString[@(handle.userName), user]; KeepString[@(handle.userPwd), password]; handle.userKey ¬ ProtocolDefs.MakeKey[handle.userPwd]; RestartPoll[handle]; END; END; Destroy: PUBLIC PROCEDURE [handle: Handle] = BEGIN InnerDestroy[handle]; Heap.systemZone.FREE[@handle]; END; InnerDestroy: ENTRY PROCEDURE [handle: Handle] = INLINE BEGIN UnsetMailboxes[handle]; KeepString[@handle.userName, NIL]; KeepString[@handle.userPwd, NIL]; END; RestartPoll: INTERNAL PROCEDURE [handle: Handle] = BEGIN handle.pollID.b ¬ handle.pollID.b + 1; --to ignore old poll replies-- IF NOT handle.polling THEN handle.sendPoll ¬ FORK RetrieveXDefs.SendPollProcess[handle]; handle.polling ¬ handle.pollWanted ¬ TRUE; handle.newPollWanted ¬ TRUE; BROADCAST handle.pollCond; END; UnsetMailboxes: INTERNAL PROCEDURE [handle: Handle] = BEGIN IF handle.polling THEN BEGIN handle.pollWanted ¬ FALSE; BROADCAST handle.pollCond; WHILE handle.polling DO WAIT handle.pollCond ENDLOOP; JOIN handle.sendPoll; END; IF handle.currentMBX # RetrieveXDefs.noMBX THEN BEGIN RetrieveXDefs.GVClose[handle]; handle.currentMBX ¬ RetrieveXDefs.noMBX; END; handle.unknownMBXCount ¬ handle.notEmptyMBXCount ¬ 0; RetrieveXDefs.SetMBXState[handle, unknown]; handle.mbxKnown ¬ FALSE; UNTIL handle.MBXChain = RetrieveXDefs.noMBX DO BEGIN next: RetrieveXDefs.MBXPtr = handle.MBXChain.next; Heap.systemZone.FREE[@handle.MBXChain.name]; Heap.systemZone.FREE[@handle.MBXChain]; handle.MBXChain ¬ next; END; ENDLOOP; END; FindRegistryAndMailboxes: PUBLIC INTERNAL PROCEDURE [ handle: RetrieveXDefs.Handle] = BEGIN IF handle.MBXChain # RetrieveXDefs.noMBX THEN ERROR; FindGVMailboxes[handle]; END; FindGVMailboxes: INTERNAL PROC [handle: RetrieveXDefs.Handle] = BEGIN Work: INTERNAL PROCEDURE [site: BodyDefs.RName] RETURNS [done: BOOLEAN] = BEGIN done ¬ FALSE; FindAddress[handle, AddMBX[handle, site]]; END; info: NameInfoDefs.ExpandInfo = NameInfoDefs.Expand[handle.userName]; WITH info SELECT FROM allDown => RetrieveXDefs.SetMBXState[handle, cantAuth]; notFound => RetrieveXDefs.SetMBXState[handle, badName]; group => BEGIN -- this case include individual with forwarding NameInfoDefs.Close[members]; handle.mbxKnown ¬ TRUE; END; individual => BEGIN NameInfoDefs.Enumerate[sites, Work]; NameInfoDefs.Close[sites]; handle.mbxKnown ¬ TRUE; END; ENDCASE => ERROR; END; AddMBX: INTERNAL PROCEDURE [handle: RetrieveXDefs.Handle, site: BodyDefs.RName] RETURNS [this: RetrieveXDefs.MBXPtr] = BEGIN mbx: LONG POINTER TO RetrieveXDefs.MBXPtr ¬ @(handle.MBXChain); -- skip to end of mailbox chain -- WHILE mbx­ # RetrieveXDefs.noMBX DO mbx ¬ @(mbx­.next); ENDLOOP; mbx­ ¬ Heap.systemZone.NEW[RetrieveXDefs.MBXData]; this ¬ mbx­; this.name ¬ NIL; KeepString[@(this.name), site]; this.next ¬ RetrieveXDefs.noMBX; this.state ¬ unknown; this.replyWanted ¬ TRUE; handle.unknownMBXCount ¬ handle.unknownMBXCount + 1; IF handle.mbxState = allEmpty THEN RetrieveXDefs.SetMBXState[handle, userOK]; this.addrState ¬ unknown; END; FindAddress: PUBLIC INTERNAL PROC [ handle: RetrieveXDefs.Handle, mbx: RetrieveXDefs.MBXPtr] = BEGIN connect: BodyDefs.Connect = [BodyDefs.maxConnectLength]; IF mbx.addrState # unknown THEN ERROR; SELECT NameInfoDefs.GetConnect[mbx.name, connect] FROM individual => NULL; allDown => GOTO noAddr; group, notFound => GOTO badConnect; ENDCASE => ERROR; mbx­.addr.socket ¬ [0, 0]; PupDefs.GetPupAddress[ @(mbx­.addr), connect ! PupDefs.PupNameTrouble => IF code = errorFromServer THEN GOTO badConnect ELSE GOTO noAddr]; mbx.addr.socket ¬ ProtocolDefs.mailServerOutputSocket; mbx.addrState ¬ known; EXITS badConnect => { RetrieveXDefs.NoteChangedMBX[handle, mbx, empty]; mbx.addrState ¬ bad}; noAddr => NULL; END; WaitForMail: PUBLIC ENTRY PROCEDURE [handle: Handle] = BEGIN WHILE handle.mbxState # notEmpty DO WAIT handle.mbxStateChange ENDLOOP; END; ProtocolDefs.Init[]; END.