/* Read all available data from the stream and empty the read buffer. */ int tio_skipall(TFILE *fp, int timeout) { struct timespec deadline = {0, 0}; int rv; size_t len; /* clear the read buffer */ fp->readbuffer.start = 0; fp->readbuffer.len = 0; fp->read_resettable = 0; /* read until we can't read no more */ len = fp->readbuffer.size; #ifdef SSIZE_MAX if (len > SSIZE_MAX) len = SSIZE_MAX; #endif /* SSIZE_MAX */ while (1) { /* wait until we have input */ if (tio_wait(fp->fd, POLLIN, timeout, &deadline)) return -1; /* read data from the stream */ rv = read(fp->fd, fp->readbuffer.buffer, len); if (rv == 0) return 0; /* end-of-file */ if ((rv < 0) && (errno == EWOULDBLOCK)) return 0; /* we've ready everything we can without blocking */ if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN)) return -1; /* something went wrong with the read */ } }
/* write all the data in the buffer to the stream */ int tio_flush(TFILE *fp) { struct timespec deadline = {0, 0}; /* loop until we have written our buffer */ while (fp->writebuffer.len > 0) { /* wait until we can write */ if (tio_wait(fp->fd, POLLOUT, fp->writetimeout, &deadline)) return -1; /* write one block */ if (tio_writebuf(fp)) return -1; } return 0; }
/* write all the data in the buffer to the stream */ int tio_flush(TFILE *fp) { struct timeval deadline; /* build a time by which we should be finished */ tio_get_deadline(&deadline,fp->writetimeout); /* loop until we have written our buffer */ while (fp->writebuffer.len > 0) { /* wait until we can write */ if (tio_wait(fp,0,&deadline)) return -1; /* write one block */ if (tio_writebuf(fp)) return -1; } return 0; }
/* do a read on the file descriptor, returning the data in the buffer if no data was read in the specified time an error is returned */ int tio_read(TFILE *fp, void *buf, size_t count) { struct timeval deadline; int rv; uint8_t *tmp; size_t newsz; size_t len; /* have a more convenient storage type for the buffer */ uint8_t *ptr=(uint8_t *)buf; /* build a time by which we should be finished */ tio_get_deadline(&deadline,fp->readtimeout); /* loop until we have returned all the needed data */ while (1) { /* check if we have enough data in the buffer */ if (fp->readbuffer.len >= count) { if (count>0) { if (ptr!=NULL) memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,count); /* adjust buffer position */ fp->readbuffer.start+=count; fp->readbuffer.len-=count; } return 0; } /* empty what we have and continue from there */ if (fp->readbuffer.len>0) { if (ptr!=NULL) { memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len); ptr+=fp->readbuffer.len; } count-=fp->readbuffer.len; fp->readbuffer.start+=fp->readbuffer.len; fp->readbuffer.len=0; } /* after this point until the read fp->readbuffer.len is 0 */ if (!fp->read_resettable) { /* the stream is not resettable, re-use the buffer */ fp->readbuffer.start=0; } else if (fp->readbuffer.start>=(fp->readbuffer.size-4)) { /* buffer is running empty, try to grow buffer */ if (fp->readbuffer.size<fp->readbuffer.maxsize) { newsz=fp->readbuffer.size*2; if (newsz>fp->readbuffer.maxsize) newsz=fp->readbuffer.maxsize; tmp=realloc(fp->readbuffer.buffer,newsz); if (tmp!=NULL) { fp->readbuffer.buffer=tmp; fp->readbuffer.size=newsz; } } /* if buffer still does not contain enough room, clear resettable */ if (fp->readbuffer.start>=(fp->readbuffer.size-4)) { fp->readbuffer.start=0; fp->read_resettable=0; } } /* wait until we have input */ if (tio_wait(fp,1,&deadline)) return -1; /* read the input in the buffer */ len=fp->readbuffer.size-fp->readbuffer.start; #ifdef SSIZE_MAX if (len>SSIZE_MAX) len=SSIZE_MAX; #endif /* SSIZE_MAX */ rv=read(fp->fd,fp->readbuffer.buffer+fp->readbuffer.start,len); /* check for errors */ if (rv==0) { errno=ECONNRESET; return -1; } else if ((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN)) return -1; /* something went wrong with the read */ /* skip the read part in the buffer */ fp->readbuffer.len=rv; #ifdef DEBUG_TIO_STATS fp->bytesread+=rv; #endif /* DEBUG_TIO_STATS */ } }