$search
00001 // 00002 // basic_endpoint.hpp 00003 // ~~~~~~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 00011 #ifndef ASIO_IP_BASIC_ENDPOINT_HPP 00012 #define ASIO_IP_BASIC_ENDPOINT_HPP 00013 00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 00015 # pragma once 00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 00017 00018 #include "asio/detail/push_options.hpp" 00019 00020 #include "asio/detail/push_options.hpp" 00021 #include <boost/throw_exception.hpp> 00022 #include <boost/detail/workaround.hpp> 00023 #include <cstring> 00024 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 00025 # include <ostream> 00026 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 00027 #include "asio/detail/pop_options.hpp" 00028 00029 #include "asio/error.hpp" 00030 #include "asio/ip/address.hpp" 00031 #include "asio/detail/socket_ops.hpp" 00032 #include "asio/detail/socket_types.hpp" 00033 00034 namespace asio { 00035 namespace ip { 00036 00038 00049 template <typename InternetProtocol> 00050 class basic_endpoint 00051 { 00052 public: 00054 typedef InternetProtocol protocol_type; 00055 00058 #if defined(GENERATING_DOCUMENTATION) 00059 typedef implementation_defined data_type; 00060 #else 00061 typedef asio::detail::socket_addr_type data_type; 00062 #endif 00063 00065 basic_endpoint() 00066 : data_() 00067 { 00068 data_.v4.sin_family = AF_INET; 00069 data_.v4.sin_port = 0; 00070 data_.v4.sin_addr.s_addr = INADDR_ANY; 00071 } 00072 00077 00089 basic_endpoint(const InternetProtocol& protocol, unsigned short port_num) 00090 : data_() 00091 { 00092 using namespace std; // For memcpy. 00093 if (protocol.family() == PF_INET) 00094 { 00095 data_.v4.sin_family = AF_INET; 00096 data_.v4.sin_port = 00097 asio::detail::socket_ops::host_to_network_short(port_num); 00098 data_.v4.sin_addr.s_addr = INADDR_ANY; 00099 } 00100 else 00101 { 00102 data_.v6.sin6_family = AF_INET6; 00103 data_.v6.sin6_port = 00104 asio::detail::socket_ops::host_to_network_short(port_num); 00105 data_.v6.sin6_flowinfo = 0; 00106 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; 00107 data_.v6.sin6_addr = tmp_addr; 00108 data_.v6.sin6_scope_id = 0; 00109 } 00110 } 00111 00115 basic_endpoint(const asio::ip::address& addr, unsigned short port_num) 00116 : data_() 00117 { 00118 using namespace std; // For memcpy. 00119 if (addr.is_v4()) 00120 { 00121 data_.v4.sin_family = AF_INET; 00122 data_.v4.sin_port = 00123 asio::detail::socket_ops::host_to_network_short(port_num); 00124 data_.v4.sin_addr.s_addr = 00125 asio::detail::socket_ops::host_to_network_long( 00126 addr.to_v4().to_ulong()); 00127 } 00128 else 00129 { 00130 data_.v6.sin6_family = AF_INET6; 00131 data_.v6.sin6_port = 00132 asio::detail::socket_ops::host_to_network_short(port_num); 00133 data_.v6.sin6_flowinfo = 0; 00134 asio::ip::address_v6 v6_addr = addr.to_v6(); 00135 asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); 00136 memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16); 00137 data_.v6.sin6_scope_id = v6_addr.scope_id(); 00138 } 00139 } 00140 00142 basic_endpoint(const basic_endpoint& other) 00143 : data_(other.data_) 00144 { 00145 } 00146 00148 basic_endpoint& operator=(const basic_endpoint& other) 00149 { 00150 data_ = other.data_; 00151 return *this; 00152 } 00153 00155 protocol_type protocol() const 00156 { 00157 if (is_v4()) 00158 return InternetProtocol::v4(); 00159 return InternetProtocol::v6(); 00160 } 00161 00163 data_type* data() 00164 { 00165 return &data_.base; 00166 } 00167 00169 const data_type* data() const 00170 { 00171 return &data_.base; 00172 } 00173 00175 std::size_t size() const 00176 { 00177 if (is_v4()) 00178 return sizeof(asio::detail::sockaddr_in4_type); 00179 else 00180 return sizeof(asio::detail::sockaddr_in6_type); 00181 } 00182 00184 void resize(std::size_t size) 00185 { 00186 if (size > sizeof(asio::detail::sockaddr_storage_type)) 00187 { 00188 asio::system_error e(asio::error::invalid_argument); 00189 boost::throw_exception(e); 00190 } 00191 } 00192 00194 std::size_t capacity() const 00195 { 00196 return sizeof(asio::detail::sockaddr_storage_type); 00197 } 00198 00201 unsigned short port() const 00202 { 00203 if (is_v4()) 00204 { 00205 return asio::detail::socket_ops::network_to_host_short( 00206 data_.v4.sin_port); 00207 } 00208 else 00209 { 00210 return asio::detail::socket_ops::network_to_host_short( 00211 data_.v6.sin6_port); 00212 } 00213 } 00214 00217 void port(unsigned short port_num) 00218 { 00219 if (is_v4()) 00220 { 00221 data_.v4.sin_port 00222 = asio::detail::socket_ops::host_to_network_short(port_num); 00223 } 00224 else 00225 { 00226 data_.v6.sin6_port 00227 = asio::detail::socket_ops::host_to_network_short(port_num); 00228 } 00229 } 00230 00232 asio::ip::address address() const 00233 { 00234 using namespace std; // For memcpy. 00235 if (is_v4()) 00236 { 00237 return asio::ip::address_v4( 00238 asio::detail::socket_ops::network_to_host_long( 00239 data_.v4.sin_addr.s_addr)); 00240 } 00241 else 00242 { 00243 asio::ip::address_v6::bytes_type bytes; 00244 memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16); 00245 return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); 00246 } 00247 } 00248 00250 void address(const asio::ip::address& addr) 00251 { 00252 basic_endpoint<InternetProtocol> tmp_endpoint(addr, port()); 00253 data_ = tmp_endpoint.data_; 00254 } 00255 00257 friend bool operator==(const basic_endpoint<InternetProtocol>& e1, 00258 const basic_endpoint<InternetProtocol>& e2) 00259 { 00260 return e1.address() == e2.address() && e1.port() == e2.port(); 00261 } 00262 00264 friend bool operator!=(const basic_endpoint<InternetProtocol>& e1, 00265 const basic_endpoint<InternetProtocol>& e2) 00266 { 00267 return e1.address() != e2.address() || e1.port() != e2.port(); 00268 } 00269 00271 friend bool operator<(const basic_endpoint<InternetProtocol>& e1, 00272 const basic_endpoint<InternetProtocol>& e2) 00273 { 00274 if (e1.address() < e2.address()) 00275 return true; 00276 if (e1.address() != e2.address()) 00277 return false; 00278 return e1.port() < e2.port(); 00279 } 00280 00281 private: 00282 // Helper function to determine whether the endpoint is IPv4. 00283 bool is_v4() const 00284 { 00285 return data_.base.sa_family == AF_INET; 00286 } 00287 00288 // The underlying IP socket address. 00289 union data_union 00290 { 00291 asio::detail::socket_addr_type base; 00292 asio::detail::sockaddr_storage_type storage; 00293 asio::detail::sockaddr_in4_type v4; 00294 asio::detail::sockaddr_in6_type v6; 00295 } data_; 00296 }; 00297 00299 00310 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 00311 template <typename InternetProtocol> 00312 std::ostream& operator<<(std::ostream& os, 00313 const basic_endpoint<InternetProtocol>& endpoint) 00314 { 00315 const address& addr = endpoint.address(); 00316 asio::error_code ec; 00317 std::string a = addr.to_string(ec); 00318 if (ec) 00319 { 00320 if (os.exceptions() & std::ios::failbit) 00321 asio::detail::throw_error(ec); 00322 else 00323 os.setstate(std::ios_base::failbit); 00324 } 00325 else 00326 { 00327 if (addr.is_v4()) 00328 os << a; 00329 else 00330 os << '[' << a << ']'; 00331 os << ':' << endpoint.port(); 00332 } 00333 return os; 00334 } 00335 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 00336 template <typename Elem, typename Traits, typename InternetProtocol> 00337 std::basic_ostream<Elem, Traits>& operator<<( 00338 std::basic_ostream<Elem, Traits>& os, 00339 const basic_endpoint<InternetProtocol>& endpoint) 00340 { 00341 const address& addr = endpoint.address(); 00342 asio::error_code ec; 00343 std::string a = addr.to_string(ec); 00344 if (ec) 00345 { 00346 if (os.exceptions() & std::ios::failbit) 00347 asio::detail::throw_error(ec); 00348 else 00349 os.setstate(std::ios_base::failbit); 00350 } 00351 else 00352 { 00353 if (addr.is_v4()) 00354 os << a; 00355 else 00356 os << '[' << a << ']'; 00357 os << ':' << endpoint.port(); 00358 } 00359 return os; 00360 } 00361 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 00362 00363 } // namespace ip 00364 } // namespace asio 00365 00366 #include "asio/detail/pop_options.hpp" 00367 00368 #endif // ASIO_IP_BASIC_ENDPOINT_HPP