]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/example/cpp03/windows/transmit_file.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / windows / transmit_file.cpp
CommitLineData
7c673cae
FG
1//
2// transmit_file.cpp
3// ~~~~~~~~~~~~~~~~~
4//
11fdf7f2 5// Copyright (c) 2003-2018 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
25// A wrapper for the TransmitFile overlapped I/O operation.
26template <typename Handler>
27void transmit_file(tcp::socket& socket,
28 random_access_handle& file, Handler handler)
29{
30 // Construct an OVERLAPPED-derived object to contain the handler.
b32b8144 31 overlapped_ptr overlapped(socket.get_executor().context(), handler);
7c673cae
FG
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-
b32b8144 43 // derived object passes to the io_context.
7c673cae
FG
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
b32b8144 51 // OVERLAPPED-derived object has passed to the io_context.
7c673cae
FG
52 overlapped.release();
53 }
54}
55
56class connection
57 : public boost::enable_shared_from_this<connection>
58{
59public:
60 typedef boost::shared_ptr<connection> pointer;
61
b32b8144 62 static pointer create(boost::asio::io_context& io_context,
7c673cae
FG
63 const std::string& filename)
64 {
b32b8144 65 return pointer(new connection(io_context, filename));
7c673cae
FG
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
87private:
b32b8144
FG
88 connection(boost::asio::io_context& io_context, const std::string& filename)
89 : socket_(io_context),
7c673cae 90 filename_(filename),
b32b8144 91 file_(io_context)
7c673cae
FG
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
107class server
108{
109public:
b32b8144 110 server(boost::asio::io_context& io_context,
7c673cae 111 unsigned short port, const std::string& filename)
b32b8144 112 : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
7c673cae
FG
113 filename_(filename)
114 {
115 start_accept();
116 }
117
118private:
119 void start_accept()
120 {
121 connection::pointer new_connection =
b32b8144 122 connection::create(acceptor_.get_executor().context(), filename_);
7c673cae
FG
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
144int 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
b32b8144 154 boost::asio::io_context io_context;
7c673cae
FG
155
156 using namespace std; // For atoi.
b32b8144 157 server s(io_context, atoi(argv[1]), argv[2]);
7c673cae 158
b32b8144 159 io_context.run();
7c673cae
FG
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)