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

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


[.] - [up] [top] - index README make include source scripts configure
  // connection.cc
  
  include <net/cs/csaddress.h>
  include <net/cs/connection.h>
  include <net/cs/dataconn.h>
  include <net/cs/listenconn.h>
  include <net/cs/samlib.h>
  
  include <unistd.h>
  include <fcntl.h>
  include <string.h>
  include <errno.h>
  include <sys/time.h>
  include <sys/types.h>
  
  //------------------------- connection implementation ----------------------
  
  connection::connection(const csaddress* addr)
  {
      init(addr);
  }
  
  connection::connection()
  {
      init(NULL);
  }
  
  void connection::init(const csaddress* addr)
  {
      _fd = -1;
      _address = (csaddress*) addr;
      _connected = 0;
  }
  
  connection::~connection()
  {
      _fd = -1;
      _address = NULL;
  }
  
  csaddress* connection::address() const
  {
      return _address;
  }
  
  int connection::fd() const
  {
      if (!_connected)
          return -1;
      else
          return _fd;
  }
  
  int connection::connected()
  {
      if (_fd < 0)
          _connected = 0;
  
      return _connected;
  }
  
  //-------------------------- data_connection implementation -----------------
  
  int data_connection::read(char* buf, int maxbytes)
  {
      int retval = 0;
  
      if (_fd < 0)
      {
          warn("data_connection::read : no valid filedescriptor %d", _fd);
          return -1;
      }
  
      if (!_connected)
      {
          warn("data_connection::read : connection is closed");
          return -1;
      }
  
  // if something went wrong, assume a broken connection
      if (ready())
      {
          if ((retval = read_nonblock(_fd, buf, maxbytes)) <= 0)
          {
              _connected = 0;
              return -1;
          }
          else
              return retval;
      }
      else
          return 0;
  }
  
  int data_connection::write(const char* buf, int nrbytes)
  {
      if (_fd < 0)
      {
          warn("data_connection::write : no valid filedescriptor %d", _fd);
          return -1;
      }
  
      if (!_connected)
      {
          warn("data_connection::write : connection is closed");
          return -1;
      }
  
      return ::write(_fd, buf, nrbytes);
  }
  
  /*
      This function checks whether data can be read by use of select.
      If timeout is NULL, ready will return immediately (unlike select, which
      blocks indefinitely if timeout is NULL).
      Therefore it's not possible to let 'ready' block indefinitely (why
      should you?, just use read/readmsg instead...).
      There's a big difference between Solaris and Linux: if select is
      interrupted, Linux will adjust the timeval to the time that's left, but
      Solaris will not do this...
  */
  int data_connection::ready(timeval* timeout) const
  {
      fd_set readfds;
      timeval tv = {0, 0};
      timeval starttime;
  
      FD_ZERO(&readfds);
      FD_SET(_fd, &readfds);
      if (timeout != NULL)
          tv = *timeout;
  
      timeval starttv = tv;
      gettimeofday(&starttime, NULL);
  
      do
      {
          int retval = select(_fd+1, &readfds, NULL, NULL, &tv);
          if (retval > 0)         // data available
              return 1;
          if (retval == 0)        // timeout
              return 0;
  
      // interrupted systemcall, compute new timeval
          timeval nowtime;
          gettimeofday(&nowtime, NULL);
      // restore tv (Linux select will adjust timeval)
          tv = starttv;
      // adjust tv to current time
          tv.tv_sec -= (nowtime.tv_sec - starttime.tv_sec);
          tv.tv_usec -= (nowtime.tv_usec - starttime.tv_usec);
          if (tv.tv_usec < 0)
          {
              tv.tv_sec--;
              tv.tv_usec += 1000000;
          }
          if (tv.tv_usec >= 1000000)
          {
              tv.tv_sec++;
              tv.tv_usec -= 1000000;
          }
          if (tv.tv_sec < 0)
              tv.tv_sec = 0;
      }
      while ((tv.tv_usec != 0) || (tv.tv_sec != 0));
  
      return 0;
  }
  
  //---------------------------- listen_connection implementation -------------
  
  /*
      Like data_connection::data_available, this function should work for all
      types of communication, but no guarentees are given. If this doesn't
      work, overload it.
      See data_connection::ready for description of timeout.
   */
  int listen_connection::ready(timeval* timeout) const
  {
      fd_set readfds;
      timeval tv = {0, 0};
      timeval starttime;
  
      FD_ZERO(&readfds);
      FD_SET(_fd, &readfds);
      if (timeout != NULL)
          tv = *timeout;
  
      timeval starttv = tv;
      gettimeofday(&starttime, NULL);
  
      do
      {
          int retval = select(_fd+1, &readfds, NULL, NULL, &tv);
          if (retval > 0)         // data available
              return 1;
          if (retval == 0)        // timeout
              return 0;
  
      // interrupted systemcall, compute new timeval
          timeval nowtime;
          gettimeofday(&nowtime, NULL);
      // restore tv (Linux select will adjust timeval)
          tv = starttv;
      // adjust tv to current time
          tv.tv_sec -= (nowtime.tv_sec - starttime.tv_sec);
          tv.tv_usec -= (nowtime.tv_usec - starttime.tv_usec);
          if (tv.tv_usec < 0)
          {
              tv.tv_sec--;
              tv.tv_usec += 1000000;
          }
          if (tv.tv_usec >= 1000000)
          {
              tv.tv_sec++;
              tv.tv_usec -= 1000000;
          }
          if (tv.tv_sec < 0)
              tv.tv_sec = 0;
      }
      while ((tv.tv_usec != 0) || (tv.tv_sec != 0));
  
      return 0;
  }
  
  

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