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