| 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-2021·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5  | //·Copyright·(c)·2003-2021·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  | } |