From ba066c34dde204aa192d03a23a81356374d93731 Mon Sep 17 00:00:00 2001 From: chatty Date: Wed, 7 Apr 1993 11:50:31 +0000 Subject: Initial revision --- comm/Address.cc | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 comm/Address.cc (limited to 'comm/Address.cc') diff --git a/comm/Address.cc b/comm/Address.cc new file mode 100644 index 0000000..789a370 --- /dev/null +++ b/comm/Address.cc @@ -0,0 +1,350 @@ +/* + * The Unix Channel + * + * by Michel Beaudouin-Lafon + * + * Copyright 1990-1993 + * Laboratoire de Recherche en Informatique (LRI) + * + * Addresses + * + * $Id$ + * $CurLog$ + */ + +#include "Address.h" +#include "error.h" + +#include +#include +#include +#include +#include +#include + +/*?class UchAddress +This class is a virtual base class: no objects of this class are ever created. +It implements the Unix type \typ{^{struct sockaddr}}, used for creating sockets. +Addresses are used mainly as arguments of constructors for the class +\typ{UchSocket} and its derived classes. +All its member functions are virtual. +These functions exist for all the derived classes but are only described here. +An address can be valid or invalid, depending on the constructor being able to create the address or not. +There are currently two derived classes, for Unix domain addresses and Internet domain addresses. + +The class \typ{^{pUchAddress}} implements smart pointers to addresses. +Smart pointers behave like pointers but they manage a reference count on the +pointed to objects for an automatic reclaim of dynamically allocated objects. +?*/ + +/*? +Construct an invalid address. +?*/ +UchAddress :: UchAddress () +: Valid (FALSE) +{ +} + +/*?nodoc?*/ +UchAddress :: ~UchAddress () +{ +} + +// virtual functions for class address +// + +/*? +Return one of \var{AF_UNSPEC}, \var{AF_UNIX} or \var{AF_INET}. +Other values may be defined if supported by the system. +?*/ +int +UchAddress :: Family () +{ + return AF_UNSPEC; +} + +/*?nextdoc?*/ +int +UchAddress :: Length () +{ + return 0; +} + +/*? +Return the address structure and its length. +\typ{^{SockAddr}} is a typedef for \typ{^{struct sockaddr}}. +?*/ +SockAddr* +UchAddress :: GetSockAddr () +{ + return 0; +} + +/*?nodoc?*/ +char* +UchAddress :: StrRepr (char* buf) +{ + strcpy (buf, "virtual address !"); + return buf; +} + +#ifdef UNIX_SOCK + +// constructors for Unix addresses +// a Unix domain address is just a filename +// -> some problems: check for access, when to unlink it ? +// to do : generate name from a template (for uniqueness) +// + +/*?nodoc?*/ +UchUnixAddress :: UchUnixAddress () +: UchAddress () +{ + // nothing +} + +/*? +Create a Unix domain address associated to file \var{filename}. +The file is not unlinked when the address is destroyed; +it should be unlinked by the application whenever the last socket using this address is closed. +?*/ +UchUnixAddress :: UchUnixAddress (const char* filename) +: UchAddress () +{ + Addr.sun_family = AF_UNIX; + strcpy (Addr.sun_path, filename); + Valid = TRUE; // should check access to file ??? + // unlink if already there ? +} + +/*?nodoc?*/ +UchUnixAddress :: ~UchUnixAddress () +{ + // how to unlink the file ?? +} + +/*?nodoc?*/ +int +UchUnixAddress :: Family () +{ + return AF_UNIX; +} + +/*?nodoc?*/ +int +UchUnixAddress :: Length () +{ + if (Valid) + return (Addr.sun_path + strlen (Addr.sun_path)) - (char*) &Addr; + return 0; +} + +/*?nodoc?*/ +SockAddr* +UchUnixAddress :: GetSockAddr () +{ + return (SockAddr*) &Addr; +} + +/*?nodoc?*/ +char* +UchUnixAddress :: StrRepr (char* buf) +{ + sprintf (buf, "%s", Addr.sun_path); + return buf; +} + +#endif /* UNIX_SOCK */ + +// constructors for inet addresses +// inet address specified by: +// hostname / port# (ANY if hostname is NIL, LOOPBACK if hostname is "") +// hostid / port# (predefined hostids ANYADDR, ...) +// todo: +// hostname / service name ?? +// +/*?nodoc?*/ +UchInetAddress :: UchInetAddress () +: UchAddress () +{ + // nothing +} + +/*? +Construct an inet address, from a hostname and a port number. +The address is valid only if the host is valid. +If \var{host} is the empty string, the loopback host is used; +if it is the nil pointer, the wildcard is used. +If the port number is 0, it will be allocated by the system. +?*/ +UchInetAddress :: UchInetAddress (const char* name, sword port) +: UchAddress () +{ + struct hostent *host; + + if (name && *name) { + host = gethostbyname (name); + if (! host) + return; + memcpy (&Addr.sin_addr, host->h_addr, host->h_length); + } else + Addr.sin_addr.s_addr = name ? INADDR_LOOPBACK : INADDR_ANY; + Addr.sin_family = AF_INET; + Addr.sin_port = htons (port); + Valid = TRUE; +} + +/*? +Construct an inet address, from a host id (internet address) and a port number. +If the port number is 0, it is assigned by the system. +The host ids \var{^{ANYADDR}}, \var{^{LOOPBACK}} and \var{^{BROADCAST}} are predefined. +\var{ANYADDR} is used to receive messages from anywhere. +\var{LOOPBACK} is the local host address. +\var{BROADCAST} makes it possible to send data to all the hosts of a local area network. +?*/ +UchInetAddress :: UchInetAddress (lword host, sword port) +: UchAddress () +{ + Addr.sin_family = AF_INET; + Addr.sin_port = htons (port); + Addr.sin_addr.s_addr = host; + Valid = TRUE; +} + +/*?nodoc?*/ +UchInetAddress :: ~UchInetAddress () +{ +} + +/*?nodoc?*/ +int +UchInetAddress :: Family () +{ + return AF_INET; +} + +/*?nodoc?*/ +int +UchInetAddress :: Length () +{ + return sizeof (Addr); +} + +/*?nodoc?*/ +SockAddr* +UchInetAddress :: GetSockAddr () +{ + return (SockAddr*) &Addr; +} + +/*?nodoc?*/ +char* +UchInetAddress :: StrRepr (char* buf) +{ + struct hostent *host; + char *hname; + unsigned long saddr; + + saddr = Addr.sin_addr.s_addr; + host = gethostbyaddr ((char*) &saddr, sizeof (long), AF_INET); + if (host) + hname = host->h_name; + else + if (saddr == INADDR_ANY) + hname = "ANY"; + else if (saddr == INADDR_LOOPBACK) + hname = "LOOPBACK"; + else if (saddr == INADDR_BROADCAST) + hname = "BROADCAST"; + else + hname = "???"; + sprintf (buf, "%s::%d", hname, ntohs (Addr.sin_port)); + return buf; +} + +/*? +This is a global function (static member of class \typ{UchAddress}). +It creates an object of a derived class of \typ{UchAddress} from a generic address +(thus is cannot be replaced by a constructor). +A generic address is the following union of address structures +(it is typically returned by system calls like \fun{recvfrom}): +\begin{ccode} +typedef union { + struct sockaddr sa; // default + struct sockaddr_un su; // Unix + struct sockaddr_in si; // inet +} GEN_ADDR; +\end{ccode} +?*/ +UchAddress* +UchAddress :: Decode (GEN_ADDR* addr, int alen) +{ + switch (addr->sa.sa_family) { +#ifdef UNIX_SOCK + case AF_UNIX : + addr->su.sun_path [alen] = 0; + return new UchUnixAddress (addr->su.sun_path); +#endif + case AF_INET : + return new UchInetAddress (addr->si.sin_addr.s_addr, addr->si.sin_port); + + default : + return 0; + } +} + +/*? +This is a global function (static member of class \typ{UchInetAddress}. +It returns the internet address of the local host. +This is different from the predefined address \var{LOOPBACK}: +\var{LOOPBACK} is the same constant on each machine, so that it cannot +be communicated across the network. +The value returned by \fun{LoopBack} is the unique internet address of the local host. +Thus it can be communicated to another host across the network. +?*/ +lword +UchInetAddress :: LoopBack () +{ + static lword loopback = 0; + + if (loopback) + return loopback; + + struct hostent *host; + char name [128]; + + gethostname (name, sizeof (name)); + host = gethostbyname (name); + if (! host) { + Error (ErrFatal, "address", "cannot get address of local host"); + return 0; + } + return loopback = * ((lword *) host->h_addr); +} + +#ifdef DOC +// fake entries for inline functions + +/*? +Return TRUE if the address is valid. +?*/ +bool +UchAddress :: IsValid () +{} + +/*? +Return the host number of the address. +?*/ +lword +UchInetAddress :: Host () +{} + +/*? +Return the port number of the address. +?*/ +sword +UchInetAddress :: Port () +{} + +#endif /* DOC */ + -- cgit v1.1