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 = BEGIN Handle: PUBLIC TYPE = GVRetrieveInternal.Handle; HandleObject: PUBLIC TYPE = GVRetrieveInternal.HandleObject; -- Global state control by the client: -- Create: PUBLIC PROCEDURE[ pollingInterval: CARDINAL, reportChanges: PROCEDURE[GVRetrieve.MBXState] _ NIL ] RETURNS[ handle: Handle ] = BEGIN handle _ NEW[HandleObject]; BEGIN 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]; END; END; NewUser: PUBLIC ENTRY PROCEDURE[ handle: Handle, user, password: Rope.ROPE] = BEGIN UnsetMailboxes[handle]; IF user.Length[] = 0 THEN GVRetrieveInternal.SetMBXState[handle, badName] ELSE IF password.Length[] = 0 THEN GVRetrieveInternal.SetMBXState[handle, badPwd] ELSE BEGIN handle.userName _ user; handle.userPwd _ password; handle.userKey _ GVBasics.MakeKey[handle.userPwd]; RestartPoll[handle]; END; END; Close: PUBLIC ENTRY PROC[handle: Handle] = BEGIN UnsetMailboxes[handle]; handle.userName _ NIL; 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 GVRetrieveInternal.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; TRUSTED{ JOIN handle.sendPoll }; END; IF handle.currentMBX # GVRetrieveInternal.noMBX THEN BEGIN GVRetrieveInternal.GVClose[handle]; handle.currentMBX _ GVRetrieveInternal.noMBX; END; handle.unknownMBXCount _ handle.notEmptyMBXCount _ 0; GVRetrieveInternal.SetMBXState[handle, unknown]; handle.mbxKnown _ FALSE; handle.MBXChain _ GVRetrieveInternal.noMBX; END; FindRegistryAndMailboxes: PUBLIC INTERNAL PROC[handle: GVRetrieveInternal.Handle] = BEGIN 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]; BEGIN called: BOOLEAN _ FALSE; Work: INTERNAL PROC[addr:PupDefs.PupAddress] RETURNS[stop:BOOLEAN] = BEGIN IF called THEN { handle.registry _ GV; stop _ TRUE } ELSE { handle.registry _ MTP; called _ TRUE; stop _ FALSE }; END; handle.registry _ GV; -- default if registry isn't in NLS -- [] _ PupDefs.EnumeratePupAddresses[registry, Work ! PupDefs.PupNameTrouble => IF code = errorFromServer THEN CONTINUE ELSE GOTO noReg ]; END; IF handle.MBXChain # GVRetrieveInternal.noMBX THEN ERROR; IF handle.registry = MTP THEN BEGIN FindAddress[handle, AddMBX[handle, registry]]; handle.mbxKnown _ TRUE; END ELSE FindGVMailboxes[handle]; EXITS noReg => GVRetrieveInternal.SetMBXState[handle, cantAuth]; END; FindGVMailboxes: INTERNAL PROC[handle: GVRetrieveInternal.Handle] = BEGIN IF handle.registry # GV THEN ERROR ELSE TRUSTED BEGIN info: GVNames.ExpandInfo = GVNames.Expand[handle.userName]; WITH info SELECT FROM allDown => GVRetrieveInternal.SetMBXState[handle, cantAuth]; notFound => GVRetrieveInternal.SetMBXState[handle, badName]; group => BEGIN -- this case includes individual with forwarding -- handle.mbxKnown _ TRUE; END; individual => BEGIN FOR site: GVNames.RListHandle _ sites, site.rest UNTIL site = NIL DO FindAddress[handle, AddMBX[handle, site.first] ] ENDLOOP; handle.mbxKnown _ TRUE; END; ENDCASE => ERROR; END; END; AddMBX: INTERNAL PROCEDURE[handle: GVRetrieveInternal.Handle, site: GVBasics.RName] RETURNS[this: GVRetrieveInternal.MBXPtr] = BEGIN last: GVRetrieveInternal.MBXPtr _ NIL; -- skip to end of mailbox chain -- 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; END; FindAddress: PUBLIC INTERNAL PROC[handle: GVRetrieveInternal.Handle, mbx: GVRetrieveInternal.MBXPtr] = BEGIN connect: GVBasics.Connect; info: GVNames.ConnectInfo; IF mbx.addrState # unknown THEN ERROR; IF mbx.type = GV THEN BEGIN [info, connect] _ GVNames.GetConnect[mbx.name]; SELECT info FROM individual => NULL; allDown => GOTO noAddr; group, notFound => GOTO badConnect; ENDCASE => ERROR; END 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; END; WaitForMail: PUBLIC ENTRY PROCEDURE[handle: Handle] = BEGIN WHILE handle.mbxState # notEmpty DO WAIT handle.mbxStateChange ENDLOOP; END; END. *GrapevineUser (Cedar): initial stages of mail retrieval/polling RetrieveInit.mesa Andrew Birrell 28-Apr-81 14:20:56 Last Edited by: Birrell, August 29, 1983 11:54 am handle.state _ ; handle.spareByteValue _; handle.header _ ; handle.mbxStateChange _; handle.pollCond _ ; handle.sendPoll _ ; Êü˜Jšœ?™?Jšœ™Jšœ"™"J™1šÏk ˜ Jšœ œ˜Jšœ œ'˜5JšœœG˜TJ˜J˜ Jšœ œ&˜6Jšœœh˜€Jšœœœ ˜)J˜—š œœœœœ"˜PJšœ@˜GJšœ!˜(J˜—Jš˜J˜Jšœœœ˜0Jšœœœ#˜