From 905bf95bf81a2c3bd7205d6da337dc8065ce8ebb Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Wed, 31 Jan 2007 16:22:17 +0000
Subject: [PATCH] Finished ClientSocketHandle documentation

---
 Socket/ClientSocketHandle.ct |  10 +-
 Socket/ClientSocketHandle.hh | 335 +++++++++++++++++++++++++++--------
 Socket/SocketPolicy.hh       |  16 +-
 3 files changed, 279 insertions(+), 82 deletions(-)

diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct
index 3f5112fc1..9379c7c6a 100644
--- a/Socket/ClientSocketHandle.ct
+++ b/Socket/ClientSocketHandle.ct
@@ -100,8 +100,14 @@ prefix_ unsigned senf::ClientSocketHandle<Policy>::available()
 {
     unsigned nread = this->protocol().available();
     if (nread == 0 && this->blocking()) {
-            this->waitReadable();
-            nread = this->protocol().available();
+	// We have to block explicitly here so we can return the
+	// number of bytes available explicitly. If no more date can
+	// be expected to arive (i.e. the other end has closed the
+	// connection), the socket will always be in the readable
+	// state. This is the only case when available() will return
+	// 0.
+	this->waitReadable();
+	nread = this->protocol().available();
     }
     return nread;
 }
diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh
index 49eafe9af..318c83d0a 100644
--- a/Socket/ClientSocketHandle.hh
+++ b/Socket/ClientSocketHandle.hh
@@ -43,11 +43,9 @@ namespace senf {
 
     /** \brief Generic SocketHandle with client interface
 	
-	This class provides the client side policy interface of the
-	socket abstraction. ClientSocketHandle defines the complete
-	policy interface. It does not implement any functionality
-	itself however. All calls are forward to the following policy
-	classes:
+	This class provides the client side policy interface of the socket
+	abstraction. ClientSocketHandle defines the complete policy interface. It does not implement
+	any functionality itself however. All calls are forward to the following policy classes:
 
 	<table class="senf">
 	<tr><th>ClientSocketHandle member</th> <th>Policy member</th></tr>
@@ -63,38 +61,31 @@ namespace senf {
 	<tr><td>sndbuf()</td>     <td>BufferingPolicy::rcvbuf (\ref senf::BufferingPolicyBase)</td></tr>
 	</table>
 
-	It is important to note, that not all members are always
-	accessible. Which are depends on the \c Policy template
-	argument. If any of the policy axis is left unspecified the
-	corresponding members will not be callable (you will get a
-	compile time error). Even if every policy axis is defined,
-	some members might (and will) not exist depending on the exact
-	policy. To find out, which members are available, you have to
-	check the documentation of the policy classes. You can also
-	find a summary of all active members in the leaf protocol
-	class documentation.
-
-	\todo Move all not template-parameter dependent code into a
-	non-template base class
-
-	\idea Give SocketHandle (and therefore ClientSocketHandle and
-	ServerSocketHandle) a \c protocol() template member and an
-	additional template arg \c Policies. This arg should be a
-	typelist of Poclicy classes which can be accessed. You use
-	protocol<ProtocolClass>() to access a protocol class. \c
-	Policies can of course be underspecified or even empty.
-
-	\idea add more flexible read/write members for a)
-	boost::arrays and arrays of other types b) std::vector (which
-	uses contiguous memory ..) c) other random-access containers
-	(we should use some configurable trait class to identify
-	containers with contiguous storage). Probably we should just
-	use a generic Boost.Range interface. Here we again come to the
-	point: make all except the most basic members be non-member
-	algorithms ? this would make the configuration of such
-	extenden members more flexible.
-
-	\see \ref policy_group
+	It is important to note, that not all members are always accessible. Which are depends on
+	the \c Policy template argument. If any of the policy axis is left unspecified the
+	corresponding members will not be callable (you will get a compile time error). Even if
+	every policy axis is defined, some members might (and will) not exist if they are
+	meaningless for the protocol of the socket. This depends on the exact policy.
+
+	To find out, which members are available, you have to check the documentation of the policy
+	classes. You can also find a summary of all members available in the leaf protocol class
+	documentation.
+
+	\todo Move all not template-parameter dependent code into a non-template base class
+
+	\idea Give SocketHandle (and therefore ClientSocketHandle and ServerSocketHandle) a \c
+	protocol() template member and an additional template arg \c Policies. This arg should be a
+	typelist of Poclicy classes which can be accessed. You use protocol<ProtocolClass>() to
+	access a protocol class. \c Policies can of course be underspecified or even empty.
+
+	\idea add more flexible read/write members for a) boost::arrays and arrays of other types b)
+	std::vector (which uses contiguous memory ..) c) other random-access containers (we should
+	use some configurable trait class to identify containers with contiguous storage). Probably
+	we should just use a generic Boost.Range interface. Here we again come to the point: make
+	all except the most basic members be non-member algorithms ? this would make the
+	configuration of such extenden members more flexible.
+
+	\see \ref policy_group \n
              \ref protocol_group
       */
     template <class Policy>
@@ -105,8 +96,19 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
+	/// Address type from the addressing policy
         typedef typename Policy::AddressingPolicy::Address Address;
+	/// 'Best' type for passing address as parameter
+	/** Depending on the type of \c Address, this will be either <tt>Address</tt> or <tt>Address
+	    const &</tt>. See <a href="http://www.boost.org/libs/utility/call_traits.htm"
+	    class="ext">call_traits documentation in the Boost.Utility library\endlink.</a>
+	 */
         typedef typename boost::call_traits<Address>::param_type AddressParam;
+	/// Corresponding server socket handle with the same policy
+	/** This class will probably only be usable, if the \c CommunicationPolicy is \c
+	    ConnectedCommunicationPolicy and the \c AddressingPolicy is not \c
+	    NoAddressingPolicy. */
+	 */
         typedef ServerSocketHandle<Policy> ServerSocketHandle;
 
         ///////////////////////////////////////////////////////////////////////////
@@ -134,68 +136,248 @@ namespace senf {
         ///\name Reading and Writing
         ///@{
 
-        // read from socket (connected or unconnected)
+	/** \brief Read data from socket
+
+	    If the sockets \c FramingPolicy is \c DatagramFramingPolicy, every read() command will
+	    return a single datagram. If the sockets FramingPolicy is StreamFraming, the operation will
+	    return as much data as possible from the socket buffer. However it cannot be guaranteed,
+	    that the socket buffer will be empty after read() returns.
+
+	    \attention If the space available for the data read is limited, the read will return no
+	    more than that amount of data. For a datagram socket, a full datagram is still dequed
+	    from the socket buffer, the remainder of the datagram will be lost.
+
+	    There are three variants of read which differ in how they return the read string. 
+
+	    \throws senf::SystemException
+
+
+	    This variant will read up to \c limit bytes from the
+	    socket and return them as a \c std::string object.
+
+	    On a blocking socket, this member will \e always return some data (as long as the socket
+	    has not been closed at the other end) and will block, if no data is available now. If
+	    you do not want to block, you \e must make the socket non-blocking (using
+	    FileHandle::blocking()).
+
+	    \param[in] limit Maximum number of bytes to read or 0 if unlimited.
+	    \returns data read
+	    
+	    \implementation The read() family of members will use standard POSIX \c read calls, not
+	    \c recv.
+	*/
         std::string  read         (unsigned limit=0);
         void         read         (std::string & buffer, unsigned limit=0);
+                                        ///< Read data into string buffer
+                                        /**< On a blocking socket, this member will \e always return
+					   some data (as long as the socket has not been closed at
+					   the other end) and will block, if no data is available
+					   now. If you do not want to block, you \e must make the
+					   socket non-blocking (using FileHandle::blocking()).
+					   \param[out] buffer data read
+					   \param[in] limit Maximum number of buytes to read or 0
+					   if unlimited 
+					   \see \ref read() */
         unsigned     read         (char * buffer, unsigned size);
+                                        ///< Read data into memory area
+                                        /**< This variant will read data into the memory area at \c
+					   buffer of size \c size. This is the most performant
+					   version of read().
+					   \param[in] buffer address of buffer to store data at
+					   \param[in] size size of memory buffer
+					   \returns Number of bytes read 
+					   \see \ref read() */
 
-        // read from unconnected socket returning peer address
-        std::pair<std::string, Address> 
+	/** \brief Read data from unconnected socket returning address
+
+	    This member behaves like read() but should only be available, if the sockets \c
+	    CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c AddressingPolicy is
+	    not \c NoAddressingPolicy. The readfrom() family will in addition to the data return the
+	    address of the sender.
+
+	    \throws senf::SystemException
+
+	    This variant will return the data read and the address as a std::pair.
+
+	    \returns \c std::pair of data read (a string) and the peers address
+
+	    \todo Add \c limit argument
+
+	    \implementation The readfrom() family of members will use \c recvfrom from the BSD
+	    socket API.
+	 */
+	std::pair<std::string, Address> 
                      readfrom     ();
         void         readfrom     (std::string & buffer, Address & from);
+                                        ///< Read data into string buffer
+                                        /**< This variant will return the result in the locations
+					   passed in
+					   \param[out] buffer data read
+					   \param[out] from peer address
+					   \see \ref readfrom() */
         unsigned     readfrom     (char * buffer, unsigned size, Address & from);
+                                        ///< Read data into memory byffer
+                                        /**< This variant will read data into the memory area at \c
+					   buffer of size \c size. This is the most performant
+					   version of readfrom().
+					   \param[in] buffer address of buffer to store data at
+					   \param[in] size size of bnuffer
+					   \param[out] from peer address
+					   \returns Number of bytes read
+					   \see \ref readfrom() */
+	
 
-        // write to connected socket
+	/** \brief Write data to socket
+
+	    The write() family of members will write out the data to the socket.  If the sockets \c
+	    FramingPolicy is \c DatagramFramingPolicy, every write() call will result in one
+	    datagram.
+
+	    A single write call might depending on the circumstances write only part of the data.
+
+	    There are two variants of thie member
+	    
+	    \throws senf::SystemException
+
+	    
+	    This variant will write out the string \c data.
+	    
+	    \param[in] data Data to write
+	    \returns number of bytes written
+	    \todo Make this member write the complete string if the socket is blocking
+	    \implementation The write() family of members will use POSIX \c write calls, not \c
+		send.
+	 */
         unsigned     write        (std::string const & data);
         unsigned     write        (char const * buffer, unsigned size);
+                                        ///< Write data to socket from memory buffer
+                                        /**< \param[in] buffer address of buffer to write
+					   \param[in] size amount of data to write
+					   \returns Number of bytes written
+					   \see \ref write() */
 
-        // write to unconnected socket
-        unsigned     writeto      (AddressParam addr, std::string const & data);
-        unsigned     writeto      (AddressParam addr, char const * buffer, unsigned size);
+	/** \brief Write data to unconnected socket
 
-        ///@}
+	    This member behaves like write() but should only be available, if the sockets \c
+	    CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c AddressingPolicy is
+	    not \c NoAddressingPolicy. The writeto() family of members takes the target address as
+	    an additional argument.
 
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Addressing
-        ///@{
+	    There are two variants of this member.
 
-        void         connect      (AddressParam addr);
-        void         bind         (AddressParam addr);
+	    \throw senf::SystemException
 
-        Address      peer         ();
-        void         peer         (Address & addr);
-        Address      local        ();
-        void         local        (Address & addr);
+	    
+	    This variant will send the string \c data to the peer \c addr.
 
-        ///@}
+	    \param[in] addr Address of peer to send data to
+	    \param[in] data data to send
+	    \returns Number of bytes written
+	 */
+	unsigned     writeto      (AddressParam addr, std::string const & data);
+	unsigned     writeto      (AddressParam addr, char const * buffer, unsigned size);
+                                        ///< Write data from memory buffer to unconnected socket
+                                        /**< \param[in] addr Address o fpeer to send data to
+					   \param[in] buffer address of buffer to write
+					   \param[in] size amount of data to write
+					   \returns Number of bytes written 
+					   \see \ref writeto() */
 
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Buffering
-        ///@{
-        
-        unsigned     rcvbuf      ();
-        void         rcvbuf      (unsigned size);        
-        unsigned     sndbuf      ();
-        void         sndbuf      (unsigned size);
-        
-        ///@}
-        
-        static ClientSocketHandle cast_static(FileHandle handle);
-        static ClientSocketHandle cast_dynamic(FileHandle handle);
+	///////////////////////////////////////////////////////////////////////////
+	///\name Addressing
+	///@{
+
+	/** \brief Connect to remote peer
+
+	    This member will establish a connection for addressable connection-oriented protocols
+	    (that is, the CommunicationPolicy is ConnectedCommunicationPolicy and the
+	    AddressingPolicy is not NoAddressingPolicy). 
+
+	    \param[in] addr Address to connect to
+
+	    \throws senf::SystemException
+	 */
+	void         connect      (AddressParam addr);
+
+	/** \brief Set local address
+	    
+	    For addressable protocols (AddressingPolicy is not NoAddressingPolicy), bind() will set
+	    the local address of the socket.
+
+	    \parm[in] addr Local socket address to asign
+
+	    \throws senf::SystemException
+	 */
+	void         bind         (AddressParam addr);
+
+	/** \brief Query remote address
+
+	    This member will return the address of the communication partner in addressable
+	    connection-oriented protocols (that is, the CommunicationPolicy is
+	    ConnectedCommunicationPolicy and the AddressingPolicy is not NoAddressingPolicy).
+
+	    There are two Variants of this member, one will return the address by value, the other
+	    takes a reference argument to elide the copy operation.
+
+	    \throws senf::SystemException
+	 */
+	Address      peer         ();
+	void         peer         (Address & addr);
+                                        ///< Query remote address
+                                        /**< \see \ref peer() */
+
+	/** \brief Query local address
+
+	    This member will return the address of the local socket in addressable protocols
+	    (AddressingPolicy is not NoAddressingPolicy).
+
+	    There are two Variants of this member, one will return the address by value, the other
+	    takes a reference argument to elide the copy operation.
+
+	 */
+	Address      local        ();
+	void         local        (Address & addr);
+                                        ///< Query local address
+                                        /**< \see \ref local() */
+
+	///@}
+
+	///////////////////////////////////////////////////////////////////////////
+	///\name Buffering
+	///@{
+
+	unsigned     rcvbuf      ();    ///< Check size of receive buffer
+                                        /**< \returns size of receive buffer in bytes */
+	void         rcvbuf      (unsigned size);
+                                        ///< Set size of receive buffer
+                                        /**< \param[in] size size of receive buffer in bytes */
+
+	unsigned     sndbuf      ();    ///< Check size of send buffer
+                                        /**< \returns size of send buffer in bytes */
+	void         sndbuf      (unsigned size);
+                                        ///< Set size of send buffer
+                                        /**< \param[in] size size of send buffer in bytes */
+
+	///@}
+
+	static ClientSocketHandle cast_static(FileHandle handle);
+                                        /**< \internal */
+	static ClientSocketHandle cast_dynamic(FileHandle handle);
+                                        /**< \internal */
 
-        // we need to override both since SocketHandle is *not* polymorphic
-        void state(SocketStateMap & map, unsigned lod=0);
-        std::string dumpState(unsigned lod=0);
+	// we need to override both since SocketHandle is *not* polymorphic
+	void state(SocketStateMap & map, unsigned lod=0);
+	std::string dumpState(unsigned lod=0);
 
     protected:
-        ClientSocketHandle(FileHandle other, bool isChecked);
-        explicit ClientSocketHandle(std::auto_ptr<SocketProtocol> protocol,
-                                    int fd = -1);
+	ClientSocketHandle(FileHandle other, bool isChecked);
+	explicit ClientSocketHandle(std::auto_ptr<SocketProtocol> protocol,
+				    int fd = -1);
 
     private:
-        unsigned available();
+	unsigned available();
 
-        friend class senf::ServerSocketHandle<Policy>;
+	friend class senf::ServerSocketHandle<Policy>;
     };
 
     /// @}
@@ -211,4 +393,5 @@ namespace senf {
 // Local Variables:
 // mode: c++
 // c-file-style: "senf"
+// fill-column: 100
 // End:
diff --git a/Socket/SocketPolicy.hh b/Socket/SocketPolicy.hh
index c7ed63ab6..708f18a31 100644
--- a/Socket/SocketPolicy.hh
+++ b/Socket/SocketPolicy.hh
@@ -24,12 +24,20 @@
     \brief Policy Framework public header
 
     \todo We should probably remove BufferingPolicy from the
-    interface, it does not make much sense (how did I come to include
-    it ??)
+	interface, it does not make much sense (how did I come to
+	include it ??)
     
     \todo Do we want to support separate read and write policies. This
-    allows to treat pipes within this framework however, is this worth
-    the effort?
+	allows to treat pipes within this framework however, is this
+	worth the effort?
+
+    \idea Creating a new Socket will create three new instances (The
+	handle, the body and the policy) of which two (body and
+	policy) live on the heap. This is expensive. We should check,
+	wether we can make all the policy classes to singletons and
+	assign the same instance to all socket bodies with the same
+	policy. This would reduce the number of allocations per socket
+	handle to one.
  */
 
 /** \defgroup policy_group The Policy Framework
-- 
GitLab