Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / detail / impl / winrt_ssocket_service_base.ipp @ 2486

History | View | Annotate | Download (16.8 kB)

1
//
2
// detail/impl/winrt_ssocket_service_base.ipp
3
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
//
5
// Copyright (c) 2003-2015 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