sel.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * sel.c: implementation of sel.h.
  3. */
  4. #include <stddef.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <assert.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <sys/time.h>
  11. #include <sys/types.h>
  12. #include <sys/select.h>
  13. #include "sel.h"
  14. #include "malloc.h"
  15. /* ----------------------------------------------------------------------
  16. * Chunk of code lifted from PuTTY's misc.c to manage buffers of
  17. * data to be written to an fd.
  18. */
  19. #define BUFFER_GRANULE 512
  20. typedef struct bufchain_tag {
  21. struct bufchain_granule *head, *tail;
  22. size_t buffersize; /* current amount of buffered data */
  23. } bufchain;
  24. struct bufchain_granule {
  25. struct bufchain_granule *next;
  26. size_t buflen, bufpos;
  27. char buf[BUFFER_GRANULE];
  28. };
  29. static void bufchain_init(bufchain *ch)
  30. {
  31. ch->head = ch->tail = NULL;
  32. ch->buffersize = 0;
  33. }
  34. static void bufchain_clear(bufchain *ch)
  35. {
  36. struct bufchain_granule *b;
  37. while (ch->head) {
  38. b = ch->head;
  39. ch->head = ch->head->next;
  40. sfree(b);
  41. }
  42. ch->tail = NULL;
  43. ch->buffersize = 0;
  44. }
  45. static size_t bufchain_size(bufchain *ch)
  46. {
  47. return ch->buffersize;
  48. }
  49. static void bufchain_add(bufchain *ch, const void *data, size_t len)
  50. {
  51. const char *buf = (const char *)data;
  52. if (len == 0) return;
  53. ch->buffersize += len;
  54. if (ch->tail && ch->tail->buflen < BUFFER_GRANULE) {
  55. size_t copylen = BUFFER_GRANULE - ch->tail->buflen;
  56. if (copylen > len)
  57. copylen = len;
  58. memcpy(ch->tail->buf + ch->tail->buflen, buf, copylen);
  59. buf += copylen;
  60. len -= copylen;
  61. ch->tail->buflen += copylen;
  62. }
  63. while (len > 0) {
  64. struct bufchain_granule *newbuf;
  65. size_t grainlen = BUFFER_GRANULE;
  66. if (grainlen > len)
  67. grainlen = len;
  68. newbuf = snew(struct bufchain_granule);
  69. newbuf->bufpos = 0;
  70. newbuf->buflen = grainlen;
  71. memcpy(newbuf->buf, buf, grainlen);
  72. buf += grainlen;
  73. len -= grainlen;
  74. if (ch->tail)
  75. ch->tail->next = newbuf;
  76. else
  77. ch->head = ch->tail = newbuf;
  78. newbuf->next = NULL;
  79. ch->tail = newbuf;
  80. }
  81. }
  82. static void bufchain_consume(bufchain *ch, size_t len)
  83. {
  84. struct bufchain_granule *tmp;
  85. assert(ch->buffersize >= len);
  86. while (len > 0) {
  87. size_t remlen = len;
  88. assert(ch->head != NULL);
  89. if (remlen >= ch->head->buflen - ch->head->bufpos) {
  90. remlen = ch->head->buflen - ch->head->bufpos;
  91. tmp = ch->head;
  92. ch->head = tmp->next;
  93. sfree(tmp);
  94. if (!ch->head)
  95. ch->tail = NULL;
  96. } else
  97. ch->head->bufpos += remlen;
  98. ch->buffersize -= remlen;
  99. len -= remlen;
  100. }
  101. }
  102. static void bufchain_prefix(bufchain *ch, void **data, size_t *len)
  103. {
  104. *len = ch->head->buflen - ch->head->bufpos;
  105. *data = ch->head->buf + ch->head->bufpos;
  106. }
  107. /* ----------------------------------------------------------------------
  108. * The actual implementation of the sel interface.
  109. */
  110. struct sel {
  111. void *ctx;
  112. sel_rfd *rhead, *rtail;
  113. sel_wfd *whead, *wtail;
  114. };
  115. struct sel_rfd {
  116. sel *parent;
  117. sel_rfd *prev, *next;
  118. sel_readdata_fn_t readdata;
  119. sel_readerr_fn_t readerr;
  120. void *ctx;
  121. int fd;
  122. int frozen;
  123. };
  124. struct sel_wfd {
  125. sel *parent;
  126. sel_wfd *prev, *next;
  127. sel_written_fn_t written;
  128. sel_writeerr_fn_t writeerr;
  129. void *ctx;
  130. int fd;
  131. bufchain buf;
  132. };
  133. sel *sel_new(void *ctx)
  134. {
  135. sel *sel = snew(struct sel);
  136. sel->ctx = ctx;
  137. sel->rhead = sel->rtail = NULL;
  138. sel->whead = sel->wtail = NULL;
  139. return sel;
  140. }
  141. sel_wfd *sel_wfd_add(sel *sel, int fd,
  142. sel_written_fn_t written, sel_writeerr_fn_t writeerr,
  143. void *ctx)
  144. {
  145. sel_wfd *wfd = snew(sel_wfd);
  146. wfd->written = written;
  147. wfd->writeerr = writeerr;
  148. wfd->ctx = ctx;
  149. wfd->fd = fd;
  150. bufchain_init(&wfd->buf);
  151. wfd->next = NULL;
  152. wfd->prev = sel->wtail;
  153. if (sel->wtail)
  154. sel->wtail->next = wfd;
  155. else
  156. sel->whead = wfd;
  157. sel->wtail = wfd;
  158. wfd->parent = sel;
  159. return wfd;
  160. }
  161. sel_rfd *sel_rfd_add(sel *sel, int fd,
  162. sel_readdata_fn_t readdata, sel_readerr_fn_t readerr,
  163. void *ctx)
  164. {
  165. sel_rfd *rfd = snew(sel_rfd);
  166. rfd->readdata = readdata;
  167. rfd->readerr = readerr;
  168. rfd->ctx = ctx;
  169. rfd->fd = fd;
  170. rfd->frozen = 0;
  171. rfd->next = NULL;
  172. rfd->prev = sel->rtail;
  173. if (sel->rtail)
  174. sel->rtail->next = rfd;
  175. else
  176. sel->rhead = rfd;
  177. sel->rtail = rfd;
  178. rfd->parent = sel;
  179. return rfd;
  180. }
  181. size_t sel_write(sel_wfd *wfd, const void *data, size_t len)
  182. {
  183. bufchain_add(&wfd->buf, data, len);
  184. return bufchain_size(&wfd->buf);
  185. }
  186. void sel_wfd_setfd(sel_wfd *wfd, int fd)
  187. {
  188. wfd->fd = fd;
  189. }
  190. void sel_rfd_setfd(sel_rfd *rfd, int fd)
  191. {
  192. rfd->fd = fd;
  193. }
  194. void sel_rfd_freeze(sel_rfd *rfd)
  195. {
  196. rfd->frozen = 1;
  197. }
  198. void sel_rfd_unfreeze(sel_rfd *rfd)
  199. {
  200. rfd->frozen = 0;
  201. }
  202. int sel_wfd_delete(sel_wfd *wfd)
  203. {
  204. sel *sel = wfd->parent;
  205. int ret;
  206. if (wfd->prev)
  207. wfd->prev->next = wfd->next;
  208. else
  209. sel->whead = wfd->next;
  210. if (wfd->next)
  211. wfd->next->prev = wfd->prev;
  212. else
  213. sel->wtail = wfd->prev;
  214. bufchain_clear(&wfd->buf);
  215. ret = wfd->fd;
  216. sfree(wfd);
  217. return ret;
  218. }
  219. int sel_rfd_delete(sel_rfd *rfd)
  220. {
  221. sel *sel = rfd->parent;
  222. int ret;
  223. if (rfd->prev)
  224. rfd->prev->next = rfd->next;
  225. else
  226. sel->rhead = rfd->next;
  227. if (rfd->next)
  228. rfd->next->prev = rfd->prev;
  229. else
  230. sel->rtail = rfd->prev;
  231. ret = rfd->fd;
  232. sfree(rfd);
  233. return ret;
  234. }
  235. void sel_free(sel *sel)
  236. {
  237. while (sel->whead)
  238. sel_wfd_delete(sel->whead);
  239. while (sel->rhead)
  240. sel_rfd_delete(sel->rhead);
  241. sfree(sel);
  242. }
  243. void *sel_get_ctx(sel *sel) { return sel->ctx; }
  244. void sel_set_ctx(sel *sel, void *ctx) { sel->ctx = ctx; }
  245. void *sel_wfd_get_ctx(sel_wfd *wfd) { return wfd->ctx; }
  246. void sel_wfd_set_ctx(sel_wfd *wfd, void *ctx) { wfd->ctx = ctx; }
  247. void *sel_rfd_get_ctx(sel_rfd *rfd) { return rfd->ctx; }
  248. void sel_rfd_set_ctx(sel_rfd *rfd, void *ctx) { rfd->ctx = ctx; }
  249. int sel_iterate(sel *sel, long timeout)
  250. {
  251. sel_rfd *rfd;
  252. sel_wfd *wfd;
  253. fd_set rset, wset;
  254. int maxfd = 0;
  255. struct timeval tv, *ptv;
  256. char buf[65536];
  257. int ret;
  258. FD_ZERO(&rset);
  259. FD_ZERO(&wset);
  260. for (rfd = sel->rhead; rfd; rfd = rfd->next) {
  261. if (rfd->fd >= 0 && !rfd->frozen) {
  262. FD_SET(rfd->fd, &rset);
  263. if (maxfd < rfd->fd + 1)
  264. maxfd = rfd->fd + 1;
  265. }
  266. }
  267. for (wfd = sel->whead; wfd; wfd = wfd->next) {
  268. if (wfd->fd >= 0 && bufchain_size(&wfd->buf)) {
  269. FD_SET(wfd->fd, &wset);
  270. if (maxfd < wfd->fd + 1)
  271. maxfd = wfd->fd + 1;
  272. }
  273. }
  274. if (timeout < 0) {
  275. ptv = NULL;
  276. } else {
  277. ptv = &tv;
  278. tv.tv_sec = timeout / 1000;
  279. tv.tv_usec = 1000 * (timeout % 1000);
  280. }
  281. do {
  282. ret = select(maxfd, &rset, &wset, NULL, ptv);
  283. } while (ret < 0 && (errno == EINTR || errno == EAGAIN));
  284. if (ret < 0)
  285. return errno;
  286. /*
  287. * Just in case one of the callbacks destroys an rfd or wfd we
  288. * had yet to get round to, we must loop from the start every
  289. * single time. Algorithmically irritating, but necessary
  290. * unless we want to store the rfd structures in a heavyweight
  291. * tree sorted by fd. And let's face it, if we cared about
  292. * good algorithmic complexity it's not at all clear we'd be
  293. * using select in the first place.
  294. */
  295. do {
  296. for (wfd = sel->whead; wfd; wfd = wfd->next)
  297. if (wfd->fd >= 0 && FD_ISSET(wfd->fd, &wset)) {
  298. void *data;
  299. size_t len;
  300. FD_CLR(wfd->fd, &wset);
  301. bufchain_prefix(&wfd->buf, &data, &len);
  302. ret = write(wfd->fd, data, len);
  303. assert(ret != 0);
  304. if (ret < 0) {
  305. if (wfd->writeerr)
  306. wfd->writeerr(wfd, errno);
  307. } else {
  308. bufchain_consume(&wfd->buf, len);
  309. if (wfd->written)
  310. wfd->written(wfd, bufchain_size(&wfd->buf));
  311. }
  312. break;
  313. }
  314. } while (wfd);
  315. do {
  316. for (rfd = sel->rhead; rfd; rfd = rfd->next)
  317. if (rfd->fd >= 0 && !rfd->frozen && FD_ISSET(rfd->fd, &rset)) {
  318. FD_CLR(rfd->fd, &rset);
  319. ret = read(rfd->fd, buf, sizeof(buf));
  320. if (ret < 0) {
  321. if (rfd->readerr)
  322. rfd->readerr(rfd, errno);
  323. } else {
  324. if (rfd->readdata)
  325. rfd->readdata(rfd, buf, ret);
  326. }
  327. break;
  328. }
  329. } while (rfd);
  330. return 0;
  331. }