Support enough of Windows to make EndToEndTest.SimpleRequestResponse pass.
PiperOrigin-RevId: 529755002
diff --git a/build/source_list.bzl b/build/source_list.bzl
index fd20c48..de04f82 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -665,6 +665,7 @@
"quic/core/quic_trace_visitor.cc",
"quic/core/quic_transmission_info.cc",
"quic/core/quic_types.cc",
+ "quic/core/quic_udp_socket.cc",
"quic/core/quic_unacked_packet_map.cc",
"quic/core/quic_utils.cc",
"quic/core/quic_version_manager.cc",
@@ -991,7 +992,6 @@
"quic/core/quic_default_packet_writer.cc",
"quic/core/quic_packet_reader.cc",
"quic/core/quic_syscall_wrapper.cc",
- "quic/core/quic_udp_socket_posix.cc",
"quic/masque/masque_client.cc",
"quic/masque/masque_client_session.cc",
"quic/masque/masque_client_tools.cc",
diff --git a/build/source_list.gni b/build/source_list.gni
index 4d34746..ac54fca 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -665,6 +665,7 @@
"src/quiche/quic/core/quic_trace_visitor.cc",
"src/quiche/quic/core/quic_transmission_info.cc",
"src/quiche/quic/core/quic_types.cc",
+ "src/quiche/quic/core/quic_udp_socket.cc",
"src/quiche/quic/core/quic_unacked_packet_map.cc",
"src/quiche/quic/core/quic_utils.cc",
"src/quiche/quic/core/quic_version_manager.cc",
@@ -991,7 +992,6 @@
"src/quiche/quic/core/quic_default_packet_writer.cc",
"src/quiche/quic/core/quic_packet_reader.cc",
"src/quiche/quic/core/quic_syscall_wrapper.cc",
- "src/quiche/quic/core/quic_udp_socket_posix.cc",
"src/quiche/quic/masque/masque_client.cc",
"src/quiche/quic/masque/masque_client_session.cc",
"src/quiche/quic/masque/masque_client_tools.cc",
diff --git a/build/source_list.json b/build/source_list.json
index d9867f7..4465eeb 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -664,6 +664,7 @@
"quiche/quic/core/quic_trace_visitor.cc",
"quiche/quic/core/quic_transmission_info.cc",
"quiche/quic/core/quic_types.cc",
+ "quiche/quic/core/quic_udp_socket.cc",
"quiche/quic/core/quic_unacked_packet_map.cc",
"quiche/quic/core/quic_utils.cc",
"quiche/quic/core/quic_version_manager.cc",
@@ -990,7 +991,6 @@
"quiche/quic/core/quic_default_packet_writer.cc",
"quiche/quic/core/quic_packet_reader.cc",
"quiche/quic/core/quic_syscall_wrapper.cc",
- "quiche/quic/core/quic_udp_socket_posix.cc",
"quiche/quic/masque/masque_client.cc",
"quiche/quic/masque/masque_client_session.cc",
"quiche/quic/masque/masque_client_tools.cc",
diff --git a/quiche/quic/core/io/socket.h b/quiche/quic/core/io/socket.h
index d428f8c..8fc7732 100644
--- a/quiche/quic/core/io/socket.h
+++ b/quiche/quic/core/io/socket.h
@@ -28,9 +28,11 @@
#if defined(_WIN32)
using SocketFd = SOCKET;
inline constexpr SocketFd kInvalidSocketFd = INVALID_SOCKET;
+inline constexpr int kSocketErrorMsgSize = WSAEMSGSIZE;
#else
using SocketFd = int;
inline constexpr SocketFd kInvalidSocketFd = -1;
+inline constexpr int kSocketErrorMsgSize = EMSGSIZE;
#endif
// Low-level platform-agnostic socket operations. Closely follows the behavior
diff --git a/quiche/quic/core/quic_default_packet_writer.cc b/quiche/quic/core/quic_default_packet_writer.cc
index 78feee5..7eac827 100644
--- a/quiche/quic/core/quic_default_packet_writer.cc
+++ b/quiche/quic/core/quic_default_packet_writer.cc
@@ -8,7 +8,7 @@
namespace quic {
-QuicDefaultPacketWriter::QuicDefaultPacketWriter(int fd)
+QuicDefaultPacketWriter::QuicDefaultPacketWriter(SocketFd fd)
: fd_(fd), write_blocked_(false) {}
QuicDefaultPacketWriter::~QuicDefaultPacketWriter() = default;
@@ -36,7 +36,7 @@
void QuicDefaultPacketWriter::SetWritable() { write_blocked_ = false; }
absl::optional<int> QuicDefaultPacketWriter::MessageTooBigErrorCode() const {
- return EMSGSIZE;
+ return kSocketErrorMsgSize;
}
QuicByteCount QuicDefaultPacketWriter::GetMaxPacketSize(
diff --git a/quiche/quic/core/quic_default_packet_writer.h b/quiche/quic/core/quic_default_packet_writer.h
index b2a0a86..718f8eb 100644
--- a/quiche/quic/core/quic_default_packet_writer.h
+++ b/quiche/quic/core/quic_default_packet_writer.h
@@ -7,6 +7,7 @@
#include <cstddef>
+#include "quiche/quic/core/io/socket.h"
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
@@ -18,7 +19,7 @@
// Default packet writer which wraps QuicSocketUtils WritePacket.
class QUIC_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
public:
- explicit QuicDefaultPacketWriter(int fd);
+ explicit QuicDefaultPacketWriter(SocketFd fd);
QuicDefaultPacketWriter(const QuicDefaultPacketWriter&) = delete;
QuicDefaultPacketWriter& operator=(const QuicDefaultPacketWriter&) = delete;
~QuicDefaultPacketWriter() override;
@@ -40,14 +41,14 @@
const QuicSocketAddress& peer_address) override;
WriteResult Flush() override;
- void set_fd(int fd) { fd_ = fd; }
+ void set_fd(SocketFd fd) { fd_ = fd; }
protected:
void set_write_blocked(bool is_blocked);
- int fd() { return fd_; }
+ SocketFd fd() { return fd_; }
private:
- int fd_;
+ SocketFd fd_;
bool write_blocked_;
};
diff --git a/quiche/quic/core/quic_udp_socket.cc b/quiche/quic/core/quic_udp_socket.cc
new file mode 100644
index 0000000..1a35b72
--- /dev/null
+++ b/quiche/quic/core/quic_udp_socket.cc
@@ -0,0 +1,205 @@
+// Copyright 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.
+
+#if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
+// This must be defined before including any system headers.
+#define __APPLE_USE_RFC_3542
+#endif // defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
+
+#include "absl/base/optimization.h"
+#include "quiche/quic/core/io/socket.h"
+#include "quiche/quic/core/quic_udp_socket.h"
+#include "quiche/quic/platform/api/quic_bug_tracker.h"
+#include "quiche/quic/platform/api/quic_flag_utils.h"
+
+// Common cmsg-related functions are defined below.
+// Windows and POSIX cmsg formats are actually fairly similar, except the
+// Windows ones have all of the macros prefixed with WSA_ and all the type names
+// are different.
+
+namespace quic {
+namespace {
+
+#if defined(_WIN32)
+using PlatformCmsghdr = ::WSACMSGHDR;
+#if !defined(CMSG_DATA)
+#define CMSG_DATA WSA_CMSG_DATA
+#endif // !defined(CMSG_DATA)
+#else
+using PlatformCmsghdr = ::cmsghdr;
+#endif // defined(_WIN32)
+
+void PopulatePacketInfoFromControlMessageBase(
+ PlatformCmsghdr* cmsg, QuicUdpPacketInfo* packet_info,
+ BitMask64 packet_info_interested) {
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+ const in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
+ const char* addr_data = reinterpret_cast<const char*>(&info->ipi6_addr);
+ int addr_len = sizeof(in6_addr);
+ QuicIpAddress self_v6_ip;
+ if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
+ packet_info->SetSelfV6Ip(self_v6_ip);
+ } else {
+ QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
+ }
+ }
+ return;
+ }
+
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+ const in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
+ const char* addr_data = reinterpret_cast<const char*>(&info->ipi_addr);
+ int addr_len = sizeof(in_addr);
+ QuicIpAddress self_v4_ip;
+ if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
+ packet_info->SetSelfV4Ip(self_v4_ip);
+ } else {
+ QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
+ }
+ }
+ return;
+ }
+}
+
+} // namespace
+} // namespace quic
+
+#if defined(_WIN32)
+#include "quiche/quic/core/quic_udp_socket_win.inc"
+#else
+#include "quiche/quic/core/quic_udp_socket_posix.inc"
+#endif
+
+namespace quic {
+
+QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
+ int receive_buffer_size,
+ int send_buffer_size, bool ipv6_only) {
+ // QUICHE_DCHECK here so the program exits early(before reading packets) in
+ // debug mode. This should have been a static_assert, however it can't be done
+ // on ios/osx because CMSG_SPACE isn't a constant expression there.
+ QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
+
+ absl::StatusOr<SocketFd> socket = socket_api::CreateSocket(
+ quiche::FromPlatformAddressFamily(address_family),
+ socket_api::SocketProtocol::kUdp,
+ /*blocking=*/false);
+
+ if (!socket.ok()) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "UDP non-blocking socket creation for address_family="
+ << address_family << " failed: " << socket.status();
+ return kQuicInvalidSocketFd;
+ }
+
+#if !defined(_WIN32)
+ SetGoogleSocketOptions(socket.value());
+#endif
+
+ if (!SetupSocket(socket.value(), address_family, receive_buffer_size,
+ send_buffer_size, ipv6_only)) {
+ Destroy(socket.value());
+ return kQuicInvalidSocketFd;
+ }
+
+ return socket.value();
+}
+
+void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd) {
+ if (fd != kQuicInvalidSocketFd) {
+ absl::Status result = socket_api::Close(fd);
+ if (!result.ok()) {
+ QUIC_LOG_FIRST_N(WARNING, 100)
+ << "Failed to close UDP socket with error " << result;
+ }
+ }
+}
+
+bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address) {
+ sockaddr_storage addr = address.generic_address();
+ int addr_len =
+ address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
+ return 0 == bind(fd, reinterpret_cast<sockaddr*>(&addr), addr_len);
+}
+
+bool QuicUdpSocketApi::BindInterface(QuicUdpSocketFd fd,
+ const std::string& interface_name) {
+#if defined(__linux__) && !defined(__ANDROID_API__)
+ if (interface_name.empty() || interface_name.size() >= IFNAMSIZ) {
+ QUIC_BUG(udp_bad_interface_name)
+ << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
+ return false;
+ }
+
+ return 0 == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+ interface_name.c_str(), interface_name.length());
+#else
+ (void)fd;
+ (void)interface_name;
+ QUIC_BUG(interface_bind_not_implemented)
+ << "Interface binding is not implemented on this platform";
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd) {
+#if defined(__linux__) && defined(SO_RXQ_OVFL)
+ int get_overflow = 1;
+ return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
+ sizeof(get_overflow));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd) {
+ int get_self_ip = 1;
+ return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO,
+ reinterpret_cast<char*>(&get_self_ip),
+ sizeof(get_self_ip));
+}
+
+bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd) {
+ int get_self_ip = 1;
+ return 0 == setsockopt(fd, IPPROTO_IPV6, kIpv6RecvPacketInfo,
+ reinterpret_cast<char*>(&get_self_ip),
+ sizeof(get_self_ip));
+}
+
+bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd) {
+#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
+ int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
+ return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
+ sizeof(timestamping));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd) {
+#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
+ int get_ttl = 1;
+ return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd) {
+#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
+ int get_ttl = 1;
+ return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
+ sizeof(get_ttl));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+} // namespace quic
diff --git a/quiche/quic/core/quic_udp_socket_posix.cc b/quiche/quic/core/quic_udp_socket_posix.inc
similarity index 77%
rename from quiche/quic/core/quic_udp_socket_posix.cc
rename to quiche/quic/core/quic_udp_socket_posix.inc
index 26d4ef4..deb406c 100644
--- a/quiche/quic/core/quic_udp_socket_posix.cc
+++ b/quiche/quic/core/quic_udp_socket_posix.inc
@@ -2,12 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "quiche/quic/core/quic_types.h"
-#if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
-// This must be defined before including any system headers.
-#define __APPLE_USE_RFC_3542
-#endif // defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
-
#include <arpa/inet.h>
#include <fcntl.h>
#include <net/if.h>
@@ -43,6 +37,8 @@
// Explicit Congestion Notification is the last two bits of the TOS byte.
constexpr uint8_t kEcnMask = 0x03;
+constexpr int kIpv6RecvPacketInfo = IPV6_RECVPKTINFO;
+
#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
#define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1
// This is the structure that SO_TIMESTAMPING fills into the cmsg header.
@@ -125,35 +121,8 @@
}
#endif
- if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
- if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP)) {
- const in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
- const char* addr_data = reinterpret_cast<const char*>(&info->ipi6_addr);
- int addr_len = sizeof(in6_addr);
- QuicIpAddress self_v6_ip;
- if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
- packet_info->SetSelfV6Ip(self_v6_ip);
- } else {
- QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
- }
- }
- return;
- }
-
- if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
- if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP)) {
- const in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
- const char* addr_data = reinterpret_cast<const char*>(&info->ipi_addr);
- int addr_len = sizeof(in_addr);
- QuicIpAddress self_v4_ip;
- if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
- packet_info->SetSelfV4Ip(self_v4_ip);
- } else {
- QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
- }
- }
- return;
- }
+ PopulatePacketInfoFromControlMessageBase(cmsg, packet_info,
+ packet_info_interested);
if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) ||
(cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT)) {
@@ -214,37 +183,6 @@
}
} // namespace
-QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
- int receive_buffer_size,
- int send_buffer_size, bool ipv6_only) {
- // QUICHE_DCHECK here so the program exits early(before reading packets) in
- // debug mode. This should have been a static_assert, however it can't be done
- // on ios/osx because CMSG_SPACE isn't a constant expression there.
- QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
-
- absl::StatusOr<SocketFd> socket = socket_api::CreateSocket(
- quiche::FromPlatformAddressFamily(address_family),
- socket_api::SocketProtocol::kUdp,
- /*blocking=*/false);
-
- if (!socket.ok()) {
- QUIC_LOG_FIRST_N(ERROR, 100)
- << "UDP non-blocking socket creation for address_family="
- << address_family << " failed: " << socket.status();
- return kQuicInvalidSocketFd;
- }
-
- SetGoogleSocketOptions(socket.value());
-
- if (!SetupSocket(socket.value(), address_family, receive_buffer_size,
- send_buffer_size, ipv6_only)) {
- Destroy(socket.value());
- return kQuicInvalidSocketFd;
- }
-
- return socket.value();
-}
-
bool QuicUdpSocketApi::SetupSocket(QuicUdpSocketFd fd, int address_family,
int receive_buffer_size,
int send_buffer_size, bool ipv6_only) {
@@ -298,98 +236,6 @@
return true;
}
-void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd) {
- if (fd != kQuicInvalidSocketFd) {
- absl::Status result = socket_api::Close(fd);
- if (!result.ok()) {
- QUIC_LOG_FIRST_N(WARNING, 100)
- << "Failed to close UDP socket with error " << result;
- }
- }
-}
-
-bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address) {
- sockaddr_storage addr = address.generic_address();
- int addr_len =
- address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
- return 0 == bind(fd, reinterpret_cast<sockaddr*>(&addr), addr_len);
-}
-
-bool QuicUdpSocketApi::BindInterface(QuicUdpSocketFd fd,
- const std::string& interface_name) {
-#if defined(__linux__) && !defined(__ANDROID_API__)
- if (interface_name.empty() || interface_name.size() >= IFNAMSIZ) {
- QUIC_BUG(udp_bad_interface_name)
- << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
- return false;
- }
-
- return 0 == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
- interface_name.c_str(), interface_name.length());
-#else
- (void)fd;
- (void)interface_name;
- QUIC_BUG(interface_bind_not_implemented)
- << "Interface binding is not implemented on this platform";
- return false;
-#endif
-}
-
-bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd) {
-#if defined(__linux__) && defined(SO_RXQ_OVFL)
- int get_overflow = 1;
- return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
- sizeof(get_overflow));
-#else
- (void)fd;
- return false;
-#endif
-}
-
-bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd) {
- int get_self_ip = 1;
- return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_self_ip,
- sizeof(get_self_ip));
-}
-
-bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd) {
- int get_self_ip = 1;
- return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_self_ip,
- sizeof(get_self_ip));
-}
-
-bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd) {
-#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
- int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
- return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
- sizeof(timestamping));
-#else
- (void)fd;
- return false;
-#endif
-}
-
-bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd) {
-#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
- int get_ttl = 1;
- return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
-#else
- (void)fd;
- return false;
-#endif
-}
-
-bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd) {
-#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
- int get_ttl = 1;
- return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
- sizeof(get_ttl));
-#else
- (void)fd;
- return false;
-#endif
-}
-
bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
QuicTime::Delta timeout) {
fd_set read_fds;
diff --git a/quiche/quic/core/quic_udp_socket_win.inc b/quiche/quic/core/quic_udp_socket_win.inc
new file mode 100644
index 0000000..429b8c7
--- /dev/null
+++ b/quiche/quic/core/quic_udp_socket_win.inc
@@ -0,0 +1,281 @@
+// Copyright 2023 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.
+
+// UDP socket implementation for Windows. Feature overview:
+// * Supported: setting and getting self IP address.
+// * Unsupported but could work on a sufficiently new Windows version:
+// - Timestamping
+// - Setting and getting TTL.
+
+#include <mswsock.h>
+#include <winsock2.h>
+
+#include <cstddef>
+
+#include "quiche/quic/core/quic_utils.h"
+
+namespace quic {
+
+namespace {
+constexpr size_t kMinCmsgSpaceForRead =
+ CMSG_SPACE(sizeof(in_pktinfo)) // V4 Self IP
+ + CMSG_SPACE(sizeof(in6_pktinfo)); // V6 Self IP
+
+constexpr int kIpv6RecvPacketInfo = IPV6_PKTINFO;
+
+void SetV4SelfIpInControlMessage(const QuicIpAddress& self_address,
+ WSACMSGHDR* cmsg) {
+ QUICHE_DCHECK(self_address.IsIPv4());
+ in_pktinfo* pktinfo = reinterpret_cast<in_pktinfo*>(WSA_CMSG_DATA(cmsg));
+ memset(pktinfo, 0, sizeof(in_pktinfo));
+ pktinfo->ipi_addr = self_address.GetIPv4();
+}
+
+void SetV6SelfIpInControlMessage(const QuicIpAddress& self_address,
+ cmsghdr* cmsg) {
+ QUICHE_DCHECK(self_address.IsIPv6());
+ in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(WSA_CMSG_DATA(cmsg));
+ memset(pktinfo, 0, sizeof(in6_pktinfo));
+ pktinfo->ipi6_addr = self_address.GetIPv6();
+}
+
+bool NextCmsg(WSAMSG* hdr, char* control_buffer, size_t control_buffer_len,
+ int cmsg_level, int cmsg_type, size_t data_size,
+ WSACMSGHDR** cmsg /*in, out*/) {
+ // msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will
+ // return nullptr.
+ hdr->Control.len += WSA_CMSG_SPACE(data_size);
+ if (hdr->Control.len > control_buffer_len) {
+ return false;
+ }
+
+ if ((*cmsg) == nullptr) {
+ QUICHE_DCHECK_EQ(nullptr, hdr->Control.buf);
+ memset(control_buffer, 0, control_buffer_len);
+ hdr->Control.buf = control_buffer;
+ (*cmsg) = WSA_CMSG_FIRSTHDR(hdr);
+ } else {
+ QUICHE_DCHECK_NE(nullptr, hdr->Control.buf);
+ (*cmsg) = WSA_CMSG_NXTHDR(hdr, (*cmsg));
+ }
+
+ if (nullptr == (*cmsg)) {
+ return false;
+ }
+
+ (*cmsg)->cmsg_len = WSA_CMSG_LEN(data_size);
+ (*cmsg)->cmsg_level = cmsg_level;
+ (*cmsg)->cmsg_type = cmsg_type;
+
+ return true;
+}
+} // namespace
+
+bool QuicUdpSocketApi::SetupSocket(QuicUdpSocketFd fd, int address_family,
+ int receive_buffer_size,
+ int send_buffer_size, bool /*ipv6_only*/) {
+ // Receive buffer size.
+ if (absl::Status status =
+ socket_api::SetReceiveBufferSize(fd, receive_buffer_size);
+ !status.ok()) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Failed to set socket recv size: " << status;
+ return false;
+ }
+
+ // Send buffer size.
+ if (absl::Status status = socket_api::SetSendBufferSize(fd, send_buffer_size);
+ !status.ok()) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Failed to set socket send size: " << status;
+ return false;
+ }
+
+ if (address_family == AF_INET) {
+ if (!EnableReceiveSelfIpAddressForV4(fd)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Failed to enable receiving of self v4 ip";
+ return false;
+ }
+ }
+
+ if (address_family == AF_INET6) {
+ if (!EnableReceiveSelfIpAddressForV6(fd)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Failed to enable receiving of self v6 ip";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResult* result) {
+ result->ok = false;
+
+ // WSARecvMsg is an extension to Windows Socket API that requires us to fetch
+ // the function pointer via an ioctl.
+ DWORD recvmsg_fn_out_bytes;
+ LPFN_WSARECVMSG recvmsg_fn = nullptr;
+ GUID recvmsg_guid = WSAID_WSARECVMSG;
+ int ioctl_result =
+ WSAIoctl(fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &recvmsg_guid,
+ sizeof(recvmsg_guid), &recvmsg_fn, sizeof(recvmsg_fn),
+ &recvmsg_fn_out_bytes, nullptr, nullptr);
+ if (ioctl_result != 0) {
+ QUICHE_LOG(ERROR) << "Failed to load WSARecvMsg() function, error code: "
+ << WSAGetLastError();
+ return;
+ }
+
+ BufferSpan& packet_buffer = result->packet_buffer;
+ BufferSpan& control_buffer = result->control_buffer;
+ QuicUdpPacketInfo* packet_info = &result->packet_info;
+
+ QUICHE_DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
+
+ WSABUF iov;
+ iov.buf = packet_buffer.buffer;
+ iov.len = packet_buffer.buffer_len;
+ sockaddr_storage raw_peer_address;
+
+ if (control_buffer.buffer_len > 0) {
+ reinterpret_cast<WSACMSGHDR*>(control_buffer.buffer)->cmsg_len =
+ control_buffer.buffer_len;
+ }
+
+ WSAMSG hdr;
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.name = reinterpret_cast<sockaddr*>(&raw_peer_address);
+ hdr.namelen = sizeof(raw_peer_address);
+ hdr.lpBuffers = &iov;
+ hdr.dwBufferCount = 1;
+ hdr.dwFlags = 0;
+ hdr.Control.buf = control_buffer.buffer;
+ hdr.Control.len = control_buffer.buffer_len;
+
+ DWORD bytes_read;
+ int recvmsg_result = recvmsg_fn(fd, &hdr, &bytes_read, nullptr, nullptr);
+ if (recvmsg_result != 0) {
+ const int error_num = WSAGetLastError();
+ if (error_num != WSAEWOULDBLOCK) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Error reading packet: " << error_num;
+ }
+ return;
+ }
+
+ packet_buffer.buffer_len = bytes_read;
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ packet_info->SetPeerAddress(QuicSocketAddress(raw_peer_address));
+ }
+
+ if (hdr.Control.len > 0) {
+ for (WSACMSGHDR* cmsg = WSA_CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
+ cmsg = WSA_CMSG_NXTHDR(&hdr, cmsg)) {
+ BitMask64 prior_bitmask = packet_info->bitmask();
+ PopulatePacketInfoFromControlMessageBase(cmsg, packet_info,
+ packet_info_interested);
+ if (packet_info->bitmask() == prior_bitmask) {
+ QUIC_DLOG(INFO) << "Ignored cmsg_level:" << cmsg->cmsg_level
+ << ", cmsg_type:" << cmsg->cmsg_type;
+ }
+ }
+ }
+
+ result->ok = true;
+}
+
+size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResults* results) {
+ size_t num_packets = 0;
+ for (ReadPacketResult& result : *results) {
+ result.ok = false;
+ }
+ for (ReadPacketResult& result : *results) {
+ ReadPacket(fd, packet_info_interested, &result);
+ if (!result.ok && WSAGetLastError() == WSAEWOULDBLOCK) {
+ break;
+ }
+ ++num_packets;
+ }
+ return num_packets;
+}
+
+WriteResult QuicUdpSocketApi::WritePacket(
+ QuicUdpSocketFd fd, const char* packet_buffer, size_t packet_buffer_len,
+ const QuicUdpPacketInfo& packet_info) {
+ if (!packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ return WriteResult(WRITE_STATUS_ERROR, WSAEINVAL);
+ }
+
+ char control_buffer[512];
+ sockaddr_storage raw_peer_address =
+ packet_info.peer_address().generic_address();
+ WSABUF iov;
+ iov.buf = const_cast<char*>(packet_buffer);
+ iov.len = packet_buffer_len;
+
+ WSAMSG hdr;
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.name = reinterpret_cast<sockaddr*>(&raw_peer_address);
+ hdr.namelen = packet_info.peer_address().host().IsIPv4()
+ ? sizeof(sockaddr_in)
+ : sizeof(sockaddr_in6);
+ hdr.lpBuffers = &iov;
+ hdr.dwBufferCount = 1;
+
+ WSACMSGHDR* cmsg = nullptr;
+
+ // Set self IP.
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP) &&
+ packet_info.self_v4_ip().IsInitialized()) {
+ if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IP,
+ IP_PKTINFO, sizeof(in_pktinfo), &cmsg)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Not enough buffer to set self v4 ip address.";
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+ SetV4SelfIpInControlMessage(packet_info.self_v4_ip(), cmsg);
+ } else if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP) &&
+ packet_info.self_v6_ip().IsInitialized()) {
+ if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IPV6,
+ IPV6_PKTINFO, sizeof(in6_pktinfo), &cmsg)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Not enough buffer to set self v6 ip address.";
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+ SetV6SelfIpInControlMessage(packet_info.self_v6_ip(), cmsg);
+ }
+
+ DWORD bytes_sent;
+ int result =
+ WSASendMsg(fd, &hdr, /*dwFlags=*/0, &bytes_sent, nullptr, nullptr);
+ if (result == 0) {
+ return WriteResult(WRITE_STATUS_OK, bytes_sent);
+ }
+ int error = WSAGetLastError();
+ return WriteResult(
+ (error == WSAEWOULDBLOCK) ? WRITE_STATUS_BLOCKED : WRITE_STATUS_ERROR,
+ error);
+}
+
+bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
+ QuicTime::Delta timeout) {
+ WSAPOLLFD polled_fd;
+ polled_fd.fd = fd;
+ polled_fd.events = POLLIN;
+ polled_fd.revents = 0;
+
+ int result = ::WSAPoll(&polled_fd, 1, timeout.ToMilliseconds());
+ if (result == SOCKET_ERROR) {
+ QUICHE_LOG(ERROR) << "Error while calling WSAPoll(): " << WSAGetLastError();
+ }
+
+ return result > 0;
+}
+
+} // namespace quic
diff --git a/quiche/quic/test_tools/quic_server_peer.cc b/quiche/quic/test_tools/quic_server_peer.cc
index 6f6c8f9..4ef81fb 100644
--- a/quiche/quic/test_tools/quic_server_peer.cc
+++ b/quiche/quic/test_tools/quic_server_peer.cc
@@ -14,8 +14,8 @@
// static
bool QuicServerPeer::SetSmallSocket(QuicServer* server) {
int size = 1024 * 10;
- return setsockopt(server->fd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) !=
- -1;
+ return setsockopt(server->fd_, SOL_SOCKET, SO_RCVBUF,
+ reinterpret_cast<char*>(&size), sizeof(size)) != -1;
}
// static
diff --git a/quiche/quic/test_tools/quic_test_client.cc b/quiche/quic/test_tools/quic_test_client.cc
index a617348..1f17227 100644
--- a/quiche/quic/test_tools/quic_test_client.cc
+++ b/quiche/quic/test_tools/quic_test_client.cc
@@ -365,7 +365,7 @@
client_->SetUserAgentID(user_agent_id);
}
-ssize_t QuicTestClient::SendRequest(const std::string& uri) {
+int64_t QuicTestClient::SendRequest(const std::string& uri) {
spdy::Http2HeaderBlock headers;
if (!PopulateHeaderBlockFromUrl(uri, &headers)) {
return 0;
@@ -373,7 +373,7 @@
return SendMessage(headers, "");
}
-ssize_t QuicTestClient::SendRequestAndRstTogether(const std::string& uri) {
+int64_t QuicTestClient::SendRequestAndRstTogether(const std::string& uri) {
spdy::Http2HeaderBlock headers;
if (!PopulateHeaderBlockFromUrl(uri, &headers)) {
return 0;
@@ -381,7 +381,7 @@
QuicSpdyClientSession* session = client()->client_session();
QuicConnection::ScopedPacketFlusher flusher(session->connection());
- ssize_t ret = SendMessage(headers, "", /*fin=*/true, /*flush=*/false);
+ int64_t ret = SendMessage(headers, "", /*fin=*/true, /*flush=*/false);
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(
session->transport_version(), 0);
@@ -398,7 +398,7 @@
}
}
-ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
+int64_t QuicTestClient::GetOrCreateStreamAndSendRequest(
const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin,
quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
ack_listener) {
@@ -426,7 +426,7 @@
}
QuicSpdyStreamPeer::set_ack_listener(stream, ack_listener);
- ssize_t ret = 0;
+ int64_t ret = 0;
if (headers != nullptr) {
spdy::Http2HeaderBlock spdy_headers(headers->Clone());
if (spdy_headers[":authority"].as_string().empty()) {
@@ -441,23 +441,23 @@
return ret;
}
-ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
+int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body) {
return SendMessage(headers, body, /*fin=*/true);
}
-ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
+int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body, bool fin) {
return SendMessage(headers, body, fin, /*flush=*/true);
}
-ssize_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
+int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body, bool fin,
bool flush) {
// Always force creation of a stream for SendMessage.
latest_created_stream_ = nullptr;
- ssize_t ret = GetOrCreateStreamAndSendRequest(&headers, body, fin, nullptr);
+ int64_t ret = GetOrCreateStreamAndSendRequest(&headers, body, fin, nullptr);
if (flush) {
WaitForWriteToFlush();
@@ -465,11 +465,11 @@
return ret;
}
-ssize_t QuicTestClient::SendData(const std::string& data, bool last_data) {
+int64_t QuicTestClient::SendData(const std::string& data, bool last_data) {
return SendData(data, last_data, nullptr);
}
-ssize_t QuicTestClient::SendData(
+int64_t QuicTestClient::SendData(
const std::string& data, bool last_data,
quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
ack_listener) {
@@ -645,7 +645,7 @@
return true;
}
-ssize_t QuicTestClient::Send(absl::string_view data) {
+int64_t QuicTestClient::Send(absl::string_view data) {
return SendData(std::string(data), false);
}
diff --git a/quiche/quic/test_tools/quic_test_client.h b/quiche/quic/test_tools/quic_test_client.h
index 9abab23..9f2a869 100644
--- a/quiche/quic/test_tools/quic_test_client.h
+++ b/quiche/quic/test_tools/quic_test_client.h
@@ -115,18 +115,18 @@
void SetUserAgentID(const std::string& user_agent_id);
// Wraps data in a quic packet and sends it.
- ssize_t SendData(const std::string& data, bool last_data);
+ int64_t SendData(const std::string& data, bool last_data);
// As above, but |delegate| will be notified when |data| is ACKed.
- ssize_t SendData(
+ int64_t SendData(
const std::string& data, bool last_data,
quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
ack_listener);
// Clears any outstanding state and sends a simple GET of 'uri' to the
// server. Returns 0 if the request failed and no bytes were written.
- ssize_t SendRequest(const std::string& uri);
+ int64_t SendRequest(const std::string& uri);
// Send a request R and a RST_FRAME which resets R, in the same packet.
- ssize_t SendRequestAndRstTogether(const std::string& uri);
+ int64_t SendRequestAndRstTogether(const std::string& uri);
// Sends requests for all the urls and waits for the responses. To process
// the individual responses as they are returned, the caller should use the
// set the response_listener on the client().
@@ -134,18 +134,18 @@
const std::vector<std::string>& url_list);
// Sends a request containing |headers| and |body| and returns the number of
// bytes sent (the size of the serialized request headers and body).
- ssize_t SendMessage(const spdy::Http2HeaderBlock& headers,
+ int64_t SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body);
// Sends a request containing |headers| and |body| with the fin bit set to
// |fin| and returns the number of bytes sent (the size of the serialized
// request headers and body).
- ssize_t SendMessage(const spdy::Http2HeaderBlock& headers,
+ int64_t SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body, bool fin);
// Sends a request containing |headers| and |body| with the fin bit set to
// |fin| and returns the number of bytes sent (the size of the serialized
// request headers and body). If |flush| is true, will wait for the message to
// be flushed before returning.
- ssize_t SendMessage(const spdy::Http2HeaderBlock& headers,
+ int64_t SendMessage(const spdy::Http2HeaderBlock& headers,
absl::string_view body, bool fin, bool flush);
// Sends a request containing |headers| and |body|, waits for the response,
// and returns the response body.
@@ -161,7 +161,7 @@
QuicSocketAddress local_address() const;
void ClearPerRequestState();
bool WaitUntil(int timeout_ms, std::function<bool()> trigger);
- ssize_t Send(absl::string_view data);
+ int64_t Send(absl::string_view data);
bool connected() const;
bool buffer_body() const;
void set_buffer_body(bool buffer_body);
@@ -259,7 +259,7 @@
// Calls GetOrCreateStream(), sends the request on the stream, and
// stores the request in case it needs to be resent. If |headers| is
// null, only the body will be sent on the stream.
- ssize_t GetOrCreateStreamAndSendRequest(
+ int64_t GetOrCreateStreamAndSendRequest(
const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin,
quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
ack_listener);
diff --git a/quiche/quic/tools/quic_client_default_network_helper.cc b/quiche/quic/tools/quic_client_default_network_helper.cc
index ab9e1b1..424b8b9 100644
--- a/quiche/quic/tools/quic_client_default_network_helper.cc
+++ b/quiche/quic/tools/quic_client_default_network_helper.cc
@@ -22,7 +22,7 @@
// listener whenever the socket gets blocked.
class LevelTriggeredPacketWriter : public QuicDefaultPacketWriter {
public:
- explicit LevelTriggeredPacketWriter(int fd, QuicEventLoop* event_loop)
+ explicit LevelTriggeredPacketWriter(SocketFd fd, QuicEventLoop* event_loop)
: QuicDefaultPacketWriter(fd), event_loop_(event_loop) {
QUICHE_DCHECK(!event_loop->SupportsEdgeTriggered());
}
@@ -68,11 +68,11 @@
bool QuicClientDefaultNetworkHelper::CreateUDPSocketAndBind(
QuicSocketAddress server_address, QuicIpAddress bind_to_address,
int bind_to_port) {
- int fd = CreateUDPSocket(server_address, &overflow_supported_);
- if (fd < 0) {
+ SocketFd fd = CreateUDPSocket(server_address, &overflow_supported_);
+ if (fd == kInvalidSocketFd) {
return false;
}
- auto closer = absl::MakeCleanup([fd] { close(fd); });
+ auto closer = absl::MakeCleanup([fd] { (void)socket_api::Close(fd); });
QuicSocketAddress client_address;
if (bind_to_address.IsInitialized()) {
@@ -124,7 +124,7 @@
return false;
}
-void QuicClientDefaultNetworkHelper::CleanUpUDPSocket(int fd) {
+void QuicClientDefaultNetworkHelper::CleanUpUDPSocket(SocketFd fd) {
CleanUpUDPSocketImpl(fd);
fd_address_map_.erase(fd);
}
@@ -136,12 +136,12 @@
fd_address_map_.clear();
}
-void QuicClientDefaultNetworkHelper::CleanUpUDPSocketImpl(int fd) {
- if (fd > -1) {
+void QuicClientDefaultNetworkHelper::CleanUpUDPSocketImpl(SocketFd fd) {
+ if (fd != kInvalidSocketFd) {
bool success = event_loop_->UnregisterSocket(fd);
QUICHE_DCHECK(success || fds_unregistered_externally_);
- int rc = close(fd);
- QUICHE_DCHECK_EQ(0, rc);
+ absl::Status rc = socket_api::Close(fd);
+ QUICHE_DCHECK(rc.ok()) << rc;
}
}
@@ -207,7 +207,7 @@
return fd_address_map_.back().second;
}
-int QuicClientDefaultNetworkHelper::GetLatestFD() const {
+SocketFd QuicClientDefaultNetworkHelper::GetLatestFD() const {
if (fd_address_map_.empty()) {
return -1;
}
@@ -221,13 +221,13 @@
client_->session()->ProcessUdpPacket(self_address, peer_address, packet);
}
-int QuicClientDefaultNetworkHelper::CreateUDPSocket(
+SocketFd QuicClientDefaultNetworkHelper::CreateUDPSocket(
QuicSocketAddress server_address, bool* overflow_supported) {
QuicUdpSocketApi api;
- int fd = api.Create(server_address.host().AddressFamilyToInt(),
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
- if (fd < 0) {
+ SocketFd fd = api.Create(server_address.host().AddressFamilyToInt(),
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ if (fd == kInvalidSocketFd) {
return fd;
}
@@ -242,7 +242,7 @@
return fd;
}
-bool QuicClientDefaultNetworkHelper::BindInterfaceNameIfNeeded(int fd) {
+bool QuicClientDefaultNetworkHelper::BindInterfaceNameIfNeeded(SocketFd fd) {
QuicUdpSocketApi api;
std::string interface_name = client_->interface_name();
if (!interface_name.empty()) {
diff --git a/quiche/quic/tools/quic_client_default_network_helper.h b/quiche/quic/tools/quic_client_default_network_helper.h
index 07b0753..f62bd80 100644
--- a/quiche/quic/tools/quic_client_default_network_helper.h
+++ b/quiche/quic/tools/quic_client_default_network_helper.h
@@ -58,20 +58,19 @@
// Accessors provided for convenience, not part of any interface.
QuicEventLoop* event_loop() { return event_loop_; }
- const quiche::QuicheLinkedHashMap<int, QuicSocketAddress>& fd_address_map()
- const {
+ const quiche::QuicheLinkedHashMap<SocketFd, QuicSocketAddress>&
+ fd_address_map() const {
return fd_address_map_;
}
// If the client has at least one UDP socket, return the latest created one.
// Otherwise, return -1.
- int GetLatestFD() const;
+ SocketFd GetLatestFD() const;
- // Create socket for connection to |server_address| with default socket
- // options.
- // Return fd index.
- virtual int CreateUDPSocket(QuicSocketAddress server_address,
- bool* overflow_supported);
+ // Create a socket for connection to |server_address| with default socket
+ // options. Returns the FD of the resulting socket.
+ virtual SocketFd CreateUDPSocket(QuicSocketAddress server_address,
+ bool* overflow_supported);
QuicClientBase* client() { return client_; }
@@ -80,7 +79,7 @@
}
// If |fd| is an open UDP socket, unregister and close it. Otherwise, do
// nothing.
- void CleanUpUDPSocket(int fd);
+ void CleanUpUDPSocket(SocketFd fd);
// Used for testing.
void SetClientPort(int port);
@@ -94,10 +93,10 @@
}
// Bind a socket to a specific network interface.
- bool BindInterfaceNameIfNeeded(int fd);
+ bool BindInterfaceNameIfNeeded(SocketFd fd);
// Actually clean up |fd|.
- virtual void CleanUpUDPSocketImpl(int fd);
+ virtual void CleanUpUDPSocketImpl(SocketFd fd);
private:
// Listens for events on the client socket.
@@ -105,7 +104,7 @@
// Map mapping created UDP sockets to their addresses. By using linked hash
// map, the order of socket creation can be recorded.
- quiche::QuicheLinkedHashMap<int, QuicSocketAddress> fd_address_map_;
+ quiche::QuicheLinkedHashMap<SocketFd, QuicSocketAddress> fd_address_map_;
// If overflow_supported_ is true, this will be the number of packets dropped
// during the lifetime of the server.
diff --git a/quiche/quic/tools/quic_server.cc b/quiche/quic/tools/quic_server.cc
index 738d8c9..63e9aca 100644
--- a/quiche/quic/tools/quic_server.cc
+++ b/quiche/quic/tools/quic_server.cc
@@ -97,8 +97,8 @@
}
QuicServer::~QuicServer() {
- close(fd_);
- fd_ = -1;
+ (void)socket_api::Close(fd_);
+ fd_ = kInvalidSocketFd;
// Should be fine without because nothing should send requests to the backend
// after `this` is destroyed, but for extra pointer safety, clear the socket