Source: socket.h


Annotated List
Files
Globals
Hierarchy
Index
// ##########################################################################
// ####                                                                  ####
// ####                      RTP Audio Server Project                    ####
// ####                    ============================                  ####
// ####                                                                  ####
// #### Socket                                                           ####
// ####                                                                  ####
// #### Version 1.00  --  February 23, 2001                              ####
// ####                                                                  ####
// #### Copyright (C) 1999  Thomas Dreibholz                             ####
// ####               2000  Universität Bonn, Abt. IV                    ####
// ####               2001  EMail: Dreibholz@bigfoot.com                 ####
// ####                     WWW:   http://www.bigfoot.com/~dreibholz     ####
// ####                                                                  ####
// ##########################################################################


#ifndef SOCKETCLASS_H
#define SOCKETCLASS_H


#include "system.h"
#include "internetaddress.h"
#include "internetflow.h"


namespace Coral {


/**
  * UDP header size.
  */
const cardinal UDPHeaderSize = 8;

/**
  * IPv4 header size.
  */
const cardinal IPv4HeaderSize = 20;

/**
  * IPv6 header size.
  */
const cardinal IPv6HeaderSize = 40;


/**
  * This class manages a socket. IPv6 support is automatically available,
  * when supported by the system.
  *
  * @short   Socket
  * @author  Thomas Dreibholz (Dreibholz@bigfoot.com)
  * @version 1.0
  */            
class Socket
{
   // ====== Definitions ====================================================
   public:
   enum SocketCommunicationDomain {
      UndefinedSocketCommunicationDomain = -1,
      IP                                 = 255,
      IPv4                               = AF_INET,  // Do not use IPv4/IPv6!
      IPv6                               = AF_INET6, // Use IP instead!
      Unix                               = AF_UNIX
   }; 
   enum SocketType {
      UndefinedSocketType = -1,
      UDP                 = SOCK_DGRAM,
      Datagram            = SOCK_DGRAM,
      TCP                 = SOCK_STREAM,
      Stream              = SOCK_STREAM,
      Raw                 = SOCK_RAW,
      RDM                 = SOCK_RDM,
      SeqPacket           = SOCK_SEQPACKET
   };
   enum SocketProtocol {
      UndefinedSocketProtocol = -1,
      Default                 = 0,
      ICMPv4                  = IPPROTO_ICMP,
      ICMPv6                  = IPPROTO_ICMPV6
   };

   // ====== Constructor/Destructor =========================================
   /**
     * Constructor.
     */
   Socket();

   /**
     * Constructor for a new socket. For automatic usage of IPv6 when available,
     * set communication domain to IP. Use IPv4/IPv6 only if a special
     * protocol version is necessary!
     * The creation success can be checked using ready() method.
     *
     * @param communicationDomain Communication domain (e.g. IP).
     * @param socketType Socket type (e.g. TCP, UDP).
     * @param socketProtocol Socket protocol (e.g. Default).
     *
     * @see ready
     */
   Socket(const SocketCommunicationDomain communicationDomain,
          const SocketType                socketType,
          const SocketProtocol            socketProtocol = Default);

   /**
     * Destructor.
     */
   virtual ~Socket();


   // ====== Create/close socket ============================================
   /**
     * Close existing socket and create new socket. For automatic usage of
     * IPv6 when available, set communication domain to IP.
     * Use IPv4/IPv6 only if a special protocol version is necessary!
     *
     * @param communicationDomain Communication domain (e.g. IP).
     * @param socketType Socket type (e.g. TCP, UDP).
     * @param socketProtocol Socket protocol (e.g. Default).
     * @return true, if creation was sucessful; false otherwise.
     */
   bool create(const SocketCommunicationDomain communicationDomain = IP,
               const SocketType                socketType          = TCP,          
               const SocketProtocol            socketProtocol      = Default);

   /**
     * Close socket.
     */
   void close();

   /**
     * Shutdown full-duplex connection partial or completely.
     * SHUT_RD - further receives will be disallowed.
     * SHUT_WR - further sends will be disallowed.
     * SHUT_RDWR - further sends and receives will be disallowed.
     *
     * @param shutdownLevel SHUT_RD, SHUT_WR, SHUT_RDWR.
     */
   void shutdown(const cardinal shutdownLevel);


