The DejaVU Framework -- hush 3.0
[.] Papers Tutorials Examples Manuals Interfaces Sources Packages Resources ?

source: tcp.c hush-3.0b4/auxiliary/net/cs


[.] - [up] [top] - index README make include source scripts configure
  // tcp.cc
  
  include <net/cs/tcp/dataconn.h>
  include <net/cs/tcp/listenconn.h>
  include <net/cs/tcp/client.h>
  include <net/cs/tcp/clientimp.h>
  include <net/cs/tcp/server.h>
  include <net/cs/tcp/serverimp.h>
  include <net/cs/dataconn.h>
  include <net/cs/listenconn.h>
  include <net/cs/csaddress.h>
  include <net/cs/inetaddr.h>
  include <net/cs/cs.h>
  include <net/cs/samlib.h>
  
  include <errno.h>
  include <unistd.h>
  include <string.h>
  include <sys/types.h>
  include <sys/socket.h>
  include <netinet/in.h>
  include <arpa/inet.h>
  include <netdb.h>
  include <stdio.h>
  include <signal.h>
  include <fcntl.h>
  include <sys/fcntl.h>
  include <stdlib.h>
  
  // IMPLEMENTATION NOTE: man socket states that SIGPIPE will be raised if a
  //                      process writes to a broken pipe (when the other side
  //                      has hung up). So for robustness, this signal has to
  //                      be handled.
  
  //---------------------------- tcpsocket implementation -------------------
  
  int tcpsocket::_got_sigpipe = 0;
  int tcpsocket::_handler_installed = 0;
  void (*tcpsocket::_old_sigpipe_handler)(int) = NULL;
  
  void tcpsocket::sigpipe_handler(int signr)
  {
      if (cs_trace)
          printf("tcpsocket::sigpipe_handle begin\n");
      signal(SIGPIPE, sigpipe_handler);
      _got_sigpipe = 1;
  
      if ((_old_sigpipe_handler != SIG_IGN) && (_old_sigpipe_handler != SIG_DFL))
          (*_old_sigpipe_handler)(signr);
  
      if (cs_trace)
          printf("tcpsocket::sigpipe_handler(%d) end\n", signr);
  }
  
  tcpsocket::tcpsocket()
  {
      if (!_handler_installed)
      {
          _old_sigpipe_handler = signal(SIGPIPE, sigpipe_handler);
          _handler_installed = 1;
          if (cs_trace > 5)
              printf("tcpsocket::tcpsocket : SIGPIPE handler installed\n");
      }
  
      _portnr = -1;
      _name.sin_family = 0;
      _name.sin_port = 0;
      _name.sin_addr.s_addr = 0;
      _sd = -1;
  }
  
  int tcpsocket::portnr() const
  {
      struct sockaddr addr;
      int addrlen;
  // hack for keeping this function 'const'
      tcpsocket* sptr = (tcpsocket*) this;
  
      if (_portnr != -1)
          return _portnr;             // portnumber already known
  
      addrlen = sizeof(addr);
      if (getsockname(_sd, &addr, &addrlen) < 0)
      {
          warn("tcp_listenconn::portnr : getsockname failed (%s)", 
               strerror(errno));
          return -1;
      }
  
      struct sockaddr_in* ptr = (struct sockaddr_in*) &addr;
      sptr -> _portnr = ntohs(ptr -> sin_port);
  
      return sptr -> _portnr;
  }
  
  void tcpsocket::close()
  {
      ::close(_sd);
      _sd = -1;
  }
  
  //--------------------------- tcp_dataconn implementation --------------------
  
  tcp_dataconn::tcp_dataconn(const csaddress* addr)
             :tcpsocket(), data_connection(addr)
  {
      if (addr == NULL)
      {
          warn("tcp_dataconn::tcp_dataconn : addr = NULL");
          return;
      }
  
  // make socket connection
      struct hostent* hp;
      inet_address* a = (inet_address*) addr;
      char* hname = (char*) a -> hostname();
  
      if ((_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
      {
          warn("tcp_dataconn::tcp_dataconn : couldn't create socket (%s)",
               strerror(errno));
          return;
      }
  
      _name.sin_family = AF_INET;
      _name.sin_port = htons(a -> portnr());
  
      if ((hname == NULL) || (strlen(hname) == 0))
      {
          warn("tcp_dataconn::tcp_dataconn : hostname = NULL or \"\"");
          ::close(_fd);
          return;
      }
      else
      {
          hp = gethostbyname(hname);
          if (hp == NULL)
              hp = gethostbyaddr(hname, strlen(hname), AF_INET);
          if (hp == NULL)
          {
              warn("tcp_dataconn::tcp_dataconn : unknown host %s", hname);
              ::close(_fd);
              return;
          }
          memcpy(&_name.sin_addr.s_addr, hp -> h_addr, hp -> h_length);
      }
  
      if (connect(_fd, (struct sockaddr*) &_name, sizeof(_name)) < 0)
      {
          warn("tcp_dataconn::tcp_dataconn : couldn't connect (%s)",
               strerror(errno));
          ::close(_fd);
          return;
      }
  
  // set socketdescriptor
      _sd = _fd;
      _connected = 1;
  }
  
  tcp_dataconn::tcp_dataconn(int fd)
             :tcpsocket(), data_connection()
  {
      _fd = fd;
      _sd = fd;
  // since this constructor will be called by the receiving side of a
  // connection, the connection is already a fact
      _connected = 1;
  }
  
  tcp_dataconn::~tcp_dataconn()
  {
      close();
  }
  
  int tcp_dataconn::readmsg(char* buf, int nrbytes)
  {
      int retval;
  
      if (_fd < 0)
      {
          warn("tcp_dataconn::readmsg : no valid filedescriptor %d", _fd);
          return -1;
      }
  
      if (!_connected)
      {
          warn("tcp_dataconn::readmsg : connection is closed");
          return -1;
      }
  
      retval = read_package(_fd, buf, nrbytes);
      if (retval <= 0)
          _connected = 0;
      return retval;
  }
  
  int tcp_dataconn::writemsg(const char* buf, int nrbytes)
  {
      int retval;
  
      if (_fd < 0)
      {
          warn("tcp_dataconn::writemsg : no valid filedescriptor %d", _fd);
          return -1;
      }
  
      if (!_connected)
      {
          warn("tcp_dataconn::writemsg : connection is closed");
          return -1;
      }
  
      retval = write_package(_fd, buf, nrbytes);
      if (retval <= 0)
          _connected = 0;
      if (_got_sigpipe)
      {
          _connected = 0;
          _got_sigpipe = 0;
      }
      return retval;
  }
  
  //------------------------ tcp_listenconn implementation --------------------
  
  tcp_listenconn::tcp_listenconn(const csaddress* addr)
               :tcpsocket(), listen_connection(addr)
  {
  // make socket connection
      struct hostent* hp;
      inet_address* a = (inet_address*) _address;     // this should be tested!!!
      char* hname = NULL;
      
      if ((_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
      {
          warn("tcp_listenconn::tcp_listenconn : couldn't create socket (%s)",
               strerror(errno));
          return;
      }
  
      _name.sin_family = AF_INET;
      if (a != NULL)
      {
          //hname = (char*) a -> hostname();      // only portnr of listenconn
                                                  // can be set
          hname = NULL;
          _name.sin_port = htons(a -> portnr());
      }
      else
      {
          hname = NULL;
          _name.sin_port = 0;
      }
  
      if (hname == NULL)
          _name.sin_addr.s_addr = INADDR_ANY;
      else
      {
          hp = gethostbyname(hname);
          if (hp == NULL)
              hp = gethostbyaddr(hname, strlen(hname), AF_INET);
          if (hp == NULL)
          {
              warn("tcp_listenconn::tcp_listenconn : unknown host %s", hname);
              ::close(_fd);
              return;
          }
          memcpy(&_name.sin_addr.s_addr, hp -> h_addr, hp -> h_length);
      }
  
      if (bind(_fd, (struct sockaddr*) &_name, sizeof(_name)) < 0)
      {
          warn("tcp_listenconn::tcp_listenconn : couldn't bind socket (%s)",
               strerror(errno));
          ::close(_fd);
          return;
      }
  
      if (listen(_fd, 5) < 0)
      {
          warn("tcp_listenconn::tcp_listenconn : listen failed (%s)",
               strerror(errno));
          ::close(_fd);
          return;
      }
  
  // set socketdescriptor
      _sd = _fd;
      _connected = 1;         // we're on the air now
  }
  
  tcp_listenconn::~tcp_listenconn()
  {
      close();
  }
  
  data_connection* tcp_listenconn::waitconnect()
  {
      int new_sd;
      data_connection* new_conn;
  
      if ((new_sd = accept(_fd, 0, 0)) < 0)
          return NULL;
  
      if (!(new_conn = new tcp_dataconn(new_sd)))
      {
          warn("tcp_listenconn::waitconnect : couldn't create new "
               "data_connection");
          return NULL;
      }
      return new_conn;
  }
  
  //------------------------ tcp_client implementation ---------------------
  
  tcp_client::tcp_client()
            :csclient(_tcpimp = new tcp_clientimp())
  {
      _inetaddr = NULL;
  }
  
  tcp_client::tcp_client(const char* hostname, int portnr)
            :csclient(_tcpimp = new tcp_clientimp(), 
                      _inetaddr = new inet_address(hostname, portnr))
  {
  }
  
  tcp_client::~tcp_client()
  {
      if (_inetaddr != NULL)
          delete _inetaddr;
      delete _tcpimp;
  }
  
  int tcp_client::connect(const char* hostname, int portnr)
  {
      if (_inetaddr)
          delete _inetaddr;
      _inetaddr = new inet_address(hostname, portnr);
  
  write_to_log("tcp_client::connect with %s at port %d", hostname, portnr);
      return csclient::connect(_inetaddr);
  }
  
  //------------------------ tcp_server implementation ---------------------
  
  tcp_server::tcp_server()
            :csserver(_tcpimp = new tcp_serverimp())
  {
      _tcpaddr = NULL;
  }
  
  tcp_server::tcp_server(int portnr)
            :csserver(_tcpimp = new tcp_serverimp(), 
                      _tcpaddr = new inet_address("", portnr))
  {
  }
  
  tcp_server::~tcp_server()
  {
      delete _tcpimp;
      if (_tcpaddr != NULL)
          delete _tcpaddr;
  }
  
  int tcp_server::portnr() const
  {
      tcp_listenconn* tlc = (tcp_listenconn*) listenconn();
  
      if (tlc != NULL)
          return tlc -> portnr();
      else
          return -1;
  }
  
  //--------------------- tcp_clientimp implementation -----------------------
  
  tcp_clientimp::tcp_clientimp()
  {
  }
  
  data_connection* tcp_clientimp::createdata(const csaddress* addr) const
  {
      return new tcp_dataconn(addr);
  }
  
  //------------------------- tcp_serverimp ------------------------------
  
  tcp_serverimp::tcp_serverimp()
  {
  }
  
  listen_connection* tcp_serverimp::createlisten(const csaddress* addr) const
  {
      return new tcp_listenconn(addr);
  }
  
  

[.] Papers Tutorials Examples Manuals Interfaces Sources Packages Resources ?
Hush Online Technology
hush@cs.vu.nl
09/09/98