DIRECTORY DebuggerFormat USING [LabelChecksum], DiskFace USING [Label, Type], Endian USING [FFromInt, FWORD, IntFromF], PrincOps, PrincOpsUtils USING [LongCopy], Process USING [EnableAborts], PupBuffer USING [Buffer], Pup USING [Address, nullAddress], PupHop USING [GetHop, Hop], PupName USING [NameLookup, Error], PupSocket USING [AllocBuffer, CreateEphemeral, Destroy, FreeBuffer, Get, GetLocalAddress, GetUserBytes, Put, SetUserHWords, Socket], PupType USING [teledebugAck, teledebugGoReply, teledebugGoRequest, Type], PupWKS USING [teleSwat], Rope USING [ROPE], TeledebugProtocol, WorldVM USING [], WVMPrivate; WVMRemote: MONITOR IMPORTS DebuggerFormat, Endian, PrincOpsUtils, Process, PupHop, PupName, PupSocket EXPORTS WorldVM, WVMPrivate = { Machine: PUBLIC TYPE = Pup.Address; ReadRemoteCore: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, mempage: WVMPrivate.PageNumber] RETURNS[map: WVMPrivate.MapEntry, ok: BOOL] = { in: LONG POINTER TO TeledebugProtocol.CoreFetchAcknowledgement; out: LONG POINTER TO TeledebugProtocol.CoreFetchRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; out _ LOOPHOLE[@b.body]; out^ _ [page: mempage]; b _ SendAndReceive[b, pageFetchRequest, TeledebugProtocol.coreFetchRequestSize]; in _ LOOPHOLE[@b.body]; IF PupWords[b] # TeledebugProtocol.coreFetchAcknowledgementSize OR WVMPrivate.PageNumber[in.page] # mempage THEN { PupSocket.FreeBuffer[b]; LOOP }; data^ _ LOOPHOLE[in.data, WVMPrivate.PageData]; map.state.flags _ LOOPHOLE[in.flags, PrincOps.PageState].flags; PupSocket.FreeBuffer[b]; ok _ LOOPHOLE[in.flags, PrincOps.PageState].flags#PrincOps.flagsVacant; EXIT ENDLOOP; Unlock[]; }; WriteRemoteCore: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, mempage: WVMPrivate.PageNumber, map: WVMPrivate.MapEntry] RETURNS[readOnly: BOOL] = { in: LONG POINTER TO TeledebugProtocol.CoreStoreAcknowledgement; out: LONG POINTER TO TeledebugProtocol.CoreStoreRequest; readOnly _ map.state.flags.readonly; IF NOT readOnly THEN map.state.flags.dirty _ TRUE; Lock[host]; DO ENABLE UNWIND => Unlock[]; b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; out _ LOOPHOLE[@b.body]; out.page _ mempage; out.flags _ LOOPHOLE[map.state.flags]; LOOPHOLE[@out.data, LONG POINTER TO WVMPrivate.PageData]^ _ data^; b _ SendAndReceive[b, pageStoreRequest, TeledebugProtocol.coreStoreRequestSize]; in _ LOOPHOLE[@b.body]; IF PupWords[b] # TeledebugProtocol.coreStoreAcknowledgementSize OR WVMPrivate.PageNumber[in.page] # mempage THEN { PupSocket.FreeBuffer[b]; LOOP }; IF in.flags#LOOPHOLE[map.state.flags, WORD] THEN ERROR; PupSocket.FreeBuffer[b]; EXIT; ENDLOOP; Unlock[]; }; ClientDiskTellsLies: ERROR = CODE; ReadRemoteDisk: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, addr: WVMPrivate.DiskAddress, label: LONG POINTER TO DiskFace.Label] = { in: LONG POINTER TO TeledebugProtocol.DiskFetchAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskAddressSetRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; out _ LOOPHOLE[@b.body]; out^ _ [addr.diskPage + addr.offset, addr.deviceType, addr.deviceOrdinal]; b _ SendAndReceive[b, diskFetchRequest, TeledebugProtocol.diskAddressSetRequestSize]; IF PupWords[b] # TeledebugProtocol.diskFetchAcknowledgementSize THEN { PupSocket.FreeBuffer[b]; LOOP }; in _ LOOPHOLE[@b.body]; IF data # NIL THEN data^ _ LOOPHOLE[in.data, WVMPrivate.PageData]; label^ _ LOOPHOLE[in.label, DiskFace.Label]; PupSocket.FreeBuffer[b]; IF addr.labelCheck # DebuggerFormat.LabelChecksum[label^, addr.offset] THEN ERROR ClientDiskTellsLies[]; EXIT ENDLOOP; Unlock[]; }; WriteRemoteDisk: PUBLIC PROC[host: Machine, data: REF WVMPrivate.PageData, addr: WVMPrivate.DiskAddress, label: LONG POINTER TO DiskFace.Label] = { b: PupBuffer.Buffer; in: LONG POINTER TO TeledebugProtocol.DiskStoreAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskStoreRequest; Lock[host]; DO ENABLE UNWIND => Unlock[]; SetDiskAddress[addr.deviceType, addr.deviceOrdinal, addr.diskPage + addr.offset]; b _ PupSocket.AllocBuffer[socket]; out _ LOOPHOLE[@b.body]; LOOPHOLE[@out.label, LONG POINTER TO DiskFace.Label]^ _ label^; LOOPHOLE[@out.data, LONG POINTER TO WVMPrivate.PageData]^ _ data^; b _ SendAndReceive[b, diskStoreRequest, TeledebugProtocol.diskStoreRequestSize]; IF PupWords[b] # TeledebugProtocol.diskStoreAcknowledgementSize THEN { PupSocket.FreeBuffer[b]; LOOP }; in _ LOOPHOLE[@b.body]; IF in.label = TeledebugProtocol.noLabel THEN ERROR ClientDiskTellsLies[]; PupSocket.FreeBuffer[b]; EXIT; ENDLOOP; Unlock[]; }; GoRemote: PUBLIC PROC [host: Machine] = { p: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; Lock[host]; { ENABLE UNWIND => Unlock[]; p _ SendAndReceive[p, PupType.teledebugGoRequest, 0]; p.id _ Endian.FFromInt[Endian.IntFromF[p.id]+1]; Send[p, PupType.teledebugGoReply, 0]; }; Unlock[]; }; SetDiskAddress: PROC [device: DiskFace.Type, deviceOrdinal: CARDINAL, page: LONG CARDINAL] = { in: LONG POINTER TO TeledebugProtocol.DiskAddressSetAcknowledgement; out: LONG POINTER TO TeledebugProtocol.DiskAddressSetRequest; DO b: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; out _ LOOPHOLE[@b.body]; out^ _ [page, device, deviceOrdinal]; b _ SendAndReceive[b, diskAddress, TeledebugProtocol.diskAddressSetRequestSize]; in _ LOOPHOLE[@b.body]; IF PupWords[b] # TeledebugProtocol.diskAddressSetAcknowledgementSize OR in^ # [page, device, deviceOrdinal] THEN { PupSocket.FreeBuffer[b]; LOOP }; PupSocket.FreeBuffer[b]; EXIT; ENDLOOP; }; lastPupID: INT _ 0; GetNextPupID: ENTRY PROC RETURNS [Endian.FWORD] = INLINE { lastPupID _ lastPupID + 1; RETURN[Endian.FFromInt[lastPupID]]; }; PupWords: PROC [p: PupBuffer.Buffer] RETURNS [CARDINAL] = INLINE { w: CARDINAL = PupSocket.GetUserBytes[p]; IF w MOD 2 # 0 THEN RETURN[LAST[CARDINAL]]; RETURN[w/2]; }; SendAndReceive: PROC [b: PupBuffer.Buffer, t: PupType.Type, words: CARDINAL] RETURNS [answer: PupBuffer.Buffer] = { b.id _ GetNextPupID[]; DO copy: PupBuffer.Buffer _ PupSocket.AllocBuffer[socket]; copy.id _ b.id; PrincOpsUtils.LongCopy[from: @b.body, nwords: words, to: @copy.body]; Send[copy, t, words]; answer _ Receive[b.id ! ReceiveTimeout => LOOP]; EXIT ENDLOOP; PupSocket.FreeBuffer[b]; }; Send: PROC [b: PupBuffer.Buffer, t: PupType.Type, words: CARDINAL] = { b.type _ t; PupSocket.SetUserHWords[b, words]; PupSocket.Put[socket, b]; }; ReceiveTimeout: ERROR = CODE; getMeAPup: CONDITION; receivedPup: PupBuffer.Buffer; wantPup: BOOL; Receive: ENTRY PROC [thisID: Endian.FWORD] RETURNS [PupBuffer.Buffer] = { ENABLE UNWIND => NULL; DO wantPup _ TRUE; receivedPup _ NIL; WAIT getMeAPup; IF receivedPup=NIL THEN RETURN WITH ERROR ReceiveTimeout; IF receivedPup.id = thisID THEN RETURN[receivedPup]; PupSocket.FreeBuffer[receivedPup]; ENDLOOP; }; keepReceiving: BOOL; ReceiveProcess: PROC = { x: PupBuffer.Buffer; Pass: ENTRY PROC = { IF wantPup THEN { wantPup _ FALSE; receivedPup _ x; NOTIFY getMeAPup } ELSE PupSocket.FreeBuffer[x]; }; Notify: ENTRY PROC = {NOTIFY getMeAPup}; Like: PROC RETURNS [BOOL] = { RETURN [ x.source = remote AND x.dest = PupSocket.GetLocalAddress[socket] AND x.type = PupType.teledebugAck]; }; WHILE keepReceiving DO x _ PupSocket.Get[socket]; IF x = NIL THEN Notify[] -- timeout ELSE IF Like[] THEN Pass[] ELSE PupSocket.FreeBuffer[x]; ENDLOOP; }; locked: BOOL _ FALSE; unlocked: CONDITION; socket: PupSocket.Socket; remote: Pup.Address; Lock: PROC [host: Machine] = { LockInner[]; IF remote = host THEN RETURN; StopTeledebuggingInner[]; remote _ host; StartTeledebuggingInner[]; }; LockInner: ENTRY PROC = { ENABLE UNWIND => NULL; WHILE locked DO WAIT unlocked; ENDLOOP; locked _ TRUE; }; Unlock: ENTRY PROC = { locked _ FALSE; NOTIFY unlocked; }; LookupFailed: PUBLIC ERROR = CODE; LocateRemote: PUBLIC PROC [name: Rope.ROPE] RETURNS [host: Machine] = { host _ PupName.NameLookup[name, PupWKS.teleSwat ! PupName.Error => ERROR LookupFailed[] ]; }; receiveProcess: PROCESS; StartTeledebugging: PROC = { Process.EnableAborts[@getMeAPup]; remote _ Pup.nullAddress; StartTeledebuggingInner[]; Unlock[]; }; StartTeledebuggingInner: PROC = { hop: PupHop.Hop _ PupHop.GetHop[remote.net]; socket _ PupSocket.CreateEphemeral[remote: remote, sendBuffers: 2, getTimeout: 2500 + 500*hop]; keepReceiving _ TRUE; wantPup _ FALSE; receiveProcess _ FORK ReceiveProcess[]; }; StopTeledebugging: PROC = { Lock[remote]; StopTeledebuggingInner[]; }; StopTeledebuggingInner: PROC = { keepReceiving _ FALSE; JOIN receiveProcess; PupSocket.Destroy[socket]; socket _ NIL; }; StartTeledebugging[]; }. WVMRemote.mesa - TeleDebug protocol Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Andrew Birrell July 29, 1983 3:56 pm Russ Atkinson, February 6, 1985 9:37:28 pm PST Hal Murray, June 3, 1986 4:14:45 pm PDT Public procedures Sending diskFetchRequest with diskAddressSetRequestSize causes a combined addressSet and diskFetch. (I didn't design it!) Actual packet transmission/reception! -- first level of screening (don't care about others) There is only one socket, protected by Lock/Unlock during remote calls -- Κ ˜codešœ#™#Kšœ Οmœ7™BKšœ%™%K™.K™'—K˜šΟk ˜ Kšœžœ˜%Kšœ žœ˜Kšœžœ ž œ ˜)K˜ Kšœžœ ˜Kšœžœ˜Kšœ žœ ˜Kšœžœ˜!Kšœžœ˜Kšœžœ˜"Kšœ žœu˜„Kšœžœ;˜IKšœžœ ˜Kšœžœžœ˜K˜Kšœžœ˜K˜ K˜—šœ ž˜KšžœK˜RKšžœ˜—K˜Kšœ žœžœ˜#K˜Kšœ™K˜šΟnœžœžœžœ5žœžœžœ˜™Kšœžœžœžœ,˜?Kšœžœžœžœ$˜8K˜ šžœžœžœ ˜K˜4Kšœžœ ˜K˜K˜PKšœžœ ˜šžœ=˜?Kšžœ)˜+Kšžœžœ˜'—Kšœžœ˜/Kšœžœ%˜?K˜Kšœžœ:˜GKšž˜—Kšžœ˜K˜ Kšœ˜K˜—š ŸœžœžœžœPžœ žœ˜ Kšœžœžœžœ,˜?Kšœžœžœžœ$˜8Kšœ$˜$Kšžœžœ žœžœ˜2K˜ šžœžœžœ ˜K˜4Kšœžœ ˜K˜Kšœ žœ˜&Kšžœ žœžœžœ˜BK˜PKšœžœ ˜Kšžœ=˜?Kšžœ)˜+Kšžœžœ˜'Kš žœ žœžœžœžœ˜7K˜Kšžœ˜—Kšžœ˜K˜ Kšœ˜K˜—Kšœžœžœ˜"K˜šŸœžœžœžœ;žœžœžœ˜’Kšœžœžœžœ,˜?Kšœžœžœžœ)˜=K˜ šžœžœžœ ˜K˜4Kšœžœ ˜K˜JKšœ>™>Kšœ:™:K˜UKšžœ=˜?Kšžœžœ˜'Kšœžœ ˜Kšžœžœžœ žœ˜BKšœ žœ˜,K˜KšžœD˜FKšžœžœ˜!Kšž˜—Kšžœ˜K˜ Kšœ˜K˜—šŸœžœžœžœ;žœžœžœ˜“K˜Kšœžœžœžœ,˜?Kšœžœžœžœ$˜8K˜ šžœžœžœ ˜K˜QK˜"Kšœžœ ˜Kšžœ žœžœžœ˜?Kšžœ žœžœžœ˜BK˜PKšžœ=˜?Kšžœžœ˜'Kšœžœ ˜Kšžœ&žœžœ˜IK˜Kšž˜—Kšžœ˜K˜ Kšœ˜K˜—šŸœžœžœ˜)K˜4K˜ šœ˜Kšžœžœ ˜Kšœ5˜5K˜0Kšœ%˜%Kšœ˜—K˜ Kšœ˜K˜—š Ÿœžœ(žœžœžœ˜^Kšœžœžœžœ1˜DKšœžœžœžœ)˜=šž˜K˜4Kšœžœ ˜K˜%K˜PKšœžœ ˜KšžœC˜EKšžœ$˜&Kšžœžœ˜'K˜Kšž˜—Kšžœ˜Kšœ˜K˜K˜—Kšœ(™(K˜Kšœ žœ˜K˜š Ÿ œžœžœžœ žœžœ˜:Kšœ žœ ž˜Kšžœ ˜&K˜—š Ÿœžœžœžœžœ˜BKšœžœ˜(Kš žœžœžœžœžœžœ˜+Kšžœ˜ Kšœ˜K˜—šŸœžœ/žœžœ˜sK˜šž˜Kšœ7˜7K˜KšœE˜EKšœ˜Kšœ*žœ˜0Kšž˜—Kšžœ˜Kšœ˜Kšœ˜K˜—šŸœžœ/žœ˜FK˜ K˜"Kšœ˜Kšœ˜K˜—Kšœžœžœ˜Kšœ ž œ˜K˜Kšœ žœ˜K˜š Ÿœžœžœžœžœ˜IKšžœžœžœ˜šž˜Kšœ žœ˜Kšœžœ˜Kšžœ ˜Kš žœ žœžœžœžœžœ˜9Kšžœžœžœ˜4Kšœ"˜"—Kšžœ˜Kšœ˜K˜—Kšœžœ˜K˜šŸœžœ˜K˜šŸœžœžœ˜Kšžœžœ žœžœ ˜FKšžœ˜Kšœ˜—KšŸœžœžœžœ ˜(šŸœžœžœžœ˜Kšœ2™2šžœ˜Kšœžœ,ž˜DKšœ˜—Kšœ˜—šžœž˜Kšœ˜Kšžœžœ Οc ˜#Kšžœžœžœžœ˜8—Kšžœ˜Kšœ˜K˜K˜K˜—KšœI™IK˜Kšœžœžœ˜Kšœ ž œ˜K˜K˜K˜K˜šŸœžœ˜Jšœ ˜ Kšžœžœžœ˜Kšœ˜K˜Kšœ˜Kšœ˜K˜—šŸ œžœžœ˜Kšžœžœžœ˜Kšžœžœžœ žœ˜'Kšœ žœ˜Kšœ˜K˜—š Ÿœžœžœžœžœ ˜:K˜—Kšœžœžœžœ˜"K˜š Ÿ œžœžœ žœžœ˜Gšœ1˜1Kšœžœ˜(—Kšœ˜K˜—Kšœžœ˜K˜šŸœžœ˜K˜!K˜Kšœ˜K˜ Kšœ˜K˜—šŸœžœ˜!Kšœ,˜,Kšœ_˜_Kšœžœ˜Kšœ žœ˜Kšœžœ˜'Kšœ˜K˜—šŸœžœ˜K˜ Kšœ˜Kšœ˜K˜—šŸœžœ˜ Kšœžœ˜Kšžœ˜K˜Kšœ žœ˜ Kšœ˜K˜—K˜K˜Kšœ˜K˜K˜—…—!š.Τ