/*
 * Copyright (C) 1997-2003 by Objective Systems, Inc.
 *
 * This software is furnished under a license and may be used and copied
 * only in accordance with the terms of such license and with the
 * inclusion of the above copyright notice. This software or any other
 * copies thereof may not be provided or otherwise made available to any
 * other person. No title to and ownership of the software is hereby
 * transferred.
 *
 * The information in this software is subject to change without notice
 * and should not be construed as a commitment by Objective Systems, Inc.
 *
 * PROPRIETARY NOTICE
 *
 * This software is an unpublished work subject to a confidentiality agreement
 * and is protected by copyright and trade secret law.  Unauthorized copying,
 * redistribution or other use of this work is prohibited.
 *
 * The above notice of copyright on this source code product does not indicate
 * any actual or intended publication of such source code.
 *
 *****************************************************************************/

/** 
 * @file OSCSocket.h 
 * TCP/IP or UDP socket class definitions.
 */
#ifndef _OSCSOCKET_H_
#define _OSCSOCKET_H_

#include "asn1CppTypes.h"
#include "rtSocket.h"

/** @defgroup socketCpp TCP/IP or UDP Socket Classes
 * These classes provide utility methods for doing socket I/O.
 * @ingroup cppruntime 
 * @{
 */

/**
 * Wrapper class for TCP/IP or UDP sockets.
 */
class EXTERNRT OSCSocket {
 protected:
   OSRTSOCKET mSocket;  ///< handle of the socket
   ASN1BOOL mOwner;     ///< indicates this class owns the socket

 public:
   /**
    * This is the default constructor. It initializes all internal members
    * with default values and creates a new socket structure.
    *
    * @exception OSCSocketException    socket can't be created.
    */
   OSCSocket ();

   /**
    * This constructor initializes an instance by using an existing socket.
    *
    * @param socket       An existing socket handle.
    * @param ownership    Boolean flag that specifies who is the owner of
    *                     the socket. If it is TRUE then the socket will be
    *                     destroyed in the destructor. Otherwise, the user is
    *                     responsible to close and destroy the socket.
    */
   OSCSocket (OSRTSOCKET socket, ASN1BOOL ownership = FALSE);
   
   /** 
    * The copy constructor. The copied instance will have the same socket
    * handle as the original one, but will not be the owner of the handle.
    */
//   OSCSocket (const OSCSocket& socket);
   
   /** 
    * The destructor. This closes socket if the instance is the owner of the
    * socket.
    */
//   ~OSCSocket ();

   /**
    * This method permits an incoming connection attempt on a socket. It
    * extracts the first connection on the queue of pending connections on
    * the socket. It then creates a new socket and returns an instance of 
    * the new socket. The newly created socket will handle the
    * actual connection and has the same properties as the original socket.
    *
    * @param destIP       Optional pointer to a buffer that receives the IP
    *                       address of the connecting entity. It may be NULL.
    * @param port         Optional pointer to a buffer that receives the port
    *                       of the connecting entity. It may be NULL.
    * @return             An instance of the new socket class.
    * @see               ::rtSocketAccept
    */
   OSCSocket* accept (OSIPADDR* destIP = 0, int *port = 0);

   /**
    * This method converts an IP address to its string representation.
    *
    * @param ipAddr                    The IP address to be converted.
    * @param pAddrStr                  Pointer to the buffer to receive a
    *                                    string with the IP address.
    * @param bufsize                   Size of the buffer.
    * @exception OSCSocketException    if buffer is too small.
    */
   static const char* addrToString (OSIPADDR ipAddr, 
                                    char* pAddrStr, 
                                    int bufsize);

   /**
    * This method associates a local address with a socket. It is used on an
    * unconnected socket before subsequent calls to the ::connect or ::listen
    * methods.
    *
    * @param addr                      The local IP address to assign to the
    *                                    socket.
    * @param port                      The local port number to assign to the
    *                                    socket.
    * @exception OSCSocketException    Call to bind system service failed.
    * @see                            ::rtSocketBind
    */
//   void bind (OSIPADDR addr, int port);

