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