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