// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1994
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        inetsocket.h
// 
// Purpose:     
// 
// Created:     4 May 95   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// 
// </file> 
#ifndef hg_dc_common_inetsocket_h
#define hg_dc_common_inetsocket_h

#include "socket.h"

#include <sys/types.h>
#include <netinet/in.h>

class INETAddress : public sockaddr_in {
public:
   INETAddress() ;
   INETAddress (const char* hostaddr, int port) ; /* addr in numbers-and-dots, port in host byte order */
   INETAddress (const sockaddr_in&) ;

   INETAddress& operator = (const sockaddr_in&) ;

   const char* host() const ; // my sockaddr_in.sin_addr, converted by inet_ntoa()
   int port() const ; // my sockaddr_in.sin_port after ntohs() (i.e., in host byte order)

   boolean operator == (const INETAddress&) const ;
   boolean operator <  (const INETAddress&) const ;
   boolean operator != (const INETAddress& a) const { return !operator==(a); }

   boolean ok() const { return sin_addr.s_addr || sin_port; }
   boolean operator !() const { return !ok(); }
   operator void*() const { return (void*)ok(); }
} ;
inline class ostream& operator << (class ostream& s, const INETAddress&) {
   return s ;
}


class INETSocketPtr ;

// <class> 
//  
// Name:             INETSocket
// 
// Purpose:          
// 
// an Internet domain socket (no na)
// 
// Public Interface: 
// 
// - INETSocket()
//   default constructor. the underlying file number is invalid, no operations 
//   will work. (see class File.)
// - INETSocket (int fd, boolean close)
//   assign me the file number fd which has to be closed on destruction if close 
//   is true.
// - INETSocket (const char* host, int port)
//   connect to the specified internet host. if the connection fails, the file 
//   number will be invalid.
// - INETSocket (int port)
//   opens an Internet port and starts listening on it immediately.
// - void attach (int fd, boolean close)
// - boolean connect (const char* host, int port) 
// - boolean listen (int port=0) 
//   these do the same as the corresponding constructors.
//   listen() takes an arbitrary port number if port is zero.
// - int port() const
//   the port number if listening, else -1.
// 
// </class> 
class INETSocket : public Socket {
public:
   INETSocket() ;
   INETSocket (int fd, boolean close) ;
   INETSocket (const char* host, int port, unsigned long timeout=0) ; // connect to ...
   INETSocket (const INETAddress&, unsigned long timeout=0) ; // connect to ...
   INETSocket (int port) ; // listen at ...

   void attach (int fd, boolean close) ;

   boolean connect (const char* host, int port, unsigned long timeout=0) ;
   boolean connect (const INETAddress&, unsigned long timeout=0) ;

   boolean thisAddress (INETAddress&) const ;
   boolean thatAddress (INETAddress&) const ;

   const INETAddress* thisAddress() const ;
   const INETAddress* thatAddress() const ;

   boolean listen (int port=0) ;
   boolean accept (int& fd) ;
   boolean accept (INETSocketPtr&, INETAddress& peer) ;
   boolean accept (INETSocketPtr&) ;
   boolean accept (SocketPtr&) ;
   int port() const ;

private:
   // dont need a length field. sockaddr_in is of constant length.
   int accept_(sockaddr_in*) ;

private:
   INETAddress* this_addr_ ;
   INETAddress* that_addr_ ;

private:
   INETSocket (const INETSocket&) {}
   INETSocket& operator = (const INETSocket&) { return *this; }
} ;

inline int INETSocket :: accept_(struct sockaddr_in* addr) {
   int len = sizeof (sockaddr_in) ;
   return Socket::accept_((struct sockaddr*)addr, &len) ;
}

SmartPtrdeclare (INETSocketPtr, INETSocket) 



#endif
