Roll forward to cl/341113126

Signed-off-by: hai007 <hais@google.com>
This commit is contained in:
hai007
2020-11-06 13:55:36 -08:00
parent 3c698dabc5
commit 67f5942051
23 changed files with 1216 additions and 79 deletions
+3
View File
@@ -16,6 +16,7 @@ cc_library(
"internal_payload.cc",
"internal_payload_factory.cc",
"offline_frames.cc",
"offline_frames_validator.cc",
"offline_service_controller.cc",
"p2p_cluster_pcp_handler.cc",
"p2p_point_to_point_pcp_handler.cc",
@@ -48,6 +49,7 @@ cc_library(
"internal_payload.h",
"internal_payload_factory.h",
"offline_frames.h",
"offline_frames_validator.h",
"offline_service_controller.h",
"p2p_cluster_pcp_handler.h",
"p2p_point_to_point_pcp_handler.h",
@@ -149,6 +151,7 @@ cc_test(
"endpoint_manager_test.cc",
"internal_payload_factory_test.cc",
"offline_frames_test.cc",
"offline_frames_validator_test.cc",
"offline_service_controller_test.cc",
"p2p_cluster_pcp_handler_test.cc",
"payload_manager_test.cc",
+3 -1
View File
@@ -474,8 +474,10 @@ Exception BasePcpHandler::WriteConnectionRequestFrame(
EndpointChannel* endpoint_channel, const std::string& local_endpoint_id,
const ByteArray& local_endpoint_info, std::int32_t nonce,
const std::vector<proto::connections::Medium>& supported_mediums) {
// TODO(b/172178926): Add WifiLan 5GHz and BSSID support.
return endpoint_channel->Write(parser::ForConnectionRequest(
local_endpoint_id, local_endpoint_info, nonce, supported_mediums));
local_endpoint_id, local_endpoint_info, nonce, /*supports_5_ghz =*/false,
/*bssid=*/std::string{}, supported_mediums));
}
void BasePcpHandler::ProcessPreConnectionInitiationFailure(
+2 -3
View File
@@ -161,9 +161,8 @@ TEST_F(EndpointManagerTest, RegisterFrameProcessorWorks) {
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
auto connect_request = std::make_unique<MockFrameProcessor>();
ByteArray endpoint_info{"endpoint_name"};
auto read_data =
parser::ForConnectionRequest("endpoint_id", endpoint_info,
1234, std::vector{Medium::BLE});
auto read_data = parser::ForConnectionRequest(
"endpoint_id", endpoint_info, 1234, false, "", std::vector{Medium::BLE});
EXPECT_CALL(*connect_request, OnIncomingFrame);
EXPECT_CALL(*connect_request, OnEndpointDisconnect);
EXPECT_CALL(*endpoint_channel, Read())
+3
View File
@@ -4,6 +4,9 @@ namespace location {
namespace nearby {
namespace connections {
// The definition is necessary before C++17.
constexpr int InternalPayload::kIndeterminateSize;
InternalPayload::InternalPayload(Payload payload)
: payload_(std::move(payload)), payload_id_(payload_.GetId()) {}
+2
View File
@@ -19,6 +19,8 @@ namespace connections {
// Payload.
class InternalPayload {
public:
static constexpr int kIndeterminateSize = -1;
explicit InternalPayload(Payload payload);
virtual ~InternalPayload() = default;
+2
View File
@@ -62,6 +62,8 @@ std::string Utils::UnwrapUpgradeServiceId(
LocationHint Utils::BuildLocationHint(const std::string& location) {
LocationHint location_hint;
location_hint.set_format(LocationStandard::UNKNOWN);
if (!location.empty()) {
location_hint.set_location(location);
if (location.at(0) == '+') {
+6
View File
@@ -243,6 +243,12 @@ WifiLanService WifiLan::GetRemoteWifiLanService(const std::string& ip_address,
return medium_.FindRemoteService(ip_address, port);
}
std::pair<std::string, int> WifiLan::GetServiceAddress(
const std::string& service_id) {
MutexLock lock(&mutex_);
return medium_.GetServiceAddress(service_id);
}
} // namespace connections
} // namespace nearby
} // namespace location
+3
View File
@@ -74,6 +74,9 @@ class WifiLan {
WifiLanService GetRemoteWifiLanService(const std::string& ip_address,
int port) ABSL_LOCKS_EXCLUDED(mutex_);
std::pair<std::string, int> GetServiceAddress(const std::string& service_id)
ABSL_LOCKS_EXCLUDED(mutex_);
private:
struct AdvertisingInfo {
bool Empty() const { return service_ids.empty(); }
+79 -7
View File
@@ -4,6 +4,7 @@
#include <utility>
#include "core/internal/message_lite.h"
#include "core/internal/offline_frames_validator.h"
#include "core/status.h"
#include "proto/connections/offline_wire_formats.pb.h"
#include "platform/base/byte_array.h"
@@ -30,6 +31,10 @@ ExceptionOrOfflineFrame FromBytes(const ByteArray& bytes) {
OfflineFrame frame;
if (frame.ParseFromString(std::string(bytes))) {
Exception validation_exception = EnsureValidOfflineFrame(frame);
if (validation_exception.Raised()) {
return ExceptionOrOfflineFrame(validation_exception);
}
return ExceptionOrOfflineFrame(std::move(frame));
} else {
return ExceptionOrOfflineFrame(Exception::kInvalidProtocolBuffer);
@@ -46,7 +51,8 @@ V1Frame::FrameType GetFrameType(const OfflineFrame& frame) {
ByteArray ForConnectionRequest(const std::string& endpoint_id,
const ByteArray& endpoint_info,
std::int32_t nonce,
std::int32_t nonce, bool supports_5_ghz,
const std::string& bssid,
const std::vector<Medium>& mediums) {
OfflineFrame frame;
@@ -54,12 +60,21 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id,
auto* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::CONNECTION_REQUEST);
auto* connection_request = v1_frame->mutable_connection_request();
connection_request->set_endpoint_id(endpoint_id);
connection_request->set_endpoint_name(std::string(endpoint_info));
connection_request->set_endpoint_info(std::string(endpoint_info));
if (!endpoint_id.empty())
connection_request->set_endpoint_id(endpoint_id);
if (!endpoint_info.Empty()) {
connection_request->set_endpoint_name(std::string(endpoint_info));
connection_request->set_endpoint_info(std::string(endpoint_info));
}
connection_request->set_nonce(nonce);
for (const auto& medium : mediums) {
connection_request->add_mediums(MediumToConnectionRequestMedium(medium));
auto* medium_metadata = connection_request->mutable_medium_metadata();
medium_metadata->set_supports_5_ghz(supports_5_ghz);
if (!bssid.empty())
medium_metadata->set_bssid(bssid);
if (!mediums.empty()) {
for (const auto& medium : mediums) {
connection_request->add_mediums(MediumToConnectionRequestMedium(medium));
}
}
return ToBytes(std::move(frame));
@@ -118,7 +133,9 @@ ByteArray ForControlPayloadTransfer(
ByteArray ForBwuWifiHotspotPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port) {
std::int32_t port,
const std::string& gateway,
bool supports_disabling_encryption) {
OfflineFrame frame;
frame.set_version(OfflineFrame::V1);
@@ -129,11 +146,14 @@ ByteArray ForBwuWifiHotspotPathAvailable(const std::string& ssid,
BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE);
auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info();
upgrade_path_info->set_medium(UpgradePathInfo::WIFI_HOTSPOT);
upgrade_path_info->set_supports_disabling_encryption(
supports_disabling_encryption);
auto* wifi_hotspot_credentials =
upgrade_path_info->mutable_wifi_hotspot_credentials();
wifi_hotspot_credentials->set_ssid(ssid);
wifi_hotspot_credentials->set_password(password);
wifi_hotspot_credentials->set_port(port);
wifi_hotspot_credentials->set_gateway(gateway);
return ToBytes(std::move(frame));
}
@@ -157,6 +177,58 @@ ByteArray ForBwuWifiLanPathAvailable(const std::string& ip_address,
return ToBytes(std::move(frame));
}
ByteArray ForBwuWifiAwarePathAvailable(const std::string& service_id,
const std::string& service_info,
const std::string& password,
bool supports_disabling_encryption) {
OfflineFrame frame;
frame.set_version(OfflineFrame::V1);
auto* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION);
auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation();
sub_frame->set_event_type(
BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE);
auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info();
upgrade_path_info->set_medium(UpgradePathInfo::WIFI_AWARE);
upgrade_path_info->set_supports_disabling_encryption(
supports_disabling_encryption);
auto* wifi_aware_credentials =
upgrade_path_info->mutable_wifi_aware_credentials();
wifi_aware_credentials->set_service_id(service_id);
wifi_aware_credentials->set_service_info(service_info);
if (!password.empty()) wifi_aware_credentials->set_password(password);
return ToBytes(std::move(frame));
}
ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption) {
OfflineFrame frame;
frame.set_version(OfflineFrame::V1);
auto* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION);
auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation();
sub_frame->set_event_type(
BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE);
auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info();
upgrade_path_info->set_medium(UpgradePathInfo::WIFI_DIRECT);
upgrade_path_info->set_supports_disabling_encryption(
supports_disabling_encryption);
auto* wifi_direct_credentials =
upgrade_path_info->mutable_wifi_direct_credentials();
wifi_direct_credentials->set_ssid(ssid);
wifi_direct_credentials->set_password(password);
wifi_direct_credentials->set_port(port);
wifi_direct_credentials->set_frequency(frequency);
return ToBytes(std::move(frame));
}
ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id,
const std::string& mac_address) {
OfflineFrame frame;
+14 -2
View File
@@ -31,7 +31,8 @@ V1Frame::FrameType GetFrameType(const OfflineFrame& offline_frame);
// Builds Connection Request / Response messages.
ByteArray ForConnectionRequest(const std::string& endpoint_id,
const ByteArray& endpoint_info,
std::int32_t nonce,
std::int32_t nonce, bool supports_5_ghz,
const std::string& bssid,
const std::vector<Medium>& mediums);
ByteArray ForConnectionResponse(std::int32_t status);
@@ -47,9 +48,20 @@ ByteArray ForControlPayloadTransfer(
ByteArray ForBwuIntroduction(const std::string& endpoint_id);
ByteArray ForBwuWifiHotspotPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port);
std::int32_t port,
const std::string& gateway,
bool supports_disabling_encryption);
ByteArray ForBwuWifiLanPathAvailable(const std::string& ip_address,
std::int32_t port);
ByteArray ForBwuWifiAwarePathAvailable(const std::string& service_id,
const std::string& service_info,
const std::string& password,
bool supports_disabling_encryption);
ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption);
ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id,
const std::string& mac_address);
ByteArray ForBwuWebrtcPathAvailable(const std::string& peer_id,
+71 -1
View File
@@ -22,6 +22,8 @@ using ::testing::EqualsProto;
constexpr absl::string_view kEndpointId{"ABC"};
constexpr absl::string_view kEndpointName{"XYZ"};
constexpr int kNonce = 1234;
constexpr bool kSupports5ghz = true;
constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"};
constexpr std::array<Medium, 9> kMediums = {
Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT,
Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE,
@@ -41,6 +43,11 @@ TEST(OfflineFramesTest, CanParseMessageFromBytes) {
sub_frame->set_endpoint_name(kEndpointName);
sub_frame->set_endpoint_info(kEndpointName);
sub_frame->set_nonce(kNonce);
auto* medium_metadata = sub_frame->mutable_medium_metadata();
medium_metadata->set_supports_5_ghz(kSupports5ghz);
medium_metadata->set_bssid(kBssid);
for (auto& medium : kMediums) {
sub_frame->add_mediums(MediumToConnectionRequestMedium(medium));
}
@@ -67,6 +74,10 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) {
endpoint_name: "XYZ"
endpoint_info: "XYZ"
nonce: 1234
medium_metadata: <
supports_5_ghz: true
bssid: "FF:FF:FF:FF:FF:FF"
>
mediums: MDNS
mediums: BLUETOOTH
mediums: WIFI_HOTSPOT
@@ -80,6 +91,7 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) {
>)pb";
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()));
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
@@ -174,11 +186,14 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiHotspotPathAvailable) {
ssid: "ssid"
password: "password"
port: 1234
gateway: "0.0.0.0"
>
supports_disabling_encryption: false
>
>
>)pb";
ByteArray bytes = ForBwuWifiHotspotPathAvailable("ssid", "password", 1234);
ByteArray bytes = ForBwuWifiHotspotPathAvailable("ssid", "password", 1234,
"0.0.0.0", false);
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = FromBytes(bytes).result();
@@ -206,6 +221,61 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiLanPathAvailable) {
EXPECT_THAT(message, EqualsProto(kExpected));
}
TEST(OfflineFramesTest, CanGenerateBwuWifiAwarePathAvailable) {
constexpr char kExpected[] =
R"pb(
version: V1
v1: <
type: BANDWIDTH_UPGRADE_NEGOTIATION
bandwidth_upgrade_negotiation: <
event_type: UPGRADE_PATH_AVAILABLE
upgrade_path_info: <
medium: WIFI_AWARE
wifi_aware_credentials: <
service_id: "service_id"
service_info: "service_info"
password: "password"
>
supports_disabling_encryption: false
>
>
>)pb";
ByteArray bytes = ForBwuWifiAwarePathAvailable("service_id", "service_info",
"password", false);
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = FromBytes(bytes).result();
EXPECT_THAT(message, EqualsProto(kExpected));
}
TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
constexpr char kExpected[] =
R"pb(
version: V1
v1: <
type: BANDWIDTH_UPGRADE_NEGOTIATION
bandwidth_upgrade_negotiation: <
event_type: UPGRADE_PATH_AVAILABLE
upgrade_path_info: <
medium: WIFI_DIRECT
wifi_direct_credentials: <
ssid: "DIRECT-A0-0123456789AB"
password: "password"
port: 1000
frequency: 1000
>
supports_disabling_encryption: false
>
>
>)pb";
ByteArray bytes = ForBwuWifiDirectPathAvailable(
"DIRECT-A0-0123456789AB", "password", 1000, 1000, false);
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = FromBytes(bytes).result();
EXPECT_THAT(message, EqualsProto(kExpected));
}
TEST(OfflineFramesTest, CanGenerateBwuBluetoothPathAvailable) {
constexpr char kExpected[] =
R"pb(
@@ -0,0 +1,366 @@
#include "core/internal/offline_frames_validator.h"
#include <regex> //NOLINT
#include "core/internal/internal_payload.h"
#include "core/internal/offline_frames.h"
#include "proto/connections/offline_wire_formats.pb.h"
namespace location {
namespace nearby {
namespace connections {
namespace parser {
namespace {
using PayloadChunk = PayloadTransferFrame::PayloadChunk;
using ControlMessage = PayloadTransferFrame::ControlMessage;
using ClientIntroduction = BandwidthUpgradeNegotiationFrame::ClientIntroduction;
using WifiHotspotCredentials = UpgradePathInfo::WifiHotspotCredentials;
using WifiLanSocket = UpgradePathInfo::WifiLanSocket;
using WifiAwareCredentials = UpgradePathInfo::WifiAwareCredentials;
using WifiDirectCredentials = UpgradePathInfo::WifiDirectCredentials;
using BluetoothCredentials = UpgradePathInfo::BluetoothCredentials;
using WebRtcCredentials = UpgradePathInfo::WebRtcCredentials;
constexpr absl::string_view kIpv4PatternString{
"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"};
constexpr absl::string_view kIpv6PatternString{
"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"};
constexpr absl::string_view kWifiDirectSsidPatternString{
"^DIRECT-[a-zA-Z0-9]{2}.*$"};
constexpr int kWifiDirectSsidMaxLength = 32;
constexpr int kWifiPasswordSsidMinLength = 8;
constexpr int kWifiPasswordSsidMaxLength = 64;
inline bool WithinRange(int value, int min, int max) {
return value >= min && value < max;
}
Exception EnsureValidConnectionRequestFrame(
const ConnectionRequestFrame& frame) {
if (!frame.has_endpoint_id()) return {Exception::kInvalidProtocolBuffer};
if (!frame.has_endpoint_name()) 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.
return {Exception::kSuccess};
}
Exception EnsureValidConnectionResponseFrame(
const ConnectionResponseFrame& frame) {
// For backwards compatibility reasons, no other fields should be null-checked
// for this frame. Parameter checking (eg. must be within this range) is fine.
return {Exception::kSuccess};
}
Exception EnsureValidPayloadTransferDataFrame(const PayloadChunk& payload_chunk,
int totalSize) {
if (!payload_chunk.has_flags()) return {Exception::kInvalidProtocolBuffer};
// Special case. The body can be null iff the chunk is flagged as the last
// chunk.
bool is_last_chunk = (payload_chunk.flags() &
PayloadTransferFrame::PayloadChunk::LAST_CHUNK) != 0;
if (!payload_chunk.has_body() && !is_last_chunk)
return {Exception::kInvalidProtocolBuffer};
if (!payload_chunk.has_offset() || payload_chunk.offset() < 0)
return {Exception::kInvalidProtocolBuffer};
if (totalSize != InternalPayload::kIndeterminateSize &&
totalSize < payload_chunk.offset()) {
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.
return {Exception::kSuccess};
}
Exception EnsureValidPayloadTransferControlFrame(
const ControlMessage& control_message, int totalSize) {
if (!control_message.has_offset() || control_message.offset() < 0)
return {Exception::kInvalidProtocolBuffer};
if (totalSize != InternalPayload::kIndeterminateSize &&
totalSize < control_message.offset()) {
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.
return {Exception::kSuccess};
}
Exception EnsureValidPayloadTransferFrame(const PayloadTransferFrame& frame) {
if (!frame.has_payload_header()) return {Exception::kInvalidProtocolBuffer};
if (!frame.payload_header().has_total_size() ||
(frame.payload_header().total_size() < 0 &&
frame.payload_header().total_size() !=
InternalPayload::kIndeterminateSize))
return {Exception::kInvalidProtocolBuffer};
if (!frame.has_packet_type()) return {Exception::kInvalidProtocolBuffer};
switch (frame.packet_type()) {
case PayloadTransferFrame::DATA:
if (frame.has_payload_chunk()) {
return EnsureValidPayloadTransferDataFrame(
frame.payload_chunk(), frame.payload_header().total_size());
}
return {Exception::kInvalidProtocolBuffer};
case PayloadTransferFrame::CONTROL:
if (frame.has_control_message()) {
return EnsureValidPayloadTransferControlFrame(
frame.control_message(), frame.payload_header().total_size());
}
return {Exception::kInvalidProtocolBuffer};
default:
break;
}
// For backwards compatibility reasons, no other fields should be null-checked
// for this frame. Parameter checking (eg. must be within this range) is fine.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame(
const WifiHotspotCredentials& wifi_hotspot_credentials) {
if (!wifi_hotspot_credentials.has_ssid())
return {Exception::kInvalidProtocolBuffer};
if (!wifi_hotspot_credentials.has_password() ||
!WithinRange(wifi_hotspot_credentials.password().length(),
kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength))
return {Exception::kInvalidProtocolBuffer};
if (!wifi_hotspot_credentials.has_gateway())
return {Exception::kInvalidProtocolBuffer};
const std::regex ip4_pattern(std::string(kIpv4PatternString).c_str());
const std::regex ip6_pattern(std::string(kIpv6PatternString).c_str());
if (!(std::regex_match(wifi_hotspot_credentials.gateway(), ip4_pattern) ||
std::regex_match(wifi_hotspot_credentials.gateway(), ip6_pattern)))
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.
return {Exception::kSuccess};
}
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)
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeWifiAwarePathAvailableFrame(
const WifiAwareCredentials& wifi_aware_credentials) {
if (!wifi_aware_credentials.has_service_id())
return {Exception::kInvalidProtocolBuffer};
if (!wifi_aware_credentials.has_service_info())
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame(
const WifiDirectCredentials& wifi_direct_credentials) {
const std::regex ssid_pattern(
std::string(kWifiDirectSsidPatternString).c_str());
if (!wifi_direct_credentials.has_ssid() ||
!(wifi_direct_credentials.ssid().length() < kWifiDirectSsidMaxLength &&
std::regex_match(wifi_direct_credentials.ssid(), ssid_pattern)))
return {Exception::kInvalidProtocolBuffer};
if (!wifi_direct_credentials.has_password() ||
!WithinRange(wifi_direct_credentials.password().length(),
kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength))
return {Exception::kInvalidProtocolBuffer};
if (!wifi_direct_credentials.has_frequency() ||
wifi_direct_credentials.frequency() < -1)
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeBluetoothPathAvailableFrame(
const BluetoothCredentials& bluetooth_credentials) {
if (!bluetooth_credentials.has_service_name())
return {Exception::kInvalidProtocolBuffer};
if (!bluetooth_credentials.has_mac_address())
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeWebRtcPathAvailableFrame(
const WebRtcCredentials& web_rtc_credentials) {
if (!web_rtc_credentials.has_peer_id())
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradePathAvailableFrame(
const UpgradePathInfo& upgrade_path_info) {
if (!upgrade_path_info.has_medium())
return {Exception::kInvalidProtocolBuffer};
switch (upgrade_path_info.medium()) {
case Medium::WIFI_HOTSPOT:
if (upgrade_path_info.has_wifi_hotspot_credentials()) {
return EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame(
upgrade_path_info.wifi_hotspot_credentials());
}
return {Exception::kInvalidProtocolBuffer};
case Medium::WIFI_LAN:
if (upgrade_path_info.has_wifi_lan_socket()) {
return EnsureValidBandwidthUpgradeWifiLanPathAvailableFrame(
upgrade_path_info.wifi_lan_socket());
}
return {Exception::kInvalidProtocolBuffer};
case Medium::WIFI_AWARE:
if (upgrade_path_info.has_wifi_aware_credentials()) {
return EnsureValidBandwidthUpgradeWifiAwarePathAvailableFrame(
upgrade_path_info.wifi_aware_credentials());
}
return {Exception::kInvalidProtocolBuffer};
case Medium::WIFI_DIRECT:
if (upgrade_path_info.has_wifi_direct_credentials()) {
return EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame(
upgrade_path_info.wifi_direct_credentials());
}
return {Exception::kInvalidProtocolBuffer};
case Medium::BLUETOOTH:
if (upgrade_path_info.has_bluetooth_credentials()) {
return EnsureValidBandwidthUpgradeBluetoothPathAvailableFrame(
upgrade_path_info.bluetooth_credentials());
}
return {Exception::kInvalidProtocolBuffer};
case Medium::WEB_RTC:
if (upgrade_path_info.has_web_rtc_credentials()) {
return EnsureValidBandwidthUpgradeWebRtcPathAvailableFrame(
upgrade_path_info.web_rtc_credentials());
}
return {Exception::kInvalidProtocolBuffer};
default:
break;
}
// For backwards compatibility reasons, no other fields should be null-checked
// for this frame. Parameter checking (eg. must be within this range) is fine.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeClientIntroductionFrame(
const ClientIntroduction& client_introduction) {
if (!client_introduction.has_endpoint_id())
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.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeNegotiationFrame(
const BandwidthUpgradeNegotiationFrame& frame) {
if (!frame.has_event_type()) return {Exception::kInvalidProtocolBuffer};
switch (frame.event_type()) {
case BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE:
if (frame.has_upgrade_path_info()) {
return EnsureValidBandwidthUpgradePathAvailableFrame(
frame.upgrade_path_info());
}
return {Exception::kInvalidProtocolBuffer};
case BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION:
if (frame.has_client_introduction()) {
return EnsureValidBandwidthUpgradeClientIntroductionFrame(
frame.client_introduction());
}
return {Exception::kInvalidProtocolBuffer};
default:
break;
}
// For backwards compatibility reasons, no other fields should be null-checked
// for this frame. Parameter checking (eg. must be within this range) is fine.
return {Exception::kSuccess};
}
} // namespace
Exception EnsureValidOfflineFrame(const OfflineFrame& offline_frame) {
V1Frame::FrameType frame_type = GetFrameType(offline_frame);
switch (frame_type) {
case V1Frame::CONNECTION_REQUEST:
if (offline_frame.has_v1() &&
offline_frame.v1().has_connection_request()) {
return EnsureValidConnectionRequestFrame(
offline_frame.v1().connection_request());
}
return {Exception::kInvalidProtocolBuffer};
case V1Frame::CONNECTION_RESPONSE:
if (offline_frame.has_v1() &&
offline_frame.v1().has_connection_response()) {
return EnsureValidConnectionResponseFrame(
offline_frame.v1().connection_response());
}
return {Exception::kInvalidProtocolBuffer};
case V1Frame::PAYLOAD_TRANSFER:
if (offline_frame.has_v1() && offline_frame.v1().has_payload_transfer()) {
return EnsureValidPayloadTransferFrame(
offline_frame.v1().payload_transfer());
}
return {Exception::kInvalidProtocolBuffer};
case V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION:
if (offline_frame.has_v1() &&
offline_frame.v1().has_bandwidth_upgrade_negotiation()) {
return EnsureValidBandwidthUpgradeNegotiationFrame(
offline_frame.v1().bandwidth_upgrade_negotiation());
}
return {Exception::kInvalidProtocolBuffer};
case V1Frame::KEEP_ALIVE:
case V1Frame::UNKNOWN_FRAME_TYPE:
default:
// Nothing to check for these frames.
break;
}
return {Exception::kSuccess};
}
} // namespace parser
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,19 @@
#ifndef CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_
#define CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_
#include "proto/connections/offline_wire_formats.pb.h"
#include "platform/base/exception.h"
namespace location {
namespace nearby {
namespace connections {
namespace parser {
Exception EnsureValidOfflineFrame(const OfflineFrame& offline_frame);
} // namespace parser
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_
@@ -0,0 +1,542 @@
#include "core/internal/offline_frames_validator.h"
#include "core/internal/offline_frames.h"
#include "proto/connections/offline_wire_formats.pb.h"
#include "platform/base/byte_array.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
namespace connections {
namespace parser {
namespace {
constexpr absl::string_view kEndpointId{"ABC"};
constexpr absl::string_view kEndpointName{"XYZ"};
constexpr int kNonce = 1234;
constexpr bool kSupports5ghz = true;
constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"};
constexpr int kStatusAccepted = 0;
constexpr absl::string_view kSsid = "ssid";
constexpr absl::string_view kPassword = "password";
constexpr absl::string_view kWifiHotspotGateway = "0.0.0.0";
constexpr absl::string_view kWifiDirectSsid = "DIRECT-A0-0123456789AB";
constexpr absl::string_view kWifiDirectPassword = "WIFIDIRECT123456";
constexpr int kWifiDirectFrequency = 1000;
constexpr int kPort = 1000;
constexpr bool kSupportsDisablingEncryption = true;
constexpr std::array<Medium, 9> kMediums = {
Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT,
Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE,
Medium::NFC, Medium::WIFI_DIRECT, Medium::WEB_RTC,
};
TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidConnectionRequestFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullConnectionRequestFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()));
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
v1_frame->clear_connection_request();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullEndpointIdInConnectionRequestFrame) {
OfflineFrame offline_frame;
std::string empty_enpoint_id;
ByteArray bytes = ForConnectionRequest(
empty_enpoint_id, ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullEndpointInfoInConnectionRequestFrame) {
OfflineFrame offline_frame;
ByteArray empty_endpoint_info;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), empty_endpoint_info, kNonce, kSupports5ghz,
std::string(kBssid), std::vector(kMediums.begin(), kMediums.end()));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsOkWithNullBssidInConnectionRequestFrame) {
OfflineFrame offline_frame;
std::string empty_bssid;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, empty_bssid,
std::vector(kMediums.begin(), kMediums.end()));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsOkWithNullMediumsInConnectionRequestFrame) {
OfflineFrame offline_frame;
std::vector<Medium> empty_mediums;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid), empty_mediums);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsOkWithValidConnectionResponseFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionResponse(kStatusAccepted);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullConnectionResponseFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionResponse(kStatusAccepted);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
v1_frame->clear_connection_response();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithUnexpectedStatusInConnectionResponseFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionResponse(-1);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
// To maintain forward compatibility, we allow unexpected status codes.
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidPayloadTransferFrame) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest, ValidatesAsFailWithNullPayloadTransferFrame) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
v1_frame->clear_payload_transfer();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullPayloadHeaderInPayloadTransferFrame) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
auto* payload_transfer = v1_frame->mutable_payload_transfer();
payload_transfer->clear_payload_header();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidSizeInPayloadHeader) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(-5);
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullPayloadChunkInPayloadTransferFrame) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
auto* payload_transfer = v1_frame->mutable_payload_transfer();
payload_transfer->clear_payload_chunk();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidOffsetInPayloadChunk) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(-1);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidLargeOffsetInPayloadChunk) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(4999);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidFlagsInPayloadChunk) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::PayloadChunk chunk;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
chunk.set_body("payload data");
chunk.set_offset(150);
chunk.set_flags(1);
OfflineFrame offline_frame;
ByteArray bytes = ForDataPayloadTransfer(header, chunk);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
auto* payload_transfer = v1_frame->mutable_payload_transfer();
auto* payload_chunk = payload_transfer->mutable_payload_chunk();
payload_chunk->clear_flags();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullControlMessageInPayloadTransferFrame) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::ControlMessage control;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED);
control.set_offset(150);
OfflineFrame offline_frame;
ByteArray bytes = ForControlPayloadTransfer(header, control);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
auto* payload_transfer = v1_frame->mutable_payload_transfer();
payload_transfer->clear_control_message();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidNegativeOffsetInControlMessage) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::ControlMessage control;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED);
control.set_offset(-1);
OfflineFrame offline_frame;
ByteArray bytes = ForControlPayloadTransfer(header, control);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidLargeOffsetInControlMessage) {
PayloadTransferFrame::PayloadHeader header;
PayloadTransferFrame::ControlMessage control;
header.set_id(12345);
header.set_type(PayloadTransferFrame::PayloadHeader::BYTES);
header.set_total_size(1024);
control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED);
control.set_offset(4999);
OfflineFrame offline_frame;
ByteArray bytes = ForControlPayloadTransfer(header, control);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsOkWithValidBandwidthUpgradeNegotiationFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForBwuWifiHotspotPathAvailable(
std::string(kSsid), std::string(kPassword), kPort,
std::string(kWifiHotspotGateway), kSupportsDisablingEncryption);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithNullBandwidthUpgradeNegotiationFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForBwuWifiHotspotPathAvailable(
std::string(kSsid), std::string(kPassword), kPort,
std::string(kWifiHotspotGateway), kSupportsDisablingEncryption);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
v1_frame->clear_bandwidth_upgrade_negotiation();
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest, ValidatesAsOkBandwidthUpgradeWifiDirect) {
OfflineFrame offline_frame;
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesValidFrequencyInBandwidthUpgradeWifiDirect) {
OfflineFrame offline_frame_1;
OfflineFrame offline_frame_2;
// Anything less than -1 is invalid
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -2,
kSupportsDisablingEncryption);
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
ASSERT_FALSE(ret_value.Ok());
// But -1 itself is not invalid
bytes = ForBwuWifiDirectPathAvailable(std::string(kWifiDirectSsid),
std::string(kWifiDirectPassword), kPort,
-1, kSupportsDisablingEncryption);
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
ASSERT_TRUE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidSsidInBandwidthUpgradeWifiDirect) {
OfflineFrame offline_frame_1;
OfflineFrame offline_frame_2;
std::string wifi_direct_ssid{"DIRECT-A*-0123456789AB"};
ByteArray bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
ASSERT_FALSE(ret_value.Ok());
std::string wifi_direct_ssid_wrong_length =
std::string{kWifiDirectSsid} + "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid_wrong_length, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
ASSERT_FALSE(ret_value.Ok());
}
TEST(OfflineFramesValidatorTest,
ValidatesAsFailWithInvalidPasswordInBandwidthUpgradeWifiDirect) {
OfflineFrame offline_frame_1;
OfflineFrame offline_frame_2;
std::string short_wifi_direct_password{"Test"};
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), short_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
ASSERT_FALSE(ret_value.Ok());
std::string long_wifi_direct_password =
std::string{kWifiDirectSsid} +
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), long_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
ASSERT_FALSE(ret_value.Ok());
}
} // namespace
} // namespace parser
} // namespace connections
} // namespace nearby
} // namespace location
+35 -48
View File
@@ -142,6 +142,10 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl(
};
}
// StopAcceptingConnections invokes for webrtc is suppressed for now to
// unblock CrOS dogfood integration. Disconnect will invoke ShutdownSignaling
// to release resources.
// TODO (hais): add corresponding logic back (b/172518506).
Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) {
bluetooth_medium_.TurnOffDiscoverability();
bluetooth_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
@@ -149,8 +153,6 @@ Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) {
ble_medium_.StopAdvertising(client->GetAdvertisingServiceId());
ble_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
webrtc_medium_.StopAcceptingConnections();
wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId());
wifi_lan_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId());
@@ -218,17 +220,13 @@ void P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler(
<< "Invoking BasePcpHandler::OnEndpointFound() for BT service="
<< service_id << "; id=" << device_name.GetEndpointId() << "; name="
<< absl::BytesToHexString(device_name.GetEndpointInfo().data());
OnEndpointFound(client,
std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{
{
device_name.GetEndpointId(),
device_name.GetEndpointInfo(),
service_id,
proto::connections::Medium::BLUETOOTH,
device_name.GetWebRtcState()
},
device,
}));
OnEndpointFound(
client, std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{
{device_name.GetEndpointId(), device_name.GetEndpointInfo(),
service_id, proto::connections::Medium::BLUETOOTH,
device_name.GetWebRtcState()},
device,
}));
});
}
@@ -260,13 +258,11 @@ void P2pClusterPcpHandler::BluetoothDeviceLostHandler(
"BT discovery handler (LOST) [client=%p, service=%s]: report "
"to client",
client, service_id.c_str());
OnEndpointLost(client, DiscoveredEndpoint{
device_name.GetEndpointId(),
device_name.GetEndpointInfo(),
service_id,
proto::connections::Medium::BLUETOOTH,
WebRtcState::kUndefined
});
OnEndpointLost(client,
DiscoveredEndpoint{device_name.GetEndpointId(),
device_name.GetEndpointInfo(), service_id,
proto::connections::Medium::BLUETOOTH,
WebRtcState::kUndefined});
});
}
@@ -353,13 +349,10 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler(
<< service_id << "; id=" << advertisement.GetEndpointId() << "; name="
<< absl::BytesToHexString(advertisement.GetEndpointInfo().data());
OnEndpointFound(client, std::make_shared<BleEndpoint>(BleEndpoint{
{
advertisement.GetEndpointId(),
advertisement.GetEndpointInfo(),
service_id,
proto::connections::Medium::BLE,
advertisement.GetWebRtcState()
},
{advertisement.GetEndpointId(),
advertisement.GetEndpointInfo(), service_id,
proto::connections::Medium::BLE,
advertisement.GetWebRtcState()},
peripheral,
}));
@@ -561,10 +554,8 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl(
// If this is an out-of-band connection, do not start actual discovery, since
// this connection is intended to be completed via InjectEndpointImpl().
if (options.is_out_of_band_connection) {
return {
.status = {Status::kSuccess},
.mediums = options.allowed.GetMediums(true)
};
return {.status = {Status::kSuccess},
.mediums = options.allowed.GetMediums(true)};
}
std::vector<proto::connections::Medium> mediums_started_successfully;
@@ -643,8 +634,7 @@ Status P2pClusterPcpHandler::StopDiscoveryImpl(ClientProxy* client) {
}
Status P2pClusterPcpHandler::InjectEndpointImpl(
ClientProxy* client,
const std::string& service_id,
ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata) {
NEARBY_LOG(INFO, "InjectEndpoint");
// Bluetooth is the only supported out-of-band connection medium.
@@ -906,8 +896,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising(
service_id, {.accepted_cb = [this, client, local_endpoint_info](
BluetoothSocket socket) {
if (!socket.IsValid()) {
NEARBY_LOG(INFO,
"Invalid socket in accept callback: name=%s",
NEARBY_LOG(INFO, "Invalid socket in accept callback: name=%s",
std::string(local_endpoint_info).c_str());
return;
}
@@ -1160,8 +1149,9 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl(
proto::connections::Medium
P2pClusterPcpHandler::StartListeningForWebRtcConnections(
ClientProxy* client, const string& service_id,
const string& local_endpoint_id, const ByteArray& local_endpoint_info) {
ClientProxy* client, const std::string& service_id,
const std::string& local_endpoint_id,
const ByteArray& local_endpoint_info) {
if (!webrtc_medium_.IsAvailable()) {
return proto::connections::UNKNOWN_MEDIUM;
}
@@ -1169,10 +1159,9 @@ P2pClusterPcpHandler::StartListeningForWebRtcConnections(
if (!webrtc_medium_.IsAcceptingConnections()) {
mediums::PeerId self_id = CreatePeerIdFromAdvertisement(
service_id, local_endpoint_id, local_endpoint_info);
LocationHint location_hint;
location_hint.set_format(LocationStandard::UNKNOWN);
std::string empty_country_code;
if (!webrtc_medium_.StartAcceptingConnections(
self_id, location_hint,
self_id, Utils::BuildLocationHint(empty_country_code),
{[this, client,
local_endpoint_info](mediums::WebRtcSocketWrapper socket) {
if (!socket.IsValid()) {
@@ -1183,7 +1172,7 @@ P2pClusterPcpHandler::StartListeningForWebRtcConnections(
RunOnPcpHandlerThread(
[this, client, socket = std::move(socket)]() {
string remote_device_name = "WebRtcSocket";
std::string remote_device_name = "WebRtcSocket";
auto channel = absl::make_unique<WebRtcEndpointChannel>(
remote_device_name, socket);
ByteArray remote_device_info{remote_device_name};
@@ -1202,13 +1191,11 @@ P2pClusterPcpHandler::StartListeningForWebRtcConnections(
BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WebRtcConnectImpl(
ClientProxy* client, WebRtcEndpoint* webrtc_endpoint) {
LocationHint location_hint;
location_hint.set_format(LocationStandard::UNKNOWN);
mediums::WebRtcSocketWrapper socket_wrapper =
webrtc_medium_.Connect(webrtc_endpoint->peer_id, location_hint);
if (!socket_wrapper.IsValid()) {
return BasePcpHandler::ConnectImplResult{.status = {Status::kError}};
std::string empty_country_code;
mediums::WebRtcSocketWrapper socket_wrapper = webrtc_medium_.Connect(
webrtc_endpoint->peer_id, Utils::BuildLocationHint(empty_country_code));
if (!socket_wrapper.IsValid()) {
return BasePcpHandler::ConnectImplResult{.status = {Status::kError}};
}
auto channel = absl::make_unique<WebRtcEndpointChannel>(
+3 -6
View File
@@ -9,9 +9,6 @@
#include "core/internal/webrtc_endpoint_channel.h"
#include "absl/functional/bind_front.h"
// Manages the Bluetooth-specific methods needed to upgrade an {@link
// EndpointChannel}.
namespace location {
namespace nearby {
namespace connections {
@@ -48,9 +45,9 @@ void WebrtcBwuHandler::OnIncomingWebrtcConnection(
bwu_notifications_.incoming_connection_cb(client, std::move(connection));
}
// Called by BWU initiator. BT Medium is set up, and BWU request is prepared,
// with necessary info (service_id, MAC address) for remote party to perform
// discovery.
// Called by BWU initiator. Set up WebRTC upgraded medium for this endpoint,
// and returns a upgrade path info (PeerId, LocationHint) for remote party to
// perform discovery.
ByteArray WebrtcBwuHandler::InitializeUpgradedMediumForEndpoint(
ClientProxy* client, const std::string& service_id,
const std::string& endpoint_id) {
+39 -11
View File
@@ -47,20 +47,28 @@ ByteArray WifiLanBwuHandler::InitializeUpgradedMediumForEndpoint(
endpoint_id.c_str());
return {};
}
NEARBY_LOG(INFO,
"WifiLanBwuHandler successfully started listening for incoming "
"WifiLan connections while upgrading endpoint %s",
endpoint_id.c_str());
NEARBY_LOGS(INFO)
<< "WifiLanBwuHandler successfully started listening for incoming "
"WifiLan connections while upgrading endpoint "
<< endpoint_id;
}
// cache service ID to revert
active_service_ids_.emplace(upgrade_service_id);
// TODO(b/169303360): Implements wifiLanCredntials for wif_lan_medium to
// get ip_address and port.
std::string ip_addresss;
std::int32_t port = 0;
return parser::ForBwuWifiLanPathAvailable(ip_addresss, port);
auto service_address = wifi_lan_medium_.GetServiceAddress(upgrade_service_id);
auto ip_address = service_address.first;
auto port = service_address.second;
if (ip_address.empty()) {
NEARBY_LOGS(INFO)
<< "WifiLanBwuHandler couldn't initiate the wifi_lan upgrade for "
"endpoint "
<< endpoint_id
<< " because the wifi_lan ip address were unable to be obtained.";
return {};
}
return parser::ForBwuWifiLanPathAvailable(ip_address, port);
}
void WifiLanBwuHandler::Revert() {
@@ -78,8 +86,28 @@ std::unique_ptr<EndpointChannel>
WifiLanBwuHandler::CreateUpgradedEndpointChannel(
ClientProxy* client, const std::string& service_id,
const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) {
// TODO(b/169303360): Implements connect WifiLan over ip address and port.
WifiLanSocket socket;
if (!upgrade_path_info.has_wifi_lan_socket()) {
return nullptr;
}
const UpgradePathInfo::WifiLanSocket& wifi_lan_socket =
upgrade_path_info.wifi_lan_socket();
if (!wifi_lan_socket.has_ip_address() || !wifi_lan_socket.has_wifi_port()) {
return nullptr;
}
const std::string& ip_address = wifi_lan_socket.ip_address();
int32 port = wifi_lan_socket.wifi_port();
WifiLanService wifi_lan_service =
wifi_lan_medium_.GetRemoteWifiLanService(ip_address, port);
if (!wifi_lan_service.IsValid()) {
return nullptr;
}
WifiLanSocket socket =
wifi_lan_medium_.Connect(wifi_lan_service, service_id);
if (!socket.IsValid()) {
return nullptr;
}
// Create a new WifiLanEndpointChannel.
auto channel = std::make_unique<WifiLanEndpointChannel>(service_id, socket);
+3
View File
@@ -110,6 +110,9 @@ class WifiLanMedium {
virtual WifiLanService* FindRemoteService(const std::string& ip_address,
int port) = 0;
virtual std::pair<std::string, int> GetServiceAddress(
const std::string& service_id) = 0;
};
} // namespace api
+7
View File
@@ -360,6 +360,13 @@ api::WifiLanService* WifiLanMedium::FindRemoteService(
return env.FindWifiLanService(ip_address, port);
}
std::pair<std::string, int> WifiLanMedium::GetServiceAddress(
const std::string& service_id) {
NEARBY_LOGS(INFO) << "G3 WifiLan GetServiceAddress: service_id="
<< service_id;
return service_.GetServiceAddress();
}
} // namespace g3
} // namespace nearby
} // namespace location
+3
View File
@@ -218,6 +218,9 @@ class WifiLanMedium : public api::WifiLanMedium {
api::WifiLanService* FindRemoteService(const std::string& ip_address,
int port) override;
std::pair<std::string, int> GetServiceAddress(
const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_);
private:
static constexpr int kMaxConcurrentAcceptLoops = 5;
+5
View File
@@ -131,5 +131,10 @@ WifiLanService WifiLanMedium::FindRemoteService(const std::string& ip_address,
return WifiLanService(impl_->FindRemoteService(ip_address, port));
}
std::pair<std::string, int> WifiLanMedium::GetServiceAddress(
const std::string& service_id) {
return impl_->GetServiceAddress(service_id);
}
} // namespace nearby
} // namespace location
+5
View File
@@ -92,6 +92,7 @@ class WifiLanSocket final {
class WifiLanMedium final {
public:
using Platform = api::ImplementationPlatform;
struct DiscoveredServiceCallback {
std::function<void(WifiLanService& wifi_lan_service,
const std::string& service_id)>
@@ -102,6 +103,7 @@ class WifiLanMedium final {
service_lost_cb =
DefaultCallback<WifiLanService&, const std::string&>();
};
struct ServiceDiscoveryInfo {
WifiLanService service;
};
@@ -110,6 +112,7 @@ class WifiLanMedium final {
std::function<void(WifiLanSocket socket, const std::string& service_id)>
accepted_cb = DefaultCallback<WifiLanSocket, const std::string&>();
};
struct AcceptedConnectionInfo {
WifiLanSocket socket;
};
@@ -147,6 +150,8 @@ class WifiLanMedium final {
WifiLanService FindRemoteService(const std::string& ip_address, int port);
std::pair<std::string, int> GetServiceAddress(const std::string& service_id);
private:
Mutex mutex_;
std::unique_ptr<api::WifiLanMedium> impl_;
@@ -113,6 +113,7 @@ message PayloadTransferFrame {
optional int64 id = 1;
optional PayloadType type = 2;
optional int64 total_size = 3;
optional bool is_sensitive = 4;
}
// Accompanies DATA packets.