#ifndef TCPSOCK_H #define TCPSOCK_H 1 #include <istream> #include <ostream> #include <streambuf> #include <iosfwd> #include <iostream> #include <ext/stdio_filebuf.h> // GNU C++ extension -- for making a filebuf from a unix file descriptor #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> using namespace std; class fdistream : public std::istream { int fd_; FILE *f_; typedef __gnu_cxx::stdio_filebuf<char> stdio_filebuf; stdio_filebuf fdsb_; public: fdistream( int fd ) : fd_(fd), f_( fdopen(fd, "rb") ), fdsb_( f_, std::ios::in /*| std::ios::binary */ , 0 ), istream( &fdsb_ ) { char c; if(::read(fd, &c, 1) < 0) { perror("fdistream: read"); } else { fprintf(stderr, "fdistream: read %c(%x)\n", c, c); } c = '?'; c = fdsb_.sgetc(); fprintf(stderr, "get() -> '%c'(%x)\n", c, c); *this >> c; fprintf(stderr, "this >> '%c'(%x)\n", c, c); } }; 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 ); fdistream *new_istream() { if(!be_connected()) return 0; return new fdistream( fd() ); } }; #endif /*TCPSOCK_H*/