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[] ] }; Filter: XNSStream.FilterProc ~ { RETURN[TRUE] }; EchoFilter: XNSStream.FilterProc ~ { RETURN[TRUE] }; Listener: XNSStream.ListenerProc ~ { 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: STREAM _ NIL] ~ { 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.ROPE _ NIL] ~ { [] _ 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.ROPE _ NIL] ~ { 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]; }; }. ΈXNSStreamTest.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Demers, October 16, 1986 12:55:00 pm PDT Stream Testing ... [stream: STREAM, remote: XNS.Address] Κ€˜codešœ™Kšœ Οmœ1™K˜šžœžœžœ ž˜0Kš œžœžœ žœžœžœ˜5Kšžœ=˜?Kšžœ˜—Kšœ!˜!KšœQ˜QKšœ˜K˜—K˜š   œžœžœžœ žœžœ˜DKšœ*žœΟc˜Ašžœžœžœž˜1Kšœžœžœ˜ K˜+Kšžœ˜—Kšœ˜—K˜š   œžœžœžœ žœžœ˜EKšœ žœ˜Kšœžœžœ$˜3Kšœžœ˜Kšœ*žœ‘˜Ašžœžœžœž˜7Kšœžœ6žœ˜OK˜2Kšžœ˜—Kšœ˜Kšœ˜—K˜—˜K˜——J˜—…—\”