net.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /** @file net.c
  2. * @brief Network related functions.
  3. */
  4. // For ppol()
  5. #define _GNU_SOURCE
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <sys/uio.h>
  14. #include <signal.h>
  15. #include <poll.h>
  16. #include "faux/faux.h"
  17. #include "faux/time.h"
  18. #include "faux/net.h"
  19. /** @brief Sends data to socket. Uses timeout and signal mask.
  20. *
  21. * The function acts like a pselect(). It gets timeout interval to interrupt
  22. * too long sending. It gets signal mask to atomically set it while blocking
  23. * within select() like function. But it doesn't blocks signals before it.
  24. * User code must do it. The function can be interrupted by unblocked signal or
  25. * by timeout. Else it will send() all data given.
  26. *
  27. * @param [in] fd Socket.
  28. * @param [in] buf Buffer to write.
  29. * @param [in] n Number of bytes to write.
  30. * @return Number of bytes written or < 0 on error.
  31. */
  32. ssize_t faux_send(int fd, const void *buf, size_t n,
  33. const struct timespec *timeout, const sigset_t *sigmask)
  34. {
  35. size_t total_written = 0;
  36. size_t left = n;
  37. const void *data = buf;
  38. struct timespec now = {};
  39. struct timespec deadline = {};
  40. assert(fd != -1);
  41. assert(buf);
  42. if ((-1 == fd) || !buf)
  43. return -1;
  44. if (0 == n)
  45. return 0;
  46. // Calculate deadline - the time when timeout must occur.
  47. if (timeout) {
  48. faux_timespec_now(&now);
  49. faux_timespec_sum(&deadline, &now, timeout);
  50. }
  51. do {
  52. ssize_t bytes_written = 0;
  53. struct pollfd fds = {};
  54. struct timespec *poll_timeout = NULL;
  55. struct timespec to = {};
  56. int sn = 0;
  57. if (timeout) {
  58. if (faux_timespec_before_now(&deadline))
  59. break; // Timeout already occured
  60. faux_timespec_now(&now);
  61. faux_timespec_diff(&to, &deadline, &now);
  62. poll_timeout = &to;
  63. }
  64. // Handlers for poll()
  65. faux_bzero(&fds, sizeof(fds));
  66. fds.fd = fd;
  67. fds.events = POLLOUT;
  68. sn = ppoll(&fds, 1, poll_timeout, sigmask);
  69. // When kernel can't allocate some internal structures it can
  70. // return EAGAIN so retry.
  71. if ((sn < 0) && (EAGAIN == errno))
  72. continue;
  73. // All unneded signals are masked so don't process EINTR
  74. // in special way. Just break the loop
  75. if (sn < 0)
  76. break;
  77. // Timeout: break the loop. User don't want to wait any more
  78. if (0 == sn)
  79. break;
  80. // Some unknown event (not POLLOUT). So retry polling
  81. if (!(fds.revents & POLLOUT))
  82. continue;
  83. // The send() call is non-blocking but it's not obvious that
  84. // it can't return EINTR. Probably it can. Due to the fact the
  85. // call is non-blocking re-send() on any signal i.e. any EINTR.
  86. do {
  87. bytes_written = send(fd, data, left, MSG_DONTWAIT | MSG_NOSIGNAL);
  88. } while ((bytes_written < 0) && (EINTR == errno));
  89. if (bytes_written < 0)
  90. break;
  91. // Insufficient space
  92. if (0 == bytes_written)
  93. break;
  94. data += bytes_written;
  95. left = left - bytes_written;
  96. total_written += bytes_written;
  97. } while (left > 0);
  98. return total_written;
  99. }
  100. ssize_t faux_send_block(int fd, const void *buf, size_t n,
  101. const struct timespec *timeout, const sigset_t *sigmask,
  102. int (*isbreak_func)(void))
  103. {
  104. sigset_t all_sigmask = {}; // All signals mask
  105. sigset_t orig_sigmask = {}; // Saved signal mask
  106. ssize_t bytes_num = 0;
  107. assert(fd != -1);
  108. assert(buf);
  109. if ((-1 == fd) || !buf)
  110. return -1;
  111. if (0 == n)
  112. return 0;
  113. // Block signals to prevent race conditions right before pselect()
  114. // Catch signals while pselect() only
  115. // Now blocks all signals
  116. sigfillset(&all_sigmask);
  117. pthread_sigmask(SIG_SETMASK, &all_sigmask, &orig_sigmask);
  118. // Signal handler can set var to interrupt exchange.
  119. // Get value of this var by special callback function.
  120. if (isbreak_func && isbreak_func())
  121. return -1;
  122. bytes_num = faux_send(fd, buf, n, timeout, sigmask);
  123. pthread_sigmask(SIG_SETMASK, &orig_sigmask, NULL);
  124. return bytes_num;
  125. }
  126. /** @brief Sends struct iovec data blocks to socket.
  127. *
  128. * This function is like a faux_send() function but uses scatter/gather.
  129. *
  130. * @see faux_send().
  131. * @param [in] fd Socket.
  132. * @param [in] buf Buffer to write.
  133. * @param [in] n Number of bytes to write.
  134. * @param [in] flags Flags.
  135. * @return Number of bytes written.
  136. * < total_length then insufficient space, timeout or
  137. * error (but some data were already sent).
  138. * < 0 - error.
  139. */
  140. ssize_t faux_sendv(int fd, const struct iovec *iov, int iovcnt,
  141. const struct timespec *timeout, const sigset_t *sigmask)
  142. {
  143. size_t total_written = 0;
  144. int i = 0;
  145. struct timespec now = {};
  146. struct timespec deadline = {};
  147. if (!iov)
  148. return -1;
  149. if (iovcnt == 0)
  150. return 0;
  151. // Calculate deadline - the time when timeout must occur.
  152. if (timeout) {
  153. faux_timespec_now(&now);
  154. faux_timespec_sum(&deadline, &now, timeout);
  155. }
  156. for (i = 0; i < iovcnt; i++) {
  157. ssize_t bytes_written = 0;
  158. struct timespec *send_timeout = NULL;
  159. struct timespec to = {};
  160. if (timeout) {
  161. if (faux_timespec_before_now(&deadline))
  162. break; // Timeout already occured
  163. faux_timespec_now(&now);
  164. faux_timespec_diff(&to, &deadline, &now);
  165. send_timeout = &to;
  166. }
  167. if (iov[i].iov_len == 0)
  168. continue;
  169. bytes_written = faux_send(fd, iov[i].iov_base, iov[i].iov_len,
  170. send_timeout, sigmask);
  171. if (bytes_written < 0) { // Error
  172. if (total_written != 0)
  173. break;
  174. return -1;
  175. }
  176. if (0 == bytes_written) // Insufficient space or timeout
  177. break;
  178. total_written += bytes_written;
  179. }
  180. return total_written;
  181. }
  182. ssize_t faux_sendv_block(int fd, const struct iovec *iov, int iovcnt,
  183. const struct timespec *timeout, const sigset_t *sigmask,
  184. int (*isbreak_func)(void))
  185. {
  186. sigset_t all_sigmask = {}; // All signals mask
  187. sigset_t orig_sigmask = {}; // Saved signal mask
  188. ssize_t bytes_num = 0;
  189. assert(fd != -1);
  190. if ((-1 == fd))
  191. return -1;
  192. if (!iov)
  193. return -1;
  194. if (iovcnt == 0)
  195. return 0;
  196. // Block signals to prevent race conditions right before pselect()
  197. // Catch signals while pselect() only
  198. // Now blocks all signals
  199. sigfillset(&all_sigmask);
  200. pthread_sigmask(SIG_SETMASK, &all_sigmask, &orig_sigmask);
  201. // Signal handler can set var to interrupt exchange.
  202. // Get value of this var by special callback function.
  203. if (isbreak_func && isbreak_func())
  204. return -1;
  205. bytes_num = faux_sendv(fd, iov, iovcnt, timeout, sigmask);
  206. pthread_sigmask(SIG_SETMASK, &orig_sigmask, NULL);
  207. return bytes_num;
  208. }
  209. ssize_t faux_recv(int fd, void *buf, size_t n,
  210. const struct timespec *timeout, const sigset_t *sigmask)
  211. {
  212. size_t total_readed = 0;
  213. size_t left = n;
  214. void *data = buf;
  215. struct timespec now = {};
  216. struct timespec deadline = {};
  217. assert(fd != -1);
  218. assert(buf);
  219. if ((-1 == fd) || !buf)
  220. return -1;
  221. if (0 == n)
  222. return 0;
  223. // Calculate deadline - the time when timeout must occur.
  224. if (timeout) {
  225. faux_timespec_now(&now);
  226. faux_timespec_sum(&deadline, &now, timeout);
  227. }
  228. do {
  229. ssize_t bytes_readed = 0;
  230. struct pollfd fds = {};
  231. struct timespec *poll_timeout = NULL;
  232. struct timespec to = {};
  233. int sn = 0;
  234. if (timeout) {
  235. if (faux_timespec_before_now(&deadline))
  236. break; // Timeout already occured
  237. faux_timespec_now(&now);
  238. faux_timespec_diff(&to, &deadline, &now);
  239. poll_timeout = &to;
  240. }
  241. // Handlers for poll()
  242. faux_bzero(&fds, sizeof(fds));
  243. fds.fd = fd;
  244. fds.events = POLLIN;
  245. sn = ppoll(&fds, 1, poll_timeout, sigmask);
  246. // When kernel can't allocate some internal structures it can
  247. // return EAGAIN so retry.
  248. if ((sn < 0) && (EAGAIN == errno))
  249. continue;
  250. // All unneded signals are masked so don't process EINTR
  251. // in special way. Just break the loop
  252. if (sn < 0)
  253. break;
  254. // Timeout: break the loop. User don't want to wait any more
  255. if (0 == sn)
  256. break;
  257. // Some unknown event (not POLLIN). So retry polling
  258. if (!(fds.revents & POLLIN))
  259. continue;
  260. // The send() call is non-blocking but it's not obvious that
  261. // it can't return EINTR. Probably it can. Due to the fact the
  262. // call is non-blocking re-send() on any signal i.e. any EINTR.
  263. do {
  264. bytes_readed = recv(fd, data, left, MSG_DONTWAIT | MSG_NOSIGNAL);
  265. } while ((bytes_readed < 0) && (EINTR == errno));
  266. if (bytes_readed < 0)
  267. break;
  268. // EOF
  269. if (0 == bytes_readed)
  270. break;
  271. data += bytes_readed;
  272. left = left - bytes_readed;
  273. total_readed += bytes_readed;
  274. } while (left > 0);
  275. return total_readed;
  276. }
  277. ssize_t faux_recvv(int fd, struct iovec *iov, int iovcnt,
  278. const struct timespec *timeout, const sigset_t *sigmask)
  279. {
  280. size_t total_readed = 0;
  281. int i = 0;
  282. struct timespec now = {};
  283. struct timespec deadline = {};
  284. if (!iov)
  285. return -1;
  286. if (iovcnt == 0)
  287. return 0;
  288. // Calculate deadline - the time when timeout must occur.
  289. if (timeout) {
  290. faux_timespec_now(&now);
  291. faux_timespec_sum(&deadline, &now, timeout);
  292. }
  293. for (i = 0; i < iovcnt; i++) {
  294. ssize_t bytes_readed = 0;
  295. struct timespec *recv_timeout = NULL;
  296. struct timespec to = {};
  297. if (timeout) {
  298. if (faux_timespec_before_now(&deadline))
  299. break; // Timeout already occured
  300. faux_timespec_now(&now);
  301. faux_timespec_diff(&to, &deadline, &now);
  302. recv_timeout = &to;
  303. }
  304. if (iov[i].iov_len == 0)
  305. continue;
  306. bytes_readed = faux_recv(fd, iov[i].iov_base, iov[i].iov_len,
  307. recv_timeout, sigmask);
  308. if (bytes_readed < 0) { // Error
  309. if (total_readed != 0)
  310. break;
  311. return -1;
  312. }
  313. if (0 == bytes_readed) // EOF or timeout
  314. break;
  315. total_readed += bytes_readed;
  316. }
  317. return total_readed;
  318. }