Fix up native_non_blocking() example and change it to be a complete working example of wrapping Linux's sendfile system call.
diff --git a/asio/include/asio/basic_socket.hpp b/asio/include/asio/basic_socket.hpp index ae43e1b..71f01f1 100644 --- a/asio/include/asio/basic_socket.hpp +++ b/asio/include/asio/basic_socket.hpp
@@ -991,18 +991,19 @@ * This function is intended to allow the encapsulation of arbitrary * non-blocking system calls as asynchronous operations, in a way that is * transparent to the user of the socket object. The following example - * illustrates how a @c sendfile system call might be encapsulated: + * illustrates how Linux's @c sendfile system call might be encapsulated: * @code template <typename Handler> * struct sendfile_op * { * tcp::socket& sock_; * int fd_; * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; * * // Function call operator meeting WriteHandler requirements. * // Used as the handler for the async_write_some operation. - * void operator()(asio::error_code ec, - * std::size_t bytes_transferred) + * void operator()(asio::error_code ec, std::size_t) * { * // Put the underlying socket into non-blocking mode. * if (!ec) @@ -1015,10 +1016,10 @@ * { * // Try the system call. * errno = 0; - * int n = ::sendfile(sock_.native_handle(), fd_, ...); - * ec = asio::error_code( - * n < 0 ? errno : 0, - * asio::error::system_category()); + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; * * // Retry operation immediately if interrupted by signal. * if (ec == asio::error::interrupted) @@ -1033,21 +1034,26 @@ * return; * } * - * // The operation is done. Exit loop so we can call the handler. - * bytes_transferred = ec ? 0 : n; - * break; + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. * } * } * * // Pass result back to user's handler. - * handler_(ec, bytes_transferred); + * handler_(ec, total_bytes_transferred_); * } * }; * * template <typename Handler> * void async_sendfile(tcp::socket& sock, int fd, Handler h) * { - * sendfile_op op = { sock, fd, h }; + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; * sock.async_write_some(asio::null_buffers(), op); * } @endcode */ @@ -1075,18 +1081,19 @@ * This function is intended to allow the encapsulation of arbitrary * non-blocking system calls as asynchronous operations, in a way that is * transparent to the user of the socket object. The following example - * illustrates how a @c sendfile system call might be encapsulated: + * illustrates how Linux's @c sendfile system call might be encapsulated: * @code template <typename Handler> * struct sendfile_op * { * tcp::socket& sock_; * int fd_; * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; * * // Function call operator meeting WriteHandler requirements. * // Used as the handler for the async_write_some operation. - * void operator()(asio::error_code ec, - * std::size_t bytes_transferred) + * void operator()(asio::error_code ec, std::size_t) * { * // Put the underlying socket into non-blocking mode. * if (!ec) @@ -1099,10 +1106,10 @@ * { * // Try the system call. * errno = 0; - * int n = ::sendfile(sock_.native_handle(), fd_, ...); - * ec = asio::error_code( - * n < 0 ? errno : 0, - * asio::error::system_category()); + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; * * // Retry operation immediately if interrupted by signal. * if (ec == asio::error::interrupted) @@ -1117,21 +1124,26 @@ * return; * } * - * // The operation is done. Exit loop so we can call the handler. - * bytes_transferred = ec ? 0 : n; - * break; + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. * } * } * * // Pass result back to user's handler. - * handler_(ec, bytes_transferred); + * handler_(ec, total_bytes_transferred_); * } * }; * * template <typename Handler> * void async_sendfile(tcp::socket& sock, int fd, Handler h) * { - * sendfile_op op = { sock, fd, h }; + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; * sock.async_write_some(asio::null_buffers(), op); * } @endcode */ @@ -1161,18 +1173,19 @@ * This function is intended to allow the encapsulation of arbitrary * non-blocking system calls as asynchronous operations, in a way that is * transparent to the user of the socket object. The following example - * illustrates how a @c sendfile system call might be encapsulated: + * illustrates how Linux's @c sendfile system call might be encapsulated: * @code template <typename Handler> * struct sendfile_op * { * tcp::socket& sock_; * int fd_; * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; * * // Function call operator meeting WriteHandler requirements. * // Used as the handler for the async_write_some operation. - * void operator()(asio::error_code ec, - * std::size_t bytes_transferred) + * void operator()(asio::error_code ec, std::size_t) * { * // Put the underlying socket into non-blocking mode. * if (!ec) @@ -1185,10 +1198,10 @@ * { * // Try the system call. * errno = 0; - * int n = ::sendfile(sock_.native_handle(), fd_, ...); - * ec = asio::error_code( - * n < 0 ? errno : 0, - * asio::error::system_category()); + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = asio::error_code(n < 0 ? errno : 0, + * asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; * * // Retry operation immediately if interrupted by signal. * if (ec == asio::error::interrupted) @@ -1203,21 +1216,26 @@ * return; * } * - * // The operation is done. Exit loop so we can call the handler. - * bytes_transferred = ec ? 0 : n; - * break; + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. * } * } * * // Pass result back to user's handler. - * handler_(ec, bytes_transferred); + * handler_(ec, total_bytes_transferred_); * } * }; * * template <typename Handler> * void async_sendfile(tcp::socket& sock, int fd, Handler h) * { - * sendfile_op op = { sock, fd, h }; + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; * sock.async_write_some(asio::null_buffers(), op); * } @endcode */
diff --git a/asio/src/doc/reference.qbk b/asio/src/doc/reference.qbk index 869e7c9..61d02cf 100644 --- a/asio/src/doc/reference.qbk +++ b/asio/src/doc/reference.qbk
@@ -16,6 +16,7 @@ [include requirements/AsyncReadStream.qbk] [include requirements/AsyncWriteStream.qbk] [include requirements/CompletionHandler.qbk] +[include requirements/ComposedConnectHandler.qbk] [include requirements/ConnectHandler.qbk] [include requirements/ConstBufferSequence.qbk] [include requirements/ConvertibleToConstBuffer.qbk] @@ -6171,7 +6172,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -6179,11 +6180,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -6196,10 +6198,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -6214,21 +6216,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -6280,7 +6287,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -6288,11 +6295,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -6305,10 +6313,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -6323,21 +6331,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -6382,7 +6395,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -6390,11 +6403,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -6407,10 +6421,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -6425,21 +6439,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -13087,7 +13106,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -13095,11 +13114,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -13112,10 +13132,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -13130,21 +13150,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -13196,7 +13221,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -13204,11 +13229,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -13221,10 +13247,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -13239,21 +13265,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -13298,7 +13329,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -13306,11 +13337,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -13323,10 +13355,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -13341,21 +13373,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -18293,7 +18330,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -18301,11 +18338,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -18318,10 +18356,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -18336,21 +18374,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -18402,7 +18445,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -18410,11 +18453,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -18427,10 +18471,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -18445,21 +18489,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -18504,7 +18553,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -18512,11 +18561,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -18529,10 +18579,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -18547,21 +18597,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -24512,7 +24567,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -24520,11 +24575,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -24537,10 +24593,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -24555,21 +24611,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -24618,7 +24679,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -24626,11 +24687,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -24643,10 +24705,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -24661,21 +24723,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -24717,7 +24784,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -24725,11 +24792,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -24742,10 +24810,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -24760,21 +24828,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -32599,7 +32672,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -32607,11 +32680,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -32624,10 +32698,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -32642,21 +32716,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -32708,7 +32787,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -32716,11 +32795,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -32733,10 +32813,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -32751,21 +32831,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -32810,7 +32895,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -32818,11 +32903,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -32835,10 +32921,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -32853,21 +32939,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -37396,7 +37487,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -37404,11 +37495,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -37421,10 +37513,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -37439,21 +37531,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -37505,7 +37602,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -37513,11 +37610,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -37530,10 +37628,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -37548,21 +37646,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -37607,7 +37710,7 @@ [heading Example] -This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how a `sendfile` system call might be encapsulated: +This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated: template <typename Handler> struct sendfile_op @@ -37615,11 +37718,12 @@ tcp::socket& sock_; int fd_; Handler handler_; + off_t offset_; + std::size_t total_bytes_transferred_; // Function call operator meeting WriteHandler requirements. // Used as the handler for the async_write_some operation. - void operator()(asio::error_code ec, - std::size_t bytes_transferred) + void operator()(asio::error_code ec, std::size_t) { // Put the underlying socket into non-blocking mode. if (!ec) @@ -37632,10 +37736,10 @@ { // Try the system call. errno = 0; - int n = ::sendfile(sock_.native_handle(), fd_, ...); - ec = asio::error_code( - n < 0 ? errno : 0, - asio::error::system_category()); + int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + ec = asio::error_code(n < 0 ? errno : 0, + asio::error::get_system_category()); + total_bytes_transferred_ += ec ? 0 : n; // Retry operation immediately if interrupted by signal. if (ec == asio::error::interrupted) @@ -37650,21 +37754,26 @@ return; } - // The operation is done. Exit loop so we can call the handler. - bytes_transferred = ec ? 0 : n; - break; + if (ec || n == 0) + { + // An error occurred, or we have reached the end of the file. + // Either way we must exit the loop so we can call the handler. + break; + } + + // Loop around to try calling sendfile again. } } // Pass result back to user's handler. - handler_(ec, bytes_transferred); + handler_(ec, total_bytes_transferred_); } }; template <typename Handler> void async_sendfile(tcp::socket& sock, int fd, Handler h) { - sendfile_op op = { sock, fd, h }; + sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; sock.async_write_some(asio::null_buffers(), op); } @@ -48889,9 +48998,9 @@ [heading Requirements] -[*Header: ][^asio/error.hpp] +[*Header: ][^asio/ssl/error.hpp] -[*Convenience header: ][^asio.hpp] +[*Convenience header: ][^asio/ssl.hpp] [endsect] @@ -49154,9 +49263,9 @@ [heading Requirements] -[*Header: ][^asio/error.hpp] +[*Header: ][^asio/ssl/error.hpp] -[*Convenience header: ][^asio.hpp] +[*Convenience header: ][^asio/ssl.hpp] [endsect] @@ -49172,9 +49281,9 @@ [heading Requirements] -[*Header: ][^asio/error.hpp] +[*Header: ][^asio/ssl/error.hpp] -[*Convenience header: ][^asio.hpp] +[*Convenience header: ][^asio/ssl.hpp] [endsect]