64
65
struct tio_buffer readbuffer;
65
66
struct tio_buffer writebuffer;
66
struct timeval readtimeout;
67
struct timeval writetimeout;
68
69
int read_resettable; /* whether the tio_reset() function can be called */
69
70
#ifdef DEBUG_TIO_STATS
70
71
/* this is used to collect statistics on the use of the streams
74
75
#endif /* DEBUG_TIO_STATS */
77
/* add the second timeval to the first modifing the first */
78
static inline void tio_tv_add(struct timeval *tv1, const struct timeval *tv2)
80
/* BUG: we hope that this does not overflow */
81
tv1->tv_usec+=tv2->tv_usec;
82
if (tv1->tv_usec>=1000000)
84
tv1->tv_usec-=1000000;
87
tv1->tv_sec+=tv2->tv_sec;
90
78
/* build a timeval for comparison to when the operation should be finished */
91
static inline void tio_tv_prepare(struct timeval *deadline, const struct timeval *timeout)
79
static inline void tio_get_deadline(struct timeval *deadline,int timeout)
93
81
if (gettimeofday(deadline,NULL))
97
85
deadline->tv_usec=0;
100
tio_tv_add(deadline,timeout);
88
deadline->tv_sec+=timeout/1000;
89
deadline->tv_sec+=(timeout%1000)*1000;
103
/* update the timeval to the value that is remaining before deadline
92
/* update the timeout to the value that is remaining before deadline
104
93
returns non-zero if there is no more time before the deadline */
105
static inline int tio_tv_remaining(struct timeval *tv, const struct timeval *deadline)
94
static inline int tio_time_remaining(const struct timeval *deadline)
107
97
/* get the current time */
108
if (gettimeofday(tv,NULL))
98
if (gettimeofday(&tv,NULL))
110
100
/* 1 second default if gettimeofday() is broken */
115
/* check if we're too late */
116
if ( (tv->tv_sec>deadline->tv_sec) ||
117
( (tv->tv_sec==deadline->tv_sec) && (tv->tv_usec>deadline->tv_usec) ) )
120
tv->tv_sec=deadline->tv_sec-tv->tv_sec;
121
if (tv->tv_usec<=deadline->tv_usec)
122
tv->tv_usec=deadline->tv_usec-tv->tv_usec;
126
tv->tv_usec=1000000+deadline->tv_usec-tv->tv_usec;
103
/* calculate time remaining in miliseconds */
104
return (deadline->tv_sec-tv.tv_sec)*1000 + (deadline->tv_usec-tv.tv_usec)/1000;
131
107
/* open a new TFILE based on the file descriptor */
132
TFILE *tio_fdopen(int fd,struct timeval *readtimeout,struct timeval *writetimeout,
108
TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
133
109
size_t initreadsize,size_t maxreadsize,
134
110
size_t initwritesize,size_t maxwritesize)
162
138
fp->writebuffer.start=0;
163
139
fp->writebuffer.len=0;
164
140
/* initialize other attributes */
165
fp->readtimeout.tv_sec=readtimeout->tv_sec;
166
fp->readtimeout.tv_usec=readtimeout->tv_usec;
167
fp->writetimeout.tv_sec=writetimeout->tv_sec;
168
fp->writetimeout.tv_usec=writetimeout->tv_usec;
141
fp->readtimeout=readtimeout;
142
fp->writetimeout=writetimeout;
169
143
fp->read_resettable=0;
170
144
#ifdef DEBUG_TIO_STATS
171
145
fp->byteswritten=0;
177
151
/* wait for any activity on the specified file descriptor using
178
152
the specified deadline */
179
static int tio_select(TFILE *fp, int readfd, const struct timeval *deadline)
153
static int tio_wait(TFILE *fp,int readfd,const struct timeval *deadline)
156
struct pollfd fds[1];
186
/* prepare our filedescriptorset */
188
FD_SET(fp->fd,&fdset);
189
160
/* figure out the time we need to wait */
190
if (tio_tv_remaining(&tv,deadline))
161
if ((timeout=tio_time_remaining(deadline))<0)
195
166
/* wait for activity */
170
fds[0].events=POLLIN;
198
171
/* santiy check for moving clock */
199
if (tv.tv_sec>fp->readtimeout.tv_sec)
200
tv.tv_sec=fp->readtimeout.tv_sec;
201
rv=select(FD_SETSIZE,&fdset,NULL,NULL,&tv);
172
if (timeout>fp->readtimeout)
173
timeout=fp->readtimeout;
178
fds[0].events=POLLOUT;
205
179
/* santiy check for moving clock */
206
if (tv.tv_sec>fp->writetimeout.tv_sec)
207
tv.tv_sec=fp->writetimeout.tv_sec;
208
rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
180
if (timeout>fp->writetimeout)
181
timeout=fp->writetimeout;
183
rv=poll(fds,1,timeout);
211
185
return 0; /* we have activity */
234
208
/* have a more convenient storage type for the buffer */
235
209
uint8_t *ptr=(uint8_t *)buf;
236
210
/* build a time by which we should be finished */
237
tio_tv_prepare(&deadline,&(fp->readtimeout));
211
tio_get_deadline(&deadline,fp->readtimeout);
238
212
/* loop until we have returned all the needed data */
294
268
/* wait until we have input */
295
if (tio_select(fp,1,&deadline))
269
if (tio_wait(fp,1,&deadline))
297
271
/* read the input in the buffer */
298
272
len=fp->readbuffer.size-fp->readbuffer.start;
342
315
#endif /* SSIZE_MAX */
345
/* prepare our file descriptor set */
347
FD_SET(fp->fd,&fdset);
348
/* prepare the time to wait */
351
318
/* see if any data is available */
352
rv=select(FD_SETSIZE,&fdset,NULL,NULL,&tv);
320
fds[0].events=POLLIN;
322
/* check the poll() result */
354
324
return 0; /* no file descriptor ready */
355
325
if ((rv<0)&&((errno==EINTR)||(errno==EAGAIN)))
425
395
struct timeval deadline;
426
396
/* build a time by which we should be finished */
427
tio_tv_prepare(&deadline,&(fp->writetimeout));
397
tio_get_deadline(&deadline,fp->writetimeout);
428
398
/* loop until we have written our buffer */
429
399
while (fp->writebuffer.len > 0)
431
401
/* wait until we can write */
432
if (tio_select(fp,0,&deadline))
402
if (tio_wait(fp,0,&deadline))
434
404
/* write one block */
435
405
if (tio_writebuf(fp))
442
412
will accept data */
443
413
static int tio_flush_nonblock(TFILE *fp)
415
struct pollfd fds[1];
448
/* prepare our filedescriptorset */
450
FD_SET(fp->fd,&fdset);
451
/* set the timeout to 0 to poll */
454
417
/* wait for activity */
455
rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
419
fds[0].events=POLLOUT;
456
421
/* check if any file descriptors were ready (timeout) or we were
458
423
if ((rv==0)||((rv<0)&&(errno==EINTR)))