]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / detail / impl / winrt_ssocket_service_base.ipp
CommitLineData
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
29namespace boost {
30namespace asio {
31namespace detail {
32
33winrt_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 42void 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
55void 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
67void 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
84void 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
121void 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
139boost::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
149winrt_ssocket_service_base::native_handle_type
150winrt_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
166std::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
231boost::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
288void 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
343boost::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
392void 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
447std::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
486void 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
527std::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
576void 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