]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / windows / transmit_file.cpp
CommitLineData
7c673cae
FG
1//
2// transmit_file.cpp
3// ~~~~~~~~~~~~~~~~~
4//
92f5a8d4 5// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7c673cae
FG
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
11#include <ctime>
12#include <iostream>
13#include <string>
14#include <boost/bind.hpp>
15#include <boost/shared_ptr.hpp>
16#include <boost/enable_shared_from_this.hpp>
17#include <boost/asio.hpp>
18
19#if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
20
21using boost::asio::ip::tcp;
22using boost::asio::windows::overlapped_ptr;
23using boost::asio::windows::random_access_handle;
24
92f5a8d4
TL
25typedef boost::asio::basic_stream_socket<tcp,
26 boost::asio::io_context::executor_type> tcp_socket;
27
28typedef boost::asio::basic_socket_acceptor<tcp,
29 boost::asio::io_context::executor_type> tcp_acceptor;
30
7c673cae
FG
31// A wrapper for the TransmitFile overlapped I/O operation.
32template <typename Handler>
92f5a8d4 33void transmit_file(tcp_socket& socket,
7c673cae
FG
34 random_access_handle& file, Handler handler)
35{
36 // Construct an OVERLAPPED-derived object to contain the handler.
b32b8144 37 overlapped_ptr overlapped(socket.get_executor().context(), handler);
7c673cae
FG
38
39 // Initiate the TransmitFile operation.
40 BOOL ok = ::TransmitFile(socket.native_handle(),
41 file.native_handle(), 0, 0, overlapped.get(), 0, 0);
42 DWORD last_error = ::GetLastError();
43
44 // Check if the operation completed immediately.
45 if (!ok && last_error != ERROR_IO_PENDING)
46 {
47 // The operation completed immediately, so a completion notification needs
48 // to be posted. When complete() is called, ownership of the OVERLAPPED-
b32b8144 49 // derived object passes to the io_context.
7c673cae
FG
50 boost::system::error_code ec(last_error,
51 boost::asio::error::get_system_category());
52 overlapped.complete(ec, 0);
53 }
54 else
55 {
56 // The operation was successfully initiated, so ownership of the
b32b8144 57 // OVERLAPPED-derived object has passed to the io_context.
7c673cae
FG
58 overlapped.release();
59 }
60}
61
62class connection
63 : public boost::enable_shared_from_this<connection>
64{
65public:
66 typedef boost::shared_ptr<connection> pointer;
67
b32b8144 68 static pointer create(boost::asio::io_context& io_context,
7c673cae
FG
69 const std::string& filename)
70 {
b32b8144 71 return pointer(new connection(io_context, filename));
7c673cae
FG
72 }
73
92f5a8d4 74 tcp_socket& socket()
7c673cae
FG
75 {
76 return socket_;
77 }
78
79 void start()
80 {
81 boost::system::error_code ec;
82 file_.assign(::CreateFile(filename_.c_str(), GENERIC_READ, 0, 0,
83 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0), ec);
84 if (file_.is_open())
85 {
86 transmit_file(socket_, file_,
87 boost::bind(&connection::handle_write, shared_from_this(),
88 boost::asio::placeholders::error,
89 boost::asio::placeholders::bytes_transferred));
90 }
91 }
92
93private:
b32b8144
FG
94 connection(boost::asio::io_context& io_context, const std::string& filename)
95 : socket_(io_context),
7c673cae 96 filename_(filename),
b32b8144 97 file_(io_context)
7c673cae
FG
98 {
99 }
100
101 void handle_write(const boost::system::error_code& /*error*/,
102 size_t /*bytes_transferred*/)
103 {
104 boost::system::error_code ignored_ec;
92f5a8d4 105 socket_.shutdown(tcp_socket::shutdown_both, ignored_ec);
7c673cae
FG
106 }
107
92f5a8d4 108 tcp_socket socket_;
7c673cae
FG
109 std::string filename_;
110 random_access_handle file_;
111};
112
113class server
114{
115public:
b32b8144 116 server(boost::asio::io_context& io_context,
7c673cae 117 unsigned short port, const std::string& filename)
b32b8144 118 : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
7c673cae
FG
119 filename_(filename)
120 {
121 start_accept();
122 }
123
124private:
125 void start_accept()
126 {
127 connection::pointer new_connection =
b32b8144 128 connection::create(acceptor_.get_executor().context(), filename_);
7c673cae
FG
129
130 acceptor_.async_accept(new_connection->socket(),
131 boost::bind(&server::handle_accept, this, new_connection,
132 boost::asio::placeholders::error));
133 }
134
135 void handle_accept(connection::pointer new_connection,
136 const boost::system::error_code& error)
137 {
138 if (!error)
139 {
140 new_connection->start();
141 }
142
143 start_accept();
144 }
145
92f5a8d4 146 tcp_acceptor acceptor_;
7c673cae
FG
147 std::string filename_;
148};
149
150int main(int argc, char* argv[])
151{
152 try
153 {
154 if (argc != 3)
155 {
156 std::cerr << "Usage: transmit_file <port> <filename>\n";
157 return 1;
158 }
159
b32b8144 160 boost::asio::io_context io_context;
7c673cae
FG
161
162 using namespace std; // For atoi.
b32b8144 163 server s(io_context, atoi(argv[1]), argv[2]);
7c673cae 164
b32b8144 165 io_context.run();
7c673cae
FG
166 }
167 catch (std::exception& e)
168 {
169 std::cerr << e.what() << std::endl;
170 }
171
172 return 0;
173}
174
175#else // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
176# error Overlapped I/O not available on this platform
177#endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)