2 * sel.c: implementation of sel.h.
13 #include <sys/types.h>
14 #include <sys/select.h>
19 /* ----------------------------------------------------------------------
20 * Chunk of code lifted from PuTTY's misc.c to manage buffers of
21 * data to be written to an fd.
24 #define BUFFER_GRANULE 512
26 typedef struct bufchain_tag
{
27 struct bufchain_granule
*head
, *tail
;
28 size_t buffersize
; /* current amount of buffered data */
30 struct bufchain_granule
{
31 struct bufchain_granule
*next
;
32 size_t buflen
, bufpos
;
33 char buf
[BUFFER_GRANULE
];
36 static void bufchain_init(bufchain
*ch
)
38 ch
->head
= ch
->tail
= NULL
;
42 static void bufchain_clear(bufchain
*ch
)
44 struct bufchain_granule
*b
;
47 ch
->head
= ch
->head
->next
;
54 static size_t bufchain_size(bufchain
*ch
)
56 return ch
->buffersize
;
59 static void bufchain_add(bufchain
*ch
, const void *data
, size_t len
)
61 const char *buf
= (const char *)data
;
65 ch
->buffersize
+= len
;
67 if (ch
->tail
&& ch
->tail
->buflen
< BUFFER_GRANULE
) {
68 size_t copylen
= BUFFER_GRANULE
- ch
->tail
->buflen
;
71 memcpy(ch
->tail
->buf
+ ch
->tail
->buflen
, buf
, copylen
);
74 ch
->tail
->buflen
+= copylen
;
77 struct bufchain_granule
*newbuf
;
78 size_t grainlen
= BUFFER_GRANULE
;
81 newbuf
= snew(struct bufchain_granule
);
83 newbuf
->buflen
= grainlen
;
84 memcpy(newbuf
->buf
, buf
, grainlen
);
88 ch
->tail
->next
= newbuf
;
90 ch
->head
= ch
->tail
= newbuf
;
96 static void bufchain_consume(bufchain
*ch
, size_t len
)
98 struct bufchain_granule
*tmp
;
100 assert(ch
->buffersize
>= len
);
103 assert(ch
->head
!= NULL
);
104 if (remlen
>= ch
->head
->buflen
- ch
->head
->bufpos
) {
105 remlen
= ch
->head
->buflen
- ch
->head
->bufpos
;
107 ch
->head
= tmp
->next
;
112 ch
->head
->bufpos
+= remlen
;
113 ch
->buffersize
-= remlen
;
118 static void bufchain_prefix(bufchain
*ch
, void **data
, size_t *len
)
120 *len
= ch
->head
->buflen
- ch
->head
->bufpos
;
121 *data
= ch
->head
->buf
+ ch
->head
->bufpos
;
124 /* ----------------------------------------------------------------------
125 * The actual implementation of the sel interface.
130 sel_rfd
*rhead
, *rtail
;
131 sel_wfd
*whead
, *wtail
;
136 sel_rfd
*prev
, *next
;
137 sel_readdata_fn_t readdata
;
138 sel_readerr_fn_t readerr
;
146 sel_wfd
*prev
, *next
;
147 sel_written_fn_t written
;
148 sel_writeerr_fn_t writeerr
;
154 sel
*sel_new(void *ctx
)
156 sel
*sel
= snew(struct sel
);
159 sel
->rhead
= sel
->rtail
= NULL
;
160 sel
->whead
= sel
->wtail
= NULL
;
165 sel_wfd
*sel_wfd_add(sel
*sel
, int fd
,
166 sel_written_fn_t written
, sel_writeerr_fn_t writeerr
,
169 sel_wfd
*wfd
= snew(sel_wfd
);
171 wfd
->written
= written
;
172 wfd
->writeerr
= writeerr
;
175 bufchain_init(&wfd
->buf
);
178 wfd
->prev
= sel
->wtail
;
180 sel
->wtail
->next
= wfd
;
189 sel_rfd
*sel_rfd_add(sel
*sel
, int fd
,
190 sel_readdata_fn_t readdata
, sel_readerr_fn_t readerr
,
193 sel_rfd
*rfd
= snew(sel_rfd
);
195 rfd
->readdata
= readdata
;
196 rfd
->readerr
= readerr
;
202 rfd
->prev
= sel
->rtail
;
204 sel
->rtail
->next
= rfd
;
213 size_t sel_write(sel_wfd
*wfd
, const void *data
, size_t len
)
215 bufchain_add(&wfd
->buf
, data
, len
);
216 return bufchain_size(&wfd
->buf
);
219 void sel_wfd_setfd(sel_wfd
*wfd
, int fd
)
224 void sel_rfd_setfd(sel_rfd
*rfd
, int fd
)
229 void sel_rfd_freeze(sel_rfd
*rfd
)
234 void sel_rfd_unfreeze(sel_rfd
*rfd
)
239 int sel_wfd_delete(sel_wfd
*wfd
)
241 sel
*sel
= wfd
->parent
;
245 wfd
->prev
->next
= wfd
->next
;
247 sel
->whead
= wfd
->next
;
249 wfd
->next
->prev
= wfd
->prev
;
251 sel
->wtail
= wfd
->prev
;
253 bufchain_clear(&wfd
->buf
);
260 int sel_rfd_delete(sel_rfd
*rfd
)
262 sel
*sel
= rfd
->parent
;
266 rfd
->prev
->next
= rfd
->next
;
268 sel
->rhead
= rfd
->next
;
270 rfd
->next
->prev
= rfd
->prev
;
272 sel
->rtail
= rfd
->prev
;
279 void sel_free(sel
*sel
)
282 sel_wfd_delete(sel
->whead
);
284 sel_rfd_delete(sel
->rhead
);
288 void *sel_get_ctx(sel
*sel
) { return sel
->ctx
; }
289 void sel_set_ctx(sel
*sel
, void *ctx
) { sel
->ctx
= ctx
; }
290 void *sel_wfd_get_ctx(sel_wfd
*wfd
) { return wfd
->ctx
; }
291 void sel_wfd_set_ctx(sel_wfd
*wfd
, void *ctx
) { wfd
->ctx
= ctx
; }
292 void *sel_rfd_get_ctx(sel_rfd
*rfd
) { return rfd
->ctx
; }
293 void sel_rfd_set_ctx(sel_rfd
*rfd
, void *ctx
) { rfd
->ctx
= ctx
; }
295 int sel_iterate(sel
*sel
, long timeout
)
301 struct timeval tv
, *ptv
;
308 for (rfd
= sel
->rhead
; rfd
; rfd
= rfd
->next
) {
309 if (rfd
->fd
>= 0 && !rfd
->frozen
) {
310 FD_SET(rfd
->fd
, &rset
);
311 if (maxfd
< rfd
->fd
+ 1)
316 for (wfd
= sel
->whead
; wfd
; wfd
= wfd
->next
) {
317 if (wfd
->fd
>= 0 && bufchain_size(&wfd
->buf
)) {
318 FD_SET(wfd
->fd
, &wset
);
319 if (maxfd
< wfd
->fd
+ 1)
328 tv
.tv_sec
= timeout
/ 1000;
329 tv
.tv_usec
= 1000 * (timeout
% 1000);
333 ret
= select(maxfd
, &rset
, &wset
, NULL
, ptv
);
334 } while (ret
< 0 && (errno
== EINTR
|| errno
== EAGAIN
));
340 * Just in case one of the callbacks destroys an rfd or wfd we
341 * had yet to get round to, we must loop from the start every
342 * single time. Algorithmically irritating, but necessary
343 * unless we want to store the rfd structures in a heavyweight
344 * tree sorted by fd. And let's face it, if we cared about
345 * good algorithmic complexity it's not at all clear we'd be
346 * using select in the first place.
349 for (wfd
= sel
->whead
; wfd
; wfd
= wfd
->next
)
350 if (wfd
->fd
>= 0 && FD_ISSET(wfd
->fd
, &wset
)) {
354 FD_CLR(wfd
->fd
, &wset
);
355 bufchain_prefix(&wfd
->buf
, &data
, &len
);
356 ret
= write(wfd
->fd
, data
, len
);
360 wfd
->writeerr(wfd
, errno
);
362 bufchain_consume(&wfd
->buf
, len
);
364 wfd
->written(wfd
, bufchain_size(&wfd
->buf
));
370 for (rfd
= sel
->rhead
; rfd
; rfd
= rfd
->next
)
371 if (rfd
->fd
>= 0 && !rfd
->frozen
&& FD_ISSET(rfd
->fd
, &rset
)) {
372 FD_CLR(rfd
->fd
, &rset
);
373 ret
= read(rfd
->fd
, buf
, sizeof(buf
));
376 rfd
->readerr(rfd
, errno
);
379 rfd
->readdata(rfd
, buf
, ret
);