/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWEAR_IPCONNECTION_H
#define __IWEAR_IPCONNECTION_H

#ifndef __IWEAR_SOCKETCONNECTION_H
#include <net/socketconnection.h>
#endif

#ifndef __IWEAR_IPV6ADDRESS_H
#include <net/ipv6address.h>
#endif

namespace iwear
{
    namespace net
    {

class IPConnection : public SocketConnection
{
private:
protected:
   /**
    * This function is called ONCE after a connect and/or accept. It will get
    * and write down all information about this connection. If the real
    * connection is another one than that one specified in bind() it will be
    * overwritten here.
    */
    void gather_connection_information( void );

    string ip_local;

    string ip_remote;

    uint16_t port_local;

    uint16_t port_remote;

    sockaddr* peer;

    socklen_t addrlen;
    
public:

    const string& get_local_ip( void ) const { return ip_local; }

    const string& get_remote_ip( void ) const { return ip_remote; }

    uint16_t get_local_port( void ) const { return port_local; }

    uint16_t get_remote_port( void ) const { return port_remote; }

    IPConnection( ip_version ipv, block_mode bm, int t, int p);

    virtual ~IPConnection();

    virtual void disconnect( void );

   /**
    * Connects to another ip endpoint. The IP Version (IPv4 vs. IPv6) is
    * beeing set at construction time, so it will not be possible to change it
    * during runtime.
    * For UDP sockets, this will only locally set the address where packets are
    * send to, so a connect should always succeed
    * @note When in non_blocking mode, it throws an exception when timed out.
    * When in blocking mode, the timeout is not obeyed, since the OS call will
    * block.
    */

    virtual void connect( const string& ip, uint16_t port, float timeout = DEFAULT_TIMEOUT );

    virtual void connect( const IPAddress& ip, uint16_t port, float timeout = DEFAULT_TIMEOUT );

    virtual void bind( const string& ip, uint16_t port, ip_version ipv = IPAny );
    
    virtual void bind( const IPAddress& ip, uint16_t port, ip_version ipv = IPAny );

    virtual void bind( uint16_t port, ip_version ipv = IPAny );

    static socklen_t fill_sockaddr( sockaddr*& peer, const IPAddress& ip, int port );

    static string ip_to_string( const sockaddr_in* add );
};

}
}
#endif