   /**
    * This method associates a local address with a socket. It is used on an
    * unconnected socket before subsequent calls to the ::connect or ::listen
    * methods.
    *
    * @param pAddrStr                  Null-terminated character string
    *                                    representing a number expressed in the
    *                                    Internet standard "." (dotted)
    *                                    notation.
    * @param port                      The local port number to assign to the
    *                                    socket.
    * @exception OSCSocketException    Call to bind system service failed.
    * @see                            ::rtSocketBind
    */
//   void bind (const char* pAddrStr, int port);

   /**
    * This method associates only a local port with a socket. It is used on an
    * unconnected socket before subsequent calls to the OSCSocket::connect or
    * OSCSocket::listen methods.
    *
    * @param port                      The local port number to assign to the
    *                                    socket.
    * @exception OSCSocketException    Call to bind system service failed.
    * @see                            ::rtSocketBind
    * @see bind                        ()
    */
//   inline void bind (int port) {
//      bind (OSIPADDR_ANY, port);
//   }

   /**
    * This method closes this socket.
    *
    * @exception OSCSocketException    Call to close system service failed.
    * @see                            ::rtSocketClose
    */
   void close ();

   /**
    * This method establishes a connection to this socket. It is used to create
    * a connection to the specified destination. When the socket call completes
    * successfully, the socket is ready to send and receive data.
    *
    * @param host                      Null-terminated character string
    *                                    representing a number expressed in the
    *                                    Internet standard "." (dotted)
    *                                    notation.
    * @param port                      The destination port to connect.
    * @exception OSCSocketException    Call to connect system service failed.
    * @see                            ::rtSocketConnect
    */
   void connect (const char* host, int port);

   /**
    * This method returns the handle of the socket.
    *
    * @return             The handle of the socket.
    */
   OSRTSOCKET getSocket () const { return mSocket; }

   /**
    * This method places a socket into a state where it is listening for 
    * an incoming connection.
    *
    * @param maxConnections            Maximum length of the queue of pending
    *                                    connections.
    * @exception OSCSocketException    Call to listen system service failed.
    * @see                            ::rtSocketListen
    */
   void listen (int maxConnections);

   /**
    * This method receives data from a connected socket. It is used to read
    * incoming data on sockets. The socket must be connected before calling
    * this function.
    *
    * @param pbuf                      Pointer to the buffer for the incoming
    *                                    data.
    * @param bufsize                   Length of the buffer.
    * @return                          If no error occurs, returns the number
    *                                    of bytes received.
    * @exception OSCSocketException    Call to recv system service failed.
    * @see                            ::rtSocketRecv
    */
   int recv (ASN1OCTET* pbuf, ASN1UINT bufsize);

   /**
    * This method sends data on a connected socket. It is used to write
    * outgoing data on a connected socket.
    *
    * @param pdata                     Buffer containing the data to be
    *                                    transmitted.
    * @param size                      Length of the data in pdata.
    * @exception OSCSocketException    Call to send system service failed.
    * @see                            ::rtSocketSend
    */
   void send (const ASN1OCTET* pdata, ASN1UINT size);

   /**
    * This method converts a string containing an Internet Protocol dotted
    * address into a proper OSIPADDR address.
    *
    * @param pAddrStr                  Null-terminated character string
    *                                    representing a number expressed in the
    *                                    Internet standard "." (dotted)
    *                                    notation.
    * @exception OSCSocketException    Format of address string is invalid.
    */
   static OSIPADDR stringToAddr (const char* pAddrStr);
} ;

/** 
 * Exception class for sockets.
 */
class EXTERNRT OSCSocketException : public ASN1RTLException {
 public:
   OSCSocketException (int stat) : ASN1RTLException(stat) {}
} ;

/** @} */
#endif //_OSCSOCKET_H_