   // ====== Statistics functions ===========================================
   /**
     * Get number of bytes sent.
     *
     * @return Number of bytes sent.
     */
   inline card64 getBytesSent() const;

   /**
     * Get number of bytes received.
     *
     * @return Number of bytes received.
     */
   inline card64 getBytesReceived() const;
   
   /**
     * Reset number of bytes sent.
     */
   inline void resetBytesSent();

   /**
     * Reset number of bytes received.
     */
   inline void resetBytesReceived();

   
   // ====== Socket control functions =======================================
   /**
     * Check, if socket is ready.
     *
     * @return true, if socket is ready; false otherwise.
     */
   inline bool ready() const;

   /**
     * Bind socket to given address. If address is null address, then
     * INADDR_ANY and an automatically selected port will be used.
     *
     * @param address Socket address.
     * @return true on success; false otherwise.
     */
   bool bind(const SocketAddress& address = InternetAddress());

   /**
     * Set socket to listen mode with given backlog (queue length for sockets
     * waiting for acception).
     *
     * @param backlog Backlog.
     * @return true on success; false otherwise.
     */
   bool listen(const cardinal backlog = 5);

   /**
     * Accept a connection.
     *
     * @return New socket.
     */
   Socket* accept();

   /**
     * Connect socket to given address. A value for traffic class is supported
     * if the connection is an IPv6 connection; otherwise it is ignored.
     *
     * @param address Address.
     * @param trafficClass Traffic class of the connection (IPv6 only!)
     * @return true on success; false otherwise.
     */
   bool connect(const SocketAddress& address, const card8 trafficClass = 0);


   // ====== Error code =====================================================
   /**
     * Get last error code. It will be reset to 0 after copying.
     *
     * @return Last error code.
     */
   inline integer getLastError();


   // ====== Socket options =================================================
   /**
     * Get socket option (wrapper for getsockopt());
     *
     * @param level Level (e.g. SOL_SOCKET).
     * @param optionNumber Option (e.g. SO_REUSEADDR).
     * @param optionValue Memory to store option got from getsockopt().
     * @param optionLength Memory with size of option memory.
     * @return Result from getsockopt().
     */
   inline integer getSocketOption(const cardinal level,
                                  const cardinal optionNumber,
                                  void*          optionValue,
                                  socklen_t*     optionLength) const;

   /**
     * Get SO_LINGER option of socket.
     *
     * @return SO_LINGER value.
     */
   cardinal getSoLinger() const;

   /**
     * Get SO_REUSEADDR option of socket.
     *
     * @return SO_REUSEADDR value.
     */
   bool getSoReuseAddress() const;

   /**
     * Get SO_BROADCAST option of socket.
     *
     * @return SO_BROADCAST value.
     */
   bool getSoBroadcast() const;

   /**
     * Get TCP_NODELAY option of socket.
     *
     * @return TCP_NODELAY value.
     */
   bool getTCPNoDelay() const;

   /**
     * Check, if blocking mode is on.
     *
     * @return true, if blocking mode is on; false otherwise.
     */
   bool getBlockingMode();


   /**
     * Get socket option (wrapper for getsockopt());
     *
     * @param level Level (e.g. SOL_SOCKET).
     * @param optionNumber Option (e.g. SO_REUSEADDR).
     * @param optionValue Memory with option.
     * @param optionLength Length of option memory.
     * @return Result from setsockopt().
     */
   inline integer setSocketOption(const cardinal  level,
                                  const cardinal  optionNumber,
                                  const void*     optionValue,
                                  const socklen_t optionLength);

   /**
     * Set SO_LINGER option of socket.
     *
     * @param on true to set linger on; false otherwise.
     * @param linger SO_LINGER in seconds.
     */
   void setSoLinger(const bool on, const cardinal linger);

   /**
     * Set SO_REUSEADDR option of socket.
     *
     * @param on true to set SO_REUSEADDR on; false otherwise.
     */
   void setSoReuseAddress(const bool on);

   /**
     * Set SO_BROADCAST option of socket.
     *
     * @param on true to set SO_BROADCAST on; false otherwise.
     */
   void setSoBroadcast(const bool on);

   /**
     * Set TCP_NODELAY option of socket.
     *
     * @param on true to set TCP_NODELAY on; false otherwise.
     */
   void setTCPNoDelay(const bool on);

