src/​examples/​cpp03/​nonblocking/​third_party_lib.​cppsrc/​examples/​cpp11/​nonblocking/​third_party_lib.​cpp
1 /​/​1 /​/​
2 /​/​·​third_party_lib.​cpp2 /​/​·​third_party_lib.​cpp
3 /​/​·​~~~~~~~~~~~~~~~~~~~3 /​/​·​~~~~~~~~~~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​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_th​is.​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·​write20 /​/​·​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·​whether21 /​/​·​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·​ready22 /​/​·​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·​session24 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·​the32 ··​/​/​·​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()​·​const34 ··​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·​the49 ··​/​/​·​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()​·​const51 ··​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_buf​fer_)​·​>·​0·​?·​writing·​:​·​reading;​63 ······​state_·​=·​asio:​:​buffer_size(write_buf​fer_)​·​>·​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_lib74 }·​/​/​·​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·​connection77 class·​connection
81 ··​:​·​public·boost:​:​enable_shared_from_th​is<connection>78 ··​:​·​public·​std:​:​enable_shared_from_th​is<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_(fal​se)​,​
109 ······write_in_progress_(fa​lse)​
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·​server163 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_conn​ection-​>socket()​,​178 ··········if·(!ec)​
199 ········boost:​:​bind(&server:​:​handle_accept,​·this,​·new_connection,​179 ··········{
200 ··········asio:​:​placeholders:​:​error)​)​;​180 ············std:​:​make_shared<connectio​n>(std:​:​move(socket)​)​-​>start()​;​
201 ··​}181 ··········​}
202
203 ··void·handle_accept(connect​ion:​:​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 ··​try192 ··​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 }