Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/io/socket.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal (petter.urkedal@matfys.lth.se)
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: socket.h,v 1.2 2002/07/30 17:46:03 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_IO_SOCKET_H
00031 #define MORE_IO_SOCKET_H
00032 
00033 #include <iostream>
00034 #include <more/lang/stdint.h>
00035 #include <more/gen/utility.h>
00036 #include <more/bits/fdstreambuf.h>
00037 #include <string>
00038 #include <list>
00039 #include <stdexcept>
00040 
00041 namespace more {
00042 namespace io {
00043 
00044   ///\if bits
00045   struct socket_base
00046   {
00047       typedef int family_type;
00048 //       static const int family_local;
00049       static const int family_inet4;
00050       static const int family_inet6;
00051 //       static const int family_ipx;
00052       // XXX
00053   };
00054   ///\endif
00055 
00056   /** \class internet_address socket.h more/io/socket.h
00057    ** An IP number. */
00058   struct internet_address : socket_base
00059   {
00060       /** Construct an undefined address. */
00061       internet_address() : m_ptr_in_addr(0)/*, m_size_in_addr(0)*/ {}
00062 
00063       /** Don't use this, use 'host_address' for name lookup an pick
00064        ** one of the IP addresses from the provided iterator range. */
00065       explicit internet_address(std::string);
00066 
00067       /** Construct a deep copy of the address. */
00068       internet_address(internet_address const&);
00069 
00070       ~internet_address();
00071 
00072       /** Assign a deep copy. */
00073       internet_address& operator=(internet_address const&);
00074 
00075       /** The IP address family.  This is typically 'family_inet4'
00076        ** meaning and IP version 4 quad. */
00077       family_type family() const { return m_family; }
00078 
00079       /** Return true of the address is defined. */
00080       bool is_defined() const { return m_ptr_in_addr; }
00081 
00082       void from_unix_in_addr(family_type family, void*);
00083       void* to_unix_in_addr() { return m_ptr_in_addr; }
00084       void const* to_unix_in_addr() const { return m_ptr_in_addr; }
00085       void to_unix(void*) const;
00086       std::size_t unix_size() const;
00087 
00088     protected:
00089       void* m_ptr_in_addr;
00090 //       size_t m_size_in_addr;
00091       family_type m_family;
00092   };
00093 
00094   std::istream& operator>>(std::istream&, internet_address&);
00095   std::ostream& operator<<(std::ostream&, internet_address const&);
00096 
00097   struct address_ipv4 : internet_address
00098   {
00099       address_ipv4(unsigned char* bytes);
00100   };
00101 
00102   struct address_ipv6 : internet_address
00103   {
00104       address_ipv6(unsigned char* bytes);
00105   };
00106 
00107   /** \class host_address socket.h more/io/socket.h
00108    ** Internet name and address information for a host. */
00109   struct host_address : socket_base
00110   {
00111       typedef std::list<internet_address>::const_iterator ip_address_iterator;
00112       typedef std::pair<ip_address_iterator, ip_address_iterator>
00113               ip_address_range;
00114 
00115       typedef std::list<std::string>::const_iterator host_alias_iterator;
00116       typedef std::pair<host_alias_iterator, host_alias_iterator>
00117               host_alias_range;
00118 
00119       /** Construct a host address from \a name possibly using
00120        ** nameserver lookup. */
00121       host_address(std::string const& name);
00122 
00123       /** Return the official name of this host. */
00124       std::string const& host_name() const { return m_name; }
00125 
00126       /** Return a range of aliases for this host. */
00127       host_alias_range
00128       host_aliases() const
00129       { return host_alias_range(m_aliases.begin(), m_aliases.end()); }
00130 
00131       /** Return a range of the IP addresses of this host. */
00132       ip_address_range
00133       ip_addresses() const
00134       { return ip_address_range(m_numbers.begin(), m_numbers.end()); }
00135 
00136     private:
00137       std::string m_name; // official name
00138       std::list<std::string> m_aliases;
00139       std::list<internet_address> m_numbers;
00140   };
00141 
00142 
00143   /** \class socket_address socket.h more/io/socket.h
00144    ** A socket address.  For network connections, this contains an
00145    ** internet address and information needed by the specified
00146    ** protocol family, like the port number for IP V4 and IP V6. */
00147   struct socket_address : socket_base
00148   {
00149       typedef lang::uint16_t port_type;
00150 
00151       /** Construct an undefined socket address. */
00152       socket_address() : m_ptr_sockaddr(0), m_size_sockaddr(0) {}
00153 
00154       /** Construct a deep copy of a socket address. */
00155       socket_address(socket_address const&);
00156 
00157       ~socket_address();
00158 
00159       /** Assign a deep copy of a socket address. */
00160       socket_address& operator=(socket_address const&);
00161 
00162       /** true if it contains a socket address. */
00163       bool is_defined() const { return m_ptr_sockaddr; }
00164 
00165       /** returns the protocol family. */
00166       family_type family() const;
00167 
00168       /** returns the port if applicable. */
00169       port_type port() const;
00170 
00171       void from_unix(void*, std::size_t size);
00172       void* to_unix() { return m_ptr_sockaddr; }
00173       void const* to_unix() const { return m_ptr_sockaddr; }
00174       std::size_t unix_size() const;
00175 
00176     protected:
00177       void assert_defined() const {
00178           if (!is_defined())
00179               throw std::logic_error("more::socket_address: "
00180                                      "Uninitialized socket address.");
00181       }
00182       void* m_ptr_sockaddr;
00183       std::size_t m_size_sockaddr;
00184       friend std::ostream& operator<<(std::ostream&, socket_address const&);
00185       friend std::istream& operator>>(std::istream&, socket_address&);
00186   };
00187 
00188   struct socket_address_ipv4 : socket_address
00189   {
00190       socket_address_ipv4(port_type port, internet_address const& addr);
00191   };
00192 
00193   struct socket_address_ipv6 : socket_address
00194   {
00195       socket_address_ipv6(port_type port, lang::uint32_t flowinfo,
00196                           internet_address const& addr,
00197                           lang::uint32_t scope_id);
00198   };
00199 
00200 
00201   /** A stream that can be attached to a socket.  Using the default
00202    ** ctor, a socket is initially in \c state_unbound.  The scenario
00203    ** then depends on whether the program is a client or a server.
00204    **
00205    ** If the program
00206    ** is a server, it will typically call the \c bind member function
00207    ** to associate to a port, and then \c listen to indicate that it
00208    ** is ready to accept connections from clients.  The socket will
00209    ** then be in \c state_listening.  Requests from clients are
00210    ** processed by constructing new sockets from the return value of
00211    ** \c accept.  The new sockets will be in \c state_accepted,
00212    ** whereas the socket from which the connections are popped will
00213    ** stay in \c state_listening.
00214    **
00215    ** A client program simply calls \c connect to establish a
00216    ** connection with the server.  It will then enter \c
00217    ** state_connected.
00218    **
00219    ** Some members returns <tt>false</tt> in case of failure.  This
00220    ** will also store the corresponding error condition internally,
00221    ** which can be probed with <tt>errno()</tt>.  Member functions
00222    ** will throw a logic error if it detects an error from the callers
00223    ** side, i.e. not originating from the unpredictable outside
00224    ** world. */
00225   struct socket
00226       : std::iostream, gen::noncopyable, socket_base
00227   {
00228       /* The state of a socket. */
00229       enum state_type
00230       {
00231           state_unbound,
00232           state_bound,
00233           state_listening,
00234           state_accepted,
00235           state_connected
00236       };
00237 
00238     private:
00239       struct _sub_init
00240       {
00241           _sub_init() {}
00242           _sub_init(_sub_init const& x) : m_fd(x.m_fd), m_sa(x.m_sa) {}
00243           _sub_init& operator=(_sub_init const& x) { return *this; }
00244 
00245       private:
00246           int m_fd;
00247           socket_address m_sa;
00248           int m_errno;
00249           friend class socket;
00250       };
00251 
00252     public:
00253       // Protcol families (see manpage socket(2)).
00254 
00255       // Communication types
00256       static const int type_stream;
00257 //       static const int type_dgram;
00258 //       static const int type_seqpacket;
00259 //       static const int type_raw;
00260 //       static const int type_rdm;
00261 //       static const int type_packet;
00262 
00263       /** Construct a socket in \c states_unbound, i.e. not attached
00264        ** to any port. */
00265       socket();
00266 
00267       /** Construct a socket from the return value of accept.  The
00268        ** socket will be in \c state_accepted, meaning that it has
00269        ** accepted a connection from a client and is ready to serve it
00270        ** by communicating over the \c std::iostream base class. */
00271       socket(_sub_init init);
00272 
00273       /** Destruction which closes the socket. */
00274       ~socket() { delete rdbuf(); close(); }
00275 
00276     private:
00277       /** open the socket. You don't need to do this explicitely, just
00278        ** call bind or connect directly. */
00279       bool open(family_type family);
00280 
00281       /** Open a socket based on the return value of accept.  Return
00282        ** true if the corresponding call to <tt>accept</tt> was
00283        ** successful, otherwise return false.  */
00284       bool open(_sub_init init);
00285 
00286     public:
00287       /** Close the socket. Normally you don't need to call this, see
00288        ** open(). */
00289       void close();
00290 
00291       /** Return the state of the socket. */
00292       state_type state() const { return m_state; }
00293 
00294       /** Return true iff the socket can be read from or written
00295        ** to. This is the case iff it is in the connected or the
00296        ** accepted state. */
00297       bool is_streamable() const
00298       {
00299           return m_state == state_connected || m_state == state_accepted;
00300       }
00301 
00302       /** Connect a socket to a remote IP V4 or V6 address.  If
00303        ** successful, return true and change to
00304        ** <tt>state_connected</tt>, else return false. */
00305       bool connect(socket_address const&);
00306 
00307       /** Bind a socket to a local IP V4 or V6 address.  After binding
00308        ** to the address, you may call \c listen to make the server
00309        ** accessible at this address.  If successful, change to \c
00310        ** state_bound and return true, else return false. */
00311       bool bind(socket_address const&);
00312 
00313       /** Signal that we are ready to accept connections.  If
00314        ** successful switch to <tt>state_listening</tt> and return
00315        ** true, else return false. */
00316       bool listen(int backlog = 5);
00317 
00318       /** Pop a connection off a listening socket. The return type can
00319        ** be used as an argument to the ctor or \c open member of
00320        ** another socket object.  If successful the socket constructed
00321        ** will be in <tt>state_accepted</tt>, otherwise it will be in
00322        ** <tt>state_unbound</tt>.  A failure of this member function
00323        ** does not affect the state of the listening socket which it
00324        ** was called from.  */
00325       _sub_init accept();
00326 
00327       /** Returns the address of the socket. */
00328       socket_address const& address() const { return m_sa; }
00329 
00330       /** Returns the C \c errno from the last error.  This can be
00331        ** passed to <tt>diag::strerror</tt> to obtain an informative
00332        ** description of the failure, or to
00333        ** <tt>diag::errno_exception</tt> to throw an exception with
00334        ** such a message.  The result of this function only makes
00335        ** sense if there has been an error. */
00336       int the_errno() const { return m_errno; }
00337 
00338     private:
00339       io::bits::fdstreambuf*
00340       rdbuf()
00341       {
00342           return static_cast<bits::fdstreambuf*>(std::iostream::rdbuf());
00343       }
00344 
00345       socket_address    m_sa;
00346       state_type        m_state;
00347       int               m_fd;
00348       int               m_errno;
00349   };
00350 
00351 }} // more::io
00352 
00353 #endif

Generated on Sat Sep 7 19:11:16 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.