pollfd.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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. * @return Pointer to new item or NULL on error.
  122. */
  123. struct pollfd *faux_pollfd_add(faux_pollfd_t *faux_pollfd, int fd)
  124. {
  125. struct pollfd *pollfd = NULL;
  126. assert(faux_pollfd);
  127. if (!faux_pollfd)
  128. return NULL;
  129. assert(fd >= 0);
  130. if (fd < 0)
  131. return NULL;
  132. // Don't add duplicate fd
  133. pollfd = faux_pollfd_find(faux_pollfd, fd);
  134. if (pollfd)
  135. return 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. return pollfd;
  143. }
  144. /** @brief Removes item specified by fd.
  145. *
  146. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  147. * @param [in] fd File descriptor to remove.
  148. * @return 0 - success, < 0 on error.
  149. */
  150. int faux_pollfd_del_by_fd(faux_pollfd_t *faux_pollfd, int fd)
  151. {
  152. int index = 0;
  153. assert(faux_pollfd);
  154. if (!faux_pollfd)
  155. return -1;
  156. assert(fd >= 0);
  157. if (fd < 0)
  158. return -1;
  159. index = faux_vec_find(faux_pollfd->vec, &fd, 0);
  160. if (index < 0) // Not found
  161. return -1;
  162. return faux_vec_del(faux_pollfd->vec, index);
  163. }
  164. /** @brief Removes item specified by index.
  165. *
  166. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  167. * @param [in] index Index of item to remove.
  168. * @return 0 - success, < 0 on error.
  169. */
  170. int faux_pollfd_del_by_index(faux_pollfd_t *faux_pollfd, unsigned int index)
  171. {
  172. assert(faux_pollfd);
  173. if (!faux_pollfd)
  174. return -1;
  175. return faux_vec_del(faux_pollfd->vec, index);
  176. }
  177. /** @brief Initilizes iterator to iterate through all the vector.
  178. *
  179. * @sa faux_pollfd_each()
  180. * @sa faux_pollfd_each_active()
  181. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  182. * @param [out] iterator Iterator to initialize.
  183. */
  184. void faux_pollfd_init_iterator(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  185. {
  186. assert(faux_pollfd);
  187. if (!faux_pollfd)
  188. return;
  189. if (!iterator)
  190. return;
  191. *iterator = 0;
  192. }
  193. /** @brief Iterate through all the vector.
  194. *
  195. * The iterator must be initialized first by faux_pollfd_init_iterator().
  196. *
  197. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  198. * @param [out] iterator Initialized iterator.
  199. * @return Pointer to item or NULL on error or on end of vector.
  200. */
  201. struct pollfd *faux_pollfd_each(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  202. {
  203. unsigned int old_iterator = 0;
  204. assert(faux_pollfd);
  205. if (!faux_pollfd)
  206. return NULL;
  207. if (!iterator)
  208. return NULL;
  209. old_iterator = *iterator;
  210. (*iterator)++;
  211. return faux_pollfd_item(faux_pollfd, old_iterator);
  212. }
  213. /** @brief Iterate through all active items of vector.
  214. *
  215. * The iterator must be initialized first by faux_pollfd_init_iterator().
  216. * Function returns items that has non-null value in "revent" field i.e.
  217. * active items.
  218. *
  219. * @param [in] faux_pollfd Allocated faux_pollfd_t object.
  220. * @param [out] iterator Initialized iterator.
  221. * @return Pointer to active item or NULL on error or on end of vector.
  222. */
  223. struct pollfd *faux_pollfd_each_active(faux_pollfd_t *faux_pollfd, faux_pollfd_iterator_t *iterator)
  224. {
  225. struct pollfd *pollfd = NULL;
  226. assert(faux_pollfd);
  227. if (!faux_pollfd)
  228. return NULL;
  229. if (!iterator)
  230. return NULL;
  231. while ((pollfd = faux_pollfd_each(faux_pollfd, iterator))) {
  232. if (pollfd->revents != 0)
  233. return pollfd;
  234. }
  235. return NULL;
  236. }