pollfd.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /** @file pollfd.c
  2. */
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <unistd.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. #include <poll.h>
  12. #include "faux/faux.h"
  13. #include "faux/net.h"
  14. #include "faux/vec.h"
  15. #include "private.h"
  16. /** @brief Callback function to search specified fd within pollfd structures.
  17. */
  18. static int cmp_by_fd(const void *key, const void *item)
  19. {
  20. int k = *(int *)key;
  21. struct pollfd *i = (struct pollfd *)item;
  22. if (k == i->fd)
  23. return 0;
  24. return -1;
  25. }
  26. /** @brief Allocates memory for faux_pollfd_t object.
  27. *
  28. * @return Allocated faux_pollfd_t object or NULL on error.
  29. */
  30. faux_pollfd_t *faux_pollfd_new(void)
  31. {
  32. faux_pollfd_t *faux_pollfd = NULL;
  33. faux_pollfd = faux_zmalloc(sizeof(*faux_pollfd));
  34. assert(faux_pollfd);
  35. if (!faux_pollfd)
  36. return NULL;
  37. faux_pollfd->vec = faux_vec_new(sizeof(struct pollfd), cmp_by_fd);
  38. return faux_pollfd;
  39. }
  40. /** @brief Frees previously allocated faux_pollfd_t object.
  41. *
  42. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  43. */
  44. void faux_pollfd_free(faux_pollfd_t *faux_pollfd)
  45. {
  46. if (!faux_pollfd)
  47. return;
  48. faux_vec_free(faux_pollfd->vec);
  49. faux_free(faux_pollfd);
  50. }
  51. /** @brief Returns whole "struct pollfd" vector.
  52. *
  53. * It can be used while poll() call.
  54. *
  55. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  56. * @return Pointer to "struct pollfd" vector or NULL on error.
  57. */
  58. struct pollfd *faux_pollfd_vector(faux_pollfd_t *faux_pollfd)
  59. {
  60. assert(faux_pollfd);
  61. if (!faux_pollfd)
  62. return NULL;
  63. return faux_vec_data(faux_pollfd->vec);
  64. }
  65. /** @brief Returns number of "struct pollfd" items within object.
  66. *
  67. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  68. * @return Number of items.
  69. */
  70. size_t faux_pollfd_len(faux_pollfd_t *faux_pollfd)
  71. {
  72. assert(faux_pollfd);
  73. if (!faux_pollfd)
  74. return 0;
  75. return faux_vec_len(faux_pollfd->vec);
  76. }
  77. /** @brief Returns "struct pollfd" item by specified index.
  78. *
  79. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  80. * @param [in] index Index of item to get.
  81. * @return Pointer to item or NULL on error.
  82. */
  83. struct pollfd *faux_pollfd_item(faux_pollfd_t *faux_pollfd, unsigned int index)
  84. {
  85. assert(faux_pollfd);
  86. if (!faux_pollfd)
  87. return NULL;
  88. return (struct pollfd *)faux_vec_item(faux_pollfd->vec, index);
  89. }
  90. /** @brief Finds item with specified fd value.
  91. *
  92. * File descriptor is a key for array. Object can contain the only one item
  93. * with the same fd value.
  94. *
  95. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  96. * @param [in] fd File descriptor to search for.
  97. * @return Pointer to found item or NULL on error or in "not found" case.
  98. */
  99. struct pollfd *faux_pollfd_find(faux_pollfd_t *faux_pollfd, int fd)
  100. {
  101. int index = 0;
  102. assert(faux_pollfd);
  103. if (!faux_pollfd)
  104. return NULL;
  105. assert(fd >= 0);
  106. if (fd < 0)
  107. return NULL;
  108. index = faux_vec_find(faux_pollfd->vec, &fd, 0);
  109. if (index < 0)
  110. return NULL;
  111. return (struct pollfd *)faux_vec_item(faux_pollfd->vec, index);
  112. }
  113. /** @brief Adds new item to object.
  114. *
  115. * The file descriptors are unique within array. So function try to find item
  116. * with the specified fd. If it's found the correspondent item will be returned
  117. * but new item will not be created.
  118. *
  119. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  120. * @param [in] fd File descriptor to set to newly created item.
  121. * @param [in] events The events interested in.
  122. * @return Pointer to new item or NULL on error.
  123. */
  124. struct pollfd *faux_pollfd_add(faux_pollfd_t *faux_pollfd, int fd, short events)
  125. {
  126. struct pollfd *pollfd = NULL;
  127. assert(faux_pollfd);
  128. if (!faux_pollfd)
  129. return NULL;
  130. assert(fd >= 0);
  131. if (fd < 0)
  132. return NULL;
  133. // Don't add duplicated fd
  134. pollfd = faux_pollfd_find(faux_pollfd, fd);
  135. if (!pollfd) {
  136. // Create new item
  137. pollfd = faux_vec_add(faux_pollfd->vec);
  138. assert(pollfd);
  139. if (!pollfd)
  140. return NULL;
  141. pollfd->fd = fd;
  142. }
  143. pollfd->events = events;
  144. pollfd->revents = 0;
  145. return pollfd;
  146. }
  147. /** @brief Removes item specified by fd.
  148. *
  149. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  150. * @param [in] fd File descriptor to remove.
  151. * @return 0 - success, < 0 on error.
  152. */
  153. int faux_pollfd_del_by_fd(faux_pollfd_t *faux_pollfd, int fd)
  154. {
  155. int index = 0;
  156. assert(faux_pollfd);
  157. if (!faux_pollfd)
  158. return -1;
  159. assert(fd >= 0);
  160. if (fd < 0)
  161. return -1;
  162. index = faux_vec_find(faux_pollfd->vec, &fd, 0);
  163. if (index < 0) // Not found
  164. return -1;
  165. return faux_vec_del(faux_pollfd->vec, index);
  166. }
  167. /** @brief Removes item specified by index.
  168. *
  169. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  170. * @param [in] index Index of item to remove.
  171. * @return 0 - success, < 0 on error.
  172. */
  173. int faux_pollfd_del_by_index(faux_pollfd_t *faux_pollfd, unsigned int index)
  174. {
  175. assert(faux_pollfd);
  176. if (!faux_pollfd)
  177. return -1;
  178. return faux_vec_del(faux_pollfd->vec, index);
  179. }
  180. /** @brief Initilizes iterator to iterate through all the vector.
  181. *
  182. * @sa faux_pollfd_each()
  183. * @sa faux_pollfd_each_active()
  184. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  185. * @param [out] iterator Iterator to initialize.
  186. */
  187. void faux_pollfd_init_iterator(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  188. {
  189. assert(faux_pollfd);
  190. if (!faux_pollfd)
  191. return;
  192. if (!iterator)
  193. return;
  194. *iterator = 0;
  195. }
  196. /** @brief Iterate through all the vector.
  197. *
  198. * The iterator must be initialized first by faux_pollfd_init_iterator().
  199. *
  200. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  201. * @param [out] iterator Initialized iterator.
  202. * @return Pointer to item or NULL on error or on end of vector.
  203. */
  204. struct pollfd *faux_pollfd_each(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  205. {
  206. unsigned int old_iterator = 0;
  207. assert(faux_pollfd);
  208. if (!faux_pollfd)
  209. return NULL;
  210. if (!iterator)
  211. return NULL;
  212. old_iterator = *iterator;
  213. (*iterator)++;
  214. return faux_pollfd_item(faux_pollfd, old_iterator);
  215. }
  216. /** @brief Iterate through all active items of vector.
  217. *
  218. * The iterator must be initialized first by faux_pollfd_init_iterator().
  219. * Function returns items that has non-null value in "revent" field i.e.
  220. * active items.
  221. *
  222. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  223. * @param [out] iterator Initialized iterator.
  224. * @return Pointer to active item or NULL on error or on end of vector.
  225. */
  226. struct pollfd *faux_pollfd_each_active(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  227. {
  228. struct pollfd *pollfd = NULL;
  229. assert(faux_pollfd);
  230. if (!faux_pollfd)
  231. return NULL;
  232. if (!iterator)
  233. return NULL;
  234. while ((pollfd = faux_pollfd_each(faux_pollfd, iterator))) {
  235. if (pollfd->revents != 0)
  236. return pollfd;
  237. }
  238. return NULL;
  239. }