DIRECTORY BasicTime USING[ Now ], GVBasics USING[ Connect, MakeKey, RName, Timestamp ], GVNames USING[ ConnectInfo, Expand, ExpandInfo, GetConnect, NameType, RListHandle ], PupDefs, PupTypes, GVRetrieve USING[ MBXState, ServerState, ServerType ], GVRetrieveInternal USING[ GVClose, Handle, HandleObject, MBXData, MBXPtr, noMBX, NoteChangedMBX, SendPollProcess, SetMBXState ], Rope USING[ Find, Length, ROPE, Substr ]; RetrieveInit: CEDAR MONITOR LOCKS handle USING handle: GVRetrieveInternal.Handle IMPORTS BasicTime, GVBasics, GVNames, PupDefs, GVRetrieveInternal, Rope EXPORTS GVRetrieve, GVRetrieveInternal = { Handle: PUBLIC TYPE = GVRetrieveInternal.Handle; HandleObject: PUBLIC TYPE = GVRetrieveInternal.HandleObject; Create: PUBLIC PROC [ pollingInterval: CARDINAL, reportChanges: PROC [GVRetrieve.MBXState] _ NIL ] RETURNS [ handle: Handle ] = { handle _ NEW[HandleObject]; { handle.MBXChain _ GVRetrieveInternal.noMBX; handle.mbxKnown _ FALSE; handle.notEmptyMBXCount _ 0; handle.unknownMBXCount _ 0; handle.registry _ GV; handle.spareByte _ FALSE; handle.currentMBX _ GVRetrieveInternal.noMBX; handle.messages _ 0; handle.currentStr _ NIL; handle.mbxState _ badName; handle.polling _ FALSE; handle.pollWanted _ FALSE; handle.newPollWanted _ FALSE; handle.pollReplying _ FALSE; handle.pollID _ [0,1]; handle.pollStarted _ BasicTime.Now[]; handle.interval _ pollingInterval; handle.changes _ reportChanges; handle.userName _ NIL; handle.userPwd _ NIL; handle.userKey _ [0,0,0,0]; }; }; NewUser: PUBLIC ENTRY PROC [ handle: Handle, user, password: Rope.ROPE] = { UnsetMailboxes[handle]; IF user.Length[] = 0 THEN GVRetrieveInternal.SetMBXState[handle, badName] ELSE IF password.Length[] = 0 THEN GVRetrieveInternal.SetMBXState[handle, badPwd] ELSE { handle.userName _ user; handle.userPwd _ password; handle.userKey _ GVBasics.MakeKey[handle.userPwd]; RestartPoll[handle]; }; }; Close: PUBLIC ENTRY PROC [handle: Handle] = { UnsetMailboxes[handle]; handle.userName _ NIL; handle.userPwd _ NIL; }; RestartPoll: INTERNAL PROC [handle: Handle] = { handle.pollID.b _ handle.pollID.b + 1; --to ignore old poll replies-- IF NOT handle.polling THEN handle.sendPoll _ FORK GVRetrieveInternal.SendPollProcess[handle]; handle.polling _ handle.pollWanted _ TRUE; handle.newPollWanted _ TRUE; BROADCAST handle.pollCond; }; UnsetMailboxes: INTERNAL PROC [handle: Handle] = { IF handle.polling THEN { sendPoll: PROCESS _ NIL; handle.pollWanted _ FALSE; BROADCAST handle.pollCond; WHILE handle.polling DO WAIT handle.pollCond ENDLOOP; sendPoll _ handle.sendPoll; IF sendPoll # NIL THEN TRUSTED { handle.sendPoll _ NIL; JOIN sendPoll; }; }; IF handle.currentMBX # GVRetrieveInternal.noMBX THEN { GVRetrieveInternal.GVClose[handle]; handle.currentMBX _ GVRetrieveInternal.noMBX; }; handle.unknownMBXCount _ handle.notEmptyMBXCount _ 0; GVRetrieveInternal.SetMBXState[handle, unknown]; handle.mbxKnown _ FALSE; handle.MBXChain _ GVRetrieveInternal.noMBX; }; FindRegistryAndMailboxes: PUBLIC INTERNAL PROC [handle: GVRetrieveInternal.Handle] = { length: INT = handle.userName.Length[]; firstRegChar: INT = handle.userName.Find["."]+1; -- =0 if no dot found registry: Rope.ROPE = handle.userName.Substr[firstRegChar, length-firstRegChar]; { called: BOOLEAN _ FALSE; Work: INTERNAL PROC [addr:PupDefs.PupAddress] RETURNS [stop:BOOLEAN] = { IF called THEN { handle.registry _ GV; stop _ TRUE } ELSE { handle.registry _ MTP; called _ TRUE; stop _ FALSE }; }; handle.registry _ GV; -- default if registry isn't in NLS [] _ PupDefs.EnumeratePupAddresses[registry, Work ! PupDefs.PupNameTrouble => IF code = errorFromServer THEN CONTINUE ELSE GOTO noReg ]; }; IF handle.MBXChain # GVRetrieveInternal.noMBX THEN ERROR; IF handle.registry = MTP THEN { FindAddress[handle, AddMBX[handle, registry]]; handle.mbxKnown _ TRUE; } ELSE FindGVMailboxes[handle]; EXITS noReg => GVRetrieveInternal.SetMBXState[handle, cantAuth]; }; FindGVMailboxes: INTERNAL PROC [handle: GVRetrieveInternal.Handle] = { IF handle.registry # GV THEN ERROR ELSE TRUSTED { info: GVNames.ExpandInfo = GVNames.Expand[handle.userName]; WITH info SELECT FROM allDown => GVRetrieveInternal.SetMBXState[handle, cantAuth]; notFound => GVRetrieveInternal.SetMBXState[handle, badName]; group => { handle.mbxKnown _ TRUE; }; individual => { FOR site: GVNames.RListHandle _ sites, site.rest UNTIL site = NIL DO FindAddress[handle, AddMBX[handle, site.first] ] ENDLOOP; handle.mbxKnown _ TRUE; }; ENDCASE => ERROR; }; }; AddMBX: INTERNAL PROC [handle: GVRetrieveInternal.Handle, site: GVBasics.RName] RETURNS [this: GVRetrieveInternal.MBXPtr] = { last: GVRetrieveInternal.MBXPtr _ NIL; FOR old: GVRetrieveInternal.MBXPtr _ handle.MBXChain, old.next UNTIL old = NIL DO last _ old ENDLOOP; this _ NEW[GVRetrieveInternal.MBXData]; IF last = NIL THEN handle.MBXChain _ this ELSE last.next _ this; this.name _ site; this.type _ IF site.Find["."] < 0 THEN MTP ELSE GV; this.next _ GVRetrieveInternal.noMBX; this.state _ unknown; this.replyWanted _ TRUE; handle.unknownMBXCount _ handle.unknownMBXCount + 1; IF handle.mbxState = allEmpty THEN GVRetrieveInternal.SetMBXState[handle, userOK]; this.addrState _ unknown; }; FindAddress: PUBLIC INTERNAL PROC [handle: GVRetrieveInternal.Handle, mbx: GVRetrieveInternal.MBXPtr] = { connect: GVBasics.Connect; info: GVNames.ConnectInfo; IF mbx.addrState # unknown THEN ERROR; IF mbx.type = GV THEN { [info, connect] _ GVNames.GetConnect[mbx.name]; SELECT info FROM individual => NULL; allDown => GOTO noAddr; group, notFound => GOTO badConnect; ENDCASE => ERROR; } ELSE connect _ mbx.name; mbx^.addr _ PupDefs.GetPupAddress[[0,0], connect ! PupDefs.PupNameTrouble => IF code = errorFromServer THEN GOTO badConnect ELSE GOTO noAddr ]; mbx.addrState _ known; EXITS badConnect => { GVRetrieveInternal.NoteChangedMBX[handle,mbx,empty]; mbx.addrState _ bad }; noAddr => NULL; }; WaitForMail: PUBLIC ENTRY PROC [handle: Handle] = { WHILE handle.mbxState # notEmpty DO WAIT handle.mbxStateChange ENDLOOP; }; }. RetrieveInit.mesa: initial stages of mail retrieval/polling Copyright c 1985 by Xerox Corporation. All rights reserved. Birrell, August 29, 1983 11:54 am Russ Atkinson (RRA) May 21, 1985 4:31:04 pm PDT Global state control by the client: handle.state _ ; handle.spareByteValue _; handle.header _ ; handle.mbxStateChange _; handle.pollCond _ ; handle.sendPoll _ ; RRA: Wait for the sendPoll process to finish. Also show that we do not need another JOIN. this case includes individual with forwarding skip to end of mailbox chain Κ―˜codešœ;™;Kšœ Οmœ1™