From ba066c34dde204aa192d03a23a81356374d93731 Mon Sep 17 00:00:00 2001 From: chatty Date: Wed, 7 Apr 1993 11:50:31 +0000 Subject: Initial revision --- comm/Socket.cc | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 comm/Socket.cc (limited to 'comm/Socket.cc') diff --git a/comm/Socket.cc b/comm/Socket.cc new file mode 100644 index 0000000..1d5a542 --- /dev/null +++ b/comm/Socket.cc @@ -0,0 +1,274 @@ +/* + * The Unix Channel + * + * by Michel Beaudouin-Lafon + * + * Copyright 1990-1993 + * Laboratoire de Recherche en Informatique (LRI) + * + * Sockets + * + * $Id$ + * $CurLog$ + */ + +#include "Socket.h" + +#include +#include +#include + +extern int errno; + +/*?class UchSocket +The class \typ{UchSocket} derives from \typ{UchChannel}. +It is a virtual base class: no objects of class \typ{UchSocket} are ever created. +It implements a Unix socket, that is a file descriptor and two addresses: +the address the socket is bound to, and the address it is connected to. +An address needs to be bound to a socket only if another process wants to connect to this socket; +a socket needs to be connected to an address only for streams or connected datagrams. +Thus, none of the addresses is mandatory. + +Addresses are always referenced by pointers. +Smart pointers to addresses (\typ{^{pUchAddress}}) can be used anywhere a pointer is used. +?*/ + +/*? +Construct a closed socket. +?*/ +UchSocket :: UchSocket () +: UchChannel (), + BAddr (0), + CAddr (0), + AddrFamily (AF_UNSPEC) +{ +} + +/*? +Construct a closed socket bound to address \var{bound} and connected to address \var{connected}. +Each or both arguments may be 0. +?*/ +UchSocket :: UchSocket (UchAddress* bound, UchAddress* connected) +: UchChannel (), + BAddr (bound), + CAddr (connected), + AddrFamily (AF_UNSPEC) +{ +} + +/*?nodoc?*/ +UchSocket :: UchSocket (const UchSocket& s) +: UchChannel (s), + BAddr (s.BAddr), + CAddr (s.CAddr) +{ +} + +/*?nodoc?*/ +UchSocket :: ~UchSocket () +{ + // will unreference addresses and destroy them if necessary + BAddr = 0; + CAddr = 0; +} + +/*?nodoc?*/ +UchChannel* +UchSocket :: Copy () const +{ + return new UchSocket (*this); +} + +/*? +This virtual function returns the type of the socket: +one of \var{SOCK_UNSPEC}, \var{SOCK_STREAM}, \var{SOCK_DGRAM}, +depending on the class. +?*/ +int +UchSocket :: SockType () +{ + return SOCK_UNSPEC; +} + +/*?nextdoc?*/ +void +UchSocket :: BindTo (UchAddress* a) +{ + BAddr = a; +} + +/*? +Set the address a socket is to be bound to or connected to. +?*/ +void +UchSocket :: ConnectTo (UchAddress* a) +{ + CAddr = a; +} + +/*? +Open the socket (with the \fun{socket} system call) if it is not already open. +The socket must have an address bound or connected to get the protocol family, +or its family must have been defined with \fun{SetFamily}. +Return FALSE if the family is undefined or if a system error occurred. +?*/ +bool +UchSocket :: Open () +{ + errno = 0; + if (FilDes () >= 0) + return TRUE; + if (AddrFamily == AF_UNSPEC) { + if (BAddr) + AddrFamily = BAddr->Family (); + else if (CAddr) + AddrFamily = CAddr->Family (); + else + return FALSE; + } + int fd = socket (AddrFamily, SockType (), 0); + if (fd < 0) + return FALSE; + UchChannel::Open (fd); + return TRUE; +} + +/*?nextdoc?*/ +int +UchSocket :: Bind () +{ + if (! BAddr || ! BAddr->IsValid ()) + return -1; + if (! Open ()) + return -1; + int ret = bind (FilDes (), BAddr->GetSockAddr (), BAddr->Length ()); + if (ret < 0) + return ret; + + GEN_ADDR addr; + int alen = sizeof (addr); + if (getsockname (FilDes (), &addr.sa, &alen) < 0) + return -1; + BAddr = UchAddress::Decode (&addr, alen); + return ret; +} + +/*?nextdoc?*/ +int +UchSocket :: Bind (UchAddress* addr) +{ + if (addr) + BAddr = addr; + return Bind (); +} + +/*?nextdoc?*/ +int +UchSocket :: Connect () +{ + if (! CAddr || ! CAddr->IsValid ()) + return -1; + if (! Open ()) + return -1; + int ret = connect (FilDes (), CAddr->GetSockAddr (), CAddr->Length ()); + if (ret < 0) + return ret; + + GEN_ADDR addr; + int alen = sizeof (addr); + if (getpeername (FilDes (), &addr.sa, &alen) < 0) + return -1; + CAddr = UchAddress::Decode (&addr, alen); + return ret; +} + +/*? +These two functions implement the Unix system calls \fun{bind} and \fun{connect}. +If \var{addr} is given, it is first associated to the socket. +Then the socket is opened, and finally the system call is performed. +The returned value is that of the system call, unless opening failed in which case +-1 is returned. +?*/ +int +UchSocket :: Connect (UchAddress* addr) +{ + if (addr) + CAddr = addr; + return Connect (); +} + +/*? +Open the socket if it is not already open. +Bind and connect it depending on the addresses that are defined. +You should use this function instead of calling \fun{Open}, \fun{Bind} and +\fun{Connect}, for it is simpler. +This function returns FALSE if a system error occurred. In this case, the caller can +call \fun{SysError} to report the error. +?*/ +bool +UchSocket :: Setup () +{ + if (! Open ()) + return FALSE; + if (BAddr) + if (BAddr->IsValid ()) + if (Bind () < 0) + return FALSE; + if (CAddr) + if (CAddr->IsValid ()) + if (Connect () < 0) + return FALSE; + return TRUE; +} + +/*?nodoc?*/ +char* +UchSocket :: StrRepr (char* buf) +{ + UchChannel :: StrRepr (buf); + strcat (buf, " / "); + if (BAddr) + BAddr -> StrRepr (buf + strlen (buf)); + else + strcat (buf, "null"); + strcat (buf, " / "); + if (CAddr) + CAddr -> StrRepr (buf + strlen (buf)); + else + strcat (buf, "null"); + return buf; +} + +#ifdef DOC + +/*?nextdoc?*/ +int +UchSocket :: Family () +{ } + +/*? +These function get and set the family. +The possible values currently are \var{AF_UNSPEC}, \var{AF_UNIX} and \var{AF_INET}. +Other values may be defined if supported by the system. +The family must be defined for \fun{Open} (and thus \fun{Setup}) to succeed. +If an address is bound or connected to the socket, its family is used. +Thus, an application seldom needs to call \fun{SetFamily}. +?*/ +void +UchSocket :: SetFamily (int f) +{ } + +/*?nextdoc?*/ +UchAddress* +UchSocket :: BoundTo () +{ } + +/*? +Return the address currently bound or connected to the socket. +?*/ +UchAddress* +UchSocket :: ConnectedTo () +{ } + +#endif /* DOC */ + -- cgit v1.1