-
Notifications
You must be signed in to change notification settings - Fork 5.5k
quic: Connect client UDP sockets before usage #35652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
f50f2db
42e0e03
d07c44b
132bc4f
9fc7c01
bdb9a1a
75b2d67
0a867bb
46792b5
2190a6b
e267fed
c7deb81
792f9c0
03e6f17
f3893e7
3af46d9
9ab784a
a516dc5
599930b
9d8f3cf
a2de295
2ee309e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,18 @@ | |
| namespace Envoy { | ||
| namespace Quic { | ||
|
|
||
| namespace { | ||
|
|
||
| Network::Address::InstanceConstSharedPtr | ||
| getLoopbackAddress(const Network::Address::IpVersion version) { | ||
| if (version == Network::Address::IpVersion::v6) { | ||
| return std::make_shared<Network::Address::Ipv6Instance>("::1"); | ||
| } | ||
| return std::make_shared<Network::Address::Ipv4Instance>("127.0.0.1"); | ||
|
abeyad marked this conversation as resolved.
|
||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| // TODO(danzh): this is called on each write. Consider to return an address instance on the stack if | ||
| // the heap allocation is too expensive. | ||
| Network::Address::InstanceConstSharedPtr | ||
|
|
@@ -168,16 +180,17 @@ createConnectionSocket(const Network::Address::InstanceConstSharedPtr& peer_addr | |
| Network::Address::InstanceConstSharedPtr& local_addr, | ||
| const Network::ConnectionSocket::OptionsSharedPtr& options, | ||
| const bool prefer_gro) { | ||
| if (local_addr == nullptr) { | ||
| local_addr = Network::Utility::getLocalAddress(peer_addr->ip()->version()); | ||
| } | ||
| ASSERT(peer_addr != nullptr); | ||
| size_t max_addresses_cache_size = | ||
| Runtime::runtimeFeatureEnabled( | ||
| "envoy.reloadable_features.quic_upstream_socket_use_address_cache_for_read") | ||
| ? 4u | ||
| : 0u; | ||
| auto connection_socket = std::make_unique<Network::ConnectionSocketImpl>( | ||
| Network::Socket::Type::Datagram, local_addr, peer_addr, | ||
| Network::Socket::Type::Datagram, | ||
| // Use the loopback address if `local_addr` is null, to pass in the socket interface used to | ||
| // create the IoHandle, without having to make the more expensive `getifaddrs` call. | ||
| local_addr ? local_addr : getLoopbackAddress(peer_addr->ip()->version()), peer_addr, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious how this local address is used. In the server case, we need a local address 'cause that's what we listen. But in the normal POSIX client socket case, a caller typically does not specify a local address. Do you understand how this is used?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, the local address is needed so we can get a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. That makes sense, but it makes me nervous. Have we tried running this PR against an external server (using HTTP/3)?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should only affect upstream traffic. And if we hide it behind a runtime feature, it should be fine.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have tested it on a mobile app connecting to a H/3 server, but for added safety, I added a runtime guard.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excellent. Can you also mention that in the PR description and update the release notes?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Release notes was updated in https://github.com/envoyproxy/envoy/pull/35652/files#diff-6f9c718224c533c13c2c0ba1d5abaab86be9d0cc73808749c77934e9f9b0d5d0. Just updated the PR description. |
||
| Network::SocketCreationOptions{false, max_addresses_cache_size}); | ||
| connection_socket->setDetectedTransportProtocol("quic"); | ||
| if (!connection_socket->isOpen()) { | ||
|
|
@@ -201,8 +214,18 @@ createConnectionSocket(const Network::Address::InstanceConstSharedPtr& peer_addr | |
| ENVOY_LOG_MISC(error, "Fail to apply pre-bind options"); | ||
| return connection_socket; | ||
| } | ||
| connection_socket->bind(local_addr); | ||
| ASSERT(local_addr->ip()); | ||
|
|
||
| if (local_addr != nullptr) { | ||
| connection_socket->bind(local_addr); | ||
| ASSERT(local_addr->ip()); | ||
| } | ||
| if (auto result = connection_socket->connect(peer_addr); result.return_value_ != 0) { | ||
| connection_socket->close(); | ||
| ENVOY_LOG_MISC(error, "Fail to connect socket: ({}) {}", result.errno_, | ||
| errorDetails(result.errno_)); | ||
| return connection_socket; | ||
| } | ||
|
|
||
| local_addr = connection_socket->connectionInfoProvider().localAddress(); | ||
| if (!Network::Socket::applyOptions(connection_socket->options(), *connection_socket, | ||
| envoy::config::core::v3::SocketOption::STATE_BOUND)) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.