1 //
2 // detail/winrt_ssocket_service.hpp
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_WINRT_SSOCKET_SERVICE_HPP
12 #define BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP
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 <boost/asio/error.hpp>
23 #include <boost/asio/io_service.hpp>
24 #include <boost/asio/detail/addressof.hpp>
25 #include <boost/asio/detail/winrt_socket_connect_op.hpp>
26 #include <boost/asio/detail/winrt_ssocket_service_base.hpp>
27 #include <boost/asio/detail/winrt_utils.hpp>
28 
29 #include <boost/asio/detail/push_options.hpp>
30 
31 namespace boost {
32 namespace asio {
33 namespace detail {
34 
35 template <typename Protocol>
36 class winrt_ssocket_service :
37   public winrt_ssocket_service_base
38 {
39 public:
40   // The protocol type.
41   typedef Protocol protocol_type;
42 
43   // The endpoint type.
44   typedef typename Protocol::endpoint endpoint_type;
45 
46   // The native type of a socket.
47   typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type;
48 
49   // The implementation type of the socket.
50   struct implementation_type : base_implementation_type
51   {
52     // Default constructor.
implementation_typeboost::asio::detail::winrt_ssocket_service::implementation_type53     implementation_type()
54       : base_implementation_type(),
55         protocol_(endpoint_type().protocol())
56     {
57     }
58 
59     // The protocol associated with the socket.
60     protocol_type protocol_;
61   };
62 
63   // Constructor.
winrt_ssocket_service(boost::asio::io_service & io_service)64   winrt_ssocket_service(boost::asio::io_service& io_service)
65     : winrt_ssocket_service_base(io_service)
66   {
67   }
68 
69   // Move-construct a new socket implementation.
move_construct(implementation_type & impl,implementation_type & other_impl)70   void move_construct(implementation_type& impl,
71       implementation_type& other_impl)
72   {
73     this->base_move_construct(impl, other_impl);
74 
75     impl.protocol_ = other_impl.protocol_;
76     other_impl.protocol_ = endpoint_type().protocol();
77   }
78 
79   // Move-assign from another socket implementation.
move_assign(implementation_type & impl,winrt_ssocket_service & other_service,implementation_type & other_impl)80   void move_assign(implementation_type& impl,
81       winrt_ssocket_service& other_service,
82       implementation_type& other_impl)
83   {
84     this->base_move_assign(impl, other_service, other_impl);
85 
86     impl.protocol_ = other_impl.protocol_;
87     other_impl.protocol_ = endpoint_type().protocol();
88   }
89 
90   // Move-construct a new socket implementation from another protocol type.
91   template <typename Protocol1>
converting_move_construct(implementation_type & impl,typename winrt_ssocket_service<Protocol1>::implementation_type & other_impl)92   void converting_move_construct(implementation_type& impl,
93       typename winrt_ssocket_service<
94         Protocol1>::implementation_type& other_impl)
95   {
96     this->base_move_construct(impl, other_impl);
97 
98     impl.protocol_ = protocol_type(other_impl.protocol_);
99     other_impl.protocol_ = typename Protocol1::endpoint().protocol();
100   }
101 
102   // Open a new socket implementation.
open(implementation_type & impl,const protocol_type & protocol,boost::system::error_code & ec)103   boost::system::error_code open(implementation_type& impl,
104       const protocol_type& protocol, boost::system::error_code& ec)
105   {
106     if (is_open(impl))
107     {
108       ec = boost::asio::error::already_open;
109       return ec;
110     }
111 
112     try
113     {
114       impl.socket_ = ref new Windows::Networking::Sockets::StreamSocket;
115       impl.protocol_ = protocol;
116       ec = boost::system::error_code();
117     }
118     catch (Platform::Exception^ e)
119     {
120       ec = boost::system::error_code(e->HResult,
121             boost::system::system_category());
122     }
123 
124     return ec;
125   }
126 
127   // Assign a native socket to a socket implementation.
assign(implementation_type & impl,const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)128   boost::system::error_code assign(implementation_type& impl,
129       const protocol_type& protocol, const native_handle_type& native_socket,
130       boost::system::error_code& ec)
131   {
132     if (is_open(impl))
133     {
134       ec = boost::asio::error::already_open;
135       return ec;
136     }
137 
138     impl.socket_ = native_socket;
139     impl.protocol_ = protocol;
140     ec = boost::system::error_code();
141 
142     return ec;
143   }
144 
145   // Bind the socket to the specified local endpoint.
bind(implementation_type &,const endpoint_type &,boost::system::error_code & ec)146   boost::system::error_code bind(implementation_type&,
147       const endpoint_type&, boost::system::error_code& ec)
148   {
149     ec = boost::asio::error::operation_not_supported;
150     return ec;
151   }
152 
153   // Get the local endpoint.
local_endpoint(const implementation_type & impl,boost::system::error_code & ec) const154   endpoint_type local_endpoint(const implementation_type& impl,
155       boost::system::error_code& ec) const
156   {
157     endpoint_type endpoint;
158     endpoint.resize(do_get_endpoint(impl, true,
159           endpoint.data(), endpoint.size(), ec));
160     return endpoint;
161   }
162 
163   // Get the remote endpoint.
remote_endpoint(const implementation_type & impl,boost::system::error_code & ec) const164   endpoint_type remote_endpoint(const implementation_type& impl,
165       boost::system::error_code& ec) const
166   {
167     endpoint_type endpoint;
168     endpoint.resize(do_get_endpoint(impl, false,
169           endpoint.data(), endpoint.size(), ec));
170     return endpoint;
171   }
172 
173   // Set a socket option.
174   template <typename Option>
set_option(implementation_type & impl,const Option & option,boost::system::error_code & ec)175   boost::system::error_code set_option(implementation_type& impl,
176       const Option& option, boost::system::error_code& ec)
177   {
178     return do_set_option(impl, option.level(impl.protocol_),
179         option.name(impl.protocol_), option.data(impl.protocol_),
180         option.size(impl.protocol_), ec);
181   }
182 
183   // Get a socket option.
184   template <typename Option>
get_option(const implementation_type & impl,Option & option,boost::system::error_code & ec) const185   boost::system::error_code get_option(const implementation_type& impl,
186       Option& option, boost::system::error_code& ec) const
187   {
188     std::size_t size = option.size(impl.protocol_);
189     do_get_option(impl, option.level(impl.protocol_),
190         option.name(impl.protocol_),
191         option.data(impl.protocol_), &size, ec);
192     if (!ec)
193       option.resize(impl.protocol_, size);
194     return ec;
195   }
196 
197   // Connect the socket to the specified endpoint.
connect(implementation_type & impl,const endpoint_type & peer_endpoint,boost::system::error_code & ec)198   boost::system::error_code connect(implementation_type& impl,
199       const endpoint_type& peer_endpoint, boost::system::error_code& ec)
200   {
201     return do_connect(impl, peer_endpoint.data(), ec);
202   }
203 
204   // Start an asynchronous connect.
205   template <typename Handler>
async_connect(implementation_type & impl,const endpoint_type & peer_endpoint,Handler & handler)206   void async_connect(implementation_type& impl,
207       const endpoint_type& peer_endpoint, Handler& handler)
208   {
209     bool is_continuation =
210       boost_asio_handler_cont_helpers::is_continuation(handler);
211 
212     // Allocate and construct an operation to wrap the handler.
213     typedef winrt_socket_connect_op<Handler> op;
214     typename op::ptr p = { boost::asio::detail::addressof(handler),
215       boost_asio_handler_alloc_helpers::allocate(
216         sizeof(op), handler), 0 };
217     p.p = new (p.v) op(handler);
218 
219     BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
220 
221     start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation);
222     p.v = p.p = 0;
223   }
224 };
225 
226 } // namespace detail
227 } // namespace asio
228 } // namespace boost
229 
230 #include <boost/asio/detail/pop_options.hpp>
231 
232 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
233 
234 #endif // BOOST_ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP
235