Move QUIC Socket Address lib to QUICHE. Patch envoy to use QuicheSocketAddress instead NOT generated via copybara PiperOrigin-RevId: 722764629
diff --git a/build/source_list.bzl b/build/source_list.bzl index f7ea431..cbed419 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -56,6 +56,7 @@ "common/quiche_protocol_flags_list.h", "common/quiche_random.h", "common/quiche_simple_arena.h", + "common/quiche_socket_address.h", "common/quiche_status_utils.h", "common/quiche_stream.h", "common/quiche_text_utils.h", @@ -426,6 +427,7 @@ "common/quiche_mem_slice_storage.cc", "common/quiche_random.cc", "common/quiche_simple_arena.cc", + "common/quiche_socket_address.cc", "common/quiche_text_utils.cc", "common/simple_buffer_allocator.cc", "common/structured_headers.cc", @@ -703,7 +705,6 @@ "quic/core/uber_received_packet_manager.cc", "quic/core/web_transport_stats.cc", "quic/core/web_transport_write_blocked_list.cc", - "quic/platform/api/quic_socket_address.cc", "web_transport/complete_buffer_visitor.cc", "web_transport/encapsulated/encapsulated_web_transport.cc", "web_transport/web_transport_headers.cc", @@ -1107,6 +1108,7 @@ "common/quiche_mem_slice_storage_test.cc", "common/quiche_random_test.cc", "common/quiche_simple_arena_test.cc", + "common/quiche_socket_address_test.cc", "common/quiche_text_utils_test.cc", "common/quiche_weak_ptr_test.cc", "common/simple_buffer_allocator_test.cc", @@ -1337,7 +1339,6 @@ "quic/core/uber_quic_stream_id_manager_test.cc", "quic/core/uber_received_packet_manager_test.cc", "quic/core/web_transport_write_blocked_list_test.cc", - "quic/platform/api/quic_socket_address_test.cc", "quic/test_tools/crypto_test_utils_test.cc", "quic/test_tools/quic_test_utils_test.cc", "quic/test_tools/simple_session_notifier_test.cc",
diff --git a/build/source_list.gni b/build/source_list.gni index 2c862ea..b5e2a84 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -56,6 +56,7 @@ "src/quiche/common/quiche_protocol_flags_list.h", "src/quiche/common/quiche_random.h", "src/quiche/common/quiche_simple_arena.h", + "src/quiche/common/quiche_socket_address.h", "src/quiche/common/quiche_status_utils.h", "src/quiche/common/quiche_stream.h", "src/quiche/common/quiche_text_utils.h", @@ -426,6 +427,7 @@ "src/quiche/common/quiche_mem_slice_storage.cc", "src/quiche/common/quiche_random.cc", "src/quiche/common/quiche_simple_arena.cc", + "src/quiche/common/quiche_socket_address.cc", "src/quiche/common/quiche_text_utils.cc", "src/quiche/common/simple_buffer_allocator.cc", "src/quiche/common/structured_headers.cc", @@ -703,7 +705,6 @@ "src/quiche/quic/core/uber_received_packet_manager.cc", "src/quiche/quic/core/web_transport_stats.cc", "src/quiche/quic/core/web_transport_write_blocked_list.cc", - "src/quiche/quic/platform/api/quic_socket_address.cc", "src/quiche/web_transport/complete_buffer_visitor.cc", "src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc", "src/quiche/web_transport/web_transport_headers.cc", @@ -1108,6 +1109,7 @@ "src/quiche/common/quiche_mem_slice_storage_test.cc", "src/quiche/common/quiche_random_test.cc", "src/quiche/common/quiche_simple_arena_test.cc", + "src/quiche/common/quiche_socket_address_test.cc", "src/quiche/common/quiche_text_utils_test.cc", "src/quiche/common/quiche_weak_ptr_test.cc", "src/quiche/common/simple_buffer_allocator_test.cc", @@ -1338,7 +1340,6 @@ "src/quiche/quic/core/uber_quic_stream_id_manager_test.cc", "src/quiche/quic/core/uber_received_packet_manager_test.cc", "src/quiche/quic/core/web_transport_write_blocked_list_test.cc", - "src/quiche/quic/platform/api/quic_socket_address_test.cc", "src/quiche/quic/test_tools/crypto_test_utils_test.cc", "src/quiche/quic/test_tools/quic_test_utils_test.cc", "src/quiche/quic/test_tools/simple_session_notifier_test.cc",
diff --git a/build/source_list.json b/build/source_list.json index 64590e2..e99fdac 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -55,6 +55,7 @@ "quiche/common/quiche_protocol_flags_list.h", "quiche/common/quiche_random.h", "quiche/common/quiche_simple_arena.h", + "quiche/common/quiche_socket_address.h", "quiche/common/quiche_status_utils.h", "quiche/common/quiche_stream.h", "quiche/common/quiche_text_utils.h", @@ -425,6 +426,7 @@ "quiche/common/quiche_mem_slice_storage.cc", "quiche/common/quiche_random.cc", "quiche/common/quiche_simple_arena.cc", + "quiche/common/quiche_socket_address.cc", "quiche/common/quiche_text_utils.cc", "quiche/common/simple_buffer_allocator.cc", "quiche/common/structured_headers.cc", @@ -702,7 +704,6 @@ "quiche/quic/core/uber_received_packet_manager.cc", "quiche/quic/core/web_transport_stats.cc", "quiche/quic/core/web_transport_write_blocked_list.cc", - "quiche/quic/platform/api/quic_socket_address.cc", "quiche/web_transport/complete_buffer_visitor.cc", "quiche/web_transport/encapsulated/encapsulated_web_transport.cc", "quiche/web_transport/web_transport_headers.cc", @@ -1107,6 +1108,7 @@ "quiche/common/quiche_mem_slice_storage_test.cc", "quiche/common/quiche_random_test.cc", "quiche/common/quiche_simple_arena_test.cc", + "quiche/common/quiche_socket_address_test.cc", "quiche/common/quiche_text_utils_test.cc", "quiche/common/quiche_weak_ptr_test.cc", "quiche/common/simple_buffer_allocator_test.cc", @@ -1337,7 +1339,6 @@ "quiche/quic/core/uber_quic_stream_id_manager_test.cc", "quiche/quic/core/uber_received_packet_manager_test.cc", "quiche/quic/core/web_transport_write_blocked_list_test.cc", - "quiche/quic/platform/api/quic_socket_address_test.cc", "quiche/quic/test_tools/crypto_test_utils_test.cc", "quiche/quic/test_tools/quic_test_utils_test.cc", "quiche/quic/test_tools/simple_session_notifier_test.cc",
diff --git a/quiche/quic/platform/api/quic_socket_address.cc b/quiche/common/quiche_socket_address.cc similarity index 65% rename from quiche/quic/platform/api/quic_socket_address.cc rename to quiche/common/quiche_socket_address.cc index f14faea..b615007 100644 --- a/quiche/quic/platform/api/quic_socket_address.cc +++ b/quiche/common/quiche_socket_address.cc
@@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/quiche_socket_address.h" #include <cstring> #include <limits> #include <string> #include "absl/strings/str_cat.h" -#include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_ip_address.h" -#include "quiche/quic/platform/api/quic_ip_address_family.h" +#include "quiche/common/platform/api/quiche_bug_tracker.h" +#include "quiche/common/quiche_ip_address.h" +#include "quiche/common/quiche_ip_address_family.h" -namespace quic { +namespace quiche { namespace { -uint32_t HashIP(const QuicIpAddress& ip) { +uint32_t HashIP(const QuicheIpAddress& ip) { if (ip.IsIPv4()) { return ip.GetIPv4().s_addr; } @@ -32,31 +32,31 @@ } // namespace -QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port) +QuicheSocketAddress::QuicheSocketAddress(QuicheIpAddress address, uint16_t port) : host_(address), port_(port) {} -QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr) { +QuicheSocketAddress::QuicheSocketAddress(const struct sockaddr_storage& saddr) { switch (saddr.ss_family) { case AF_INET: { const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&saddr); - host_ = QuicIpAddress(v4->sin_addr); + host_ = QuicheIpAddress(v4->sin_addr); port_ = ntohs(v4->sin_port); break; } case AF_INET6: { const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&saddr); - host_ = QuicIpAddress(v6->sin6_addr); + host_ = QuicheIpAddress(v6->sin6_addr); port_ = ntohs(v6->sin6_port); break; } default: - QUIC_BUG(quic_bug_10075_1) + QUICHE_BUG(unknown_address_family) << "Unknown address family passed: " << saddr.ss_family; break; } } -QuicSocketAddress::QuicSocketAddress(const sockaddr* saddr, socklen_t len) { +QuicheSocketAddress::QuicheSocketAddress(const sockaddr* saddr, socklen_t len) { sockaddr_storage storage; static_assert(std::numeric_limits<socklen_t>::max() >= sizeof(storage), "Cannot cast sizeof(storage) to socklen_t as it does not fit"); @@ -66,24 +66,29 @@ (saddr->sa_family == AF_INET6 && len < static_cast<socklen_t>(sizeof(sockaddr_in6))) || len > static_cast<socklen_t>(sizeof(storage))) { - QUIC_BUG(quic_bug_10075_2) << "Socket address of invalid length provided"; + QUICHE_BUG(socket_address_bad_length) + << "Socket address of invalid length provided"; return; } memcpy(&storage, saddr, len); - *this = QuicSocketAddress(storage); + *this = QuicheSocketAddress(storage); } -bool operator==(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) { +bool operator==(const QuicheSocketAddress& lhs, + const QuicheSocketAddress& rhs) { return lhs.host_ == rhs.host_ && lhs.port_ == rhs.port_; } -bool operator!=(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) { +bool operator!=(const QuicheSocketAddress& lhs, + const QuicheSocketAddress& rhs) { return !(lhs == rhs); } -bool QuicSocketAddress::IsInitialized() const { return host_.IsInitialized(); } +bool QuicheSocketAddress::IsInitialized() const { + return host_.IsInitialized(); +} -std::string QuicSocketAddress::ToString() const { +std::string QuicheSocketAddress::ToString() const { switch (host_.address_family()) { case IpAddressFamily::IP_V4: return absl::StrCat(host_.ToString(), ":", port_); @@ -94,7 +99,7 @@ } } -int QuicSocketAddress::FromSocket(int fd) { +int QuicheSocketAddress::FromSocket(int fd) { sockaddr_storage addr; socklen_t addr_len = sizeof(addr); int result = getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &addr_len); @@ -102,21 +107,21 @@ bool success = result == 0 && addr_len > 0 && static_cast<size_t>(addr_len) <= sizeof(addr); if (success) { - *this = QuicSocketAddress(addr); + *this = QuicheSocketAddress(addr); return 0; } return -1; } -QuicSocketAddress QuicSocketAddress::Normalized() const { - return QuicSocketAddress(host_.Normalized(), port_); +QuicheSocketAddress QuicheSocketAddress::Normalized() const { + return QuicheSocketAddress(host_.Normalized(), port_); } -QuicIpAddress QuicSocketAddress::host() const { return host_; } +QuicheIpAddress QuicheSocketAddress::host() const { return host_; } -uint16_t QuicSocketAddress::port() const { return port_; } +uint16_t QuicheSocketAddress::port() const { return port_; } -sockaddr_storage QuicSocketAddress::generic_address() const { +sockaddr_storage QuicheSocketAddress::generic_address() const { union { sockaddr_storage storage; sockaddr_in v4; @@ -142,11 +147,11 @@ return result.storage; } -uint32_t QuicSocketAddress::Hash() const { +uint32_t QuicheSocketAddress::Hash() const { uint32_t value = 0; value ^= HashIP(host_); value ^= port_ | (port_ << 16); return value; } -} // namespace quic +} // namespace quiche
diff --git a/quiche/common/quiche_socket_address.h b/quiche/common/quiche_socket_address.h new file mode 100644 index 0000000..9cfbd06 --- /dev/null +++ b/quiche/common/quiche_socket_address.h
@@ -0,0 +1,69 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_COMMON_QUICHE_SOCKET_ADDRESS_H_ +#define QUICHE_COMMON_QUICHE_SOCKET_ADDRESS_H_ + +#include <string> + +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_ip_address.h" + +namespace quiche { + +// A class representing a socket endpoint address (i.e., IP address plus a +// port). +class QUICHE_EXPORT QuicheSocketAddress { + public: + QuicheSocketAddress() {} + QuicheSocketAddress(QuicheIpAddress address, uint16_t port); + explicit QuicheSocketAddress(const struct sockaddr_storage& saddr); + explicit QuicheSocketAddress(const sockaddr* saddr, socklen_t len); + QuicheSocketAddress(const QuicheSocketAddress& other) = default; + QuicheSocketAddress& operator=(const QuicheSocketAddress& other) = default; + QuicheSocketAddress& operator=(QuicheSocketAddress&& other) = default; + QUICHE_EXPORT friend bool operator==(const QuicheSocketAddress& lhs, + const QuicheSocketAddress& rhs); + QUICHE_EXPORT friend bool operator!=(const QuicheSocketAddress& lhs, + const QuicheSocketAddress& rhs); + + bool IsInitialized() const; + std::string ToString() const; + + // TODO(ericorth): Convert usage over to socket_api::GetSocketAddress() and + // remove. + int FromSocket(int fd); + + QuicheSocketAddress Normalized() const; + + QuicheIpAddress host() const; + uint16_t port() const; + sockaddr_storage generic_address() const; + + // Hashes this address to an uint32_t. + uint32_t Hash() const; + + private: + QuicheIpAddress host_; + uint16_t port_ = 0; +}; + +inline std::ostream& operator<<(std::ostream& os, + const QuicheSocketAddress address) { + os << address.ToString(); + return os; +} + +// clang-format off +class QUICHE_EXPORT QuicheSocketAddressHash { + public: + size_t operator()(QuicheSocketAddress const& address) const noexcept { + return address.Hash(); + } +}; +// clang-format on + +} // namespace quiche + +#endif // QUICHE_COMMON_QUICHE_SOCKET_ADDRESS_H_
diff --git a/quiche/common/quiche_socket_address_test.cc b/quiche/common/quiche_socket_address_test.cc new file mode 100644 index 0000000..e724133 --- /dev/null +++ b/quiche/common/quiche_socket_address_test.cc
@@ -0,0 +1,133 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/common/quiche_socket_address.h" + +#include <sstream> + +#include "quiche/common/platform/api/quiche_test.h" +#include "quiche/common/quiche_ip_address.h" + +namespace quiche { +namespace { + +TEST(QuicheSocketAddress, Uninitialized) { + QuicheSocketAddress uninitialized; + EXPECT_FALSE(uninitialized.IsInitialized()); +} + +TEST(QuicheSocketAddress, ExplicitConstruction) { + QuicheSocketAddress ipv4_address(QuicheIpAddress::Loopback4(), 443); + QuicheSocketAddress ipv6_address(QuicheIpAddress::Loopback6(), 443); + EXPECT_TRUE(ipv4_address.IsInitialized()); + EXPECT_EQ("127.0.0.1:443", ipv4_address.ToString()); + EXPECT_EQ("[::1]:443", ipv6_address.ToString()); + EXPECT_EQ(QuicheIpAddress::Loopback4(), ipv4_address.host()); + EXPECT_EQ(QuicheIpAddress::Loopback6(), ipv6_address.host()); + EXPECT_EQ(443, ipv4_address.port()); +} + +TEST(QuicheSocketAddress, OutputToStream) { + QuicheSocketAddress ipv4_address(QuicheIpAddress::Loopback4(), 443); + std::stringstream stream; + stream << ipv4_address; + EXPECT_EQ("127.0.0.1:443", stream.str()); +} + +TEST(QuicheSocketAddress, FromSockaddrIPv4) { + union { + sockaddr_storage storage; + sockaddr addr; + sockaddr_in v4; + } address; + + memset(&address, 0, sizeof(address)); + address.v4.sin_family = AF_INET; + address.v4.sin_addr = QuicheIpAddress::Loopback4().GetIPv4(); + address.v4.sin_port = htons(443); + EXPECT_EQ("127.0.0.1:443", + QuicheSocketAddress(&address.addr, sizeof(address.v4)).ToString()); + EXPECT_EQ("127.0.0.1:443", QuicheSocketAddress(address.storage).ToString()); +} + +TEST(QuicheSocketAddress, FromSockaddrIPv6) { + union { + sockaddr_storage storage; + sockaddr addr; + sockaddr_in6 v6; + } address; + + memset(&address, 0, sizeof(address)); + address.v6.sin6_family = AF_INET6; + address.v6.sin6_addr = QuicheIpAddress::Loopback6().GetIPv6(); + address.v6.sin6_port = htons(443); + EXPECT_EQ("[::1]:443", + QuicheSocketAddress(&address.addr, sizeof(address.v6)).ToString()); + EXPECT_EQ("[::1]:443", QuicheSocketAddress(address.storage).ToString()); +} + +TEST(QuicSocketAddres, ToSockaddrIPv4) { + union { + sockaddr_storage storage; + sockaddr_in v4; + } address; + + address.storage = + QuicheSocketAddress(QuicheIpAddress::Loopback4(), 443).generic_address(); + ASSERT_EQ(AF_INET, address.v4.sin_family); + EXPECT_EQ(QuicheIpAddress::Loopback4(), QuicheIpAddress(address.v4.sin_addr)); + EXPECT_EQ(htons(443), address.v4.sin_port); +} + +TEST(QuicheSocketAddress, Normalize) { + QuicheIpAddress dual_stacked; + ASSERT_TRUE(dual_stacked.FromString("::ffff:127.0.0.1")); + ASSERT_TRUE(dual_stacked.IsIPv6()); + QuicheSocketAddress not_normalized(dual_stacked, 443); + QuicheSocketAddress normalized = not_normalized.Normalized(); + EXPECT_EQ("[::ffff:127.0.0.1]:443", not_normalized.ToString()); + EXPECT_EQ("127.0.0.1:443", normalized.ToString()); +} + +// TODO(vasilvv): either ensure this works on all platforms, or deprecate and +// remove this API. +#if defined(__linux__) && !defined(ANDROID) +#include <errno.h> +#include <sys/socket.h> +#include <sys/types.h> + +TEST(QuicheSocketAddress, FromSocket) { + int fd; + QuicheSocketAddress address; + bool bound = false; + for (int port = 50000; port < 50400; port++) { + fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + ASSERT_GT(fd, 0); + + address = QuicheSocketAddress(QuicheIpAddress::Loopback6(), port); + sockaddr_storage raw_address = address.generic_address(); + int bind_result = bind(fd, reinterpret_cast<const sockaddr*>(&raw_address), + sizeof(sockaddr_in6)); + + if (bind_result < 0 && errno == EADDRINUSE) { + close(fd); + continue; + } + + ASSERT_EQ(0, bind_result); + bound = true; + break; + } + ASSERT_TRUE(bound); + + QuicheSocketAddress real_address; + ASSERT_EQ(0, real_address.FromSocket(fd)); + ASSERT_TRUE(real_address.IsInitialized()); + EXPECT_EQ(real_address, address); + close(fd); +} +#endif + +} // namespace +} // namespace quiche
diff --git a/quiche/quic/platform/api/quic_socket_address.h b/quiche/quic/platform/api/quic_socket_address.h index 626a54d..37b368a 100644 --- a/quiche/quic/platform/api/quic_socket_address.h +++ b/quiche/quic/platform/api/quic_socket_address.h
@@ -5,62 +5,12 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_SOCKET_ADDRESS_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_SOCKET_ADDRESS_H_ -#include <string> - -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_ip_address.h" +#include "quiche/common/quiche_socket_address.h" namespace quic { -// A class representing a socket endpoint address (i.e., IP address plus a -// port) in QUIC. -class QUIC_EXPORT_PRIVATE QuicSocketAddress { - public: - QuicSocketAddress() {} - QuicSocketAddress(QuicIpAddress address, uint16_t port); - explicit QuicSocketAddress(const struct sockaddr_storage& saddr); - explicit QuicSocketAddress(const sockaddr* saddr, socklen_t len); - QuicSocketAddress(const QuicSocketAddress& other) = default; - QuicSocketAddress& operator=(const QuicSocketAddress& other) = default; - QuicSocketAddress& operator=(QuicSocketAddress&& other) = default; - QUIC_EXPORT_PRIVATE friend bool operator==(const QuicSocketAddress& lhs, - const QuicSocketAddress& rhs); - QUIC_EXPORT_PRIVATE friend bool operator!=(const QuicSocketAddress& lhs, - const QuicSocketAddress& rhs); - - bool IsInitialized() const; - std::string ToString() const; - - // TODO(ericorth): Convert usage over to socket_api::GetSocketAddress() and - // remove. - int FromSocket(int fd); - - QuicSocketAddress Normalized() const; - - QuicIpAddress host() const; - uint16_t port() const; - sockaddr_storage generic_address() const; - - // Hashes this address to an uint32_t. - uint32_t Hash() const; - - private: - QuicIpAddress host_; - uint16_t port_ = 0; -}; - -inline std::ostream& operator<<(std::ostream& os, - const QuicSocketAddress address) { - os << address.ToString(); - return os; -} - -class QUIC_EXPORT_PRIVATE QuicSocketAddressHash { - public: - size_t operator()(QuicSocketAddress const& address) const noexcept { - return address.Hash(); - } -}; +using QuicSocketAddress = ::quiche::QuicheSocketAddress; +using QuicSocketAddressHash = ::quiche::QuicheSocketAddressHash; } // namespace quic
diff --git a/quiche/quic/platform/api/quic_socket_address_test.cc b/quiche/quic/platform/api/quic_socket_address_test.cc deleted file mode 100644 index 9512c9f..0000000 --- a/quiche/quic/platform/api/quic_socket_address_test.cc +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "quiche/quic/platform/api/quic_socket_address.h" - -#include <memory> -#include <sstream> - -#include "quiche/quic/platform/api/quic_ip_address.h" -#include "quiche/quic/platform/api/quic_test.h" - -namespace quic { -namespace { - -TEST(QuicSocketAddress, Uninitialized) { - QuicSocketAddress uninitialized; - EXPECT_FALSE(uninitialized.IsInitialized()); -} - -TEST(QuicSocketAddress, ExplicitConstruction) { - QuicSocketAddress ipv4_address(QuicIpAddress::Loopback4(), 443); - QuicSocketAddress ipv6_address(QuicIpAddress::Loopback6(), 443); - EXPECT_TRUE(ipv4_address.IsInitialized()); - EXPECT_EQ("127.0.0.1:443", ipv4_address.ToString()); - EXPECT_EQ("[::1]:443", ipv6_address.ToString()); - EXPECT_EQ(QuicIpAddress::Loopback4(), ipv4_address.host()); - EXPECT_EQ(QuicIpAddress::Loopback6(), ipv6_address.host()); - EXPECT_EQ(443, ipv4_address.port()); -} - -TEST(QuicSocketAddress, OutputToStream) { - QuicSocketAddress ipv4_address(QuicIpAddress::Loopback4(), 443); - std::stringstream stream; - stream << ipv4_address; - EXPECT_EQ("127.0.0.1:443", stream.str()); -} - -TEST(QuicSocketAddress, FromSockaddrIPv4) { - union { - sockaddr_storage storage; - sockaddr addr; - sockaddr_in v4; - } address; - - memset(&address, 0, sizeof(address)); - address.v4.sin_family = AF_INET; - address.v4.sin_addr = QuicIpAddress::Loopback4().GetIPv4(); - address.v4.sin_port = htons(443); - EXPECT_EQ("127.0.0.1:443", - QuicSocketAddress(&address.addr, sizeof(address.v4)).ToString()); - EXPECT_EQ("127.0.0.1:443", QuicSocketAddress(address.storage).ToString()); -} - -TEST(QuicSocketAddress, FromSockaddrIPv6) { - union { - sockaddr_storage storage; - sockaddr addr; - sockaddr_in6 v6; - } address; - - memset(&address, 0, sizeof(address)); - address.v6.sin6_family = AF_INET6; - address.v6.sin6_addr = QuicIpAddress::Loopback6().GetIPv6(); - address.v6.sin6_port = htons(443); - EXPECT_EQ("[::1]:443", - QuicSocketAddress(&address.addr, sizeof(address.v6)).ToString()); - EXPECT_EQ("[::1]:443", QuicSocketAddress(address.storage).ToString()); -} - -TEST(QuicSocketAddres, ToSockaddrIPv4) { - union { - sockaddr_storage storage; - sockaddr_in v4; - } address; - - address.storage = - QuicSocketAddress(QuicIpAddress::Loopback4(), 443).generic_address(); - ASSERT_EQ(AF_INET, address.v4.sin_family); - EXPECT_EQ(QuicIpAddress::Loopback4(), QuicIpAddress(address.v4.sin_addr)); - EXPECT_EQ(htons(443), address.v4.sin_port); -} - -TEST(QuicSocketAddress, Normalize) { - QuicIpAddress dual_stacked; - ASSERT_TRUE(dual_stacked.FromString("::ffff:127.0.0.1")); - ASSERT_TRUE(dual_stacked.IsIPv6()); - QuicSocketAddress not_normalized(dual_stacked, 443); - QuicSocketAddress normalized = not_normalized.Normalized(); - EXPECT_EQ("[::ffff:127.0.0.1]:443", not_normalized.ToString()); - EXPECT_EQ("127.0.0.1:443", normalized.ToString()); -} - -// TODO(vasilvv): either ensure this works on all platforms, or deprecate and -// remove this API. -#if defined(__linux__) && !defined(ANDROID) -#include <errno.h> -#include <sys/socket.h> -#include <sys/types.h> - -TEST(QuicSocketAddress, FromSocket) { - int fd; - QuicSocketAddress address; - bool bound = false; - for (int port = 50000; port < 50400; port++) { - fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - ASSERT_GT(fd, 0); - - address = QuicSocketAddress(QuicIpAddress::Loopback6(), port); - sockaddr_storage raw_address = address.generic_address(); - int bind_result = bind(fd, reinterpret_cast<const sockaddr*>(&raw_address), - sizeof(sockaddr_in6)); - - if (bind_result < 0 && errno == EADDRINUSE) { - close(fd); - continue; - } - - ASSERT_EQ(0, bind_result); - bound = true; - break; - } - ASSERT_TRUE(bound); - - QuicSocketAddress real_address; - ASSERT_EQ(0, real_address.FromSocket(fd)); - ASSERT_TRUE(real_address.IsInitialized()); - EXPECT_EQ(real_address, address); - close(fd); -} -#endif - -} // namespace -} // namespace quic