/* libzzsock
 *
 * This program is distributed under the GNU General Public License, version 2.
 * A copy of this license is included with this source.
 *
 * Copyright 2000-2006, Toni Thomsson <toni@tonjac.org> 
*/

#ifndef zz_socket_h
#define zz_socket_h

#ifdef _WIN32
    #include <winsock2.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h> 
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <errno.h>
    typedef int SOCKET;
    #define INVALID_SOCKET -1
    #define SOCKET_ERROR -1
#endif

#include <zz_string.h>
#include <zz_exception.h>
#include <zz_sock_exception.h>
#include <zz_export.h>

/*
    Description:
    TCP Socket

    Author: 
    Toni Thomsson, toni@tonjac.org

    Library:
    libzzsock.a (HPUX) libzzsock.lib (win32)

    Platform:
    HPUX, win32
*/
class ZZ_API CzzSocket
{
public:

    /*
        Description: 
        Skapar en socket
    
        Remarks: 
        Kopplar upp som en server

        Throws:
        CzzSockException
    */
    CzzSocket( const char* port,    // IN, port
                int que             // IN, antal inkommande anrop som köas
                );

    /*
        Remarks: 
        Kopplar upp som en klient
    */
    CzzSocket( const char* host,            // IN, host
                const char* port,           // IN, port
                unsigned short s_timeout,   // IN, send timeout
                unsigned short r_timeout    // IN, receive timeout
                );

    /*
        Remarks: 
        Skapar ett socket-objekt från ett befintligt handtag
    */
    CzzSocket( SOCKET socket,       // IN, socket handtag 
                const char* host    // IN, host
                );

    /*
        Remarks: 
        Kopieringskonstruktor
    */
    CzzSocket( CzzSocket& obj 
                );
    /*
        Remarks:
        Defaultkonstruktor: kopplar inte upp, anropa ConnectAsClient eller ConnectAsServer
    */
    CzzSocket( void );
    
    virtual ~CzzSocket();

    /*
        Description: 
        Lyssnar efter inkommande anrop

        Returns:
        Ny socket för snack med anropande klient

        Throws:
        CzzSockException
    */
    CzzSocket* Accept( void );

    /*
        Description: 
        Läser data från socket

        Returns:
        Antal lästa bytes

        Throws:
        CzzSockException
    */
    int Receive( char* receiveBuffer,   // UT, data-buffert
                    int bufferSize,     // IN, storlek på buffert
                    int bytesAquired,   // IN, antal bytes att läsa
                    int flags           // IN, flaggor, se recv()
                    );

    /*
        Description: 
        Skickar data via socket

        Returns:
        Antal skickade bytes

        Throws:
        CzzSockException
    */
    int Send( char* sendBuffer, // IN, databuffert
                int bufferSize, // IN, storlek på buffert
                int flags       // IN, flaggor, se send()
                );

    /*
        Description: 
        Kopplar upp socket som en server

        Throws:
        CzzSockException
    */
    void ConnectAsServer( void );

    /*
        Description: 
        Kopplar upp socket som en klient

        Throws:
        CzzSockException
    */
    void ConnectAsClient( void );
    
    /*
        Description: 
        Kopplar ner socket

        Throws:
        CzzSockException
    */
    void Disconnect( void );

    // Description: Socket-handtag
    SOCKET GetSocket( void ) { return m_Socket; };
    
    // Description: Host-namn
    CzzString GetHost( void ) { return m_Host; };

    // Description: Port
    CzzString GetPort( void ) { return m_Port; };

    // Description: Antal som läggs i kö
    unsigned int GetQue( void ) { return m_Que; };

    // Description: Send timeout
    unsigned short GetSendTimeout( void ) { return m_SendTimeout; };

    // Description: Receive timeout
    unsigned short GetReceiveTimeout( void ) { return m_ReceiveTimeout; };

    // Description: Sätter hostnamn
    void SetHost( const CzzString& host ) { m_Host = host; };

    // Description: Sätter port
    void SetPort( const CzzString& port ) { m_Port = port; };

    // Description: Sätter kö antal
    void SetQue( unsigned int que ) { m_Que = que; };

    // Description: Sätter send timeout
    void SetSendTimeout( unsigned short to ) { m_SendTimeout = to; };

    // Description: Sätter receive timeout
    void SetReceiveTimeout( unsigned short to ) { m_ReceiveTimeout = to; };

    // Description: Aktuell host
    CzzString GetCurrentHost( void );

    void setNonBlocking( bool nonblock );
    
    /*
        Description: 
        Initierar socket API

        Remarks:
        Behövs endast anropas under win32. Skall anropas innan man
        skapar några CzzSocket-objekt

        Throws:
        CzzSockException
    */
    static void Init( void );

    /*
        Description: 
        Städar upp socket API

        Remarks:
        Behövs endast anropas under win32
    */
    static void Exit( void );

protected:

    SOCKET m_Socket;
    CzzString m_Host;
    CzzString m_Port;
    unsigned int m_Que;
    unsigned short m_SendTimeout;
    unsigned short m_ReceiveTimeout;

    bool isDataAvailable( SOCKET sock );

};

#endif // zz_socket_h