-- TeleLoadImpl6.mesa
-- Last Modified By L. Stewart On September 7, 1982 10:34 PM
DIRECTORY
PupDefs,
PupTypes,
PupStream,
Storage,
TeleLoad6;
TeleLoadImpl6: PROGRAM
IMPORTS PupDefs, PupStream, Storage
EXPORTS TeleLoad6 =
BEGIN OPEN TeleLoad6;
MDSZoneRec: TYPE = MACHINE DEPENDENT RECORD [
procs(0:0..15): POINTER TO MDSZoneProcsRec
];
MDSZoneProcsRec: TYPE = MACHINE DEPENDENT RECORD [
alloc(0): PROC [zone: MDSZone, size: CARDINAL] RETURNS [POINTER],
dealloc(1): PROC [zone: MDSZone, object: POINTER]
];
myMDSZoneRec: MDSZoneRec ← [procs: @myMDSZoneProcsRec];
myMDSZoneProcsRec: MDSZoneProcsRec ← [alloc: myAlloc, dealloc: myDeAlloc];
GetZone: PUBLIC PROC RETURNS [MDSZone] = { RETURN [LOOPHOLE[@myMDSZoneRec]]; };
myAlloc: PROC [zone: MDSZone, size: CARDINAL] RETURNS [POINTER] = {
RETURN [Storage.Node[size]];
};
myDeAlloc: PROC [zone: MDSZone, object: POINTER] = {
Storage.Free[object];
};
Start: PUBLIC PROC [hostName: STRING]
RETURNS [h: Handle] = {
sendHim: PupTypes.PupAddress;
sid: PupDefs.PupSocketID;
allok: BOOLEAN ← TRUE;
PupDefs.PupPackageMake[];
sid ← PupDefs.UniqueLocalPupSocketID[];
sendHim ← [
PupTypes.fillInNetID, PupTypes.fillInHostID, teleSwatSocket];
IF hostName.length = 0 THEN RETURN[NIL];
PupStream.GetPupAddress[@sendHim, hostName !
PupStream.PupNameTrouble => {allok ← FALSE; CONTINUE; }];
IF NOT allok THEN RETURN[NIL];
h ← Storage.Node[SIZE[TLObject]];
IF h = NIL THEN ERROR;
h.socket ← PupDefs.PupSocketMake[
local: teleSwatSocket, remote: sendHim, ticks: PupDefs.SecondsToTocks[1]];
IF h.socket = NIL THEN ERROR;
h.myID.a ← LOOPHOLE[sid.a, CARDINAL]+LOOPHOLE[sid.b, CARDINAL];
h.myID.b ← 0;
h.attempts ← 5;
RETURN[h];
};
Stop: PUBLIC PROC [h: Handle] = {
IF h=NIL OR h.socket=NIL THEN RETURN;
PupDefs.PupSocketDestroy[h.socket];
PupDefs.PupPackageDestroy[];
h.socket ← NIL;
Storage.Free[h];
};
Store: PUBLIC PROC [h: Handle, cb: CoreBlock] RETURNS [Result] = {
RETURN[GStore[h: h, requestcb: cb, type: coreStoreRequest]];
};
Fetch: PUBLIC PROC [h: Handle, cb: CoreBlock] RETURNS [Result] = {
RETURN[GFetch[h: h, requestcb: cb, type: coreFetchRequest]];
};
StoreState: PUBLIC PROC [h: Handle, cb: CoreBlock] RETURNS [Result] = {
RETURN[GStore[h: h, requestcb: cb, type: stateStoreRequest]];
};
FetchState: PUBLIC PROC [h: Handle, cb: CoreBlock] RETURNS [Result] = {
RETURN[GFetch[h: h, requestcb: cb, type: stateFetchRequest]];
};
GStore: PUBLIC PROC [h: Handle, requestcb: CoreBlock, type: PupTypes.PupType] RETURNS [a: Result] = {
b: PupDefs.PupBuffer ← NIL;
replycb: CorePkt;
IF h=NIL OR h.socket=NIL THEN RETURN[[success: FALSE, attempts: 0]];
NewPupID[h];
a.success ← TRUE;
a.attempts ← 0;
FOR i: INTEGER IN [1..h.attempts] DO
a.attempts ← i;
IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b];
b ← PupDefs.GetFreePupBuffer[];
replycb ← LOOPHOLE[@b.pupBody];
replycb.address ← requestcb.address;
replycb.count ← requestcb.count;
FOR j: CARDINAL IN [0..requestcb.count) DO
replycb.data[j] ← requestcb.data[j];
ENDLOOP;
PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]+((requestcb.count+1)/2)];
b ← Exchange[h, b, type];
IF b=NIL THEN LOOP;
replycb ← LOOPHOLE[@b.pupBody];
IF NOT Check[requestcb, replycb] THEN LOOP;
EXIT;
REPEAT
FINISHED => a.success ← FALSE;
ENDLOOP;
IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b];
};
GFetch: PUBLIC PROC [h: Handle, requestcb: CoreBlock, type: PupTypes.PupType] RETURNS [a: Result] = {
b: PupDefs.PupBuffer ← NIL;
replycb: CorePkt;
IF h=NIL OR h.socket=NIL THEN RETURN[[success: FALSE, attempts: 0]];
NewPupID[h];
a.success ← TRUE;
a.attempts ← 0;
FOR i: INTEGER IN [1..h.attempts] DO
a.attempts ← i;
IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b];
b ← PupDefs.GetFreePupBuffer[];
replycb ← LOOPHOLE[@b.pupBody];
replycb.address ← requestcb.address;
replycb.count ← requestcb.count;
PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]];
b ← Exchange[h, b, type];
IF b=NIL THEN LOOP;
replycb ← LOOPHOLE[@b.pupBody];
IF replycb.address # requestcb.address THEN LOOP;
IF replycb.count # requestcb.count THEN LOOP;
FOR j: CARDINAL IN [0..requestcb.count) DO
requestcb.data[j] ← replycb.data[j];
ENDLOOP;
EXIT;
REPEAT
FINISHED => a.success ← FALSE;
ENDLOOP;
IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b];
};
Exchange: PROC [h: Handle, request: PupDefs.PupBuffer, type: PupTypes.PupType] RETURNS[PupDefs.PupBuffer] = {
reply: PupDefs.PupBuffer ← NIL;
request.pupID ← h.myID;
request.pupType ← type;
h.socket.put[request];
DO
IF reply#NIL THEN PupDefs.ReturnFreePupBuffer[reply];
reply ← h.socket.get[];
IF reply = NIL THEN RETURN[NIL];
IF reply.pupType # LOOPHOLE[LOOPHOLE[type, CARDINAL]+1] THEN LOOP;
IF reply.pupID # h.myID THEN LOOP;
RETURN[reply];
ENDLOOP;
};
Check: PROC [a: CoreBlock, b: CorePkt] RETURNS [BOOLEAN] = {
IF a.address # b.address THEN RETURN[FALSE];
IF a.count # b.count THEN RETURN[FALSE];
FOR i: CARDINAL IN [0..a.count) DO
IF a.data[i] # b.data[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
};
NewPupID: PROC [h: Handle] = { h.myID.b ← h.myID.b + 1; };
END.
December 30, 1981 3:14 PM, Stewart, created from AudioSocket.mesa
July 20, 1982 10:23 AM, Stewart, Mesa6
July 27, 1982 3:59 PM, Stewart, MDSZone
September 7, 1982 10:34 PM, Stewart, added attempt counters