]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/include/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / asio / include / boost / asio / detail / impl / winrt_ssocket_service_base.ipp
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