2 // detail/impl/descriptor_ops.ipp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
12 #define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #include <boost/asio/detail/descriptor_ops.hpp>
21 #include <boost/asio/error.hpp>
23 #if !defined(BOOST_ASIO_WINDOWS) \
24 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
25 && !defined(__CYGWIN__)
27 #include <boost/asio/detail/push_options.hpp>
32 namespace descriptor_ops {
34 int open(const char* path, int flags, boost::system::error_code& ec)
37 int result = error_wrapper(::open(path, flags), ec);
39 ec = boost::system::error_code();
43 int close(int d, state_type& state, boost::system::error_code& ec)
49 result = error_wrapper(::close(d), ec);
52 && (ec == boost::asio::error::would_block
53 || ec == boost::asio::error::try_again))
55 // According to UNIX Network Programming Vol. 1, it is possible for
56 // close() to fail with EWOULDBLOCK under certain circumstances. What
57 // isn't clear is the state of the descriptor after this error. The one
58 // current OS where this behaviour is seen, Windows, says that the socket
59 // remains open. Therefore we'll put the descriptor back into blocking
60 // mode and have another attempt at closing it.
61 #if defined(__SYMBIAN32__)
62 int flags = ::fcntl(d, F_GETFL, 0);
64 ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
65 #else // defined(__SYMBIAN32__)
66 ioctl_arg_type arg = 0;
67 ::ioctl(d, FIONBIO, &arg);
68 #endif // defined(__SYMBIAN32__)
69 state &= ~non_blocking;
72 result = error_wrapper(::close(d), ec);
77 ec = boost::system::error_code();
81 bool set_user_non_blocking(int d, state_type& state,
82 bool value, boost::system::error_code& ec)
86 ec = boost::asio::error::bad_descriptor;
91 #if defined(__SYMBIAN32__)
92 int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
96 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
97 result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
99 #else // defined(__SYMBIAN32__)
100 ioctl_arg_type arg = (value ? 1 : 0);
101 int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
102 #endif // defined(__SYMBIAN32__)
106 ec = boost::system::error_code();
108 state |= user_set_non_blocking;
111 // Clearing the user-set non-blocking mode always overrides any
112 // internally-set non-blocking flag. Any subsequent asynchronous
113 // operations will need to re-enable non-blocking I/O.
114 state &= ~(user_set_non_blocking | internal_non_blocking);
122 bool set_internal_non_blocking(int d, state_type& state,
123 bool value, boost::system::error_code& ec)
127 ec = boost::asio::error::bad_descriptor;
131 if (!value && (state & user_set_non_blocking))
133 // It does not make sense to clear the internal non-blocking flag if the
134 // user still wants non-blocking behaviour. Return an error and let the
135 // caller figure out whether to update the user-set non-blocking flag.
136 ec = boost::asio::error::invalid_argument;
141 #if defined(__SYMBIAN32__)
142 int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
146 int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
147 result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
149 #else // defined(__SYMBIAN32__)
150 ioctl_arg_type arg = (value ? 1 : 0);
151 int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
152 #endif // defined(__SYMBIAN32__)
156 ec = boost::system::error_code();
158 state |= internal_non_blocking;
160 state &= ~internal_non_blocking;
167 std::size_t sync_read(int d, state_type state, buf* bufs,
168 std::size_t count, bool all_empty, boost::system::error_code& ec)
172 ec = boost::asio::error::bad_descriptor;
176 // A request to read 0 bytes on a stream is a no-op.
179 ec = boost::system::error_code();
186 // Try to complete the operation without blocking.
188 signed_size_type bytes = error_wrapper(::readv(
189 d, bufs, static_cast<int>(count)), ec);
191 // Check if operation succeeded.
198 ec = boost::asio::error::eof;
203 if ((state & user_set_non_blocking)
204 || (ec != boost::asio::error::would_block
205 && ec != boost::asio::error::try_again))
208 // Wait for descriptor to become ready.
209 if (descriptor_ops::poll_read(d, 0, ec) < 0)
214 bool non_blocking_read(int d, buf* bufs, std::size_t count,
215 boost::system::error_code& ec, std::size_t& bytes_transferred)
221 signed_size_type bytes = error_wrapper(::readv(
222 d, bufs, static_cast<int>(count)), ec);
224 // Check for end of stream.
227 ec = boost::asio::error::eof;
231 // Retry operation if interrupted by signal.
232 if (ec == boost::asio::error::interrupted)
235 // Check if we need to run the operation again.
236 if (ec == boost::asio::error::would_block
237 || ec == boost::asio::error::try_again)
240 // Operation is complete.
243 ec = boost::system::error_code();
244 bytes_transferred = bytes;
247 bytes_transferred = 0;
253 std::size_t sync_write(int d, state_type state, const buf* bufs,
254 std::size_t count, bool all_empty, boost::system::error_code& ec)
258 ec = boost::asio::error::bad_descriptor;
262 // A request to write 0 bytes on a stream is a no-op.
265 ec = boost::system::error_code();
272 // Try to complete the operation without blocking.
274 signed_size_type bytes = error_wrapper(::writev(
275 d, bufs, static_cast<int>(count)), ec);
277 // Check if operation succeeded.
282 if ((state & user_set_non_blocking)
283 || (ec != boost::asio::error::would_block
284 && ec != boost::asio::error::try_again))
287 // Wait for descriptor to become ready.
288 if (descriptor_ops::poll_write(d, 0, ec) < 0)
293 bool non_blocking_write(int d, const buf* bufs, std::size_t count,
294 boost::system::error_code& ec, std::size_t& bytes_transferred)
300 signed_size_type bytes = error_wrapper(::writev(
301 d, bufs, static_cast<int>(count)), ec);
303 // Retry operation if interrupted by signal.
304 if (ec == boost::asio::error::interrupted)
307 // Check if we need to run the operation again.
308 if (ec == boost::asio::error::would_block
309 || ec == boost::asio::error::try_again)
312 // Operation is complete.
315 ec = boost::system::error_code();
316 bytes_transferred = bytes;
319 bytes_transferred = 0;
325 int ioctl(int d, state_type& state, long cmd,
326 ioctl_arg_type* arg, boost::system::error_code& ec)
330 ec = boost::asio::error::bad_descriptor;
335 int result = error_wrapper(::ioctl(d, cmd, arg), ec);
339 ec = boost::system::error_code();
341 // When updating the non-blocking mode we always perform the ioctl syscall,
342 // even if the flags would otherwise indicate that the descriptor is
343 // already in the correct state. This ensures that the underlying
344 // descriptor is put into the state that has been requested by the user. If
345 // the ioctl syscall was successful then we need to update the flags to
347 if (cmd == static_cast<long>(FIONBIO))
351 state |= user_set_non_blocking;
355 // Clearing the non-blocking mode always overrides any internally-set
356 // non-blocking flag. Any subsequent asynchronous operations will need
357 // to re-enable non-blocking I/O.
358 state &= ~(user_set_non_blocking | internal_non_blocking);
366 int fcntl(int d, int cmd, boost::system::error_code& ec)
370 ec = boost::asio::error::bad_descriptor;
375 int result = error_wrapper(::fcntl(d, cmd), ec);
377 ec = boost::system::error_code();
381 int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
385 ec = boost::asio::error::bad_descriptor;
390 int result = error_wrapper(::fcntl(d, cmd, arg), ec);
392 ec = boost::system::error_code();
396 int poll_read(int d, state_type state, boost::system::error_code& ec)
400 ec = boost::asio::error::bad_descriptor;
408 int timeout = (state & user_set_non_blocking) ? 0 : -1;
410 int result = error_wrapper(::poll(&fds, 1, timeout), ec);
412 ec = (state & user_set_non_blocking)
413 ? boost::asio::error::would_block : boost::system::error_code();
415 ec = boost::system::error_code();
419 int poll_write(int d, state_type state, boost::system::error_code& ec)
423 ec = boost::asio::error::bad_descriptor;
429 fds.events = POLLOUT;
431 int timeout = (state & user_set_non_blocking) ? 0 : -1;
433 int result = error_wrapper(::poll(&fds, 1, timeout), ec);
435 ec = (state & user_set_non_blocking)
436 ? boost::asio::error::would_block : boost::system::error_code();
438 ec = boost::system::error_code();
442 int poll_error(int d, state_type state, boost::system::error_code& ec)
446 ec = boost::asio::error::bad_descriptor;
452 fds.events = POLLPRI | POLLERR | POLLHUP;
454 int timeout = (state & user_set_non_blocking) ? 0 : -1;
456 int result = error_wrapper(::poll(&fds, 1, timeout), ec);
458 ec = (state & user_set_non_blocking)
459 ? boost::asio::error::would_block : boost::system::error_code();
461 ec = boost::system::error_code();
465 } // namespace descriptor_ops
466 } // namespace detail
470 #include <boost/asio/detail/pop_options.hpp>
472 #endif // !defined(BOOST_ASIO_WINDOWS)
473 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
474 // && !defined(__CYGWIN__)
476 #endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP