]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/impl/winrt_ssocket_service_base.ipp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 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 | #ifndef BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP | |
12 | #define BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <boost/asio/detail/config.hpp> | |
19 | ||
20 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) | |
21 | ||
22 | #include <cstring> | |
23 | #include <boost/asio/detail/winrt_ssocket_service_base.hpp> | |
24 | #include <boost/asio/detail/winrt_async_op.hpp> | |
25 | #include <boost/asio/detail/winrt_utils.hpp> | |
26 | ||
27 | #include <boost/asio/detail/push_options.hpp> | |
28 | ||
29 | namespace boost { | |
30 | namespace asio { | |
31 | namespace detail { | |
32 | ||
33 | winrt_ssocket_service_base::winrt_ssocket_service_base( | |
92f5a8d4 TL |
34 | execution_context& context) |
35 | : scheduler_(use_service<scheduler_impl>(context)), | |
36 | async_manager_(use_service<winrt_async_manager>(context)), | |
7c673cae FG |
37 | mutex_(), |
38 | impl_list_(0) | |
39 | { | |
40 | } | |
41 | ||
b32b8144 | 42 | void winrt_ssocket_service_base::base_shutdown() |
7c673cae FG |
43 | { |
44 | // Close all implementations, causing all operations to complete. | |
45 | boost::asio::detail::mutex::scoped_lock lock(mutex_); | |
46 | base_implementation_type* impl = impl_list_; | |
47 | while (impl) | |
48 | { | |
49 | boost::system::error_code ignored_ec; | |
50 | close(*impl, ignored_ec); | |
51 | impl = impl->next_; | |
52 | } | |
53 | } | |
54 | ||
55 | void winrt_ssocket_service_base::construct( | |
56 | winrt_ssocket_service_base::base_implementation_type& impl) | |
57 | { | |
58 | // Insert implementation into linked list of all implementations. | |
59 | boost::asio::detail::mutex::scoped_lock lock(mutex_); | |
60 | impl.next_ = impl_list_; | |
61 | impl.prev_ = 0; | |
62 | if (impl_list_) | |
63 | impl_list_->prev_ = &impl; | |
64 | impl_list_ = &impl; | |
65 | } | |
66 | ||
67 | void winrt_ssocket_service_base::base_move_construct( | |
68 | winrt_ssocket_service_base::base_implementation_type& impl, | |
69 | winrt_ssocket_service_base::base_implementation_type& other_impl) | |
92f5a8d4 | 70 | BOOST_ASIO_NOEXCEPT |
7c673cae FG |
71 | { |
72 | impl.socket_ = other_impl.socket_; | |
73 | other_impl.socket_ = nullptr; | |
74 | ||
75 | // Insert implementation into linked list of all implementations. | |
76 | boost::asio::detail::mutex::scoped_lock lock(mutex_); | |
77 | impl.next_ = impl_list_; | |
78 | impl.prev_ = 0; | |
79 | if (impl_list_) | |
80 | impl_list_->prev_ = &impl; | |
81 | impl_list_ = &impl; | |
82 | } | |
83 | ||
84 | void winrt_ssocket_service_base::base_move_assign( | |
85 | winrt_ssocket_service_base::base_implementation_type& impl, | |
86 | winrt_ssocket_service_base& other_service, | |
87 | winrt_ssocket_service_base::base_implementation_type& other_impl) | |
88 | { | |
89 | boost::system::error_code ignored_ec; | |
90 | close(impl, ignored_ec); | |
91 | ||
92 | if (this != &other_service) | |
93 | { | |
94 | // Remove implementation from linked list of all implementations. | |
95 | boost::asio::detail::mutex::scoped_lock lock(mutex_); | |
96 | if (impl_list_ == &impl) | |
97 | impl_list_ = impl.next_; | |
98 | if (impl.prev_) | |
99 | impl.prev_->next_ = impl.next_; | |
100 | if (impl.next_) | |
101 | impl.next_->prev_= impl.prev_; | |
102 | impl.next_ = 0; | |
103 | impl.prev_ = 0; | |
104 | } | |
105 | ||
106 | impl.socket_ = other_impl.socket_; | |
107 | other_impl.socket_ = nullptr; | |
108 | ||
109 | if (this != &other_service) | |
110 | { | |
111 | // Insert implementation into linked list of all implementations. | |
112 | boost::asio::detail::mutex::scoped_lock lock(other_service.mutex_); | |
113 | impl.next_ = other_service.impl_list_; | |
114 | impl.prev_ = 0; | |
115 | if (other_service.impl_list_) | |
116 | other_service.impl_list_->prev_ = &impl; | |
117 | other_service.impl_list_ = &impl; | |
118 | } | |
119 | } | |
120 | ||
121 | void winrt_ssocket_service_base::destroy( | |
122 | winrt_ssocket_service_base::base_implementation_type& impl) | |
123 | { | |
124 | boost::system::error_code ignored_ec; | |
125 | close(impl, ignored_ec); | |
126 | ||
127 | // Remove implementation from linked list of all implementations. | |
128 | boost::asio::detail::mutex::scoped_lock lock(mutex_); | |
129 | if (impl_list_ == &impl) | |
130 | impl_list_ = impl.next_; | |
131 | if (impl.prev_) | |
132 | impl.prev_->next_ = impl.next_; | |
133 | if (impl.next_) | |
134 | impl.next_->prev_= impl.prev_; | |
135 | impl.next_ = 0; | |
136 | impl.prev_ = 0; | |
137 | } | |
138 | ||
139 | boost::system::error_code winrt_ssocket_service_base::close( | |
140 | winrt_ssocket_service_base::base_implementation_type& impl, | |
141 | boost::system::error_code& ec) | |
142 | { | |
f67539c2 TL |
143 | delete impl.socket_; |
144 | impl.socket_ = nullptr; | |
7c673cae FG |
145 | ec = boost::system::error_code(); |
146 | return ec; | |
147 | } | |
148 | ||
b32b8144 FG |
149 | winrt_ssocket_service_base::native_handle_type |
150 | winrt_ssocket_service_base::release( | |
151 | winrt_ssocket_service_base::base_implementation_type& impl, | |
152 | boost::system::error_code& ec) | |
153 | { | |
154 | if (!is_open(impl)) | |
155 | return nullptr; | |
156 | ||
157 | cancel(impl, ec); | |
158 | if (ec) | |
159 | return nullptr; | |
160 | ||
161 | native_handle_type tmp = impl.socket_; | |
162 | impl.socket_ = nullptr; | |
163 | return tmp; | |
164 | } | |
165 | ||
7c673cae FG |
166 | std::size_t winrt_ssocket_service_base::do_get_endpoint( |
167 | const base_implementation_type& impl, bool local, | |
168 | void* addr, std::size_t addr_len, boost::system::error_code& ec) const | |
169 | { | |
170 | if (!is_open(impl)) | |
171 | { | |
172 | ec = boost::asio::error::bad_descriptor; | |
173 | return addr_len; | |
174 | } | |
175 | ||
176 | try | |
177 | { | |
178 | std::string addr_string = winrt_utils::string(local | |
179 | ? impl.socket_->Information->LocalAddress->CanonicalName | |
180 | : impl.socket_->Information->RemoteAddress->CanonicalName); | |
181 | unsigned short port = winrt_utils::integer(local | |
182 | ? impl.socket_->Information->LocalPort | |
183 | : impl.socket_->Information->RemotePort); | |
184 | unsigned long scope = 0; | |
185 | ||
186 | switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) | |
187 | { | |
188 | case BOOST_ASIO_OS_DEF(AF_INET): | |
189 | if (addr_len < sizeof(sockaddr_in4_type)) | |
190 | { | |
191 | ec = boost::asio::error::invalid_argument; | |
192 | return addr_len; | |
193 | } | |
194 | else | |
195 | { | |
196 | socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET), addr_string.c_str(), | |
197 | &reinterpret_cast<sockaddr_in4_type*>(addr)->sin_addr, &scope, ec); | |
198 | reinterpret_cast<sockaddr_in4_type*>(addr)->sin_port | |
199 | = socket_ops::host_to_network_short(port); | |
200 | ec = boost::system::error_code(); | |
201 | return sizeof(sockaddr_in4_type); | |
202 | } | |
203 | case BOOST_ASIO_OS_DEF(AF_INET6): | |
204 | if (addr_len < sizeof(sockaddr_in6_type)) | |
205 | { | |
206 | ec = boost::asio::error::invalid_argument; | |
207 | return addr_len; | |
208 | } | |
209 | else | |
210 | { | |
211 | socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6), addr_string.c_str(), | |
212 | &reinterpret_cast<sockaddr_in6_type*>(addr)->sin6_addr, &scope, ec); | |
213 | reinterpret_cast<sockaddr_in6_type*>(addr)->sin6_port | |
214 | = socket_ops::host_to_network_short(port); | |
215 | ec = boost::system::error_code(); | |
216 | return sizeof(sockaddr_in6_type); | |
217 | } | |
218 | default: | |
219 | ec = boost::asio::error::address_family_not_supported; | |
220 | return addr_len; | |
221 | } | |
222 | } | |
223 | catch (Platform::Exception^ e) | |
224 | { | |
225 | ec = boost::system::error_code(e->HResult, | |
226 | boost::system::system_category()); | |
227 | return addr_len; | |
228 | } | |
229 | } | |
230 | ||
231 | boost::system::error_code winrt_ssocket_service_base::do_set_option( | |
232 | winrt_ssocket_service_base::base_implementation_type& impl, | |
233 | int level, int optname, const void* optval, | |
234 | std::size_t optlen, boost::system::error_code& ec) | |
235 | { | |
236 | if (!is_open(impl)) | |
237 | { | |
238 | ec = boost::asio::error::bad_descriptor; | |
239 | return ec; | |
240 | } | |
241 | ||
242 | try | |
243 | { | |
244 | if (level == BOOST_ASIO_OS_DEF(SOL_SOCKET) | |
245 | && optname == BOOST_ASIO_OS_DEF(SO_KEEPALIVE)) | |
246 | { | |
247 | if (optlen == sizeof(int)) | |
248 | { | |
249 | int value = 0; | |
250 | std::memcpy(&value, optval, optlen); | |
251 | impl.socket_->Control->KeepAlive = !!value; | |
252 | ec = boost::system::error_code(); | |
253 | } | |
254 | else | |
255 | { | |
256 | ec = boost::asio::error::invalid_argument; | |
257 | } | |
258 | } | |
259 | else if (level == BOOST_ASIO_OS_DEF(IPPROTO_TCP) | |
260 | && optname == BOOST_ASIO_OS_DEF(TCP_NODELAY)) | |
261 | { | |
262 | if (optlen == sizeof(int)) | |
263 | { | |
264 | int value = 0; | |
265 | std::memcpy(&value, optval, optlen); | |
266 | impl.socket_->Control->NoDelay = !!value; | |
267 | ec = boost::system::error_code(); | |
268 | } | |
269 | else | |
270 | { | |
271 | ec = boost::asio::error::invalid_argument; | |
272 | } | |
273 | } | |
274 | else | |
275 | { | |
276 | ec = boost::asio::error::invalid_argument; | |
277 | } | |
278 | } | |
279 | catch (Platform::Exception^ e) | |
280 | { | |
281 | ec = boost::system::error_code(e->HResult, | |
282 | boost::system::system_category()); | |
283 | } | |
284 | ||
285 | return ec; | |
286 | } | |
287 | ||
288 | void winrt_ssocket_service_base::do_get_option( | |
289 | const winrt_ssocket_service_base::base_implementation_type& impl, | |
290 | int level, int optname, void* optval, | |
291 | std::size_t* optlen, boost::system::error_code& ec) const | |
292 | { | |
293 | if (!is_open(impl)) | |
294 | { | |
295 | ec = boost::asio::error::bad_descriptor; | |
296 | return; | |
297 | } | |
298 | ||
299 | try | |
300 | { | |
301 | if (level == BOOST_ASIO_OS_DEF(SOL_SOCKET) | |
302 | && optname == BOOST_ASIO_OS_DEF(SO_KEEPALIVE)) | |
303 | { | |
304 | if (*optlen >= sizeof(int)) | |
305 | { | |
306 | int value = impl.socket_->Control->KeepAlive ? 1 : 0; | |
307 | std::memcpy(optval, &value, sizeof(int)); | |
308 | *optlen = sizeof(int); | |
309 | ec = boost::system::error_code(); | |
310 | } | |
311 | else | |
312 | { | |
313 | ec = boost::asio::error::invalid_argument; | |
314 | } | |
315 | } | |
316 | else if (level == BOOST_ASIO_OS_DEF(IPPROTO_TCP) | |
317 | && optname == BOOST_ASIO_OS_DEF(TCP_NODELAY)) | |
318 | { | |
319 | if (*optlen >= sizeof(int)) | |
320 | { | |
321 | int value = impl.socket_->Control->NoDelay ? 1 : 0; | |
322 | std::memcpy(optval, &value, sizeof(int)); | |
323 | *optlen = sizeof(int); | |
324 | ec = boost::system::error_code(); | |
325 | } | |
326 | else | |
327 | { | |
328 | ec = boost::asio::error::invalid_argument; | |
329 | } | |
330 | } | |
331 | else | |
332 | { | |
333 | ec = boost::asio::error::invalid_argument; | |
334 | } | |
335 | } | |
336 | catch (Platform::Exception^ e) | |
337 | { | |
338 | ec = boost::system::error_code(e->HResult, | |
339 | boost::system::system_category()); | |
340 | } | |
341 | } | |
342 | ||
343 | boost::system::error_code winrt_ssocket_service_base::do_connect( | |
344 | winrt_ssocket_service_base::base_implementation_type& impl, | |
345 | const void* addr, boost::system::error_code& ec) | |
346 | { | |
347 | if (!is_open(impl)) | |
348 | { | |
349 | ec = boost::asio::error::bad_descriptor; | |
350 | return ec; | |
351 | } | |
352 | ||
353 | char addr_string[max_addr_v6_str_len]; | |
354 | unsigned short port; | |
355 | switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) | |
356 | { | |
357 | case BOOST_ASIO_OS_DEF(AF_INET): | |
358 | socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET), | |
359 | &reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_addr, | |
360 | addr_string, sizeof(addr_string), 0, ec); | |
361 | port = socket_ops::network_to_host_short( | |
362 | reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_port); | |
363 | break; | |
364 | case BOOST_ASIO_OS_DEF(AF_INET6): | |
365 | socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET6), | |
366 | &reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_addr, | |
367 | addr_string, sizeof(addr_string), 0, ec); | |
368 | port = socket_ops::network_to_host_short( | |
369 | reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_port); | |
370 | break; | |
371 | default: | |
372 | ec = boost::asio::error::address_family_not_supported; | |
373 | return ec; | |
374 | } | |
375 | ||
376 | if (!ec) try | |
377 | { | |
378 | async_manager_.sync(impl.socket_->ConnectAsync( | |
379 | ref new Windows::Networking::HostName( | |
380 | winrt_utils::string(addr_string)), | |
381 | winrt_utils::string(port)), ec); | |
382 | } | |
383 | catch (Platform::Exception^ e) | |
384 | { | |
385 | ec = boost::system::error_code(e->HResult, | |
386 | boost::system::system_category()); | |
387 | } | |
388 | ||
389 | return ec; | |
390 | } | |
391 | ||
392 | void winrt_ssocket_service_base::start_connect_op( | |
393 | winrt_ssocket_service_base::base_implementation_type& impl, | |
394 | const void* addr, winrt_async_op<void>* op, bool is_continuation) | |
395 | { | |
396 | if (!is_open(impl)) | |
397 | { | |
398 | op->ec_ = boost::asio::error::bad_descriptor; | |
92f5a8d4 | 399 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
400 | return; |
401 | } | |
402 | ||
403 | char addr_string[max_addr_v6_str_len]; | |
404 | unsigned short port = 0; | |
405 | switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) | |
406 | { | |
407 | case BOOST_ASIO_OS_DEF(AF_INET): | |
408 | socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET), | |
409 | &reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_addr, | |
410 | addr_string, sizeof(addr_string), 0, op->ec_); | |
411 | port = socket_ops::network_to_host_short( | |
412 | reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_port); | |
413 | break; | |
414 | case BOOST_ASIO_OS_DEF(AF_INET6): | |
415 | socket_ops::inet_ntop(BOOST_ASIO_OS_DEF(AF_INET6), | |
416 | &reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_addr, | |
417 | addr_string, sizeof(addr_string), 0, op->ec_); | |
418 | port = socket_ops::network_to_host_short( | |
419 | reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_port); | |
420 | break; | |
421 | default: | |
422 | op->ec_ = boost::asio::error::address_family_not_supported; | |
423 | break; | |
424 | } | |
425 | ||
426 | if (op->ec_) | |
427 | { | |
92f5a8d4 | 428 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
429 | return; |
430 | } | |
431 | ||
432 | try | |
433 | { | |
434 | async_manager_.async(impl.socket_->ConnectAsync( | |
435 | ref new Windows::Networking::HostName( | |
436 | winrt_utils::string(addr_string)), | |
437 | winrt_utils::string(port)), op); | |
438 | } | |
439 | catch (Platform::Exception^ e) | |
440 | { | |
441 | op->ec_ = boost::system::error_code( | |
442 | e->HResult, boost::system::system_category()); | |
92f5a8d4 | 443 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
444 | } |
445 | } | |
446 | ||
447 | std::size_t winrt_ssocket_service_base::do_send( | |
448 | winrt_ssocket_service_base::base_implementation_type& impl, | |
449 | const boost::asio::const_buffer& data, | |
450 | socket_base::message_flags flags, boost::system::error_code& ec) | |
451 | { | |
452 | if (flags) | |
453 | { | |
454 | ec = boost::asio::error::operation_not_supported; | |
455 | return 0; | |
456 | } | |
457 | ||
458 | if (!is_open(impl)) | |
459 | { | |
460 | ec = boost::asio::error::bad_descriptor; | |
461 | return 0; | |
462 | } | |
463 | ||
464 | try | |
465 | { | |
466 | buffer_sequence_adapter<boost::asio::const_buffer, | |
b32b8144 | 467 | boost::asio::const_buffer> bufs(boost::asio::buffer(data)); |
7c673cae FG |
468 | |
469 | if (bufs.all_empty()) | |
470 | { | |
471 | ec = boost::system::error_code(); | |
472 | return 0; | |
473 | } | |
474 | ||
475 | return async_manager_.sync( | |
476 | impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), ec); | |
477 | } | |
478 | catch (Platform::Exception^ e) | |
479 | { | |
480 | ec = boost::system::error_code(e->HResult, | |
481 | boost::system::system_category()); | |
482 | return 0; | |
483 | } | |
484 | } | |
485 | ||
486 | void winrt_ssocket_service_base::start_send_op( | |
487 | winrt_ssocket_service_base::base_implementation_type& impl, | |
488 | const boost::asio::const_buffer& data, socket_base::message_flags flags, | |
489 | winrt_async_op<unsigned int>* op, bool is_continuation) | |
490 | { | |
491 | if (flags) | |
492 | { | |
493 | op->ec_ = boost::asio::error::operation_not_supported; | |
92f5a8d4 | 494 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
495 | return; |
496 | } | |
497 | ||
498 | if (!is_open(impl)) | |
499 | { | |
500 | op->ec_ = boost::asio::error::bad_descriptor; | |
92f5a8d4 | 501 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
502 | return; |
503 | } | |
504 | ||
505 | try | |
506 | { | |
507 | buffer_sequence_adapter<boost::asio::const_buffer, | |
b32b8144 | 508 | boost::asio::const_buffer> bufs(boost::asio::buffer(data)); |
7c673cae FG |
509 | |
510 | if (bufs.all_empty()) | |
511 | { | |
92f5a8d4 | 512 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
513 | return; |
514 | } | |
515 | ||
516 | async_manager_.async( | |
517 | impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), op); | |
518 | } | |
519 | catch (Platform::Exception^ e) | |
520 | { | |
521 | op->ec_ = boost::system::error_code(e->HResult, | |
522 | boost::system::system_category()); | |
92f5a8d4 | 523 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
524 | } |
525 | } | |
526 | ||
527 | std::size_t winrt_ssocket_service_base::do_receive( | |
528 | winrt_ssocket_service_base::base_implementation_type& impl, | |
529 | const boost::asio::mutable_buffer& data, | |
530 | socket_base::message_flags flags, boost::system::error_code& ec) | |
531 | { | |
532 | if (flags) | |
533 | { | |
534 | ec = boost::asio::error::operation_not_supported; | |
535 | return 0; | |
536 | } | |
537 | ||
538 | if (!is_open(impl)) | |
539 | { | |
540 | ec = boost::asio::error::bad_descriptor; | |
541 | return 0; | |
542 | } | |
543 | ||
544 | try | |
545 | { | |
546 | buffer_sequence_adapter<boost::asio::mutable_buffer, | |
b32b8144 | 547 | boost::asio::mutable_buffer> bufs(boost::asio::buffer(data)); |
7c673cae FG |
548 | |
549 | if (bufs.all_empty()) | |
550 | { | |
551 | ec = boost::system::error_code(); | |
552 | return 0; | |
553 | } | |
554 | ||
555 | async_manager_.sync( | |
556 | impl.socket_->InputStream->ReadAsync( | |
557 | bufs.buffers()[0], bufs.buffers()[0]->Capacity, | |
558 | Windows::Storage::Streams::InputStreamOptions::Partial), ec); | |
559 | ||
560 | std::size_t bytes_transferred = bufs.buffers()[0]->Length; | |
561 | if (bytes_transferred == 0 && !ec) | |
562 | { | |
563 | ec = boost::asio::error::eof; | |
564 | } | |
565 | ||
566 | return bytes_transferred; | |
567 | } | |
568 | catch (Platform::Exception^ e) | |
569 | { | |
570 | ec = boost::system::error_code(e->HResult, | |
571 | boost::system::system_category()); | |
572 | return 0; | |
573 | } | |
574 | } | |
575 | ||
576 | void winrt_ssocket_service_base::start_receive_op( | |
577 | winrt_ssocket_service_base::base_implementation_type& impl, | |
578 | const boost::asio::mutable_buffer& data, socket_base::message_flags flags, | |
579 | winrt_async_op<Windows::Storage::Streams::IBuffer^>* op, | |
580 | bool is_continuation) | |
581 | { | |
582 | if (flags) | |
583 | { | |
584 | op->ec_ = boost::asio::error::operation_not_supported; | |
92f5a8d4 | 585 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
586 | return; |
587 | } | |
588 | ||
589 | if (!is_open(impl)) | |
590 | { | |
591 | op->ec_ = boost::asio::error::bad_descriptor; | |
92f5a8d4 | 592 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
593 | return; |
594 | } | |
595 | ||
596 | try | |
597 | { | |
598 | buffer_sequence_adapter<boost::asio::mutable_buffer, | |
b32b8144 | 599 | boost::asio::mutable_buffer> bufs(boost::asio::buffer(data)); |
7c673cae FG |
600 | |
601 | if (bufs.all_empty()) | |
602 | { | |
92f5a8d4 | 603 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
604 | return; |
605 | } | |
606 | ||
607 | async_manager_.async( | |
608 | impl.socket_->InputStream->ReadAsync( | |
609 | bufs.buffers()[0], bufs.buffers()[0]->Capacity, | |
610 | Windows::Storage::Streams::InputStreamOptions::Partial), op); | |
611 | } | |
612 | catch (Platform::Exception^ e) | |
613 | { | |
614 | op->ec_ = boost::system::error_code(e->HResult, | |
615 | boost::system::system_category()); | |
92f5a8d4 | 616 | scheduler_.post_immediate_completion(op, is_continuation); |
7c673cae FG |
617 | } |
618 | } | |
619 | ||
620 | } // namespace detail | |
621 | } // namespace asio | |
622 | } // namespace boost | |
623 | ||
624 | #include <boost/asio/detail/pop_options.hpp> | |
625 | ||
626 | #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) | |
627 | ||
628 | #endif // BOOST_ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP |