From 07d33cfa9ebf6fcb8eb45cdbb7d35b40a469725f Mon Sep 17 00:00:00 2001 From: jfcarroll Date: Thu, 12 Aug 2021 14:32:37 -0700 Subject: [PATCH] Initial implementation of BluetoothServerSocket PiperOrigin-RevId: 390461649 --- .../impl/windows/bluetooth_classic_medium.cc | 107 +++++++++----- .../impl/windows/bluetooth_classic_medium.h | 30 ++-- .../bluetooth_classic_server_socket.cc | 137 +++++++++++++++++- .../windows/bluetooth_classic_server_socket.h | 67 ++++++++- .../impl/windows/bluetooth_classic_socket.h | 5 + cpp/platform/impl/windows/utils.h | 17 ++- 6 files changed, 300 insertions(+), 63 deletions(-) diff --git a/cpp/platform/impl/windows/bluetooth_classic_medium.cc b/cpp/platform/impl/windows/bluetooth_classic_medium.cc index 179ad101..61c2c398 100644 --- a/cpp/platform/impl/windows/bluetooth_classic_medium.cc +++ b/cpp/platform/impl/windows/bluetooth_classic_medium.cc @@ -14,18 +14,23 @@ #include "platform/impl/windows/bluetooth_classic_medium.h" +#include +#include +#include + +#include "platform/base/cancellation_flag.h" +#include "platform/base/cancellation_flag_listener.h" +#include "platform/base/exception.h" +#include "platform/impl/windows/bluetooth_classic_device.h" +#include "platform/impl/windows/bluetooth_classic_server_socket.h" +#include "platform/impl/windows/bluetooth_classic_socket.h" #include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h" #include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h" #include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h" #include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h" #include "platform/impl/windows/generated/winrt/base.h" - -#include "platform/base/exception.h" -#include "platform/impl/windows/bluetooth_classic_device.h" -#include "platform/impl/windows/bluetooth_classic_socket.h" +#include "platform/impl/windows/utils.h" #include "platform/public/logging.h" -#include "platform/base/cancellation_flag.h" -#include "platform/base/cancellation_flag_listener.h" namespace location { namespace nearby { @@ -34,32 +39,7 @@ namespace windows { BluetoothClassicMedium::BluetoothClassicMedium() { InitializeCriticalSection(&critical_section_); - // create watcher - device_watcher_ = DeviceInformation::CreateWatcher( - BLUETOOTH_SELECTOR, nullptr, DeviceInformationKind::AssociationEndpoint); - - // An app must subscribe to all of the added, removed, and updated events to - // be notified when there are device additions, removals or updates. If an app - // handles only the added event, it will not receive an update if a device is - // added to the system after the initial device enumeration completes. - // register event handlers before starting the watcher - // - // Event that is raised when a device is added to the collection enumerated - // by the DeviceWatcher. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348 - device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added}); - - // Event that is raised when a device is updated in the collection of - // enumerated devices. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348 - device_watcher_.Updated( - {this, &BluetoothClassicMedium::DeviceWatcher_Updated}); - - // Event that is raised when a device is removed from the collection of - // enumerated devices. - // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348 - device_watcher_.Removed( - {this, &BluetoothClassicMedium::DeviceWatcher_Removed}); + InitializeDeviceWatcher(); } BluetoothClassicMedium::~BluetoothClassicMedium() {} @@ -99,6 +79,37 @@ bool BluetoothClassicMedium::StopDiscovery() { return result; } +void BluetoothClassicMedium::InitializeDeviceWatcher() { + // create watcher + device_watcher_ = DeviceInformation::CreateWatcher( + BLUETOOTH_SELECTOR, // aqsFilter + nullptr, // additionalProperties + DeviceInformationKind::AssociationEndpoint); // kind + + // An app must subscribe to all of the added, removed, and updated events to + // be notified when there are device additions, removals or updates. If an app + // handles only the added event, it will not receive an update if a device is + // added to the system after the initial device enumeration completes. + // register event handlers before starting the watcher + // + // Event that is raised when a device is added to the collection enumerated + // by the DeviceWatcher. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348 + device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added}); + + // Event that is raised when a device is updated in the collection of + // enumerated devices. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348 + device_watcher_.Updated( + {this, &BluetoothClassicMedium::DeviceWatcher_Updated}); + + // Event that is raised when a device is removed from the collection of + // enumerated devices. + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348 + device_watcher_.Removed( + {this, &BluetoothClassicMedium::DeviceWatcher_Removed}); +} + std::unique_ptr BluetoothClassicMedium::ConnectToService( api::BluetoothDevice& remote_device, const std::string& service_uuid, CancellationFlag* cancellation_flag) { @@ -141,8 +152,7 @@ std::unique_ptr BluetoothClassicMedium::ConnectToService( location::nearby::CancellationFlagListener cancellationFlagListener( cancellation_flag, - [&rfcommSocket]() { rfcommSocket.get()->CancelIOAsync().get(); - }); + [&rfcommSocket]() { rfcommSocket.get()->CancelIOAsync().get(); }); try { rfcommSocket @@ -209,16 +219,16 @@ bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) { // device that actually supports the Bluetooth Rfcomm Service // https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.getsdprawattributesasync?view=winrt-20348 auto attributes = /*await*/ requestedService.GetSdpRawAttributesAsync(); - if (!attributes.get().HasKey(SdpServiceNameAttributeId)) { + if (!attributes.get().HasKey(Constants::SdpServiceNameAttributeId)) { return false; } auto attributeReader = DataReader::FromBuffer( - attributes.get().Lookup(SdpServiceNameAttributeId)); + attributes.get().Lookup(Constants::SdpServiceNameAttributeId)); auto attributeType = attributeReader.ReadByte(); - if (attributeType != SdpServiceNameAttributeType) { + if (attributeType != Constants::SdpServiceNameAttributeType) { return false; } @@ -237,7 +247,20 @@ bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) { std::unique_ptr BluetoothClassicMedium::ListenForService(const std::string& service_name, const std::string& service_uuid) { - return nullptr; + if (service_uuid.empty()) { + return nullptr; + } + + if (service_name.empty()) { + return nullptr; + } + + auto bluetooth_server_socket = + std::make_unique(); + + bluetooth_server_socket->StartListening(service_name, service_uuid); + + return std::move(bluetooth_server_socket); } // TODO(b/184975123): replace with real implementation. @@ -301,12 +324,12 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added( devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice); - LeaveCriticalSection(&critical_section_); - if (discovery_callback_.device_discovered_cb != nullptr) { discovery_callback_.device_discovered_cb( *devices_by_id_[deviceInfo.Id()]); } + + LeaveCriticalSection(&critical_section_); }); } } @@ -326,6 +349,8 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated( winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed( DeviceWatcher sender, DeviceInformationUpdate deviceInfo) { if (IsWatcherStarted()) { + EnterCriticalSection(&critical_section_); + if (discovery_callback_.device_lost_cb != nullptr) { discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]); } @@ -333,6 +358,8 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed( devices_by_id_.erase(deviceInfo.Id()); } + LeaveCriticalSection(&critical_section_); + return winrt::fire_and_forget(); } diff --git a/cpp/platform/impl/windows/bluetooth_classic_medium.h b/cpp/platform/impl/windows/bluetooth_classic_medium.h index b79fed92..befe187a 100644 --- a/cpp/platform/impl/windows/bluetooth_classic_medium.h +++ b/cpp/platform/impl/windows/bluetooth_classic_medium.h @@ -18,8 +18,12 @@ #include #include +#include "platform/api/bluetooth_classic.h" #include "platform/impl/windows/bluetooth_classic_device.h" +#include "platform/impl/windows/bluetooth_classic_server_socket.h" +#include "platform/impl/windows/bluetooth_classic_socket.h" #include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h" +#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h" #include "platform/impl/windows/generated/winrt/base.h" namespace location { @@ -69,6 +73,10 @@ using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId; // https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348 using winrt::Windows::Storage::Streams::DataReader; +// Writes data to an output stream. +// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348 +using winrt::Windows::Storage::Streams::DataWriter; + // Bluetooth protocol ID = \"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\" // https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids #define BLUETOOTH_SELECTOR \ @@ -80,7 +88,6 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { public: explicit BluetoothClassicMedium(); - // TODO(b/184975123): replace with real implementation. ~BluetoothClassicMedium() override; // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery() @@ -91,7 +98,6 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { // Returns true once discovery is well and truly stopped; after this returns, // there must be no more invocations of the DiscoveryCallback passed in to // StartDiscovery(). - // TODO(b/184975123): replace with real implementation. bool StopDiscovery() override; // A combination of @@ -120,7 +126,6 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { // UUID. // // Returns nullptr error. - // TODO(b/184975123): replace with real implementation. std::unique_ptr ListenForService( const std::string& service_name, const std::string& service_uuid) override; @@ -134,6 +139,7 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { bool StopScanning(); bool IsWatcherStarted(); bool IsWatcherRunning(); + void InitializeDeviceWatcher(); // This is for a coroutine whose return type is winrt::fire_and_forget, which // handles async operations which don't have any dependencies. @@ -151,27 +157,17 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { bool HaveAccess(winrt::hstring deviceId); // Get the service requested - winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService - GetRequestedService(location::nearby::windows::BluetoothDevice* device, - winrt::guid service); + RfcommDeviceService GetRequestedService(BluetoothDevice* device, + winrt::guid service); // Check to see that the device actually handles the requested service - bool CheckSdp(winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService - requestedService); + bool CheckSdp(RfcommDeviceService requestedService); BluetoothClassicMedium::DiscoveryCallback discovery_callback_; DeviceWatcher device_watcher_ = nullptr; - // The Id of the Service Name SDP attribute - const uint16 SdpServiceNameAttributeId = 0x100; - - // The SDP Type of the Service Name SDP attribute. - // The first byte in the SDP Attribute encodes the SDP Attribute Type as - // follows : - // - the Attribute Type size in the least significant 3 bits, - // - the SDP Attribute Type value in the most significant 5 bits. - const char SdpServiceNameAttributeType = (4 << 3) | 5; + std::unique_ptr bluetooth_socket_; // hstring is the only type of string winrt understands. // https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring diff --git a/cpp/platform/impl/windows/bluetooth_classic_server_socket.cc b/cpp/platform/impl/windows/bluetooth_classic_server_socket.cc index 1406fea5..191ad17b 100644 --- a/cpp/platform/impl/windows/bluetooth_classic_server_socket.cc +++ b/cpp/platform/impl/windows/bluetooth_classic_server_socket.cc @@ -14,9 +14,22 @@ #include "platform/impl/windows/bluetooth_classic_server_socket.h" +#include +#include +#include + +#include "platform/impl/windows/bluetooth_classic_socket.h" +#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h" +#include "platform/impl/windows/utils.h" +#include "platform/public/logging.h" + namespace location { namespace nearby { namespace windows { +BluetoothServerSocket::BluetoothServerSocket() { + InitializeCriticalSection(&critical_section_); +} + BluetoothServerSocket::~BluetoothServerSocket() {} // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept() @@ -27,17 +40,135 @@ BluetoothServerSocket::~BluetoothServerSocket() {} // On success, returns connected socket, ready to exchange data. // Returns nullptr on error. // Once error is reported, it is permanent, and ServerSocket has to be closed. -// TODO(b/184975123): replace with real implementation. std::unique_ptr BluetoothServerSocket::Accept() { + while (bluetooth_sockets_.empty() && !closed_) { + Sleep(1000); + } + + EnterCriticalSection(&critical_section_); + if (!closed_) { + std::unique_ptr bluetoothSocket = + std::move(bluetooth_sockets_.front()); + bluetooth_sockets_.pop(); + LeaveCriticalSection(&critical_section_); + + return std::move(bluetoothSocket); + } else { + bluetooth_sockets_ = {}; + LeaveCriticalSection(&critical_section_); + } + return nullptr; } +Exception BluetoothServerSocket::StartListening( + const std::string& service_name, const std::string& service_uuid) { + EnterCriticalSection(&critical_section_); + + winrt::guid service(service_uuid); + + // Create the StreamSocketListener + stream_socket_listener_ = StreamSocketListener(); + + // Configure control property + stream_socket_listener_.Control().QualityOfService( + SocketQualityOfService::LowLatency); + + stream_socket_listener_.Control().KeepAlive(true); + + // Note From the perspective of a StreamSocket, a Parallel Patterns Library + // (PPL) completion handler is done executing (and the socket is eligible for + // disposal) before the continuation body runs. So, to keep your socket from + // being disposed if you want to use it inside a continuation, you'll need to + // use one of the techniques described in References to StreamSockets in C++ + // PPL continuations. + // Assign ConnectionReceived event to event handler on the server socket + stream_socket_listener_.ConnectionReceived( + [this](StreamSocketListener streamSocketListener, + StreamSocketListenerConnectionReceivedEventArgs args) { + EnterCriticalSection(&critical_section_); + if (!closed_) { + this->bluetooth_sockets_.push( + std::make_unique(args.Socket())); + } + LeaveCriticalSection(&critical_section_); + }); + + try { + auto rfcommProviderRef = + RfcommServiceProvider::CreateAsync(RfcommServiceId::FromUuid(service)) + .get(); + + rfcomm_provider_ = &rfcommProviderRef; + + std::wstring_convert> converter; + stream_socket_listener_ + .BindServiceNameAsync(winrt::to_hstring(service_name.c_str())) + .get(); + + // Set the SDP attributes and start Bluetooth advertising + InitializeServiceSdpAttributes(*rfcomm_provider_, service_name); + } catch (std::exception exception) { + // We will log and eat the exception since the caller + // expects nullptr if it fails + NEARBY_LOGS(ERROR) << __func__ << ": Exception setting up for listen: " + << exception.what(); + + LeaveCriticalSection(&critical_section_); + + return {Exception::kFailed}; + } + + try { + rfcomm_provider_->StartAdvertising( + stream_socket_listener_.as(), true); + } catch (std::exception exception) { + // We will log and eat the exception since the caller + // expects nullptr if it fails + NEARBY_LOGS(ERROR) << __func__ << ": Exception calling StartAdvertising: " + << exception.what(); + + LeaveCriticalSection(&critical_section_); + + return {Exception::kFailed}; + } + + LeaveCriticalSection(&critical_section_); + + return {Exception::kSuccess}; +} + +void BluetoothServerSocket::InitializeServiceSdpAttributes( + RfcommServiceProvider rfcommProvider, std::string service_name) { + auto sdpWriter = DataWriter(); + + // Write the Service Name Attribute. + sdpWriter.WriteByte(Constants::SdpServiceNameAttributeType); + + // The length of the UTF-8 encoded Service Name SDP Attribute. + sdpWriter.WriteByte(service_name.size()); + + // The UTF-8 encoded Service Name value. + sdpWriter.UnicodeEncoding(UnicodeEncoding::Utf8); + sdpWriter.WriteString(winrt::to_hstring(service_name)); + + // Set the SDP Attribute on the RFCOMM Service Provider. + rfcommProvider.SdpRawAttributes().Insert(Constants::SdpServiceNameAttributeId, + sdpWriter.DetachBuffer()); +} + // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close() // // Returns Exception::kIo on error, Exception::kSuccess otherwise. -// TODO(b/184975123): replace with real implementation. -Exception BluetoothServerSocket::Close() { return Exception(); } +Exception BluetoothServerSocket::Close() { + EnterCriticalSection(&critical_section_); + closed_ = true; + bluetooth_sockets_ = {}; + rfcomm_provider_->StopAdvertising(); + LeaveCriticalSection(&critical_section_); + return {Exception::kSuccess}; +} } // namespace windows } // namespace nearby } // namespace location diff --git a/cpp/platform/impl/windows/bluetooth_classic_server_socket.h b/cpp/platform/impl/windows/bluetooth_classic_server_socket.h index c96d0890..8b10b25a 100644 --- a/cpp/platform/impl/windows/bluetooth_classic_server_socket.h +++ b/cpp/platform/impl/windows/bluetooth_classic_server_socket.h @@ -15,14 +15,60 @@ #ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_ #define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_ +#include + +#include + #include "platform/api/bluetooth_classic.h" +#include "platform/impl/windows/bluetooth_classic_socket.h" +#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h" +#include "platform/impl/windows/generated/winrt/Windows.Foundation.h" +#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h" +#include "platform/impl/windows/generated/winrt/base.h" namespace location { namespace nearby { namespace windows { + +// Supports listening for an incoming network connection using Bluetooth RFCOMM. +// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistener?view=winrt-20348 +using winrt::Windows::Networking::Sockets::StreamSocketListener; + +// Provides data for a ConnectionReceived event on a StreamSocketListener +// object. +// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistenerconnectionreceivedeventargs?view=winrt-20348 +using winrt::Windows::Networking::Sockets:: + StreamSocketListenerConnectionReceivedEventArgs; + +// Represents an asynchronous action. +// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348 +using winrt::Windows::Foundation::IAsyncAction; + +// Specifies the quality of service for a StreamSocket object. +// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketqualityofservice?view=winrt-20348 +using winrt::Windows::Networking::Sockets::SocketQualityOfService; + +// Represents an instance of a local RFCOMM service. +// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceprovider?view=winrt-20348 +using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider; + +// Represents an RFCOMM service ID. +// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348 +using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId; + +// Writes data to an output stream. +// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348 +using winrt::Windows::Storage::Streams::DataWriter; + +// Specifies the type of character encoding for a stream. +// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.unicodeencoding?view=winrt-20348 +using winrt::Windows::Storage::Streams::UnicodeEncoding; + // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html. class BluetoothServerSocket : public api::BluetoothServerSocket { public: + BluetoothServerSocket(); + // TODO(b/184975123): replace with real implementation. ~BluetoothServerSocket() override; @@ -34,14 +80,31 @@ class BluetoothServerSocket : public api::BluetoothServerSocket { // On success, returns connected socket, ready to exchange data. // Returns nullptr on error. // Once error is reported, it is permanent, and ServerSocket has to be closed. - // TODO(b/184975123): replace with real implementation. std::unique_ptr Accept() override; // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close() // // Returns Exception::kIo on error, Exception::kSuccess otherwise. - // TODO(b/184975123): replace with real implementation. Exception Close() override; + + Exception StartListening(const std::string& service_name, + const std::string& service_uuid); + + private: + void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider, + std::string service_name); + + // This is used to store sockets in case Accept hasn't been called. Once + // Accept has been called the socket is popped from the queue and returned to + // the caller + std::queue> bluetooth_sockets_; + + StreamSocketListener stream_socket_listener_; + + CRITICAL_SECTION critical_section_; + bool closed_ = false; + + RfcommServiceProvider* rfcomm_provider_; }; } // namespace windows diff --git a/cpp/platform/impl/windows/bluetooth_classic_socket.h b/cpp/platform/impl/windows/bluetooth_classic_socket.h index ab9b3ff6..639ba356 100644 --- a/cpp/platform/impl/windows/bluetooth_classic_socket.h +++ b/cpp/platform/impl/windows/bluetooth_classic_socket.h @@ -16,6 +16,7 @@ #define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_ #include "platform/api/bluetooth_classic.h" + #include "platform/impl/windows/generated/winrt/Windows.Foundation.h" #include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h" #include "platform/impl/windows/generated/winrt/Windows.Storage.Streams.h" @@ -65,6 +66,10 @@ class BluetoothSocket : public api::BluetoothSocket { public: BluetoothSocket(); + BluetoothSocket( + winrt::Windows::Networking::Sockets::StreamSocket streamSocket) + : windows_socket_(streamSocket) {} + // TODO(b/184975123): replace with real implementation. ~BluetoothSocket() override; diff --git a/cpp/platform/impl/windows/utils.h b/cpp/platform/impl/windows/utils.h index 962466ec..0158d3cf 100644 --- a/cpp/platform/impl/windows/utils.h +++ b/cpp/platform/impl/windows/utils.h @@ -15,6 +15,9 @@ #ifndef PLATFORM_IMPL_WINDOWS_UTILS_H_ #define PLATFORM_IMPL_WINDOWS_UTILS_H_ +#include +#include + #include namespace location { @@ -23,7 +26,19 @@ namespace windows { std::string uint64_to_mac_address_string(uint64_t bluetoothAddress); -} +namespace Constants { +// The Id of the Service Name SDP attribute +const uint16_t SdpServiceNameAttributeId = 0x100; + +// The SDP Type of the Service Name SDP attribute. +// The first byte in the SDP Attribute encodes the SDP Attribute Type as +// follows: +// - the Attribute Type size in the least significant 3 bits, +// - the SDP Attribute Type value in the most significant 5 bits. +const char SdpServiceNameAttributeType = (4 << 3) | 5; +} // namespace Constants + +} // namespace windows } // namespace nearby } // namespace location