| src/examples/cpp03/nonblocking/third_party_lib.cpp | src/examples/cpp11/nonblocking/third_party_lib.cpp | 
|---|
| ⋮ | ⋮ | 
| 1 | // | 1 | // | 
| 2 | //·third_party_lib.cpp | 2 | //·third_party_lib.cpp | 
| 3 | //·~~~~~~~~~~~~~~~~~~~ | 3 | //·~~~~~~~~~~~~~~~~~~~ | 
| 4 | // | 4 | // | 
| 5 | //·Copyright·(c)·2003-2020·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5 | //·Copyright·(c)·2003-2020·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 
| 6 | // | 6 | // | 
| 7 | //·Distributed·under·the·Boost·Software·License,·Version·1.0.·(See·accompanying | 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) | 8 | //·file·LICENSE_1_0.txt·or·copy·at·http://www.boost.org/LICENSE_1_0.txt) | 
| 9 | // | 9 | // | 
| 10 |  | 10 |  | 
| 11 | #include·<asio.hpp> | 11 | #include·<asio.hpp> | 
| 12 | #include·<boost/array.hpp> | 12 | #include·<array> | 
| 13 | #include·<boost/bind/bind.hpp> |  | 
| 14 | #include·<boost/shared_ptr.hpp> |  | 
| 15 | #include·<boost/enable_shared_from_this.hpp> |  | 
| 16 | #include·<iostream> | 13 | #include·<iostream> | 
|  | 14 | #include·<memory> | 
| 17 |  | 15 |  | 
| 18 | using·asio::ip::tcp; | 16 | using·asio::ip::tcp; | 
| 19 |  | 17 |  | 
| 20 | namespace·third_party_lib·{ | 18 | namespace·third_party_lib·{ | 
| 21 |  | 19 |  | 
| 22 | //·Simulation·of·a·third·party·library·that·wants·to·perform·read·and·write | 20 | //·Simulation·of·a·third·party·library·that·wants·to·perform·read·and·write | 
| 23 | //·operations·directly·on·a·socket.·It·needs·to·be·polled·to·determine·whether | 21 | //·operations·directly·on·a·socket.·It·needs·to·be·polled·to·determine·whether | 
| 24 | //·it·requires·a·read·or·write·operation,·and·notified·when·the·socket·is·ready | 22 | //·it·requires·a·read·or·write·operation,·and·notified·when·the·socket·is·ready | 
| 25 | //·for·reading·or·writing. | 23 | //·for·reading·or·writing. | 
| 26 | class·session | 24 | class·session | 
| 27 | { | 25 | { | 
| 28 | public: | 26 | public: | 
| 29 | ··session(tcp::socket&·socket) | 27 | ··session(tcp::socket&·socket) | 
| 30 | ····:·socket_(socket), | 28 | ····:·socket_(socket) | 
| 31 | ······state_(reading) |  | 
| 32 | ··{ | 29 | ··{ | 
| 33 | ··} | 30 | ··} | 
| 34 |  | 31 |  | 
| 35 | ··//·Returns·true·if·the·third·party·library·wants·to·be·notified·when·the | 32 | ··//·Returns·true·if·the·third·party·library·wants·to·be·notified·when·the | 
| 36 | ··//·socket·is·ready·for·reading. | 33 | ··//·socket·is·ready·for·reading. | 
| 37 | ··bool·want_read()·const | 34 | ··bool·want_read()·const | 
| 38 | ··{ | 35 | ··{ | 
| 39 | ····return·state_·==·reading; | 36 | ····return·state_·==·reading; | 
| 40 | ··} | 37 | ··} | 
| 41 |  | 38 |  | 
| 42 | ··//·Notify·that·third·party·library·that·it·should·perform·its·read·operation. | 39 | ··//·Notify·that·third·party·library·that·it·should·perform·its·read·operation. | 
| 43 | ··void·do_read(asio::error_code&·ec) | 40 | ··void·do_read(std::error_code&·ec) | 
| 44 | ··{ | 41 | ··{ | 
| 45 | ····if·(std::size_t·len·=·socket_.read_some(asio::buffer(data_),·ec)) | 42 | ····if·(std::size_t·len·=·socket_.read_some(asio::buffer(data_),·ec)) | 
| 46 | ····{ | 43 | ····{ | 
| 47 | ······write_buffer_·=·asio::buffer(data_,·len); | 44 | ······write_buffer_·=·asio::buffer(data_,·len); | 
| 48 | ······state_·=·writing; | 45 | ······state_·=·writing; | 
| 49 | ····} | 46 | ····} | 
| 50 | ··} | 47 | ··} | 
| 51 |  | 48 |  | 
| 52 | ··//·Returns·true·if·the·third·party·library·wants·to·be·notified·when·the | 49 | ··//·Returns·true·if·the·third·party·library·wants·to·be·notified·when·the | 
| 53 | ··//·socket·is·ready·for·writing. | 50 | ··//·socket·is·ready·for·writing. | 
| 54 | ··bool·want_write()·const | 51 | ··bool·want_write()·const | 
| 55 | ··{ | 52 | ··{ | 
| 56 | ····return·state_·==·writing; | 53 | ····return·state_·==·writing; | 
| 57 | ··} | 54 | ··} | 
| 58 |  | 55 |  | 
| 59 | ··//·Notify·that·third·party·library·that·it·should·perform·its·write·operation. | 56 | ··//·Notify·that·third·party·library·that·it·should·perform·its·write·operation. | 
| 60 | ··void·do_write(asio::error_code&·ec) | 57 | ··void·do_write(std::error_code&·ec) | 
| 61 | ··{ | 58 | ··{ | 
| 62 | ····if·(std::size_t·len·=·socket_.write_some( | 59 | ····if·(std::size_t·len·=·socket_.write_some( | 
| 63 | ··········asio::buffer(write_buffer_),·ec)) | 60 | ··········asio::buffer(write_buffer_),·ec)) | 
| 64 | ····{ | 61 | ····{ | 
| 65 | ······write_buffer_·=·write_buffer_·+·len; | 62 | ······write_buffer_·=·write_buffer_·+·len; | 
| 66 | ······state_·=·asio::buffer_size(write_buffer_)·>·0·?·writing·:·reading; | 63 | ······state_·=·asio::buffer_size(write_buffer_)·>·0·?·writing·:·reading; | 
| 67 | ····} | 64 | ····} | 
| 68 | ··} | 65 | ··} | 
| 69 |  | 66 |  | 
| 70 | private: | 67 | private: | 
| 71 | ··tcp::socket&·socket_; | 68 | ··tcp::socket&·socket_; | 
| 72 | ··enum·{·reading,·writing·}·state_; | 69 | ··enum·{·reading,·writing·}·state_·=·reading; | 
| 73 | ··boost::array<char,·128>·data_; | 70 | ··std::array<char,·128>·data_; | 
| 74 | ··asio::const_buffer·write_buffer_; | 71 | ··asio::const_buffer·write_buffer_; | 
| 75 | }; | 72 | }; | 
| 76 |  | 73 |  | 
| 77 | }·//·namespace·third_party_lib | 74 | }·//·namespace·third_party_lib | 
| 78 |  | 75 |  | 
| 79 | //·The·glue·between·asio's·sockets·and·the·third·party·library. | 76 | //·The·glue·between·asio's·sockets·and·the·third·party·library. | 
| 80 | class·connection | 77 | class·connection | 
| 81 | ··:·public·boost::enable_shared_from_this<connection> | 78 | ··:·public·std::enable_shared_from_this<connection> | 
| 82 | { | 79 | { | 
| 83 | public: | 80 | public: | 
| 84 | ··typedef·boost::shared_ptr<connection>·pointer; | 81 | ··connection(tcp::socket·socket) | 
| 85 |  | 82 | ····:·socket_(std::move(socket)) | 
| 86 | ··static·pointer·create(const·asio::any_io_executor&·ex) |  | 
| 87 | ··{ |  | 
| 88 | ····return·pointer(new·connection(ex)); |  | 
| 89 | ··} |  | 
| 90 |  |  | 
| 91 | ··tcp::socket&·socket() |  | 
| 92 | ··{ | 83 | ··{ | 
| 93 | ····return·socket_; |  | 
| 94 | ··} | 84 | ··} | 
| 95 |  | 85 |  | 
| 96 | ··void·start() | 86 | ··void·start() | 
| 97 | ··{ | 87 | ··{ | 
| 98 | ····//·Put·the·socket·into·non-blocking·mode. | 88 | ····//·Put·the·socket·into·non-blocking·mode. | 
| 99 | ····socket_.non_blocking(true); | 89 | ····socket_.non_blocking(true); | 
| 100 |  | 90 |  | 
| 101 | ····start_operations(); | 91 | ····do_operations(); | 
| 102 | ··} | 92 | ··} | 
| 103 |  | 93 |  | 
| 104 | private: | 94 | private: | 
| 105 | ··connection(const·asio::any_io_executor&·ex) | 95 | ··void·do_operations() | 
| 106 | ····:·socket_(ex), |  | 
| 107 | ······session_impl_(socket_), |  | 
| 108 | ······read_in_progress_(false), |  | 
| 109 | ······write_in_progress_(false) |  | 
| 110 | ··{ | 96 | ··{ | 
| 111 | ··} | 97 | ····auto·self(shared_from_this()); | 
| 112 |  | 98 |  | 
| 113 | ··void·start_operations() |  | 
| 114 | ··{ |  | 
| 115 | ····//·Start·a·read·operation·if·the·third·party·library·wants·one. | 99 | ····//·Start·a·read·operation·if·the·third·party·library·wants·one. | 
| 116 | ····if·(session_impl_.want_read()·&&·!read_in_progress_) | 100 | ····if·(session_impl_.want_read()·&&·!read_in_progress_) | 
| 117 | ····{ | 101 | ····{ | 
| 118 | ······read_in_progress_·=·true; | 102 | ······read_in_progress_·=·true; | 
| 119 | ······socket_.async_wait(tcp::socket::wait_read, | 103 | ······socket_.async_wait(tcp::socket::wait_read, | 
| 120 | ··········boost::bind(&connection::handle_read, | 104 | ··········[this,·self](std::error_code·ec) | 
| 121 | ············shared_from_this(), | 105 | ··········{ | 
| 122 | ············asio::placeholders::error)); | 106 | ············read_in_progress_·=·false; | 
|  | 107 |  | 
|  | 108 | ············//·Notify·third·party·library·that·it·can·perform·a·read. | 
|  | 109 | ············if·(!ec) | 
|  | 110 | ··············session_impl_.do_read(ec); | 
|  | 111 |  | 
|  | 112 | ············//·The·third·party·library·successfully·performed·a·read·on·the | 
|  | 113 | ············//·socket.·Start·new·read·or·write·operations·based·on·what·it·now | 
|  | 114 | ············//·wants. | 
|  | 115 | ············if·(!ec·||·ec·==·asio::error::would_block) | 
|  | 116 | ··············do_operations(); | 
|  | 117 |  | 
|  | 118 | ············//·Otherwise,·an·error·occurred.·Closing·the·socket·cancels·any | 
|  | 119 | ············//·outstanding·asynchronous·read·or·write·operations.·The | 
|  | 120 | ············//·connection·object·will·be·destroyed·automatically·once·those | 
|  | 121 | ············//·outstanding·operations·complete. | 
|  | 122 | ············else | 
|  | 123 | ··············socket_.close(); | 
|  | 124 | ··········}); | 
| 123 | ····} | 125 | ····} | 
| 124 |  | 126 |  | 
| 125 | ····//·Start·a·write·operation·if·the·third·party·library·wants·one. | 127 | ····//·Start·a·write·operation·if·the·third·party·library·wants·one. | 
| 126 | ····if·(session_impl_.want_write()·&&·!write_in_progress_) | 128 | ····if·(session_impl_.want_write()·&&·!write_in_progress_) | 
| 127 | ····{ | 129 | ····{ | 
| 128 | ······write_in_progress_·=·true; | 130 | ······write_in_progress_·=·true; | 
| 129 | ······socket_.async_wait(tcp::socket::wait_write, | 131 | ······socket_.async_wait(tcp::socket::wait_write, | 
| 130 | ··········boost::bind(&connection::handle_write, | 132 | ··········[this,·self](std::error_code·ec) | 
| 131 | ············shared_from_this(), | 133 | ··········{ | 
| 132 | ············asio::placeholders::error)); | 134 | ············write_in_progress_·=·false; | 
|  | 135 |  | 
|  | 136 | ············//·Notify·third·party·library·that·it·can·perform·a·write. | 
|  | 137 | ············if·(!ec) | 
|  | 138 | ··············session_impl_.do_write(ec); | 
|  | 139 |  | 
|  | 140 | ············//·The·third·party·library·successfully·performed·a·write·on·the | 
|  | 141 | ············//·socket.·Start·new·read·or·write·operations·based·on·what·it·now | 
|  | 142 | ············//·wants. | 
|  | 143 | ············if·(!ec·||·ec·==·asio::error::would_block) | 
|  | 144 | ··············do_operations(); | 
|  | 145 |  | 
|  | 146 | ············//·Otherwise,·an·error·occurred.·Closing·the·socket·cancels·any | 
|  | 147 | ············//·outstanding·asynchronous·read·or·write·operations.·The | 
|  | 148 | ············//·connection·object·will·be·destroyed·automatically·once·those | 
|  | 149 | ············//·outstanding·operations·complete. | 
|  | 150 | ············else | 
|  | 151 | ··············socket_.close(); | 
|  | 152 | ··········}); | 
| 133 | ····} | 153 | ····} | 
| 134 | ··} | 154 | ··} | 
| 135 |  | 155 |  | 
| 136 | ··void·handle_read(asio::error_code·ec) |  | 
| 137 | ··{ |  | 
| 138 | ····read_in_progress_·=·false; |  | 
| 139 |  |  | 
| 140 | ····//·Notify·third·party·library·that·it·can·perform·a·read. |  | 
| 141 | ····if·(!ec) |  | 
| 142 | ······session_impl_.do_read(ec); |  | 
| 143 |  |  | 
| 144 | ····//·The·third·party·library·successfully·performed·a·read·on·the·socket. |  | 
| 145 | ····//·Start·new·read·or·write·operations·based·on·what·it·now·wants. |  | 
| 146 | ····if·(!ec·||·ec·==·asio::error::would_block) |  | 
| 147 | ······start_operations(); |  | 
| 148 |  |  | 
| 149 | ····//·Otherwise,·an·error·occurred.·Closing·the·socket·cancels·any·outstanding |  | 
| 150 | ····//·asynchronous·read·or·write·operations.·The·connection·object·will·be |  | 
| 151 | ····//·destroyed·automatically·once·those·outstanding·operations·complete. |  | 
| 152 | ····else |  | 
| 153 | ······socket_.close(); |  | 
| 154 | ··} |  | 
| 155 |  |  | 
| 156 | ··void·handle_write(asio::error_code·ec) |  | 
| 157 | ··{ |  | 
| 158 | ····write_in_progress_·=·false; |  | 
| 159 |  |  | 
| 160 | ····//·Notify·third·party·library·that·it·can·perform·a·write. |  | 
| 161 | ····if·(!ec) |  | 
| 162 | ······session_impl_.do_write(ec); |  | 
| 163 |  |  | 
| 164 | ····//·The·third·party·library·successfully·performed·a·write·on·the·socket. |  | 
| 165 | ····//·Start·new·read·or·write·operations·based·on·what·it·now·wants. |  | 
| 166 | ····if·(!ec·||·ec·==·asio::error::would_block) |  | 
| 167 | ······start_operations(); |  | 
| 168 |  |  | 
| 169 | ····//·Otherwise,·an·error·occurred.·Closing·the·socket·cancels·any·outstanding |  | 
| 170 | ····//·asynchronous·read·or·write·operations.·The·connection·object·will·be |  | 
| 171 | ····//·destroyed·automatically·once·those·outstanding·operations·complete. |  | 
| 172 | ····else |  | 
| 173 | ······socket_.close(); |  | 
| 174 | ··} |  | 
| 175 |  |  | 
| 176 | private: | 156 | private: | 
| 177 | ··tcp::socket·socket_; | 157 | ··tcp::socket·socket_; | 
| 178 | ··third_party_lib::session·session_impl_; | 158 | ··third_party_lib::session·session_impl_{socket_}; | 
| 179 | ··bool·read_in_progress_; | 159 | ··bool·read_in_progress_·=·false; | 
| 180 | ··bool·write_in_progress_; | 160 | ··bool·write_in_progress_·=·false; | 
| 181 | }; | 161 | }; | 
| 182 |  | 162 |  | 
| 183 | class·server | 163 | class·server | 
| 184 | { | 164 | { | 
| 185 | public: | 165 | public: | 
| 186 | ··server(asio::io_context&·io_context,·unsigned·short·port) | 166 | ··server(asio::io_context&·io_context,·unsigned·short·port) | 
| 187 | ····:·acceptor_(io_context,·tcp::endpoint(tcp::v4(),·port)) | 167 | ····:·acceptor_(io_context,·{tcp::v4(),·port}) | 
| 188 | ··{ | 168 | ··{ | 
| 189 | ····start_accept(); | 169 | ····do_accept(); | 
| 190 | ··} | 170 | ··} | 
| 191 |  | 171 |  | 
| 192 | private: | 172 | private: | 
| 193 | ··void·start_accept() | 173 | ··void·do_accept() | 
| 194 | ··{ | 174 | ··{ | 
| 195 | ····connection::pointer·new_connection·= | 175 | ····acceptor_.async_accept( | 
| 196 | ······connection::create(acceptor_.get_executor()); | 176 | ········[this](std::error_code·ec,·tcp::socket·socket) | 
| 197 |  | 177 | ········{ | 
| 198 | ····acceptor_.async_accept(new_connection->socket(), | 178 | ··········if·(!ec) | 
| 199 | ········boost::bind(&server::handle_accept,·this,·new_connection, | 179 | ··········{ | 
| 200 | ··········asio::placeholders::error)); | 180 | ············std::make_shared<connection>(std::move(socket))->start(); | 
| 201 | ··} | 181 | ··········} | 
| 202 |  |  | 
| 203 | ··void·handle_accept(connection::pointer·new_connection, |  | 
| 204 | ······const·asio::error_code&·error) |  | 
| 205 | ··{ |  | 
| 206 | ····if·(!error) |  | 
| 207 | ····{ |  | 
| 208 | ······new_connection->start(); |  | 
| 209 | ····} |  | 
| 210 |  | 182 |  | 
| 211 | ····start_accept(); | 183 | ··········do_accept(); | 
|  | 184 | ········}); | 
| 212 | ··} | 185 | ··} | 
| 213 |  | 186 |  | 
| 214 | ··tcp::acceptor·acceptor_; | 187 | ··tcp::acceptor·acceptor_; | 
| 215 | }; | 188 | }; | 
| 216 |  | 189 |  | 
| 217 | int·main(int·argc,·char*·argv[]) | 190 | int·main(int·argc,·char*·argv[]) | 
| 218 | { | 191 | { | 
| 219 | ··try | 192 | ··try | 
| 220 | ··{ | 193 | ··{ | 
| 221 | ····if·(argc·!=·2) | 194 | ····if·(argc·!=·2) | 
| 222 | ····{ | 195 | ····{ | 
| 223 | ······std::cerr·<<·"Usage:·third_party_lib·<port>\n"; | 196 | ······std::cerr·<<·"Usage:·third_party_lib·<port>\n"; | 
| 224 | ······return·1; | 197 | ······return·1; | 
| 225 | ····} | 198 | ····} | 
| 226 |  | 199 |  | 
| 227 | ····asio::io_context·io_context; | 200 | ····asio::io_context·io_context; | 
| 228 |  | 201 |  | 
| 229 | ····using·namespace·std;·//·For·atoi. | 202 | ····server·s(io_context,·std::atoi(argv[1])); | 
| 230 | ····server·s(io_context,·atoi(argv[1])); |  | 
| 231 |  | 203 |  | 
| 232 | ····io_context.run(); | 204 | ····io_context.run(); | 
| 233 | ··} | 205 | ··} | 
| 234 | ··catch·(std::exception&·e) | 206 | ··catch·(std::exception&·e) | 
| 235 | ··{ | 207 | ··{ | 
| 236 | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 208 | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 
| 237 | ··} | 209 | ··} | 
| 238 |  | 210 |  | 
| 239 | ··return·0; | 211 | ··return·0; | 
| 240 | } | 212 | } |