int dv_sockser_status (SIM_DESC sd) { int numrfds,numwfds,status; struct timeval tv; fd_set readfds,writefds; /* status to return if the socket isn't set up, or select fails */ status = DV_SOCKSER_INPUT_EMPTY | DV_SOCKSER_OUTPUT_EMPTY | DV_SOCKSER_DISCONNECTED; if (! connected_p (sd)) return status; FD_ZERO (&readfds); FD_ZERO (&writefds); FD_SET (sockser_fd, &readfds); FD_SET (sockser_fd, &writefds); /* ??? One can certainly argue this should be done differently, but for now this is sufficient. The read is done separately from the write to enforce the delay which we heuristically set to once every SOCKSER_TIMEOUT_FREQ tries. No, this isn't great for SMP situations, blah blah blah. */ { static int n; #define SOCKSER_TIMEOUT_FREQ 42 if (++n == SOCKSER_TIMEOUT_FREQ) n = 0; if (n == 0) { tv.tv_sec = 0; tv.tv_usec = sockser_timeout; numrfds = select (sockser_fd + 1, &readfds, 0, 0, &tv); tv.tv_sec = 0; tv.tv_usec = 0; numwfds = select (sockser_fd + 1, 0, &writefds, 0, &tv); } else /* do both selects at once */ { tv.tv_sec = 0; tv.tv_usec = 0; numrfds = numwfds = select (sockser_fd + 1, &readfds, &writefds, 0, &tv); } } status = 0; if (numrfds <= 0 || ! FD_ISSET (sockser_fd, &readfds)) status |= DV_SOCKSER_INPUT_EMPTY; if (numwfds <= 0 || FD_ISSET (sockser_fd, &writefds)) status |= DV_SOCKSER_OUTPUT_EMPTY; return status; }
int dv_sockser_write (SIM_DESC sd, unsigned char c) { int n; if (! connected_p (sd)) return -1; n = write (sockser_fd, &c, 1); if (n == -1) { if (errno == EPIPE) { close (sockser_fd); sockser_fd = -1; } return -1; } if (n != 1) return -1; return 1; }
int dv_sockser_write_buffer (SIM_DESC sd, const unsigned char *buffer, unsigned nr_bytes) { int n; if (! connected_p (sd)) return -1; n = write (sockser_fd, buffer, nr_bytes); if (n == -1) { if (errno == EPIPE) { close (sockser_fd); sockser_fd = -1; } return -1; } if (n != nr_bytes) return -1; return nr_bytes; }
int dv_sockser_read (SIM_DESC sd) { unsigned char c; int n; if (! connected_p (sd)) return -1; n = read (sockser_fd, &c, 1); /* ??? We're assuming semantics that may not be correct for all hosts. In particular (from cvssrc/src/server.c), this assumes that we are using BSD or POSIX nonblocking I/O. System V nonblocking I/O returns zero if there is nothing to read. */ if (n == 0) { close (sockser_fd); sockser_fd = -1; return -1; } if (n != 1) return -1; return c; }