#ifndef TCPSOCK_H
#define TCPSOCK_H 1

#include <fstream>
#include <iosfwd>

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

class TCPsocket {
    int fd_;
    enum sockstate { INVALID, LISTENING, CONNECTING, CONNECTED } state_;
    int backlog_;
    bool nonblock_;
    struct sockaddr_in sin_;

    bool mksock( const char *name, bool nonblock );
    bool do_accept();
    void connectwith( const char *name, int port, bool nonblock );
    void listenwith( int listenport, bool await_first_contact, int backlog, bool nonblock );

  public:
    TCPsocket( const char *name, int port, bool nonblock = false );	// connect()
    TCPsocket( int listenport, bool await_first_contact = true, int backlog = 5, bool nonblock = false ); // listen()
    TCPsocket( TCPsocket &listener, bool nonblock = false );
    ~TCPsocket();

    bool valid() const { return state_ != INVALID; }
    enum sockstate state() const { return state_; }
    bool connected() const { return state_ == CONNECTED; }
    bool listening() const { return state_ == LISTENING; }

    void nonblock( bool nb );

    bool be_connected();				// wait for connection; false on failure

    int fd() const { return fd_; }			// suitable for select()ing

    bool ready();
    bool await( int usecs = -1 );

    bool open_ifstream( std::ifstream & );
    char *fdname();
};
#endif /*TCPSOCK_H*/