[Haskell] Re: Should inet_ntoa Be Pure?

Marcin 'Qrczak' Kowalczyk qrczak at knm.org.pl
Mon May 9 13:41:56 EDT 2005


Peter Simons <simons at cryp.to> writes:

> I would be curious to know how other programming languages
> have solved this problem. C's solution is the one we all
> know and love, and C++ added pretty much nothing to that in
> the last 10 years or so. How about others?

I once looked at .NET and was not impressed: too many variations of
types which hold various kinds of addresses, hard-coded choices which
are left more polymorphic in the BSD sockets API, and mono performs
packing and unpacking of addresses on operations.

Java also was not very interesting, I don't remember the details.

For my language Kogut I have designed and implemented the following
as a wrapper around BSD sockets (warning: not tested on real-life
applications). In a few places I rely on dynamic typing and optional
keyword parameters, so it would have to be changed a bit for Haskell.

* Address families and protocol families of type FAMILY:
  InetFamily, Inet6Family (optional), and UnixFamily.

* Socket types of type SOCKET_TYPE: AnyType, DgramType,
  RawType (optional), SeqPacketType, and StreamType.

* Protocols are represented by strings or numbers. Function
  GetProtocolInfo resolves a protocol to a record of type
  PROTOCOL_INFO with fields code, name, and aliases.

* Sockets of type SOCKET. It may be the same as RAW_FILE (currently
  it is always the same). Function Socket creates an unconnected
  socket. It has keyword parameters family (default: DefaultFamily,
  which is Inet6Family or InetFamily by default), type (default:
  StreamType), and protocol (default: depends on the family and type).

* Function SocketPair creates a pair of sockets connected to each
  other. It has the same arguments as Socket.

* Addresses of type ADDRESS with fields family and data. Data is
  exposed as a byte array whose format depends on the family and on
  the system. Data is also exposed as a set of fields which depend
  on the address family:
  - InetFamily: port (0..65535), addr (a list of 4 bytes);
    some constants for the addr field: InetAddrAny,
    InetAddrBroadcast and InetAddrLoopback
  - Inet6Family: port (0..65535), flowInfo (0..2**31-1),
    addr (a list of 16 bytes), scopeId (0..2**31-1);
    some constants for the addr field: Inet6AddrAny,
    Inet6AddrLoopback; some predicates on the addr field:
    IsInet6AddrUnspecified, IsInet6AddrLoopback,
    IsInet6AddrMulticast, IsInet6AddrLinkLocal,
    IsInet6AddrSiteLocal, IsInet6AddrV4Mapped,
    IsInet6AddrV4Compat, IsInet6AddrMcNodeLocal,
    IsInet6AddrMcLinkLocal, IsInet6AddrMcSiteLocal,
    IsInet6AddrMcOrgLocal, IsInet6AddrMcGlobal
  - UnixFamily: path (string)
  There is a constructor Address with parameter family and
  named parameters: either data or family-dependent fields. The
  UnspecAddress constant can be used with Connect for clearing
  the default destination of datagram sockets. Even though data
  is a mutable byte array, addresses are immutable; a new array
  is created each time the data field is accessed. Addresses are
  compared and hashed by value.

* Function GetAddrInfo resolves a host (string) and port (string or
  number) to a list of records of type ADDR_INFO with fields family,
  type, protocol, address, and canonName. Either the host or the
  port may be missing, but not both. Other keyword parameters of
  GetAddrInfo are family (default: find out automatically), type
  (default: StreamType), protocol (default: depends on the family
  and type), and flags: passive, canonName, numericHost, numericServ,
  v4Mapped, all, addrConfig (default: v4Mapped and addrConfig are
  True, others are False).

* Function GetFirstAddrInfo returns the first element of the list
  returned by GetAddrInfo.

* Function GetNameInfo translates an address to a pair of strings:
  host and port. It takes keyword parameters after the address:
  noFQDN, numericHost, nameReqd, numericServ, numericScope, and
  dgram.

* Functions Connect and Bind take a socket and keyword parameters:
  either address, or arguments for GetFirstAddrInfo.

* Function Listen takes a socket and a keyword parameter backlog
  (default: DefaultBacklog, which is 5 by default).

* Function Accept takes a socket and returns a pair: a socket for
  the connection and the peer address.

* Function Shutdown takes a socket and a symbol #read, #write, or
  #both.

* Functions GetSocketName and GetPeerName take a socket and return
  an address.

* Function SocketOption takes a socket, protocol level (SocketLevel,
  IPProtoIP, IPProtoIPv6, IPProtoICMP, IPProtoRAW, IPProtoTCP,
  IPProtoUDP), option name (#acceptConn, #broadcast, #debug,
  #dontRoute, #error, #keepAlive, #linger, #oobInline, #rcvBuf,
  #rcvLoWat, #rcvTimeO, #reuseAddr, #sndBuf, #sndLoWat, #sndTimeO,
  #type, #noDelay), and either gets the socket option, or takes the
  new value as the last argument and sets the option. The type of
  the value depends on the option name.

* Function Receive takes a socket, byte array to fill, maximum size,
  and keyword parameters: peek, oob, and waitAll; it returns a
  boolean indicating the end of transmission. Function ReceiveFrom
  takes the same parameters and returns the sender address or Null
  if the address is unavailable.

* Function Send takes a socket, byte array to send, maximum size,
  and keyword parameters: eor and oob. Function SendTo additionally
  takes the recipient address after the socket.

* Function SocketStreams exposes a socket as a pair of streams:
  input stream and output stream of bytes. Closing both streams
  closes the socket.

* Functions SocketTextStreams and SocketBinaryStreams expose a
  socket as a pair of {Text,Binary}{Reader,Writer}. They ensure that
  the writer is flushed before asking for input. They take keyword
  parameters for readers and writers.

* Function ClientSocket is a convenience wrapper for Socket and
  Connect. Function ServerSocket is a convenience wrapper for
  Socket, Bind, and Listen. They take combined keyword parameters
  for the functions they use. The family of the address (if the
  address is given) or the result of resolving the name (if the host
  or port are given) influences the family, type and protocol of the
  socket.

* Functions {ClientSocket,Accept}{,Text,Binary}Streams are
  convenience wrappers for {ClientSocket,Accept} and
  Socket{,Text,Binary}Streams. They take combined keyword
  parameters for the functions they use.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak at knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/


More information about the Haskell mailing list