   /**
     * Set blocking mode.
     *
     * @param on True to set blocking mode, false to unset.
     */
   void setBlockingMode(const bool on);


   // ====== Get flow label/traffic class ===================================
   /**
     * Get flow label of the connection.
     *
     * @return Flow label of the connection or 0, if there is no flow label.
     *
     * @see connect
     */
   inline card32 getSendFlowLabel() const;

   /**
     * Get traffic class of the connection.
     *
     * @return Traffic class of the connection or 0, if there is no traffic class.
     *
     * @see connect
     */
   inline card8 getSendTrafficClass() const;

   /**
     * Get last received flow label.
     *
     * @return Last received flow label or 0, if there is no flow label.
     */
   inline card32 getReceivedFlowLabel() const;

   /**
     * Get last received traffic class.
     *
     * @return Last received traffic class or 0, if there is no traffic class.
     */
   inline card8 getReceivedTrafficClass() const;

   
   // ====== I/O functions ==================================================
   /**
     * Wrapper for sendto().
     * sendto() will set the packet's traffic class, if trafficClass is not 0.
     *
     * @param buffer Buffer with data to send.
     * @param length Length of data to send.
     * @param flags Flags for sendto().
     * @param receiver Address of receiver.
     * @return Bytes sent or error code < 0.
     */   
   virtual ssize_t sendTo(const void*          buffer,
                          const size_t         length,
                          const cardinal       flags,
                          const SocketAddress& receiver,
                          const card8          trafficClass = 0);

   /**
     * Wrapper for send().
     * send() will set the packet's traffic class, if trafficClass is not 0.
     * In this case, the packet will be sent by sendto() to the destination
     * address, the socket is connected to!
     *
     * @param buffer Buffer with data to send.
     * @param length Length of data to send.
     * @param flags Flags for sendto().
     * @param trafficClass Traffic class for packet.
     * @return Bytes sent or error code < 0.
     */
   virtual ssize_t send(const void*    buffer,
                        const size_t   length,
                        const cardinal flags        = 0,
                        const card8    trafficClass = 0);

   /**
     * Wrapper for recvfrom().
     *
     * @param buffer Buffer to receive data to.
     * @param length Maximum length of data to be received.
     * @param sender Address to store sender's address.
     * @param flags Flags for recvfrom().
     * @return Bytes received or error code < 0.
     */   
   virtual ssize_t receiveFrom(void*          buffer,
                               const size_t   length,
                               SocketAddress& sender,
                               const cardinal flags = 0);

   /**
     * Wrapper for recv().
     *
     * @param buffer Buffer to read data to.
     * @param length Maximum length of data to be received.
     * @param flags Flags for recv().
     * @return Bytes read or error code < 0.
     */   
   virtual ssize_t receive(void*          buffer,
                           const size_t   length,
                           const cardinal flags = 0);

   /**
     * Wrapper for read().
     *
     * @param buffer Buffer to read data to.
     * @param length Maximum length of data to be received.
     * @return Bytes read or error code < 0.
     */   
   virtual ssize_t read(void*        buffer,
                        const size_t length);

   /**
     * Wrapper for write().
     *
     * @param buffer Buffer with data to write
     * @param length Length of data to write
     * @return Bytes sent or error code < 0.
     */
   virtual ssize_t write(const void*  buffer,
                         const size_t length);

   /**
     * Wrapper for fcntl().
     *
     * @param cmd Command.
     * @param arg Argument.
     * @return Result of fcntl() call.
     */   
   inline integer fcntl(const integer cmd, const long arg = 0);


   /**
     * Wrapper for ioctl().
     *
     * @param request Request.
     * @param argp Argument.
     * @return Result of ioctl() call.
     */   
   inline integer ioctl(const integer request, const void* argp);

                                                          
   // ====== Get address ====================================================
   /**
     * Get the socket's address. Note: A socket has to be bound to an address
     * and port or connected to a peer first to let the socket have an address!
     *
     * @param address Reference to SocketAddress to write address to.
     * @return true, if call was successful; false otherwise.
     *
     * @see bind
     * @see connect
     * @see getPeerAddress
     */
   bool getSocketAddress(SocketAddress& address) const;

   /**
     * Get the peer's address. Note: A socket has to be connected to a peer
     * first to get a peer address!
     *
     * @param address Reference to SocketAddress to write address to.
     * @return true, if call was successful; false otherwise.
     *
     * @see bind
     * @see connect
     * @see getSocketAddress
     */
   bool getPeerAddress(SocketAddress& address) const;


