DIRECTORY Arpa, Basics, Convert, IO, NetworkStream, NetworkStreamSupportTCP, Rope, UnixTypes, UnixSysCalls ; NetworkStreamSupportTCPImpl: CEDAR MONITOR IMPORTS Basics, Convert, Rope, UnixSysCalls EXPORTS NetworkStreamSupportTCP ~ { OPEN NS: NetworkStream, NSS: NetworkStreamSupportTCP, USC: UnixSysCalls; ROPE: TYPE ~ Rope.ROPE; PCRMsec: TYPE ~ CARD; pcrWaitForever: PCRMsec ~ 0; PCRFildes: TYPE ~ UnixTypes.FileDescriptor; pcrErrorFildes: PCRFildes ~ error; AttnType: TYPE ~ NSS.AttnType; CC: TYPE ~ NSS.CompletionCode; successCC: CC ~ NSS.successCC; ioErrorCC: CC ~ 5; -- Unix EIO addressSyntaxCC: CC ~ 1024; StreamDescriptor: TYPE ~ REF StreamDescriptorObject; StreamDescriptorObject: PUBLIC TYPE ~ RECORD [ descriptor: PCRFildes ]; ListenerDescriptor: TYPE ~ REF ListenerDescriptorObject; ListenerDescriptorObject: PUBLIC TYPE ~ RECORD [ descriptor: PCRFildes ]; Address: TYPE ~ Arpa.Address; nullAddress: Address ~ Arpa.nullAddress; Port: TYPE ~ Basics.HWORD; nullPort: Port ~ [0, 0]; SockAddrIN: TYPE ~ REF SockAddrINStruct; SockAddrINStruct: TYPE ~ WORD16 MACHINE DEPENDENT RECORD [ addressFamily(0): UnixTypes.AddressFamily ¬ inet, port(1): Port ¬ nullPort, address(2): Address ¬ nullAddress, zeroes(4): PACKED ARRAY[0..8) OF BYTE ¬ [0, 0, 0, 0, 0, 0, 0, 0] ]; RopeFromCC: PUBLIC PROC [cc: CC] RETURNS [ROPE] ~ { SELECT cc FROM successCC => RETURN ["success"]; addressSyntaxCC => RETURN ["address syntax error"]; ENDCASE => RETURN [ Rope.Concat["Unix(tm) error number ", Convert.RopeFromInt[cc]] ]; }; AtomFromCC: PUBLIC PROC [cc: CC] RETURNS [atom: ATOM] ~ { SELECT cc FROM successCC => RETURN [$success]; addressSyntaxCC => RETURN [$addressSyntax]; ENDCASE => RETURN [ Convert.AtomFromRope[ Rope.Concat["UnixError", Convert.RopeFromInt[cc]] ] ]; }; FixTimeout: PROC [ms: NS.Milliseconds] RETURNS [pcrms: PCRMsec] ~ { pcrms ¬ (SELECT TRUE FROM (ms = NS.waitForever) => pcrWaitForever, (ms = NS.dontWait) => 1, ENDCASE => ms); }; UnFixTimeout: PROC [pcrms: PCRMsec] RETURNS [ms: NS.Milliseconds] ~ { ms ¬ (SELECT TRUE FROM (pcrms = NS.dontWait) => 1, (pcrms = NS.waitForever) => pcrWaitForever, ENDCASE => pcrms); }; PortFromRope: PROC [r: ROPE] RETURNS [Port] ~ { pos: INT; lo, hi: CARD ¬ 0; pos ¬ Rope.Find[r, ":"]; IF pos >= 0 THEN r ¬ Rope.Substr[r, pos+1]; IF Rope.IsEmpty[r] THEN RETURN [nullPort]; pos ¬ Rope.Find[r, "."]; IF pos > 0 THEN hi ¬ Convert.CardFromWholeNumberLiteral[Rope.Substr[r, 0, pos]]; IF (pos+1) < Rope.Length[r] THEN lo ¬ Convert.CardFromWholeNumberLiteral[Rope.Substr[r, pos+1]]; RETURN [ Basics.HFromCard16[(hi*256) + lo] ]; }; AddressFromRope: PROC [r: ROPE] RETURNS [address: Address] ~ { RETURN [Convert.ArpaAddressFromRope[r]]; }; AddressAndPortFromRope: PROC [r: ROPE] RETURNS [address: Address ¬ nullAddress, port: Port ¬ nullPort] ~ { portPos, addrLen: INT; BEGIN addrLen ¬ Rope.Find[r, ":"]; IF addrLen >= 0 THEN { portPos ¬ addrLen + 1; GOTO Found }; addrLen ¬ Rope.Find[r, "]"]; IF addrLen >= 0 THEN { addrLen ¬ addrLen + 1; portPos ¬ addrLen; GOTO Found }; portPos ¬ addrLen ¬ Rope.Length[r]; EXITS Found => NULL; END; address ¬ AddressFromRope[Rope.Substr[r, 0, addrLen]]; -- nullAddress if empty rope port ¬ PortFromRope[Rope.Substr[r, portPos]]; -- nullPort if empty rope }; RopeFromAddressAndPort: PROC [address: Address ¬ nullAddress, port: Port ¬ nullPort] RETURNS [r: ROPE ¬ NIL] ~ { IF address # nullAddress THEN r ¬ Convert.RopeFromArpaAddress[address]; IF port # nullPort THEN r ¬ Rope.Cat[r, ":", Convert.RopeFromCard[Basics.Card16FromH[port]]]; }; SockAddrINFromRope: PROC [r: ROPE] RETURNS [cc: CC ¬ successCC, inap: SockAddrIN] ~ { ENABLE Convert.Error => { cc ¬ addressSyntaxCC; inap ¬ NIL; CONTINUE }; inap ¬ NEW[ SockAddrINStruct ¬ [] ]; [address~inap.address, port~inap.port] ¬ AddressAndPortFromRope[r]; }; RopeFromSockAddrIN: PROC [inap: SockAddrIN] RETURNS [r: ROPE] ~ { r ¬ RopeFromAddressAndPort[inap.address, inap.port]; }; GetCC: PROC RETURNS [CC] ~ TRUSTED MACHINE CODE { "XR_GetErrno" }; GCreateStreamFildes: PROC [inap: SockAddrIN, timeout: PCRMsec] RETURNS [PCRFildes] ~ TRUSTED MACHINE CODE { "XR_NSSTCPCreateStreamFildes" }; GDestroyStreamFildes: PROC [sock: PCRFildes, abort: INT] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPDestroyStreamFildes" }; GAddressesFromStreamFildes: PROC [sock: PCRFildes, local: SockAddrIN, remote: SockAddrIN] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPAddressesFromStreamFildes" }; GSend: PROC [sock: PCRFildes, buf: POINTER TO Basics.RawBytes, nBytes: INT] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPSend" }; GSetPutTimeout: PROC [sock: PCRFildes, timeout: PCRMsec] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_SetPutTimeout" }; GGetPutTimeout: PROC [sock: PCRFildes] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_GetPutTimeout" }; GSendAttn: PROC [sock: PCRFildes, attnType: AttnType] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPSendAttn" }; GReceive: UNSAFE PROC [sock: PCRFildes, buf: POINTER TO Basics.RawBytes, nBytes: INT] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPReceive" }; GSetGetTimeout: PROC [sock: PCRFildes, timeout: PCRMsec] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_SetGetTimeout" }; GGetGetTimeout: PROC [sock: PCRFildes] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_GetGetTimeout" }; GInputReady: PROC [sock: PCRFildes, timeout: PCRMsec] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPInputReady" }; GWaitOOBAttn: PROC [sock: PCRFildes, timeout: PCRMsec] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPWaitOOBAttn" }; GAtIBAttn: PROC [sock: PCRFildes] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPAtIBAttn" }; GCreateListenerFildes: PROC [inap: SockAddrIN] RETURNS [PCRFildes] ~ TRUSTED MACHINE CODE { "XR_NSSTCPCreateListenerFildes" }; GDestroyListenerFildes: PROC [listener: PCRFildes] RETURNS[INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPDestroyListenerFildes" }; GAddressFromListenerFildes: PROC [listener: PCRFildes, local: SockAddrIN] RETURNS [INT] ~ TRUSTED MACHINE CODE { "XR_NSSTCPAddressFromListenerFildes" }; GAccept: PROC [listener: PCRFildes] RETURNS [PCRFildes] ~ TRUSTED MACHINE CODE { "XR_NSSTCPAccept" }; CreateStreamDescriptor: PUBLIC PROC [remote: ROPE, timeout: NS.Milliseconds] RETURNS [cc: CC ¬ successCC, sd: StreamDescriptor ¬ NIL] ~ { fd: PCRFildes; ina: SockAddrIN; [cc, ina] ¬ SockAddrINFromRope[remote]; IF cc # successCC THEN RETURN; fd ¬ GCreateStreamFildes[ina, timeout]; IF fd = pcrErrorFildes THEN cc ¬ GetCC[] ELSE sd ¬ NEW [ StreamDescriptorObject ¬ [fd] ]; }; DestroyStreamDescriptor: PUBLIC PROC [sd: StreamDescriptor, abort: BOOL] RETURNS [cc: CC ¬ successCC] ~ { ans: INT ¬ GDestroyStreamFildes[sd.descriptor, IF abort THEN 1 ELSE 0]; IF ans = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; AddressesFromStreamDescriptor: PUBLIC PROC [sd: StreamDescriptor] RETURNS [cc: CC ¬ successCC, local: ROPE ¬ NIL, remote: ROPE ¬ NIL] ~ { ls: SockAddrIN ¬ NEW[ SockAddrINStruct ]; rs: SockAddrIN ¬ NEW[ SockAddrINStruct ]; ans: INT ¬ GAddressesFromStreamFildes[sd.descriptor, ls, rs]; IF ans = (-1) THEN { cc ¬ GetCC[]; RETURN }; local ¬ RopeFromSockAddrIN[ls]; remote ¬ RopeFromSockAddrIN[rs]; }; Send: PUBLIC PROC [sd: StreamDescriptor, block: IO.UnsafeBlock] RETURNS [cc: CC ¬ successCC] ~ { ans: INT; ans ¬ GSend[sd.descriptor, block.base + block.startIndex, block.count]; IF ans = (-1) THEN { cc ¬ GetCC[]; RETURN }; IF ans # block.count THEN { cc ¬ ioErrorCC; RETURN }; }; SetPutTimeout: PUBLIC PROC [sd: StreamDescriptor, timeout: NS.Milliseconds] RETURNS [cc: CC ¬ successCC] ~ { IF GSetPutTimeout[sd.descriptor, FixTimeout[timeout]] = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; GetPutTimeout: PUBLIC PROC [sd: StreamDescriptor] RETURNS [cc: CC ¬ successCC, timeout: NS.Milliseconds ¬ 0] ~ { ans: INT ¬ GGetPutTimeout[sd.descriptor]; IF ans = (-1) THEN { cc ¬ GetCC[]; RETURN }; timeout ¬ UnFixTimeout[LOOPHOLE[ans]]; }; SendAttn: PUBLIC PROC [sd: StreamDescriptor, attnType: AttnType] RETURNS [cc: CC ¬ successCC] ~ { IF GSendAttn[sd.descriptor, attnType] = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; Receive: PUBLIC UNSAFE PROC [sd: StreamDescriptor, block: IO.UnsafeBlock] RETURNS [cc: CC ¬ successCC, nBytesReceived: INT] ~ { TRUSTED { nBytesReceived ¬ USC.Read[sd.descriptor, LOOPHOLE[block.base+block.startIndex], block.count] }; IF nBytesReceived = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; SetGetTimeout: PUBLIC PROC [sd: StreamDescriptor, timeout: NS.Milliseconds] RETURNS [cc: CC ¬ successCC] ~ { IF GSetGetTimeout[sd.descriptor, FixTimeout[timeout]] = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; GetGetTimeout: PUBLIC PROC [sd: StreamDescriptor] RETURNS [cc: CC ¬ successCC, timeout: NS.Milliseconds ¬ 0] ~ { ans: INT ¬ GGetGetTimeout[sd.descriptor]; IF ans = (-1) THEN { cc ¬ GetCC[]; RETURN }; timeout ¬ UnFixTimeout[LOOPHOLE[ans]]; }; InputReady: PUBLIC PROC [sd: StreamDescriptor, wait: BOOL] RETURNS [cc: CC ¬ successCC, inputReady: BOOL ¬ FALSE] ~ { ans: INT; timeout: PCRMsec ¬ 0; IF wait THEN { [cc, timeout] ¬ GetGetTimeout[sd]; IF cc # successCC THEN RETURN; }; IF (ans ¬ GInputReady[sd.descriptor, timeout]) = (-1) THEN { cc ¬ GetCC[]; RETURN }; inputReady ¬ (ans > 0); }; WaitOOBAttn: PUBLIC PROC [sd: StreamDescriptor, timeout: NS.Milliseconds] RETURNS [cc: CC ¬ successCC, attnType: AttnType] ~ { attnType ¬ 0; -- the only one there is! IF GWaitOOBAttn[sd.descriptor, FixTimeout[timeout]] = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; AtIBAttn: PUBLIC PROC [sd: StreamDescriptor] RETURNS [cc: CC ¬ successCC, atIBAttn: BOOL ¬ FALSE] ~ { ans: INT; IF (ans ¬ GAtIBAttn[sd.descriptor]) = (-1) THEN { cc ¬ GetCC[]; RETURN }; atIBAttn ¬ (ans > 0); }; CreateListenerDescriptor: PUBLIC PROC [local: ROPE ¬ NIL] RETURNS [cc: CC, ld: ListenerDescriptor ¬ NIL] ~ { fd: PCRFildes; ina: SockAddrIN; [cc, ina] ¬ SockAddrINFromRope[local]; IF cc # successCC THEN RETURN; fd ¬ GCreateListenerFildes[ina]; IF fd = pcrErrorFildes THEN { cc ¬ GetCC[]; RETURN }; ld ¬ NEW [ ListenerDescriptorObject ¬ [fd] ]; }; DestroyListenerDescriptor: PUBLIC PROC [ld: ListenerDescriptor] RETURNS [cc: CC ¬ successCC] ~ { IF GDestroyListenerFildes[ld.descriptor] = (-1) THEN { cc ¬ GetCC[]; RETURN }; }; AddressFromListenerDescriptor: PUBLIC PROC [ld: ListenerDescriptor] RETURNS [cc: CC ¬ successCC, local: ROPE ¬ NIL] ~ { ls: SockAddrIN ¬ NEW[ SockAddrINStruct ]; IF GAddressFromListenerFildes[ld.descriptor, ls] = (-1) THEN { cc ¬ GetCC[]; RETURN }; local ¬ RopeFromSockAddrIN[ls]; }; AcceptConnection: PUBLIC PROC [ld: ListenerDescriptor] RETURNS [cc: CC ¬ successCC, sd: StreamDescriptor ¬ NIL] ~ { fd: PCRFildes ¬ GAccept[ld.descriptor]; IF fd = pcrErrorFildes THEN { cc ¬ GetCC[]; RETURN }; sd ¬ NEW [ StreamDescriptorObject ¬ [fd] ]; }; }.  NetworkStreamSupportTCPImpl.mesa Copyright Σ 1989, 1991 by Xerox Corporation. All rights reserved. Demers, November 6, 1990 3:05 pm PST Willie-s, September 30, 1991 1:13 pm PDT Types Public Utilities Private Utilities Glue Stream Operations Listener Operations Κ Π•NewlineDelimiter –(cedarcode) style™codešœ ™ Kšœ Οeœ7™BK™$K™(K™—šΟk ˜ K˜K˜K˜Kšžœ˜K˜K˜K˜K˜ K˜ K˜K˜—šΟnœžœž˜*Kšžœ$˜+Kšžœ˜K˜Kšžœžœžœžœ˜Hhead™Kšžœžœžœ˜K˜Kšœ žœžœ˜Kšœ˜K˜Kšœ žœ˜+Kšœ"˜"K˜Kšœ žœžœ ˜K˜Kšžœžœžœ˜Kšœ žœžœ ˜Kšœ žœΟc ˜Kšœžœ˜K˜Kšœžœžœ˜4šœž œžœ˜.Kšœ˜Kšœ˜—K˜Kšœžœžœ˜8šœž œžœ˜0Kšœ˜Kšœ˜K˜—Kšœ žœ˜K˜(K˜Kšœžœ žœ˜Kšœ˜K˜Kšœ žœžœ˜(š œžœžœžœž œžœ˜:Kšœ1˜1Kšœ˜Kšœ"˜"Kš œ žœžœžœžœ˜@K˜K˜——™š Ÿ œž œžœžœžœ˜3šžœž˜Kšœ žœ ˜ Kšœžœ˜3KšžœžœD˜U—K˜K˜—š Ÿ œž œžœžœžœ˜9šžœž˜Kšœ žœ ˜Kšœžœ˜+KšžœžœO˜`—K˜——™šŸ œžœžœžœ˜Cšœ žœžœž˜Kšœžœ ˜(Kšœžœ˜Kšžœ˜—K˜K˜—šŸ œžœžœžœ˜Ešœžœžœž˜Kšœ žœ˜Kšœ žœ ˜+Kšžœ ˜—K˜K˜—šŸ œžœžœžœ ˜/Kšœžœ˜ Kšœžœ˜K˜Kšžœ žœ˜+Kšžœžœžœ ˜*K˜Kšžœ žœA˜PKšžœžœ@˜`Kšžœ'˜-K˜K˜—šŸœžœžœžœ˜>Kšžœ"˜(K˜K˜—šŸœžœžœžœ<˜jKšœžœ˜šž˜Kšœ˜Kšžœžœžœ ˜;Kšœ˜Kšžœžœ-žœ ˜NKšœ#˜#šž˜Kšœ žœ˜—Kšžœ˜—Kšœ7 ˜SKšœ. ˜GK˜K˜—š Ÿœžœ9žœžœžœ˜pKšžœžœ*˜GKšžœžœF˜]K˜K˜—š Ÿœžœžœžœžœ#˜UKšžœ1žœžœ˜GKšœžœ˜$KšœC˜CK˜K˜—šŸœžœžœžœ˜AKšœ4˜4K˜——™šŸœžœžœžœžœžœžœ˜BK˜—š Ÿœžœ&žœžœžœžœ#˜ŒK˜—šŸœžœžœžœžœžœžœžœ$˜K˜—šŸœžœ:žœžœžœžœžœ*˜¨K˜—šŸœžœžœžœžœžœžœžœžœžœ˜…K˜—šŸœžœ%žœžœžœžœžœ˜uK˜—šŸœžœžœžœžœžœžœ˜cK˜—šŸ œžœ'žœžœžœžœžœ˜sK˜—šŸœžœžœžœžœžœžœžœžœžœžœ˜’K˜—šŸœžœ%žœžœžœžœžœ˜uK˜—šŸœžœžœžœžœžœžœ˜cK˜—šŸ œžœ%žœžœžœžœžœ˜uK˜—šŸ œžœ%žœžœžœžœžœ˜wK˜—šŸ œžœžœžœžœžœžœ˜_K˜—š Ÿœžœžœžœžœžœ%˜~K˜—šŸœžœžœžœžœžœžœ&˜|K˜—šŸœžœ*žœžœžœžœžœ*˜˜K˜—Kš Ÿœžœžœžœžœžœ˜e—™šŸœžœžœ žœ žœžœžœ%žœ˜‰K˜K˜K˜Kšœ'˜'šžœ˜Kšžœžœ˜ —Kšœ'˜'šžœ˜Kšžœ ˜Kšžœžœ#˜0—K˜K˜—š Ÿœžœžœžœžœžœ˜iKš œžœ'žœžœžœ˜Gšžœ ˜ Kšžœžœ˜—K˜K˜—šŸœžœžœžœžœžœžœ žœžœ˜‰Kšœžœ˜)Kšœžœ˜)Kšœžœ5˜=šžœ ˜ Kšžœžœ˜—Kšœ˜Kšœ ˜ K˜K˜—š Ÿœžœžœžœžœžœ˜`Kšœžœ˜ KšœG˜GKšžœ žœžœ˜,Kšžœžœžœ˜5˜K˜——š Ÿ œžœžœ!žœžœžœ˜lšžœ:˜