descriptor_ops.ipp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. //
  2. // detail/impl/descriptor_ops.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <cerrno>
  17. #include <boost/asio/detail/descriptor_ops.hpp>
  18. #include <boost/asio/error.hpp>
  19. #if !defined(BOOST_ASIO_WINDOWS) \
  20. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  21. && !defined(__CYGWIN__)
  22. #include <boost/asio/detail/push_options.hpp>
  23. namespace boost {
  24. namespace asio {
  25. namespace detail {
  26. namespace descriptor_ops {
  27. int open(const char* path, int flags, boost::system::error_code& ec)
  28. {
  29. errno = 0;
  30. int result = error_wrapper(::open(path, flags), ec);
  31. if (result >= 0)
  32. ec = boost::system::error_code();
  33. return result;
  34. }
  35. int close(int d, state_type& state, boost::system::error_code& ec)
  36. {
  37. int result = 0;
  38. if (d != -1)
  39. {
  40. errno = 0;
  41. result = error_wrapper(::close(d), ec);
  42. if (result != 0
  43. && (ec == boost::asio::error::would_block
  44. || ec == boost::asio::error::try_again))
  45. {
  46. // According to UNIX Network Programming Vol. 1, it is possible for
  47. // close() to fail with EWOULDBLOCK under certain circumstances. What
  48. // isn't clear is the state of the descriptor after this error. The one
  49. // current OS where this behaviour is seen, Windows, says that the socket
  50. // remains open. Therefore we'll put the descriptor back into blocking
  51. // mode and have another attempt at closing it.
  52. #if defined(__SYMBIAN32__)
  53. int flags = ::fcntl(d, F_GETFL, 0);
  54. if (flags >= 0)
  55. ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
  56. #else // defined(__SYMBIAN32__)
  57. ioctl_arg_type arg = 0;
  58. ::ioctl(d, FIONBIO, &arg);
  59. #endif // defined(__SYMBIAN32__)
  60. state &= ~non_blocking;
  61. errno = 0;
  62. result = error_wrapper(::close(d), ec);
  63. }
  64. }
  65. if (result == 0)
  66. ec = boost::system::error_code();
  67. return result;
  68. }
  69. bool set_user_non_blocking(int d, state_type& state,
  70. bool value, boost::system::error_code& ec)
  71. {
  72. if (d == -1)
  73. {
  74. ec = boost::asio::error::bad_descriptor;
  75. return false;
  76. }
  77. errno = 0;
  78. #if defined(__SYMBIAN32__)
  79. int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
  80. if (result >= 0)
  81. {
  82. errno = 0;
  83. int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
  84. result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
  85. }
  86. #else // defined(__SYMBIAN32__)
  87. ioctl_arg_type arg = (value ? 1 : 0);
  88. int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
  89. #endif // defined(__SYMBIAN32__)
  90. if (result >= 0)
  91. {
  92. ec = boost::system::error_code();
  93. if (value)
  94. state |= user_set_non_blocking;
  95. else
  96. {
  97. // Clearing the user-set non-blocking mode always overrides any
  98. // internally-set non-blocking flag. Any subsequent asynchronous
  99. // operations will need to re-enable non-blocking I/O.
  100. state &= ~(user_set_non_blocking | internal_non_blocking);
  101. }
  102. return true;
  103. }
  104. return false;
  105. }
  106. bool set_internal_non_blocking(int d, state_type& state,
  107. bool value, boost::system::error_code& ec)
  108. {
  109. if (d == -1)
  110. {
  111. ec = boost::asio::error::bad_descriptor;
  112. return false;
  113. }
  114. if (!value && (state & user_set_non_blocking))
  115. {
  116. // It does not make sense to clear the internal non-blocking flag if the
  117. // user still wants non-blocking behaviour. Return an error and let the
  118. // caller figure out whether to update the user-set non-blocking flag.
  119. ec = boost::asio::error::invalid_argument;
  120. return false;
  121. }
  122. errno = 0;
  123. #if defined(__SYMBIAN32__)
  124. int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
  125. if (result >= 0)
  126. {
  127. errno = 0;
  128. int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
  129. result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
  130. }
  131. #else // defined(__SYMBIAN32__)
  132. ioctl_arg_type arg = (value ? 1 : 0);
  133. int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
  134. #endif // defined(__SYMBIAN32__)
  135. if (result >= 0)
  136. {
  137. ec = boost::system::error_code();
  138. if (value)
  139. state |= internal_non_blocking;
  140. else
  141. state &= ~internal_non_blocking;
  142. return true;
  143. }
  144. return false;
  145. }
  146. std::size_t sync_read(int d, state_type state, buf* bufs,
  147. std::size_t count, bool all_empty, boost::system::error_code& ec)
  148. {
  149. if (d == -1)
  150. {
  151. ec = boost::asio::error::bad_descriptor;
  152. return 0;
  153. }
  154. // A request to read 0 bytes on a stream is a no-op.
  155. if (all_empty)
  156. {
  157. ec = boost::system::error_code();
  158. return 0;
  159. }
  160. // Read some data.
  161. for (;;)
  162. {
  163. // Try to complete the operation without blocking.
  164. errno = 0;
  165. signed_size_type bytes = error_wrapper(::readv(
  166. d, bufs, static_cast<int>(count)), ec);
  167. // Check if operation succeeded.
  168. if (bytes > 0)
  169. return bytes;
  170. // Check for EOF.
  171. if (bytes == 0)
  172. {
  173. ec = boost::asio::error::eof;
  174. return 0;
  175. }
  176. // Operation failed.
  177. if ((state & user_set_non_blocking)
  178. || (ec != boost::asio::error::would_block
  179. && ec != boost::asio::error::try_again))
  180. return 0;
  181. // Wait for descriptor to become ready.
  182. if (descriptor_ops::poll_read(d, 0, ec) < 0)
  183. return 0;
  184. }
  185. }
  186. bool non_blocking_read(int d, buf* bufs, std::size_t count,
  187. boost::system::error_code& ec, std::size_t& bytes_transferred)
  188. {
  189. for (;;)
  190. {
  191. // Read some data.
  192. errno = 0;
  193. signed_size_type bytes = error_wrapper(::readv(
  194. d, bufs, static_cast<int>(count)), ec);
  195. // Check for end of stream.
  196. if (bytes == 0)
  197. {
  198. ec = boost::asio::error::eof;
  199. return true;
  200. }
  201. // Retry operation if interrupted by signal.
  202. if (ec == boost::asio::error::interrupted)
  203. continue;
  204. // Check if we need to run the operation again.
  205. if (ec == boost::asio::error::would_block
  206. || ec == boost::asio::error::try_again)
  207. return false;
  208. // Operation is complete.
  209. if (bytes > 0)
  210. {
  211. ec = boost::system::error_code();
  212. bytes_transferred = bytes;
  213. }
  214. else
  215. bytes_transferred = 0;
  216. return true;
  217. }
  218. }
  219. std::size_t sync_write(int d, state_type state, const buf* bufs,
  220. std::size_t count, bool all_empty, boost::system::error_code& ec)
  221. {
  222. if (d == -1)
  223. {
  224. ec = boost::asio::error::bad_descriptor;
  225. return 0;
  226. }
  227. // A request to write 0 bytes on a stream is a no-op.
  228. if (all_empty)
  229. {
  230. ec = boost::system::error_code();
  231. return 0;
  232. }
  233. // Write some data.
  234. for (;;)
  235. {
  236. // Try to complete the operation without blocking.
  237. errno = 0;
  238. signed_size_type bytes = error_wrapper(::writev(
  239. d, bufs, static_cast<int>(count)), ec);
  240. // Check if operation succeeded.
  241. if (bytes > 0)
  242. return bytes;
  243. // Operation failed.
  244. if ((state & user_set_non_blocking)
  245. || (ec != boost::asio::error::would_block
  246. && ec != boost::asio::error::try_again))
  247. return 0;
  248. // Wait for descriptor to become ready.
  249. if (descriptor_ops::poll_write(d, 0, ec) < 0)
  250. return 0;
  251. }
  252. }
  253. bool non_blocking_write(int d, const buf* bufs, std::size_t count,
  254. boost::system::error_code& ec, std::size_t& bytes_transferred)
  255. {
  256. for (;;)
  257. {
  258. // Write some data.
  259. errno = 0;
  260. signed_size_type bytes = error_wrapper(::writev(
  261. d, bufs, static_cast<int>(count)), ec);
  262. // Retry operation if interrupted by signal.
  263. if (ec == boost::asio::error::interrupted)
  264. continue;
  265. // Check if we need to run the operation again.
  266. if (ec == boost::asio::error::would_block
  267. || ec == boost::asio::error::try_again)
  268. return false;
  269. // Operation is complete.
  270. if (bytes >= 0)
  271. {
  272. ec = boost::system::error_code();
  273. bytes_transferred = bytes;
  274. }
  275. else
  276. bytes_transferred = 0;
  277. return true;
  278. }
  279. }
  280. int ioctl(int d, state_type& state, long cmd,
  281. ioctl_arg_type* arg, boost::system::error_code& ec)
  282. {
  283. if (d == -1)
  284. {
  285. ec = boost::asio::error::bad_descriptor;
  286. return -1;
  287. }
  288. errno = 0;
  289. int result = error_wrapper(::ioctl(d, cmd, arg), ec);
  290. if (result >= 0)
  291. {
  292. ec = boost::system::error_code();
  293. // When updating the non-blocking mode we always perform the ioctl syscall,
  294. // even if the flags would otherwise indicate that the descriptor is
  295. // already in the correct state. This ensures that the underlying
  296. // descriptor is put into the state that has been requested by the user. If
  297. // the ioctl syscall was successful then we need to update the flags to
  298. // match.
  299. if (cmd == static_cast<long>(FIONBIO))
  300. {
  301. if (*arg)
  302. {
  303. state |= user_set_non_blocking;
  304. }
  305. else
  306. {
  307. // Clearing the non-blocking mode always overrides any internally-set
  308. // non-blocking flag. Any subsequent asynchronous operations will need
  309. // to re-enable non-blocking I/O.
  310. state &= ~(user_set_non_blocking | internal_non_blocking);
  311. }
  312. }
  313. }
  314. return result;
  315. }
  316. int fcntl(int d, int cmd, boost::system::error_code& ec)
  317. {
  318. if (d == -1)
  319. {
  320. ec = boost::asio::error::bad_descriptor;
  321. return -1;
  322. }
  323. errno = 0;
  324. int result = error_wrapper(::fcntl(d, cmd), ec);
  325. if (result != -1)
  326. ec = boost::system::error_code();
  327. return result;
  328. }
  329. int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
  330. {
  331. if (d == -1)
  332. {
  333. ec = boost::asio::error::bad_descriptor;
  334. return -1;
  335. }
  336. errno = 0;
  337. int result = error_wrapper(::fcntl(d, cmd, arg), ec);
  338. if (result != -1)
  339. ec = boost::system::error_code();
  340. return result;
  341. }
  342. int poll_read(int d, state_type state, boost::system::error_code& ec)
  343. {
  344. if (d == -1)
  345. {
  346. ec = boost::asio::error::bad_descriptor;
  347. return -1;
  348. }
  349. pollfd fds;
  350. fds.fd = d;
  351. fds.events = POLLIN;
  352. fds.revents = 0;
  353. int timeout = (state & user_set_non_blocking) ? 0 : -1;
  354. errno = 0;
  355. int result = error_wrapper(::poll(&fds, 1, timeout), ec);
  356. if (result == 0)
  357. ec = (state & user_set_non_blocking)
  358. ? boost::asio::error::would_block : boost::system::error_code();
  359. else if (result > 0)
  360. ec = boost::system::error_code();
  361. return result;
  362. }
  363. int poll_write(int d, state_type state, boost::system::error_code& ec)
  364. {
  365. if (d == -1)
  366. {
  367. ec = boost::asio::error::bad_descriptor;
  368. return -1;
  369. }
  370. pollfd fds;
  371. fds.fd = d;
  372. fds.events = POLLOUT;
  373. fds.revents = 0;
  374. int timeout = (state & user_set_non_blocking) ? 0 : -1;
  375. errno = 0;
  376. int result = error_wrapper(::poll(&fds, 1, timeout), ec);
  377. if (result == 0)
  378. ec = (state & user_set_non_blocking)
  379. ? boost::asio::error::would_block : boost::system::error_code();
  380. else if (result > 0)
  381. ec = boost::system::error_code();
  382. return result;
  383. }
  384. int poll_error(int d, state_type state, boost::system::error_code& ec)
  385. {
  386. if (d == -1)
  387. {
  388. ec = boost::asio::error::bad_descriptor;
  389. return -1;
  390. }
  391. pollfd fds;
  392. fds.fd = d;
  393. fds.events = POLLPRI | POLLERR | POLLHUP;
  394. fds.revents = 0;
  395. int timeout = (state & user_set_non_blocking) ? 0 : -1;
  396. errno = 0;
  397. int result = error_wrapper(::poll(&fds, 1, timeout), ec);
  398. if (result == 0)
  399. ec = (state & user_set_non_blocking)
  400. ? boost::asio::error::would_block : boost::system::error_code();
  401. else if (result > 0)
  402. ec = boost::system::error_code();
  403. return result;
  404. }
  405. } // namespace descriptor_ops
  406. } // namespace detail
  407. } // namespace asio
  408. } // namespace boost
  409. #include <boost/asio/detail/pop_options.hpp>
  410. #endif // !defined(BOOST_ASIO_WINDOWS)
  411. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  412. // && !defined(__CYGWIN__)
  413. #endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP