diff --git a/connections/implementation/offline_frames_validator.cc b/connections/implementation/offline_frames_validator.cc index 0c058fbc..c53afded 100644 --- a/connections/implementation/offline_frames_validator.cc +++ b/connections/implementation/offline_frames_validator.cc @@ -258,10 +258,10 @@ Exception EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame( Exception EnsureValidBandwidthUpgradeWifiLanPathAvailableFrame( const WifiLanSocket& wifi_lan_socket) { - if (!wifi_lan_socket.has_ip_address()) - return {Exception::kInvalidProtocolBuffer}; - if (!wifi_lan_socket.has_wifi_port() || wifi_lan_socket.wifi_port() < 0) + if ((!wifi_lan_socket.has_ip_address() || wifi_lan_socket.wifi_port() <= 0) && + wifi_lan_socket.address_candidates_size() == 0) { return {Exception::kInvalidProtocolBuffer}; + } // For backwards compatibility reasons, no other fields should be null-checked // for this frame. Parameter checking (eg. must be within this range) is fine. diff --git a/connections/implementation/offline_frames_validator_test.cc b/connections/implementation/offline_frames_validator_test.cc index 3b97dc19..5c27c940 100644 --- a/connections/implementation/offline_frames_validator_test.cc +++ b/connections/implementation/offline_frames_validator_test.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include "gtest/gtest.h" #include "absl/strings/string_view.h" @@ -680,6 +681,23 @@ TEST(OfflineFramesValidatorTest, EXPECT_FALSE(ret_value.Ok()); } +TEST(OfflineFramesValidatorTest, + ValidateWifiLanUpgradeFrameWithAddressCandidatesSucceeds) { + OfflineFrame offline_frame; + std::vector address_candidates = { + std::string( + "\x2a\x00\x79\xe0\x2e\x87\x00\x06\xb7\x28\x67\x45\x7a\xdd\x01\x53", + 16), + std::string("\xc0\xa8\x00\x01", 4), + }; + ByteArray bytes = ForBwuWifiLanPathAvailable(address_candidates, kPort); + offline_frame.ParseFromString(std::string(bytes)); + + auto ret_value = EnsureValidOfflineFrame(offline_frame); + + EXPECT_TRUE(ret_value.Ok()); +} + TEST(OfflineFramesValidatorTest, ValidatesAsFailWithNullBandwidthUpgradeNegotiationFrame) { OfflineFrame offline_frame; diff --git a/connections/implementation/wifi_lan_bwu_handler.cc b/connections/implementation/wifi_lan_bwu_handler.cc index 3d87c887..0cbd42cd 100644 --- a/connections/implementation/wifi_lan_bwu_handler.cc +++ b/connections/implementation/wifi_lan_bwu_handler.cc @@ -31,6 +31,7 @@ #include "internal/platform/expected.h" #include "internal/platform/implementation/wifi_utils.h" #include "internal/platform/logging.h" +#include "internal/platform/wifi_credential.h" #include "internal/platform/wifi_lan.h" namespace nearby { @@ -57,46 +58,62 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel( } const UpgradePathInfo::WifiLanSocket& upgrade_path_info_socket = upgrade_path_info.wifi_lan_socket(); - if (!upgrade_path_info_socket.has_ip_address() || - !upgrade_path_info_socket.has_wifi_port()) { + if ((!upgrade_path_info_socket.has_ip_address() || + !upgrade_path_info_socket.has_wifi_port()) && + upgrade_path_info_socket.address_candidates_size() == 0) { LOG(ERROR) << "WifiLanBwuHandler failed to parse UpgradePathInfo."; return {Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_IP_ADDRESS_ERROR)}; } - const std::string& ip_address = upgrade_path_info_socket.ip_address(); - std::int32_t port = upgrade_path_info_socket.wifi_port(); - - VLOG(1) << "WifiLanBwuHandler is attempting to connect to " - << "available WifiLan service (" + std::vector address_candidates; + for (const auto& address_candidate : + upgrade_path_info_socket.address_candidates()) { + if (address_candidate.has_ip_address() && address_candidate.has_port()) { + address_candidates.push_back(ServiceAddress{ + .address = + std::vector(address_candidate.ip_address().begin(), + address_candidate.ip_address().end()), + .port = static_cast(address_candidate.port())}); + } + } + // Only use ip_address and wifi_port if address_candidates is empty. + if (address_candidates.empty()) { + address_candidates.push_back(ServiceAddress{ + .address = + std::vector(upgrade_path_info_socket.ip_address().begin(), + upgrade_path_info_socket.ip_address().end()), + .port = static_cast(upgrade_path_info_socket.wifi_port())}); + } + Error error; + for (const auto& address_candidate : address_candidates) { + std::string ip_address = std::string(address_candidate.address.begin(), + address_candidate.address.end()); + int port = address_candidate.port; + VLOG(1) << "WifiLanBwuHandler is attempting to connect to available " + "WifiLan service (" + << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" << port + << ") for endpoint " << endpoint_id; + ErrorOr socket_result = wifi_lan_medium_.Connect( + service_id, ip_address, port, client->GetCancellationFlag(endpoint_id)); + if (socket_result.has_error()) { + LOG(ERROR) + << "WifiLanBwuHandler failed to connect to the WifiLan service (" << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" << port << ") for endpoint " << endpoint_id; + error = Error(socket_result.error().operation_result_code().value()); + continue; + } + VLOG(1) << "WifiLanBwuHandler successfully connected to WifiLan service (" + << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" << port + << ") while upgrading endpoint " << endpoint_id; - ErrorOr socket_result = wifi_lan_medium_.Connect( - service_id, ip_address, port, client->GetCancellationFlag(endpoint_id)); - if (socket_result.has_error()) { - LOG(ERROR) << "WifiLanBwuHandler failed to connect to the WifiLan service (" - << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" - << port << ") for endpoint " << endpoint_id; - return {Error(socket_result.error().operation_result_code().value())}; + // Create a new WifiLanEndpointChannel. + auto channel = std::make_unique( + service_id, /*channel_name=*/service_id, socket_result.value()); + return {std::move(channel)}; } - VLOG(1) << "WifiLanBwuHandler successfully connected to WifiLan service (" - << WifiUtils::GetHumanReadableIpAddress(ip_address) << ":" << port - << ") while upgrading endpoint " << endpoint_id; - - // Create a new WifiLanEndpointChannel. - auto channel = std::make_unique( - service_id, /*channel_name=*/service_id, socket_result.value()); - if (channel == nullptr) { - LOG(ERROR) << "WifiLanBwuHandler failed to create WifiLan endpoint " - << "channel to the WifiLan service (" << ip_address << ":" - << port << ") for endpoint " << endpoint_id; - socket_result.value().Close(); - return {Error( - OperationResultCode::NEARBY_LAN_ENDPOINT_CHANNEL_CREATION_FAILURE)}; - } - - return {std::move(channel)}; + return {error}; } // Called by BWU initiator. Set up WifiLan upgraded medium for this endpoint,