net_io.c 11 KB

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