00001
00002
00003
00004
00005
00006
00007
00008
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
00066 #if defined(GENERATING_DOCUMENTATION)
00067 typedef implementation_defined size_type;
00068 #else
00069 typedef asio::detail::socket_addr_len_type size_type;
00070 #endif
00071
00073 basic_endpoint()
00074 : data_()
00075 {
00076 asio::detail::sockaddr_in4_type& data
00077 = reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_);
00078 data.sin_family = AF_INET;
00079 data.sin_port = 0;
00080 data.sin_addr.s_addr = INADDR_ANY;
00081 }
00082
00087
00099 basic_endpoint(const InternetProtocol& protocol, unsigned short port_num)
00100 : data_()
00101 {
00102 using namespace std;
00103 if (protocol.family() == PF_INET)
00104 {
00105 asio::detail::sockaddr_in4_type& data
00106 = reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_);
00107 data.sin_family = AF_INET;
00108 data.sin_port =
00109 asio::detail::socket_ops::host_to_network_short(port_num);
00110 data.sin_addr.s_addr = INADDR_ANY;
00111 }
00112 else
00113 {
00114 asio::detail::sockaddr_in6_type& data
00115 = reinterpret_cast<asio::detail::sockaddr_in6_type&>(data_);
00116 data.sin6_family = AF_INET6;
00117 data.sin6_port =
00118 asio::detail::socket_ops::host_to_network_short(port_num);
00119 data.sin6_flowinfo = 0;
00120 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00121 data.sin6_addr = tmp_addr;
00122 data.sin6_scope_id = 0;
00123 }
00124 }
00125
00129 basic_endpoint(const asio::ip::address& addr, unsigned short port_num)
00130 : data_()
00131 {
00132 using namespace std;
00133 if (addr.is_v4())
00134 {
00135 asio::detail::sockaddr_in4_type& data
00136 = reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_);
00137 data.sin_family = AF_INET;
00138 data.sin_port =
00139 asio::detail::socket_ops::host_to_network_short(port_num);
00140 data.sin_addr.s_addr =
00141 asio::detail::socket_ops::host_to_network_long(
00142 addr.to_v4().to_ulong());
00143 }
00144 else
00145 {
00146 asio::detail::sockaddr_in6_type& data
00147 = reinterpret_cast<asio::detail::sockaddr_in6_type&>(data_);
00148 data.sin6_family = AF_INET6;
00149 data.sin6_port =
00150 asio::detail::socket_ops::host_to_network_short(port_num);
00151 data.sin6_flowinfo = 0;
00152 asio::ip::address_v6 v6_addr = addr.to_v6();
00153 asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
00154 memcpy(data.sin6_addr.s6_addr, bytes.elems, 16);
00155 data.sin6_scope_id = v6_addr.scope_id();
00156 }
00157 }
00158
00160 basic_endpoint(const basic_endpoint& other)
00161 : data_(other.data_)
00162 {
00163 }
00164
00166 basic_endpoint& operator=(const basic_endpoint& other)
00167 {
00168 data_ = other.data_;
00169 return *this;
00170 }
00171
00173 protocol_type protocol() const
00174 {
00175 if (is_v4())
00176 return InternetProtocol::v4();
00177 return InternetProtocol::v6();
00178 }
00179
00181 data_type* data()
00182 {
00183 return reinterpret_cast<data_type*>(&data_);
00184 }
00185
00187 const data_type* data() const
00188 {
00189 return reinterpret_cast<const data_type*>(&data_);
00190 }
00191
00193 size_type size() const
00194 {
00195 if (is_v4())
00196 return sizeof(asio::detail::sockaddr_in4_type);
00197 else
00198 return sizeof(asio::detail::sockaddr_in6_type);
00199 }
00200
00202 void resize(size_type size)
00203 {
00204 if (size > size_type(sizeof(data_)))
00205 {
00206 asio::system_error e(asio::error::invalid_argument);
00207 boost::throw_exception(e);
00208 }
00209 }
00210
00212 size_type capacity() const
00213 {
00214 return sizeof(data_);
00215 }
00216
00219 unsigned short port() const
00220 {
00221 if (is_v4())
00222 {
00223 return asio::detail::socket_ops::network_to_host_short(
00224 reinterpret_cast<const asio::detail::sockaddr_in4_type&>(
00225 data_).sin_port);
00226 }
00227 else
00228 {
00229 return asio::detail::socket_ops::network_to_host_short(
00230 reinterpret_cast<const asio::detail::sockaddr_in6_type&>(
00231 data_).sin6_port);
00232 }
00233 }
00234
00237 void port(unsigned short port_num)
00238 {
00239 if (is_v4())
00240 {
00241 reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_).sin_port
00242 = asio::detail::socket_ops::host_to_network_short(port_num);
00243 }
00244 else
00245 {
00246 reinterpret_cast<asio::detail::sockaddr_in6_type&>(data_).sin6_port
00247 = asio::detail::socket_ops::host_to_network_short(port_num);
00248 }
00249 }
00250
00252 asio::ip::address address() const
00253 {
00254 using namespace std;
00255 if (is_v4())
00256 {
00257 const asio::detail::sockaddr_in4_type& data
00258 = reinterpret_cast<const asio::detail::sockaddr_in4_type&>(
00259 data_);
00260 return asio::ip::address_v4(
00261 asio::detail::socket_ops::network_to_host_long(
00262 data.sin_addr.s_addr));
00263 }
00264 else
00265 {
00266 const asio::detail::sockaddr_in6_type& data
00267 = reinterpret_cast<const asio::detail::sockaddr_in6_type&>(
00268 data_);
00269 asio::ip::address_v6::bytes_type bytes;
00270 memcpy(bytes.elems, data.sin6_addr.s6_addr, 16);
00271 return asio::ip::address_v6(bytes, data.sin6_scope_id);
00272 }
00273 }
00274
00276 void address(const asio::ip::address& addr)
00277 {
00278 basic_endpoint<InternetProtocol> tmp_endpoint(addr, port());
00279 data_ = tmp_endpoint.data_;
00280 }
00281
00283 friend bool operator==(const basic_endpoint<InternetProtocol>& e1,
00284 const basic_endpoint<InternetProtocol>& e2)
00285 {
00286 return e1.address() == e2.address() && e1.port() == e2.port();
00287 }
00288
00290 friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,
00291 const basic_endpoint<InternetProtocol>& e2)
00292 {
00293 return e1.address() != e2.address() || e1.port() != e2.port();
00294 }
00295
00297 friend bool operator<(const basic_endpoint<InternetProtocol>& e1,
00298 const basic_endpoint<InternetProtocol>& e2)
00299 {
00300 if (e1.address() < e2.address())
00301 return true;
00302 if (e1.address() != e2.address())
00303 return false;
00304 return e1.port() < e2.port();
00305 }
00306
00307 private:
00308
00309 bool is_v4() const
00310 {
00311 #if defined(_AIX)
00312 return data_.__ss_family == AF_INET;
00313 #else
00314 return data_.ss_family == AF_INET;
00315 #endif
00316 }
00317
00318
00319 asio::detail::sockaddr_storage_type data_;
00320 };
00321
00323
00334 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00335 template <typename InternetProtocol>
00336 std::ostream& operator<<(std::ostream& os,
00337 const basic_endpoint<InternetProtocol>& endpoint)
00338 {
00339 const address& addr = endpoint.address();
00340 if (addr.is_v4())
00341 os << addr.to_string();
00342 else
00343 os << '[' << addr.to_string() << ']';
00344 os << ':' << endpoint.port();
00345 return os;
00346 }
00347 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00348 template <typename Elem, typename Traits, typename InternetProtocol>
00349 std::basic_ostream<Elem, Traits>& operator<<(
00350 std::basic_ostream<Elem, Traits>& os,
00351 const basic_endpoint<InternetProtocol>& endpoint)
00352 {
00353 const address& addr = endpoint.address();
00354 if (addr.is_v4())
00355 os << addr.to_string();
00356 else
00357 os << '[' << addr.to_string() << ']';
00358 os << ':' << endpoint.port();
00359 return os;
00360 }
00361 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00362
00363 }
00364 }
00365
00366 #include "asio/detail/pop_options.hpp"
00367
00368 #endif // ASIO_IP_BASIC_ENDPOINT_HPP