Types
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]
];
Private Utilities
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];
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];
};
Glue
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" };
Stream Operations
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);
};
Listener Operations
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] ];
};
}.