XNSStreamTest.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Demers, October 16, 1986 12:55:00 pm PDT
DIRECTORY
BasicTime USING [GetClockPulses, Pulses, PulsesToMicroseconds],
Endian USING [HFromCard],
IO USING [CharsAvail, Close, GetBlock, GetChar, PutBlock, PutChar, STREAM],
RefText USING [AppendRope, New, ObtainScratch, ReleaseScratch],
Rope USING [Concat, Fetch, FromChar, FromRefText, Length, ROPE],
XNS USING [Address, Socket],
XNSAddressParsing USING [AddressFromRope],
XNSSPPBuf USING [maxBodyBytes],
XNSStream USING [AttentionType, CloseReason, ConnectionClosed, Create, CreateListener, DestroyListener, FilterProc, GetStatus, Listener, ListenerProc, SendEndOfMessage, Timeout];
XNSStreamTest: CEDAR PROGRAM
IMPORTS BasicTime, Endian, IO, RefText, Rope, XNSAddressParsing, XNSStream
~ {
STREAM: TYPE ~ IO.STREAM;
Pulses: TYPE ~ BasicTime.Pulses;
Now: PROC RETURNS [Pulses] ~ INLINE { RETURN [ BasicTime.GetClockPulses[] ] };
Stream Testing ...
Filter: XNSStream.FilterProc ~ {
RETURN[TRUE] };
EchoFilter: XNSStream.FilterProc ~ {
RETURN[TRUE] };
Listener: XNSStream.ListenerProc ~ {
[stream: STREAM, remote: XNS.Address]
CleanUp: PROC ~ { IO.Close[self~stream, abort~TRUE] };
{ ENABLE {
XNSStream.ConnectionClosed => { CleanUp[]; CONTINUE };
UNWIND => CleanUp[]; };
blockSize: NAT ~ 2048;
block: REF TEXT ~ RefText.New[blockSize];
nChars: NAT;
DO
nChars ← IO.GetBlock[self~stream, block~block
! XNSStream.Timeout => RESUME];
IF nChars = 0 THEN [] ← XNSStream.GetStatus[self~stream, reset~TRUE];
ENDLOOP;
};
};
Listen: PROC [socketNum: CARDINAL] RETURNS [listener: XNSStream.Listener ← NIL] ~ {
ENABLE XNSStream.ConnectionClosed => {
CONTINUE };
listenerSocket: XNS.Socket;
TRUSTED { listenerSocket ← LOOPHOLE[Endian.HFromCard[socketNum]] };
listener ← XNSStream.CreateListener[socket~listenerSocket, worker~Listener, getTimeout~5000, putTimeout~5000, filter~Filter, echoFilter~EchoFilter];
};
UnListen: PROC [listener: XNSStream.Listener] ~ {
XNSStream.DestroyListener[listener] };
Create: PROC [hisAddr: Rope.ROPE] RETURNS [stream: STREAMNIL] ~ {
ENABLE XNSStream.ConnectionClosed => {
CONTINUE };
remote: XNS.Address;
remote ← XNSAddressParsing.AddressFromRope[hisAddr];
stream ← XNSStream.Create[remote~remote];
};
Destroy: PROC [stream: STREAM] ~ {
IO.Close[stream];
};
PutCharRope: PROC [self: STREAM, rope: Rope.ROPE] ~ {
FOR i: INT IN [0 .. Rope.Length[rope]) DO
IO.PutChar[self~self, char~Rope.Fetch[base~rope, index~i]];
ENDLOOP;
XNSStream.SendEndOfMessage[self];
};
PutNChars: PROC [self: STREAM, n: INT, c: CHAR ← 'X] ~ {
FOR i: INT IN [1 .. n] DO IO.PutChar[self~self, char~c] ENDLOOP;
XNSStream.SendEndOfMessage[self];
};
PutBlockRope: PROC [self: STREAM, rope: Rope.ROPE] ~ {
len: NAT ~ Rope.Length[rope];
block: REF TEXT;
block ← RefText.ObtainScratch[len];
block ← RefText.AppendRope[to~block, from~rope, start~0, len~len];
IO.PutBlock[self~self, block~block, startIndex~0, count~len];
XNSStream.SendEndOfMessage[self~self];
RefText.ReleaseScratch[block];
};
PutNBlock: PROC [self: STREAM, n: INT, c: CHAR ← 'X]
RETURNS [usecs: LONG CARDINAL] ~ {
startTime: Pulses ~ Now[];
len: NAT ~ XNSSPPBuf.maxBodyBytes;
block: REF TEXT;
block ← RefText.ObtainScratch[len];
FOR i: INT IN [0 .. block.maxLength) DO block[i] ← c; ENDLOOP;
block.length ← len;
FOR chunk: INT ← n, chunk-len WHILE chunk > 0 DO
count: NAT ~ IF chunk > len THEN len ELSE NAT[chunk];
IO.PutBlock[self~self, block~block, startIndex~0, count~count];
ENDLOOP;
XNSStream.SendEndOfMessage[self];
usecs ← BasicTime.PulsesToMicroseconds[ BasicTime.GetClockPulses[] - startTime ];
RefText.ReleaseScratch[block];
};
GetCharRope: PROC [self: STREAM] RETURNS [rope: Rope.ROPENIL] ~ {
[] ← XNSStream.GetStatus[self~self, reset~TRUE]; -- clear status.
WHILE IO.CharsAvail[self~self, wait~FALSE] > 0 DO
c: CHAR ~ IO.GetChar[self~self];
rope ← Rope.Concat[rope, Rope.FromChar[c]];
ENDLOOP;
};
GetBlockRope: PROC [self: STREAM] RETURNS [rope: Rope.ROPENIL] ~ {
blockSize: NAT ~ 100;
block: REF TEXT ~ RefText.ObtainScratch[blockSize];
n: NAT;
[] ← XNSStream.GetStatus[self~self, reset~TRUE]; -- clear status.
WHILE (n ← IO.CharsAvail[self~self, wait~FALSE]) > 0 DO
[] ← IO.GetBlock[self~self, block~block, startIndex~0, count~MIN[n,blockSize]];
rope ← Rope.Concat[rope, Rope.FromRefText[block]];
ENDLOOP;
RefText.ReleaseScratch[block];
};
}.