   // ====== IPv6 flow functions ============================================
   /**
     * Allocate a new flow to a given destination. A InternetFlow object is
     * returned, the value flow.getFlowLabel() will not be 0, if the allocFlow()
     * call was successful.
     *
     * @param address Address of the destination.
     * @param flowLabel Flowlabel; 0 for random value.
     * @param shareLevel Share level for flow label.
     * @return InternetFlow.
     */
   InternetFlow allocFlow(const InternetAddress& address,
                          const card32           flowLabel  = 0,
                          const card8            shareLevel = IPV6_FL_S_PROCESS);

   /**
     * Free a flow.
     *
     * @param flow Flow to be freed.
     */
   void freeFlow(InternetFlow& flow);

   /**
     * Renew a flow label allocation with given expires and linger
     * (default 6) values. The expires value gives the seconds to go
     * until the flow label expires, the linger value gives the timeout in
     * seconds the freed flow label cannot be allocated again.
     *
     * @param flow Flow to be renewed.
     * @param expires Seconds until the flow label expires.
     * @param linger Linger (default 6).
     * @return true on success; false otherwise.
     */
   bool renewFlow(InternetFlow&  flow,
                  const cardinal expires,
                  const cardinal linger = 6);

   /**
     * Renew current flow's flow label allocation with given expires and linger
     * (default 6) values.
     *
     * @param expires Seconds until the flow label expires.
     * @param linger Linger (default 6).
     * @return true on success; false otherwise.
     */
   bool renewFlow(const cardinal expires,
                  const cardinal linger = 6);


   // ====== Bind pair of internet sockets ==================================
   /**
     * Bind a pair of internet sockets to a given address and port number
     * x and x + 1. x will be a random number, if given port number is 0.
     *
     * @param senderSocket First socket.
     * @param receiverSocket Second socket.
     * @param receiver Address (e.g ipv6-localhost:0) or NULL for Any address.
     */
   static bool bindInternetSocketPair(Socket&                senderSocket,
                                      Socket&                receiverSocket,
                                      const InternetAddress& receiver = InternetAddress());


   // ====== Traffic shaper methods =========================================
   /**
     * Set traffic constraint to given byte rate. Packets exceeding the given
     * constraint will be dropped. Note: This functionality has to be
     * implemented by subclasses!
     *
     * @param trafficClass Traffic class.
     * @param bandwidth Bandwidth.
     * @param bufferDelay Maximum buffer delay in microseconds.
     */
   virtual void setTrafficConstraint(const card8  trafficClass,
                                     const card64 bandwidth,
                                     const double bufferDelay);

   /**
     * Flush traffic shaper buffer. Note: This functionality has to be
     * implemented by subclasses!
     */
   virtual void flush();


   // ====== Get system's socket descriptor =================================
   /**
     * Get system's socket descriptor.
     * Warning: It is not recommended to manipulate the socket directly.
     * Use Socket's methods instead.
     *
     * @return Socket descriptor.
     */
   inline int getSystemSocketDescriptor() const;


   // ====== Constants ======================================================
   /**
     * Minimum port number for bind()'s automatic port selection.
     *
     * @see bind
     */
   static const cardinal MinAutoSelectPort = 16384;

   /**
     * Maximum port number for bind()'s automatic port selection.
     *
     * @see bind
     */
   static const cardinal MaxAutoSelectPort = 65535;


   // ====== Private data ===================================================
   protected:
   friend class TrafficShaper;


   void init();
   bool setTOS(const card8 trafficClass);
   ssize_t recvFrom(int              fd,
                    void*            buf,
                    const size_t     len,
                    const integer    flags,
                    struct sockaddr* addr,
                    size_t*          addrlen);


   card64                    BytesSent;
   card64                    BytesReceived;
   card32                    SendFlow;
   card32                    ReceivedFlow;
   cardinal                  Backlog;
   cardinal                  LastError;
   int                       SocketDescriptor;
   sockaddr*                 Destination;
   SocketCommunicationDomain CommunicationDomain;
   SocketType                Type;
   SocketProtocol            Protocol;
};


}


#include "socket.icc"


#endif

Generated by: viper@odin on Fri Feb 23 12:41:26 2001, using kdoc 2.0a36.