Skip to content

Commit cf28679

Browse files
authored
Merge pull request #119 from microsoft/apdiscoveryif
Change access point discovery output from interface name to IAccessPoint
2 parents fe60c2d + b61f71d commit cf28679

19 files changed

+153
-126
lines changed

src/common/wifi/apmanager/AccessPointDiscoveryAgent.cxx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ AccessPointDiscoveryAgent::RegisterDiscoveryEventCallback(AccessPointPresenceEve
3636
}
3737

3838
void
39-
AccessPointDiscoveryAgent::DevicePresenceChanged(AccessPointPresenceEvent presence, std::string interfaceName) const noexcept
39+
AccessPointDiscoveryAgent::DevicePresenceChanged(AccessPointPresenceEvent presence, std::shared_ptr<IAccessPoint> accessPoint) const noexcept
4040
{
4141
std::shared_lock<std::shared_mutex> onDevicePresenceChangedLock{ m_onDevicePresenceChangedGate };
4242
if (m_onDevicePresenceChanged) {
4343
LOGD << "Access point discovery agent detected a device presence change";
44-
m_onDevicePresenceChanged(presence, std::move(interfaceName));
44+
m_onDevicePresenceChanged(presence, std::move(accessPoint));
4545
}
4646
}
4747

@@ -57,10 +57,10 @@ AccessPointDiscoveryAgent::Start()
5757
bool expected = false;
5858
if (m_started.compare_exchange_weak(expected, true)) {
5959
LOGD << "Access point discovery agent starting";
60-
m_operations->Start([weakThis = std::weak_ptr<AccessPointDiscoveryAgent>(GetInstance())](auto&& presence, auto&& interfaceName) {
60+
m_operations->Start([weakThis = std::weak_ptr<AccessPointDiscoveryAgent>(GetInstance())](auto&& presence, auto&& accessPoint) {
6161
// Attempt to promote the weak pointer to a shared pointer to ensure this instance is still valid.
6262
if (auto strongThis = weakThis.lock(); strongThis) {
63-
strongThis->DevicePresenceChanged(presence, std::move(interfaceName));
63+
strongThis->DevicePresenceChanged(presence, std::move(accessPoint));
6464
}
6565
});
6666
}
@@ -76,9 +76,8 @@ AccessPointDiscoveryAgent::Stop()
7676
}
7777
}
7878

79-
std::future<std::vector<std::string>>
79+
std::future<std::vector<std::shared_ptr<IAccessPoint>>>
8080
AccessPointDiscoveryAgent::ProbeAsync()
8181
{
82-
LOGD << "Access point discovery agent probing for devices";
8382
return m_operations->ProbeAsync();
8483
}

src/common/wifi/apmanager/AccessPointManager.cxx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
#include <chrono>
44
#include <iterator>
55

6+
#include <magic_enum.hpp>
67
#include <microsoft/net/wifi/AccessPoint.hxx>
78
#include <microsoft/net/wifi/AccessPointDiscoveryAgent.hxx>
89
#include <microsoft/net/wifi/AccessPointManager.hxx>
910
#include <microsoft/net/wifi/IAccessPoint.hxx>
1011
#include <notstd/Memory.hxx>
12+
#include <plog/Log.h>
1113

1214
using namespace Microsoft::Net::Wifi;
1315

14-
AccessPointManager::AccessPointManager(std::unique_ptr<IAccessPointFactory> accessPointFactory) :
15-
m_accessPointFactory(std::move(accessPointFactory))
16-
{}
17-
1816
/* static */
1917
std::shared_ptr<AccessPointManager>
20-
AccessPointManager::Create(std::unique_ptr<IAccessPointFactory> accessPointFactory)
18+
AccessPointManager::Create()
2119
{
22-
return std::make_shared<notstd::enable_make_protected<AccessPointManager>>(std::move(accessPointFactory));
20+
return std::make_shared<notstd::enable_make_protected<AccessPointManager>>();
2321
}
2422

