// 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; }
Hush Online Technology
hush@cs.vu.nl
09/09/98 |
![]() |
![]() |