tcp/src/WIN32/IP.m3


Copyright (C) 1994, Digital Equipment Corp.
 Created on Sat Jan 11 15:49:00 PST 1992 by gnelson       
                                                          

UNSAFE MODULE IP;

IMPORT Atom, AtomList, M3toC, Process, TextF, WinSock;

VAR mu := NEW(MUTEX);

PROCEDURE GetHostByName(nm: TEXT; VAR (*out*) res: Address): BOOLEAN
    RAISES {Error} =
  BEGIN
    LOCK mu DO
      VAR h := WinSock.gethostbyname(ADR(nm[0])); BEGIN
        IF h = NIL THEN InterpretError(); RETURN FALSE; END;
        res := GetAddress(h);
      END;
    END;
    RETURN TRUE;
  END GetHostByName;

PROCEDURE GetCanonicalByName(nm: TEXT): TEXT RAISES {Error} =
  BEGIN
    LOCK mu DO
      VAR h := WinSock.gethostbyname(ADR(nm[0])); BEGIN
        IF h # NIL THEN
          RETURN M3toC.CopyStoT(h.h_name);
        END;
      END;
    END;
    InterpretError();
    RETURN NIL;
  END GetCanonicalByName;

PROCEDURE GetCanonicalByAddr(addr: Address): TEXT RAISES {Error} =
  VAR ua: WinSock.struct_in_addr;
  BEGIN
    ua.s_addr := LOOPHOLE(addr, WinSock.u_long);
    LOCK mu DO
      VAR h := WinSock.gethostbyaddr(
                   ADR(ua), BYTESIZE(ua), WinSock.AF_INET);
      BEGIN
        IF h # NIL THEN
          RETURN M3toC.CopyStoT(h.h_name);
        END;
      END;
    END;
    InterpretError();
    RETURN NIL;
  END GetCanonicalByAddr;

PROCEDURE GetAddress (ent: WinSock.struct_hostent_star): Address =
  VAR ua: WinSock.struct_in_addr;
  BEGIN
    <* ASSERT ent.h_length <= BYTESIZE(Address) *>
    ua := LOOPHOLE(ent.h_addr_list,
                    UNTRACED REF UNTRACED REF WinSock.struct_in_addr)^^;
    RETURN LOOPHOLE(ua.s_addr, Address);
  END GetAddress;

PROCEDURE GetHostAddr(): Address =
  VAR hname: ARRAY [0..255] OF CHAR;
  BEGIN
    LOCK mu DO
      IF WinSock.gethostname(ADR(hname[0]), BYTESIZE(hname)) # 0 THEN
        Die();
      END;
      RETURN GetAddress(WinSock.gethostbyname(ADR(hname[0])));
    END;
  END GetHostAddr;

PROCEDURE InterpretError() RAISES {Error} =
  VAR err := WinSock.WSAGetLastError();
  BEGIN
    CASE err OF
    | WinSock.TRY_AGAIN, WinSock.NO_RECOVERY, WinSock.NO_ADDRESS =>
        RAISE Error(AtomList.List1(LookupFailure));
    ELSE
    END;
  END InterpretError;

CONST WinSockVersion = 16_0101;       (* App version 1.1 *)

PROCEDURE Init() =
  VAR data: WinSock.WSAData;
  BEGIN
    IF WinSock.WSAStartup(WinSockVersion, ADR(data)) # 0 THEN Die(); END;
    Process.RegisterExitor(Exitor);
  END Init;

PROCEDURE Exitor() =
  BEGIN
    EVAL WinSock.WSACleanup();
  END Exitor;

EXCEPTION FatalError;

PROCEDURE Die() RAISES {} =
  <* FATAL FatalError *>
  BEGIN
    RAISE FatalError;
  END Die;

BEGIN
  LookupFailure := Atom.FromText("IP.LookupFailure");
  Unreachable := Atom.FromText("IP.Unreachable");
  PortBusy := Atom.FromText("IP.PortBusy");
  NoResources := Atom.FromText("IP.NoResources");
  Init();
END IP.