2523
std::shared_ptr<AccessPointManager>
@@ -98,9 +96,8 @@ AccessPointManager::AddDiscoveryAgent(std::shared_ptr<AccessPointDiscoveryAgent>
9896
// be safely destroyed prior to the discovery agent. This allows the
9997
// callback to be registered indefinitely, safely checking whether this
10098
// instance is still valid upon each callback invocation.
101-
discoveryAgent->RegisterDiscoveryEventCallback([discoveryAgentPtr = discoveryAgent.get(), weakThis = std::weak_ptr<AccessPointManager>(GetInstance())](auto&& presence, auto&& interfaceName) {
99+
discoveryAgent->RegisterDiscoveryEventCallback([discoveryAgentPtr = discoveryAgent.get(), weakThis = std::weak_ptr<AccessPointManager>(GetInstance())](auto&& presence, auto&& accessPointChanged) {
102100
if (auto strongThis = weakThis.lock()) {
103-
auto accessPointChanged = strongThis->m_accessPointFactory->Create(interfaceName);
104101
strongThis->OnAccessPointPresenceChanged(discoveryAgentPtr, presence, std::move(accessPointChanged));
105102
}
106103
});
@@ -111,29 +108,28 @@ AccessPointManager::AddDiscoveryAgent(std::shared_ptr<AccessPointDiscoveryAgent>
111108
}
112109

113110
// Kick off a probe to ensure any access points already present will be added to this manager.
114-
auto existingAccessPointInterfaceNamesProbe = discoveryAgent->ProbeAsync();
111+
auto existingAccessPointsProbe = discoveryAgent->ProbeAsync();
115112

116113
// Add the agent.
117114
{
118115
std::unique_lock<std::shared_mutex> discoveryAgentLock{ m_discoveryAgentsGate };
119116
m_discoveryAgents.push_back(std::move(discoveryAgent));
120117
}
121118

122-
if (existingAccessPointInterfaceNamesProbe.valid()) {
119+
if (existingAccessPointsProbe.valid()) {
123120
static constexpr auto ProbeTimeout = 3s;
124121

125122
// Wait for the operation to complete.
126-
const auto waitResult = existingAccessPointInterfaceNamesProbe.wait_for(ProbeTimeout);
123+
const auto waitResult = existingAccessPointsProbe.wait_for(ProbeTimeout);
127124

128125
// If the operation completed, get the results and add those access points.
129126
if (waitResult == std::future_status::ready) {
130-
auto existingAccessPointInterfaceNames = existingAccessPointInterfaceNamesProbe.get();
131-
for (const auto& existingAccessPointInterfaceName : existingAccessPointInterfaceNames) {
132-
auto existingAccessPoint = m_accessPointFactory->Create(existingAccessPointInterfaceName);
127+
auto existingAccessPoints = existingAccessPointsProbe.get();
128+
for (const auto& existingAccessPoint : existingAccessPoints) {
133129
AddAccessPoint(std::move(existingAccessPoint));
134130
}
135131
} else {
136-
// TODO: log error
132+
LOGE << std::format("Access point discovery agent probe failed ({})", magic_enum::enum_name(waitResult));
137133
}
138134
}
139135
}

src/common/wifi/apmanager/include/microsoft/net/wifi/AccessPointDiscoveryAgent.hxx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include <future>
88
#include <memory>
99
#include <shared_mutex>
10-
#include <string>
1110

1211
#include <microsoft/net/wifi/IAccessPointDiscoveryAgentOperations.hxx>
1312

@@ -75,11 +74,11 @@ struct AccessPointDiscoveryAgent :
7574
Stop();
7675

7776
/**
78-
* @brief Probe for all existing devices.
77+
* @brief Perform an asynchronous discovery probe.
7978
*
80-
* @return std::future<std::vector<std::string>>
79+
* @return std::future<std::vector<std::shared_ptr<IAccessPoint>>>
8180
*/
82-
std::future<std::vector<std::string>>
81+
std::future<std::vector<std::shared_ptr<IAccessPoint>>>
8382
ProbeAsync();
8483

8584
protected:
@@ -94,10 +93,10 @@ protected:
9493
* @brief Wrapper for safely invoking any device presence changed registered callback.
9594
*
9695
* @param presence The presence change that occurred.
97-
* @param interfaceName The name of the network interface of the access point that changed.
96+
* @param accessPoint The access point instance that changed.
9897
*/
9998
void
100-
DevicePresenceChanged(AccessPointPresenceEvent presence, std::string interfaceName) const noexcept;
99+
DevicePresenceChanged(AccessPointPresenceEvent presence, std::shared_ptr<IAccessPoint> accessPoint) const noexcept;
101100

102101
private:
103102
std::unique_ptr<IAccessPointDiscoveryAgentOperations> m_operations;

src/common/wifi/apmanager/include/microsoft/net/wifi/AccessPointManager.hxx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public:
3333
* @return std::shared_ptr<AccessPointManager>
3434
*/
3535
[[nodiscard]] static std::shared_ptr<AccessPointManager>
36-
Create(std::unique_ptr<IAccessPointFactory> accessPointFactory);
36+
Create();
3737

3838
/**
3939
* @brief Get an instance of this access point manager.
@@ -84,20 +84,11 @@ public:
8484

8585
protected:
8686
/**
87-
* @brief Default constructor.
87+
* @brief Construct a new AccessPointManager object.
8888
*
89-
* It's intentional that this is *declared* here and default-implemented
90-
* in the source file. This is required because IAccessPoint
91-
* and AccessPointDiscoveryAgent are used as incomplete
92-
* types with std::unique_ptr and std::shared_ptr. In case an exception is
93-
* thrown in the constructor, their destructors may be called, and the
94-
* wrapped type must be complete at that time. As such, defining the
95-
* constructor implementation as default here would require the type to be
96-
* complete, which is impossible due to the forward declaration.
97-
* Consequently, the = default implementation is done in the source file
98-
* instead.
89+
* @param accessPointFactory
9990
*/
100-
AccessPointManager(std::unique_ptr<IAccessPointFactory> accessPointFactory);
91+
AccessPointManager() = default;
10192

10293
private:
10394
/**
@@ -127,7 +118,7 @@ private:
127118
RemoveAccessPoint(std::shared_ptr<IAccessPoint> accessPoint);
128119

129120
private:
130-
std::unique_ptr<IAccessPointFactory> m_accessPointFactory;
121+
std::shared_ptr<IAccessPointFactory> m_accessPointFactory;
131122

132123
mutable std::mutex m_accessPointGate;
133124
std::vector<std::shared_ptr<IAccessPoint>> m_accessPoints{};

src/common/wifi/apmanager/include/microsoft/net/wifi/IAccessPointDiscoveryAgentOperations.hxx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <functional>
66
#include <future>
77
#include <memory>
8-
#include <string>
98
#include <vector>
109

1110
namespace Microsoft::Net::Wifi
@@ -20,7 +19,7 @@ struct IAccessPoint;
2019
/**
2120
* @brief Prototype for the callback invoked when an access point is discovered or removed.
2221
*/
23-
using AccessPointPresenceEventCallback = std::function<void(AccessPointPresenceEvent, std::string interfaceName)>;
22+
using AccessPointPresenceEventCallback = std::function<void(AccessPointPresenceEvent, std::shared_ptr<IAccessPoint> accessPoint)>;
2423

2524
/**
2625
* @brief Operations used to perform discovery of access points, used by
@@ -47,9 +46,9 @@ struct IAccessPointDiscoveryAgentOperations
4746
/**
4847
* @brief Perform an asynchronous discovery probe.
4948
*
50-
* @return std::future<std::vector<std::string>>
49+
* @return std::future<std::vector<std::shared_ptr<IAccessPoint>>>
5150
*/
52-
virtual std::future<std::vector<std::string>>
51+
virtual std::future<std::vector<std::shared_ptr<IAccessPoint>>>
5352
ProbeAsync() = 0;
5453
};
5554

src/linux/server/Main.cxx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ main(int argc, char *argv[])
4848

4949
// Create an access point manager and discovery agent.
5050
{
51-
auto accessPointControllerFactory = std::make_unique<AccessPointControllerHostapdFactory>();
52-
auto accessPointFactory = std::make_unique<AccessPointFactoryLinux>(std::move(accessPointControllerFactory));
53-
configuration.AccessPointManager = AccessPointManager::Create(std::move(accessPointFactory));
51+
configuration.AccessPointManager = AccessPointManager::Create();
5452

55-
auto &accessPointManager = configuration.AccessPointManager;
56-
auto accessPointDiscoveryAgentOperationsNetlink = std::make_unique<AccessPointDiscoveryAgentOperationsNetlink>();
53+
auto accessPointControllerFactory = std::make_unique<AccessPointControllerHostapdFactory>();
54+
auto accessPointFactory = std::make_shared<AccessPointFactoryLinux>(std::move(accessPointControllerFactory));
55+
auto accessPointDiscoveryAgentOperationsNetlink = std::make_unique<AccessPointDiscoveryAgentOperationsNetlink>(accessPointFactory);
5756
auto accessPointDiscoveryAgent = AccessPointDiscoveryAgent::Create(std::move(accessPointDiscoveryAgentOperationsNetlink));
57+
auto &accessPointManager = configuration.AccessPointManager;
58+
5859
accessPointManager->AddDiscoveryAgent(std::move(accessPointDiscoveryAgent));
5960
}
6061

src/linux/tools/apmonitor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ target_link_libraries(apmonitor-cli-linux
1010
PRIVATE
1111
plog::plog
1212
wifi-apmanager-linux
13+
wifi-core-linux
1314
)
1415

1516
set_target_properties(apmonitor-cli-linux

src/linux/tools/apmonitor/Main.cxx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
#include <format>
33

44
#include <magic_enum.hpp>
5+
#include <microsoft/net/wifi/AccessPointControllerHostapd.hxx>
56
#include <microsoft/net/wifi/AccessPointDiscoveryAgent.hxx>
67
#include <microsoft/net/wifi/AccessPointDiscoveryAgentOperationsNetlink.hxx>
8+
#include <microsoft/net/wifi/AccessPointLinux.hxx>
79
#include <microsoft/net/wifi/IAccessPoint.hxx>
810
#include <plog/Appenders/ColorConsoleAppender.h>
911
#include <plog/Formatters/MessageOnlyFormatter.h>
1012
#include <plog/Init.h>
1113
#include <plog/Log.h>
1214
#include <signal.h>
1315

14-
using Microsoft::Net::Wifi::AccessPointDiscoveryAgent;
15-
using Microsoft::Net::Wifi::AccessPointDiscoveryAgentOperationsNetlink;
16-
using Microsoft::Net::Wifi::IAccessPointDiscoveryAgentOperations;
16+
using namespace Microsoft::Net::Wifi;
1717

1818
int
1919
main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
@@ -23,10 +23,12 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
2323
plog::init(plog::verbose, &colorConsoleAppender);
2424

2525
// Configure monitoring with the netlink protocol.
26-
auto accessPointDiscoveryAgentOperationsNetlink{ std::make_unique<AccessPointDiscoveryAgentOperationsNetlink>() };
26+
auto accessPointControllerFactory = std::make_unique<AccessPointControllerHostapdFactory>();
27+
auto accessPointFactory = std::make_shared<AccessPointFactoryLinux>(std::move(accessPointControllerFactory));
28+
auto accessPointDiscoveryAgentOperationsNetlink{ std::make_unique<AccessPointDiscoveryAgentOperationsNetlink>(accessPointFactory) };
2729
auto accessPointDiscoveryAgent{ AccessPointDiscoveryAgent::Create(std::move(accessPointDiscoveryAgentOperationsNetlink)) };
28-
accessPointDiscoveryAgent->RegisterDiscoveryEventCallback([](auto&& presence, auto&& interfaceName) {
29-
PLOG_INFO << std::format("{} -> {}", interfaceName, magic_enum::enum_name(presence));
30+
accessPointDiscoveryAgent->RegisterDiscoveryEventCallback([](auto&& presence, auto&& accessPointChanged) {
31+
LOGI << std::format("{} -> {}", accessPointChanged->GetInterfaceName(), magic_enum::enum_name(presence));
3032
});
3133

3234
LOG_INFO << "starting access point discovery agent";

src/linux/wifi/apmanager/AccessPointDiscoveryAgentOperationsNetlink.cxx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <linux/if.h>
1111
#include <magic_enum.hpp>
1212
#include <microsoft/net/netlink/nl80211/Netlink80211.hxx>
13-
#include <microsoft/net/netlink/nl80211/Netlink80211Interface.hxx>
1413
#include <microsoft/net/wifi/AccessPointDiscoveryAgentOperationsNetlink.hxx>
1514
#include <microsoft/net/wifi/IAccessPoint.hxx>
1615
#include <netlink/genl/genl.h>
@@ -31,7 +30,8 @@ using Microsoft::Net::Netlink::NetlinkMessage;
3130
using Microsoft::Net::Netlink::NetlinkSocket;
3231
using Microsoft::Net::Netlink::Nl80211::Nl80211ProtocolState;
3332

34-
AccessPointDiscoveryAgentOperationsNetlink::AccessPointDiscoveryAgentOperationsNetlink() :
33+
AccessPointDiscoveryAgentOperationsNetlink::AccessPointDiscoveryAgentOperationsNetlink(std::shared_ptr<IAccessPointFactory> accessPointFactory) :
34+
m_accessPointFactory(std::move(accessPointFactory)),
3535
m_cookie(CookieValid),
3636
m_netlink80211ProtocolState(Nl80211ProtocolState::Instance())
3737
{}
@@ -123,7 +123,7 @@ namespace detail
123123
/**
124124
* @brief Helper function to determine if an nl80211 interface is an AP. To be used in range expressions.
125125
*
126-
* @param nl80211Interface
126+
* @param nl80211Interface The nl80211 interface to check.
127127
* @return true
128128
* @return false
129129
*/
@@ -134,28 +134,33 @@ IsNl80211InterfaceTypeAp(const Nl80211Interface &nl80211Interface)
134134
}
135135

136136
/**
137-
* @brief Helper function returning the name of an nl80211 interface. To be used in range expressions.
137+
* @brief Helper function to create an access point instance from an nl80211 interface. To be used in range expressions.
138138
*
139-
* @param nl80211Interface
140-
* @return std::string
139+
* @param accessPointFactory The factory to use for creating the access point instance.
140+
* @param nl80211Interface The nl80211 interface to create the access point instance from.
141+
* @return std::shared_ptr<IAccessPoint>
141142
*/
142-
std::string
143-
Nl80211InterfaceName(const Nl80211Interface &nl80211Interface)
143+
std::shared_ptr<IAccessPoint>
144+
MakeAccessPoint(std::shared_ptr<IAccessPointFactory> accessPointFactory, const Nl80211Interface &nl80211Interface)
144145
{
145-
return nl80211Interface.Name;
146+
return accessPointFactory->Create(nl80211Interface.Name);
146147
}
147148
} // namespace detail
148149

149-
std::future<std::vector<std::string>>
150+
std::future<std::vector<std::shared_ptr<IAccessPoint>>>
150151
AccessPointDiscoveryAgentOperationsNetlink::ProbeAsync()
151152
{
152-
std::promise<std::vector<std::string>> probePromise{};
153+
const auto MakeAccessPoint = [this](const Nl80211Interface &nl80211Interface) {
154+
return detail::MakeAccessPoint(m_accessPointFactory, nl80211Interface);
155+
};
156+
157+
std::promise<std::vector<std::shared_ptr<IAccessPoint>>> probePromise{};
153158
auto probeFuture = probePromise.get_future();
154159

155160
// Enumerate all nl80211 interfaces and filter out those that are not APs.
156161
auto nl80211Interfaces{ Nl80211Interface::Enumerate() };
157-
auto nl80211ApInterfaceNames = nl80211Interfaces | std::views::filter(detail::IsNl80211InterfaceTypeAp) | std::views::transform(detail::Nl80211InterfaceName);
158-
std::vector<std::string> accessPoints(std::make_move_iterator(std::begin(nl80211ApInterfaceNames)), std::make_move_iterator(std::end(nl80211ApInterfaceNames)));
162+
auto accessPointsView = nl80211Interfaces | std::views::filter(detail::IsNl80211InterfaceTypeAp) | std::views::transform(MakeAccessPoint);
163+
std::vector<std::shared_ptr<IAccessPoint>> accessPoints(std::make_move_iterator(std::begin(accessPointsView)), std::make_move_iterator(std::end(accessPointsView)));
159164

160165
// Clear the vector since most of the items were moved out.
161166
nl80211Interfaces.clear();
@@ -237,7 +242,8 @@ AccessPointDiscoveryAgentOperationsNetlink::ProcessNetlinkMessage(struct nl_msg
237242
// Invoke presence event callback if present.
238243
if (accessPointPresenceEventCallback != nullptr) {
239244
LOGV << std::format("Invoking access point presence event callback with event args 'interface={}, presence={}'", interfaceName, magic_enum::enum_name(accessPointPresenceEvent));
240-
accessPointPresenceEventCallback(accessPointPresenceEvent, interfaceName);
245+
auto accessPoint = m_accessPointFactory->Create(interfaceName);
246+
accessPointPresenceEventCallback(accessPointPresenceEvent, accessPoint);
241247
}
242248

243249
return NL_OK;

0 commit comments

Comments
 (0)